123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381 |
- #pragma once
- #include <Mathematics/Logger.h>
- #include <Mathematics/WeakPtrCompare.h>
- #include <Mathematics/EdgeKey.h>
- #include <Mathematics/TriangleKey.h>
- #include <map>
- #include <vector>
- namespace WwiseGTE
- {
- class ETNonmanifoldMesh
- {
- public:
-
- class Edge;
- typedef std::shared_ptr<Edge>(*ECreator)(int, int);
- typedef std::map<EdgeKey<false>, std::shared_ptr<Edge>> EMap;
-
- class Triangle;
- typedef std::shared_ptr<Triangle>(*TCreator)(int, int, int);
- typedef std::map<TriangleKey<true>, std::shared_ptr<Triangle>> TMap;
-
- class Edge
- {
- public:
- virtual ~Edge() = default;
- Edge(int v0, int v1)
- :
- V{ v0, v1 }
- {
- }
- bool operator<(Edge const& other) const
- {
- return EdgeKey<false>(V[0], V[1]) < EdgeKey<false>(other.V[0], other.V[1]);
- }
-
- std::array<int, 2> V;
-
- std::set<std::weak_ptr<Triangle>, WeakPtrLT<Triangle>> T;
- };
-
- class Triangle
- {
- public:
- virtual ~Triangle() = default;
- Triangle(int v0, int v1, int v2)
- :
- V{ v0, v1, v2 }
- {
- }
- bool operator<(Triangle const& other) const
- {
- return TriangleKey<true>(V[0], V[1], V[2]) < TriangleKey<true>(other.V[0], other.V[1], other.V[2]);
- }
-
- std::array<int, 3> V;
-
- std::array<std::weak_ptr<Edge>, 3> E;
- };
-
- virtual ~ETNonmanifoldMesh() = default;
- ETNonmanifoldMesh(ECreator eCreator = nullptr, TCreator tCreator = nullptr)
- :
- mECreator(eCreator ? eCreator : CreateEdge),
- mTCreator(tCreator ? tCreator : CreateTriangle)
- {
- }
-
-
-
-
-
- ETNonmanifoldMesh(ETNonmanifoldMesh const& mesh)
- {
- *this = mesh;
- }
- ETNonmanifoldMesh& operator=(ETNonmanifoldMesh const& mesh)
- {
- Clear();
- mECreator = mesh.mECreator;
- mTCreator = mesh.mTCreator;
- for (auto const& element : mesh.mTMap)
- {
- Insert(element.first.V[0], element.first.V[1], element.first.V[2]);
- }
- return *this;
- }
-
- inline EMap const& GetEdges() const
- {
- return mEMap;
- }
- inline TMap const& GetTriangles() const
- {
- return mTMap;
- }
-
-
-
- virtual std::shared_ptr<Triangle> Insert(int v0, int v1, int v2)
- {
- TriangleKey<true> tkey(v0, v1, v2);
- if (mTMap.find(tkey) != mTMap.end())
- {
-
-
- return nullptr;
- }
-
-
-
-
- std::shared_ptr<Triangle> tri = mTCreator(v0, v1, v2);
-
- for (int i0 = 2, i1 = 0; i1 < 3; i0 = i1++)
- {
- EdgeKey<false> ekey(tri->V[i0], tri->V[i1]);
- std::shared_ptr<Edge> edge;
- auto eiter = mEMap.find(ekey);
- if (eiter == mEMap.end())
- {
-
- edge = mECreator(tri->V[i0], tri->V[i1]);
- mEMap[ekey] = edge;
- }
- else
- {
-
- edge = eiter->second;
- LogAssert(edge != nullptr, "Unexpected condition.");
- }
-
- tri->E[i0] = edge;
-
- edge->T.insert(tri);
- }
- mTMap[tkey] = tri;
- return tri;
- }
-
-
- virtual bool Remove(int v0, int v1, int v2)
- {
- TriangleKey<true> tkey(v0, v1, v2);
- auto titer = mTMap.find(tkey);
- if (titer == mTMap.end())
- {
-
- return false;
- }
-
- std::shared_ptr<Triangle> tri = titer->second;
-
- for (int i = 0; i < 3; ++i)
- {
-
- auto edge = tri->E[i].lock();
- LogAssert(edge != nullptr, "Unexpected condition.");
-
-
- size_t numRemoved = edge->T.erase(tri);
- LogAssert(numRemoved > 0, "Unexpected condition.");
-
- if (edge->T.size() == 0)
- {
- EdgeKey<false> ekey(edge->V[0], edge->V[1]);
- mEMap.erase(ekey);
- }
- }
-
- mTMap.erase(tkey);
- return true;
- }
-
- virtual void Clear()
- {
- mEMap.clear();
- mTMap.clear();
- }
-
-
- bool IsManifold() const
- {
- for (auto const& element : mEMap)
- {
- if (element.second->T.size() > 2)
- {
- return false;
- }
- }
- return true;
- }
-
-
-
-
-
-
- bool IsClosed() const
- {
- for (auto const& element : mEMap)
- {
- if (element.second->T.size() != 2)
- {
- return false;
- }
- }
- return true;
- }
-
-
-
-
-
-
-
- void GetComponents(std::vector<std::vector<std::shared_ptr<Triangle>>>& components) const
- {
-
- std::map<std::shared_ptr<Triangle>, int> visited;
- for (auto const& element : mTMap)
- {
- visited.insert(std::make_pair(element.second, 0));
- }
- for (auto& element : mTMap)
- {
- auto tri = element.second;
- if (visited[tri] == 0)
- {
- std::vector<std::shared_ptr<Triangle>> component;
- DepthFirstSearch(tri, visited, component);
- components.push_back(component);
- }
- }
- }
- void GetComponents(std::vector<std::vector<TriangleKey<true>>>& components) const
- {
-
- std::map<std::shared_ptr<Triangle>, int> visited;
- for (auto const& element : mTMap)
- {
- visited.insert(std::make_pair(element.second, 0));
- }
- for (auto& element : mTMap)
- {
- std::shared_ptr<Triangle> tri = element.second;
- if (visited[tri] == 0)
- {
- std::vector<std::shared_ptr<Triangle>> component;
- DepthFirstSearch(tri, visited, component);
- std::vector<TriangleKey<true>> keyComponent;
- keyComponent.reserve(component.size());
- for (auto const& t : component)
- {
- keyComponent.push_back(TriangleKey<true>(t->V[0], t->V[1], t->V[2]));
- }
- components.push_back(keyComponent);
- }
- }
- }
- protected:
-
- static std::shared_ptr<Edge> CreateEdge(int v0, int v1)
- {
- return std::make_shared<Edge>(v0, v1);
- }
- ECreator mECreator;
- EMap mEMap;
-
- static std::shared_ptr<Triangle> CreateTriangle(int v0, int v1, int v2)
- {
- return std::make_shared<Triangle>(v0, v1, v2);
- }
- TCreator mTCreator;
- TMap mTMap;
-
-
-
-
- void DepthFirstSearch(std::shared_ptr<Triangle> const& tInitial,
- std::map<std::shared_ptr<Triangle>, int>& visited,
- std::vector<std::shared_ptr<Triangle>>& component) const
- {
-
-
-
- std::vector<std::shared_ptr<Triangle>> tStack(mTMap.size());
- int top = -1;
- tStack[++top] = tInitial;
- while (top >= 0)
- {
- std::shared_ptr<Triangle> tri = tStack[top];
- visited[tri] = 1;
- int i;
- for (i = 0; i < 3; ++i)
- {
- auto edge = tri->E[i].lock();
- LogAssert(edge != nullptr, "Unexpected condition.");
- bool foundUnvisited = false;
- for (auto const& adjw : edge->T)
- {
- auto adj = adjw.lock();
- LogAssert(adj != nullptr, "Unexpected condition.");
- if (visited[adj] == 0)
- {
- tStack[++top] = adj;
- foundUnvisited = true;
- break;
- }
- }
- if (foundUnvisited)
- {
- break;
- }
- }
- if (i == 3)
- {
- visited[tri] = 2;
- component.push_back(tri);
- --top;
- }
- }
- }
- };
- }
|