Skip to main content
gamedev.net
🔒 Locked

Octree Memory Management Problem?

Started by Destroyer 1 reply 1k views
Original Post
Destroyer
Destroyer
Now this is something I'm finding really difficult to understand... :P I'm building an Octree class which recursively builds from the root to its nodes. I've single stepped through the code, and pinned down the problem to one place, and when it happens. This code is built of the tutorial found at GameTutorials.com

void COctree::CreateNewNode(CVector3 *Vertices, vector<bool> TriangleList, unsigned int NumVertices, CVector3 Center, float Width, unsigned int TriCount, unsigned int NodeID)
{
	int i;
	int index = 0;
	
	CVector3 *pvNodeVertices;

	if(TriCount)		
	{

		try {
			pvNodeVertices = new CVector3 [TriCount * 3];
		} catch (bad_alloc xa) {
			LogImmediate("Log.txt", "Failed allocation");
		}

		++NodeCount;
		//We're adding 3 (2?) vertices for every triangle found

		for(i = 0; i < NumVertices; ++i)
		{
			if(TriangleList[i / 3])	
			{
				pvNodeVertices[index] = Vertices;
				index++;
			}
		}

		m_pOctreeNodes[NodeID] = new COctree; //Creating a new Octree for this Node
		m_pOctreeNodes[NodeID]->m_NodeID = (eOctreeNodes)NodeID;

		// Get the new node's center point depending on the nodexIndex (which of the 8 subdivided cubes).
		CVector3 vNodeCenter = GetNewNodeCenter(Center, m_Width, NodeID);

		//Since it will start recurse starting here, increment the Subdivision count
		++m_iSubDivisionCount;
		//This will assign the vertices to the node if necessary so we can delet pvNodeVertices after.
		LogImmediate("Log.txt", "Subdividing Current Node");
		m_pOctreeNodes[NodeID]->SubDivideNode(pvNodeVertices, TriCount * 3, Width / 2, vNodeCenter); // The new width is HALF the previous width
		//We've just come out of recursing so decrease the Subdivision count
		LogImmediate("Log.txt", "Finished Subdividing  Node");
		--m_iSubDivisionCount;

		delete [] pvNodeVertices;
		LogImmediate("Log.txt", "Sucessful delete");
	}
}

The "SubDivideNode" method calls CreateNewNode to build the 8 nodes off the current one. The problem happens the first node of the root of the tree is recursively subdivided. Every thing seems to divide perfectly, all the nodes get set up nice... but when it comes back out to the root node as soon as it tries to "delete [] pvNodeVertices" the debugger suddenly spews out: "User breakpoint called at (Insert random memory adress here)" Which happens to be in the module of "ntdll.dll". This is also where the program seems to crash, my LogImmediate functions writes text to a file. CVector3 doesn't do any memory management of its own. And pvNodeVertices seems to always allocate memory without "throw"ing anything bad... What's going on ? :) Thanks for your time in advance.
snk_kid
snk_kid
Can you post the whole code for COctree type? its hard to tell I have a suspicion it has something to do with your SubDivideNode method where your passing your vertex list to it, and your doing some kind of shallow copying then when you delete the list you have one or more invalid pointers somewhere that you try to dereference and use.

Also from the code you have posted there are a couple of things i would suggest you change, pass your vector of booleans & center vector by reference not by value. Something that seems to be a strange is your casting NodeID to type eOctreeNodes why do you need to do this for?. Last thing but this is just a personal preference i would change vertex list using raw pointers with standard library list of CVector3 passed by reference in that function.
Destroyer
Destroyer
Thanks,

Your suggestions are appreciated, and yes, of course, I should be passing by reference, and not by value :).

The whole m_NodeID thing was just for debugging, it was hard keeping track of where I was in the tree. So I added it and single stepped through it. I could keep track in tree where the program crashed. And yes, it's silly to pass an unsigned int and cast it to an eOctreeNodes enumeration, I've changed it. It was just a quick way of trying to debug this problem of mine.

I'm not going to post the whole class implementation, because it's quite large.
But as requested, I'll post the SubDivideNode method, all the other methods called are rather self explanatory ;) and don't involve any memory management...

So here it is:

