|
Blender
V2.59
|
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