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