Browse Source

Added GetWorldBoundingBox() to CollisionShape.
Prefer physics geometry (trimesh, convex hull, box supported) when generating navigation mesh.

Lasse Öörni 12 years ago
parent
commit
606d374936

+ 1 - 0
Docs/ScriptAPI.dox

@@ -5195,6 +5195,7 @@ Properties:<br>
 - float margin
 - Model@ model
 - uint lodLevel
+- BoundingBox worldBoundingBox (readonly)
 
 
 RigidBody

+ 1 - 0
Engine/Engine/PhysicsAPI.cpp

@@ -93,6 +93,7 @@ static void RegisterCollisionShape(asIScriptEngine* engine)
     engine->RegisterObjectMethod("CollisionShape", "Model@+ get_model() const", asMETHOD(CollisionShape, GetModel), asCALL_THISCALL);
     engine->RegisterObjectMethod("CollisionShape", "void set_lodLevel(uint)", asMETHOD(CollisionShape, SetLodLevel), asCALL_THISCALL);
     engine->RegisterObjectMethod("CollisionShape", "uint get_lodLevel() const", asMETHOD(CollisionShape, GetLodLevel), asCALL_THISCALL);
+    engine->RegisterObjectMethod("CollisionShape", "BoundingBox get_worldBoundingBox() const", asMETHOD(CollisionShape, GetWorldBoundingBox), asCALL_THISCALL);
     
     // Register Variant GetPtr() for CollisionShape
     engine->RegisterObjectMethod("Variant", "CollisionShape@+ GetCollisionShape() const", asFUNCTION(GetVariantPtr<CollisionShape>), asCALL_CDECL_OBJLAST);

+ 1 - 1
Engine/Graphics/Drawable.h

@@ -162,7 +162,7 @@ public:
     /// Mark for update before octree reinsertion.
     void MarkForUpdate();
     
-    /// Return world bounding box.
+    /// Return world-space bounding box.
     const BoundingBox& GetWorldBoundingBox();
     /// Return drawable flags.
     unsigned char GetDrawableFlags() const { return drawableFlags_; }

+ 4 - 1
Engine/Graphics/Model.cpp

@@ -472,9 +472,12 @@ unsigned Model::GetNumGeometryLodLevels(unsigned index) const
 
 Geometry* Model::GetGeometry(unsigned index, unsigned lodLevel) const
 {
-    if (index >= geometries_.Size() || lodLevel >= geometries_[index].Size())
+    if (index >= geometries_.Size() || geometries_[index].Empty())
         return 0;
     
+    if (lodLevel >= geometries_[index].Size())
+        lodLevel = geometries_[index].Size() - 1;
+    
     return geometries_[index][lodLevel];
 }
 

+ 1 - 1
Engine/Graphics/Model.h

@@ -115,7 +115,7 @@ public:
     const Vector<Vector<SharedPtr<Geometry> > >& GetGeometries() const { return geometries_; }
     /// Return geometry center points.
     const PODVector<Vector3>& GetGeometryCenters() const { return geometryCenters_; }
-    /// Return geometry by index and LOD level.
+    /// Return geometry by index and LOD level. The LOD level is clamped if out of range.
     Geometry* GetGeometry(unsigned index, unsigned lodLevel) const;
     /// Return geometery bone mappings.
     const Vector<PODVector<unsigned> >& GetGeometryBoneMappings() const { return geometryBoneMappings_; }

+ 1 - 1
Engine/Graphics/Octree.h

@@ -72,7 +72,7 @@ public:
         }
     }
     
-    /// Return world bounding box.
+    /// Return world-space bounding box.
     const BoundingBox& GetWorldBoundingBox() const { return worldBoundingBox_; }
     /// Return bounding box used for fitting drawable objects.
     const BoundingBox& GetCullingBox() const { return cullingBox_; }

+ 172 - 71
Engine/Navigation/NavigationMesh.cpp

@@ -28,6 +28,7 @@
 #include "Geometry.h"
 #include "Log.h"
 #include "MemoryBuffer.h"
