22 using namespace detail;
28 : m_Triangles(TriIndices.
size() / 3),
44 assert(out_pPrimitivesVector);
57 out_pPrimitivesVector->clear();
64 std::swap(m_PrimitivesVector, (* out_pPrimitivesVector));
69 void tri_stripper::InitTriHeap()
75 for (
size_t i = 0;
i < m_Triangles.
size(); ++
i)
76 m_TriHeap.
push(m_Triangles[
i].out_size());
83 while ((! m_TriHeap.
empty()) && (m_TriHeap.
top() == 0))
89 void tri_stripper::ResetStripIDs()
92 (**it).ResetStripID();
97 void tri_stripper::Stripify()
99 while (! m_TriHeap.
empty()) {
102 const size_t HeapTop = m_TriHeap.
position(0);
103 m_Candidates.push_back(HeapTop);
105 while (! m_Candidates.empty()) {
108 const strip TriStrip = FindBestStrip();
110 if (TriStrip.
Size() >= m_MinStripSize)
111 BuildStrip(TriStrip);
114 if (! m_TriHeap.
removed(HeapTop))
115 m_TriHeap.
erase(HeapTop);
118 while ((! m_TriHeap.
empty()) && (m_TriHeap.
top() == 0))
125 inline strip tri_stripper::FindBestStrip()
130 policy Policy(m_MinStripSize, Cache());
132 while (! m_Candidates.empty()) {
134 const size_t Candidate = m_Candidates.back();
135 m_Candidates.pop_back();
138 if ((m_Triangles[Candidate].marked()) || (m_TriHeap[Candidate] == 0))
142 for (
size_t i = 0;
i < 3; ++
i) {
147 m_Cache = CacheBackup;
151 if (m_BackwardSearch) {
153 for (
size_t i = 0;
i < 3; ++
i) {
158 m_Cache = CacheBackup;
161 for (
size_t i = 0;
i < 3; ++
i) {
166 m_Cache = CacheBackup;
182 m_Triangles[Start]->SetStripID(++m_StripID);
183 AddTriangle(* m_Triangles[Start], Order,
false);
186 bool ClockWise =
false;
189 for (tri_iterator Node = (m_Triangles.
begin() + Start);
190 (Node != m_Triangles.
end()) && (!Cache() || ((Size + 2) < CacheSize()));
193 const const_link_iterator Link = LinkToNeighbour(Node, ClockWise, Order,
false);
196 if (Link == Node->out_end()) {
198 Node = m_Triangles.
end();
203 Node = Link->terminal();
204 (* Node)->SetStripID(m_StripID);
205 ClockWise = ! ClockWise;
210 return strip(Start, StartOrder, Size);
218 m_Triangles[Start]->SetStripID(++m_StripID);
219 BackAddIndex(LastEdge(* m_Triangles[Start], Order).B());
225 for (Node = (m_Triangles.
begin() + Start);
226 !Cache() || ((Size + 2) < CacheSize());
229 const const_link_iterator Link = BackLinkToNeighbour(Node, ClockWise, Order);
232 if (Link == Node->out_end())
236 Node = Link->terminal();
237 (* Node)->SetStripID(m_StripID);
238 ClockWise = ! ClockWise;
250 m_Cache.
merge(m_BackCache, Size);
254 return strip(Node - m_Triangles.
begin(), Order, Size);
259 void tri_stripper::BuildStrip(
const strip Strip)
261 const size_t Start = Strip.
Start();
263 bool ClockWise =
false;
269 AddTriangle(* m_Triangles[Start], Order,
true);
270 MarkTriAsTaken(Start);
273 tri_iterator Node = (m_Triangles.
begin() + Start);
275 for (
size_t Size = 1; Size < Strip.
Size(); ++Size) {
277 const const_link_iterator Link = LinkToNeighbour(Node, ClockWise, Order,
true);
279 assert(Link != Node->out_end());
282 Node = Link->terminal();
283 MarkTriAsTaken(Node - m_Triangles.
begin());
284 ClockWise = ! ClockWise;
290 inline tri_stripper::const_link_iterator tri_stripper::LinkToNeighbour(
const const_tri_iterator Node,
const bool ClockWise,
triangle_order & Order,
const bool NotSimulation)
294 for (const_link_iterator Link = Node->out_begin(); Link != Node->out_end(); ++Link) {
297 const triangle & Tri = ** Link->terminal();
300 if (NotSimulation || (Tri.
StripID() != m_StripID)) {
302 if (! Link->terminal()->marked()) {
306 if ((Edge.
B() == Tri.
A()) && (Edge.
A() == Tri.
B())) {
307 Order = (ClockWise) ?
ABC :
BCA;
308 AddIndex(Tri.
C(), NotSimulation);
312 else if ((Edge.
B() == Tri.
B()) && (Edge.
A() == Tri.
C())) {
313 Order = (ClockWise) ?
BCA :
CAB;
314 AddIndex(Tri.
A(), NotSimulation);
318 else if ((Edge.
B() == Tri.
C()) && (Edge.
A() == Tri.
A())) {
319 Order = (ClockWise) ?
CAB :
ABC;
320 AddIndex(Tri.
B(), NotSimulation);
328 return Node->out_end();
333 inline tri_stripper::const_link_iterator tri_stripper::BackLinkToNeighbour(const_tri_iterator Node,
bool ClockWise,
triangle_order & Order)
337 for (const_link_iterator Link = Node->out_begin(); Link != Node->out_end(); ++Link) {
340 const triangle & Tri = ** Link->terminal();
343 if ((Tri.
StripID() != m_StripID) && ! Link->terminal()->marked()) {
347 if ((Edge.
B() == Tri.
A()) && (Edge.
A() == Tri.
B())) {
348 Order = (ClockWise) ?
CAB :
BCA;
349 BackAddIndex(Tri.
C());
353 else if ((Edge.
B() == Tri.
B()) && (Edge.
A() == Tri.
C())) {
354 Order = (ClockWise) ?
ABC :
CAB;
355 BackAddIndex(Tri.
A());
359 else if ((Edge.
B() == Tri.
C()) && (Edge.
A() == Tri.
A())) {
360 Order = (ClockWise) ?
BCA :
ABC;
361 BackAddIndex(Tri.
B());
368 return Node->out_end();
373 void tri_stripper::MarkTriAsTaken(
const size_t i)
379 m_Triangles[
i].mark();
386 for (tri_link_iter Link = m_Triangles[i].out_begin(); Link != m_Triangles[
i].out_end(); ++Link) {
388 const size_t j = Link->terminal() - m_Triangles.
begin();
390 if ((! m_Triangles[j].marked()) && (! m_TriHeap.
removed(j))) {
391 size_t NewDegree = m_TriHeap.
peek(j);
392 NewDegree = NewDegree - 1;
393 m_TriHeap.
update(j, NewDegree);
396 if (Cache() && (NewDegree > 0))
397 m_Candidates.push_back(j);
446 inline void tri_stripper::AddIndex(
const index i,
const bool NotSimulation)
449 m_Cache.
push(i, ! NotSimulation);
452 m_PrimitivesVector.back().Indices.push_back(i);
457 inline void tri_stripper::BackAddIndex(
const index i)
460 m_BackCache.
push(i,
true);
465 inline void tri_stripper::AddTriangle(
const triangle & Tri,
const triangle_order Order,
const bool NotSimulation)
470 AddIndex(Tri.
A(), NotSimulation);
471 AddIndex(Tri.
B(), NotSimulation);
472 AddIndex(Tri.
C(), NotSimulation);
476 AddIndex(Tri.
B(), NotSimulation);
477 AddIndex(Tri.
C(), NotSimulation);
478 AddIndex(Tri.
A(), NotSimulation);
482 AddIndex(Tri.
C(), NotSimulation);
483 AddIndex(Tri.
A(), NotSimulation);
484 AddIndex(Tri.
B(), NotSimulation);
496 BackAddIndex(Tri.
C());
497 BackAddIndex(Tri.
B());
498 BackAddIndex(Tri.
A());
502 BackAddIndex(Tri.
A());
503 BackAddIndex(Tri.
C());
504 BackAddIndex(Tri.
B());
508 BackAddIndex(Tri.
B());
509 BackAddIndex(Tri.
A());
510 BackAddIndex(Tri.
C());
517 void tri_stripper::AddLeftTriangles()
522 m_PrimitivesVector.push_back(Primitives);
523 indices & Indices = m_PrimitivesVector.back().Indices;
525 for (
size_t i = 0; i < m_Triangles.
size(); ++
i)
526 if (! m_Triangles[i].marked()) {
527 Indices.push_back(m_Triangles[i]->A());
528 Indices.push_back(m_Triangles[i]->B());
529 Indices.push_back(m_Triangles[i]->C());
533 if (Indices.size() == 0)
534 m_PrimitivesVector.pop_back();
539 inline bool tri_stripper::Cache()
const 541 return (m_Cache.
size() != 0);
546 inline size_t tri_stripper::CacheSize()
const 548 return m_Cache.
size();
void SetPushCacheHits(bool Enabled=true)
void Strip(primitive_vector *out_pPrimitivesVector)
void reserve(size_t Size)
void update(size_t i, const T &Elem)
size_t push(const T &Elem)
void Challenge(strip Strip, size_t Degree, size_t CacheHits)
const T & peek(size_t i) const
void SetBackwardSearch(bool Enabled=false)
void merge(const cache_simulator &Backward, size_t PossibleOverlap)
std::vector< indice > indices
size_t position(size_t i) const
bool removed(size_t i) const
void SetMinStripSize(size_t MinStripSize=2)
arc_list::iterator out_arc_iterator
void SetCacheSize(size_t CacheSize=10)
node_vector::iterator node_iterator
void make_connectivity_graph(graph_array< triangle > &Triangles, const indices &Indices)
tri_stripper(const indices &TriIndices)
std::vector< primitive_group > primitive_vector
triangle_order Order() const
void push(index i, bool CountCacheHit=false)
void unmark_nodes(graph_array< nodetype > &G)