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