3D Engine Structure?

>>Use typical object oriented design approaches. Look for the nouns, like scene, object, terrain, model, camera, etc. and make classes out of them. Look for opportunites to use inheritance as well. Personally, I have all of my objects derived directly or indirectly from an Entity class, and all moving entities derived from a DynamicEntity class. This allows me to share positioning and physics code between all of my different types of objects. Hope this gives you some ideas.<<

i dont like inheritence from what ive seen in textbooks.
eg
struct Object{}

struct SpaceShip : public Object{}

struct Alien : public SpaceShip{}

struct Player : public SpaceShip{}

etc personally i find this bollux.

the only inheritence i use is the following this is the single structure that gets inherited in the whole engine

struct Object
{
Object() { set_ID(); }
int ID;
int object_type;
};

struct Alien : public Object
{};

struct Xtree : public Object
{};

thus any object can comunicate with any other object in the scene.

You wouldnt make alien derived from space ship. I use something like this:

class Entity

class DynamicEntity : public Entity

class ParticleCluster : public DynamicEntity

class Camera : public DynamicEntity

class Light : public DynamicEntity

class ModelEntity : public DynamicEntity

class Character : public ModelEntity

Sigh it’s a shame that Martin Shaw mistook himself for a serious actor, didn’t want to be typecast and put the kybosh on repeats (at least that’s what I heard). Best series ever.

Do do do, doobie doobie do do, do do do do do.

I got an idea how to create my engine.

is this a good way ?

first I have created a main class called C_ICE3D. in that class I have a virtual Render function and a pointer to my renderer (only OpenGL at the moment). and a World class that contains a CameraManger, LightManager and an ObjectManager.

ex:
class C_ICE3D {
C_IceRenderer *Renderer;
C_IceWorld *World;

virtual void Render(void);
StartEngine(HWND hwnd);
StopEngine();
};

then my world class looks like this

class C_IceWorld {
C_CameraManager *Cameras;
C_LightManager *Lights;
C_ObjectManager *Objects;
C_TextureManager *Textures;
C_TextManager *Text;

void Render();

};

and my render class has a C_Camera class pointer to the active camera from the camera manager, and then it has a pointer to all the other managers (Light, Objects, Font, Texture) the Render class calls the LightManager class to get the lights currently active (class can contain more then 8 lights but only 8 lights active at once) then it sets all light propertis and positions, after that it calls the ObjectManager to get a RenderObjectList that list points to the objects in the ObjectManager in the order to render them (Z-Sort, texture-sort and so on). when the objects renders the texturemanager is called to get the texture(s) for the object(s).
when all objects is done the TextManager is called to get the text-strings and position, colors/texture and then it prints out all text.

to use the C_ICE3D class you have to create your own class that inherits from C_ICE3D

ex:
class C_MyEngine : public C_ICE3D {
void Render(void); // This is the render loop
};

then create your render window and in WM_CREATE: call MyEngine->StartEngine(hwnd);

you have to call World->Render(); in your render loop to render all objects… I made it that way so you can disable the use of the buildt in World Class.

is this a good solution?

Did any of you see The Bullsh*tters? It was a parody of The Professionals done by the “Comic Strip Presents…” people?
The homo-erotic undertones of the series were explored quite extensively…it was hilarious. Keith Alan and Peter Richardson got it bang on.

>>>then create your render window and in WM_CREATE: call MyEngine->StartEngine(hwnd);

you have to call World->Render(); in your render loop to render all objects… I made it that way so you can disable the use of the buildt in World Class.

is this a good solution?<<<

The least I can say is

MyEngine->StartEngine(hwnd);

I don’t know what the above does, but personally, I wouldn’t.

as for
World->Render();

that’s more inline.

>>C_CameraManager *Cameras;
C_LightManager *Lights;
C_ObjectManager *Objects;
C_TextureManager *Textures;
C_TextManager *Text;<<

textures dont belong in the same structure with the rest (not sure what text is doing there also?)

also try to minimize use of pointers, eg what happens if an object has a pointer to a texture + then later the texture doesnt exist?
bummer, use IDs instead

I would use interface pointers rather than concrete pointers, with contracts between the interfaces and the users.

Then I’d build the system in layers, where there’s generic allocators, containers, and strategies at the bottom; specific implementations and adaptors in the middle; application code that instantiates and uses all this stuff at the top. And I’d be really strict about layering.

Originally posted by V-man:
MyEngine->StartEngine(hwnd);
World->Render();

well the MyEngine->StartEngine(hwnd); starts the renderloop in a new thread that’s why I have it that way.

The World->Render(); is a function to render all objects in my world class.

Originally posted by zed:
textures dont belong in the same structure with the rest (not sure what text is doing there also?)

how should I control the texture and text then?

I will use ID’s and then when I render the stuff the renderfunction will call the TextureManager for the texture with the specefic ID.

Originally posted by jwatte:

I would use interface pointers rather than concrete pointers, with contracts between the interfaces and the users.

what do you mean with that?

Originally posted by McZ:
what do you mean with that?

He most likely means that you should define abstract base classes. Then derive concrete classes from your abstract classes. Your client code would have a pointer to the abstract class that points to some concrete class. For example, some pseudocode:

class IModelLoader
{
virtual Load() = 0;
};

class C3DSLoader : public IModelLoader
{
Load();
};

class CMD3Loader : public IModelLoader
{
Load();
};

class CEngine
{
public:

private:
IModelLoader mLoader;
// or even better
std::vector<IModelLoader
> mLoaders;
};

What I do is store my loaders in a std::map. They are mapped with the file extensions that they handle. So given a filename, I lookup the appropriate loader by parsing the file extension and then I load away.

So what are the advantages? I don’t have to keep adding Load3DS(), LoadFoo(), LoadBar() member functions to some low-level which would require a recompile throughout the whole codebase.

Since I use pointers in my interfaces rather than objects, I can forward declare classes rather than #include the file.

// engine.h

// Forward declaration
// #include “modelloader.h” not required
class IModelLoader;

class CEngine
{
public:

private:

IModelLoader *mLoader;
};

Btw, I recommend reading
Design Patterns. Gamma et all.
http://www3.addall.com/New/compare.cgi?isbn=0201633612

Warning: Design patterns are not a silver bullet though. After reading the book, everything will look like a pattern. But experience will help you figure out when to apply a pattern.

I also recommend Large Scale C++ Software Design. http://www3.addall.com/New/compare.cgi?isbn=0201633620

Thanks for the answer PK.

now I understand. and I already use that type of pointers. my FileManager is buildt that way. and my render class

ex.

class C_Renderer {
// some private stuff
public:
virtual void CreateRenderer();
virtual void Render();

};

then when I init the engine I choose wich renderer to use.

class C_RendererGL : public C_Renderer {

};

or

clas C_RendererD3D : public C_Renderer {

};

the Direct3D version isn’t functional yet though.

my FileManager works the same way… with only one Load(…); function and then it checks the filetype and choose the correct class for it… ex. C_AseFile for ase files…

[This message has been edited by McZ (edited 02-17-2003).]

Above are links to other game engine projects. Often game engines are built ontop of scene graphs, reusing whats out there might save you alot of time, or might help in guiding the developing on your own rendering code.

The three main open source scene graphs are:
http://www.openscenegraph.org http://www.plib.org http://www.opensg.org

Robert.