+#include "Model.h"
 #include "Navigable.h"
 #include "NavigationMesh.h"
 #include "Profiler.h"
@@ -594,30 +595,62 @@ void NavigationMesh::CollectGeometries(Vector<NavigationGeometryInfo>& geometryL
     
     Matrix3x4 inverseTransform = node_->GetWorldTransform().Inverse();
     
-    /// \todo Prefer physics geometry if available
-    PODVector<Drawable*> drawables;
-    node->GetDerivedComponents<Drawable>(drawables);
-    for (unsigned i = 0; i < drawables.Size(); ++i)
+    // Prefer compatible physics collision shapes (triangle mesh, convex hull, box) if found.
+    // Then fallback to visible geometry
+    PODVector<CollisionShape*> collisionShapes;
+    node->GetComponents<CollisionShape>(collisionShapes);
+    bool collisionShapeFound = false;
+    
+    for (unsigned i = 0; i < collisionShapes.Size(); ++i)
     {
-        /// \todo Evaluate whether should handle other types. Now StaticModel & TerrainPatch are supported, others skipped
-        Drawable* drawable = drawables[i];
-        if (!drawable->IsEnabledEffective())
-            continue;
-        
-        NavigationGeometryInfo info;
-        
-        if (drawable->GetType() == StaticModel::GetTypeStatic())
-            info.lodLevel_ = static_cast<StaticModel*>(drawable)->GetOcclusionLodLevel();
-        else if (drawable->GetType() == TerrainPatch::GetTypeStatic())
-            info.lodLevel_ = 0;
-        else
+        CollisionShape* shape = collisionShapes[i];
+        if (!shape->IsEnabledEffective())
             continue;
         
-        info.component_ = drawable;
-        info.transform_ = inverseTransform * node->GetWorldTransform();
-        info.boundingBox_ = drawable->GetWorldBoundingBox().Transformed(inverseTransform);
+        ShapeType type = shape->GetShapeType();
+        if ((type == SHAPE_BOX || type == SHAPE_TRIANGLEMESH || type == SHAPE_CONVEXHULL) && shape->GetCollisionShape())
+        {
+            NavigationGeometryInfo info;
+            
+            Matrix3x4 scaleMatrix(Matrix3x4::IDENTITY);
+            scaleMatrix.SetScale(shape->GetSize());
+            
+            info.component_ = shape;
+            info.transform_ = inverseTransform * node->GetWorldTransform() * scaleMatrix;
+            info.boundingBox_ = shape->GetWorldBoundingBox().Transformed(inverseTransform);
+            
+            geometryList.Push(info);
+            collisionShapeFound = true;
+        }
+    }
+    
+    if (!collisionShapeFound)
+    {
+        PODVector<Drawable*> drawables;
+        node->GetDerivedComponents<Drawable>(drawables);
         
-        geometryList.Push(info);
+        for (unsigned i = 0; i < drawables.Size(); ++i)
+        {
+            /// \todo Evaluate whether should handle other types. Now StaticModel & TerrainPatch are supported, others skipped
+            Drawable* drawable = drawables[i];
+            if (!drawable->IsEnabledEffective())
+                continue;
+            
+            NavigationGeometryInfo info;
+            
+            if (drawable->GetType() == StaticModel::GetTypeStatic())
+                info.lodLevel_ = static_cast<StaticModel*>(drawable)->GetOcclusionLodLevel();
+            else if (drawable->GetType() == TerrainPatch::GetTypeStatic())
+                info.lodLevel_ = 0;
+            else
+                continue;
+            
+            info.component_ = drawable;
+            info.transform_ = inverseTransform * node->GetWorldTransform();
+            info.boundingBox_ = drawable->GetWorldBoundingBox().Transformed(inverseTransform);
+            
+            geometryList.Push(info);
+        }
     }
     
     if (recursive)
@@ -635,69 +668,133 @@ void NavigationMesh::GetTileGeometry(NavigationBuildData& build, Vector<Navigati
         if (box.IsInsideFast(geometryList[i].boundingBox_) != OUTSIDE)
         {
             const Matrix3x4& transform = geometryList[i].transform_;
-            Drawable* drawable = dynamic_cast<Drawable*>(geometryList[i].component_);
             
-            if (drawable)
+            CollisionShape* shape = dynamic_cast<CollisionShape*>(geometryList[i].component_);
+            if (shape)
             {
-                const Vector<SourceBatch>& batches = drawable->GetBatches();
-                
-                for (unsigned j = 0; j < batches.Size(); ++j)
+                switch (shape->GetShapeType())
                 {
-                    Geometry* geometry = drawable->GetLodGeometry(j, geometryList[i].lodLevel_);
-                    if (!geometry)
-                        continue;
-                
-                    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)
+                case SHAPE_TRIANGLEMESH:
                     {
-                        Vector3 vertex = transform * *((const Vector3*)(&vertexData[k * vertexSize]));
-                        build.vertices_.Push(vertex);
+                        Model* model = shape->GetModel();
+                        if (!model)
+                            continue;
+                        
+                        unsigned lodLevel = shape->GetLodLevel();
+                        for (unsigned j = 0; j < model->GetNumGeometries(); ++j)
+                            AddTriMeshGeometry(build, model->GetGeometry(j, lodLevel), transform);
                     }
+                    break;
                     
-                    // Copy remapped indices
-                    if (indexSize == sizeof(unsigned short))
+                case SHAPE_CONVEXHULL:
                     {
-                        const unsigned short* indices = ((const unsigned short*)indexData) + srcIndexStart;
-                        const unsigned short* indicesEnd = indices + srcIndexCount;
+                        ConvexData* data = static_cast<ConvexData*>(shape->GetGeometryData());
+                        if (!data)
+                            continue;
+                        
+                        unsigned numVertices = data->vertexCount_;
+                        unsigned numIndices = data->indexCount_;
+                        unsigned destVertexStart = build.vertices_.Size();
+                        
+                        for (unsigned j = 0; j < numVertices; ++j)
+                            build.vertices_.Push(transform * data->vertexData_[j]);
                         
-                        while (indices < indicesEnd)
-                        {
-                            build.indices_.Push(*indices - srcVertexStart + destVertexStart);
-                            ++indices;
-                        }
+                        for (unsigned j = 0; j < numIndices; ++j)
+                            build.indices_.Push(data->indexData_[j] + destVertexStart);
                     }
-                    else
+                    break;
+                    
+                case SHAPE_BOX:
                     {
-                        const unsigned* indices = ((const unsigned*)indexData) + srcIndexStart;
-                        const unsigned* indicesEnd = indices + srcIndexCount;
+                        unsigned destVertexStart = build.vertices_.Size();
+                        
+                        build.vertices_.Push(transform * Vector3(-0.5f, 0.5f, -0.5f));
+                        build.vertices_.Push(transform * Vector3(0.5f, 0.5f, -0.5f));
+                        build.vertices_.Push(transform * Vector3(0.5f, -0.5f, -0.5f));
+                        build.vertices_.Push(transform * Vector3(-0.5f, -0.5f, -0.5f));
+                        build.vertices_.Push(transform * Vector3(-0.5f, 0.5f, 0.5f));
+                        build.vertices_.Push(transform * Vector3(0.5f, 0.5f, 0.5f));
+                        build.vertices_.Push(transform * Vector3(0.5f, -0.5f, 0.5f));
+                        build.vertices_.Push(transform * Vector3(-0.5f, -0.5f, 0.5f));
                         
-                        while (indices < indicesEnd)
-                        {
-                            build.indices_.Push(*indices - srcVertexStart + destVertexStart);
-                            ++indices;
-                        }
+                        const unsigned indices[] = {
+                            0, 1, 2, 0, 2, 3, 1, 5, 6, 1, 6, 2, 4, 5, 1, 4, 1, 0, 5, 4, 7, 5, 7, 6,
+                            4, 0, 3, 4, 3, 7, 1, 0, 4, 1, 4, 5
+                        };
+                        
+                        for (unsigned j = 0; j < 36; ++j)
+                            build.indices_.Push(indices[j] + destVertexStart);
                     }
+                    break;
                 }
             }
+            else
+            {
+                Drawable* drawable = dynamic_cast<Drawable*>(geometryList[i].component_);
+                if (drawable)
+                {
+                    const Vector<SourceBatch>& batches = drawable->GetBatches();
+                    
+                    for (unsigned j = 0; j < batches.Size(); ++j)
+                        AddTriMeshGeometry(build, drawable->GetLodGeometry(j, geometryList[i].lodLevel_), transform);
+                }
+            }
+        }
+    }
+}
+
+void NavigationMesh::AddTriMeshGeometry(NavigationBuildData& build, Geometry* geometry, const Matrix3x4& transform)
+{
+    if (!geometry)
+        return;
+    
+    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)
+        return;
+    
+    unsigned srcIndexStart = geometry->GetIndexStart();
+    unsigned srcIndexCount = geometry->GetIndexCount();
+    unsigned srcVertexStart = geometry->GetVertexStart();
+    unsigned srcVertexCount = geometry->GetVertexCount();
+    
+    if (!srcIndexCount)
+        return;
+    
+    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;
         }
     }
 }
