Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | File List | Namespace Members | Class Members | File Members | Related Pages

meshmodifier.cpp

Go to the documentation of this file.
00001 /*
00002     Sheep - A Rigid Body Dynamics Engine
00003     Copyright (C) 2001-2004 Francois Beaune
00004     Contact: http://toxicengine.sourceforge.net/
00005 
00006     This file is part of Sheep.
00007 
00008     Sheep is free software; you can redistribute it and/or modify
00009     it under the terms of the GNU General Public License as published by
00010     the Free Software Foundation; either version 2 of the License, or
00011     (at your option) any later version.
00012 
00013     Sheep is distributed in the hope that it will be useful,
00014     but WITHOUT ANY WARRANTY; without even the implied warranty of
00015     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00016     GNU General Public License for more details.
00017 
00018     You should have received a copy of the GNU General Public License
00019     along with Sheep; if not, write to the Free Software
00020     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00021 */
00022 
00023 #include "meshmodifier.h"   // include first
00024 
00025 #include <cassert>
00026 #include <cmath>
00027 
00028 //#define VERBOSE
00029 
00030 #ifdef VERBOSE
00031 #include <iostream>
00032 #endif  // VERBOSE
00033 
00034 using namespace sheep;
00035 using namespace std;
00036 
00037 void MeshModifier::ComputeSmoothedVertexNormals(Real smoothing_threshold_angle) {
00038     m_compute_smoothed_vn = true;
00039     m_smoothing_threshold_angle = smoothing_threshold_angle;
00040 }
00041 
00042 void MeshModifier::OptimizeMesh(Real vertex_welding_threshold_dist,
00043                                 Real normal_welding_threshold_angle)
00044 {
00045     m_optimize_mesh = true;
00046     m_vertex_welding_threshold_dist = vertex_welding_threshold_dist;
00047     m_normal_welding_threshold_angle = normal_welding_threshold_angle;
00048 }
00049 
00050 MeshModifier::MeshModifier(IMeshBuilder &builder) :
00051     m_builder(builder)
00052 {
00053     m_compute_smoothed_vn = false;
00054     m_optimize_mesh = false;
00055 }
00056 
00057 MeshModifier::~MeshModifier() {
00058 }
00059 
00060 // IMeshBuilder interface.
00061 
00062 IMeshBuilder::IGeometryBuilder *MeshModifier::GeometryBuilder() {
00063     if(m_builder.GeometryBuilder())
00064         return this;
00065     else return 0;
00066 }
00067 
00068 IMeshBuilder::IMaterialBuilder *MeshModifier::MaterialBuilder() {
00069     if(m_builder.MaterialBuilder())
00070         return this;
00071     else return 0;
00072 }
00073 
00074 // IGeometryBuilder interface.
00075 
00076 void MeshModifier::BeginSubMesh(const string &name) {
00077     m_sub_mesh = new sub_mesh();
00078     m_sub_mesh->m_name = name;
00079     m_sub_mesh->m_material = -1;
00080 }
00081 
00082 void MeshModifier::EndSubMesh() {
00083     // Optimize vertices and faces.
00084     if(m_optimize_mesh) {
00085 #ifdef VERBOSE
00086         cerr << "[MeshModifier] Before optimization:" << endl;
00087         cerr << "[MeshModifier]   Vertices: " << m_sub_mesh->m_vertices.size() << endl;
00088         cerr << "[MeshModifier]   Normals: " << m_sub_mesh->m_normals.size() << endl;
00089         cerr << "[MeshModifier]   Faces: " << m_sub_mesh->m_faces.size() << endl;
00090         cerr << "[MeshModifier] Optimizing faces..." << endl;
00091 #endif  // VERBOSE
00092 
00093         m_sub_mesh->OptimizeFaces();
00094 
00095 #ifdef VERBOSE
00096         cerr << "[MeshModifier] Optimizing vertices..." << endl;
00097 #endif  // VERBOSE
00098 
00099         m_sub_mesh->OptimizeVertices(m_vertex_welding_threshold_dist);
00100     }
00101 
00102     // Compute smoothed normals.
00103     if(m_compute_smoothed_vn) {
00104 #ifdef VERBOSE
00105         cerr << "[MeshModifier] Computing smoothed vertex normals..." << endl;
00106 #endif  // VERBOSE
00107 
00108         m_sub_mesh->ComputeSmoothedVertexNormals(m_smoothing_threshold_angle);
00109     }
00110 
00111     // Optimize normals.
00112     if(m_optimize_mesh) {
00113 #ifdef VERBOSE
00114         cerr << "[MeshModifier] Optimizing normals..." << endl;
00115 #endif  // VERBOSE
00116 
00117         m_sub_mesh->OptimizeNormals(m_normal_welding_threshold_angle);
00118 
00119 #ifdef VERBOSE
00120         cerr << "[MeshModifier] After optimization:" << endl;
00121         cerr << "[MeshModifier]   Vertices: " << m_sub_mesh->m_vertices.size() << endl;
00122         cerr << "[MeshModifier]   Normals: " << m_sub_mesh->m_normals.size() << endl;
00123         cerr << "[MeshModifier]   Faces: " << m_sub_mesh->m_faces.size() << endl;
00124 #endif  // VERBOSE
00125     }
00126 
00127     // Begin sub mesh description.
00128     m_builder.GeometryBuilder()->BeginSubMesh(m_sub_mesh->m_name);
00129 
00130     // Send vertices.
00131     for(vector<Point3>::const_iterator i = m_sub_mesh->m_vertices.begin(),
00132         e = m_sub_mesh->m_vertices.end(); i != e; ++i)
00133     {
00134         m_builder.GeometryBuilder()->AppendVertex(*i);
00135     }
00136 
00137     // Send normals.
00138     for(vector<Vector3>::const_iterator i = m_sub_mesh->m_normals.begin(),
00139         e = m_sub_mesh->m_normals.end(); i != e; ++i)
00140     {
00141         m_builder.GeometryBuilder()->AppendNormal(*i);
00142     }
00143 
00144     // Send texture coordinates.
00145     for(vector<Vector2>::const_iterator i = m_sub_mesh->m_texcoords.begin(),
00146         e = m_sub_mesh->m_texcoords.end(); i != e; ++i)
00147     {
00148         m_builder.GeometryBuilder()->AppendTexCoord(*i);
00149     }
00150 
00151     // Send faces.
00152     for(vector<sub_mesh::face>::const_iterator i = m_sub_mesh->m_faces.begin(),
00153         e = m_sub_mesh->m_faces.end(); i != e; ++i)
00154     {
00155         const FeatureId v[3] = { i->m_v0, i->m_v1, i->m_v2 };
00156         const FeatureId fid = m_builder.GeometryBuilder()->AppendFace(3, v);
00157 
00158         if(i->m_n0 != -1) {
00159             const FeatureId vn[3] = { i->m_n0, i->m_n1, i->m_n2 };
00160             m_builder.GeometryBuilder()->SetFaceNormals(fid, 3, vn);
00161         }
00162 
00163         if(i->m_t0 != -1) {
00164             const FeatureId vt[3] = { i->m_t0, i->m_t1, i->m_t2 };
00165             m_builder.GeometryBuilder()->SetFaceTexCoords(fid, 3, vt);
00166         }
00167     }
00168 
00169     if(m_sub_mesh->m_material != -1)
00170         m_builder.GeometryBuilder()->SetMaterial(m_sub_mesh->m_material);
00171 
00172     // Close sub mesh.
00173     m_builder.GeometryBuilder()->EndSubMesh();
00174 
00175     delete m_sub_mesh;
00176 }
00177 
00178 IMeshBuilder::FeatureId MeshModifier::AppendVertex(const Vector3 &v) {
00179     m_sub_mesh->m_vertices.push_back(v);
00180 
00181     return m_sub_mesh->m_vertices.size() - 1;
00182 }
00183 
00184 IMeshBuilder::FeatureId MeshModifier::AppendNormal(const Vector3 &vn) {
00185     if(m_compute_smoothed_vn)
00186         return -1;
00187 
00188     m_sub_mesh->m_normals.push_back(vn);
00189 
00190     return m_sub_mesh->m_normals.size() - 1;
00191 }
00192 
00193 IMeshBuilder::FeatureId MeshModifier::AppendTexCoord(const Vector2 &vt) {
00194     m_sub_mesh->m_texcoords.push_back(vt);
00195 
00196     return m_sub_mesh->m_texcoords.size() - 1;
00197 }
00198 
00199 IMeshBuilder::FeatureId MeshModifier::AppendFace(int n, const FeatureId *v) {
00200     assert(n == 3);
00201     assert(v);
00202 
00203     sub_mesh::face f;
00204 
00205     f.m_v0 = v[0];
00206     f.m_v1 = v[1];
00207     f.m_v2 = v[2];
00208 
00209     f.m_n0 = f.m_n1 = f.m_n2 = -1;
00210     f.m_t0 = f.m_t1 = f.m_t2 = -1;
00211 
00212     m_sub_mesh->m_faces.push_back(f);
00213 
00214     return m_sub_mesh->m_faces.size() - 1;
00215 }
00216 
00217 void MeshModifier::SetFaceNormals(FeatureId face, int n, const FeatureId *vn) {
00218     assert(face >= 0 && face < m_sub_mesh->m_faces.size());
00219     assert(n == 3);
00220     assert(vn);
00221 
00222     if(!m_compute_smoothed_vn) {
00223         sub_mesh::face &f = m_sub_mesh->m_faces[face];
00224 
00225         f.m_n0 = vn[0];
00226         f.m_n1 = vn[1];
00227         f.m_n2 = vn[2];
00228     }
00229 }
00230 
00231 void MeshModifier::SetFaceTexCoords(FeatureId face, int n, const FeatureId *vt) {
00232     assert(face >= 0 && face < m_sub_mesh->m_faces.size());
00233     assert(n == 3);
00234     assert(vt);
00235 
00236     sub_mesh::face &f = m_sub_mesh->m_faces[face];
00237 
00238     f.m_t0 = vt[0];
00239     f.m_t1 = vt[1];
00240     f.m_t2 = vt[2];
00241 }
00242 
00243 void MeshModifier::SetMaterial(FeatureId material) {
00244     m_sub_mesh->m_material = material;
00245 }
00246 
00247 // IMaterialBuilder interface.
00248 
00249 IMeshBuilder::FeatureId MeshModifier::BeginMaterial(const string &name) {
00250     return m_builder.MaterialBuilder()->BeginMaterial(name);
00251 }
00252 
00253 void MeshModifier::EndMaterial() {
00254     m_builder.MaterialBuilder()->EndMaterial();
00255 }
00256 
00257 void MeshModifier::SetAmbientColor(Real r, Real g, Real b) {
00258     m_builder.MaterialBuilder()->SetAmbientColor(r, g, b);
00259 }
00260 
00261 void MeshModifier::SetDiffuseColor(Real r, Real g, Real b) {
00262     m_builder.MaterialBuilder()->SetDiffuseColor(r, g, b);
00263 }
00264 
00265 void MeshModifier::SetSpecularColor(Real r, Real g, Real b) {
00266     m_builder.MaterialBuilder()->SetSpecularColor(r, g, b);
00267 }
00268 
00269 void MeshModifier::SetTexture(int w, int h, const unsigned char *texels) {  //!< 24-bit RGB format.
00270     m_builder.MaterialBuilder()->SetTexture(w, h, texels);
00271 }
00272 
00273     // Build smoothed normals whithout threshold angle.
00274 
00275 /*  m_submesh->m_normals.clear();
00276     m_submesh->m_normals.reserve(m_submesh->m_vertices.size());
00277 
00278     for(int i = 0; i < m_submesh->m_vertices.size(); ++i) {
00279         m_submesh->m_normals.push_back(Vector3(0.0));
00280     }
00281 
00282     for(GLMesh::SubMesh::FaceVectorIt i = m_submesh->m_faces.begin(),
00283         e = m_submesh->m_faces.end(); i != e; ++i)
00284     {
00285         GLMesh::SubMesh::Face &f = *i;
00286 
00287         const Point3 &v0 = m_submesh->m_vertices[f.m_v0];
00288         const Point3 &v1 = m_submesh->m_vertices[f.m_v1];
00289         const Point3 &v2 = m_submesh->m_vertices[f.m_v2];
00290 
00291         const Vector3 e0 = v1 - v0;
00292         const Vector3 e1 = v2 - v0;
00293         const Vector3 face_normal = (e0 ^ e1).Normalized();
00294 
00295         f.m_n0 = f.m_v0;
00296         f.m_n1 = f.m_v1;
00297         f.m_n2 = f.m_v2;
00298 
00299         m_submesh->m_normals[f.m_n0] += face_normal;
00300         m_submesh->m_normals[f.m_n1] += face_normal;
00301         m_submesh->m_normals[f.m_n2] += face_normal;
00302     }
00303 
00304     for(GLMesh::SubMesh::Vector3VectorIt i = m_submesh->m_normals.begin(),
00305         e = m_submesh->m_normals.end(); i != e; ++i)
00306     {
00307         i->Normalize();
00308     }*/
00309 
00310     // Build normals for flat-shading.
00311 
00312 /*  m_submesh->m_normals.clear();
00313 
00314     for(GLMesh::SubMesh::FaceVectorIt i = m_submesh->m_faces.begin(),
00315         e = m_submesh->m_faces.end(); i != e; ++i)
00316     {
00317         GLMesh::SubMesh::Face &f = *i;
00318 
00319 //      if(f.m_n0 == -1 || f.m_n1 == -1 || f.m_n2 == -1) {
00320             const Point3 &v0 = m_submesh->m_vertices[f.m_v0];
00321             const Point3 &v1 = m_submesh->m_vertices[f.m_v1];
00322             const Point3 &v2 = m_submesh->m_vertices[f.m_v2];
00323 
00324             const Vector3 e0 = v1 - v0;
00325             const Vector3 e1 = v2 - v0;
00326             const Vector3 vn = (e0 ^ e1).Normalized();
00327 
00328             m_submesh->m_normals.push_back(vn);
00329 
00330             f.m_n0 = f.m_n1 = f.m_n2 =
00331                 static_cast<FeatureId>(m_submesh->m_normals.size() - 1);
00332 //      }
00333     }*/
00334 
00335 void MeshModifier::sub_mesh::ComputeSmoothedVertexNormals(Real smoothing_threshold_angle) {
00336     assert(smoothing_threshold_angle >= 0.0);
00337 
00338     const Real cos_smoothing_threshold_angle = cos(smoothing_threshold_angle);
00339 
00340     const int vertex_count = m_vertices.size();
00341     const int face_count = m_faces.size();
00342 
00343     // Compute geometric normal to each face.
00344 
00345     Vector3 *face_normals = new Vector3[face_count];
00346 
00347     for(int i = 0; i < face_count; ++i) {
00348         const face &f = m_faces[i];
00349 
00350         const Point3 &v0 = m_vertices[f.m_v0];
00351         const Point3 &v1 = m_vertices[f.m_v1];
00352         const Point3 &v2 = m_vertices[f.m_v2];
00353 
00354         const Vector3 e0 = v1 - v0;
00355         const Vector3 e1 = v2 - v0;
00356 
00357         face_normals[i] = (e0 ^ e1).Normalized();
00358     }
00359 
00360     // Find the list of faces each vertex belongs to.
00361 
00362     vector<int> *vertex_membership = new vector<int>[vertex_count];
00363 
00364     for(int i = 0; i < face_count; ++i) {
00365         const face &f = m_faces[i];
00366 
00367         vertex_membership[f.m_v0].push_back(i);
00368         vertex_membership[f.m_v1].push_back(i);
00369         vertex_membership[f.m_v2].push_back(i);
00370     }
00371 
00372     // Compute smoothed normals.
00373 
00374     vector<Vector3> smoothed_normals;
00375 
00376     for(int i = 0; i < vertex_count; ++i) {
00377         const vector<int> &member_faces = vertex_membership[i];
00378 
00379         // Make sure this vertex belongs to at least one face.
00380         assert(member_faces.size() > 0);
00381 
00382         for(int j = 0; j < member_faces.size(); ++j) {
00383             const int face1_index = member_faces[j];
00384             face &face1 = m_faces[face1_index];
00385             const Vector3 &face1_normal = face_normals[face1_index];
00386 
00387             const int smoothed_normal_index = smoothed_normals.size();
00388             Vector3 smoothed_normal = face1_normal;
00389 
00390             if(face1.m_v0 == i) face1.m_n0 = smoothed_normal_index;
00391             if(face1.m_v1 == i) face1.m_n1 = smoothed_normal_index;
00392             if(face1.m_v2 == i) face1.m_n2 = smoothed_normal_index;
00393 
00394             for(int k = 0; k < member_faces.size(); ++k) {
00395                 if(j != k) {
00396                     const int face2_index = member_faces[k];
00397                     face &face2 = m_faces[face2_index];
00398                     const Vector3 &face2_normal = face_normals[face2_index];
00399 
00400                     if(face1_normal * face2_normal > cos_smoothing_threshold_angle) {
00401                         smoothed_normal += face2_normal;
00402 
00403                         if(face2.m_v0 == i) face2.m_n0 = smoothed_normal_index;
00404                         if(face2.m_v1 == i) face2.m_n1 = smoothed_normal_index;
00405                         if(face2.m_v2 == i) face2.m_n2 = smoothed_normal_index;
00406                     }
00407                 }
00408             }
00409 
00410             smoothed_normal.Normalize();
00411             smoothed_normals.push_back(smoothed_normal);
00412         }
00413     }
00414 
00415     delete [] vertex_membership;
00416     delete [] face_normals;
00417 
00418     // Replace old normals with smoothed normals.
00419     m_normals.resize(smoothed_normals.size());
00420     copy(smoothed_normals.begin(), smoothed_normals.end(), m_normals.begin());
00421 }
00422 
00423 void MeshModifier::sub_mesh::OptimizeVertices(Real welding_threshold_dist) {
00424     assert(welding_threshold_dist >= 0.0);
00425 
00426     const Real welding_threshold_dist2 = sq(welding_threshold_dist);
00427 
00428     vector<Point3> new_vertices;
00429     int *tt = new int[m_vertices.size()];   // translation table
00430 
00431     for(int i = 0; i < m_vertices.size(); ++i) {
00432         const Point3 &p = m_vertices[i];
00433 
00434         tt[i] = -1;
00435 
00436         for(int j = 0; j < new_vertices.size(); ++j) {
00437             const Real distance2 = (p - new_vertices[j]).SquareNorm();
00438 
00439             if(distance2 < welding_threshold_dist2) {
00440                 tt[i] = j;
00441                 break;
00442             }
00443         }
00444 
00445         if(tt[i] == -1) {
00446             tt[i] = new_vertices.size();
00447             new_vertices.push_back(p);
00448         }
00449     }
00450 
00451     // Replace old vertices with new vertices.
00452     m_vertices.resize(new_vertices.size());
00453     copy(new_vertices.begin(), new_vertices.end(), m_vertices.begin());
00454 
00455     // Fix face vertex indices.
00456     for(vector<face>::iterator i = m_faces.begin(), e = m_faces.end(); i != e; ++i) {
00457         i->m_v0 = tt[i->m_v0];
00458         i->m_v1 = tt[i->m_v1];
00459         i->m_v2 = tt[i->m_v2];
00460     }
00461 
00462     delete [] tt;
00463 }
00464 
00465 void MeshModifier::sub_mesh::OptimizeNormals(Real welding_threshold_angle) {
00466     assert(welding_threshold_angle >= 0.0);
00467 
00468     const Real cos_welding_threshold_angle = cos(welding_threshold_angle);
00469 
00470     vector<Vector3> new_normals;
00471     int *tt = new int[m_normals.size()];    // translation table
00472 
00473     for(int i = 0; i < m_normals.size(); ++i) {
00474         const Vector3 &n = m_normals[i];
00475 
00476         assert(n.IsUnitLength());
00477 
00478         tt[i] = -1;
00479 
00480         for(int j = 0; j < new_normals.size(); ++j) {
00481             const Real cos_angle = n * new_normals[j];
00482 
00483             if(cos_angle > cos_welding_threshold_angle) {
00484                 tt[i] = j;
00485                 break;
00486             }
00487         }
00488 
00489         if(tt[i] == -1) {
00490             tt[i] = new_normals.size();
00491             new_normals.push_back(n);
00492         }
00493     }
00494 
00495     // Replace old normals with new normals.
00496     m_normals.resize(new_normals.size());
00497     copy(new_normals.begin(), new_normals.end(), m_normals.begin());
00498 
00499     // Fix face normal indices.
00500     for(vector<face>::iterator i = m_faces.begin(), e = m_faces.end(); i != e; ++i) {
00501         i->m_n0 = tt[i->m_n0];
00502         i->m_n1 = tt[i->m_n1];
00503         i->m_n2 = tt[i->m_n2];
00504     }
00505 
00506     delete [] tt;
00507 }
00508 
00509 void MeshModifier::sub_mesh::OptimizeFaces() {
00510     vector<face> new_faces;
00511 
00512     for(vector<face>::iterator i = m_faces.begin(), e = m_faces.end(); i != e; ++i) {
00513         face &f = *i;
00514 
00515         if( f.m_v0 != f.m_v1 &&
00516             f.m_v0 != f.m_v2 &&
00517             f.m_v1 != f.m_v2)
00518         {
00519             new_faces.push_back(f);
00520         }
00521     }
00522 
00523     // Replace old faces with new faces.
00524     m_faces.resize(new_faces.size());
00525     copy(new_faces.begin(), new_faces.end(), m_faces.begin());
00526 }

Generated on Tue May 11 01:31:51 2004 for toxic by doxygen 1.3.6