switch (object->type)
{
case TRIANGLE: ...
case SPHERE: ...
...
}While it clearly handles the different object types, it sets up regular patterns of duplicated code. Once for intersection, then for finding a color, etc. Each pattern also has to be modified if a new scene object is introduced. But I wanted something better, particularly I wanted to show that carrying a type field is unnecessary for my design. I concluded that I could have my scene objects carry their function pointers. (Note, the following code is still pseudo in nature and is provided for illustration and not compilation purposes).
typedef struct _SCENE_OBJECT {
float (*Intersect) (pSCENE_OBJECT, Vec3);
void (*Color) (pSCENE_OBJECT, Vec3 ...);
pSCENE_OBJECT next;
} SCENE_OBJECT, *pSCENE_OBJECT;
Then I declare my sphere scene object (and similarly for other scene objects), as follows:
typedef struct _SCENE_OBJECT_SPHERE {
SCENE_OBJECT generic;
....
} SCENE_OBJECT_SPHERE, *pSCENE_OBJECT_SPHERE;
Now, my scene object types have inherited from the base object. Therefore, the intersection loop from part one now has a single line intersection call:
dist = object->Intersect(object, ray);
This approach still has drawbacks, but it achieves a simple inheritance between structs in C, thereby providing a rudimentary OO capability to a language known for not having one. In part 3, I look forward to exploring some of the drawbacks, as well as the elusive discussion of how OO intrinsically works in C++ or other languages.
No comments:
Post a Comment