@@ -706,6 +803,9 @@ bool NavigationMesh::BuildTile(Vector<NavigationGeometryInfo>& geometryList, int
 {
     PROFILE(BuildNavigationMeshTile);
     
+    // Remove previous tile (if any)
+    navMesh_->removeTile(navMesh_->getTileRefAt(x, z, 0), 0, 0);
+    
     float tileEdgeLength = (float)tileSize_ * cellSize_;
     
     BoundingBox tileBoundingBox(Vector3(
@@ -751,6 +851,9 @@ bool NavigationMesh::BuildTile(Vector<NavigationGeometryInfo>& geometryList, int
     BoundingBox expandedBox(*reinterpret_cast<Vector3*>(cfg.bmin), *reinterpret_cast<Vector3*>(cfg.bmax));
     GetTileGeometry(build, geometryList, expandedBox);
     
+    if (build.vertices_.Empty() || build.indices_.Empty())
+        return true; // Nothing to do
+    
     build.heightField_ = rcAllocHeightfield();
     if (!build.heightField_)
     {
@@ -886,8 +989,6 @@ bool NavigationMesh::BuildTile(Vector<NavigationGeometryInfo>& geometryList, int
         return false;
     }
     
-    // Remove previous tile (if any), then add new
-    navMesh_->removeTile(navMesh_->getTileRefAt(x, z, 0), 0, 0);
     if (dtStatusFailed(navMesh_->addTile(navData, navDataSize, DT_TILE_FREE_DATA, 0, 0)))
     {
         LOGERROR("Failed to add navigation mesh tile");

+ 2 - 0
Engine/Navigation/NavigationMesh.h

@@ -148,6 +148,8 @@ private:
     void CollectGeometries(Vector<NavigationGeometryInfo>& geometryList, Node* node, HashSet<Node*>& processedNodes, bool recursive);
     /// Get geometry data within a bounding box.
     void GetTileGeometry(NavigationBuildData& build, Vector<NavigationGeometryInfo>& geometryList, BoundingBox& box);
+    /// Add a triangle mesh to the geometry data.
+    void AddTriMeshGeometry(NavigationBuildData& build, Geometry* geometry, const Matrix3x4& transform);
     /// Build one tile of the navigation mesh. Return true if successful.
     bool BuildTile(Vector<NavigationGeometryInfo>& geometryList, int x, int z);
     /// Initialize navigation mesh query. Return true if successful.

+ 34 - 20
Engine/Physics/CollisionShape.cpp

@@ -78,16 +78,13 @@ TriangleMeshData::TriangleMeshData(Model* model, unsigned lodLevel) :
 {
     modelName_ = model->GetName();
     meshData_ = new btTriangleMesh();
-    const Vector<Vector<SharedPtr<Geometry> > >& geometries = model->GetGeometries();
     
-    for (unsigned i = 0; i < geometries.Size(); ++i)
+    unsigned numGeometries = model->GetNumGeometries();
+    
+    for (unsigned i = 0; i < numGeometries; ++i)
     {
-        unsigned subGeometryLodLevel = lodLevel;
-        if (subGeometryLodLevel >= geometries[i].Size())
-            subGeometryLodLevel = geometries[i].Size() - 1;
-        
-        Geometry* geom = geometries[i][subGeometryLodLevel];
-        if (!geom)
+        Geometry* geometry = model->GetGeometry(i, lodLevel);
+        if (!geometry)
         {
             LOGWARNING("Skipping null geometry for triangle mesh collision");
             continue;
@@ -99,15 +96,15 @@ TriangleMeshData::TriangleMeshData(Model* model, unsigned lodLevel) :
         unsigned indexSize;
         unsigned elementMask;
         
-        geom->GetRawData(vertexData, vertexSize, indexData, indexSize, elementMask);
+        geometry->GetRawData(vertexData, vertexSize, indexData, indexSize, elementMask);
         if (!vertexData || !indexData)
         {
             LOGWARNING("Skipping geometry with no CPU-side geometry data for triangle mesh collision");
             continue;
         }
         
-        unsigned indexStart = geom->GetIndexStart();
-        unsigned indexCount = geom->GetIndexCount();
+        unsigned indexStart = geometry->GetIndexStart();
+        unsigned indexCount = geometry->GetIndexCount();
         
         // 16-bit indices
         if (indexSize == sizeof(unsigned short))
@@ -152,17 +149,13 @@ TriangleMeshData::~TriangleMeshData()
 ConvexData::ConvexData(Model* model, unsigned lodLevel)
 {
     modelName_ = model->GetName();
-    const Vector<Vector<SharedPtr<Geometry> > >& geometries = model->GetGeometries();
     
     PODVector<Vector3> originalVertices;
+    unsigned numGeometries = model->GetNumGeometries();
     
-    for (unsigned i = 0; i < geometries.Size(); ++i)
+    for (unsigned i = 0; i < numGeometries; ++i)
     {
-        unsigned subGeometryLodLevel = lodLevel;
-        if (subGeometryLodLevel >= geometries[i].Size())
-            subGeometryLodLevel = geometries[i].Size() - 1;
-        
-        Geometry* geom = geometries[i][subGeometryLodLevel];
+        Geometry* geom = model->GetGeometry(i, lodLevel);
         if (!geom)
         {
             LOGWARNING("Skipping null geometry for convex hull collision");
@@ -340,8 +333,8 @@ void CollisionShape::DrawDebugGeometry(DebugRenderer* debug, bool depthTest)
             position.y_ += (heightfield->minHeight_ + heightfield->maxHeight_) * 0.5f;
         }
         
-        Vector3 worldPosition = worldTransform * position;
-        Quaternion worldRotation = worldTransform.Rotation() * rotation_;
+        Vector3 worldPosition(worldTransform * position);
+        Quaternion worldRotation(worldTransform.Rotation() * rotation_);
         
         btDiscreteDynamicsWorld* world = physicsWorld_->GetWorld();
         world->debugDrawObject(btTransform(ToBtQuaternion(worldRotation), ToBtVector3(worldPosition)), shape_, bodyActive ?
@@ -566,6 +559,27 @@ void CollisionShape::SetLodLevel(unsigned lodLevel)
     }
 }
 
+BoundingBox CollisionShape::GetWorldBoundingBox() const
+{
+    if (shape_ && node_)
+    {
+        // Use the rigid body's world transform if possible, as it may be different from the rendering transform
+        RigidBody* body = GetComponent<RigidBody>();
+        Matrix3x4 worldTransform = body ? Matrix3x4(body->GetPosition(), body->GetRotation(), node_->GetWorldScale()) :
+            node_->GetWorldTransform();
+        
+        Vector3 worldPosition(worldTransform * position_);
+        Quaternion worldRotation(worldTransform.Rotation() * rotation_);
+        btTransform shapeWorldTransform(ToBtQuaternion(worldRotation), ToBtVector3(worldPosition));
+        btVector3 aabbMin, aabbMax;
+        shape_->getAabb(shapeWorldTransform, aabbMin, aabbMax);
+        
+        return BoundingBox(ToVector3(aabbMin), ToVector3(aabbMax));
+    }
+    else
+        return BoundingBox();
+}
+
 void CollisionShape::NotifyRigidBody()
 {
     btCompoundShape* compound = GetParentCompoundShape();

+ 4 - 0
Engine/Physics/CollisionShape.h

@@ -171,6 +171,8 @@ public:
     
     /// Return Bullet collision shape.
     btCollisionShape* GetCollisionShape() const { return shape_; }
+    /// Return the shared geometry data.
+    CollisionGeometryData* GetGeometryData() const { return geometry_; }
     /// Return physics world.
     PhysicsWorld* GetPhysicsWorld() const { return physicsWorld_; }
     /// Return shape type.
@@ -187,6 +189,8 @@ public:
     Model* GetModel() const { return model_; }
     /// Return model LOD level.
     unsigned GetLodLevel() const { return lodLevel_; }
+    /// Return world-space bounding box.
+    BoundingBox GetWorldBoundingBox() const;
     
     /// Update the new collision shape to the RigidBody, and tell it to update its mass.
     void NotifyRigidBody();

+ 2 - 2
Engine/Scene/Component.h

@@ -75,10 +75,10 @@ public:
     bool IsEnabled() const { return enabled_; }
     /// Return whether is effectively enabled (node is also enabled.)
     bool IsEnabledEffective() const;
-    /// Return components in the same scene node by type.
-    void GetComponents(PODVector<Component*>& dest, ShortStringHash type) const;
     /// Return component in the same scene node by type. If there are several, returns the first.
     Component* GetComponent(ShortStringHash type) const;
+    /// Return components in the same scene node by type.
+    void GetComponents(PODVector<Component*>& dest, ShortStringHash type) const;
     /// Template version of returning a component in the same scene node by type.
     template <class T> T* GetComponent() const;
     /// Template version of returning components in the same scene node by type.

+ 6 - 6
Tools/AssetImporter/AssetImporter.cpp

@@ -1391,18 +1391,18 @@ void CombineLods(const PODVector<float>& lodDistances, const Vector<String>& mod
         outModel->SetNumGeometryLodLevels(i, srcModels.Size());
         for (unsigned j = 0; j < srcModels.Size(); ++j)
         {
-            Geometry* geom = srcModels[j]->GetGeometry(i, 0);
-            geom->SetLodDistance(lodDistances[j]);
-            outModel->SetGeometry(i, j, geom);
+            Geometry* geometry = srcModels[j]->GetGeometry(i, 0);
+            geometry->SetLodDistance(lodDistances[j]);
+            outModel->SetGeometry(i, j, geometry);
             
-            for (unsigned k = 0; k < geom->GetNumVertexBuffers(); ++k)
+            for (unsigned k = 0; k < geometry->GetNumVertexBuffers(); ++k)
             {
-                SharedPtr<VertexBuffer> vb(geom->GetVertexBuffer(k));
+                SharedPtr<VertexBuffer> vb(geometry->GetVertexBuffer(k));
                 if (!vbVector.Contains(vb))
                     vbVector.Push(vb);
             }
             
-            SharedPtr<IndexBuffer> ib(geom->GetIndexBuffer());
+            SharedPtr<IndexBuffer> ib(geometry->GetIndexBuffer());
             if (!ibVector.Contains(ib))
                 ibVector.Push(ib);
         }