2 #include "TopologyBuilder.h"
8 FacetKey(CVertex
* a1
, CVertex
* a2
, CVertex
* a3
)
10 v1
= a1
; v2
= a2
; v3
= a3
;
12 bool operator<(const FacetKey
& rhs
) const
14 if(v1
< rhs
.v1
) { return true; }
15 if(v1
> rhs
.v1
) { return false; }
16 if(v2
< rhs
.v2
) { return true; }
17 if(v2
> rhs
.v2
) { return false; }
25 static std::set
<FacetKey
>* all_facet_keys
;
26 void CTopologyBuilder::begin_surface()
28 transition(eS_Initial
, eS_Surface
);
30 nb_non_manifold_v_
= 0;
33 all_facet_keys
= new std::set
<FacetKey
>;
36 void CTopologyBuilder::clear()
42 void CTopologyBuilder::end_surface(bool remove
)
44 delete all_facet_keys
; all_facet_keys
= NULL
;
45 transition(eS_Surface
, eS_Final
);
53 if(!quiet_
&& (nb_non_manifold_v_
!= 0))
55 CryLog("MapBuilder Encountered non-manifold vertices (fixed)");
57 if(!quiet_
&& (nb_duplicate_e_
!= 0))
59 CryLog("MapBuilder Encountered duplicated edges (fixed)");
61 if(!quiet_
&& (nb_isolated_v_
!= 0))
63 CryLog("MapBuilder Encountered isolated vertices (removed)");
67 void CTopologyBuilder::reset()
69 transition(eS_Final
, eS_Initial
);
72 void CTopologyBuilder::add_vertex(unsigned int id
, const Vec3d
& p
)
74 transition(eS_Surface
, eS_Surface
);
75 add_vertex_internal(id
, p
);
78 void CTopologyBuilder::add_vertex(const Vec3d
& p
)
80 transition(eS_Surface
, eS_Surface
);
81 add_vertex_internal(p
);
84 void CTopologyBuilder::add_tex_vertex(const Vec2d
& p
)
86 add_tex_vertex(tex_vertex_
.size(), p
);
89 void CTopologyBuilder::add_tex_vertex(unsigned int id
, const Vec2d
& p
)
91 transition(eS_Surface
, eS_Surface
);
92 std::shared_ptr
<CTexVertex
>& new_tv
= std::shared_ptr
<CTexVertex
>(target_
->new_tex_vertex());
93 new_tv
-> set_tex_coord(p
);
94 while(tex_vertex_
.size() <= id
) {
95 tex_vertex_
.push_back(NULL
);
97 tex_vertex_
[id
] = new_tv
;
100 void CTopologyBuilder::add_vertex_internal(unsigned int id
, const Vec3d
& p
)
102 CVertex
* new_v
= target_
->new_vertex();
103 new_v
-> set_point(p
);
104 while(vertex_
.size() <= id
) {
105 vertex_
.push_back(NULL
);
111 void CTopologyBuilder::add_vertex_internal(const Vec3d
& p
)
113 add_vertex_internal(vertex_
.size(), p
);
116 void CTopologyBuilder::begin_facet() {
117 facet_vertex_
.clear();
118 facet_tex_vertex_
.clear();
121 void CTopologyBuilder::end_facet()
123 assert(facet_vertex_
.size() == facet_tex_vertex_
.size());
124 int nb_vertices
= facet_vertex_
.size();
130 CryLog("MapBuilder Facet with less than 3 vertices");
135 if(false && nb_vertices
== 3)
137 std::vector
<CVertex
*> W
= facet_vertex_
;
138 std::sort(W
.begin(), W
.end());
139 FacetKey
k(W
[0], W
[1],W
[2]);
140 if(all_facet_keys
->find(k
) != all_facet_keys
->end())
142 //std::cerr << '.' << std::flush;
145 all_facet_keys
->insert(k
);
149 // Detect duplicated vertices
150 for(int i
=0; i
<nb_vertices
; i
++)
152 for(int j
=i
+1; j
<nb_vertices
; j
++)
154 if(facet_vertex_
[i
] == facet_vertex_
[j
])
158 CryLog("MapBuilder Duplicated vertex in facet, ignoring facet");
165 // Detect and remove non-manifold edges by duplicating
166 // the corresponding vertices.
167 for(int from
=0; from
<nb_vertices
; from
++)
169 int to
=((from
+1) % nb_vertices
);
170 if(find_halfedge_between(facet_vertex_
[from
], facet_vertex_
[to
]) != NULL
)
173 facet_vertex_
[from
] = copy_vertex(facet_vertex_
[from
]);
174 facet_vertex_
[to
] = copy_vertex(facet_vertex_
[to
]);
179 begin_facet_internal();
180 for(int i
=0; i
<nb_vertices
; i
++)
182 add_vertex_to_facet_internal(facet_vertex_
[i
]);
183 if(facet_tex_vertex_
[i
] != NULL
)
185 set_corner_tex_vertex_internal(facet_tex_vertex_
[i
]);
188 end_facet_internal();
192 CVertex
* CTopologyBuilder::copy_vertex(CVertex
* from
)
194 // Note: tex coords are not copied, since
195 // an halfedge does not exist in the copy to
196 // store the texvertex pointer.
198 CVertex
* result
= target_
->new_vertex();
199 result
->set_point(from
->point());
202 is_locked_
[result
] = true;
207 void CTopologyBuilder::add_vertex_to_facet(int i
)
209 if(i
< 0 || i
>= int(vertex_
.size()))
213 CryLog("MapBuilder vertex index %d out of range",i
);
217 facet_vertex_
.push_back(vertex_
[i
]);
218 facet_tex_vertex_
.push_back(NULL
);
221 void CTopologyBuilder::set_corner_tex_vertex(int i
)
223 if(i
< 0 || i
>= int(tex_vertex_
.size()))
226 // CryLog("MapBuilder") << "texvertex index "
227 // << i << " out of range"
232 *(facet_tex_vertex_
.rbegin()) = tex_vertex_
[i
];
235 void CTopologyBuilder::lock_vertex(int i
)
237 if(i
< 0 || i
>= int(vertex_
.size()))
241 CryLog("MapBuilder vertex index %d out of range",i
);
245 is_locked_
[vertex(i
)] = true;
248 void CTopologyBuilder::unlock_vertex(int i
)
250 if(i
< 0 || i
>= int(vertex_
.size()))
254 CryLog("MapBuilder vertex index %d out of range",i
);
258 is_locked_
[vertex(i
)] = false;
261 void CTopologyBuilder::begin_facet_internal()
263 transition(eS_Surface
, eS_Facet
);
264 current_facet_
= target_
->new_facet();
265 first_vertex_in_facet_
= NULL
;
266 current_vertex_
= NULL
;
267 first_halfedge_in_facet_
= NULL
;
268 current_halfedge_
= NULL
;
269 first_tex_vertex_in_facet_
= NULL
;
272 void CTopologyBuilder::end_facet_internal()
274 transition(eS_Facet
, eS_Surface
);
275 CHalfedge
* h
= new_halfedge_between(current_vertex_
, first_vertex_in_facet_
);
277 CTopologyGraphMutator::link(current_halfedge_
, h
, 1);
278 CTopologyGraphMutator::link(h
, first_halfedge_in_facet_
, 1);
279 if(first_tex_vertex_in_facet_
!= NULL
)
281 CTopologyGraphMutator::set_halfedge_tex_vertex(h
, std::shared_ptr
<CTexVertex
>(first_tex_vertex_in_facet_
));
285 void CTopologyBuilder::add_vertex_to_facet_internal(CVertex
* v
)
287 transition(eS_Facet
, eS_Facet
);
289 if(first_vertex_in_facet_
== NULL
)
291 first_vertex_in_facet_
= v
;
295 CHalfedge
* new_halfedge
= new_halfedge_between(current_vertex_
, v
);
297 if(first_halfedge_in_facet_
== NULL
)
299 first_halfedge_in_facet_
= new_halfedge
;
300 CTopologyGraphMutator::make_facet_key(first_halfedge_in_facet_
);
304 CTopologyGraphMutator::link(current_halfedge_
, new_halfedge
, 1);
306 current_halfedge_
= new_halfedge
;
311 void CTopologyBuilder::set_corner_tex_vertex_internal(std::shared_ptr
<CTexVertex
>& tv
)
313 transition(eS_Facet
, eS_Facet
);
314 if(current_halfedge_
== NULL
)
316 first_tex_vertex_in_facet_
= tv
;
320 CTopologyGraphMutator::set_halfedge_tex_vertex(current_halfedge_
, tv
);
325 CVertex
* CTopologyBuilder::current_vertex()
327 return vertex_
[vertex_
.size() - 1];
330 CVertex
* CTopologyBuilder::vertex(int i
)
335 std::shared_ptr
<CTexVertex
>& CTopologyBuilder::current_tex_vertex()
337 return tex_vertex_
[tex_vertex_
.size() - 1];
340 std::shared_ptr
<CTexVertex
>& CTopologyBuilder::tex_vertex(int i
)
342 return tex_vertex_
[i
];
345 CFacet
* CTopologyBuilder::current_facet()
347 return current_facet_
;
350 CHalfedge
* CTopologyBuilder::new_halfedge_between(CVertex
* from
, CVertex
* to
)
354 // Non-manifold edges have been removed
355 // by the higher level public functions.
356 // Let us do a sanity check anyway ...
357 assert(find_halfedge_between(from
, to
) == NULL
);
359 CHalfedge
* result
= target_
->new_halfedge();
360 CTopologyGraphMutator::set_halfedge_facet(result
, current_facet_
);
361 CTopologyGraphMutator::set_halfedge_vertex(result
, to
);
363 CHalfedge
* opposite
= find_halfedge_between(to
, from
);
364 if(opposite
!= NULL
) {
365 CTopologyGraphMutator::link(result
, opposite
, 2);
368 star_
[from
].push_back(result
);
369 CTopologyGraphMutator::set_vertex_halfedge(to
, result
);
374 CHalfedge
* CTopologyBuilder::find_halfedge_between(CVertex
* from
, CVertex
* to
)
376 Star
& star
= star_
[from
];
377 for(Star::iterator it
= star
.begin(); it
!= star
.end(); it
++)
379 CHalfedge
* cur
= *it
;
380 if(cur
-> vertex() == to
)
386 bool CTopologyBuilder::vertex_is_manifold(CVertex
* v
)
388 if(v
->halfedge() == NULL
)
390 // Isolated vertex, removed in subsequent steps
394 // A vertex is manifold if the stored and the
395 // computed stars match (the number of halfedges
397 // Note: this test is valid only if the borders
398 // have been constructed.
400 return (int(star_
[v
].size()) == v
->degree());
403 bool CTopologyBuilder::split_non_manifold_vertex(CVertex
* v
)
405 if(vertex_is_manifold(v
))
410 std::set
<CHalfedge
*> star
;
411 for(unsigned int i
=0; i
<star_
[v
].size(); i
++)
413 star
.insert(star_
[v
][i
]);
416 // For the first wedge, reuse the vertex
417 disconnect_vertex(v
->halfedge()->opposite(), v
, star
);
419 // There should be other wedges (else the vertex
420 // would have been manifold)
421 assert(!star
.empty());
425 // Create the vertices for the remaining wedges.
428 CVertex
* new_v
= copy_vertex(v
);
429 is_locked
[new_v
] = true;
430 CHalfedge
* h
= *(star
.begin());
431 disconnect_vertex(h
, new_v
, star
);
439 void CTopologyBuilder::disconnect_vertex(CHalfedge
* start_in
, CVertex
* v
, std::set
<CHalfedge
*>& star
)
441 CHalfedge
* start
= start_in
;
445 // Important note: in this class, all the Stars correspond to the
446 // set of halfedges radiating FROM a vertex (i.e. h->vertex() != v
447 // if h belongs to Star(v) ).
449 assert(star
.find(start
) != star
.end());
452 // Note: the following code needs a special handling
453 // of borders, since borders are not correctly connected
454 // in a non-manifold vertex (the standard next_around_vertex
455 // iteration does not traverse the whole star)
457 while(!start
->is_border())
459 start
= start
->prev()->opposite();
460 if(start
== start_in
)
463 CTopologyGraphMutator::set_vertex_halfedge(v
,start
->opposite());
465 CHalfedge
* cur
= start
;
466 CTopologyGraphMutator::set_halfedge_vertex(cur
->opposite(), v
);
467 star_
[v
].push_back(cur
);
468 std::set
<CHalfedge
*>::iterator it
= star
.find(cur
);
469 assert(it
!= star
.end());
472 while(!cur
->opposite()->is_border())
474 cur
= cur
->opposite()->next();
477 CTopologyGraphMutator::set_halfedge_vertex(cur
->opposite(), v
);
478 std::set
<CHalfedge
*>::iterator it
= star
.find(cur
);
479 assert(it
!= star
.end());
481 star_
[v
].push_back(cur
);
484 if(start
->is_border())
486 CTopologyGraphMutator::link(cur
->opposite(),start
,1);
491 void CTopologyBuilder::terminate_surface()
494 // Step 1 : create the border halfedges, and setup the 'opposite'
495 // and 'vertex' pointers.
496 std::vector
<CHalfedge
*> halfedgelist
;
497 FOR_EACH_HALFEDGE(CTopologyGraph
, target_
, it
)
499 halfedgelist
.push_back(*it
);
501 for (std::vector
<CHalfedge
*>::iterator it
= halfedgelist
.begin();it
!= halfedgelist
.end();it
++)
503 if((*it
)-> opposite() == NULL
)
505 CHalfedge
* h
= target_
->new_halfedge();
506 CTopologyGraphMutator::link(h
, *it
, 2);
507 CTopologyGraphMutator::set_halfedge_vertex(h
, (*it
)-> prev()-> vertex());
509 // Initialize texture coordinates
510 CTopologyGraphMutator::set_halfedge_tex_vertex(h
, (*it
)-> prev()-> tex_vertex());
512 // Used later to fix non-manifold vertices.
513 star_
[ (*it
)-> vertex() ].push_back(h
);
517 // Step 2 : setup the 'next' and 'prev' pointers of the border.
519 FOR_EACH_HALFEDGE(CTopologyGraph
, target_
, it
)
521 if((*it
)-> facet() == NULL
)
524 CHalfedge
* next
= (*it
)-> opposite();
525 while(next
-> facet() != NULL
)
527 next
= next
-> prev()-> opposite();
529 CTopologyGraphMutator::set_halfedge_next(*it
, next
);
531 CHalfedge
* prev
= (*it
)-> opposite();
532 while(prev
-> facet() != NULL
)
534 prev
= prev
-> next()-> opposite();
536 CTopologyGraphMutator::set_halfedge_prev(*it
, prev
);
540 // Step 3 : fix non-manifold vertices
542 for(unsigned int i
=0; i
<vertex_
.size(); i
++)
544 if(vertex_
[i
] == NULL
) {
547 if(split_non_manifold_vertex(vertex_
[i
]))
549 nb_non_manifold_v_
++;
554 // Step 4 : create TexVertices
556 FOR_EACH_HALFEDGE(CTopologyGraph
, target_
, it
)
558 if((*it
)->tex_vertex() == NULL
)
560 std::shared_ptr
<CTexVertex
>& new_tv
= std::shared_ptr
<CTexVertex
>(target_
->new_tex_vertex());
561 CHalfedge
* cur
= *it
;
564 CTopologyGraphMutator::set_halfedge_tex_vertex(cur
, new_tv
);
565 cur
= cur
-> next()-> opposite();
567 while(cur
-> tex_vertex() == NULL
);
568 cur
= (*it
)-> opposite()-> prev();
569 while((*it
)-> tex_vertex() == NULL
)
571 CTopologyGraphMutator::set_halfedge_tex_vertex(cur
, new_tv
);
572 cur
= cur
-> opposite()-> prev();
577 // Step 5 : check for isolated vertices
578 for(unsigned int i
=0; i
<vertex_
.size(); i
++)
580 if(vertex_
[i
] == NULL
)
584 if(star_
[vertex_
[i
]].size() == 0)
587 target_
->delete_vertex(vertex_
[i
]);
591 target_
->assert_is_valid();
594 void CTopologyBuilder::transition(EState from
, EState to
)
600 void CTopologyBuilder::check_state(EState s
)
604 CryLog("MapBuilder invalid state: '%s' , expected '%s'",state_to_string(state_
),state_to_string(s
));
610 std::string
CTopologyBuilder::state_to_string(EState s
)
628 void CTopologyBuilder::set_vertex(unsigned int v
, const Vec3d
& p
)
630 vertex(v
)->set_point(p
);
634 void CTopologyBuilder::create_vertices(unsigned int nb_v
, bool with_colors
)
636 for(unsigned int i
=0; i
<nb_v
; i
++)
638 add_vertex(Vec3d(0.0, 0.0, 0.0)) ;