void COctree::SubDivideNode(CVector3 *pvVertices, unsigned int NumVertices, float Width, CVector3 Center){	int i; //index for the the for loops	unsigned int NumTri1 = 0;		// TOP_LEFT_FRONT	unsigned int NumTri2 = 0;		// TOP_LEFT_REAR	unsigned int NumTri3 = 0;		// TOP_RIGHT_REAR	unsigned int NumTri4 = 0;		// TOP_RIGHT_FRONT	unsigned int NumTri5 = 0;		// BOTTOM_LEFT_FRONT	unsigned int NumTri6 = 0;		// BOTTOM_LEFT_REAR	unsigned int NumTri7 = 0;		// BOTTOM_RIGHT_REAR	unsigned int NumTri8 = 0;		// BOTTOM_RIGHT_FRONT	m_Width = Width;	m_vCenter = Center;	AddDebugCube(m_vCenter, m_Width);	m_SubDivision = m_iSubDivisionCount;	if(m_SubDivision == 0)		m_NodeID = ROOT;	m_iNumTriangles = NumVertices / 3;	LogImmediate("Log.txt", "Tri Count %i, Sub Count %i, MaxTri %i, MaxSub %i", m_iNumTriangles, m_iSubDivisionCount, MaxTriangles, MaxSubdivisions);	if( (m_iSubDivisionCount < MaxSubdivisions) && (m_iNumTriangles > MaxTriangles) )	{		m_fSubDivided = true;		//Stores the number of Triangles for each node and which triangle refers to which vertex		vector<bool> TriList1(m_iNumTriangles);		// TOP_LEFT_FRONT		vector<bool> TriList2(m_iNumTriangles);		// TOP_LEFT_REAR		vector<bool> TriList3(m_iNumTriangles);		// TOP_RIGHT_REAR		vector<bool> TriList4(m_iNumTriangles);		// TOP_RIGHT_FRONT		vector<bool> TriList5(m_iNumTriangles);		// BOTTOM_LEFT_FRONT		vector<bool> TriList6(m_iNumTriangles);		// BOTTOM_LEFT_REAR		vector<bool> TriList7(m_iNumTriangles);		// BOTTOM_RIGHT_REAR		vector<bool> TriList8(m_iNumTriangles);		// BOTTOM_RIGHT_FRONT			//Count the number of triangles and store it in a list...		//Dividing by 3 because we want to count the number of TRIANGLES, not vertices		for(i = 0; i < NumVertices; ++i)		{			//TOP LEFT FRONT node			if( (pvVertices.x <= m_vCenter.x) && (pvVertices.y >= m_vCenter.y) && (pvVertices.z >= m_vCenter.z) ) 				TriList1[i / 3] = true;			//TOP LEFT BACK node			if( (pvVertices.x <= m_vCenter.x) && (pvVertices.y >= m_vCenter.y) && (pvVertices.z <= m_vCenter.z) ) 				TriList2[i / 3] = true;			//TOP RIGHT BACK node			if( (pvVertices.x >= m_vCenter.x) && (pvVertices.y >= m_vCenter.y) && (pvVertices.z <= m_vCenter.z) ) 				TriList3[i / 3] = true;			//TOP RIGHT FRONT node			if( (pvVertices.x >= m_vCenter.x) && (pvVertices.y >= m_vCenter.y) && (pvVertices.z >= m_vCenter.z) ) 				TriList4[i / 3] = true;			//BOTTOM LEFT FRONT node			if( (pvVertices.x <= m_vCenter.x) && (pvVertices.y <= m_vCenter.y) && (pvVertices.z >= m_vCenter.z) ) 				TriList5[i / 3] = true;			//BOTTOM LEFT BACK node			if( (pvVertices.x <= m_vCenter.x) && (pvVertices.y <= m_vCenter.y) && (pvVertices.z <= m_vCenter.z) ) 				TriList6[i / 3] = true;			//BOTTOM RIGHT BACK node			if( (pvVertices.x >= m_vCenter.x) && (pvVertices.y <= m_vCenter.y) && (pvVertices.z <= m_vCenter.z) ) 				TriList7[i / 3] = true;			//BOTTOM RIGHT FRONT node			if( (pvVertices.x >= m_vCenter.x) && (pvVertices.y <= m_vCenter.y) && (pvVertices.z >= m_vCenter.z) ) 				TriList8[i / 3] = true;		}				//Count the number of triangle for each node		for(i = 0; i < m_iNumTriangles; ++i)  		{			if(TriList1)	NumTri1++;				if(TriList2)	NumTri2++;			if(TriList3)	NumTri3++;				if(TriList4)	NumTri4++;			if(TriList5)	NumTri5++;				if(TriList6)	NumTri6++;			if(TriList7)	NumTri7++;			if(TriList8)	NumTri8++;		}		CreateNewNode(pvVertices, TriList1, NumVertices, m_vCenter, m_Width, NumTri1, TOP_LEFT_FRONT);		CreateNewNode(pvVertices, TriList2, NumVertices, m_vCenter, m_Width, NumTri2, TOP_LEFT_REAR);		CreateNewNode(pvVertices, TriList3, NumVertices, m_vCenter, m_Width, NumTri3, TOP_RIGHT_REAR);		CreateNewNode(pvVertices, TriList4, NumVertices, m_vCenter, m_Width, NumTri4, TOP_RIGHT_FRONT);		CreateNewNode(pvVertices, TriList5, NumVertices, m_vCenter, m_Width, NumTri5, BOTTOM_LEFT_FRONT);		CreateNewNode(pvVertices, TriList6, NumVertices, m_vCenter, m_Width, NumTri6, BOTTOM_LEFT_REAR);		CreateNewNode(pvVertices, TriList7, NumVertices, m_vCenter, m_Width, NumTri7, BOTTOM_RIGHT_REAR);		CreateNewNode(pvVertices, TriList8, NumVertices, m_vCenter, m_Width, NumTri8, BOTTOM_RIGHT_FRONT);	}	else	{		//Give this node the vertices...		m_fSubDivided = false;		m_pvVertices = new CVector3 [NumVertices];		memset(m_pvVertices, 0, sizeof(CVector3) * NumVertices);		memcpy(m_pvVertices, pvVertices, sizeof(CVector3) * NumVertices);	//	NodeCount++;	}}


Again, thanks for your time in advance. :)

Topic Locked

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

Sign in to reply to this topic.