Go to the documentation of this file.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 #include <vlGraphics/PolygonSimplifier.hpp>
00033 #include <vlGraphics/DoubleVertexRemover.hpp>
00034 #include <vlCore/Time.hpp>
00035 #include <vlCore/Log.hpp>
00036 #include <vlCore/Say.hpp>
00037 #include <set>
00038
00039 using namespace vl;
00040
00041
00042 namespace
00043 {
00044 class VertexPtrWrapper
00045 {
00046 public:
00047 VertexPtrWrapper(PolygonSimplifier::Vertex* ptr=NULL): mVertex(ptr) {}
00048
00049 bool operator==(const VertexPtrWrapper& other) const
00050 {
00051 return mVertex == other.mVertex;
00052 }
00053
00054 bool operator!=(const VertexPtrWrapper& other) const
00055 {
00056 return mVertex == other.mVertex;
00057 }
00058
00059 bool operator<(const VertexPtrWrapper& other) const
00060 {
00061 if ( mVertex->collapseCost() != other.mVertex->collapseCost() )
00062 return mVertex->collapseCost() < other.mVertex->collapseCost();
00063 else
00064 return mVertex < other.mVertex;
00065 }
00066 PolygonSimplifier::Vertex* mVertex;
00067 };
00068 }
00069
00070 void PolygonSimplifier::simplify(float simplification_ratio, Geometry* geom)
00071 {
00072 if ( simplification_ratio > 1.0f || simplification_ratio <= 0.0f )
00073 return;
00074
00075 ArrayFloat3* pvec3 = dynamic_cast<ArrayFloat3*>( geom->vertexArray() );
00076 if (pvec3)
00077 {
00078 simplify( (int)(simplification_ratio*pvec3->size()), geom );
00079 }
00080 else
00081 {
00082 Log::error("PolygonSimplifier::simplify() supports only position arrays of type ArrayFloat3.\n");
00083 return;
00084 }
00085 }
00086
00087 void PolygonSimplifier::simplify(int target_vertex_count, Geometry* geom)
00088 {
00089
00090 #ifndef NDEBUG
00091 bool problem = false;
00092 problem |= geom->normalArray() != NULL;
00093 problem |= geom->colorArray() != NULL;
00094 problem |= geom->secondaryColorArray() != NULL;
00095 problem |= geom->fogCoordArray() != NULL;
00096 for( int i=0; i<VL_MAX_TEXTURE_UNITS; ++i)
00097 problem |= geom->texCoordArray(i) != NULL;
00098 problem |= geom->vertexAttribArrays()->size() != 0;
00099 if (problem)
00100 Log::warning("PolygonSimplifier::simplify() simplifies only the position array of a Geometry, the other attibutes will be discarded.\n");
00101 #endif
00102
00103 if (!dynamic_cast<ArrayFloat3*>(geom->vertexArray()))
00104 {
00105 Log::error("PolygonSimplifier::simplify() supports only position arrays of type ArrayFloat3!\n");
00106 return;
00107 }
00108
00109 Time timer;
00110 timer.start();
00111
00112 if ( removeDoubles() )
00113 {
00114 DoubleVertexRemover remover;
00115 remover.removeDoubles( geom );
00116 }
00117
00118 std::vector<fvec3> verts;
00119 std::vector<int> indices;
00120 indices.reserve(1000);
00121
00122
00123 ref<DrawElementsUInt> pint = new DrawElementsUInt(PT_TRIANGLES, 1);
00124 for(int i=0; i<geom->drawCalls()->size(); ++i)
00125 {
00126 DrawCall* prim = geom->drawCalls()->at(i);
00127 for(TriangleIterator trit = prim->triangleIterator(); !trit.isEnd(); trit.next())
00128 {
00129 indices.push_back( trit.a() );
00130 indices.push_back( trit.b() );
00131 indices.push_back( trit.c() );
00132 }
00133 }
00134
00135
00136 ref<ArrayFloat3> pvec3 = dynamic_cast<ArrayFloat3*>( geom->vertexArray() );
00137 verts.resize( pvec3->size() );
00138 memcpy( &verts[0], pvec3->ptr(), sizeof(verts[0]) * verts.size() );
00139
00140 simplify(target_vertex_count, verts, indices);
00141
00142 pvec3->resize( (int)verts.size() );
00143 pint->indices()->resize( (int)indices.size() );
00144 memcpy( pvec3->ptr(), &verts[0], sizeof(verts[0]) * verts.size() );
00145 memcpy( pint->indices()->ptr(), &indices[0], sizeof(indices[0]) * indices.size() );
00146
00147
00148
00149 geom->drawCalls()->clear();
00150 geom->drawCalls()->push_back(pint.get());
00151
00152
00153 geom->setNormalArray(NULL);
00154 geom->setColorArray(NULL);
00155 geom->setSecondaryColorArray(NULL);
00156 geom->setFogCoordArray(NULL);
00157 for( int i=0; i<VL_MAX_TEXTURE_UNITS; ++i)
00158 geom->setTexCoordArray(i, NULL);
00159 geom->vertexAttribArrays()->clear();
00160
00161 if (verbose())
00162 Log::print( Say("PolygonSimplifier::simplify() done in %.3ns\n") << timer.elapsed() );
00163 }
00164
00165 void PolygonSimplifier::simplify(int target_vertex_count, std::vector<fvec3>& in_out_verts, std::vector<int>& in_out_tris)
00166 {
00167 if (verbose())
00168 Log::print("PolygonSimplifier::simplify() starting ... \n");
00169
00170 Time timer;
00171 timer.start();
00172
00173 mSimplifiedVertices.clear();
00174 mSimplifiedTriangles.clear();
00175 mProtectedVerts.clear();
00176 mTriangleLump.clear();
00177 mVertexLump.clear();
00178
00179
00180 mTriangleLump.resize(in_out_tris.size()/3);
00181 mVertexLump.resize(in_out_verts.size());
00182
00183 int polys_before = (int)in_out_tris.size() / 3;
00184 int verts_before = (int)in_out_verts.size();
00185
00186 mSimplifiedTriangles.resize( in_out_tris.size() / 3 );
00187 mSimplifiedVertices.resize( in_out_verts.size() );
00188
00189 #define SHUFFLE_VERTICES 0
00190
00191 #if SHUFFLE_VERTICES
00192 std::vector<Vertex*> vertex_pool;
00193 vertex_pool.resize( in_out_verts.size() );
00194 for(int i=0; i<(int)mVertexLump.size(); ++i)
00195 vertex_pool[i] = &mVertexLump[i];
00196
00197
00198 for(int i=0; i<(int)vertex_pool.size(); ++i)
00199 {
00200 int a = int( (float)rand() / (RAND_MAX+1) * vertex_pool.size() );
00201 int b = int( (float)rand() / (RAND_MAX+1) * vertex_pool.size() );
00202 Vertex* tmp = vertex_pool[a];
00203 vertex_pool[a] = vertex_pool[b];
00204 vertex_pool[b] = tmp;
00205 }
00206 #endif
00207
00208
00209 for(int ivert=0; ivert<(int)in_out_verts.size(); ++ivert)
00210 {
00211 #if SHUFFLE_VERTICES
00212 mSimplifiedVertices[ivert] = vertex_pool[ivert];
00213 #else
00214 mSimplifiedVertices[ivert] = &mVertexLump[ivert];
00215 #endif
00216 mSimplifiedVertices[ivert]->mPosition = in_out_verts[ivert];
00217
00218
00219 mSimplifiedVertices[ivert]->mOriginalIndex = ivert;
00220
00221
00222 mSimplifiedVertices[ivert]->mProtected = false;
00223
00224
00225 mSimplifiedVertices[ivert]->mIncidentTriangles.reserve(12);
00226 mSimplifiedVertices[ivert]->mAdjacentVerts.reserve(12);
00227 }
00228
00229
00230 for(int idx=0, itri=0; idx<(int)in_out_tris.size(); idx+=3, ++itri)
00231 {
00232 mSimplifiedTriangles[itri] = &mTriangleLump[itri];
00233 mSimplifiedTriangles[itri]->mVertices[0] = mSimplifiedVertices[ in_out_tris[idx+0] ];
00234 mSimplifiedTriangles[itri]->mVertices[1] = mSimplifiedVertices[ in_out_tris[idx+1] ];
00235 mSimplifiedTriangles[itri]->mVertices[2] = mSimplifiedVertices[ in_out_tris[idx+2] ];
00236 }
00237
00238
00239 for(int itri=0; itri<(int)mSimplifiedTriangles.size(); ++itri)
00240 {
00241
00242 mSimplifiedTriangles[itri]->mVertices[0]->mIncidentTriangles.push_back( mSimplifiedTriangles[itri] );
00243 mSimplifiedTriangles[itri]->mVertices[1]->mIncidentTriangles.push_back( mSimplifiedTriangles[itri] );
00244 mSimplifiedTriangles[itri]->mVertices[2]->mIncidentTriangles.push_back( mSimplifiedTriangles[itri] );
00245
00246 mSimplifiedTriangles[itri]->mVertices[0]->addAdjacentVertex( mSimplifiedTriangles[itri]->mVertices[1] );
00247 mSimplifiedTriangles[itri]->mVertices[0]->addAdjacentVertex( mSimplifiedTriangles[itri]->mVertices[2] );
00248 mSimplifiedTriangles[itri]->mVertices[1]->addAdjacentVertex( mSimplifiedTriangles[itri]->mVertices[0] );
00249 mSimplifiedTriangles[itri]->mVertices[1]->addAdjacentVertex( mSimplifiedTriangles[itri]->mVertices[2] );
00250 mSimplifiedTriangles[itri]->mVertices[2]->addAdjacentVertex( mSimplifiedTriangles[itri]->mVertices[0] );
00251 mSimplifiedTriangles[itri]->mVertices[2]->addAdjacentVertex( mSimplifiedTriangles[itri]->mVertices[1] );
00252
00253 mSimplifiedTriangles[itri]->computeNormal();
00254
00255 QErr qerr = mSimplifiedTriangles[itri]->computeQErr();
00256 mSimplifiedTriangles[itri]->mVertices[0]->addQErr(qerr);
00257 mSimplifiedTriangles[itri]->mVertices[1]->addQErr(qerr);
00258 mSimplifiedTriangles[itri]->mVertices[2]->addQErr(qerr);
00259 }
00260
00261
00262
00263
00264 for( int ivert=(int)mSimplifiedVertices.size(); ivert--; )
00265 {
00266 if ( mSimplifiedVertices[ivert]->incidentTrianglesCount() == 0 )
00267 mSimplifiedVertices.erase( mSimplifiedVertices.begin() + ivert );
00268 else
00269 {
00270 mSimplifiedVertices[ivert]->computeEdgePenalty();
00271 computeCollapseInfo( mSimplifiedVertices[ivert] );
00272 }
00273 }
00274
00275
00276 for(int i=0; i<(int)mProtectedVerts.size(); ++i)
00277 {
00278 VL_CHECK(mProtectedVerts[i] < (int)mSimplifiedVertices.size() )
00279 mSimplifiedVertices[ mProtectedVerts[i] ]->mProtected = true;
00280 }
00281
00282 if (verbose())
00283 Log::print(Say("database setup = %.3n\n") << timer.elapsed() );
00284
00285 std::set<VertexPtrWrapper> vertex_set;
00286 for(int ivert=0; ivert<(int)mSimplifiedVertices.size(); ++ivert)
00287 if ( !mSimplifiedVertices[ivert]->mProtected )
00288 vertex_set.insert( mSimplifiedVertices[ivert] );
00289
00290 if (verbose())
00291 Log::print(Say("heap setup = %.3n\n") << timer.elapsed() );
00292
00293 if (target_vertex_count < 3)
00294 {
00295 Log::print(Say("Invalid target_vertex_count = %n\n") << target_vertex_count);
00296 return;
00297 }
00298
00299 std::vector< PolygonSimplifier::Vertex* > adj_verts;
00300 for( int remove_order=0; (int)vertex_set.size()>target_vertex_count; ++remove_order )
00301 {
00302 std::set<VertexPtrWrapper>::iterator it = vertex_set.begin();
00303 PolygonSimplifier::Vertex* v = it->mVertex;
00304 v->mRemoveOrder = remove_order;
00305 vertex_set.erase(it);
00306
00307
00308 adj_verts.clear();
00309 for(int i=0; i<v->adjacentVerticesCount(); ++i)
00310 {
00311 VL_CHECK( v != v->adjacentVertex(i) )
00312 VL_CHECK( !v->adjacentVertex(i)->mAlreadyProcessed )
00313
00314 adj_verts.push_back( v->adjacentVertex(i) );
00315 adj_verts.back()->mAlreadyProcessed = true;
00316 vertex_set.erase( v->adjacentVertex(i) );
00317 }
00318 for(int i=0; i<v->collapseVertex()->adjacentVerticesCount(); ++i)
00319 {
00320 if ( !v->collapseVertex()->adjacentVertex(i)->mAlreadyProcessed )
00321 {
00322 adj_verts.push_back( v->collapseVertex()->adjacentVertex(i) );
00323 vertex_set.erase( v->collapseVertex()->adjacentVertex(i) );
00324 }
00325 }
00326
00327 VL_CHECK(!v->removed())
00328 VL_CHECK(v->collapseVertex())
00329 VL_CHECK(!v->collapseVertex()->removed())
00330
00331 collapse( v );
00332
00333
00334
00335 for( int i=(int)adj_verts.size(); i--; )
00336 {
00337 adj_verts[i]->mAlreadyProcessed = false;
00338
00339 if ( adj_verts[i]->removed() )
00340 continue;
00341
00342 computeCollapseInfo( adj_verts[i] );
00343
00344 VL_CHECK( adj_verts[i]->checkTriangles() )
00345 VL_CHECK( adj_verts[i]->collapseVertex() != v )
00346 VL_CHECK( !adj_verts[i]->collapseVertex()->removed() )
00347
00348 vertex_set.insert( adj_verts[i] );
00349 }
00350 }
00351
00352 if (verbose())
00353 Log::print(Say("simplification = %.3n\n") << timer.elapsed() );
00354
00355
00356 in_out_verts.clear();
00357 int vert_index = 0;
00358 for(int i=0; i<(int)mSimplifiedVertices.size(); ++i)
00359 {
00360 if (!mSimplifiedVertices[i]->mRemoved)
00361 {
00362 in_out_verts.push_back( mSimplifiedVertices[i]->mPosition );
00363 mSimplifiedVertices[i]->mSimplifiedIndex = vert_index++;
00364 }
00365 }
00366
00367
00368 in_out_tris.clear();
00369 for(int i=0; i<(int)mSimplifiedTriangles.size(); ++i)
00370 {
00371 if(!mSimplifiedTriangles[i]->mRemoved)
00372 {
00373 VL_CHECK( !mSimplifiedTriangles[i]->mVertices[0]->mRemoved )
00374 VL_CHECK( !mSimplifiedTriangles[i]->mVertices[1]->mRemoved )
00375 VL_CHECK( !mSimplifiedTriangles[i]->mVertices[2]->mRemoved )
00376
00377 in_out_tris.push_back( mSimplifiedTriangles[i]->mVertices[0]->mSimplifiedIndex );
00378 in_out_tris.push_back( mSimplifiedTriangles[i]->mVertices[1]->mSimplifiedIndex );
00379 in_out_tris.push_back( mSimplifiedTriangles[i]->mVertices[2]->mSimplifiedIndex );
00380 }
00381 }
00382
00383 if (verbose())
00384 {
00385 float elapsed = (float)timer.elapsed();
00386 int polys_after = (int)in_out_tris.size() / 3;
00387 int verts_after = (int)in_out_verts.size();
00388 Log::print(Say("POLYS: %n -> %n, %.2n%%, %.1nT/s\n") << polys_before << polys_after << 100.0f*verts_after/verts_before << (polys_before - polys_after)/elapsed );
00389 Log::print(Say("VERTS: %n -> %n, %.2n%%, %.1nV/s\n") << verts_before << verts_after << 100.0f*verts_after/verts_before << (verts_before - verts_after)/elapsed );
00390 }
00391 }
00392
00393 void PolygonSimplifier::clearTrianglesAndVertices()
00394 {
00395 mSimplifiedVertices.clear();
00396 mSimplifiedTriangles.clear();
00397 mProtectedVerts.clear();
00398 mTriangleLump.clear();
00399 mVertexLump.clear();
00400 }
00401