Game Development Community

Help needed with scene graph reorganization

by Ben Versaw · in Technical Issues · 06/13/2007 (6:38 pm) · 2 replies

I ran into a problem with my game engine I am building that uses a scene graph. Mainly that if I want an object to be draw over another object the object on top must be added to the scene graph after the object on bottom. (Note: This is logical and perfectly acceptable behavior for a scene graph)

To make this simpler I added the idea of draw layers, so that the scene graph would be reorganized so that the lowest draw layers are added first and the highest draw layers are added last.

I figured out a way to do this quite easily (or so I thought), however I ran across a strange problem that caused the program to enter an endless loop.

Eventually I discovered that this was because the nodes were being copied into the new tree directly, which was as I had programed it, this caused the last node of the new scene graph to often point to a node listed earlier in the graph thereby causing an infinite loop.

I then came up with a genius idea, at least it seemed like it at the time, to clear the nodes of their pointer to the next node in the scene graph. However as many of you probably have realized by now if I am only passing pointers of the nodes around then that method directly clears the node itself and causing the old scene graph to be broken in such a way that the reorganization cannot continue.

So I am now thoroughly stumped on what to do and need any suggestions or help that this community can give. Below you can find my own attempt at doing this.

Please note, however, that I copied it directly out of my source code and that it was commented out due to sheer frustrated so it quite likely has a number of errors that I introduced trying to fix it.

Any help would earn my deepest thanks,
-BenV

void ScreenObject::ReorganizeSceneGraph(void)
{
	SceneObject *m_pRootNewGraph = 0;

	int reordered = 0;
	int curdraworder = m_iLowestDrawLayer;

	while(reordered < m_iNumObjects)
	{
		SceneObject *pObject = 0;
		pObject = m_pRootObj;
		while(pObject)
		{
			if(reordered < m_iNumObjects)
			{
				if(pObject->GetDrawLayer()==curdraworder)
				{
					if(&m_pRootNewGraph == NULL)
					{
						m_pRootNewGraph = pObject;
						m_pRootNewGraph.ClearHierarchy();
					}
					else
					{
						SceneObject *nObj = pObject;
						nObj->ClearHierarchy();
						SceneObject* pObj = m_pRootNewGraph;
						while(pObj->GetNext())
						{
							pObj = pObj->GetNext();
						}
						pObj->AddAfter(nObj);
					}
					reordered++;
				}
				pObject = pObject->GetNext();
			}
			else
			{
				pObject = NULL;
			}
		}
		curdraworder++;
	}

	//Copy the new graph
	m_iNumObjects = 0;
	m_pRootObj = m_pRootNewGraph;
}

#1
06/13/2007 (9:55 pm)
Rather than organizing the objects sequentially, may you should try adding a "draw layer index" for each object. for instance, the draw layer index could be based on the distance the object is from the camera. objects could be grouped together based on their index. when you render the scene, you can render each draw layer separately by traversing the list for the corresponding index. all the objects with that index would be drawn. increment the index and search the list again for the new index. it's not the most efficient system, but I think it would be the best.

if you would prefer to use pointers you could also try using a global ***Sceneobject pointer. however, it would be difficult to maintain a list using that.
#2
06/14/2007 (8:10 am)
I actually got several useful solutions on IRC last night. I will post them in a hopefully useful form sometime later today when I have time. Right now I'm going to be trying a render queue method that was suggested.

Thank you for all the help,
-BenV