Browse Source

Transform geometry to local space of the navigation mesh root node to allow moving the root without invalidating navigation data.

Lasse Öörni 12 years ago
parent
commit
3c43ccb3f1
2 changed files with 28 additions and 14 deletions
  1. 27 13
      Engine/Navigation/NavigationMesh.cpp
  2. 1 1
      Engine/Navigation/NavigationMesh.h

+ 27 - 13
Engine/Navigation/NavigationMesh.cpp

@@ -162,7 +162,7 @@ void NavigationMesh::RegisterObject(Context* context)
 
 
 void NavigationMesh::DrawDebugGeometry(DebugRenderer* debug, bool depthTest)
 void NavigationMesh::DrawDebugGeometry(DebugRenderer* debug, bool depthTest)
 {
 {
-    if (!navMesh_)
+    if (!navMesh_ || !node_)
         return;
         return;
     
     
     const dtNavMesh* navMesh = navMesh_;
     const dtNavMesh* navMesh = navMesh_;
@@ -170,14 +170,16 @@ void NavigationMesh::DrawDebugGeometry(DebugRenderer* debug, bool depthTest)
     if (!tile)
     if (!tile)
         return;
         return;
     
     
+    const Matrix3x4& worldTransform = node_->GetWorldTransform();
+    
     for (int i = 0; i < tile->header->polyCount; ++i)
     for (int i = 0; i < tile->header->polyCount; ++i)
     {
     {
         dtPoly* poly = tile->polys + i;
         dtPoly* poly = tile->polys + i;
         for (unsigned j = 0; j < poly->vertCount; ++j)
         for (unsigned j = 0; j < poly->vertCount; ++j)
         {
         {
             debug->AddLine(
             debug->AddLine(
-                *reinterpret_cast<const Vector3*>(&tile->verts[poly->verts[j] * 3]),
-                *reinterpret_cast<const Vector3*>(&tile->verts[poly->verts[(j + 1) % poly->vertCount] * 3]),
+                worldTransform * *reinterpret_cast<const Vector3*>(&tile->verts[poly->verts[j] * 3]),
+                worldTransform * *reinterpret_cast<const Vector3*>(&tile->verts[poly->verts[(j + 1) % poly->vertCount] * 3]),
                 Color::YELLOW,
                 Color::YELLOW,
                 depthTest
                 depthTest
             );
             );
@@ -254,6 +256,9 @@ bool NavigationMesh::Build()
     if (!node_)
     if (!node_)
         return false;
         return false;
     
     
+    if (!node_->GetWorldScale().Equals(Vector3::ONE))
+        LOGWARNING("Navigation mesh root node has scaling. Agent parameters may not work as intended");
+    
     NavigationBuildData build;
     NavigationBuildData build;
     
     
     {
     {
@@ -448,10 +453,17 @@ void NavigationMesh::FindPath(PODVector<Vector3>& dest, const Vector3& start, co
     if (!navMesh_ || !navMeshQuery_)
     if (!navMesh_ || !navMeshQuery_)
         return;
         return;
     
     
+    // Navigation data is in local space. Transform path points from world to local
+    const Matrix3x4& transform = node_->GetWorldTransform();
+    Matrix3x4 inverseTransform = transform.Inverse();
+    
+    Vector3 localStart = inverseTransform * start;
+    Vector3 localEnd = inverseTransform * end;
+    
     dtPolyRef startRef;
     dtPolyRef startRef;
     dtPolyRef endRef;
     dtPolyRef endRef;
-    navMeshQuery_->findNearestPoly(&start.x_, &extents.x_, queryFilter_, &startRef, 0);
-    navMeshQuery_->findNearestPoly(&end.x_, &extents.x_, queryFilter_, &endRef, 0);
+    navMeshQuery_->findNearestPoly(&localStart.x_, &extents.x_, queryFilter_, &startRef, 0);
+    navMeshQuery_->findNearestPoly(&localEnd.x_, &extents.x_, queryFilter_, &endRef, 0);
     
     
     if (!startRef || !endRef)
     if (!startRef || !endRef)
         return;
         return;
@@ -463,20 +475,22 @@ void NavigationMesh::FindPath(PODVector<Vector3>& dest, const Vector3& start, co
     int numPolys = 0;
     int numPolys = 0;
     int numPathPoints = 0;
     int numPathPoints = 0;
     
     
-    navMeshQuery_->findPath(startRef, endRef, &start.x_, &end.x_, queryFilter_, polys, &numPolys, MAX_POLYS);
+    navMeshQuery_->findPath(startRef, endRef, &localStart.x_, &localEnd.x_, queryFilter_, polys, &numPolys, MAX_POLYS);
     if (!numPolys)
     if (!numPolys)
         return;
         return;
     
     
-    Vector3 actualEnd = end;
+    Vector3 actualLocalEnd = localEnd;
     
     
     // If full path was not found, clamp end point to the end polygon
     // If full path was not found, clamp end point to the end polygon
     if (polys[numPolys - 1] != endRef)
     if (polys[numPolys - 1] != endRef)
-        navMeshQuery_->closestPointOnPoly(polys[numPolys - 1], &end.x_, &actualEnd.x_);
+        navMeshQuery_->closestPointOnPoly(polys[numPolys - 1], &localEnd.x_, &actualLocalEnd.x_);
     
     
-    navMeshQuery_->findStraightPath(&start.x_, &actualEnd.x_, polys, numPolys, &pathPoints[0].x_, pathFlags, pathPolys, &numPathPoints, MAX_POLYS);
+    navMeshQuery_->findStraightPath(&localStart.x_, &actualLocalEnd.x_, polys, numPolys, &pathPoints[0].x_, pathFlags, pathPolys,
+        &numPathPoints, MAX_POLYS);
     
     
+    // Transform path result back to world space
     for (int i = 0; i < numPathPoints; ++i)
     for (int i = 0; i < numPathPoints; ++i)
-        dest.Push(pathPoints[i]);
+        dest.Push(transform * pathPoints[i]);
 }
 }
 
 
 void NavigationMesh::SetNavigationDataAttr(const PODVector<unsigned char>& data)
 void NavigationMesh::SetNavigationDataAttr(const PODVector<unsigned char>& data)
@@ -538,6 +552,9 @@ void NavigationMesh::AddGeometry(NavigationBuildData& build, Node* node, Geometr
     unsigned indexSize;
     unsigned indexSize;
     unsigned elementMask;
     unsigned elementMask;
     
     
+    // Transform geometry to local space of the navigation mesh node
+    Matrix3x4 transform = node_->GetWorldTransform().Inverse() * node->GetWorldTransform();
+    
     geometry->GetRawData(vertexData, vertexSize, indexData, indexSize, elementMask);
     geometry->GetRawData(vertexData, vertexSize, indexData, indexSize, elementMask);
     if (!vertexData || !indexData || (elementMask & MASK_POSITION) == 0)
     if (!vertexData || !indexData || (elementMask & MASK_POSITION) == 0)
     {
     {
@@ -558,9 +575,6 @@ void NavigationMesh::AddGeometry(NavigationBuildData& build, Node* node, Geometr
     
     
     unsigned destVertexStart = build.vertices_.Size();
     unsigned destVertexStart = build.vertices_.Size();
     
     
-    // Copy draw range vertices transformed into world space
-    Matrix3x4 transform = node->GetWorldTransform();
-    
     for (unsigned i = srcVertexStart; i < srcVertexStart + srcVertexCount; ++i)
     for (unsigned i = srcVertexStart; i < srcVertexStart + srcVertexCount; ++i)
     {
     {
         Vector3 vertex = transform * *((const Vector3*)(&vertexData[i * vertexSize]));
         Vector3 vertex = transform * *((const Vector3*)(&vertexData[i * vertexSize]));

+ 1 - 1
Engine/Navigation/NavigationMesh.h

@@ -79,7 +79,7 @@ public:
     void SetDetailSampleMaxError(float error);
     void SetDetailSampleMaxError(float error);
     /// Rebuild the navigation data. Return true if successful.
     /// Rebuild the navigation data. Return true if successful.
     bool Build();
     bool Build();
-    /// Find a path. Return non-empty list of points if successful.
+    /// Find a path between world space points. Return non-empty list of points if successful.
     void FindPath(PODVector<Vector3>& dest, const Vector3& start, const Vector3& end, const Vector3& extents = Vector3::ONE);
     void FindPath(PODVector<Vector3>& dest, const Vector3& start, const Vector3& end, const Vector3& extents = Vector3::ONE);
     
     
     /// Return cell size.
     /// Return cell size.