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