Skip to main content
gamedev.net
🔒 Locked

Object Oriented 3d Engine

Started by chewy Jul 6, 2000 at 8:56 AM 10 replies 550+ views
Original Post
chewy
chewy
Ok I''m interested in everyone''s opinion on how they would design a 3d engine implemented in OO. What classes would you have and how would they be related. Obviously you would have a CEngine class but what other classes would you design? ideally you would want to be able to implement indoor rendering, outdoor rendering, terrain rendering, etc. using the same parent class so that your Engine is much more portable across different projects. Any ideas or am I off my rocker
Ingenu
Ingenu
I''m code/class desiging my 3dengine right now.
(Along with looking for a real nice way to do shadows!:^)

There''s no big challenge doing a 3d engine in OO style.

Simply think of the kind of objects you''ll have in the engine.
(Static objects, lights, moving objects, ...)
And what you''ll have to manage
(textures, world, camera,...)

And you''ll end up with a good idea of the classes you''ll need.

...Still working on my design...

-* So many things to do, so little time to spend. *-
-* So many things to do, so little time to spend. *-
kill
kill
It is a challange. I am working on something like this now, and it takes guts to create a good design.

You have your CEngine that initializes all your stuff.
CCamera, CViewport to implement your basic transformations. CLight, CMaterial. May be CTexture. You might encapsulate all your lighting stuff into CLight, or u can make ur CLight a base clase, and inherit CSunLight from it, CDirectionalLight, etc. Depends on your needs.

Now you''re ready to design your basic functionality CObject3D or something like that.

Now the hard part. You have to design your actual rendering classes. CLandscape, CPortal, etc. Basically the ways you will render things. This will render levels for you. Now you have to think of how to combine the two: how r u gonna have a building on a landscape in one level. How to switch effectively between the portal rendering and terrain rendering, etc.

It takes guts to do all this, but with good design, you''ll be flexible enough to change things when they have to be changed without changing anything major in the engine architecture.
SHilbert
SHilbert
I'm thinking of making my engine rendering-based, rather than scene-based (I know that sounds odd, but let me explain): for example, instead of adding everything to a global scene and calling CScene::Render(), you just have a bunch of CMeshes that you can render in any order you want. That way you can easily draw transparent things last & turn off Z-buffering for skydomes and things like that. It offers more room for trickery, basically Plus it's easier to adapt to different games, because it doesn't have a strict heirarchy. It's much more primitive (and maybe mundane), but I like it I'm not sure if it's really called an "engine" then, though.

lntakitopi@aol.com - http://www.geocities.com/guanajam

Edited by - SHilbert on July 6, 2000 2:44:59 PM
kill
kill
Making something like CScene::Render() limits the engine in many ways. There are a couple of design issues related to this.

1. Memory management. If you have something like CScene:AddObject(), there is a simple question: who''s going to be responsible for deleting these objects, and how r they going to be stored? I would prefer the user to manage all the memory management in this case. I don''t want the engine to manage anything, because it limites the user. Therefore, I prefer CMesh::Render() rather then CScene:Add()..., CScene::Render().
2. Who''s going to be responsible for the CScene::Render() routine? The engine? In that case you are going to limit the user. Big time. The user? Then there is no need to make CScene::Render().

I got these two from the top of my head. I''m sure I could think of a lot more issues.

Don''t get me wrong, I''m not saying that CScene::Render() is an inferior way. It''s definetly good if you''re developing an engine that is very static in a sense that it''s good for one type of game. In that case, you know how everything is going to be rendered, so you don''t need to give the user flexibility.

CMesh::Render() is definetly a better way for general engines.

I propose to keep this post alive, because this is an ongoing issue for many people, and it''s a good idea to discuss these issues here.
XBTC
XBTC
First of all the most important thing(at least for me) is a strict division of the front(no drawing just vis-determination...) and the back end(actual drawing)....At the point where they are connected,nothing more than triangles(or other primitives) should be exchanged!This gives you max freedom to change especially the special-effect-blending-lightmap-whatever things without even touching the front end.I think the back-end needs some state-machinery like OpenGl itself.Every face has it´s properties and sets the according state.If you sort your faces in a good way you won´t have much state changes.

To the Moving\static thing:I would strictly divide the rendering of the static level-geometry and the moving objects.However the moving objects should use the same Backend as the static....

These are just some ideas and their work good for me but I think these things are the most important factor for the succes or fail of a 3D-Engine so (as kill said) it is good to keep such a thread going.

Greets,XBTC!

Bobas_Dog
Bobas_Dog
kill,

You raise some interesting points, and since I''m working on an OO 3D engine right now, I have recently faced some of the problems you have raised. What I did, was I stored all of the objects in a linked list (I know they are not the most efficient, but it does the job...). Since my LinkedList class is extremely general, I can store all sorts of nice stuff in it. This way, the user would have access to all geometric objects, lights, etc... in the engine, and would thus be able to alter, delete, add objects into the engine. From a design/coding standpoint, I think this is a simple way of doing things.

