Problem of Object Model arising from a Ray-trace Model

The purpose of the following code i wrote is to test the feasibility and efficiency of a surface object for regulating bending of light (refract or reflect) in a ray-trace simulator. The first method which looks ugly shows the mechanism straightforwardly. The second uses multi-inheritance in a weird style. Both methods fulfill the requirement of making two references of interface for both sides on one object with one copy of data. The result (with a gcc compiler) shows the size of entitative object "boundary" in both implementation is 16 bytes, 8 extra bytes in addition to 8-byte useful contents.

Original mail sent to robbie (poorly written illustration):

two objects "connected by" a "boundary", from each side to the other, a "surface" is applied to provide a transfer value n1/n2 or n2/n1, like refraction coefficient... "Cast" initiates the transfer procedure from either side to the other, returns the sum of both objects inner data and surface transfer value in corresponding direction.

Code:

#include <stdio.h>

#if 0

/* embedded */

struct Surface
{
    virtual float Transfer () = 0;
};

struct BoundaryData
{
    float   m_AToB;
    float   m_BToA;
};

struct Boundary
{
   struct SurfaceAToB : public Surface
    {
        virtual float Transfer ()
        {
            printf("a2b/n");
            BoundaryData *bd = reinterpret_cast<BoundaryData *>
                (reinterpret_cast<char*>(this) - sizeof(BoundaryData));
            return bd->m_AToB / bd->m_BToA;
        }
    };

    struct SurfaceBToA : public Surface
    {
        virtual float Transfer ()
        {
            printf("b2a/n");
            BoundaryData *bd =
                reinterpret_cast<BoundaryData *>
                (reinterpret_cast<char*>(this) - sizeof(SurfaceAToB) - sizeof(BoundaryData));
            return bd->m_BToA / bd->m_AToB;
        }
    };

    BoundaryData    m_Data;
    SurfaceAToB     m_SurfAToB;
    SurfaceBToA     m_SurfBToA;

    void SetAToB (float v)
    {
        m_Data.m_AToB = v;
    }
    void SetBToA (float v)
    {
        m_Data.m_BToA = v;
    }

    Surface * GetSurfaceAToB ()
    {
        return &m_SurfAToB;
    }

    Surface * GetSurfaceBToA ()
    {
        return &m_SurfBToA;
    }
};

#else

/* object oriented? nge */

struct Surface
{
    virtual float Transfer () = 0;
};

struct BoundaryData
{
    float   m_AToB;
    float   m_BToA;

    void SetAToB (float v)
    {
        m_AToB = v;
    }
    void SetBToA (float v)
    {
        m_BToA = v;
    }
};

struct SurfaceAToB : virtual public BoundaryData, public Surface
{
    virtual float Transfer ()
    {
        printf("a2b/n");
        return m_AToB / m_BToA;
    }
};

struct SurfaceBToA : virtual public BoundaryData, public Surface
{
    virtual float Transfer ()
    {
        printf("b2a/n");
        return m_BToA / m_AToB;
    }
};

struct Boundary : public SurfaceAToB, public SurfaceBToA
{
    Surface * GetSurfaceAToB ()
    {
        return dynamic_cast<SurfaceAToB *>(this);
    }

    Surface * GetSurfaceBToA ()
    {
        return dynamic_cast<SurfaceBToA *>(this);
    }
};

#endif

struct Object
{
    float   m_Data;

    Surface *m_pSurface;
};

Object  g_Obj1, g_Obj2;
Boundary    g_Bound;

void Create ()
{
    g_Obj1.m_Data = 1;
    g_Obj2.m_Data = 2;
    g_Bound.SetAToB(3);
    g_Bound.SetBToA(4);
    g_Obj1.m_pSurface = g_Bound.GetSurfaceAToB();
    g_Obj2.m_pSurface = g_Bound.GetSurfaceBToA();
}

float Cast (Object *obj1, Object *obj2)
{
    Surface *surface = obj1->m_pSurface;
    return obj1->m_Data + obj2->m_Data + surface->Transfer();
}

void ViewBoundaryInBinary (Boundary *boundary, int size)
{
    unsigned char *b = reinterpret_cast<unsigned char *>(boundary);
    for (int i = 0; i < size; i++)
    {
        printf("%2x, ", b[i]);
    }
    printf("/n");
}

int main ()
{
    printf("size of boundary is %d, of boundary data is %d/n", sizeof(Boundary), sizeof(BoundaryData));
    Create();
    ViewBoundaryInBinary(&g_Bound, sizeof(Boundary));
    float res = Cast(&g_Obj1, &g_Obj2);
    printf("Cast 1 to 2 is %f/n", res);
    res = Cast(&g_Obj2, &g_Obj1);
    printf("Cast 2 to 1 is %f/n", res);
    return 0;
}

result 1 (multi-inheritance disabled):
| two float values | place holder for two surface object
 0,  0, 40, 40,  0,  0, 80, 40, 54, 74, 40,  0, 64, 74, 40,  0,
a2b
Cast 1 to 2 is 3.750000
b2a
Cast 2 to 1 is 4.333333

 
result 2 (multi-inheritance enabled):
|     C++ RTTI     | two float values
1c, 74, 40,  0, 2c, 74, 40,  0,  0,  0, 40, 40,  0,  0, 80, 40,
a2b
Cast 1 to 2 is 3.750000
b2a
Cast 2 to 1 is 4.333333

 

posted @ 2007-09-25 23:07  quanben  阅读(190)  评论(0编辑  收藏  举报