//----------------------------------------------------------------------------- // Recursively checks the scene's leaves against the given object. //----------------------------------------------------------------------------- void SceneManager::RecursiveBuildCollisionArray( SceneLeaf *leaf, SceneObject *object ) { // Only process the leaves if the object's bounding box intesects with it. // NOTE: Test both ways to ensure smaller nodes are accepted for intersection. if( !IsBoxInBox( object->GetBoundingBox()->min, object->GetBoundingBox()->max, leaf->GetBoundingBox()->min, leaf->GetBoundingBox()->max ) && !IsBoxInBox( leaf->GetBoundingBox()->min, leaf->GetBoundingBox()->max, object->GetBoundingBox()->min, object->GetBoundingBox()->max ) ) return; // Recursively build collision array from each of the leaf's children. for( char c = 0; c < 8; c++ ) if( leaf->children[c] != NULL ) RecursiveBuildCollisionArray( leaf->children[c], object ); // Add the faces in this leaf to the array of possible collision faces. for( unsigned long f = 0; f < leaf->totalFaces; f++ ) { if( m_totalCollisionFaces == m_totalFaces ) return; m_collisionFaces[m_totalCollisionFaces] = &m_faces[leaf->faces[f]]; m_totalCollisionFaces++; } }
//----------------------------------------------------------------------------- // Recursively builds the scene. //----------------------------------------------------------------------------- void SceneManager::RecursiveSceneBuild( SceneLeaf *leaf, D3DXVECTOR3 translation, float halfSize ) { // Build a bounding volume around this leaf. leaf->SetBoundingBox( D3DXVECTOR3( translation.x - halfSize, translation.y - halfSize, translation.z - halfSize ), D3DXVECTOR3( translation.x + halfSize, translation.y + halfSize, translation.z + halfSize ) ); leaf->SetBoundingSphere( translation, (float)sqrt( halfSize * halfSize + halfSize * halfSize + halfSize * halfSize ) ); // Count the number of face in this leaf. unsigned long totalFaces = 0; for( unsigned long f = 0; f < m_totalFaces; f++ ) if( IsFaceInBox( &m_vertices[m_faces[f].vertex0], &m_vertices[m_faces[f].vertex1], &m_vertices[m_faces[f].vertex2], leaf->GetBoundingBox()->min, leaf->GetBoundingBox()->max ) == true ) totalFaces++; // Only divide the leaf up if it is too big and contains too many faces. if( halfSize > m_maxHalfSize && totalFaces > m_maxFaces ) { // Go through all the child leaves. for( char c = 0; c < 8; c++ ) { D3DXVECTOR3 newTranslation, newMin, newMax; float newHalfSize = halfSize / 2.0f; float mod; // Calculate the translation of the new leaf on the x axis. mod = 1.0f; if( c % 2 < 1 ) mod = -1.0f; newTranslation.x = translation.x + newHalfSize * mod; // Calculate the translation of the new leaf on the y axis. mod = 1.0f; if( c % 4 < 2 ) mod = -1.0f; newTranslation.y = translation.y + newHalfSize * mod; // Calculate the translation of the new leaf on the z axis. mod = 1.0f; if( c % 8 < 4 ) mod = -1.0f; newTranslation.z = translation.z + newHalfSize * mod; // Calculate the bounding box around the new leaf. newMin = D3DXVECTOR3( newTranslation.x - newHalfSize, newTranslation.y - newHalfSize, newTranslation.z - newHalfSize ); newMax = D3DXVECTOR3( newTranslation.x + newHalfSize, newTranslation.y + newHalfSize, newTranslation.z + newHalfSize ); // Check if the new scene leaf will have at least one face in it. for( f = 0; f < m_totalFaces; f++ ) { if( IsFaceInBox( &m_vertices[m_faces[f].vertex0], &m_vertices[m_faces[f].vertex1], &m_vertices[m_faces[f].vertex2], newMin, newMax ) == true ) { // A face has been found that is inside the new child scene // leaf, so create the scene leaf. Then recurse through the // scene leaf's branch of the scene hierarchy. leaf->children[c] = new SceneLeaf; RecursiveSceneBuild( leaf->children[c], newTranslation, halfSize / 2.0f ); break; } } } return; } // Create the leaf's array of face indices. leaf->totalFaces = totalFaces; leaf->faces = new unsigned long[totalFaces]; // If any face is contained in the leaf's bounding box, then store // the index of the face in the leaf's face index array. totalFaces = 0; for( f = 0; f < m_totalFaces; f++ ) if( IsFaceInBox( &m_vertices[m_faces[f].vertex0], &m_vertices[m_faces[f].vertex1], &m_vertices[m_faces[f].vertex2], leaf->GetBoundingBox()->min, leaf->GetBoundingBox()->max ) == true ) leaf->faces[totalFaces++] = f; // Store pointers to any occluding objects in the leaf. m_occludingObjects->Iterate( true ); while( m_occludingObjects->Iterate() ) if( IsBoxInBox( m_occludingObjects->GetCurrent()->GetBoundingBox()->min, m_occludingObjects->GetCurrent()->GetBoundingBox()->max, leaf->GetBoundingBox()->min, leaf->GetBoundingBox()->max ) == true ) leaf->occluders->Add( m_occludingObjects->GetCurrent() ); }