|
Blender
V2.59
|
00001 /* 00002 * $Id: LOD_QSDecimator.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_QSDecimator.h" 00035 00036 #include "LOD_ExternBufferEditor.h" 00037 00038 using namespace std; 00039 00040 LOD_QSDecimator * 00041 LOD_QSDecimator:: 00042 New( 00043 LOD_ManMesh2 &mesh, 00044 LOD_ExternNormalEditor &face_editor, 00045 LOD_ExternBufferEditor &extern_editor 00046 ){ 00047 00048 MEM_SmartPtr<LOD_QSDecimator> output 00049 = new LOD_QSDecimator(mesh,face_editor,extern_editor); 00050 00051 MEM_SmartPtr<LOD_EdgeCollapser > collapser(LOD_EdgeCollapser::New()); 00052 MEM_SmartPtr<LOD_QuadricEditor> q_editor(LOD_QuadricEditor::New(mesh)); 00053 00054 if ( 00055 output == NULL || 00056 collapser == NULL || 00057 q_editor == NULL 00058 ) { 00059 return NULL; 00060 } 00061 output->m_collapser = collapser.Release(); 00062 output->m_quadric_editor = q_editor.Release(); 00063 return output.Release(); 00064 } 00065 00066 00067 00068 bool 00069 LOD_QSDecimator:: 00070 Arm( 00071 ){ 00072 MT_assert(!m_is_armed); 00073 bool heap_result = BuildHeap(); 00074 if (!heap_result) { 00075 return false; 00076 } 00077 m_is_armed = true; 00078 return true; 00079 } 00080 00081 bool 00082 LOD_QSDecimator:: 00083 Step( 00084 ){ 00085 return CollapseEdge(); 00086 } 00087 00088 00089 LOD_QSDecimator:: 00090 LOD_QSDecimator( 00091 LOD_ManMesh2 &mesh, 00092 LOD_ExternNormalEditor &face_editor, 00093 LOD_ExternBufferEditor &extern_editor 00094 ) : 00095 m_is_armed (false), 00096 m_mesh(mesh), 00097 m_face_editor(face_editor), 00098 m_extern_editor(extern_editor) 00099 { 00100 m_deg_edges.reserve(32); 00101 m_deg_faces.reserve(32); 00102 m_deg_vertices.reserve(32); 00103 m_update_faces.reserve(32); 00104 m_new_edges.reserve(32); 00105 m_update_vertices.reserve(32); 00106 }; 00107 00108 bool 00109 LOD_QSDecimator:: 00110 CollapseEdge( 00111 ){ 00112 00113 // find an edge to collapse 00114 00115 // FIXME force an edge collapse 00116 // or return false 00117 00118 std::vector<LOD_Edge> & edges = m_mesh.EdgeSet(); 00119 std::vector<LOD_Vertex> & verts = m_mesh.VertexSet(); 00120 std::vector<LOD_Quadric> & quadrics = m_quadric_editor->Quadrics(); 00121 int size = edges.size(); 00122 00123 if (size == 0) return false; 00124 00125 const int heap_top = m_heap->Top(); 00126 00127 if (heap_top == -1 || edges[heap_top].HeapKey() <= -MT_INFINITY) { 00128 return false; 00129 } 00130 00131 // compute the target position 00132 MT_Vector3 new_vertex = m_quadric_editor->TargetVertex(edges[heap_top]); 00133 LOD_Quadric & q0 = quadrics[edges[heap_top].m_verts[0]]; 00134 LOD_Quadric & q1 = quadrics[edges[heap_top].m_verts[1]]; 00135 00136 LOD_Vertex &v0 = verts[edges[heap_top].m_verts[0]]; 00137 LOD_Vertex &v1 = verts[edges[heap_top].m_verts[1]]; 00138 00139 LOD_Quadric sum = q0; 00140 sum += q1; 00141 00142 00143 if (m_collapser->CollapseEdge( 00144 heap_top, 00145 m_mesh, 00146 m_deg_edges, 00147 m_deg_faces, 00148 m_deg_vertices, 00149 m_new_edges, 00150 m_update_faces, 00151 m_update_vertices 00152 )) { 00153 00154 // assign new vertex position 00155 00156 v0.pos = new_vertex; 00157 v1.pos = new_vertex; 00158 00159 // sum the quadrics of v0 and v1 00160 q0 = sum; 00161 q1 = sum; 00162 00163 // ok update the primitive properties 00164 00165 m_face_editor.Update(m_update_faces); 00166 m_face_editor.UpdateVertexNormals(m_update_vertices); 00167 00168 // update the external vertex buffer 00169 m_extern_editor.CopyModifiedVerts(m_mesh,m_update_vertices); 00170 00171 // update the external face buffer 00172 m_extern_editor.CopyModifiedFaces(m_mesh,m_update_faces); 00173 00174 // update the edge heap 00175 UpdateHeap(m_deg_edges,m_new_edges); 00176 00177 m_quadric_editor->Remove(m_deg_vertices); 00178 m_face_editor.Remove(m_deg_faces); 00179 m_face_editor.RemoveVertexNormals(m_deg_vertices); 00180 00181 // delete the primitives 00182 00183 DeletePrimitives(m_deg_edges,m_deg_faces,m_deg_vertices); 00184 00185 } else { 00186 // the edge could not be collapsed at the moment - so 00187 // we adjust it's priority and add it back to the heap. 00188 m_heap->Remove(&edges[0],0); 00189 edges[heap_top].HeapKey() = - MT_INFINITY; 00190 m_heap->Insert(&edges[0],heap_top); 00191 } 00192 00193 //clear all the temporary buffers 00194 00195 m_deg_faces.clear(); 00196 m_deg_edges.clear(); 00197 m_deg_vertices.clear(); 00198 00199 m_update_faces.clear(); 00200 m_update_vertices.clear(); 00201 m_new_edges.clear(); 00202 00203 return true; 00204 00205 } 00206 00207 void 00208 LOD_QSDecimator:: 00209 DeletePrimitives( 00210 const vector<LOD_EdgeInd> & degenerate_edges, 00211 const vector<LOD_FaceInd> & degenerate_faces, 00212 const vector<LOD_VertexInd> & degenerate_vertices 00213 ) { 00214 00215 // assumes that the 3 vectors are sorted in descending order. 00216 00217 // Delete Degnerate primitives 00219 00220 00221 // delete the old edges - we have to be very careful here 00222 // mesh.delete() swaps edges to be deleted with the last edge in 00223 // the edge buffer. However the next edge to be deleted may have 00224 // been the last edge in the buffer! 00225 00226 // One way to solve this is to sort degenerate_edges in descending order. 00227 // And then delete them in that order. 00228 00229 // it is also vital that degenerate_edges contains no duplicates 00230 00231 vector<LOD_EdgeInd>::const_iterator edge_it = degenerate_edges.begin(); 00232 vector<LOD_EdgeInd>::const_iterator edge_end = degenerate_edges.end(); 00233 00234 for (; edge_it != edge_end; ++edge_it) { 00235 m_mesh.DeleteEdge(*edge_it,m_heap); 00236 } 00237 00238 00239 00240 vector<LOD_FaceInd>::const_iterator face_it = degenerate_faces.begin(); 00241 vector<LOD_FaceInd>::const_iterator face_end = degenerate_faces.end(); 00242 00243 for (;face_it != face_end; ++face_it) { 00244 m_mesh.DeleteFace(m_extern_editor,*face_it); 00245 } 00246 00247 vector<LOD_VertexInd>::const_iterator vertex_it = degenerate_vertices.begin(); 00248 vector<LOD_VertexInd>::const_iterator vertex_end = degenerate_vertices.end(); 00249 00250 for (;vertex_it != vertex_end; ++vertex_it) { 00251 m_mesh.DeleteVertex(m_extern_editor,*vertex_it); 00252 } 00253 } 00254 00255 00256 bool 00257 LOD_QSDecimator:: 00258 BuildHeap( 00259 ){ 00260 // build the quadrics 00261 00262 if (m_quadric_editor->BuildQuadrics(m_face_editor,true) == false) return false; 00263 00264 00265 m_heap = CTR_UHeap<LOD_Edge>::New(); 00266 // load in edge pointers to the heap 00267 00268 std::vector<LOD_Edge> & edge_set= m_mesh.EdgeSet(); 00269 std::vector<LOD_Edge>::const_iterator edge_end = edge_set.end(); 00270 std::vector<LOD_Edge>::iterator edge_start = edge_set.begin(); 00271 00272 std::vector<int> & heap_vector = m_heap->HeapVector(); 00273 00274 for (unsigned int i = 0; i < edge_set.size(); ++i) { 00275 edge_set[i].HeapPos() = i; 00276 heap_vector.push_back(i); 00277 } 00278 00279 m_heap->MakeHeap(&edge_set[0]); 00280 00281 return true; 00282 } 00283 00284 void 00285 LOD_QSDecimator:: 00286 UpdateHeap( 00287 std::vector<LOD_EdgeInd> °_edges, 00288 std::vector<LOD_EdgeInd> &new_edges 00289 ){ 00290 // first of all compute values for the new edges 00291 // and bung them on the heap. 00292 00293 std::vector<LOD_Edge> & edge_set= m_mesh.EdgeSet(); 00294 00295 std::vector<LOD_EdgeInd>::const_iterator edge_it = new_edges.begin(); 00296 std::vector<LOD_EdgeInd>::const_iterator end_it = new_edges.end(); 00297 00298 00299 // insert all the new edges 00301 00302 // compute edge costs ffor the new edges 00303 00304 m_quadric_editor->ComputeEdgeCosts(new_edges); 00305 00306 // inser the new elements into the heap 00307 00308 for (; edge_it != end_it; ++edge_it) { 00309 m_heap->Insert(&edge_set[0],*edge_it); 00310 } 00311 00312 00313 // remove all the old values from the heap 00314 00315 edge_it = deg_edges.begin(); 00316 end_it = deg_edges.end(); 00317 00318 for (; edge_it != end_it; ++edge_it) { 00319 LOD_Edge &e = edge_set[*edge_it]; 00320 m_heap->Remove(&edge_set[0],e.HeapPos()); 00321 00322 e.HeapPos() = -1; 00323 00324 } 00325 } 00326