Managing Game States

Started by
16 comments, last by Hiiri 12 years ago
Btw. do you have to open up your projects? Aren't they always open? :)
Advertisement
I used to have one CSceneManager which was created by the CGame class, but then I had to make hacks to get multiple cameras working in the same scene when we wanted to draw one 3D scene and then another on top of it. Some objects were tagged to one camera and some to the other.
It didn’t make sense so in my new engine I let users create their own CSceneManager instances and as many of them as they please. This is a lot more elegant and efficient.

The scene is set up in the Init() class on CState.

As for how they are rendered, you have it backwards.
A rendered should never know what a scene is.
A scene knows what a scene is and it should render itself using the abstract and general-purpose functions provided to it by the renderer.

m_smScene.Draw().

The scene culls objects, selects the active camera, applies the projection matrices and other render states that need to be set, and eventually tells objects to draw themselves.
Objects set shaders for themselves, activate vertex and index buffers for themselves, and perform a render.



Btw. do you have to open up your projects? Aren't they always open? smile.png

Not this week. I am watching Avatar: The Last Airbender by recommendation from a friend. But only 2 more left to watch.


L. Spiro

I restore Nintendo 64 video-game OST’s into HD! https://www.youtube.com/channel/UCCtX_wedtZ5BoyQBXEhnVZw/playlists?view=1&sort=lad&flow=grid

Ah I see.. I only have the root node in my state and then pass that to the renderer.. so I guess my renderer is kind of acting as my scenemanager.. even though I'm still doing the traversal and culling in the scene nodes themself though.. sceneNode.GetRenderablesCulled().. I'll redesign it so I'll move stuff into a scenemanager..

Im not sure where I should put my templated resource managers.. the manager that make sure there is only one instance of each loaded resource at one time.. Right now I've put the resource managers related to the renderer in the renderer.. so the user would do:


void MyState::Init()
{
VertexBuffer vBuffer("vertexbuffer.file");
int handlevBuffer = m_renderer->Register(vBuffer);
IndexBuffer iBuffer("indexbuffer.file");
int handleiBuffer = m_renderer->Register(iBuffer);
// more setup
Renderable renderable(handlevBuffer, handleiBuffer, handleShader, ...);
m_scene->addNode(renderable);
}


So if I try to register a vertex buffer with a filename that is already registered it will return a handle to the one already registered instead of storing the new one.

Been thinking of having a ResourceManagerManager, but even the name of that sounds wrong tongue.png If I put it in the scenemanager I wont be able to use the same resource managers for the different scenes..
You generally don’t load “vertex files” and “index files”.
You load models. Any sharing between vertex and index buffers can be predetermined offline, since it is unlikely any vertex buffers will ever be shared between models.
Trying to share all vertex buffers on a system-wide scale is over-engineering.

This is how mine looks:
LSVOID LSE_CALL CModelTest::Init( CGame * _pgGame, LSINT32 _ui32State, LSINT32 _ui32PrevState, LSUINTPTR _uptrUser ) {
m_dmipInstance = m_sgpScene->CreateDrawableModelInstance( "KinoGirl.lsm" );
m_sgpScene->CreateDrawableModelInstance( "Ground.lsm" )->SetCastsShadow( false );
}


You can probably agree that this would be more preferable for anyone using your engine, including yourself.

There is no need for a global general-purpose resource manager. Resources don’t have enough in common to warrant such a thing.
As far as anything managing resources goes, there are unique ones for the scene, models, etc.
And all of these are handled at a high level. For example you are proposing to share all vertex buffers period. What if I want to load the same one again so I can make changes to it?
A more common example of the same thing is textures. I very easily might want to apply some filter that is expensive if done in a shader, so I want to modify the original. But that would change all instances of it, so I need to be able to load multiple copies of it.

However I know that within my model library I am not modifying those textures. They are shared between each other and only each other. No other system is involved, so while it may be wasteful if a sprite were to later reload the same file, it is the lesser of evils and in practice never happens. And textures within the sprite system are shared amongst each other as well.


L. Spiro

I restore Nintendo 64 video-game OST’s into HD! https://www.youtube.com/channel/UCCtX_wedtZ5BoyQBXEhnVZw/playlists?view=1&sort=lad&flow=grid

Yes the plan has been to load a renderable from file and the code loading the renderable will be loading vertex and index buffer like that.. so I would have

/renderables/Cube01/indexbuffer
/renderables/Cube01/vertexbuffer
/renderables/Cube01/shader
/renderables/Cube01/renderable
/textures/sometexture.png

The user would do something like loadRenderable('/meshes/Cube01/') and it would find the renderable file which have info on how stuff should be set up.. I got a dat archive file and a gui tool I've created and it exports any format with the assimp library and puts the files like that. hum.. maybe I should change it and put it all into my own model format.. Its easy to work with it when its like that though.. so I wasn't realy thinking of sharing the vertex buffers between different renderables as it is identified by the path in the dat file..

But you're saying that I should share renderables/textures, but still make it possible to load a seperate instance of it?

...
What if I want to load the same one again so I can make changes to it?
...

Seems to me the best way to handle this would be to have a system which only loads resources once (from disk, DVD, internet, whatever) but employ copy-on-write semantics on your shared resources.

But you're saying that I should share renderables/textures, but still make it possible to load a seperate instance of it?

Basically. The below reply provides a reason as to why.



[quote name='YogurtEmperor' timestamp='1333110537' post='4926652']
...
What if I want to load the same one again so I can make changes to it?
...

Seems to me the best way to handle this would be to have a system which only loads resources once (from disk, DVD, internet, whatever) but employ copy-on-write semantics on your shared resources.
[/quote]
I saw a video about some game that allowed slicing enemies in half and I wanted to support such an ability in my own, and the best way I thought to do that was via copy-on-write.

But later I realized that the problem with copy-on-write is that it is hidden overhead. People might be doing it and incurring a significant amount of overhead without understanding why.
When it comes to game engines, this isn’t acceptable. Users should know what actions they are doing to cause performance issues and be pushed towards a more performant way of accomplishing the same thing.

But this is a perspective unique to myself—not everyone here is planning on making a business out of middleware.
My original mindset allowed copy-on-write because I wasn’t considering other people using my engine (even though that was my goal and I should have been). If you are just making your own personal engine, copy-on-write is a very elegant solution to this problem.


L. Spiro

I restore Nintendo 64 video-game OST’s into HD! https://www.youtube.com/channel/UCCtX_wedtZ5BoyQBXEhnVZw/playlists?view=1&sort=lad&flow=grid

Wouldn't some sort of stack of states work pretty well. You throw in the topmost of the stack the state you're showing currently, and once you're done with it, you pop it out. Then use some boolean value when creating state to determine, if the state manager goes further in the state stack. Like lets say you have following stack:

Options - state
Main game - state
The bottom - state

So looking this way, the control needs to go on the topmost object, but the logic update needs to go through whole stack. At least this would be the way how I would start implementing the controller, but probably other people have better ideas.

Maybe you could pass some values like, canDrawUnder and capturesController, or something like that to determine how far of the stack you must go.

This topic is closed to new replies.

Advertisement