SettingsMap* ConfigManager::GetSection(const Urho3D::String& section, bool create) { // Empty section gets assigned to main map if (section == Urho3D::String::EMPTY) return &_map; // Split section into submaps Urho3D::Vector<Urho3D::String> split; unsigned splitPos = 0; if (ConfigFile::ParseHeader(section).Empty()) { return &_map; } // Split sections by '.' or '/' // Comments will ignore splits behind them while (splitPos != Urho3D::String::NPOS) { // Find next comment split auto commentSplitPos = splitPos; auto hashPos = section.Find("#", commentSplitPos); auto slashesPos = section.Find("//", commentSplitPos); commentSplitPos = (hashPos < slashesPos) ? hashPos : slashesPos; // Find next split auto lastSplitPos = splitPos; auto dotPos = section.Find(".", lastSplitPos); auto slashPos = section.Find("/", lastSplitPos); splitPos = (dotPos < slashPos) ? dotPos : slashPos; // Ignore splits after comments splitPos = (commentSplitPos <= splitPos) ? Urho3D::String::NPOS : splitPos; int length = splitPos - lastSplitPos; if (splitPos == Urho3D::String::NPOS) { length = section.Length() - lastSplitPos; } auto sub = section.Substring(lastSplitPos, length); if (sub != Urho3D::String::EMPTY) split.Push(sub); } SettingsMap* currentMap = &_map; for (auto itr = split.Begin(); itr != split.End(); itr++) { auto section = *itr; // Find section SettingsMap* newMap = 0; for (auto map_itr = currentMap->Begin(); map_itr != currentMap->End(); map_itr++) { if (map_itr->first_ == section) { newMap = static_cast<SettingsMap*>(map_itr->second_.GetVoidPtr()); // Key exists, but is not a SettingsMap if (!newMap) { return 0; } // Key exists break; } } // Key does not exist if (!newMap) { if (create) { currentMap->operator[](section) = new SettingsMap(); newMap = static_cast<SettingsMap*>((*currentMap)[section].GetVoidPtr()); } } if (newMap) { currentMap = newMap; } } return currentMap; }
// ---------------------------------------------------------------------------- void Hull::SetMesh(Polyhedron* polyhedron) { faces_.Clear(); edges_.Clear(); hullMesh_ = polyhedron; if(hullMesh_->FaceCount() == 0) return; Urho3D::Vector<Urho3D::Vector3> trianglePositions; Polyhedron::ConstIterator vertexIt = hullMesh_->Begin(); while(vertexIt != hullMesh_->End()) { Vertex* v0 = *vertexIt++; Vertex* v1 = *vertexIt++; Vertex* v2 = *vertexIt++; // Accumulate positions of triangle centres for average position trianglePositions.Push( (v0->position_ + v1->position_ + v2->position_) / 3.0f ); // Add face faces_.Push(Face(v0, v1, v2)); } // Average triangle centres to get centre of hull centre_ = Urho3D::Vector3::ZERO; for(Urho3D::Vector<Urho3D::Vector3>::ConstIterator it = trianglePositions.Begin(); it != trianglePositions.End(); ++it) { centre_ += *it; } centre_ /= trianglePositions.Size(); // Make sure each triangle's normal vector is pointing away from centre of // the hull for(Urho3D::Vector<Face>::Iterator it = faces_.Begin(); it != faces_.End(); ++it) { Urho3D::Vector3 outwards = it->GetVertex(0)->position_ - centre_; if(outwards.DotProduct(it->GetNormal()) < 0) it->FlipNormal(); } // With the centre and normals calculated, we can use that information to // construct edges. Each edge stores the normal vectors of both triangles // it joins in order to calculate if a projected point is projected from // the correct angle or not. // // We iterate the polyhedron and the triangles list simultaneously, because // it is more efficient to check for joined edges using the polyhedron data // structure than the triangles list. The triangles list is required to get // the calculated and adjusted normals. vertexIt = hullMesh_->Begin(); Urho3D::Vector<Face>::ConstIterator triangleIt = faces_.Begin(); for(; vertexIt != hullMesh_->End(); triangleIt++) { Vertex* vertex[3]; vertex[0] = *vertexIt++; vertex[1] = *vertexIt++; vertex[2] = *vertexIt++; // find the three adjacent triangles Urho3D::Vector<Face>::ConstIterator triangleIt2 = faces_.Begin(); Polyhedron::ConstIterator vertexIt2 = hullMesh_->Begin(); for(; vertexIt2 != hullMesh_->End(); triangleIt2++) { Vertex* vertex2[3]; vertex2[0] = *vertexIt2++; vertex2[1] = *vertexIt2++; vertex2[2] = *vertexIt2++; // skip self if(vertexIt == vertexIt2) continue; // joined[2] will contain two Vertex objects if we find an edge // that is shared between the two current triangles. Vertex* joined[2]; Vertex** joinedPtr = joined; for(unsigned char i = 0; i != 3; ++i) for(unsigned char j = 0; j != 3; ++j) if(vertex[i] == vertex2[j]) *joinedPtr++ = vertex[i]; // Calculate number of vertices that were found joined. unsigned joinedCount = joinedPtr - joined; assert(joinedCount != 3); if(joinedCount != 2) continue; // Found a joined edge, add it edges_.Push(Edge( joined[0], joined[1], triangleIt->GetNormal(), triangleIt2->GetNormal() )); // Make sure edge boundary check points outwards from the hull's // centre Urho3D::Vector2 bary = edges_.Back().ProjectAndTransformToBarycentric(centre_); if(edges_.Back().ProjectionAngleIsInBounds(edges_.Back().TransformToCartesian(bary), centre_)) edges_.Back().FlipBoundaryCheck(); } } }