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;
 double compute_angle() const
Returns the overall angle subtended by the fan, from the leading edge to the trailing edge,...
EggVertex * add_vertex(EggVertex *vertex, int index=-1)
Adds the indicated vertex to the pool.
A base class for nodes in the hierarchy that are not leaf nodes.
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...
void copy_attributes(const EggAttributes &other)
Copies the rendering attributes from the indicated primitive.
LVertexd get_pos3() const
Valid if get_num_dimensions() returns 3 or 4.
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,...
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
const EggMesherEdge * find_opposite_edge(int vi) const
Returns the first edge found that does not contain the given vertex.
This class is used by EggMesher::find_fans() to attempt to make an EggTriangleFan out of the polygons...
Collects together unrelated EggPrimitives, determines their edge connectivity, and generates a set of...
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
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.
Represents one edge of a triangle, as used by the EggMesher to discover connected triangles.
EggNode * add_child(EggNode *node)
Adds the indicated child to the group and returns it.
Represents a triangle strip or quad strip in progress, as assembled by the mesher.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
bool join(EggMesherFanMaker &other)
Attempts to connect two fans end-to-end.
bool is_valid() const
Returns true if the fan maker has enough edges to define at least one fan, false otherwise.
A collection of vertices.