int QuadTree::CountTriangles(float positionX, float positionZ, float width) { int count, i; bool result; // Initialize the count to zero. count = 0; // Go through all the triangles in the entire mesh and check which ones should be inside this node. for(i=0; i<m_triangleCount; i++) { // If the triangle is inside the node then increment the count by one. result = IsTriangleContained(i, positionX, positionZ, width); if(result == true) { count++; } } return count; }
void QuadTreeClass::CreateTreeNode(NodeType* node, float positionX, float positionZ, float width, ID3D10Device* device) { int numTriangles, i, count, vertexCount, index, vertexIndex; float offsetX, offsetZ; VertexType* vertices; unsigned long* indices; bool result; D3D10_BUFFER_DESC vertexBufferDesc, indexBufferDesc; D3D10_SUBRESOURCE_DATA vertexData, indexData; // Store the node position and size. node->positionX = positionX; node->positionZ = positionZ; node->width = width; // Initialize the triangle count to zero for the node. node->triangleCount = 0; // Initialize the vertex and index buffer to null. node->vertexBuffer = 0; node->indexBuffer = 0; // Initialize the vertex array to null. node->vertexArray = 0; // Initialize the children nodes of this node to null. node->nodes[0] = 0; node->nodes[1] = 0; node->nodes[2] = 0; node->nodes[3] = 0; // Count the number of triangles that are inside this node. numTriangles = CountTriangles(positionX, positionZ, width); // Case 1: If there are no triangles in this node then return as it is empty and requires no processing. if (numTriangles == 0) { return; } // Case 2: If there are too many triangles in this node then split it into four equal sized smaller tree nodes. if (numTriangles > MAX_TRIANGLES) { for (i = 0; i<4; i++) { // Calculate the position offsets for the new child node. offsetX = (((i % 2) < 1) ? -1.0f : 1.0f) * (width / 4.0f); offsetZ = (((i % 4) < 2) ? -1.0f : 1.0f) * (width / 4.0f); // See if there are any triangles in the new node. count = CountTriangles((positionX + offsetX), (positionZ + offsetZ), (width / 2.0f)); if (count > 0) { // If there are triangles inside where this new node would be then create the child node. node->nodes[i] = new NodeType; // Extend the tree starting from this new child node now. CreateTreeNode(node->nodes[i], (positionX + offsetX), (positionZ + offsetZ), (width / 2.0f), device); } } return; } // Case 3: If this node is not empty and the triangle count for it is less than the max then // this node is at the bottom of the tree so create the list of triangles to store in it. node->triangleCount = numTriangles; // Calculate the number of vertices. vertexCount = numTriangles * 3; // Create the vertex array. vertices = new VertexType[vertexCount]; // Create the index array. indices = new unsigned long[vertexCount]; // Create the vertex array. node->vertexArray = new VectorType[vertexCount]; // Initialize the index for this new vertex and index array. index = 0; // Go through all the triangles in the vertex list. for (i = 0; i<m_triangleCount; i++) { // If the triangle is inside this node then add it to the vertex array. result = IsTriangleContained(i, positionX, positionZ, width); if (result == true) { // Calculate the index into the terrain vertex list. vertexIndex = i * 3; // Get the three vertices of this triangle from the vertex list. vertices[index].position = m_vertexList[vertexIndex].position; vertices[index].texture = m_vertexList[vertexIndex].texture; vertices[index].normal = m_vertexList[vertexIndex].normal; indices[index] = index; // Also store the vertex position information in the node vertex array. node->vertexArray[index].x = m_vertexList[vertexIndex].position.x; node->vertexArray[index].y = m_vertexList[vertexIndex].position.y; node->vertexArray[index].z = m_vertexList[vertexIndex].position.z; // Increment the indexes. index++; vertexIndex++; // Do the same for the next point. vertices[index].position = m_vertexList[vertexIndex].position; vertices[index].texture = m_vertexList[vertexIndex].texture; vertices[index].normal = m_vertexList[vertexIndex].normal; indices[index] = index; node->vertexArray[index].x = m_vertexList[vertexIndex].position.x; node->vertexArray[index].y = m_vertexList[vertexIndex].position.y; node->vertexArray[index].z = m_vertexList[vertexIndex].position.z; index++; vertexIndex++; // Do the same for the next point also. vertices[index].position = m_vertexList[vertexIndex].position; vertices[index].texture = m_vertexList[vertexIndex].texture; vertices[index].normal = m_vertexList[vertexIndex].normal; indices[index] = index; node->vertexArray[index].x = m_vertexList[vertexIndex].position.x; node->vertexArray[index].y = m_vertexList[vertexIndex].position.y; node->vertexArray[index].z = m_vertexList[vertexIndex].position.z; index++; } } // Set up the description of the vertex buffer. vertexBufferDesc.Usage = D3D10_USAGE_DEFAULT; vertexBufferDesc.ByteWidth = sizeof(VertexType) * vertexCount; vertexBufferDesc.BindFlags = D3D10_BIND_VERTEX_BUFFER; vertexBufferDesc.CPUAccessFlags = 0; vertexBufferDesc.MiscFlags = 0; //vertexBufferDesc.StructureByteStride = 0; // Give the subresource structure a pointer to the vertex data. vertexData.pSysMem = vertices; vertexData.SysMemPitch = 0; vertexData.SysMemSlicePitch = 0; // Now finally create the vertex buffer. device->CreateBuffer(&vertexBufferDesc, &vertexData, &node->vertexBuffer); // Set up the description of the index buffer. indexBufferDesc.Usage = D3D10_USAGE_DEFAULT; indexBufferDesc.ByteWidth = sizeof(unsigned long) * vertexCount; indexBufferDesc.BindFlags = D3D10_BIND_INDEX_BUFFER; indexBufferDesc.CPUAccessFlags = 0; indexBufferDesc.MiscFlags = 0; //indexBufferDesc.StructureByteStride = 0; // Give the subresource structure a pointer to the index data. indexData.pSysMem = indices; indexData.SysMemPitch = 0; indexData.SysMemSlicePitch = 0; // Create the index buffer. device->CreateBuffer(&indexBufferDesc, &indexData, &node->indexBuffer); // Release the vertex and index arrays now that the data is stored in the buffers in the node. delete[] vertices; vertices = 0; delete[] indices; indices = 0; return; }