void NavigationMesh::CollectGeometries(Vector<NavigationGeometryInfo>& geometryList) { ATOMIC_PROFILE(CollectNavigationGeometry); // Get Navigable components from child nodes, not from whole scene. This makes it possible to partition // the scene into several navigation meshes PODVector<Navigable*> navigables; node_->GetComponents<Navigable>(navigables, true); HashSet<Node*> processedNodes; for (unsigned i = 0; i < navigables.Size(); ++i) { if (navigables[i]->IsEnabledEffective()) CollectGeometries(geometryList, navigables[i]->GetNode(), processedNodes, navigables[i]->IsRecursive()); } // Get offmesh connections Matrix3x4 inverse = node_->GetWorldTransform().Inverse(); PODVector<OffMeshConnection*> connections; node_->GetComponents<OffMeshConnection>(connections, true); for (unsigned i = 0; i < connections.Size(); ++i) { OffMeshConnection* connection = connections[i]; if (connection->IsEnabledEffective() && connection->GetEndPoint()) { const Matrix3x4& transform = connection->GetNode()->GetWorldTransform(); NavigationGeometryInfo info; info.component_ = connection; info.boundingBox_ = BoundingBox(Sphere(transform.Translation(), connection->GetRadius())).Transformed(inverse); geometryList.Push(info); } } // Get nav area volumes PODVector<NavArea*> navAreas; node_->GetComponents<NavArea>(navAreas, true); areas_.Clear(); for (unsigned i = 0; i < navAreas.Size(); ++i) { NavArea* area = navAreas[i]; if (area->IsEnabledEffective()) { NavigationGeometryInfo info; info.component_ = area; info.boundingBox_ = area->GetWorldBoundingBox(); geometryList.Push(info); areas_.Push(WeakPtr<NavArea>(area)); } } }
PODVector<OffMeshConnection*> DynamicNavigationMesh::CollectOffMeshConnections(const BoundingBox& bounds) { PODVector<OffMeshConnection*> connections; node_->GetComponents<OffMeshConnection>(connections, true); for (unsigned i = 0; i < connections.Size(); ++i) { OffMeshConnection* connection = connections[i]; if (!(connection->IsEnabledEffective() && connection->GetEndPoint())) { // discard this connection connections.Erase(i); --i; } } return connections; }
void NavigationMesh::GetTileGeometry(NavBuildData* build, Vector<NavigationGeometryInfo>& geometryList, BoundingBox& box) { Matrix3x4 inverse = node_->GetWorldTransform().Inverse(); for (unsigned i = 0; i < geometryList.Size(); ++i) { if (box.IsInsideFast(geometryList[i].boundingBox_) != OUTSIDE) { const Matrix3x4& transform = geometryList[i].transform_; if (geometryList[i].component_->GetType() == OffMeshConnection::GetTypeStatic()) { OffMeshConnection* connection = static_cast<OffMeshConnection*>(geometryList[i].component_); Vector3 start = inverse * connection->GetNode()->GetWorldPosition(); Vector3 end = inverse * connection->GetEndPoint()->GetWorldPosition(); build->offMeshVertices_.Push(start); build->offMeshVertices_.Push(end); build->offMeshRadii_.Push(connection->GetRadius()); build->offMeshFlags_.Push((unsigned short)connection->GetMask()); build->offMeshAreas_.Push((unsigned char)connection->GetAreaID()); build->offMeshDir_.Push((unsigned char)(connection->IsBidirectional() ? DT_OFFMESH_CON_BIDIR : 0)); continue; } else if (geometryList[i].component_->GetType() == NavArea::GetTypeStatic()) { NavArea* area = static_cast<NavArea*>(geometryList[i].component_); NavAreaStub stub; stub.areaID_ = (unsigned char)area->GetAreaID(); stub.bounds_ = area->GetWorldBoundingBox(); build->navAreas_.Push(stub); continue; } #ifdef ATOMIC_PHYSICS CollisionShape* shape = dynamic_cast<CollisionShape*>(geometryList[i].component_); if (shape) { switch (shape->GetShapeType()) { case SHAPE_TRIANGLEMESH: { 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; case SHAPE_CONVEXHULL: { 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]); for (unsigned j = 0; j < numIndices; ++j) build->indices_.Push(data->indexData_[j] + destVertexStart); } break; case SHAPE_BOX: { 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)); 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; default: break; } continue; } #endif 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); } } } }