design question...
I am currently working on my scenegraph design but I have several ideas for how the render system and such will be interfaced with it. Im going to run these ideas by you guys in hopes that you maybe able to help me see the various flaws and things that I maybe overlooking..
Being that this is my first large scale project, it's a bit hard for my to really fully visualise everything, so I can only explain my ideas to the best of my abilities...
Alrighty, well the first design I came up with was to keep the render system seperate from the scene graph and have the entities access the render system through the RenderEngine interface. This interface class would contain pointers to the various components of the render system such as the model manager, the material system, the shadow class, various gl extension classes, etc.
The scene graph would not be an entity node but more less the entity manager. It will be incharge of calling all entity updation, drawing, loading, freeing functions (the entities would then call these same functions for thier children). All common information that the entities need will either be wrapped up into a "world/level" class or the scene graph would contain the data. However, so that I wouldn't have to make a bunch of hacks so that the entities can access the scene graphs data, I think the earlier would be best.
The second design that seems to me like would work best is as follows:
The scene graph will be a node of some base class along with the entity base class. This class would then contain all of the common data such as the camera, rendering options (use shadows, use lights, use hardware or software implementations etc), collision functions, common physics options, etc. The scene graph would then still be incharge of updating all other entities.
A "world/level" class would then be responcible for loading maps and filling in the scene graph data from the map information. The renderer would more less be wrapped up in the scene graph/entity base class however, the entities would then access the various renderer components but would only be able to use what there allowed to by the base class.
Now that I think about it, the second design seems to be a lot more flexable and would present less "hacking". What do you guys think?
Sorry about the length of this thread, and if the mod feels that it should be moved else where, np. Thanks a lot guys.
~J
ok. The very first thing I thought when I read your ideas was when reading:
AHHH!!! NO NO ! :)
ok this is just my opinion, but that last bit is bad. giving game objects access to the low level rendering stuff is a very bad idea. For example, giving those objects the ability to disable lighting through glDisable, is a disaster just waiting to happen. Imagine if the next object assumes that lighting is enabled. Or it assumes that the depth bounds extension isn't enabled. Everything can blow up spectacuarly.
Trust me, I've had it happen :)
maybe I'm preaching to the converted, but the way to get around this problem is a technique called abstraction. Basically wrapping up what something does, and giving it a nice pretty interface that only does what you let be done, and does it through specification. Ie, instead of saying 'disable lighting' you say 'I want lighting disabled' - does that make sense? - like a boolean for lighting being on or off. So when it comes to rendering, some other code takes care of the glDisable/Enable call (if needed!) - and that way a problem will never occur as the game object never touches GL.
That way later on you can then go off and write a Direct3D back end and the rest of the code will be none the wiser either :)
anyway a couple of topics in recent memory on this are this and that.
Ok. overall though, you will probably find that no matter how well you design your system, it won't work. Or it won't work quite right. Don't be put off by this, you absolutly must make it. Otherwise you won't learn why it didn't quite work out right. But don't worry, you will hack it to peices during construction to get it to work, but in a year, it will get into a state where it's too difficult to get it to do anything new and fun, and you will start again, with a much better design.
Trust me [wink] - it's fun and it's the best way.
As for the object control design:
I do it something like this:
there is a overall controling object, maybe called GameState.
This doesn't actually control anything, but lets an object do things. It may, for example, have objects within called 'renderer', 'timer', 'input' and so on.
(although input might be better done through input objects, eg, CKeyboard..?)
Anyway, The point is, the object is a interface. Renderer may only allow one thing, rendering vertex data from vertex and index buffers. And that would be enough. There may be a higher level interface for the actual Game object that does things like set the camera, lighting, etc.
Now, for scenegraphing, why not treat a scene graph as another game object?
this is just an example, but imagine the only requirment of a game object is that it has a matrix to represent it's position and rotation...
And the 'GameObject' interface has a single method to override - 'render(GameState state, Matrix world)'.
Now.. in this case, a scene graph could just do:
world *= this.matrix;
foreach (GameObject go in scenegraph)
go.render(state, world);
That way, no matter what's in the scene graph (even other scene graphs), eveything still gets rendered correctly, and importantly, doesn't actually know what it resides withing (which is good).
A world/level object may has a scene graph within.. as another object.. and inside it's 'render' method, it may just be:
map.render(...)
scene.render(...)
players.render(...)
or the like.
When an object actually does want to render something on screen, then it would possibly be:
state.renderer.render(vertexbuffer,indexbuffer,TYPE.Triangles,shader);
and so on.
The actual renderer object, behind the scenes, may not actually do the renderering then and there, it may want to wait until all render() calls are made, then optimize things (eg, render all the same shaders at once).
overall, if you find you need to do a hack, you design is broken. And maybe it needs reworking. This design is fairly felxible, even though, in a lot of ways, very little is actually known at any one point. It's just what is known, and what can be done, is very useful.
I'm not saying do it this way or suffer my wrath! - I'm just giving an example thats close to what I use. Hopfully this will make you go 'ohh ahh yes! I know...' :)
does that make sense? :)
[Edited by - RipTorn on January 27, 2005 6:09:21 AM]
Quote:
...hadow class, various gl extension classes, etc...
AHHH!!! NO NO ! :)
ok this is just my opinion, but that last bit is bad. giving game objects access to the low level rendering stuff is a very bad idea. For example, giving those objects the ability to disable lighting through glDisable, is a disaster just waiting to happen. Imagine if the next object assumes that lighting is enabled. Or it assumes that the depth bounds extension isn't enabled. Everything can blow up spectacuarly.
Trust me, I've had it happen :)
maybe I'm preaching to the converted, but the way to get around this problem is a technique called abstraction. Basically wrapping up what something does, and giving it a nice pretty interface that only does what you let be done, and does it through specification. Ie, instead of saying 'disable lighting' you say 'I want lighting disabled' - does that make sense? - like a boolean for lighting being on or off. So when it comes to rendering, some other code takes care of the glDisable/Enable call (if needed!) - and that way a problem will never occur as the game object never touches GL.
That way later on you can then go off and write a Direct3D back end and the rest of the code will be none the wiser either :)
anyway a couple of topics in recent memory on this are this and that.
Ok. overall though, you will probably find that no matter how well you design your system, it won't work. Or it won't work quite right. Don't be put off by this, you absolutly must make it. Otherwise you won't learn why it didn't quite work out right. But don't worry, you will hack it to peices during construction to get it to work, but in a year, it will get into a state where it's too difficult to get it to do anything new and fun, and you will start again, with a much better design.
Trust me [wink] - it's fun and it's the best way.
As for the object control design:
I do it something like this:
there is a overall controling object, maybe called GameState.
This doesn't actually control anything, but lets an object do things. It may, for example, have objects within called 'renderer', 'timer', 'input' and so on.
(although input might be better done through input objects, eg, CKeyboard..?)
Anyway, The point is, the object is a interface. Renderer may only allow one thing, rendering vertex data from vertex and index buffers. And that would be enough. There may be a higher level interface for the actual Game object that does things like set the camera, lighting, etc.
Now, for scenegraphing, why not treat a scene graph as another game object?
this is just an example, but imagine the only requirment of a game object is that it has a matrix to represent it's position and rotation...
And the 'GameObject' interface has a single method to override - 'render(GameState state, Matrix world)'.
Now.. in this case, a scene graph could just do:
world *= this.matrix;
foreach (GameObject go in scenegraph)
go.render(state, world);
That way, no matter what's in the scene graph (even other scene graphs), eveything still gets rendered correctly, and importantly, doesn't actually know what it resides withing (which is good).
A world/level object may has a scene graph within.. as another object.. and inside it's 'render' method, it may just be:
map.render(...)
scene.render(...)
players.render(...)
or the like.
When an object actually does want to render something on screen, then it would possibly be:
state.renderer.render(vertexbuffer,indexbuffer,TYPE.Triangles,shader);
and so on.
The actual renderer object, behind the scenes, may not actually do the renderering then and there, it may want to wait until all render() calls are made, then optimize things (eg, render all the same shaders at once).
overall, if you find you need to do a hack, you design is broken. And maybe it needs reworking. This design is fairly felxible, even though, in a lot of ways, very little is actually known at any one point. It's just what is known, and what can be done, is very useful.
I'm not saying do it this way or suffer my wrath! - I'm just giving an example thats close to what I use. Hopfully this will make you go 'ohh ahh yes! I know...' :)
does that make sense? :)
[Edited by - RipTorn on January 27, 2005 6:09:21 AM]
This topic is closed to new replies.
Advertisement
Popular Topics
Advertisement