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