Blender  V2.59
LOD_QSDecimator.cpp
Go to the documentation of this file.
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> &deg_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