Blender V2.61 - r43446

LOD_QuadricEditor.cpp

Go to the documentation of this file.
00001 /*
00002  * ***** BEGIN GPL LICENSE BLOCK *****
00003  *
00004  * This program is free software; you can redistribute it and/or
00005  * modify it under the terms of the GNU General Public License
00006  * as published by the Free Software Foundation; either version 2
00007  * of the License, or (at your option) any later version.
00008  *
00009  * This program is distributed in the hope that it will be useful,
00010  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  * GNU General Public License for more details.
00013  *
00014  * You should have received a copy of the GNU General Public License
00015  * along with this program; if not, write to the Free Software Foundation,
00016  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00017  *
00018  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
00019  * All rights reserved.
00020  *
00021  * The Original Code is: all of this file.
00022  *
00023  * Contributor(s): none yet.
00024  *
00025  * ***** END GPL LICENSE BLOCK *****
00026  */
00027 
00033 #include "LOD_QuadricEditor.h"
00034 #include "LOD_ExternNormalEditor.h"
00035 
00036 // Creation
00038 
00039 using namespace std;
00040 
00041 
00042 LOD_QuadricEditor::
00043 LOD_QuadricEditor(
00044     LOD_ManMesh2 &mesh
00045 ) :
00046     m_quadrics(NULL),
00047     m_mesh(mesh)
00048 {
00049 };
00050 
00051     LOD_QuadricEditor *
00052 LOD_QuadricEditor::
00053 New(
00054     LOD_ManMesh2 &mesh
00055 ){
00056     //same number of quadrics as vertices in the mesh
00057 
00058     MEM_SmartPtr<LOD_QuadricEditor> output(new LOD_QuadricEditor(mesh));
00059 
00060     if (output == NULL) {
00061         return NULL;
00062     }
00063     return output.Release();
00064 }
00065 
00066 
00067 // Property editor interface
00069 
00070     void
00071 LOD_QuadricEditor::
00072 Remove(
00073     std::vector<LOD_VertexInd> &sorted_vertices
00074 ){
00075     vector<LOD_Quadric> & quadrics = *m_quadrics;
00076 
00077     vector<LOD_VertexInd>::const_iterator it_start = sorted_vertices.begin();
00078     vector<LOD_VertexInd>::const_iterator it_end = sorted_vertices.end();
00079 
00080     for (; it_start != it_end; ++it_start) {
00081 
00082         if (quadrics.size() > 0) {
00083             LOD_Quadric temp = quadrics[*it_start];
00084         
00085             quadrics[*it_start] = quadrics.back();
00086             quadrics.back() = temp;
00087 
00088             quadrics.pop_back();
00089         }
00090     }
00091 };
00092 
00093 
00094 // Editor specific methods
00096 
00097     bool
00098 LOD_QuadricEditor::
00099 BuildQuadrics(
00100     LOD_ExternNormalEditor& normal_editor,
00101     bool preserve_boundaries
00102 ){
00103     if (m_quadrics != NULL) delete(m_quadrics);     
00104 
00105     m_quadrics =new vector<LOD_Quadric> (m_mesh.VertexSet().size());
00106     if (m_quadrics == NULL) return false;
00107 
00108     // iterate through the face set of the mesh
00109     // compute a quadric based upon that face and 
00110     // add it to each of it's vertices quadrics.
00111 
00112     const vector<LOD_TriFace> &faces = m_mesh.FaceSet();
00113     const vector<LOD_Vertex> &verts = m_mesh.VertexSet();
00114     vector<LOD_Edge> &edges = m_mesh.EdgeSet(); 
00115 
00116     const vector<MT_Vector3> &normals = normal_editor.Normals();
00117     vector<MT_Vector3>::const_iterator normal_it = normals.begin();
00118     
00119     vector<LOD_TriFace>::const_iterator face_it = faces.begin();
00120     vector<LOD_TriFace>::const_iterator face_end = faces.end();
00121 
00122     vector<LOD_Quadric> & quadrics = *m_quadrics;
00123 
00124 
00125     for (; face_it != face_end; ++face_it, ++normal_it) {
00126                 
00127         MT_Vector3 normal = *normal_it;
00128         MT_Scalar offset = -normal.dot(verts[face_it->m_verts[0]].pos); 
00129 
00130         LOD_Quadric q(normal,offset);
00131 
00132         quadrics[face_it->m_verts[0]] += q;
00133         quadrics[face_it->m_verts[1]] += q;
00134         quadrics[face_it->m_verts[2]] += q;
00135     }
00136 
00137     if (preserve_boundaries) {
00138 
00139         // iterate through the edge set and add a boundary quadric to 
00140         // each of the boundary edges vertices.
00141     
00142         vector<LOD_Edge>::const_iterator edge_it = edges.begin();
00143         vector<LOD_Edge>::const_iterator edge_end = edges.end();    
00144 
00145         for (; edge_it != edge_end; ++edge_it) {
00146             if (edge_it->BoundaryEdge()) {
00147 
00148                 // compute a plane perpendicular to the edge and the normal
00149                 // of the edges single polygon.
00150                 const MT_Vector3 & v0 = verts[edge_it->m_verts[0]].pos;
00151                 const MT_Vector3 & v1 = verts[edge_it->m_verts[1]].pos;
00152     
00153                 MT_Vector3 edge_vector = v1 - v0;
00154 
00155                 LOD_FaceInd edge_face = edge_it->OpFace(LOD_EdgeInd::Empty());
00156                 edge_vector = edge_vector.cross(normals[edge_face]);
00157 
00158                 if (!edge_vector.fuzzyZero()) {
00159                     edge_vector.normalize();
00160                 
00161                     LOD_Quadric boundary_q(edge_vector, - edge_vector.dot(v0)); 
00162                     boundary_q *= 100;              
00163 
00164                     quadrics[edge_it->m_verts[0]] += boundary_q;
00165                     quadrics[edge_it->m_verts[1]] += boundary_q;
00166                 }
00167             }
00168         }
00169     }
00170 
00171 
00172     // initiate the heap keys of the edges by computing the edge costs.
00173 
00174     vector<LOD_Edge>::iterator edge_it = edges.begin();
00175     vector<LOD_Edge>::const_iterator edge_end = edges.end();
00176 
00177     for (; edge_it != edge_end; ++edge_it)  {
00178         
00179         MT_Vector3 target = TargetVertex(*edge_it);
00180 
00181         LOD_Edge &e = *edge_it;
00182         LOD_Quadric q0 = quadrics[e.m_verts[0]];
00183         const LOD_Quadric &q1 = quadrics[e.m_verts[1]];
00184         
00185         e.HeapKey() = -float(q0.Evaluate(target) + q1.Evaluate(target));
00186     }
00187 
00188     return true;
00189 
00190 };
00191 
00192     MT_Vector3 
00193 LOD_QuadricEditor::
00194 TargetVertex(
00195     LOD_Edge & e
00196 ){
00197 
00198     // compute an edge contration target for edge ei
00199     // this is computed by summing it's vertices quadrics and 
00200     // optimizing the result.
00201     vector<LOD_Vertex> &verts = m_mesh.VertexSet();
00202 
00203     vector<LOD_Quadric> &quadrics = *m_quadrics;
00204 
00205     LOD_VertexInd v0 = e.m_verts[0];
00206     LOD_VertexInd v1 = e.m_verts[1];
00207 
00208     LOD_Quadric q0 = quadrics[v0];
00209     q0 += quadrics[v1];
00210 
00211     MT_Vector3 result;
00212 
00213     if (q0.Optimize(result)) {
00214         return result;
00215     } else {
00216         // the quadric was degenerate -> just take the average of 
00217         // v0 and v1
00218 
00219         return ((verts[v0].pos + verts[v1].pos) * 0.5);
00220     }
00221 };
00222 
00223     void
00224 LOD_QuadricEditor::
00225 ComputeEdgeCosts(
00226     vector<LOD_EdgeInd> &edges
00227 ){  
00228     
00229     // for each we compute the target vertex and then compute
00230     // the quadric error e = Q1(v') + Q2(v')
00231     vector<LOD_Edge> &edge_set = m_mesh.EdgeSet();
00232 
00233     vector<LOD_Quadric> &quadrics = *m_quadrics;
00234 
00235     vector<LOD_EdgeInd>::const_iterator edge_it = edges.begin();
00236     vector<LOD_EdgeInd>::const_iterator edge_end = edges.end();
00237 
00238     for (; edge_it != edge_end; ++edge_it)  {
00239         
00240         MT_Vector3 target = TargetVertex(edge_set[*edge_it]);
00241 
00242         LOD_Edge &e = edge_set[*edge_it];
00243         LOD_Quadric q0 = quadrics[e.m_verts[0]];
00244         const LOD_Quadric &q1 = quadrics[e.m_verts[1]];
00245         
00246         e.HeapKey() = -float(q0.Evaluate(target) + q1.Evaluate(target));
00247     }
00248 };
00249     
00250         
00251 
00252 
00253         
00254 
00255 
00256 
00257 
00258 
00259     
00260 
00261 
00262 
00263 
00264 
00265 
00266 
00267 
00268 
00269 
00270 
00271 
00272 
00273 
00274 
00275 
00276 
00277 
00278 
00279