Blender V2.61 - r43446
|
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_NdQSDecimator.h" 00034 00035 #include "LOD_ExternBufferEditor.h" 00036 #include "LOD_ExternNormalEditor.h" 00037 #include "LOD_ExternVColorEditor.h" 00038 #include "TNT/lu.h" 00039 00040 #include <iostream> 00041 00042 using namespace std; 00043 00044 LOD_NdQSDecimator * 00045 LOD_NdQSDecimator:: 00046 New( 00047 LOD_ManMesh2 &mesh, 00048 LOD_ExternNormalEditor &face_editor, 00049 LOD_ExternVColorEditor &color_editor, 00050 LOD_ExternBufferEditor &extern_editor 00051 ){ 00052 00053 NanPtr<LOD_NdQSDecimator> output 00054 = new LOD_NdQSDecimator(mesh,face_editor,color_editor,extern_editor); 00055 00056 NanPtr<LOD_EdgeCollapser > collapser(LOD_EdgeCollapser::New()); 00057 NanPtr<LOD_NdQuadricEditor> q_editor(LOD_NdQuadricEditor::New(mesh)); 00058 00059 if ( 00060 output == NULL || 00061 collapser == NULL || 00062 q_editor == NULL 00063 ) { 00064 return NULL; 00065 } 00066 output->m_collapser = collapser.Release(); 00067 output->m_quadric_editor = q_editor.Release(); 00068 return output.Release(); 00069 } 00070 00071 00072 00073 bool 00074 LOD_NdQSDecimator:: 00075 Arm( 00076 ){ 00077 MT_assert(!m_is_armed); 00078 bool heap_result = BuildHeap(); 00079 if (!heap_result) { 00080 return false; 00081 } 00082 m_is_armed = true; 00083 return true; 00084 } 00085 00086 bool 00087 LOD_NdQSDecimator:: 00088 Step( 00089 ){ 00090 return CollapseEdge(); 00091 } 00092 00093 00094 LOD_NdQSDecimator:: 00095 LOD_NdQSDecimator( 00096 LOD_ManMesh2 &mesh, 00097 LOD_ExternNormalEditor &face_editor, 00098 LOD_ExternVColorEditor &color_editor, 00099 LOD_ExternBufferEditor &extern_editor 00100 ) : 00101 m_mesh(mesh), 00102 m_face_editor(face_editor), 00103 m_color_editor(color_editor), 00104 m_extern_editor(extern_editor), 00105 m_is_armed (false) 00106 { 00107 m_deg_edges.reserve(32); 00108 m_deg_faces.reserve(32); 00109 m_deg_vertices.reserve(32); 00110 m_update_faces.reserve(32); 00111 m_new_edges.reserve(32); 00112 m_update_vertices.reserve(32); 00113 }; 00114 00115 bool 00116 LOD_NdQSDecimator:: 00117 CollapseEdge( 00118 ){ 00119 00120 // find an edge to collapse 00121 00122 // FIXME force an edge collapse 00123 // or return false 00124 00125 vector<LOD_Edge> & edges = m_mesh.EdgeSet(); 00126 vector<LOD_Vertex> & verts = m_mesh.VertexSet(); 00127 vector<LOD_NdQuadric> & quadrics = m_quadric_editor->Quadrics(); 00128 int size = edges.size(); 00129 00130 if (size == 0) return false; 00131 00132 const int heap_top = m_heap->Top(); 00133 00134 if (heap_top == -1 || edges[heap_top].HeapKey() <= -MT_INFINITY) { 00135 return false; 00136 } 00137 00138 // compute the target position 00139 00140 TNT::Vector<MT_Scalar> new_vector(6,MT_Scalar(0)); 00141 00142 m_quadric_editor->TargetVertex(edges[heap_top],new_vector,m_color_editor); 00143 00144 00145 MT_Vector3 new_vertex( 00146 new_vector[0], 00147 new_vector[1], 00148 new_vector[2] 00149 ); 00150 for (int i = 3; i < 6;i++) { 00151 if (new_vector[i] > MT_Scalar(1)) { 00152 new_vector[i] = MT_Scalar(1); 00153 } else 00154 if (new_vector[i] < MT_Scalar(0)) { 00155 new_vector[i] = MT_Scalar(0); 00156 } 00157 } 00158 MT_Vector3 new_color( 00159 new_vector[3], 00160 new_vector[4], 00161 new_vector[5] 00162 ); 00163 00164 // bounds check? 00165 00166 00167 LOD_NdQuadric & q0 = quadrics[edges[heap_top].m_verts[0]]; 00168 LOD_NdQuadric & q1 = quadrics[edges[heap_top].m_verts[1]]; 00169 00170 const LOD_VertexInd v0ind = edges[heap_top].m_verts[0]; 00171 const LOD_VertexInd v1ind = edges[heap_top].m_verts[1]; 00172 00173 LOD_Vertex &v0 = verts[v0ind]; 00174 LOD_Vertex &v1 = verts[v1ind]; 00175 00176 LOD_NdQuadric sum = q0; 00177 sum += q1; 00178 00179 00180 if (m_collapser->CollapseEdge( 00181 heap_top, 00182 m_mesh, 00183 m_deg_edges, 00184 m_deg_faces, 00185 m_deg_vertices, 00186 m_new_edges, 00187 m_update_faces, 00188 m_update_vertices 00189 )) { 00190 00191 // assign new vertex position 00192 00193 v0.pos = new_vertex; 00194 v1.pos = new_vertex; 00195 00196 // assign the new vertex color 00197 00198 m_color_editor.SetColor(new_color,v0ind); 00199 m_color_editor.SetColor(new_color,v1ind); 00200 00201 // sum the quadrics of v0 and v1 00202 q0 = sum; 00203 q1 = sum; 00204 00205 // ok update the primitive properties 00206 00207 m_face_editor.Update(m_update_faces); 00208 m_face_editor.UpdateVertexNormals(m_update_vertices); 00209 00210 // update the external vertex buffer 00211 m_extern_editor.CopyModifiedVerts(m_mesh,m_update_vertices); 00212 00213 // update the external face buffer 00214 m_extern_editor.CopyModifiedFaces(m_mesh,m_update_faces); 00215 00216 // update the edge heap 00217 UpdateHeap(m_deg_edges,m_new_edges); 00218 00219 m_quadric_editor->Remove(m_deg_vertices); 00220 m_face_editor.Remove(m_deg_faces); 00221 m_face_editor.RemoveVertexNormals(m_deg_vertices); 00222 m_color_editor.RemoveVertexColors(m_deg_vertices); 00223 00224 // delete the primitives 00225 00226 DeletePrimitives(m_deg_edges,m_deg_faces,m_deg_vertices); 00227 00228 } else { 00229 // the edge could not be collapsed at the moment - so 00230 // we adjust it's priority and add it back to the heap. 00231 m_heap->Remove(edges.begin(),0); 00232 edges[heap_top].HeapKey() = - MT_INFINITY; 00233 m_heap->Insert(edges.begin(),heap_top); 00234 } 00235 00236 //clear all the temporary buffers 00237 00238 m_deg_faces.clear(); 00239 m_deg_edges.clear(); 00240 m_deg_vertices.clear(); 00241 00242 m_update_faces.clear(); 00243 m_update_vertices.clear(); 00244 m_new_edges.clear(); 00245 00246 return true; 00247 00248 } 00249 00250 void 00251 LOD_NdQSDecimator:: 00252 DeletePrimitives( 00253 const vector<LOD_EdgeInd> & degenerate_edges, 00254 const vector<LOD_FaceInd> & degenerate_faces, 00255 const vector<LOD_VertexInd> & degenerate_vertices 00256 ) { 00257 00258 // assumes that the 3 vectors are sorted in descending order. 00259 00260 // Delete Degnerate primitives 00262 00263 00264 // delete the old edges - we have to be very careful here 00265 // mesh.delete() swaps edges to be deleted with the last edge in 00266 // the edge buffer. However the next edge to be deleted may have 00267 // been the last edge in the buffer! 00268 00269 // One way to solve this is to sort degenerate_edges in descending order. 00270 // And then delete them in that order. 00271 00272 // it is also vital that degenerate_edges contains no duplicates 00273 00274 vector<LOD_EdgeInd>::const_iterator edge_it = degenerate_edges.begin(); 00275 vector<LOD_EdgeInd>::const_iterator edge_end = degenerate_edges.end(); 00276 00277 for (; edge_it != edge_end; ++edge_it) { 00278 m_mesh.DeleteEdge(*edge_it,m_heap); 00279 } 00280 00281 00282 00283 vector<LOD_FaceInd>::const_iterator face_it = degenerate_faces.begin(); 00284 vector<LOD_FaceInd>::const_iterator face_end = degenerate_faces.end(); 00285 00286 for (;face_it != face_end; ++face_it) { 00287 m_mesh.DeleteFace(m_extern_editor,*face_it); 00288 } 00289 00290 vector<LOD_VertexInd>::const_iterator vertex_it = degenerate_vertices.begin(); 00291 vector<LOD_VertexInd>::const_iterator vertex_end = degenerate_vertices.end(); 00292 00293 for (;vertex_it != vertex_end; ++vertex_it) { 00294 m_mesh.DeleteVertex(m_extern_editor,*vertex_it); 00295 } 00296 } 00297 00298 00299 bool 00300 LOD_NdQSDecimator:: 00301 BuildHeap( 00302 ){ 00303 // build the geometric quadrics 00304 00305 if (m_quadric_editor->BuildQuadrics(m_face_editor,true) == false) return false; 00306 00307 // add in the property quadrics. 00308 ComputePropertyQuadrics(); 00309 00310 m_quadric_editor->InitializeHeapKeys(m_color_editor); 00311 00312 m_heap = Heap<LOD_Edge>::New(); 00313 // load in edge pointers to the heap 00314 00315 vector<LOD_Edge> & edge_set= m_mesh.EdgeSet(); 00316 vector<LOD_Edge>::const_iterator edge_end = edge_set.end(); 00317 vector<LOD_Edge>::iterator edge_start = edge_set.begin(); 00318 00319 vector<int> & heap_vector = m_heap->HeapVector(); 00320 00321 for (int i = 0; i < edge_set.size(); ++i) { 00322 edge_set[i].HeapPos() = i; 00323 heap_vector.push_back(i); 00324 } 00325 00326 m_heap->MakeHeap(edge_set.begin()); 00327 00328 return true; 00329 } 00330 00331 void 00332 LOD_NdQSDecimator:: 00333 UpdateHeap( 00334 vector<LOD_EdgeInd> °_edges, 00335 vector<LOD_EdgeInd> &new_edges 00336 ){ 00337 // first of all compute values for the new edges 00338 // and bung them on the heap. 00339 00340 vector<LOD_Edge> & edge_set= m_mesh.EdgeSet(); 00341 00342 vector<LOD_EdgeInd>::const_iterator edge_it = new_edges.begin(); 00343 vector<LOD_EdgeInd>::const_iterator end_it = new_edges.end(); 00344 00345 00346 // insert all the new edges 00348 00349 // compute edge costs ffor the new edges 00350 00351 m_quadric_editor->ComputeEdgeCosts(new_edges,m_color_editor); 00352 00353 // inser the new elements into the heap 00354 00355 for (; edge_it != end_it; ++edge_it) { 00356 m_heap->Insert(edge_set.begin(),*edge_it); 00357 } 00358 00359 00360 // remove all the old values from the heap 00361 00362 edge_it = deg_edges.begin(); 00363 end_it = deg_edges.end(); 00364 00365 for (; edge_it != end_it; ++edge_it) { 00366 LOD_Edge &e = edge_set[*edge_it]; 00367 m_heap->Remove(edge_set.begin(),e.HeapPos()); 00368 00369 e.HeapPos() = 0xffffffff; 00370 00371 } 00372 } 00373 00374 void 00375 LOD_NdQSDecimator:: 00376 ComputePropertyQuadrics( 00377 ){ 00378 00379 vector<LOD_TriFace> & faces = m_mesh.FaceSet(); 00380 vector<LOD_Vertex> & verts = m_mesh.VertexSet(); 00381 vector<LOD_NdQuadric> & quadrics = m_quadric_editor->Quadrics(); 00382 const vector<MT_Vector3> &face_normals = m_face_editor.Normals(); 00383 00384 // compute the linear functionals for each face 00385 00386 // For each property associated with that face we compute 00387 // a property gradient, construct a quadric based on this and add 00388 // it to each of the face's vertex quadrics. 00389 00390 vector<LOD_TriFace>::const_iterator f_start = faces.begin(); 00391 vector<LOD_TriFace>::const_iterator f_end = faces.end(); 00392 vector<LOD_TriFace>::iterator f = faces.begin(); 00393 00394 // we need a little matrix space to help us with the 00395 // linear functional computation. 00396 00397 TNT::Matrix<MT_Scalar> mat(4,4,MT_Scalar(0)); 00398 TNT::Vector<MT_Scalar> vec(4,MT_Scalar(1)); 00399 00400 // some pivots. 00401 00402 TNT::Vector<TNT::Subscript> pivots(4,int(0)); 00403 00404 // Quadrics now consume heap memory so let's 00405 // reuse one in the following loop rather than 00406 // making one each iteration. 00407 00408 LOD_NdQuadric qp; 00409 00410 00411 for (;f != f_end; ++f) { 00412 00413 // collect the coordinates of the face 00414 // and the normal into a matrix 00415 00416 const LOD_VertexInd * f_verts= f->m_verts; 00417 00418 const MT_Vector3 & p0 = verts[f_verts[0]].pos; 00419 const MT_Vector3 & p1 = verts[f_verts[1]].pos; 00420 const MT_Vector3 & p2 = verts[f_verts[2]].pos; 00421 00422 const MT_Vector3 c0 = m_color_editor.IndexColor(f_verts[0]); 00423 const MT_Vector3 c1 = m_color_editor.IndexColor(f_verts[1]); 00424 const MT_Vector3 c2 = m_color_editor.IndexColor(f_verts[2]); 00425 00426 // get the face normal 00427 00428 const MT_Vector3 & fn = face_normals[int(f - f_start)]; 00429 00430 // load into mat 00431 00432 int i; 00433 for (i = 0; i < 3; i++) { 00434 mat[0][i] = p0[i]; 00435 mat[1][i] = p1[i]; 00436 mat[2][i] = p2[i]; 00437 mat[3][i] = fn[i]; 00438 } 00439 mat[0][3] = MT_Scalar(1); 00440 mat[1][3] = MT_Scalar(1); 00441 mat[2][3] = MT_Scalar(1); 00442 mat[3][3] = MT_Scalar(0); 00443 00444 // Compute the pivots 00445 00446 if (TNT::LU_factor(mat,pivots)) { 00447 // bad face! 00448 continue; 00449 } 00450 00451 // compute red linear functional 00452 00453 vec[0] = c0[0]; 00454 vec[1] = c1[0]; 00455 vec[2] = c2[0]; 00456 vec[3] = MT_Scalar(0); 00457 00458 TNT::LU_solve(mat,pivots,vec); 00459 00460 // construct a quadric based on this functional 00461 00462 qp = LOD_NdQuadric( 00463 MT_Vector3(vec[0],vec[1],vec[2]), 00464 vec[3], 00465 0 00466 ); 00467 // compute green functional 00468 00469 vec[0] = c0[1]; 00470 vec[1] = c1[1]; 00471 vec[2] = c2[1]; 00472 vec[3] = MT_Scalar(0); 00473 00474 TNT::LU_solve(mat,pivots,vec); 00475 00476 // construct a quadric based on this functional 00477 00478 qp += LOD_NdQuadric( 00479 MT_Vector3(vec[0],vec[1],vec[2]), 00480 vec[3], 00481 1 00482 ); 00483 00484 // compute blue functional 00485 00486 vec[0] = c0[2]; 00487 vec[1] = c1[2]; 00488 vec[2] = c2[2]; 00489 vec[3] = MT_Scalar(0); 00490 00491 TNT::LU_solve(mat,pivots,vec); 00492 00493 // construct a quadric based on this functional 00494 00495 qp += LOD_NdQuadric( 00496 MT_Vector3(vec[0],vec[1],vec[2]), 00497 vec[3], 00498 2 00499 ); 00500 00501 // add to the geometric quadrics of each of the 00502 // vertices of f 00503 00504 qp *= MT_Scalar(50); 00505 00506 00507 quadrics[f_verts[0]] += qp; 00508 quadrics[f_verts[1]] += qp; 00509 quadrics[f_verts[2]] += qp; 00510 00511 qp.Clear(); 00512 00513 } 00514 } 00515 00516 00517