|
Blender
V2.59
|
00001 /* 00002 * $Id: LOD_NdQuadricEditor.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_NdQuadricEditor.h" 00035 #include "LOD_ExternNormalEditor.h" 00036 #include "LOD_ExternVColorEditor.h" 00037 00038 // Creation 00040 00041 using namespace std; 00042 00043 00044 LOD_NdQuadricEditor:: 00045 LOD_NdQuadricEditor( 00046 LOD_ManMesh2 &mesh 00047 ) : 00048 m_quadrics(NULL), 00049 m_mesh(mesh) 00050 { 00051 }; 00052 00053 LOD_NdQuadricEditor * 00054 LOD_NdQuadricEditor:: 00055 New( 00056 LOD_ManMesh2 &mesh 00057 ){ 00058 //same number of quadrics as vertices in the mesh 00059 00060 NanPtr<LOD_NdQuadricEditor> output(new LOD_NdQuadricEditor(mesh)); 00061 00062 if (output == NULL) { 00063 return NULL; 00064 } 00065 return output.Release(); 00066 } 00067 00068 00069 // Property editor interface 00071 00072 void 00073 LOD_NdQuadricEditor:: 00074 Remove( 00075 const std::vector<LOD_VertexInd> &sorted_vertices 00076 ){ 00077 vector<LOD_NdQuadric> & quadrics = *m_quadrics; 00078 00079 vector<LOD_VertexInd>::const_iterator it_start = sorted_vertices.begin(); 00080 vector<LOD_VertexInd>::const_iterator it_end = sorted_vertices.end(); 00081 00082 for (; it_start != it_end; ++it_start) { 00083 00084 if (quadrics.size() > 0) { 00085 LOD_NdQuadric temp = quadrics[*it_start]; 00086 00087 quadrics[*it_start] = quadrics.back(); 00088 quadrics.back() = temp; 00089 00090 quadrics.pop_back(); 00091 } 00092 } 00093 }; 00094 00095 00096 // Editor specific methods 00098 00099 bool 00100 LOD_NdQuadricEditor:: 00101 BuildQuadrics( 00102 const LOD_ExternNormalEditor& normal_editor, 00103 bool preserve_boundaries 00104 ){ 00105 if (m_quadrics != NULL) delete(m_quadrics); 00106 00107 m_quadrics =new vector<LOD_NdQuadric> (m_mesh.VertexSet().size()); 00108 if (m_quadrics == NULL) return false; 00109 00110 // iterate through the face set of the mesh 00111 // compute a quadric based upon that face and 00112 // add it to each of it's vertices quadrics. 00113 00114 const vector<LOD_TriFace> &faces = m_mesh.FaceSet(); 00115 const vector<LOD_Vertex> &verts = m_mesh.VertexSet(); 00116 vector<LOD_Edge> &edges = m_mesh.EdgeSet(); 00117 00118 const vector<MT_Vector3> &normals = normal_editor.Normals(); 00119 vector<MT_Vector3>::const_iterator normal_it = normals.begin(); 00120 00121 vector<LOD_TriFace>::const_iterator face_it = faces.begin(); 00122 vector<LOD_TriFace>::const_iterator face_end = faces.end(); 00123 00124 vector<LOD_NdQuadric> & quadrics = *m_quadrics; 00125 00126 00127 for (; face_it != face_end; ++face_it, ++normal_it) { 00128 00129 MT_Vector3 normal = *normal_it; 00130 MT_Scalar offset = -normal.dot(verts[face_it->m_verts[0]].pos); 00131 00132 LOD_NdQuadric q(normal,offset); 00133 00134 #if 0 00135 // try something with the size of the face. 00136 00137 MT_Vector3 vec1 = 00138 verts[face_it->m_verts[1]].pos - 00139 verts[face_it->m_verts[0]].pos; 00140 00141 MT_Vector3 vec2 = 00142 verts[face_it->m_verts[2]].pos - 00143 verts[face_it->m_verts[1]].pos; 00144 00145 vec1 = vec1.cross(vec2); 00146 00147 q *= vec1.length(); 00148 #endif 00149 quadrics[face_it->m_verts[0]] += q; 00150 quadrics[face_it->m_verts[1]] += q; 00151 quadrics[face_it->m_verts[2]] += q; 00152 } 00153 00154 if (preserve_boundaries) { 00155 00156 // iterate through the edge set and add a boundary quadric to 00157 // each of the boundary edges vertices. 00158 00159 vector<LOD_Edge>::const_iterator edge_it = edges.begin(); 00160 vector<LOD_Edge>::const_iterator edge_end = edges.end(); 00161 00162 for (; edge_it != edge_end; ++edge_it) { 00163 if (edge_it->BoundaryEdge()) { 00164 00165 // compute a plane perpendicular to the edge and the normal 00166 // of the edges single polygon. 00167 const MT_Vector3 & v0 = verts[edge_it->m_verts[0]].pos; 00168 const MT_Vector3 & v1 = verts[edge_it->m_verts[1]].pos; 00169 00170 MT_Vector3 edge_vector = v1 - v0; 00171 00172 LOD_FaceInd edge_face = edge_it->OpFace(LOD_EdgeInd::Empty()); 00173 edge_vector = edge_vector.cross(normals[edge_face]); 00174 00175 if (!edge_vector.fuzzyZero()) { 00176 edge_vector.normalize(); 00177 00178 LOD_NdQuadric boundary_q(edge_vector, - edge_vector.dot(v0)); 00179 boundary_q *= 100; 00180 00181 quadrics[edge_it->m_verts[0]] += boundary_q; 00182 quadrics[edge_it->m_verts[1]] += boundary_q; 00183 } 00184 } 00185 } 00186 } 00187 00188 return true; 00189 00190 }; 00191 00192 void 00193 LOD_NdQuadricEditor:: 00194 InitializeHeapKeys( 00195 const LOD_ExternVColorEditor & color_editor 00196 ){ 00197 // initiate the heap keys of the edges by computing the edge costs. 00198 00199 vector<LOD_Edge> &edges = m_mesh.EdgeSet(); 00200 vector<LOD_NdQuadric> & quadrics = *m_quadrics; 00201 00202 vector<LOD_Edge>::iterator edge_it = edges.begin(); 00203 vector<LOD_Edge>::const_iterator edge_end = edges.end(); 00204 00205 00206 TNT::Vector<MT_Scalar> target(6,MT_Scalar(0)); 00207 00208 for (; edge_it != edge_end; ++edge_it) { 00209 00210 TargetVertex(*edge_it,target,color_editor); 00211 LOD_Edge &e = *edge_it; 00212 const LOD_NdQuadric &q0 = quadrics[e.m_verts[0]]; 00213 const LOD_NdQuadric &q1 = quadrics[e.m_verts[1]]; 00214 00215 #if 0 00216 // testing print out target colors. 00217 00218 std::cout << color_editor.IndexColor(e.m_verts[0]) << "\n"; 00219 std::cout << color_editor.IndexColor(e.m_verts[1]) << "\n"; 00220 00221 MT_Vector3 target_color(target[3],target[4],target[5]); 00222 00223 std::cout << target_color << "\n\n"; 00224 #endif 00225 00226 00227 e.HeapKey() = -float(q0.Evaluate(target) + q1.Evaluate(target)); 00228 } 00229 } 00230 00231 00232 00233 00234 00235 00236 void 00237 LOD_NdQuadricEditor:: 00238 TargetVertex( 00239 const LOD_Edge & e, 00240 TNT::Vector<MT_Scalar> &result, 00241 const LOD_ExternVColorEditor & color_editor 00242 ) const { 00243 00244 // compute an edge contration target for edge ei 00245 // this is computed by summing it's vertices quadrics and 00246 // optimizing the result. 00247 vector<LOD_Vertex> &verts = m_mesh.VertexSet(); 00248 vector<LOD_NdQuadric> &quadrics = *m_quadrics; 00249 00250 LOD_VertexInd v0 = e.m_verts[0]; 00251 LOD_VertexInd v1 = e.m_verts[1]; 00252 00253 LOD_NdQuadric q0 = quadrics[v0]; 00254 q0 += quadrics[v1]; 00255 00256 if (q0.Optimize(result)) { 00257 return; 00258 } else { 00259 // the quadric was degenerate -> just take the average of 00260 // v0 and v1 00261 00262 MT_Vector3 t_result = ((verts[v0].pos + verts[v1].pos) * 0.5); 00263 result[0] = t_result[0]; 00264 result[1] = t_result[1]; 00265 result[2] = t_result[2]; 00266 00267 // do the same for the colors 00268 00269 MT_Vector3 c0 = color_editor.IndexColor(v0); 00270 MT_Vector3 c1 = color_editor.IndexColor(v0); 00271 00272 c0 = (c0 + c1) *0.5; 00273 result[3] = c0[0]; 00274 result[4] = c0[1]; 00275 result[5] = c0[2]; 00276 00277 return ; 00278 } 00279 }; 00280 00281 void 00282 LOD_NdQuadricEditor:: 00283 ComputeEdgeCosts( 00284 const vector<LOD_EdgeInd> &edges, 00285 const LOD_ExternVColorEditor & color_editor 00286 ){ 00287 00288 // for each we compute the target vertex and then compute 00289 // the quadric error e = Q1(v') + Q2(v') 00290 vector<LOD_Edge> &edge_set = m_mesh.EdgeSet(); 00291 00292 vector<LOD_NdQuadric> &quadrics = *m_quadrics; 00293 00294 vector<LOD_EdgeInd>::const_iterator edge_it = edges.begin(); 00295 vector<LOD_EdgeInd>::const_iterator edge_end = edges.end(); 00296 00297 TNT::Vector<MT_Scalar> target(6,MT_Scalar(0)); 00298 00299 for (; edge_it != edge_end; ++edge_it) { 00300 00301 TargetVertex(edge_set[*edge_it],target,color_editor); 00302 00303 LOD_Edge &e = edge_set[*edge_it]; 00304 const LOD_NdQuadric &q0 = quadrics[e.m_verts[0]]; 00305 const LOD_NdQuadric &q1 = quadrics[e.m_verts[1]]; 00306 00307 e.HeapKey() = -float(q0.Evaluate(target) + q1.Evaluate(target)); 00308 } 00309 }; 00310 00311 00312 00313 00314 00315 00316 00317 00318 00319 00320 00321 00322 00323 00324 00325 00326 00327 00328 00329 00330 00331 00332 00333 00334 00335 00336 00337 00338 00339 00340