Jelajahi Sumber

Store the indices of a physics convex hull in preparation to using it for navigation data.
Generalized the geometry collection list in NavigationMesh to hold any components.

Lasse Öörni 12 tahun lalu
induk
melakukan
56a7f36a0c

+ 112 - 104
Engine/Navigation/NavigationMesh.cpp

@@ -295,7 +295,7 @@ bool NavigationMesh::Build()
     if (!node_->GetWorldScale().Equals(Vector3::ONE))
         LOGWARNING("Navigation mesh root node has scaling. Agent parameters may not work as intended");
     
-    Vector<GeometryInfo> geometryList;
+    Vector<NavigationGeometryInfo> geometryList;
     CollectGeometries(geometryList);
     
     if (geometryList.Empty())
@@ -307,31 +307,31 @@ bool NavigationMesh::Build()
     
     {
         PROFILE(BuildNavigationMesh);
-        
-        // Calculate number of tiles
-        int gridW = 0, gridH = 0;
-        float tileEdgeLength = (float)tileSize_ * cellSize_;
-        rcCalcGridSize(&boundingBox_.min_.x_, &boundingBox_.max_.x_, cellSize_, &gridW, &gridH);
-        numTilesX_ = (gridW + tileSize_ - 1) / tileSize_;
-        numTilesZ_ = (gridH + tileSize_ - 1) / tileSize_;
-        
-        // Calculate max. number of tiles and polygons, 22 bits available to identify both tile & polygon within tile
-        unsigned maxTiles = NextPowerOfTwo(numTilesX_ * numTilesZ_);
-        unsigned tileBits = 0;
-        unsigned temp = maxTiles;
-        while (temp > 1)
-        {
-            temp >>= 1;
-            ++tileBits;
-        }
-        
-        unsigned maxPolys = 1 << (22 - tileBits);
-        
-        dtNavMeshParams params;
-        rcVcopy(params.orig, &boundingBox_.min_.x_);
-        params.tileWidth = tileEdgeLength;
-        params.tileHeight = tileEdgeLength;
-        params.maxTiles = maxTiles;
+        
+        // Calculate number of tiles
+        int gridW = 0, gridH = 0;
+        float tileEdgeLength = (float)tileSize_ * cellSize_;
+        rcCalcGridSize(&boundingBox_.min_.x_, &boundingBox_.max_.x_, cellSize_, &gridW, &gridH);
+        numTilesX_ = (gridW + tileSize_ - 1) / tileSize_;
+        numTilesZ_ = (gridH + tileSize_ - 1) / tileSize_;
+        
+        // Calculate max. number of tiles and polygons, 22 bits available to identify both tile & polygon within tile
+        unsigned maxTiles = NextPowerOfTwo(numTilesX_ * numTilesZ_);
+        unsigned tileBits = 0;
+        unsigned temp = maxTiles;
+        while (temp > 1)
+        {
+            temp >>= 1;
+            ++tileBits;
+        }
+        
+        unsigned maxPolys = 1 << (22 - tileBits);
+        
+        dtNavMeshParams params;
+        rcVcopy(params.orig, &boundingBox_.min_.x_);
+        params.tileWidth = tileEdgeLength;
+        params.tileHeight = tileEdgeLength;
+        params.maxTiles = maxTiles;
         params.maxPolys = maxPolys;
         
         navMesh_ = dtAllocNavMesh();
@@ -347,12 +347,12 @@ bool NavigationMesh::Build()
             ReleaseNavigationMesh();
             return false;
         }
