27 if (edge !=
nullptr) {
28 _edges.push_back(edge);
30 _strips.push_back(tri);
31 _planar = tri->_planar;
40 _vertex(copy._vertex),
42 _strips(copy._strips),
43 _planar(copy._planar),
51 void EggMesherFanMaker::
53 _vertex = copy._vertex;
55 _strips = copy._strips;
56 _planar = copy._planar;
57 _mesher = copy._mesher;
69 nassertr(_vertex == other._vertex,
false);
70 nassertr(_mesher == other._mesher,
false);
72 nassertr(!_edges.empty() && !other._edges.empty(),
false);
76 nassertr(my_back !=
nullptr &&
77 other_front !=
nullptr,
false);
79 int my_back_b = my_back->_vi_b;
80 int other_front_a = other_front->_vi_a;
82 if (my_back_b == other_front_a) {
84 _edges.splice(_edges.end(), other._edges);
85 _strips.splice(_strips.end(), other._strips);
91 nassertr(my_front !=
nullptr &&
92 other_back !=
nullptr,
false);
94 int my_front_a = my_front->_vi_a;
95 int other_back_b = other_back->_vi_b;
97 if (my_front_a == other_back_b) {
99 _edges.splice(_edges.begin(), other._edges);
100 _strips.splice(_strips.begin(), other._strips);
123 Edges::const_iterator ei;
124 for (ei = _edges.begin(); ei != _edges.end(); ++ei) {
130 angle += acos(dot(v1, v2));
133 return rad_2_deg(angle);
149 nassertr(_edges.size() == _strips.size(), 0);
151 int num_tris = _edges.size();
153 double avg_angle = net_angle / (double)num_tris;
155 if (avg_angle > egg_max_tfan_angle) {
161 if (egg_min_tfan_tris == 0 || num_tris < egg_min_tfan_tris) {
163 if (!egg_unroll_fans) {
178 Strips::iterator si, last_si;
179 Edges::iterator ei, last_ei;
184 si = _strips.begin();
188 int found_seam =
false;
190 for (++si, ++ei; si != _strips.end() && !found_seam; ++si, ++ei) {
191 nassertr(ei != _edges.end(), 0);
192 if ( ((*si)->_prims.front()->compare_to(*(*last_si)->_prims.front()) != 0) ||
193 !(*si)->is_coplanar_with(*(*last_si), egg_coplanar_threshold)) {
196 _edges.splice(_edges.begin(), _edges, ei, _edges.end());
197 _strips.splice(_strips.begin(), _strips, si, _strips.end());
202 si = _strips.begin();
208 for (++si, ++ei; si != _strips.end(); ++si, ++ei) {
209 nassertr(ei != _edges.end(), 0);
210 if ( ((*si)->_prims.front()->compare_to(*(*last_si)->_prims.front()) != 0) ||
211 !(*si)->is_coplanar_with(*(*last_si), egg_coplanar_threshold)) {
213 count +=
unroll(last_si, si, last_ei, ei, unrolled_tris);
218 count +=
unroll(last_si, si, last_ei, ei, unrolled_tris);
223 EggMesherStrip new_fan(EggMesherStrip::PT_trifan, EggMesherStrip::MO_fanpoly);
224 new_fan._verts.push_back(_vertex);
226 new_fan._verts.push_back(_edges.front()->_vi_a);
228 for (ei = _edges.begin(); ei != _edges.end(); ++ei) {
229 new_fan._verts.push_back((*ei)->_vi_b);
233 for (si = _strips.begin(); si != _strips.end(); ++si) {
234 new_fan._prims.splice(new_fan._prims.end(), (*si)->_prims);
235 (*si)->remove_all_edges();
236 (*si)->_verts.clear();
237 (*si)->_status = EggMesherStrip::MS_dead;
242 nassertr(new_fan._verts.size() == new_fan._prims.size() + 2, 0);
246 _mesher->_done.push_back(new_fan);
259 unroll(Strips::iterator strip_begin, Strips::iterator strip_end,
260 Edges::iterator edge_begin, Edges::iterator edge_end,
266 for (ei = edge_begin; ei != edge_end; ++ei) {
284 if ((*ei)->_vi_b != (*edge_begin)->_vi_a) {
288 poly->add_vertex(vertex_pool->
get_vertex((*edge_begin)->_vi_a));
291 for (ei = edge_begin; ei != edge_end; ++ei) {
292 poly->add_vertex(vertex_pool->
get_vertex((*ei)->_vi_b));
297 if (egg_show_quads) {
308 result = poly->triangulate_into(unrolled_tris,
true);
313 for (si = strip_begin; si != strip_end; ++si) {
314 (*si)->remove_all_edges();
315 (*si)->_verts.clear();
316 (*si)->_prims.clear();
317 (*si)->_status = EggMesherStrip::MS_dead;
328 void EggMesherFanMaker::
329 output(std::ostream &out)
const {
330 out << _vertex <<
":[";
331 if (!_edges.empty()) {
332 Edges::const_iterator ei;
333 for (ei = _edges.begin(); ei != _edges.end(); ++ei) {
334 out <<
" " << (*ei)->_vi_a;
336 out <<
" " << _edges.back()->_vi_b;
A base class for nodes in the hierarchy that are not leaf nodes.
EggNode * add_child(EggNode *node)
Adds the indicated child to the group and returns it.
Represents one edge of a triangle, as used by the EggMesher to discover connected triangles.
This class is used by EggMesher::find_fans() to attempt to make an EggTriangleFan out of the polygons...
double compute_angle() const
Returns the overall angle subtended by the fan, from the leading edge to the trailing edge,...
bool join(EggMesherFanMaker &other)
Attempts to connect two fans end-to-end.
int unroll(Strips::iterator strip_begin, Strips::iterator strip_end, Edges::iterator edge_begin, Edges::iterator edge_end, EggGroupNode *unrolled_tris)
Unrolls a planar subset of the current working fan, defined by the given iterators,...
int build(EggGroupNode *unrolled_tris)
Begins the fanning process.
bool is_coplanar_with(const EggMesherFanMaker &other) const
Returns true if the strip and the other strip are coplanar.
bool is_valid() const
Returns true if the fan maker has enough edges to define at least one fan, false otherwise.
Represents a triangle strip or quad strip in progress, as assembled by the mesher.
const EggMesherEdge * find_opposite_edge(int vi) const
Returns the first edge found that does not contain the given vertex.
Collects together unrelated EggPrimitives, determines their edge connectivity, and generates a set of...
void copy_attributes(const EggAttributes &other)
Copies the rendering attributes from the indicated primitive.
A collection of vertices.
EggVertex * get_vertex(int index) const
Returns the vertex in the pool with the indicated index number, or NULL if no vertices have that inde...
EggVertex * add_vertex(EggVertex *vertex, int index=-1)
Adds the indicated vertex to the pool.
LVertexd get_pos3() const
Valid if get_num_dimensions() returns 3 or 4.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.