I should add a disclaimer that this is the first 3D-engine I''ve worked on alone (I did a raytracer, and a regular openGL renderer in school, but the Prof. provided much of the engine for us). But I think using OO is a simpler way of designing an engine, and a good design can be applied to various types of games (FPS, RTS, RPG, etc...), and for some one like me who really wants to make the game (while still getting a feel for the other parts of the engine), this is a great way to go about it. Of course, this is all my humble opinion...

Sorry about the length of this blabber,

Andy, err... Bobas_Dog
Hway
Hway
(off-topic rant)
All thieves should be taken behind a barn and executed without trial when caught... I just spent about $100 to replace my car radio/cassette player, and I still have to buy new loudspeakers. Just because some a**h***s thought that money comes easier by stealing stuff than by working for it... I still can''t understand why they stole also my two-year old, worn-out, dirty sneakers... Ohwell. Time to buy car alarm system...
(/off-topic)

I prefer to see "renderer" as distict package, which does nothing but draws tris.

So I have Cd3d (whee, what a name) which does strictly D3D init, rendering and so on. Currently, it has also a custom geometry system which shares matrices with D3D''s geometry pipe, so I can use D3DVERTEX, D3DLVERTEX and D3DTLVERTEX as needed in same program... (why? hint: 2d-coords for transformed vertices...)
Geometry system is kinda "expansion", and probably should completely be separated, but currently "it works, so I won''t fix it..."

Then I have CImage, which actually should be named CBitmap, for it handles all images and textures and format conversion and surfaces as needed. And yes, in hierarchy it is below Cd3d...

Then there is CImageLib, which is a "higher" level expansion of CImage (supports various formats other than my own "spritefileformat", like PCX, LBM, JPG and so on).

CModel has 3D models, and does everything related to them.

CObject is "expansion" of CModel, and handles for example situations where I have in scene hundred objects that all have same 3D model...

In current project, above those all are for example CMap, which does map rendering by using Cd3d directly, and object rendering through CObject interface...

Now, this probably isn''t the best way to arrange object hierarchy, but it works pretty well...
~~~ "'impossible' is a word in the dictonary of fools" --Napoleon
RWarden
RWarden
I think it''s a good idea to keep the scene management and the rendering engines seperate. In the engine I''m toying with, I have a CRenderDevice class, from which I have derived classes CSoftwareDevice, COpenGLDevice, CD3DDevice, etc.
(Currently only the OpenGL device is fully implemented and I''m working on the software.)
Each of these devices has the same interface, so without changing a single line of code I can switch from software to OpenGL to D3D, simply by doing something like this:

    
// to switch to software..

CSoftwareDevice* pSoftDev = new CSoftwareDevice;
// init device..

// ...

MyEngine->SetRenderDevice ( pSoftDev );


Don''t you love polymorphism?
I do have a question.. currently I have two options for storing lists of things (vertices, polygons, etc.), both implemented as templated classes. One is a sorted array and the other a linked list. I''m thinking the array is probably faster for lists that don''t need to be updated very often (usually only during loading scenes) while the linked lists are marginally slower for accessing but much, much faster for inserting items on the fly.
So, what are you all using?

-RWarden (roberte@maui.net)
shamen
shamen
It seems i also have chosen a trodden path.
Although i have a scene, all rendered objects that can be added to the scene have an abstract base class of CObject. Each primative is then derived from from this base and knows how to display itself.
There can be multiple scenes, which the engine knows how to order based upon rules, then the engine basically calls Show() for every object (passing itself as a parameter). Using this method, the Engine is completely abstracted from the objects too. This basically means my engine is in charge of resources (textures, meshes, sounds, screen representation etc) but leaves it to the objects as to how to use the resources.
The disadvantages of doing this is that my 3D implementation is relatively fixed (OpenGL only). Otherwise a further sub-engine would be needed to abstract all the 3D functions. As my two target systems are Windows and Linux, this isnt a problem to me.
chewy
chewy
Wow great discussion. So I have another question is anyone making their engines have the ability to do multiple rendering api's? i.e. D3d, OGL, Software. I know shamen said he couldn't do it in his so how has everyone else implimented this.

Edited by - chewy on July 11, 2000 10:03:21 AM
shamen
shamen
RWarden - a reply to your question.

Personally i use arrays in the OpenGL vertex array format (but then i''m only using OpenGL). I think it depends on what you want to do with your objects. If the mesh is static (ie you''re not going to be added or removing vertices from it during the game) then i would use arrays - they are faster, particularly if you can pass them directly to your renderer.

What i do, is load (from wavefront obj files) my mesh data into linked lists using a class so i can play about with them a bit (smoothing normals, changing texture coordinates etc). Then i build arrays of data Primatives (grouped by texture) from this class which are saved in my own format and used by the engine.

I am going to add a Progressive Mesh capability to some of my primatives however, which means that i wont be able to use vertex arrays apart from the top collapse levels.

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.