-        
-        // Build each tile
-        unsigned numTiles = 0;
-        
-        for (int z = 0; z < numTilesZ_; ++z)
-        {
+        
+        // Build each tile
+        unsigned numTiles = 0;
+        
+        for (int z = 0; z < numTilesZ_; ++z)
+        {
             for (int x = 0; x < numTilesX_; ++x)
             {
                 if (BuildTile(geometryList, x, z))
@@ -386,7 +386,7 @@ bool NavigationMesh::Build(const BoundingBox& boundingBox)
     
     float tileEdgeLength = (float)tileSize_ * cellSize_;
     
-    Vector<GeometryInfo> geometryList;
+    Vector<NavigationGeometryInfo> geometryList;
     CollectGeometries(geometryList);
     
     int sx = Clamp((int)((localSpaceBox.min_.x_ - boundingBox_.min_.x_) / tileEdgeLength), 0, numTilesX_ - 1);
@@ -479,11 +479,11 @@ void NavigationMesh::SetNavigationDataAttr(PODVector<unsigned char> data)
     numTilesX_ = buffer.ReadInt();
     numTilesZ_ = buffer.ReadInt();
 
-    dtNavMeshParams params;
-    rcVcopy(params.orig, &boundingBox_.min_.x_);
-    params.tileWidth = buffer.ReadFloat();
-    params.tileHeight = buffer.ReadFloat();
-    params.maxTiles = buffer.ReadInt();
+    dtNavMeshParams params;
+    rcVcopy(params.orig, &boundingBox_.min_.x_);
+    params.tileWidth = buffer.ReadFloat();
+    params.tileHeight = buffer.ReadFloat();
+    params.maxTiles = buffer.ReadInt();
     params.maxPolys = buffer.ReadInt();
     
     navMesh_ = dtAllocNavMesh();
@@ -568,7 +568,7 @@ PODVector<unsigned char> NavigationMesh::GetNavigationDataAttr() const
     return ret.GetBuffer();
 }
 
-void NavigationMesh::CollectGeometries(Vector<GeometryInfo>& geometryList)
+void NavigationMesh::CollectGeometries(Vector<NavigationGeometryInfo>& geometryList)
 {
     PROFILE(CollectNavigationGeometry);
     
@@ -585,7 +585,7 @@ void NavigationMesh::CollectGeometries(Vector<GeometryInfo>& geometryList)
     }
 }
 
-void NavigationMesh::CollectGeometries(Vector<GeometryInfo>& geometryList, Node* node, HashSet<Node*>& processedNodes, bool recursive)
+void NavigationMesh::CollectGeometries(Vector<NavigationGeometryInfo>& geometryList, Node* node, HashSet<Node*>& processedNodes, bool recursive)
 {
     // Make sure nodes are not included twice
     if (processedNodes.Contains(node))
@@ -604,24 +604,20 @@ void NavigationMesh::CollectGeometries(Vector<GeometryInfo>& geometryList, Node*
         if (!drawable->IsEnabledEffective())
             continue;
         
-        unsigned numGeometries = drawable->GetBatches().Size();
-        unsigned lodLevel;
+        NavigationGeometryInfo info;
+        
         if (drawable->GetType() == StaticModel::GetTypeStatic())
-            lodLevel = static_cast<StaticModel*>(drawable)->GetOcclusionLodLevel();
+            info.lodLevel_ = static_cast<StaticModel*>(drawable)->GetOcclusionLodLevel();
         else if (drawable->GetType() == TerrainPatch::GetTypeStatic())
-            lodLevel = 0;
+            info.lodLevel_ = 0;
         else
             continue;
         
-        GeometryInfo info;
+        info.component_ = drawable;
         info.transform_ = inverseTransform * node->GetWorldTransform();
         info.boundingBox_ = drawable->GetWorldBoundingBox().Transformed(inverseTransform);
         
-        for (unsigned j = 0; j < numGeometries; ++j)
-        {
-            info.geometry_ = drawable->GetLodGeometry(j, lodLevel);
-            geometryList.Push(info);
-        }
+        geometryList.Push(info);
     }
     
     if (recursive)
@@ -632,69 +628,81 @@ void NavigationMesh::CollectGeometries(Vector<GeometryInfo>& geometryList, Node*
     }
 }
 
-void NavigationMesh::GetTileGeometry(NavigationBuildData& build, Vector<GeometryInfo>& geometryList, BoundingBox& box)
+void NavigationMesh::GetTileGeometry(NavigationBuildData& build, Vector<NavigationGeometryInfo>& geometryList, BoundingBox& box)
 {
     for (unsigned i = 0; i < geometryList.Size(); ++i)
     {
         if (box.IsInsideFast(geometryList[i].boundingBox_) != OUTSIDE)
         {
-            Geometry* geometry = geometryList[i].geometry_;
-            Matrix3x4& transform = geometryList[i].transform_;
-            
-            const unsigned char* vertexData;
-            const unsigned char* indexData;
-            unsigned vertexSize;
-            unsigned indexSize;
-            unsigned elementMask;
+            const Matrix3x4& transform = geometryList[i].transform_;
+            Drawable* drawable = dynamic_cast<Drawable*>(geometryList[i].component_);
             
-            geometry->GetRawData(vertexData, vertexSize, indexData, indexSize, elementMask);
-            if (!vertexData || !indexData || (elementMask & MASK_POSITION) == 0)
-                continue;
-            
-            unsigned srcIndexStart = geometry->GetIndexStart();
-            unsigned srcIndexCount = geometry->GetIndexCount();
-            unsigned srcVertexStart = geometry->GetVertexStart();
-            unsigned srcVertexCount = geometry->GetVertexCount();
-            
-            if (!srcIndexCount)
-                continue;
-            
-            unsigned destVertexStart = build.vertices_.Size();
-            
-            for (unsigned j = srcVertexStart; j < srcVertexStart + srcVertexCount; ++j)
+            if (drawable)
             {
-                Vector3 vertex = transform * *((const Vector3*)(&vertexData[j * vertexSize]));
-                build.vertices_.Push(vertex);
-            }
-            
-            // Copy remapped indices
-            if (indexSize == sizeof(unsigned short))
-            {
-                const unsigned short* indices = ((const unsigned short*)indexData) + srcIndexStart;
-                const unsigned short* indicesEnd = indices + srcIndexCount;
+                const Vector<SourceBatch>& batches = drawable->GetBatches();
                 
-                while (indices < indicesEnd)
+                for (unsigned j = 0; j < batches.Size(); ++j)
                 {
-                    build.indices_.Push(*indices - srcVertexStart + destVertexStart);
-                    ++indices;
-                }
-            }
-            else
-            {
-                const unsigned* indices = ((const unsigned*)indexData) + srcIndexStart;
-                const unsigned* indicesEnd = indices + srcIndexCount;
+                    Geometry* geometry = drawable->GetLodGeometry(j, geometryList[i].lodLevel_);
+                    if (!geometry)
+                        continue;
                 
-                while (indices < indicesEnd)
-                {
-                    build.indices_.Push(*indices - srcVertexStart + destVertexStart);
-                    ++indices;
+                    const unsigned char* vertexData;
+                    const unsigned char* indexData;
+                    unsigned vertexSize;
+                    unsigned indexSize;
+                    unsigned elementMask;
+                    
+                    geometry->GetRawData(vertexData, vertexSize, indexData, indexSize, elementMask);
+                    if (!vertexData || !indexData || (elementMask & MASK_POSITION) == 0)
+                        continue;
+                    
+                    unsigned srcIndexStart = geometry->GetIndexStart();
+                    unsigned srcIndexCount = geometry->GetIndexCount();
+                    unsigned srcVertexStart = geometry->GetVertexStart();
+                    unsigned srcVertexCount = geometry->GetVertexCount();
+                    
+                    if (!srcIndexCount)
+                        continue;
+                    
+                    unsigned destVertexStart = build.vertices_.Size();
+                    
+                    for (unsigned k = srcVertexStart; k < srcVertexStart + srcVertexCount; ++k)
+                    {
+                        Vector3 vertex = transform * *((const Vector3*)(&vertexData[k * vertexSize]));
+                        build.vertices_.Push(vertex);
+                    }
+                    
+                    // Copy remapped indices
+                    if (indexSize == sizeof(unsigned short))
+                    {
+                        const unsigned short* indices = ((const unsigned short*)indexData) + srcIndexStart;
+                        const unsigned short* indicesEnd = indices + srcIndexCount;
+                        
+                        while (indices < indicesEnd)
+                        {
+                            build.indices_.Push(*indices - srcVertexStart + destVertexStart);
+                            ++indices;
+                        }
+                    }
+                    else
+                    {
+                        const unsigned* indices = ((const unsigned*)indexData) + srcIndexStart;
+                        const unsigned* indicesEnd = indices + srcIndexCount;
+                        
+                        while (indices < indicesEnd)
+                        {
+                            build.indices_.Push(*indices - srcVertexStart + destVertexStart);
+                            ++indices;
+                        }
+                    }
                 }
             }
         }
     }
 }
 
-bool NavigationMesh::BuildTile(Vector<GeometryInfo>& geometryList, int x, int z)
+bool NavigationMesh::BuildTile(Vector<NavigationGeometryInfo>& geometryList, int x, int z)
 {
     PROFILE(BuildNavigationMeshTile);
     
@@ -726,18 +734,18 @@ bool NavigationMesh::BuildTile(Vector<GeometryInfo>& geometryList, int x, int z)
     cfg.minRegionArea = (int)sqrtf(regionMinSize_);
     cfg.mergeRegionArea = (int)sqrtf(regionMergeSize_);
     cfg.maxVertsPerPoly = 6;
-    cfg.tileSize = tileSize_;
-    cfg.borderSize = cfg.walkableRadius + 3; // Add padding
-    cfg.width = cfg.tileSize + cfg.borderSize * 2;
+    cfg.tileSize = tileSize_;
+    cfg.borderSize = cfg.walkableRadius + 3; // Add padding
+    cfg.width = cfg.tileSize + cfg.borderSize * 2;
     cfg.height = cfg.tileSize + cfg.borderSize * 2;
     cfg.detailSampleDist = detailSampleDistance_ < 0.9f ? 0.0f : cellSize_ * detailSampleDistance_;
     cfg.detailSampleMaxError = cellHeight_ * detailSampleMaxError_;
     
     rcVcopy(cfg.bmin, &tileBoundingBox.min_.x_);
     rcVcopy(cfg.bmax, &tileBoundingBox.max_.x_);
-    cfg.bmin[0] -= cfg.borderSize * cfg.cs;
-    cfg.bmin[2] -= cfg.borderSize * cfg.cs;
-    cfg.bmax[0] += cfg.borderSize * cfg.cs;
+    cfg.bmin[0] -= cfg.borderSize * cfg.cs;
+    cfg.bmin[2] -= cfg.borderSize * cfg.cs;
+    cfg.bmax[0] += cfg.borderSize * cfg.cs;
     cfg.bmax[2] += cfg.borderSize * cfg.cs;
     
     BoundingBox expandedBox(*reinterpret_cast<Vector3*>(cfg.bmin), *reinterpret_cast<Vector3*>(cfg.bmax));
@@ -864,7 +872,7 @@ bool NavigationMesh::BuildTile(Vector<GeometryInfo>& geometryList, int x, int z)
     params.walkableHeight = agentHeight_;
     params.walkableRadius = agentRadius_;
     params.walkableClimb = agentMaxClimb_;
-    params.tileX = x;
+    params.tileX = x;
     params.tileY = z;
     rcVcopy(params.bmin, build.polyMesh_->bmin);
     rcVcopy(params.bmax, build.polyMesh_->bmax);

+ 10 - 8
Engine/Navigation/NavigationMesh.h

@@ -39,11 +39,13 @@ class Geometry;
 struct FindPathData;
 struct NavigationBuildData;
 
-/// Geometry with transform and bounds information.
-struct GeometryInfo
+/// Description of a navigation mesh geometry component, with transform and bounds information.
+struct NavigationGeometryInfo
 {
-    /// Geometry object.
-    Geometry* geometry_;
+    /// Component.
+    Component* component_;
+    /// Geometry LOD level if applicable.
+    unsigned lodLevel_;
     /// Transform relative to the navigation mesh root node.
     Matrix3x4 transform_;
     /// Bounding box relative to the navigation mesh root node.
@@ -141,13 +143,13 @@ public:
     
 private:
     /// Collect geometry from under Navigable components.
-    void CollectGeometries(Vector<GeometryInfo>& geometryList);
+    void CollectGeometries(Vector<NavigationGeometryInfo>& geometryList);
     /// Visit nodes and collect navigable geometry.
-    void CollectGeometries(Vector<GeometryInfo>& geometryList, Node* node, HashSet<Node*>& processedNodes, bool recursive);
+    void CollectGeometries(Vector<NavigationGeometryInfo>& geometryList, Node* node, HashSet<Node*>& processedNodes, bool recursive);
     /// Get geometry data within a bounding box.
-    void GetTileGeometry(NavigationBuildData& build, Vector<GeometryInfo>& geometryList, BoundingBox& box);
+    void GetTileGeometry(NavigationBuildData& build, Vector<NavigationGeometryInfo>& geometryList, BoundingBox& box);
     /// Build one tile of the navigation mesh. Return true if successful.
-    bool BuildTile(Vector<GeometryInfo>& geometryList, int x, int z);
+    bool BuildTile(Vector<NavigationGeometryInfo>& geometryList, int x, int z);
     /// Initialize navigation mesh query. Return true if successful.
     bool InitializeQuery();
     /// Release the navigation mesh and the query.

+ 6 - 1
Engine/Physics/CollisionShape.cpp

@@ -209,8 +209,13 @@ ConvexData::ConvexData(Model* model, unsigned lodLevel)
         
         vertexCount_ = result.mNumOutputVertices;
         vertexData_ = new Vector3[vertexCount_];
-        // Copy vertex data
+        
+        indexCount_ = result.mNumIndices;
+        indexData_ = new unsigned[indexCount_];
+        
+        // Copy vertex data & index data
         memcpy(vertexData_.Get(), result.mOutputVertices, vertexCount_ * sizeof(Vector3));
+        memcpy(indexData_.Get(), result.mIndices, indexCount_ * sizeof(unsigned));
         
         lib.ReleaseResult(result);
     }

+ 4 - 0
Engine/Physics/CollisionShape.h

@@ -88,6 +88,10 @@ struct ConvexData : public CollisionGeometryData
     SharedArrayPtr<Vector3> vertexData_;
     /// Number of vertices.
     unsigned vertexCount_;
+    /// Index data.
+    SharedArrayPtr<unsigned> indexData_;
+    /// Number of indices.
+    unsigned indexCount_;
 };
 
 /// Heightfield geometry data.