|
|
@@ -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);
|