void COctree::CreateNewNode(CVector3 *pVertices, vector<bool> pList, int numberOfVerts, CVector3 vCenter, float width, int triangleCount, int nodeID) { // This function helps us set up the new node that is being created. We only // want to create a new node if it found triangles in it's area. If there were // no triangle found in this node's cube, then we ignore it and don't create a node. // Check if the first node found some triangles in it if(triangleCount) { // Allocate memory for the triangles found in this node (tri's * 3 for vertices) CVector3 *pNodeVertices = new CVector3 [triangleCount * 3]; // Create an counter to count the current index of the new node vertices int index = 0; // Go through all the vertices and assign the vertices to the node's list for(int i = 0; i < numberOfVerts; i++) { // If this current triangle is in the node, assign it's vertices to it if(pList[i / 3]) { pNodeVertices[index] = pVertices[i]; index++; } } // Now comes the initialization of the node. First we allocate memory for // our node and then get it's center point. Depending on the nodeID, // GetNewNodeCenter() knows which center point to pass back (TOP_LEFT_FRONT, etc..) // Allocate a new node for this octree m_pOctreeNodes[nodeID] = new COctree; // Get the new node's center point depending on the nodexIndex (which of the 8 subdivided cubes). CVector3 vNodeCenter = GetNewNodeCenter(vCenter, width, nodeID); // Below, before and after we recurse further down into the tree, we keep track // of the level of subdivision that we are in. This way we can restrict it. // Increase the current level of subdivision g_CurrentSubdivision++; // Recurse through this node and subdivide it if necessary m_pOctreeNodes[nodeID]->CreateNode(pNodeVertices, triangleCount * 3, vNodeCenter, width / 2); // Decrease the current level of subdivision g_CurrentSubdivision--; // Free the allocated vertices for the triangles found in this node delete [] pNodeVertices; } }
void COctree::CreateNewNode(t3DModel *pWorld, vector<tFaceList> pList, int triangleCount, CVector3 vCenter, float width, int nodeID) { // This function is used as our helper function to partition the world data // to pass into the subdivided nodes. The same things go on as in the previous // tutorials, but it's dealing with more than just vertices. We are given // the world data that needs to be partitioned, the list of faces that are in // the new node about to be created, the triangle count, the parent node's center // and width, along with the enum ID that tells us which new node is being created. // // The tFaceList structure stores a vector of booleans, which tell us if that face // index is in our end node (true) or not (false). It also contains a integer // to tell us how many of those faces (triangles) are "true", or in other words, // are in our node that is being created. // Check if the first node found some triangles in it, if not we don't continue if(!triangleCount) return; // Here we create the temporary partitioned data model, which will contain // all the objects and triangles in this end node. t3DModel *pTempWorld = new t3DModel; // Intialize the temp model data and assign the object count to it memset(pTempWorld, 0, sizeof(t3DModel)); pTempWorld->numOfObjects = pWorld->numOfObjects; // Go through all of the objects in the current partition passed in for(int i = 0; i < pWorld->numOfObjects; i++) { // Get a pointer to the current object to avoid ugly code t3DObject *pObject = &(pWorld->pObject[i]); // Create a new object, initialize it, then add it to our temp partition t3DObject newObject; memset(&newObject, 0, sizeof(t3DObject)); pTempWorld->pObject.push_back(newObject); // Assign the new node's face count, material ID, texture boolean and // vertices to the new object. Notice that it's not that pObject's face // count, but the pList's. Also, we are just assigning the pointer to the // vertices, not copying them. pTempWorld->pObject[i].numOfFaces = pList[i].totalFaceCount; pTempWorld->pObject[i].materialID = pObject->materialID; pTempWorld->pObject[i].bHasTexture = pObject->bHasTexture; pTempWorld->pObject[i].pVerts = pObject->pVerts; // Allocate memory for the new face list pTempWorld->pObject[i].pFaces = new tFace [pTempWorld->pObject[i].numOfFaces]; // Create a counter to count the current index of the new node vertices int index = 0; // Go through all of the current object's faces and only take the ones in this new node for(int j = 0; j < pObject->numOfFaces; j++) { // If this current triangle is in the node, assign it's index to our new face list if(pList[i].pFaceList[j]) { pTempWorld->pObject[i].pFaces[index] = pObject->pFaces[j]; index++; } } } /////// * /////////// * /////////// * NEW * /////// * /////////// * /////////// * // Now comes the initialization of the node. First we allocate memory for // our node and then get it's center point. Depending on the nodeID, // GetNewNodeCenter() knows which center point to pass back (TOP_LEFT_FRONT, etc..) // Allocate a new node for this octree m_pOctreeNodes[nodeID] = new COctree; // Get the new node's center point depending on the nodexIndex (which of the 8 subdivided cubes). CVector3 vNodeCenter = GetNewNodeCenter(vCenter, width, nodeID); // Below, before and after we recurse further down into the tree, we keep track // of the level of subdivision that we are in. This way we can restrict it. // Increase the current level of subdivision g_CurrentSubdivision++; /////// * /////////// * /////////// * NEW * /////// * /////////// * /////////// * // This chance is just that we pass in the temp partitioned world for this node, // instead of passing in just straight vertices. // Recurse through this node and subdivide it if necessary m_pOctreeNodes[nodeID]->CreateNode(pTempWorld, triangleCount, vNodeCenter, width / 2); /////// * /////////// * /////////// * NEW * /////// * /////////// * /////////// * // Decrease the current level of subdivision g_CurrentSubdivision--; /////// * /////////// * /////////// * NEW * /////// * /////////// * /////////// * // To free the temporary partition, we just go through all of it's objects and // free the faces. The rest of the dynamic data was just being pointed too and // does not to be deleted. Finally, we delete the allocated pTempWorld. // Go through all of the objects in our temporary partition for(i = 0; i < pWorld->numOfObjects; i++) { // If there are faces allocated for this object, delete them if(pTempWorld->pObject[i].pFaces) delete [] pTempWorld->pObject[i].pFaces; } // Delete the allocated partition delete pTempWorld; /////// * /////////// * /////////// * NEW * /////// * /////////// * /////////// * }