Пример #1
0
void COctree::CreateNode(CVector3 *pVertices, int numberOfVerts, CVector3 vCenter, float width)
{
    // This is our main function that creates the octree.  We will recurse through
    // this function until we finish subdividing.  Either this will be because we
    // subdivided too many levels or we divided all of the triangles up.

    // Create a variable to hold the number of triangles
    int numberOfTriangles = numberOfVerts / 3;

    // Initialize this node's center point.  Now we know the center of this node.
    m_vCenter = vCenter;

    // Initialize this nodes cube width.  Now we know the width of this current node.
    m_Width = width;

    // Add the current node to our debug rectangle list so we can visualize it.
    // We can now see this node visually as a cube when we render the rectangles.
    // Since it's a cube we pass in the width for width, height and depth.
    g_Debug.AddDebugRectangle(vCenter, width, width, width);

    // Check if we have too many triangles in this node and we haven't subdivided
    // above our max subdivisions.  If so, then we need to break this node into
    // 8 more nodes (hence the word OCTree).  Both must be true to divide this node.
    if( (numberOfTriangles > g_MaxTriangles) && (g_CurrentSubdivision < g_MaxSubdivisions) )
    {
        // Since we need to subdivide more we set the divided flag to true.
        // This let's us know that this node does NOT have any vertices assigned to it,
        // but nodes that perhaps have vertices stored in them (Or their nodes, etc....)
        // We will querey this variable when we are drawing the octree.
        m_bSubDivided = true;

        // Create a list for each new node to store if a triangle should be stored in it's
        // triangle list.  For each index it will be a true or false to tell us if that triangle
        // is in the cube of that node.  Below we check every point to see where it's
        // position is from the center (I.E. if it's above the center, to the left and
        // back it's the TOP_LEFT_BACK node).  Depending on the node we set the pList
        // index to true.  This will tell us later which triangles go to which node.
        // You might catch that this way will produce doubles in some nodes.  Some
        // triangles will intersect more than 1 node right?  We won't split the triangles
        // in this tutorial just to keep it simple, but the next tutorial we will.

        // Create the list of booleans for each triangle index
        vector<bool> pList1(numberOfTriangles);		// TOP_LEFT_FRONT node list
        vector<bool> pList2(numberOfTriangles);		// TOP_LEFT_BACK node list
        vector<bool> pList3(numberOfTriangles);		// TOP_RIGHT_BACK node list
        vector<bool> pList4(numberOfTriangles);		// TOP_RIGHT_FRONT node list
        vector<bool> pList5(numberOfTriangles);		// BOTTOM_LEFT_FRONT node list
        vector<bool> pList6(numberOfTriangles);		// BOTTOM_LEFT_BACK node list
        vector<bool> pList7(numberOfTriangles);		// BOTTOM_RIGHT_BACK node list
        vector<bool> pList8(numberOfTriangles);		// BOTTOM_RIGHT_FRONT node list

        // Create this variable to cut down the thickness of the code below (easier to read)
        CVector3 vCtr = vCenter;

        // Go through all of the vertices and check which node they belong too.  The way
        // we do this is use the center of our current node and check where the point
        // lies in relationship to the center.  For instance, if the point is
        // above, left and back from the center point it's the TOP_LEFT_BACK node.
        // You'll see we divide by 3 because there are 3 points in a triangle.
        // If the vertex index 0 and 1 are in a node, 0 / 3 and 1 / 3 is 0 so it will
        // just set the 0'th index to TRUE twice, which doesn't hurt anything.  When
        // we get to the 3rd vertex index of pVertices[] it will then be checking the
        // 1st index of the pList*[] array.  We do this because we want a list of the
        // triangles in the node, not the vertices.
        for(int i = 0; i < numberOfVerts; i++)
        {
            // Create some variables to cut down the thickness of the code (easier to read)
            CVector3 vPoint = pVertices[i];

            // Check if the point lines within the TOP LEFT FRONT node
            if( (vPoint.x <= vCtr.x) && (vPoint.y >= vCtr.y) && (vPoint.z >= vCtr.z) )
                pList1[i / 3] = true;

            // Check if the point lines within the TOP LEFT BACK node
            if( (vPoint.x <= vCtr.x) && (vPoint.y >= vCtr.y) && (vPoint.z <= vCtr.z) )
                pList2[i / 3] = true;

            // Check if the point lines within the TOP RIGHT BACK node
            if( (vPoint.x >= vCtr.x) && (vPoint.y >= vCtr.y) && (vPoint.z <= vCtr.z) )
                pList3[i / 3] = true;

            // Check if the point lines within the TOP RIGHT FRONT node
            if( (vPoint.x >= vCtr.x) && (vPoint.y >= vCtr.y) && (vPoint.z >= vCtr.z) )
                pList4[i / 3] = true;

            // Check if the point lines within the BOTTOM LEFT FRONT node
            if( (vPoint.x <= vCtr.x) && (vPoint.y <= vCtr.y) && (vPoint.z >= vCtr.z) )
                pList5[i / 3] = true;

            // Check if the point lines within the BOTTOM LEFT BACK node
            if( (vPoint.x <= vCtr.x) && (vPoint.y <= vCtr.y) && (vPoint.z <= vCtr.z) )
                pList6[i / 3] = true;

            // Check if the point lines within the BOTTOM RIGHT BACK node
            if( (vPoint.x >= vCtr.x) && (vPoint.y <= vCtr.y) && (vPoint.z <= vCtr.z) )
                pList7[i / 3] = true;

            // Check if the point lines within the BOTTOM RIGHT FRONT node
            if( (vPoint.x >= vCtr.x) && (vPoint.y <= vCtr.y) && (vPoint.z >= vCtr.z) )
                pList8[i / 3] = true;
        }

        // Here we create a variable for each list that holds how many triangles
        // were found for each of the 8 subdivided nodes.
        int triCount1 = 0;
        int triCount2 = 0;
        int triCount3 = 0;
        int triCount4 = 0;
        int triCount5 = 0;
        int triCount6 = 0;
        int triCount7 = 0;
        int triCount8 = 0;

        // Go through each of the lists and increase the triangle count for each node.
        for(int i = 0; i < numberOfTriangles; i++)
        {
            // Increase the triangle count for each node that has a "true" for the index i.
            if(pList1[i])	triCount1++;
            if(pList2[i])	triCount2++;
            if(pList3[i])	triCount3++;
            if(pList4[i])	triCount4++;
            if(pList5[i])	triCount5++;
            if(pList6[i])	triCount6++;
            if(pList7[i])	triCount7++;
            if(pList8[i])	triCount8++;
        }

        // Next we do the dirty work.  We need to set up the new nodes with the triangles
        // that are assigned to each node, along with the new center point of the node.
        // Through recursion we subdivide this node into 8 more nodes.

        // Create the subdivided nodes if necessary and then recurse through them.
        // The information passed into CreateNewNode() are essential for creating the
        // new nodes.  We pass the 8 ID's in so it knows how to calculate it's new center.
        CreateNewNode(pVertices, pList1, numberOfVerts, vCenter, width, triCount1, TOP_LEFT_FRONT);
        CreateNewNode(pVertices, pList2, numberOfVerts, vCenter, width, triCount2, TOP_LEFT_BACK);
        CreateNewNode(pVertices, pList3, numberOfVerts, vCenter, width, triCount3, TOP_RIGHT_BACK);
        CreateNewNode(pVertices, pList4, numberOfVerts, vCenter, width, triCount4, TOP_RIGHT_FRONT);
        CreateNewNode(pVertices, pList5, numberOfVerts, vCenter, width, triCount5, BOTTOM_LEFT_FRONT);
        CreateNewNode(pVertices, pList6, numberOfVerts, vCenter, width, triCount6, BOTTOM_LEFT_BACK);
        CreateNewNode(pVertices, pList7, numberOfVerts, vCenter, width, triCount7, BOTTOM_RIGHT_BACK);
        CreateNewNode(pVertices, pList8, numberOfVerts, vCenter, width, triCount8, BOTTOM_RIGHT_FRONT);
    }
    else
    {
        // If we get here we must either be subdivided past our max level, or our triangle
        // count went below the minimum amount of triangles so we need to store them.

        // Assign the vertices to this node since we reached the end node.
        // This will be the end node that actually gets called to be drawn.
        // We just pass in the vertices and vertex count to be assigned to this node.
        AssignVerticesToNode(pVertices, numberOfVerts);
    }
}
void COctree::CreateNode(t3DModel *pWorld, int numberOfTriangles, CVector3 vCenter, float width)
{
	// Initialize this node's center point.  Now we know the center of this node.
	m_vCenter = vCenter;

	// Initialize this nodes cube width.  Now we know the width of this current node.
	m_Width = width;

	// Add the current node to our debug rectangle list so we can visualize it.
	g_Debug.AddDebugRectangle(vCenter, width, width, width);

	// Check if we have too many triangles in this node and we haven't subdivided
	// above our max subdivisions.  If so, then we need to break this node into
	// 8 more nodes (hence the word OCTree).  Both must be true to divide this node.
	if( (numberOfTriangles > g_MaxTriangles) && (g_CurrentSubdivision < g_MaxSubdivisions) )
	{
		// Since we need to subdivide more we set the divided flag to true.
		m_bSubDivided = true;


/////// * /////////// * /////////// * NEW * /////// * /////////// * /////////// *
	
		// This function pretty much stays the same, except a small twist because
		// we are dealing with multiple objects for the scene, not just an array of vertices.
		// In the previous tutorials, we used a vector<> of booleans, but now we use our
		// tFaceList to store a vector of booleans for each object.

		// Create the list of tFaceLists for each child node
		vector<tFaceList> pList1(pWorld->numOfObjects);		// TOP_LEFT_FRONT node list
		vector<tFaceList> pList2(pWorld->numOfObjects);		// TOP_LEFT_BACK node list
		vector<tFaceList> pList3(pWorld->numOfObjects);		// TOP_RIGHT_BACK node list
		vector<tFaceList> pList4(pWorld->numOfObjects);		// TOP_RIGHT_FRONT node list
		vector<tFaceList> pList5(pWorld->numOfObjects);		// BOTTOM_LEFT_FRONT node list
		vector<tFaceList> pList6(pWorld->numOfObjects);		// BOTTOM_LEFT_BACK node list
		vector<tFaceList> pList7(pWorld->numOfObjects);		// BOTTOM_RIGHT_BACK node list
		vector<tFaceList> pList8(pWorld->numOfObjects);		// BOTTOM_RIGHT_FRONT node list
	
		// Create this variable to cut down the thickness of the code below (easier to read)
		CVector3 vCtr = vCenter;

		// Go through every object in the current partition of the world
		for(int i = 0; i < pWorld->numOfObjects; i++)
		{
			// Store a point to the current object
			t3DObject *pObject = &(pWorld->pObject[i]);

			// Now, we have a face list for each object, for every child node.
			// We need to then check every triangle in this current object
			// to see if it's in any of the child nodes dimensions.  We store a "true" in
			// the face list index to tell us if that's the case.  This is then used
			// in CreateNewNode() to create a new partition of the world for that child node.

			// Resize the current face list to be the size of this object's face count
			pList1[i].pFaceList.resize(pObject->numOfFaces);
			pList2[i].pFaceList.resize(pObject->numOfFaces);
			pList3[i].pFaceList.resize(pObject->numOfFaces);
			pList4[i].pFaceList.resize(pObject->numOfFaces);
			pList5[i].pFaceList.resize(pObject->numOfFaces);
			pList6[i].pFaceList.resize(pObject->numOfFaces);
			pList7[i].pFaceList.resize(pObject->numOfFaces);
			pList8[i].pFaceList.resize(pObject->numOfFaces);

			// Go through all the triangles for this object
			for(int j = 0; j < pObject->numOfFaces; j++)
			{
				// Check every vertice in the current triangle to see if it's inside a child node
				for(int whichVertex = 0; whichVertex < 3; whichVertex++)
				{
					// Store the current vertex to be checked against all the child nodes
					CVector3 vPoint = pObject->pVerts[pObject->pFaces[j].vertIndex[whichVertex]];

					// Check if the point lies within the TOP LEFT FRONT node
					if( (vPoint.x <= vCtr.x) && (vPoint.y >= vCtr.y) && (vPoint.z >= vCtr.z) ) 
						pList1[i].pFaceList[j] = true;

					// Check if the point lies within the TOP LEFT BACK node
					if( (vPoint.x <= vCtr.x) && (vPoint.y >= vCtr.y) && (vPoint.z <= vCtr.z) ) 
						pList2[i].pFaceList[j] = true;

					// Check if the point lies within the TOP RIGHT BACK node
					if( (vPoint.x >= vCtr.x) && (vPoint.y >= vCtr.y) && (vPoint.z <= vCtr.z) ) 
						pList3[i].pFaceList[j] = true;

					// Check if the point lies within the TOP RIGHT FRONT node
					if( (vPoint.x >= vCtr.x) && (vPoint.y >= vCtr.y) && (vPoint.z >= vCtr.z) ) 
						pList4[i].pFaceList[j] = true;

					// Check if the point lies within the BOTTOM LEFT FRONT node
					if( (vPoint.x <= vCtr.x) && (vPoint.y <= vCtr.y) && (vPoint.z >= vCtr.z) ) 
						pList5[i].pFaceList[j] = true;

					// Check if the point lies within the BOTTOM LEFT BACK node
					if( (vPoint.x <= vCtr.x) && (vPoint.y <= vCtr.y) && (vPoint.z <= vCtr.z) ) 
						pList6[i].pFaceList[j] = true;

					// Check if the point lies within the BOTTOM RIGHT BACK node
					if( (vPoint.x >= vCtr.x) && (vPoint.y <= vCtr.y) && (vPoint.z <= vCtr.z) ) 
						pList7[i].pFaceList[j] = true;

					// Check if the point lines within the BOTTOM RIGHT FRONT node
					if( (vPoint.x >= vCtr.x) && (vPoint.y <= vCtr.y) && (vPoint.z >= vCtr.z) ) 
						pList8[i].pFaceList[j] = true;
				}
			}	

			// Here we initialize the face count for each list that holds how many triangles
			// were found for each of the 8 subdivided nodes.
			pList1[i].totalFaceCount = 0;		pList2[i].totalFaceCount = 0;
			pList3[i].totalFaceCount = 0;		pList4[i].totalFaceCount = 0;
			pList5[i].totalFaceCount = 0;		pList6[i].totalFaceCount = 0;
			pList7[i].totalFaceCount = 0;		pList8[i].totalFaceCount = 0;
		}

		// Here we create a variable for each list that holds how many triangles
		// were found for each of the 8 subdivided nodes.
		int triCount1 = 0;	int triCount2 = 0;	int triCount3 = 0;	int triCount4 = 0;
		int triCount5 = 0;	int triCount6 = 0;	int triCount7 = 0;	int triCount8 = 0;
			
		// Go through all of the objects of this current partition
		for(i = 0; i < pWorld->numOfObjects; i++)
		{
			// Go through all of the current objects triangles
			for(int j = 0; j < pWorld->pObject[i].numOfFaces; j++)
			{
				// Increase the triangle count for each node that has a "true" for the index i.
				// In other words, if the current triangle is in a child node, add 1 to the count.
				// We need to store the total triangle count for each object, but also
				// the total for the whole child node.  That is why we increase 2 variables.
				if(pList1[i].pFaceList[j])	{ pList1[i].totalFaceCount++; triCount1++; }
				if(pList2[i].pFaceList[j])	{ pList2[i].totalFaceCount++; triCount2++; }
				if(pList3[i].pFaceList[j])	{ pList3[i].totalFaceCount++; triCount3++; }
				if(pList4[i].pFaceList[j])	{ pList4[i].totalFaceCount++; triCount4++; }
				if(pList5[i].pFaceList[j])	{ pList5[i].totalFaceCount++; triCount5++; }
				if(pList6[i].pFaceList[j])	{ pList6[i].totalFaceCount++; triCount6++; }
				if(pList7[i].pFaceList[j])	{ pList7[i].totalFaceCount++; triCount7++; }
				if(pList8[i].pFaceList[j])	{ pList8[i].totalFaceCount++; triCount8++; }
			}
		}

		// Next we do the dirty work.  We need to set up the new nodes with the triangles
		// that are assigned to each node, along with the new center point of the node.
		// Through recursion we subdivide this node into 8 more potential nodes.

		// Create the subdivided nodes if necessary and then recurse through them.
		// The information passed into CreateNewNode() are essential for creating the
		// new nodes.  We pass the 8 ID's in so it knows how to calculate it's new center.
		CreateNewNode(pWorld, pList1, triCount1, vCenter, width, TOP_LEFT_FRONT);
		CreateNewNode(pWorld, pList2, triCount2, vCenter, width, TOP_LEFT_BACK);
		CreateNewNode(pWorld, pList3, triCount3, vCenter, width, TOP_RIGHT_BACK);
		CreateNewNode(pWorld, pList4, triCount4, vCenter, width, TOP_RIGHT_FRONT);
		CreateNewNode(pWorld, pList5, triCount5, vCenter, width, BOTTOM_LEFT_FRONT);
		CreateNewNode(pWorld, pList6, triCount6, vCenter, width, BOTTOM_LEFT_BACK);
		CreateNewNode(pWorld, pList7, triCount7, vCenter, width, BOTTOM_RIGHT_BACK);
		CreateNewNode(pWorld, pList8, triCount8, vCenter, width, BOTTOM_RIGHT_FRONT);
	}
	else
	{
		// If we get here we must either be subdivided past our max level, or our triangle
		// count went below the minimum amount of triangles so we need to store them.
		
		// We pass in the current partition of world data to be assigned to this end node
		AssignTrianglesToNode(pWorld, numberOfTriangles);
	}

/////// * /////////// * /////////// * NEW * /////// * /////////// * /////////// *

}