00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include "eggMesherFanMaker.h"
00016 #include "eggMesher.h"
00017 #include "eggPolygon.h"
00018 #include "eggGroupNode.h"
00019
00020
00021
00022
00023
00024
00025 EggMesherFanMaker::
00026 EggMesherFanMaker(int vertex, EggMesherStrip *tri,
00027 EggMesher *mesher) {
00028 _vertex = vertex;
00029 const EggMesherEdge *edge = tri->find_opposite_edge(vertex);
00030 if (edge != (const EggMesherEdge *)NULL) {
00031 _edges.push_back(edge);
00032 }
00033 _strips.push_back(tri);
00034 _planar = tri->_planar;
00035 _mesher = mesher;
00036 }
00037
00038
00039
00040
00041
00042
00043 EggMesherFanMaker::
00044 EggMesherFanMaker(const EggMesherFanMaker ©) :
00045 _vertex(copy._vertex),
00046 _edges(copy._edges),
00047 _strips(copy._strips),
00048 _planar(copy._planar),
00049 _mesher(copy._mesher)
00050 {
00051 }
00052
00053
00054
00055
00056
00057
00058 void EggMesherFanMaker::
00059 operator = (const EggMesherFanMaker ©) {
00060 _vertex = copy._vertex;
00061 _edges = copy._edges;
00062 _strips = copy._strips;
00063 _planar = copy._planar;
00064 _mesher = copy._mesher;
00065 }
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076 bool EggMesherFanMaker::
00077 join(EggMesherFanMaker &other) {
00078 nassertr(_vertex == other._vertex, false);
00079 nassertr(_mesher == other._mesher, false);
00080
00081 nassertr(!_edges.empty() && !other._edges.empty(), false);
00082
00083 const EggMesherEdge *my_back = _edges.back();
00084 const EggMesherEdge *other_front = other._edges.front();
00085 nassertr(my_back != (EggMesherEdge *)NULL &&
00086 other_front != (EggMesherEdge *)NULL, false);
00087
00088 int my_back_b = my_back->_vi_b;
00089 int other_front_a = other_front->_vi_a;
00090
00091 if (my_back_b == other_front_a) {
00092 _planar = is_coplanar_with(other);
00093 _edges.splice(_edges.end(), other._edges);
00094 _strips.splice(_strips.end(), other._strips);
00095 return true;
00096 }
00097
00098 const EggMesherEdge *my_front = _edges.front();
00099 const EggMesherEdge *other_back = other._edges.back();
00100 nassertr(my_front != (EggMesherEdge *)NULL &&
00101 other_back != (EggMesherEdge *)NULL, false);
00102
00103 int my_front_a = my_front->_vi_a;
00104 int other_back_b = other_back->_vi_b;
00105
00106 if (my_front_a == other_back_b) {
00107 _planar = is_coplanar_with(other);
00108 _edges.splice(_edges.begin(), other._edges);
00109 _strips.splice(_strips.begin(), other._strips);
00110 return true;
00111 }
00112
00113 return false;
00114 }
00115
00116
00117
00118
00119
00120
00121
00122 double EggMesherFanMaker::
00123 compute_angle() const {
00124
00125
00126
00127 nassertr(is_valid(), 0.0);
00128
00129 EggVertexPool *vertex_pool = _mesher->_vertex_pool;
00130
00131 double angle = 0.0;
00132 LPoint3d v0 = vertex_pool->get_vertex(_vertex)->get_pos3();
00133
00134 Edges::const_iterator ei;
00135 for (ei = _edges.begin(); ei != _edges.end(); ++ei) {
00136 LVector3d v1 = vertex_pool->get_vertex((*ei)->_vi_a)->get_pos3() - v0;
00137 LVector3d v2 = vertex_pool->get_vertex((*ei)->_vi_b)->get_pos3() - v0;
00138
00139 v1 = normalize(v1);
00140 v2 = normalize(v2);
00141 angle += acos(dot(v1, v2));
00142 }
00143
00144 return rad_2_deg(angle);
00145 }
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162 int EggMesherFanMaker::
00163 build(EggGroupNode *unrolled_tris) {
00164 nassertr(_edges.size() == _strips.size(), 0);
00165
00166 int num_tris = _edges.size();
00167 double net_angle = compute_angle();
00168 double avg_angle = net_angle / (double)num_tris;
00169
00170 if (avg_angle > egg_max_tfan_angle) {
00171
00172
00173 return 0;
00174 }
00175
00176 if (egg_min_tfan_tris == 0 || num_tris < egg_min_tfan_tris) {
00177
00178 if (!egg_unroll_fans) {
00179 return 0;
00180 }
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193 Strips::iterator si, last_si;
00194 Edges::iterator ei, last_ei;
00195
00196
00197
00198
00199 si = _strips.begin();
00200 last_si = si;
00201 ei = _edges.begin();
00202 last_ei = ei;
00203 int found_seam = false;
00204
00205 for (++si, ++ei; si != _strips.end() && !found_seam; ++si, ++ei) {
00206 nassertr(ei != _edges.end(), 0);
00207 if ( ((*si)->_prims.front()->compare_to(*(*last_si)->_prims.front()) != 0) ||
00208 !(*si)->is_coplanar_with(*(*last_si), egg_coplanar_threshold)) {
00209
00210 found_seam = true;
00211 _edges.splice(_edges.begin(), _edges, ei, _edges.end());
00212 _strips.splice(_strips.begin(), _strips, si, _strips.end());
00213 }
00214 }
00215
00216
00217
00218 si = _strips.begin();
00219 last_si = si;
00220 ei = _edges.begin();
00221 last_ei = ei;
00222
00223 int count = 0;
00224 for (++si, ++ei; si != _strips.end(); ++si, ++ei) {
00225 nassertr(ei != _edges.end(), 0);
00226 if ( ((*si)->_prims.front()->compare_to(*(*last_si)->_prims.front()) != 0) ||
00227 !(*si)->is_coplanar_with(*(*last_si), egg_coplanar_threshold)) {
00228
00229 count += unroll(last_si, si, last_ei, ei, unrolled_tris);
00230 last_si = si;
00231 last_ei = ei;
00232 }
00233 }
00234 count += unroll(last_si, si, last_ei, ei, unrolled_tris);
00235
00236 return count;
00237
00238 } else {
00239 EggMesherStrip new_fan(EggMesherStrip::PT_trifan, EggMesherStrip::MO_fanpoly);
00240 new_fan._verts.push_back(_vertex);
00241
00242 new_fan._verts.push_back(_edges.front()->_vi_a);
00243 Edges::iterator ei;
00244 for (ei = _edges.begin(); ei != _edges.end(); ++ei) {
00245 new_fan._verts.push_back((*ei)->_vi_b);
00246 }
00247
00248 Strips::iterator si;
00249 for (si = _strips.begin(); si != _strips.end(); ++si) {
00250 new_fan._prims.splice(new_fan._prims.end(), (*si)->_prims);
00251 (*si)->remove_all_edges();
00252 (*si)->_verts.clear();
00253 (*si)->_status = EggMesherStrip::MS_dead;
00254 }
00255
00256
00257
00258
00259 nassertr(new_fan._verts.size() == new_fan._prims.size() + 2, 0);
00260
00261
00262
00263 _mesher->_done.push_back(new_fan);
00264 }
00265
00266 return 1;
00267 }
00268
00269
00270
00271
00272
00273
00274
00275
00276
00277
00278
00279 int EggMesherFanMaker::
00280 unroll(Strips::iterator strip_begin, Strips::iterator strip_end,
00281 Edges::iterator edge_begin, Edges::iterator edge_end,
00282 EggGroupNode *unrolled_tris) {
00283 Edges::iterator ei;
00284 Strips::iterator si;
00285
00286 int num_tris = 0;
00287 for (ei = edge_begin; ei != edge_end; ++ei) {
00288 num_tris++;
00289 }
00290
00291 if (num_tris < 3) {
00292
00293 return 0;
00294 }
00295
00296 PT(EggPolygon) poly = new EggPolygon;
00297
00298
00299
00300 poly->copy_attributes(*(*strip_begin)->_prims.front());
00301 EggVertexPool *vertex_pool = _mesher->_vertex_pool;
00302
00303 ei = edge_end;
00304 --ei;
00305 if ((*ei)->_vi_b != (*edge_begin)->_vi_a) {
00306
00307
00308
00309 poly->add_vertex(vertex_pool->get_vertex(_vertex));
00310 poly->add_vertex(vertex_pool->get_vertex((*edge_begin)->_vi_a));
00311 }
00312
00313 for (ei = edge_begin; ei != edge_end; ++ei) {
00314 poly->add_vertex(vertex_pool->get_vertex((*ei)->_vi_b));
00315 }
00316
00317 bool result = true;
00318
00319 if (egg_show_quads) {
00320
00321
00322
00323
00324
00325
00326
00327 unrolled_tris->add_child(poly);
00328
00329 } else {
00330
00331 result = poly->triangulate_into(unrolled_tris, true);
00332 }
00333
00334 if (result) {
00335
00336 for (si = strip_begin; si != strip_end; ++si) {
00337 (*si)->remove_all_edges();
00338 (*si)->_verts.clear();
00339 (*si)->_prims.clear();
00340 (*si)->_status = EggMesherStrip::MS_dead;
00341 }
00342 return 1;
00343 } else {
00344 return 0;
00345 }
00346 }
00347
00348
00349
00350
00351
00352
00353 void EggMesherFanMaker::
00354 output(ostream &out) const {
00355 out << _vertex << ":[";
00356 if (!_edges.empty()) {
00357 Edges::const_iterator ei;
00358 for (ei = _edges.begin(); ei != _edges.end(); ++ei) {
00359 out << " " << (*ei)->_vi_a;
00360 }
00361 out << " " << _edges.back()->_vi_b;
00362 }
00363 out << " ]";
00364
00365 if (_planar) {
00366 out << " (planar)";
00367 }
00368 }