00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032 #ifndef PolygonSimplifier_INCLUDE_ONCE
00033 #define PolygonSimplifier_INCLUDE_ONCE
00034
00035 #include <vlCore/Object.hpp>
00036 #include <vlCore/Vector3.hpp>
00037 #include <vlCore/GLSLmath.hpp>
00038 #include <vlGraphics/link_config.hpp>
00039 #include <vector>
00040 #include <algorithm>
00041
00042 namespace vl
00043 {
00044 class Geometry;
00045
00046
00047
00052 class VLGRAPHICS_EXPORT PolygonSimplifier: public Object
00053 {
00054 public:
00055 class Vertex;
00056
00057
00058
00060 class QErr
00061 {
00062 public:
00063 QErr()
00064 {
00065 a2 = 0.0;
00066 ab = 0.0;
00067 ac = 0.0;
00068 ad = 0.0;
00069 b2 = 0.0;
00070 bc = 0.0;
00071 bd = 0.0;
00072 c2 = 0.0;
00073 cd = 0.0;
00074 d2 = 0.0;
00075 }
00076
00077 QErr(const dvec3& n, double d, double w = 1.0)
00078 {
00079 a2 = w * n.x() * n.x();
00080 ab = w * n.x() * n.y();
00081 ac = w * n.x() * n.z();
00082 ad = w * n.x() * d;
00083 b2 = w * n.y() * n.y();
00084 bc = w * n.y() * n.z();
00085 bd = w * n.y() * d;
00086 c2 = w * n.z() * n.z();
00087 cd = w * n.z() * d;
00088 d2 = w * d*d;
00089
00090
00091 VL_CHECK( d2 == d2 )
00092 }
00093
00094 dmat3 matrix() const
00095 {
00096 return dmat3(
00097 a2, ab, ac,
00098 ab, b2, bc,
00099 ac, bc, c2 );
00100 }
00101
00102 dvec3 vector() const
00103 {
00104 return dvec3( ad, bd, cd );
00105 }
00106
00107 double offset() const
00108 {
00109 return d2;
00110 }
00111
00112 double evaluate(const dvec3& v) const
00113 {
00114 return v.x()*v.x()*a2 + 2*v.x()*v.y()*ab + 2*v.x()*v.z()*ac + 2*v.x()*ad
00115 + v.y()*v.y()*b2 + 2*v.y()*v.z()*bc + 2*v.y()*bd
00116 + v.z()*v.z()*c2 + 2*v.z()*cd
00117 + d2;
00118 }
00119
00120 bool analyticSolution(dvec3& v) const
00121 {
00122 #if 0
00123 dmat3 Ainv;
00124 double det = matrix().getInverse(Ainv);
00125 if (!det)
00126 return false;
00127 v = -(Ainv*vector());
00128 return true;
00129 #else
00130 double A = c2*b2-bc*bc;
00131 double B = bc*ac-c2*ab;
00132 double C = bc*ab-b2*ac;
00133 double det = a2*(A)+ab*(B)+ac*(C);
00134 if (fabs(det) < 0.0000001)
00135 return false;
00136 else
00137 {
00138 double inv_det = 1.0 / det;
00139 dmat3 Ainv( A*inv_det, B*inv_det, C*inv_det,
00140 (ac*bc-c2*ab)*inv_det, (c2*a2-ac*ac)*inv_det, (ab*ac-bc*a2)*inv_det,
00141 (bc*ab-ac*b2)*inv_det, (ac*ab-bc*a2)*inv_det, (b2*a2-ab*ab)*inv_det );
00142 v = Ainv * dvec3( -ad, -bd, -cd );
00143 return true;
00144 }
00145 #endif
00146 }
00147
00148 QErr operator+(const QErr& other)
00149 {
00150 QErr q = *this;
00151 q.a2 += other.a2;
00152 q.ab += other.ab;
00153 q.ac += other.ac;
00154 q.ad += other.ad;
00155 q.b2 += other.b2;
00156 q.bc += other.bc;
00157 q.bd += other.bd;
00158 q.c2 += other.c2;
00159 q.cd += other.cd;
00160 q.d2 += other.d2;
00161 return q;
00162 }
00163
00164 const QErr& operator+=(const QErr& other)
00165 {
00166 a2 += other.a2;
00167 ab += other.ab;
00168 ac += other.ac;
00169 ad += other.ad;
00170 b2 += other.b2;
00171 bc += other.bc;
00172 bd += other.bd;
00173 c2 += other.c2;
00174 cd += other.cd;
00175 d2 += other.d2;
00176 return *this;
00177 }
00178
00179 protected:
00180
00181 double a2, ab, ac, ad;
00182 double b2, bc, bd;
00183 double c2, cd;
00184 double d2;
00185 };
00186
00187
00188
00190 class Triangle
00191 {
00192 friend class PolygonSimplifier;
00193 friend class Vertex;
00194 public:
00195 Triangle(): mRemoved(false)
00196 {
00197 mVertices[0] = NULL;
00198 mVertices[1] = NULL;
00199 mVertices[2] = NULL;
00200 }
00201
00202 inline void replaceVertex( Vertex* oldv, Vertex* newv );
00203 inline void computeNormal();
00204 inline float computeArea() const;
00205 inline float computePotentialArea(const Vertex* oldv, const Vertex* newv) const;
00206 inline fvec3 computePotentialNormal(const Vertex* oldv, const Vertex* newv) const;
00207 inline bool hasVertex(const Vertex*v) const;
00208 inline bool checkTriangle() const;
00209
00210 inline QErr computeQErr() const;
00211
00213 const Vertex* vertex(int index) const { return mVertices[index]; }
00214 Vertex* vertex(int index) { return mVertices[index]; }
00216 const fvec3& normal() const { return mNormal; }
00218
00220 bool removed() const { return mRemoved; }
00222
00223 protected:
00225 Vertex* mVertices[3];
00227 fvec3 mNormal;
00229
00231 bool mRemoved;
00232 };
00233
00234
00235
00237 class Vertex
00238 {
00239 friend class Triangle;
00240 friend class PolygonSimplifier;
00241 public:
00242 Vertex(): mCollapseCost(0.0f), mOriginalIndex(-1) , mSimplifiedIndex(-1), mRemoveOrder(-1),
00243 mRemoved(false), mProtected(false), mAlreadyProcessed(false)
00244 {
00245 }
00246
00247 inline void addAdjacentVertex(Vertex* v);
00248 inline void removeAdjacentVertex(Vertex* v);
00249 inline void computeAdjacentVertices();
00250 inline bool checkConnectivity();
00251 inline bool isAdjacentVertex(Vertex*) const;
00252 inline bool isIncidentTriangle(Triangle*) const;
00253 inline void discardRemovedTriangles();
00254 inline void removeIncidentTriangle(const Triangle*);
00255 inline bool checkTriangles() const;
00256 inline void computeEdgePenalty();
00257
00259 const fvec3& position() const { return mPosition; }
00261 int adjacentVerticesCount() const { return (int)mAdjacentVerts.size(); }
00262 Vertex* adjacentVertex(int index) const { return mAdjacentVerts[index]; }
00264 int incidentTrianglesCount() const { return (int)mIncidentTriangles.size(); }
00265 Triangle* incidentTriangle(int index) const { return mIncidentTriangles[index]; }
00267 Vertex* collapseVertex() const { return mCollapseVertex; }
00269 float collapseCost() const { return mCollapseCost; }
00271 const fvec3& collapsePosition() const { return mCollapsePosition; }
00272 void setCollapsePosition(const fvec3& pos) { mCollapsePosition = pos; }
00274 int removeOrder() const { return mRemoveOrder; }
00276 bool removed() const { return mRemoved; }
00278 bool isProtected() const { return mProtected; }
00280 int originalIndex() const { return mOriginalIndex; }
00282 int simplifiedIndex() const { return mSimplifiedIndex; }
00284 bool alreadyProcessed() const { return mAlreadyProcessed; }
00286 const QErr& qerr() const { return mQErr; }
00287 void setQErr(const QErr& qerr) { mQErr = qerr; }
00288 void addQErr(const QErr& qerr) { mQErr += qerr; }
00289
00290 protected:
00291 QErr mQErr;
00293 fvec3 mPosition;
00295 std::vector< Vertex* > mAdjacentVerts;
00297 std::vector< Triangle* > mIncidentTriangles;
00299 Vertex* mCollapseVertex;
00301 float mCollapseCost;
00303 fvec3 mCollapsePosition;
00305 int mOriginalIndex;
00307 int mSimplifiedIndex;
00309 int mRemoveOrder;
00311 bool mRemoved;
00313 bool mProtected;
00315 bool mAlreadyProcessed;
00316 };
00317
00318 public:
00319 PolygonSimplifier(): mRemoveDoubles(false), mVerbose(true), mQuick(true) {}
00320
00321 virtual const char* className() { return "vl::PolygonSimplifier"; }
00322
00323 void simplify(float simplification_ratio, Geometry* geom);
00324 void simplify(int target_vertex_count, Geometry* geom);
00325 void simplify(int target_vertex_count, std::vector<fvec3>& in_out_verts, std::vector<int>& in_out_tris);
00326
00327 void setProtectedVertices(const std::vector<int>& protected_verts) { mProtectedVerts = protected_verts; }
00328
00329 int simplifiedVerticesCount() const { return (int)mSimplifiedVertices.size(); }
00330 Vertex* simplifiedVertices(int index) const { return mSimplifiedVertices[index]; }
00331
00332 int simplifiedTrianglesCount() const { return (int)mSimplifiedTriangles.size(); }
00333 Triangle* simplifiedTriangles(int index) const { return mSimplifiedTriangles[index]; }
00334
00335 void clearTrianglesAndVertices();
00336
00337 bool removeDoubles() const { return mRemoveDoubles; }
00338 void setRemoveDoubles(bool remove_doubles) { mRemoveDoubles = remove_doubles; }
00339
00340 bool verbose() const { return mVerbose; }
00341 void setVerbose(bool verbose) { mVerbose = verbose; }
00342
00343 bool quick() const { return mQuick; }
00344 void setQuick(bool quick) { mQuick = quick; }
00345
00346 protected:
00347 inline void collapse(Vertex* v);
00348 inline void computeCollapseInfo(Vertex* v);
00349
00350 protected:
00351 std::vector<Vertex*> mSimplifiedVertices;
00352 std::vector<Triangle*> mSimplifiedTriangles;
00353 std::vector<int> mProtectedVerts;
00354 bool mRemoveDoubles;
00355 bool mVerbose;
00356 bool mQuick;
00357
00358 private:
00359 std::vector<Triangle> mTriangleLump;
00360 std::vector<Vertex> mVertexLump;
00361 };
00362
00363
00364
00365 inline void PolygonSimplifier::Vertex::addAdjacentVertex(Vertex* v)
00366 {
00367 if( v != this )
00368 {
00369 for(int i=0; i<adjacentVerticesCount(); ++i)
00370 if (mAdjacentVerts[i] == v)
00371 return;
00372 mAdjacentVerts.push_back(v);
00373 }
00374 }
00375
00376 inline void PolygonSimplifier::Vertex::removeAdjacentVertex(Vertex* v)
00377 {
00378 VL_CHECK( v != this )
00379 VL_CHECK( std::find(mAdjacentVerts.begin(), mAdjacentVerts.end(), v) != mAdjacentVerts.end() )
00380 for(int i=0; i<adjacentVerticesCount(); ++i)
00381 if (mAdjacentVerts[i] == v)
00382 {
00383 mAdjacentVerts.erase(mAdjacentVerts.begin() + i);
00384 return;
00385 }
00386 }
00387
00388 inline void PolygonSimplifier::Vertex::computeAdjacentVertices()
00389 {
00390 mAdjacentVerts.clear();
00391 for(int itri=0; itri<incidentTrianglesCount(); ++itri)
00392 {
00393 VL_CHECK(!mIncidentTriangles[itri]->mRemoved)
00394 addAdjacentVertex( mIncidentTriangles[itri]->mVertices[0] );
00395 addAdjacentVertex( mIncidentTriangles[itri]->mVertices[1] );
00396 addAdjacentVertex( mIncidentTriangles[itri]->mVertices[2] );
00397 }
00398 mRemoved = mAdjacentVerts.empty();
00399 }
00400
00401 inline bool PolygonSimplifier::Vertex::checkTriangles() const
00402 {
00403 for(int itri=incidentTrianglesCount(); itri--; )
00404 if ( !incidentTriangle(itri)->checkTriangle() )
00405 return false;
00406 return true;
00407 }
00408
00409 inline void PolygonSimplifier::Vertex::computeEdgePenalty()
00410 {
00411 for(int ivert=0; ivert<adjacentVerticesCount(); ++ivert)
00412 {
00413 int edge_count = 0;
00414 int border_tri = -1;
00415 for(int itri=0; itri<incidentTrianglesCount() && edge_count<=1; ++itri)
00416 {
00417 if ( incidentTriangle(itri)->hasVertex( adjacentVertex(ivert) ) )
00418 {
00419 border_tri = itri;
00420 ++edge_count;
00421 }
00422 }
00423 if ( edge_count == 1 )
00424 {
00425 fvec3 edge = position() - adjacentVertex(ivert)->position();
00426 dvec3 n = (dvec3)cross(incidentTriangle(border_tri)->normal(), edge );
00427 n.normalize();
00428 double d = -dot(n,(dvec3)position());
00429 mQErr += QErr( n, d, dot(edge, edge) * 1.0 );
00430 }
00431 }
00432 }
00433 inline void PolygonSimplifier::Vertex::removeIncidentTriangle(const Triangle* tri)
00434 {
00435 for(int itri=incidentTrianglesCount(); itri--; )
00436 {
00437 if (mIncidentTriangles[itri] == tri)
00438 {
00439 mIncidentTriangles.erase( mIncidentTriangles.begin() + itri );
00440 break;
00441 }
00442 }
00443 }
00444
00445 inline void PolygonSimplifier::Vertex::discardRemovedTriangles()
00446 {
00447 for(int itri=incidentTrianglesCount(); itri--; )
00448 {
00449 if (mIncidentTriangles[itri]->mRemoved)
00450 mIncidentTriangles.erase( mIncidentTriangles.begin() + itri );
00451 }
00452 }
00453
00454 inline bool PolygonSimplifier::Vertex::isAdjacentVertex(Vertex* v) const
00455 {
00456 for(int i=0; i<adjacentVerticesCount(); ++i)
00457 if ( adjacentVertex(i) == v )
00458 return true;
00459 return false;
00460 }
00461
00462 inline bool PolygonSimplifier::Vertex::isIncidentTriangle(Triangle* t) const
00463 {
00464 for(int i=0; i<incidentTrianglesCount(); ++i)
00465 if ( incidentTriangle(i) == t )
00466 return true;
00467 return false;
00468 }
00469
00470 inline bool PolygonSimplifier::Vertex::checkConnectivity()
00471 {
00472 VL_CHECK( mCollapseVertex )
00473 VL_CHECK( !mCollapseVertex->removed() )
00474
00475 for(int ivert=0; ivert<adjacentVerticesCount(); ++ivert)
00476 {
00477 Vertex* adj = mAdjacentVerts[ivert];
00478 if ( adj->removed() )
00479 return false;
00480 if( std::find(adj->mAdjacentVerts.begin(), adj->mAdjacentVerts.end(), this) == adj->mAdjacentVerts.end() )
00481 return false;
00482 }
00483 return true;
00484 }
00485
00486
00487
00488 inline PolygonSimplifier::QErr PolygonSimplifier::Triangle::computeQErr() const
00489 {
00490 dvec3 n = (dvec3)normal();
00491 double d = -dot((dvec3)vertex(0)->position(), n);
00492 QErr qerr(n, d, computeArea() * (1.0 / 3.0) );
00493 return qerr;
00494 }
00495
00496 inline fvec3 PolygonSimplifier::Triangle::computePotentialNormal(const Vertex* oldv, const Vertex* newv) const
00497 {
00498 fvec3 a = (mVertices[0]->mPosition == oldv->mPosition ? newv->mPosition : mVertices[0]->mPosition);
00499 fvec3 b = (mVertices[1]->mPosition == oldv->mPosition ? newv->mPosition : mVertices[1]->mPosition) - a;
00500 fvec3 c = (mVertices[2]->mPosition == oldv->mPosition ? newv->mPosition : mVertices[2]->mPosition) - a;
00501
00502 fvec3 n = cross(b,c);
00503 n.normalize();
00504 return n;
00505 }
00506
00507 inline bool PolygonSimplifier::Triangle::checkTriangle() const
00508 {
00509 bool ok = true;
00510 ok &= !mVertices[0]->removed(); VL_CHECK(ok)
00511 ok &= !mVertices[1]->removed(); VL_CHECK(ok)
00512 ok &= !mVertices[2]->removed(); VL_CHECK(ok)
00513 ok &= mVertices[0] != mVertices[1]; VL_CHECK(ok)
00514 ok &= mVertices[0] != mVertices[2]; VL_CHECK(ok)
00515 ok &= mVertices[1] != mVertices[2]; VL_CHECK(ok)
00516 return ok;
00517 }
00518
00519 inline bool PolygonSimplifier::Triangle::hasVertex(const Vertex*v) const
00520 {
00521 return mVertices[0] == v || mVertices[1] == v || mVertices[2] == v;
00522 }
00523
00524 inline float PolygonSimplifier::Triangle::computePotentialArea(const Vertex* oldv, const Vertex* newv) const
00525 {
00526 fvec3 A = (mVertices[0]->mPosition == oldv->mPosition ? newv->mPosition : mVertices[0]->mPosition);
00527 fvec3 B = (mVertices[1]->mPosition == oldv->mPosition ? newv->mPosition : mVertices[1]->mPosition) - A;
00528 fvec3 C = (mVertices[2]->mPosition == oldv->mPosition ? newv->mPosition : mVertices[2]->mPosition) - A;
00529
00530 float base = 0.0f;
00531 float height = 0.0f;
00532 fvec3 AC = C-A;
00533 fvec3 AB = B-A;
00534 base = AB.length();
00535 AB = AB * (1.0f / base);
00536 fvec3 h = vl::dot(AC,AB) * AB + A;
00537 height = (C-h).length();
00538
00539 return base * height * 0.5f;
00540 }
00541
00542 inline float PolygonSimplifier::Triangle::computeArea() const
00543 {
00544 const fvec3& A = mVertices[0]->mPosition;
00545 const fvec3& B = mVertices[1]->mPosition;
00546 const fvec3& C = mVertices[2]->mPosition;
00547
00548 float base = 0.0f;
00549 float height = 0.0f;
00550 fvec3 AC = C-A;
00551 fvec3 AB = B-A;
00552 base = AB.length();
00553 if (!base)
00554 return 0;
00555 AB = AB * (1.0f / base);
00556 fvec3 h = vl::dot(AC,AB) * AB + A;
00557 height = (C-h).length();
00558
00559 VL_CHECK( base == base )
00560 VL_CHECK( height == height )
00561 return base * height * 0.5f;
00562 }
00563
00564 inline void PolygonSimplifier::Triangle::computeNormal()
00565 {
00566 const fvec3& a = mVertices[0]->mPosition;
00567 fvec3 b = mVertices[1]->mPosition - a;
00568 fvec3 c = mVertices[2]->mPosition - a;
00569 mNormal = cross(b,c);
00570 mNormal.normalize();
00571 }
00572
00573 inline void PolygonSimplifier::Triangle::replaceVertex( Vertex* oldv, Vertex* newv )
00574 {
00575
00576 mRemoved = hasVertex(newv);
00577 if (mRemoved)
00578 {
00579
00580
00581
00582 }
00583 else
00584 {
00585 if (mVertices[0] == oldv) mVertices[0] = newv;
00586 if (mVertices[1] == oldv) mVertices[1] = newv;
00587 if (mVertices[2] == oldv) mVertices[2] = newv;
00588 VL_CHECK( !mVertices[0]->mRemoved )
00589 VL_CHECK( !mVertices[1]->mRemoved )
00590 VL_CHECK( !mVertices[2]->mRemoved )
00591 }
00592 }
00593
00594 inline void PolygonSimplifier::collapse(Vertex* v)
00595 {
00596 VL_CHECK(!v->mRemoved)
00597 VL_CHECK(v->mCollapseVertex)
00598 VL_CHECK( !v->mCollapseVertex->mRemoved )
00599 #ifndef NDEBUG
00600 v->checkConnectivity();
00601
00602 for(int ivert=0; ivert<v->adjacentVerticesCount(); ++ivert)
00603 {
00604 VL_CHECK( v->mAdjacentVerts[ivert]->checkConnectivity() )
00605 }
00606 #endif
00607
00608 v->mRemoved = true;
00609
00610 v->mCollapseVertex->mPosition = v->mCollapsePosition;
00611 v->mCollapseVertex->mQErr += v->mQErr;
00612
00613 for(int itri=0; itri<v->incidentTrianglesCount(); ++itri)
00614 {
00615 VL_CHECK(!v->mIncidentTriangles[itri]->mRemoved)
00616
00617
00618
00619 v->mIncidentTriangles[itri]->replaceVertex( v, v->mCollapseVertex );
00620
00621
00622 if (!v->mIncidentTriangles[itri]->mRemoved)
00623 {
00624
00625 VL_CHECK( !v->mCollapseVertex->isIncidentTriangle( v->mIncidentTriangles[itri] ) )
00626 v->mCollapseVertex->mIncidentTriangles.push_back( v->mIncidentTriangles[itri] );
00627 }
00628 }
00629
00630
00631 for(int ivert=0; ivert<v->adjacentVerticesCount(); ++ivert)
00632 v->mAdjacentVerts[ivert]->discardRemovedTriangles();
00633
00634
00635 for(int ivert=0; ivert<v->adjacentVerticesCount(); ++ivert)
00636 {
00637 #if 1
00638
00639 v->mAdjacentVerts[ivert]->computeAdjacentVertices();
00640 #else
00641 ... this is not correct since does not mark as removed the vertices that remain without triangles ...
00642 mAdjacentVerts[ivert]->removeAdjacentVertex(this);
00643 mAdjacentVerts[ivert]->addAdjacentVertex(mCollapseVertex);
00644 mCollapseVertex->addAdjacentVertex(mAdjacentVerts[ivert]);
00645 #endif
00646 }
00647
00648 #ifndef NDEBUG
00649 for(int ivert=0; ivert<v->mCollapseVertex->adjacentVerticesCount(); ++ivert)
00650 {
00651 VL_CHECK( v->mCollapseVertex->adjacentVertex(ivert)->checkTriangles() )
00652 }
00653
00654
00655 if ( v->mCollapseVertex->removed() )
00656 {
00657 VL_CHECK( v->mCollapseVertex->mIncidentTriangles.empty() )
00658 VL_CHECK( v->mCollapseVertex->mAdjacentVerts.empty() )
00659 }
00660 #endif
00661
00662
00663
00664 if ( !quick() )
00665 {
00666
00667 for(int itri=0; itri<v->mCollapseVertex->incidentTrianglesCount(); ++itri)
00668 {
00669 VL_CHECK( !v->mCollapseVertex->mIncidentTriangles[itri]->removed() )
00670 VL_CHECK( v->mCollapseVertex->mIncidentTriangles[itri]->checkTriangle() )
00671 v->mCollapseVertex->mIncidentTriangles[itri]->computeNormal();
00672 }
00673 }
00674
00675 VL_CHECK( !v->mCollapseVertex->isAdjacentVertex(v) )
00676
00677
00678 v->mIncidentTriangles.clear();
00679 v->mAdjacentVerts.clear();
00680 }
00681
00682
00683 inline void PolygonSimplifier::computeCollapseInfo(Vertex* v)
00684 {
00685 VL_CHECK(!v->mRemoved)
00686 if(v->mRemoved)
00687 return;
00688
00689
00690
00691
00692 v->mCollapseCost = 1.0e+38f;
00693 v->mCollapseVertex = NULL;
00694 VL_CHECK( v->adjacentVerticesCount() )
00695 for(int ivert=0; ivert<v->adjacentVerticesCount(); ++ivert)
00696 {
00697 VL_CHECK(!v->mAdjacentVerts[ivert]->mRemoved)
00698
00699 double cost = 0.0;
00700 dvec3 solution;
00701 if (quick())
00702 {
00703 QErr qe = v->qerr();
00704 qe += v->mAdjacentVerts[ivert]->qerr();
00705
00706 solution = (dvec3)v->position();
00707 solution += (dvec3)v->mAdjacentVerts[ivert]->position();
00708 solution *= 0.5;
00709 cost = qe.evaluate( solution );
00710 }
00711 else
00712 {
00713 QErr qe = v->qerr();
00714 qe += v->mAdjacentVerts[ivert]->qerr();
00715 bool analytic_ok = qe.analyticSolution(solution);
00716 if ( analytic_ok )
00717 {
00718 cost = qe.evaluate(solution);
00719 VL_CHECK(cost < 1e+38)
00720 }
00721 else
00722 {
00723 dvec3 a = (dvec3)v->position();
00724 dvec3 b = (dvec3)v->mAdjacentVerts[ivert]->position();
00725 dvec3 c = (a+b) * 0.5;
00726 double ae = qe.evaluate(a);
00727 double be = qe.evaluate(b);
00728 double ce = qe.evaluate(c);
00729 if (ae < be && ae < ce)
00730 {
00731 solution = a;
00732 cost = ae;
00733 }
00734 else
00735 if (be < ae && be < ce)
00736 {
00737 solution = b;
00738 cost = be;
00739 }
00740 else
00741 {
00742 solution = c;
00743 cost = ce;
00744 }
00745 VL_CHECK(cost < 1e+38)
00746 }
00747
00748 int degenerate_count = 0;
00749 for( int itri=0; itri<v->incidentTrianglesCount() && !degenerate_count; ++itri )
00750 {
00751
00752 if ( v->incidentTriangle(itri)->hasVertex(v->mAdjacentVerts[ivert]) )
00753 continue;
00754
00755 Vertex* edgev[] = { NULL, NULL };
00756 if ( v == v->incidentTriangle(itri)->vertex(0) )
00757 {
00758 edgev[0] = v->incidentTriangle(itri)->vertex(1);
00759 edgev[1] = v->incidentTriangle(itri)->vertex(2);
00760 }
00761 else
00762 if ( v == v->incidentTriangle(itri)->vertex(1) )
00763 {
00764 edgev[0] = v->incidentTriangle(itri)->vertex(0);
00765 edgev[1] = v->incidentTriangle(itri)->vertex(2);
00766 }
00767 else
00768 if ( v == v->incidentTriangle(itri)->vertex(2) )
00769 {
00770 edgev[0] = v->incidentTriangle(itri)->vertex(0);
00771 edgev[1] = v->incidentTriangle(itri)->vertex(1);
00772 }
00773
00774 fvec3 edge = (edgev[1]->position() - edgev[0]->position());
00775 fvec3 n = cross( edge, v->incidentTriangle(itri)->normal() );
00776 n.normalize();
00777 float d1 = dot( v->position() - edgev[0]->position(), n );
00778 float d2 = dot( (fvec3)solution - edgev[0]->position(), n );
00779
00780 if (d1 * d2 < 0)
00781 ++degenerate_count;
00782 }
00783
00784
00785 Vertex* u = v->mAdjacentVerts[ivert];
00786 for( int itri=0; itri<u->incidentTrianglesCount() && !degenerate_count; ++itri )
00787 {
00788
00789 if ( u->incidentTriangle(itri)->hasVertex(v) )
00790 continue;
00791
00792 Vertex* edgev[] = { NULL, NULL };
00793 if ( u == u->incidentTriangle(itri)->vertex(0) )
00794 {
00795 edgev[0] = u->incidentTriangle(itri)->vertex(1);
00796 edgev[1] = u->incidentTriangle(itri)->vertex(2);
00797 }
00798 else
00799 if ( u == u->incidentTriangle(itri)->vertex(1) )
00800 {
00801 edgev[0] = u->incidentTriangle(itri)->vertex(0);
00802 edgev[1] = u->incidentTriangle(itri)->vertex(2);
00803 }
00804 else
00805 if ( u == u->incidentTriangle(itri)->vertex(2) )
00806 {
00807 edgev[0] = u->incidentTriangle(itri)->vertex(0);
00808 edgev[1] = u->incidentTriangle(itri)->vertex(1);
00809 }
00810
00811 fvec3 edge = (edgev[1]->position() - edgev[0]->position());
00812 fvec3 n = cross( edge, u->incidentTriangle(itri)->normal() );
00813 n.normalize();
00814 float d1 = dot( u->position() - edgev[0]->position(), n );
00815 float d2 = dot( (fvec3)solution - edgev[0]->position(), n );
00816
00817 if (d1 * d2 < 0)
00818 ++degenerate_count;
00819 }
00820
00821
00822 if (degenerate_count)
00823 cost = 1.0e+37f;
00824 }
00825
00826
00827 cost += ((dvec3)v->position() - solution).length() * 1.0e-12;
00828
00829
00830 VL_CHECK( cost == cost )
00831 if ( cost < v->mCollapseCost )
00832 {
00833 v->mCollapseCost = (float)cost;
00834 v->mCollapseVertex = v->mAdjacentVerts[ivert];
00835 v->mCollapsePosition = (fvec3)solution;
00836 }
00837 }
00838
00839 VL_CHECK( v->mCollapseVertex )
00840 }
00841
00842 }
00843
00844 #endif