From 12315f4d0e0ae993805f141f64cb8c73c5297311 Mon Sep 17 00:00:00 2001 From: Hans Lambermont Date: Sat, 12 Oct 2002 11:37:38 +0000 Subject: Initial revision --- intern/decimation/Makefile | 52 ++ intern/decimation/extern/LOD_decimation.h | 119 ++++ intern/decimation/intern/LOD_DecimationClass.h | 118 ++++ intern/decimation/intern/LOD_EdgeCollapser.cpp | 408 ++++++++++++++ intern/decimation/intern/LOD_EdgeCollapser.h | 118 ++++ intern/decimation/intern/LOD_ExternBufferEditor.h | 164 ++++++ .../decimation/intern/LOD_ExternNormalEditor.cpp | 264 +++++++++ intern/decimation/intern/LOD_ExternNormalEditor.h | 134 +++++ intern/decimation/intern/LOD_FaceNormalEditor.cpp | 291 ++++++++++ intern/decimation/intern/LOD_FaceNormalEditor.h | 143 +++++ intern/decimation/intern/LOD_ManMesh2.cpp | 617 +++++++++++++++++++++ intern/decimation/intern/LOD_ManMesh2.h | 264 +++++++++ intern/decimation/intern/LOD_MeshBounds.h | 134 +++++ intern/decimation/intern/LOD_MeshException.h | 55 ++ intern/decimation/intern/LOD_MeshPrimitives.cpp | 407 ++++++++++++++ intern/decimation/intern/LOD_MeshPrimitives.h | 221 ++++++++ intern/decimation/intern/LOD_QSDecimator.cpp | 324 +++++++++++ intern/decimation/intern/LOD_QSDecimator.h | 128 +++++ intern/decimation/intern/LOD_Quadric.h | 168 ++++++ intern/decimation/intern/LOD_QuadricEditor.cpp | 279 ++++++++++ intern/decimation/intern/LOD_QuadricEditor.h | 119 ++++ intern/decimation/intern/LOD_decimation.cpp | 156 ++++++ intern/decimation/intern/Makefile | 45 ++ intern/decimation/make/msvc_6_0/decimation.dsp | 188 +++++++ intern/decimation/make/msvc_6_0/decimation.dsw | 33 ++ 25 files changed, 4949 insertions(+) create mode 100644 intern/decimation/Makefile create mode 100644 intern/decimation/extern/LOD_decimation.h create mode 100644 intern/decimation/intern/LOD_DecimationClass.h create mode 100644 intern/decimation/intern/LOD_EdgeCollapser.cpp create mode 100644 intern/decimation/intern/LOD_EdgeCollapser.h create mode 100644 intern/decimation/intern/LOD_ExternBufferEditor.h create mode 100644 intern/decimation/intern/LOD_ExternNormalEditor.cpp create mode 100644 intern/decimation/intern/LOD_ExternNormalEditor.h create mode 100644 intern/decimation/intern/LOD_FaceNormalEditor.cpp create mode 100644 intern/decimation/intern/LOD_FaceNormalEditor.h create mode 100644 intern/decimation/intern/LOD_ManMesh2.cpp create mode 100644 intern/decimation/intern/LOD_ManMesh2.h create mode 100644 intern/decimation/intern/LOD_MeshBounds.h create mode 100644 intern/decimation/intern/LOD_MeshException.h create mode 100644 intern/decimation/intern/LOD_MeshPrimitives.cpp create mode 100644 intern/decimation/intern/LOD_MeshPrimitives.h create mode 100644 intern/decimation/intern/LOD_QSDecimator.cpp create mode 100644 intern/decimation/intern/LOD_QSDecimator.h create mode 100644 intern/decimation/intern/LOD_Quadric.h create mode 100644 intern/decimation/intern/LOD_QuadricEditor.cpp create mode 100644 intern/decimation/intern/LOD_QuadricEditor.h create mode 100644 intern/decimation/intern/LOD_decimation.cpp create mode 100644 intern/decimation/intern/Makefile create mode 100644 intern/decimation/make/msvc_6_0/decimation.dsp create mode 100644 intern/decimation/make/msvc_6_0/decimation.dsw (limited to 'intern/decimation') diff --git a/intern/decimation/Makefile b/intern/decimation/Makefile new file mode 100644 index 00000000000..f0d9567a618 --- /dev/null +++ b/intern/decimation/Makefile @@ -0,0 +1,52 @@ +# +# $Id$ +# +# ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. The Blender +# Foundation also sells licenses for use in proprietary software under +# the Blender License. See http://www.blender.org/BL/ for information +# about this. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software Foundation, +# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +# The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. +# All rights reserved. +# +# The Original Code is: all of this file. +# +# Contributor(s): none yet. +# +# ***** END GPL/BL DUAL LICENSE BLOCK ***** +# decimation main makefile. +# + +include nan_definitions.mk + +LIBNAME = decimation +SOURCEDIR = intern/$(LIBNAME) +DIR = $(OCGDIR)/$(SOURCEDIR) +DIRS = intern +TESTDIRS = test + +include nan_subdirs.mk + +install: all debug + @[ -d $(NAN_DECIMATION) ] || mkdir $(NAN_DECIMATION) + @[ -d $(NAN_DECIMATION)/include ] || mkdir $(NAN_DECIMATION)/include + @[ -d $(NAN_DECIMATION)/lib ] || mkdir $(NAN_DECIMATION)/lib + @[ -d $(NAN_DECIMATION)/lib/debug ] || mkdir $(NAN_DECIMATION)/lib/debug + cp -f $(DIR)/libdecimation.a $(NAN_DECIMATION)/lib/ + cp -f $(DIR)/debug/libdecimation.a $(NAN_DECIMATION)/lib/debug/ + cp -f extern/*.h $(NAN_DECIMATION)/include/ + diff --git a/intern/decimation/extern/LOD_decimation.h b/intern/decimation/extern/LOD_decimation.h new file mode 100644 index 00000000000..7a74dde165a --- /dev/null +++ b/intern/decimation/extern/LOD_decimation.h @@ -0,0 +1,119 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +/** + + * @author Laurence Bourn + * @date 6/7/2001 + * + * This is the external interface for the decimation module. + */ + +#ifndef NAN_INCLUDED_LOD_decimation_h +#define NAN_INCLUDED_LOD_decimation_h + + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * External decimation structure + */ + +typedef struct LOD_Decimation_Info { + float * vertex_buffer; + float * vertex_normal_buffer; + int * triangle_index_buffer; + int vertex_num; + int face_num; + void * intern; +} LOD_Decimation_Info; + +typedef LOD_Decimation_Info* LOD_Decimation_InfoPtr; + +/** + * Create internal mesh representation from + * LOD_Decimation_Info structure. + * @return 1 on successful loading + * @return 0 on failure + * @warning This should be changed to return an enumeration + * detailing the error encountered + */ + +extern int LOD_LoadMesh(LOD_Decimation_InfoPtr info); + +/** + * Allocate and Compute internal data strucures required for + * decimation. + * @return 1 on successful computation of data + * @return 0 on failure + * @warning This should be changed to return an enumeration + * detailing the error encountered + */ + +extern int LOD_PreprocessMesh(LOD_Decimation_InfoPtr info); + +/** + * Once both the stages above have been completed + * this function collapses a single edge in the mesh. + * The LOD_Decimation_Info structure is updated + * to represent the new mesh. + * @return 1 if an edge was collapsed. + * @return 0 if no suitable edge was found to be collapsable + * You should stop calling this method in this case + * @warning Do not expect that the order of polygons, vertices or + * vertex normals will be preserved by this operation. This function + * returns a packed array of polygons and vertices and so necessarily + * the order will be different. This means you should not expect to + * find the same polygon in the same place in the polygon array after + * this function has been called. + */ + +extern int LOD_CollapseEdge(LOD_Decimation_InfoPtr info); + +/** + * Free any memory the decimation process used + * during the decimation process + * @return 1 if internal data successfully freed + * @return 0 if no data was freed + */ + +extern int LOD_FreeDecimationData(LOD_Decimation_InfoPtr); + +#ifdef __cplusplus +} +#endif + +#endif // NAN_INCLUDED_LOD_decimation_h + + + diff --git a/intern/decimation/intern/LOD_DecimationClass.h b/intern/decimation/intern/LOD_DecimationClass.h new file mode 100644 index 00000000000..7df294daaee --- /dev/null +++ b/intern/decimation/intern/LOD_DecimationClass.h @@ -0,0 +1,118 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +#ifndef NAN_INCLUDED_LOD_DecimationClass_h + +#define NAN_INCLUDED_LOD_DecimationClass_h + +#include "MEM_SmartPtr.h" +#include "MEM_NonCopyable.h" + +#include "LOD_ManMesh2.h" +#include "LOD_QSDecimator.h" +#include "LOD_ExternNormalEditor.h" +#include "../extern/LOD_decimation.h" +#include "LOD_ExternBufferEditor.h" + + +class LOD_DecimationClass : public MEM_NonCopyable +{ +public : + + enum { + e_not_loaded, + e_loaded, + e_preprocessed + } m_e_decimation_state; + + + static + LOD_DecimationClass * + New( + LOD_Decimation_InfoPtr extern_info + ) { + // create everything + + MEM_SmartPtr output(new LOD_DecimationClass()); + MEM_SmartPtr mesh(LOD_ManMesh2::New()); + MEM_SmartPtr extern_editor(LOD_ExternBufferEditor::New(extern_info)); + + if (mesh == NULL || extern_editor == NULL) return NULL; + MEM_SmartPtr normals(LOD_ExternNormalEditor::New(extern_info,mesh.Ref())); + + if (normals == NULL) return NULL; + MEM_SmartPtr decimator(LOD_QSDecimator::New( + mesh.Ref(), + normals.Ref(), + extern_editor.Ref() + )); + if (decimator == NULL || output == NULL) return NULL; + + output->m_mesh = mesh.Release(); + output->m_decimator = decimator.Release(); + output->m_normals = normals.Release(); + output->m_extern_editor = extern_editor.Release(); + + return output.Release(); + } + + LOD_ManMesh2 & + Mesh( + ){ + return m_mesh.Ref(); + } + + LOD_QSDecimator & + Decimator( + ) { + return m_decimator.Ref(); + } + + LOD_ExternNormalEditor & + FaceEditor( + ){ + return m_normals.Ref(); + } + +private : + + LOD_DecimationClass( + ) : m_e_decimation_state(e_not_loaded) { + }; + + MEM_SmartPtr m_mesh; + MEM_SmartPtr m_decimator; + MEM_SmartPtr m_normals; + MEM_SmartPtr m_extern_editor; +}; + + +#endif diff --git a/intern/decimation/intern/LOD_EdgeCollapser.cpp b/intern/decimation/intern/LOD_EdgeCollapser.cpp new file mode 100644 index 00000000000..4168a2ae371 --- /dev/null +++ b/intern/decimation/intern/LOD_EdgeCollapser.cpp @@ -0,0 +1,408 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +#include "LOD_EdgeCollapser.h" + +#include "LOD_ManMesh2.h" +#include "CTR_TaggedSetOps.h" +#include +#include + + +using namespace std; + + + LOD_EdgeCollapser * +LOD_EdgeCollapser:: +New( +){ + return new LOD_EdgeCollapser(); +} + + + bool +LOD_EdgeCollapser:: +TJunctionTest( + LOD_ManMesh2 &mesh, + vector &e_v0v1, + LOD_EdgeInd collapse_edge +){ + + // we need to copy the egdes in e_v0v1 from the mesh + // into a new buffer -> we are going to modify them + + int original_size = e_v0v1.size(); + if (original_size == 0) return true; + + vector &edge_set = mesh.EdgeSet(); + + LOD_VertexInd c_v0 = edge_set[collapse_edge].m_verts[0]; + LOD_VertexInd c_v1 = edge_set[collapse_edge].m_verts[1]; + + vector temp_edges; + temp_edges.reserve(e_v0v1.size()); + + vector::iterator edge_it = e_v0v1.begin(); + vector::const_iterator edge_end = e_v0v1.end(); + + for (;edge_it != edge_end; ++edge_it) { + temp_edges.push_back(edge_set[*edge_it]); + } + + // in the copied edges replace all instances of c_v0 with c_v1 + + vector::iterator e_it = temp_edges.begin(); + vector::const_iterator e_it_end = temp_edges.end(); + + for (; e_it != e_it_end; ++e_it) { + + if (e_it->m_verts[0] == c_v0) { + e_it->m_verts[0] = c_v1; + } + if (e_it->m_verts[1] == c_v0) { + e_it->m_verts[1] = c_v1; + } + + // normalize the edge + if (int(e_it->m_verts[0]) > int(e_it->m_verts[1])) { + LOD_EdgeInd temp = e_it->m_verts[0]; + e_it->m_verts[0] = e_it->m_verts[1]; + e_it->m_verts[1] = temp; + } + } + + // sort the edges using the edge less functional + + sort(temp_edges.begin(),temp_edges.end(),LOD_EdgeCollapser::less()); + // count the unique edges. + + e_it = temp_edges.begin(); + e_it_end = temp_edges.end(); + + int coincedent_edges = 0; + + vector::const_iterator last_edge = e_it; + ++e_it; + + for (; e_it != e_it_end; ++e_it) { + + if ((e_it->m_verts[0] == last_edge->m_verts[0]) && + (e_it->m_verts[1] == last_edge->m_verts[1]) + ) { + ++coincedent_edges; + } + last_edge = e_it; + } + + // now if the collapse edge is a boundary edges + // then we are alloved at most one coincedent edge + + // otherwise at most 2 coincedent edges + + if (edge_set[collapse_edge].BoundaryEdge()) { + return (coincedent_edges > 1); + } else { + return (coincedent_edges > 2); + } + + +} + + + + bool +LOD_EdgeCollapser:: +CollapseEdge( + LOD_EdgeInd ei, + LOD_ManMesh2 &mesh, + vector & degenerate_edges, + vector & degenerate_faces, + vector & degenerate_vertices, + vector & new_edges, + vector & update_faces, + vector & update_vertices +){ + + vector &verts = mesh.VertexSet(); + vector &edges = mesh.EdgeSet(); + vector &faces = mesh.FaceSet(); + + // shouldn't do this (use mesh interface instead!) + LOD_VertexInd v0_ind = edges[ei].m_verts[0]; + LOD_VertexInd v1_ind = edges[ei].m_verts[1]; +#if 0 + LOD_Vertex &v0 = verts[v0_ind]; + LOD_Vertex &v1 = verts[v1_ind]; +#endif + vector > e_v01(2); + e_v01[0].reserve(32); + e_v01[1].reserve(32); + + mesh.VertexEdges(v0_ind,e_v01[0]); + mesh.VertexEdges(v1_ind,e_v01[1]); + + + // compute the union of e_v0 and e_v1 -> this is the degenerate edges of the collapse + // we remove old edges and replace edges inside the collapse zone with new ones + + CTR_TaggedSetOps::Union(e_v01,edges,degenerate_edges); + + vector< vector > p_v01(2); + p_v01[0].reserve(32); + p_v01[1].reserve(32); + + mesh.VertexFaces(v0_ind,p_v01[0]); + mesh.VertexFaces(v1_ind,p_v01[1]); + + // compute the union of p_v0 anf p_v1 + vector p_v0v1; + p_v0v1.reserve(32); + + CTR_TaggedSetOps::Union(p_v01,faces,p_v0v1); + + // compute the union of all the edges in p_v0v1 this is the collapse zone + + vector > e_input_vectors(p_v0v1.size()); + + vector::iterator p_v0v1_end = p_v0v1.end(); + vector::iterator p_v0v1_start = p_v0v1.begin(); + + vector >::iterator vector_insert_it = e_input_vectors.begin(); + + for (;p_v0v1_start != p_v0v1_end; ++p_v0v1_start , ++vector_insert_it) { + mesh.FaceEdges(*p_v0v1_start,*vector_insert_it); + } + + vector collapse_zone; + collapse_zone.reserve(32); + + CTR_TaggedSetOps::Union(e_input_vectors,edges,collapse_zone); + + // compute the ring edges = collpase_zone - e_v0v1 + + vector edge_ring; + edge_ring.reserve(32); + + CTR_TaggedSetOps::Difference(collapse_zone,degenerate_edges,edges,edge_ring); + + // T Junction test + ////////////////// + // At this point we check to see if any of the polygons + // in p_v0v1 are coninceddent - this leads + // to errors later on if we try and insert a polygon + // into the mesh to an edge which already has 2 polygons. + + // not that t junctions occur naturally from edge collapses + // and are not just the result of coincedent polygons + // for example consider collapsing an edge that forms part + // of a triangular bottle neck. + + // Really we need to make sure that we don't create t-junctions. + + // I think that a sufficient test is to check the number of + // coincedent edge pairs after a collapse. If it is more than 2 + // then collapsing the edge may result in an undeleted edge + // sharing more than 2 polygons. This test probably is too + // restictive though. + + // To perform this test we need to make a copy of the edges + // in e_v0v1. We then apply the contraction to these edge + // copies. Sort them using a function that places coincedent + // edges next to each other. And then count the number + // of coincedent pairs. + + // Of course we have to do this test before we change any of the + // mesh -> so we can back out safely. + + if (TJunctionTest(mesh,degenerate_edges,ei)) return false; + + // Compute the set of possibly degenerate vertices + // this is the union of all the vertices of polygons + // of v0 and v1 + + vector::iterator face_it = p_v0v1.begin(); + vector::const_iterator face_end = p_v0v1.end(); + + + vector > p_v0v1_vertices(p_v0v1.size()); + + for (int i = 0; face_it != face_end; ++face_it, ++i) { + mesh.FaceVertices(*face_it,p_v0v1_vertices[i]); + } + + vector vertex_ring; + vertex_ring.reserve(32); + + CTR_TaggedSetOps::Union(p_v0v1_vertices,verts,vertex_ring); + + // remove all the internal edges e_v0v1 from the mesh. + // for each edge remove the egde from it's vertices edge lists. + + vector::iterator edge_it = degenerate_edges.begin(); + vector::const_iterator edge_end = degenerate_edges.end(); + + for (; edge_it != edge_end; ++edge_it) { + + LOD_Edge & edge = edges[*edge_it]; + + verts[edge.m_verts[0]].RemoveEdge(*edge_it); + verts[edge.m_verts[1]].RemoveEdge(*edge_it); + } + + // we postpone deletion of the internal edges untill the end + // this is because deleting edges invalidates all of the + // EdgeInd vectors above. + + + // now untie all the polygons in p_v0v1 from the edge ring + + // select all polygons in p_v0v1 + + face_it = p_v0v1.begin(); + face_end = p_v0v1.end(); + + for (;face_it != face_end; ++face_it) { + faces[*face_it].SetSelectTag(true); + } + + edge_it = edge_ring.begin(); + edge_end = edge_ring.end(); + + for (;edge_it != edge_end; ++edge_it) { + LOD_Edge & edge = edges[*edge_it]; + + // presumably all edges in edge_ring point to at least + // one polygon from p_v0v1 + + if (!edge.m_faces[0].IsEmpty() && faces[edge.m_faces[0]].SelectTag()) { + edge.m_faces[0].Invalidate(); + } + + if (!edge.m_faces[1].IsEmpty() && faces[edge.m_faces[1]].SelectTag()) { + edge.m_faces[1].Invalidate(); + } + } + + // deselect the faces + + face_it = p_v0v1.begin(); + face_end = p_v0v1.end(); + + for (;face_it != face_end; ++face_it) { + faces[*face_it].SetSelectTag(false); + } + + // perform the edge collapse + //////////////////////////// + + // iterate through the polygons of p_v0 and replace the vertex + // index v0 with v1 + + face_it = p_v01[0].begin(); + face_end = p_v01[0].end(); + + for (;face_it != face_end; ++face_it) { + faces[*face_it].SwapVertex(v0_ind,v1_ind); + } + + face_it = p_v0v1.begin(); + face_end = p_v0v1.end(); + + for (;face_it != face_end; ++face_it) { + if (faces[*face_it].Degenerate()) { + degenerate_faces.push_back(*face_it); + } else { + update_faces.push_back(*face_it); + } + } + + // Add all the non-degenerate faces back into the + // mesh. Get a record of the new edges created in + // this process. + + face_it = update_faces.begin(); + face_end = update_faces.end(); + + for (;face_it != face_end; ++face_it) { + mesh.ConnectTriangle(*face_it,new_edges); + } + + // degenerate ring primitives + ///////////////////////////// + + // we now need to examine each of the edges on the ring + // and work out if they are degenerate - if so we attempt + // to delete them -> add them to the other edges to delete + // in e_v0v1 + + edge_it = edge_ring.begin(); + edge_end = edge_ring.end(); + + for (;edge_it != edge_end; ++edge_it) { + if (edges[*edge_it].Degenerate()) { + degenerate_edges.push_back(*edge_it); + } + } + + // do the same for the ring vertices. + + vector::iterator vertex_it = vertex_ring.begin(); + vector::const_iterator vertex_end = vertex_ring.end(); + + for (;vertex_it != vertex_end; ++vertex_it) { + if (verts[*vertex_it].Degenerate()) { + degenerate_vertices.push_back(*vertex_it); + } else { + update_vertices.push_back(*vertex_it); + } + } + + // we now know all the degenerate primitives + // and the new primitives we have inserted into the mesh + + // We now delete the mesh primitives, mesh.DeleteXXXXXX() methods + // assume that the index vectors are sorted into descending order. + // we do that now. + + sort(degenerate_edges.begin(),degenerate_edges.end(),LOD_EdgeInd::greater()); + sort(degenerate_faces.begin(),degenerate_faces.end(),LOD_FaceInd::greater()); + sort(degenerate_vertices.begin(),degenerate_vertices.end(),LOD_VertexInd::greater()); + + + return true; + +} + +LOD_EdgeCollapser:: +LOD_EdgeCollapser( +){ + // nothing to do +} diff --git a/intern/decimation/intern/LOD_EdgeCollapser.h b/intern/decimation/intern/LOD_EdgeCollapser.h new file mode 100644 index 00000000000..d500c45e1ba --- /dev/null +++ b/intern/decimation/intern/LOD_EdgeCollapser.h @@ -0,0 +1,118 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +#ifndef NAN_INCLDUED_EgdeCollapser_h + +#define NAN_INCLDUED_EgdeCollapser_h + +// This is a helper class that collapses edges of a 2 - manifold mesh. + +#include "LOD_MeshPrimitives.h" +#include "MEM_NonCopyable.h" +#include +#include + +class LOD_ManMesh2; + +class LOD_EdgeCollapser +: public MEM_NonCopyable +{ + +public : + + static + LOD_EdgeCollapser * + New( + ); + + // returns via arguments the set of modified + // verts,edges and faces. + + bool + CollapseEdge( + LOD_EdgeInd ei, + LOD_ManMesh2 &mesh, + std::vector & degenerate_edges, + std::vector & degenerate_faces, + std::vector & degenerate_vertices, + std::vector & new_edges, + std::vector & update_faces, + std::vector & update_vertices + ); + +private : + + LOD_EdgeCollapser( + ); + + // Test to see if the result of collapsing the + // edge produces 2 junctions in the mesh i.e. where + // an edge is shared by more than 2 polygons + + // We count the number of coincedent edge pairs that + // result from the collapse of collapse_edge. + + // If collapse edge is a boundary edge then the number of + // coincedent pairs should be 1 + // else it should be 2. + + bool + TJunctionTest( + LOD_ManMesh2 &mesh, + std::vector &e_v0v1, + LOD_EdgeInd collapse_edge + ); + + // here's the definition of the sort function + // we use to determine coincedent edges + + // assumes the edges are normalized i.e. m_verts[0] <= m_verts[1] + + struct less : std::binary_function { + bool + operator()( + const LOD_Edge& a, + const LOD_Edge& b + ) const { + + if (int(a.m_verts[0]) == int(b.m_verts[0])) { + return (int(a.m_verts[1]) < int(b.m_verts[1])); + } else { + return (int(a.m_verts[0]) < int(b.m_verts[0])); + } + } + }; + +}; + + +#endif + diff --git a/intern/decimation/intern/LOD_ExternBufferEditor.h b/intern/decimation/intern/LOD_ExternBufferEditor.h new file mode 100644 index 00000000000..9f628c4455b --- /dev/null +++ b/intern/decimation/intern/LOD_ExternBufferEditor.h @@ -0,0 +1,164 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +/** + + * $Id$ + * Copyright (C) 2001 NaN Technologies B.V. + */ + +#ifndef NAN_INCLUDED_LOD_ExternBufferEditor_h +#define NAN_INCLUDED_LOD_ExternBufferEditor_h + +#include "LOD_MeshPrimitives.h" +#include +#include "LOD_ManMesh2.h" +#include "../extern/LOD_decimation.h" + + +// This class syncs external vertex/face buffers +// with the internal mesh representation during +// decimation. + +class LOD_ExternBufferEditor +{ + +public : + + static + LOD_ExternBufferEditor * + New( + LOD_Decimation_InfoPtr extern_info + ){ + if (extern_info == NULL) return NULL; + return new LOD_ExternBufferEditor(extern_info); + } + + // update the external vertex buffer with vertices + // from the mesh + + void + CopyModifiedVerts( + LOD_ManMesh2 & mesh, + const std::vector & mod_vertices + ){ + + std::vector::const_iterator v_start = mod_vertices.begin(); + std::vector::const_iterator v_end = mod_vertices.end(); + + std::vector & mesh_verts = mesh.VertexSet(); + + float * const extern_vertex_ptr = m_extern_info->vertex_buffer; + + for (; v_start != v_end; ++v_start) { + float * mod_vert = extern_vertex_ptr + int(*v_start)*3; + mesh_verts[*v_start].CopyPosition(mod_vert); + } + } + + // update the external face buffer with faces from the mesh + + void + CopyModifiedFaces( + LOD_ManMesh2 & mesh, + const std::vector & mod_faces + ){ + + std::vector::const_iterator f_start = mod_faces.begin(); + std::vector::const_iterator f_end = mod_faces.end(); + + std::vector &mesh_faces = mesh.FaceSet(); + + int * const extern_face_ptr = m_extern_info->triangle_index_buffer; + + for (; f_start != f_end; ++f_start) { + int *mod_face = extern_face_ptr + 3*int(*f_start); + mesh_faces[*f_start].CopyVerts(mod_face); + } + } + + + // Copy the last vertex over the vertex specified by + // vi. Decrement the size of the vertex array + + void + CopyBackVertex( + LOD_VertexInd vi + ){ + + float * const extern_vertex_ptr = m_extern_info->vertex_buffer; + int * extern_vertex_num = &(m_extern_info->vertex_num); + + float * last_external_vert = extern_vertex_ptr + 3*((*extern_vertex_num) - 1); + float * external_vert = extern_vertex_ptr + 3*int(vi); + + external_vert[0] = last_external_vert[0]; + external_vert[1] = last_external_vert[1]; + external_vert[2] = last_external_vert[2]; + + *extern_vertex_num -=1; + } + + // Copy the last face over the face specified by fi + // Decrement the size of the face array + + void + CopyBackFace( + LOD_FaceInd fi + ) { + int * const extern_face_ptr = m_extern_info->triangle_index_buffer; + int * extern_face_num = &(m_extern_info->face_num); + + int * last_external_face = extern_face_ptr + 3*((*extern_face_num) -1); + int * external_face = extern_face_ptr + 3*int(fi); + external_face[0] = last_external_face[0]; + external_face[1] = last_external_face[1]; + external_face[2] = last_external_face[2]; + + *extern_face_num -=1; + } + + +private : + + LOD_ExternBufferEditor( + LOD_Decimation_InfoPtr extern_info + ) : + m_extern_info (extern_info) + { + } + + LOD_Decimation_InfoPtr const m_extern_info; + +}; + +#endif + diff --git a/intern/decimation/intern/LOD_ExternNormalEditor.cpp b/intern/decimation/intern/LOD_ExternNormalEditor.cpp new file mode 100644 index 00000000000..357aaf56006 --- /dev/null +++ b/intern/decimation/intern/LOD_ExternNormalEditor.cpp @@ -0,0 +1,264 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +#include "LOD_ExternNormalEditor.h" + +#include + +using namespace std; + + +LOD_ExternNormalEditor:: +LOD_ExternNormalEditor( + LOD_Decimation_InfoPtr extern_info, + LOD_ManMesh2 &mesh +) : + m_extern_info (extern_info), + m_mesh(mesh) +{ +} + + LOD_ExternNormalEditor * +LOD_ExternNormalEditor:: +New( + LOD_Decimation_InfoPtr extern_info, + LOD_ManMesh2 &mesh +){ + if (extern_info == NULL) return NULL; + + MEM_SmartPtr output(new LOD_ExternNormalEditor(extern_info,mesh)); + + int face_num = mesh.FaceSet().size(); + + MEM_SmartPtr > normals(new vector); + + if (output == NULL || + normals == NULL + ) { + return NULL; + } + + normals->reserve(face_num); + output->m_normals = normals.Release(); + + return output.Release(); +}; + + + void +LOD_ExternNormalEditor:: +Remove( + std::vector &sorted_faces +){ + // assumes a collection of faces sorted in descending order . + + vector & normals = m_normals.Ref(); + + vector::const_iterator it_start = sorted_faces.begin(); + vector::const_iterator it_end = sorted_faces.end(); + + for (; it_start != it_end; ++it_start) { + + if (normals.size() > 0) { + MT_Vector3 temp = normals[*it_start]; + + normals[*it_start] = normals.back(); + normals.back() = temp; + + normals.pop_back(); + } + + // FIXME - throw exception + } +} + + + void +LOD_ExternNormalEditor:: +Add( +){ + MT_Vector3 zero(0.0f,0.0f,0.0f); + m_normals->push_back(zero); +}; + + void +LOD_ExternNormalEditor:: +Update( + std::vector &sorted_faces +){ + vector & normals = m_normals.Ref(); + + vector::const_iterator it_start = sorted_faces.begin(); + vector::const_iterator it_end = sorted_faces.end(); + + const vector &faces = m_mesh.FaceSet(); + + for (; it_start != it_end; ++it_start) { + normals[*it_start] = ComputeNormal(faces[*it_start]); + } +}; + + + + +// vertex normals +///////////////// + + void +LOD_ExternNormalEditor:: +RemoveVertexNormals( + std::vector &sorted_verts +){ + + float * vertex_normals = m_extern_info->vertex_normal_buffer; + + // assumption here that the vertexs normal number corresponds with + // the number of vertices ! + + int vertex_normal_num = m_extern_info->vertex_num; + + vector::const_iterator it_start = sorted_verts.begin(); + vector::const_iterator it_end = sorted_verts.end(); + + for (; it_start != it_end; ++it_start) { + + if (vertex_normal_num > 0) { + float * vertex_normal = vertex_normals + int(*it_start)*3; + float * last_vertex = vertex_normals + ((vertex_normal_num-1)*3); + + MT_Vector3 last_v(last_vertex); + last_v.getValue(vertex_normal); + vertex_normal_num--; + } + + // FIXME - through exception + } +}; + + + + void +LOD_ExternNormalEditor:: +UpdateVertexNormals( + std::vector &sorted_verts +){ + float * vertex_normals = m_extern_info->vertex_normal_buffer; + + vector::const_iterator it_start = sorted_verts.begin(); + vector::const_iterator it_end = sorted_verts.end(); + + for (; it_start != it_end; ++it_start) { + MT_Vector3 temp = ComputeVertexNormal(*it_start); + float * vertex_normal = vertex_normals + int(*it_start)*3; + temp.getValue(vertex_normal); + } +} + +// Editor specific methods +////////////////////////// + + void +LOD_ExternNormalEditor:: +BuildNormals( +) { + const vector &faces = m_mesh.FaceSet(); + vector & normals = m_normals.Ref(); + + int face_num = faces.size(); + int cur_face = 0; + + for (; cur_face < face_num; ++cur_face) { + + MT_Vector3 new_normal = ComputeNormal(faces[cur_face]); + normals.push_back(new_normal); + } +} + +const + MT_Vector3 +LOD_ExternNormalEditor:: +ComputeNormal( + const LOD_TriFace &face +) const { + + const vector &verts = m_mesh.VertexSet(); + + MT_Vector3 vec1 = + verts[face.m_verts[1]].pos - + verts[face.m_verts[0]].pos; + + MT_Vector3 vec2 = + verts[face.m_verts[2]].pos - + verts[face.m_verts[1]].pos; + + vec1 = vec1.cross(vec2); + + if (!vec1.fuzzyZero()) { + vec1.normalize(); + return (vec1); + } else { + return (MT_Vector3(1.0,0,0)); + } +} + +const + MT_Vector3 +LOD_ExternNormalEditor:: +ComputeVertexNormal( + const LOD_VertexInd v +) const { + + // average the face normals surrounding this + // vertex and normalize + vector &verts = m_mesh.VertexSet(); + const vector & face_normals = m_normals.Ref(); + + vector vertex_faces; + vertex_faces.reserve(32); + + m_mesh.VertexFaces(v,vertex_faces); + + MT_Vector3 normal(0,0,0); + + vector::const_iterator face_it = vertex_faces.begin(); + vector::const_iterator face_end = vertex_faces.end(); + + for (; face_it != face_end; ++face_it) { + normal += face_normals[*face_it]; + } + + if (!normal.fuzzyZero()) { + normal.normalize(); + return (normal); + } else { + return (MT_Vector3(1.0,0,0)); + } +} diff --git a/intern/decimation/intern/LOD_ExternNormalEditor.h b/intern/decimation/intern/LOD_ExternNormalEditor.h new file mode 100644 index 00000000000..c32b3d5a0b3 --- /dev/null +++ b/intern/decimation/intern/LOD_ExternNormalEditor.h @@ -0,0 +1,134 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +#ifndef NAN_INCLUDED_ExternNormalEditor_h + +#define NAN_INCLUDED_ExternNormalEditor_h + +#include "MEM_NonCopyable.h" +#include "LOD_ManMesh2.h" +#include "MT_Vector3.h" +#include "../extern/LOD_decimation.h" + +class LOD_ExternNormalEditor : public MEM_NonCopyable +{ + +public : + + // Creation + /////////// + + static + LOD_ExternNormalEditor * + New( + LOD_Decimation_InfoPtr, + LOD_ManMesh2 &mesh + ); + + // Property editor interface + //////////////////////////// + + + // Faces + //////// + void + Remove( + std::vector &sorted_faces + ); + + void + Add( + ); + + void + Update( + std::vector &sorted_faces + ); + + const + std::vector & + Normals( + ) const { + return m_normals.Ref(); + }; + + + // vertex normals + ///////////////// + + void + RemoveVertexNormals( + std::vector &sorted_verts + ); + + + void + UpdateVertexNormals( + std::vector &sorted_verts + ); + + // Editor specific methods + ////////////////////////// + + void + BuildNormals( + ); + + +private : + + MEM_SmartPtr > m_normals; + + LOD_ManMesh2 &m_mesh; + LOD_Decimation_InfoPtr m_extern_info; + +private : + + + LOD_ExternNormalEditor( + LOD_Decimation_InfoPtr extern_info, + LOD_ManMesh2 &mesh + ); + + const + MT_Vector3 + ComputeNormal( + const LOD_TriFace &face + ) const ; + + const + MT_Vector3 + ComputeVertexNormal ( + const LOD_VertexInd vi + ) const; +}; + +#endif diff --git a/intern/decimation/intern/LOD_FaceNormalEditor.cpp b/intern/decimation/intern/LOD_FaceNormalEditor.cpp new file mode 100644 index 00000000000..ef6bc0d252e --- /dev/null +++ b/intern/decimation/intern/LOD_FaceNormalEditor.cpp @@ -0,0 +1,291 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +// implementation of LOD_FaceNormalEditor.h + +/////////////////////////////////////// + +#include "LOD_FaceNormalEditor.h" + +using namespace std; + +LOD_FaceNormalEditor:: +LOD_FaceNormalEditor( + LOD_ManMesh2 & mesh +) : m_mesh(mesh) { +}; + + LOD_FaceNormalEditor * +LOD_FaceNormalEditor:: +New( + LOD_ManMesh2 &mesh +){ + // build a set of normals of the same size + // as the number of polys in the mesh + + MEM_SmartPtr output(new LOD_FaceNormalEditor(mesh)); + + int face_num = mesh.FaceSet().size(); + + MEM_SmartPtr > normals(new vector); + MEM_SmartPtr > vertex_normals(new vector); + + if (output == NULL || + normals == NULL + ) { + return NULL; + } + + normals->reserve(face_num); + vertex_normals->reserve(mesh.VertexSet().size()); + output->m_normals = normals.Release(); + output->m_vertex_normals = vertex_normals.Release(); + + return output.Release(); +}; + + +// Property editor interface +//////////////////////////// + + void +LOD_FaceNormalEditor:: +Remove( + std::vector &sorted_faces +){ + + // assumes a collection of faces sorted in descending order . + + vector & normals = m_normals.Ref(); + + vector::const_iterator it_start = sorted_faces.begin(); + vector::const_iterator it_end = sorted_faces.end(); + + for (; it_start != it_end; ++it_start) { + + if (normals.size() > 0) { + MT_Vector3 temp = normals[*it_start]; + + normals[*it_start] = normals.back(); + normals.back() = temp; + + normals.pop_back(); + } + + // FIXME - through exception + } +} + + + void +LOD_FaceNormalEditor:: +Add( +){ + MT_Vector3 zero(0.0f,0.0f,0.0f); + m_normals->push_back(zero); +} + + void +LOD_FaceNormalEditor:: +Update( + std::vector &sorted_faces +){ + + vector & normals = m_normals.Ref(); + + vector::const_iterator it_start = sorted_faces.begin(); + vector::const_iterator it_end = sorted_faces.end(); + + const vector &faces = m_mesh.FaceSet(); + + for (; it_start != it_end; ++it_start) { + normals[*it_start] = ComputeNormal(faces[*it_start]); + } +}; + +// vertex normals +///////////////// + + + void +LOD_FaceNormalEditor:: +RemoveVertexNormals( + vector &sorted_verts +){ + vector & vertex_normals = m_vertex_normals.Ref(); + + vector::const_iterator it_start = sorted_verts.begin(); + vector::const_iterator it_end = sorted_verts.end(); + + for (; it_start != it_end; ++it_start) { + + if (vertex_normals.size() > 0) { + MT_Vector3 temp = vertex_normals[*it_start]; + + vertex_normals[*it_start] = vertex_normals.back(); + vertex_normals.back() = temp; + + vertex_normals.pop_back(); + } + + // FIXME - through exception + } +}; + + void +LOD_FaceNormalEditor:: +UpdateVertexNormals( + vector &sorted_verts +){ + vector & vertex_normals = m_vertex_normals.Ref(); + + vector::const_iterator it_start = sorted_verts.begin(); + vector::const_iterator it_end = sorted_verts.end(); + + for (; it_start != it_end; ++it_start) { + vertex_normals[*it_start] = ComputeVertexNormal(*it_start); + } +} + + + +// Editor specific methods +////////////////////////// + + void +LOD_FaceNormalEditor:: +BuildNormals( +){ + + const vector &faces = m_mesh.FaceSet(); + vector & normals = m_normals.Ref(); + + int face_num = faces.size(); + int cur_face = 0; + + for (; cur_face < face_num; ++cur_face) { + + MT_Vector3 new_normal = ComputeNormal(faces[cur_face]); + normals.push_back(new_normal); + } + // now build the vertex normals + + vector & vertex_normals = m_vertex_normals.Ref(); + const vector &verts = m_mesh.VertexSet(); + + int vertex_num = verts.size(); + int cur_vertex = 0; + + for (; cur_vertex < vertex_num; ++cur_vertex) { + MT_Vector3 new_normal = ComputeVertexNormal(cur_vertex); + vertex_normals.push_back(new_normal); + } +} + +const + MT_Vector3 +LOD_FaceNormalEditor:: +ComputeNormal( + const LOD_TriFace &face +) const { + + const vector &verts = m_mesh.VertexSet(); + + MT_Vector3 vec1 = + verts[face.m_verts[1]].pos - + verts[face.m_verts[0]].pos; + + MT_Vector3 vec2 = + verts[face.m_verts[2]].pos - + verts[face.m_verts[1]].pos; + + vec1 = vec1.cross(vec2); + + if (!vec1.fuzzyZero()) { + vec1.normalize(); + return (vec1); + } else { + return (MT_Vector3(1.0,0,0)); + } +} + +const + MT_Vector3 +LOD_FaceNormalEditor:: +ComputeVertexNormal( + const LOD_VertexInd v +) const { + + // average the face normals surrounding this + // vertex and normalize + const vector & face_normals = m_normals.Ref(); + + vector vertex_faces; + vertex_faces.reserve(32); + + m_mesh.VertexFaces(v,vertex_faces); + + MT_Vector3 normal(0,0,0); + + vector::const_iterator face_it = vertex_faces.begin(); + vector::const_iterator face_end = vertex_faces.end(); + + for (; face_it != face_end; ++face_it) { + normal += face_normals[*face_it]; + } + + if (!normal.fuzzyZero()) { + normal.normalize(); + return (normal); + } else { + return (MT_Vector3(1.0,0,0)); + } +} + + + + + + + + + + + + + + + + + + + + diff --git a/intern/decimation/intern/LOD_FaceNormalEditor.h b/intern/decimation/intern/LOD_FaceNormalEditor.h new file mode 100644 index 00000000000..345dc4f8246 --- /dev/null +++ b/intern/decimation/intern/LOD_FaceNormalEditor.h @@ -0,0 +1,143 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +#ifndef NAN_INCLUDED_FaceNormalEditor_h + +#define NAN_INCLUDED_FaceNormalEditor_h + +#include "MEM_NonCopyable.h" +#include "LOD_ManMesh2.h" +#include "MT_Vector3.h" + + +class LOD_FaceNormalEditor : public MEM_NonCopyable +{ + +public : + + // Creation + /////////// + + static + LOD_FaceNormalEditor * + New( + LOD_ManMesh2 &mesh + ); + + // Property editor interface + //////////////////////////// + + + // Faces + //////// + void + Remove( + std::vector &sorted_faces + ); + + void + Add( + ); + + void + Update( + std::vector &sorted_faces + ); + + + // vertex normals + ///////////////// + + void + RemoveVertexNormals( + std::vector &sorted_verts + ); + + + void + UpdateVertexNormals( + std::vector &sorted_verts + ); + + + + const + std::vector & + Normals( + ) const { + return m_normals.Ref(); + }; + + + const + std::vector & + VertexNormals( + ) const { + return m_vertex_normals.Ref(); + }; + + // Editor specific methods + ////////////////////////// + + void + BuildNormals( + ); + + +private : + + MEM_SmartPtr > m_normals; + MEM_SmartPtr > m_vertex_normals; + + LOD_ManMesh2 &m_mesh; + +private : + + + LOD_FaceNormalEditor(LOD_ManMesh2 &mesh); + + const + MT_Vector3 + ComputeNormal( + const LOD_TriFace &face + ) const ; + + const + MT_Vector3 + ComputeVertexNormal ( + const LOD_VertexInd vi + ) const; + + + +}; + +#endif diff --git a/intern/decimation/intern/LOD_ManMesh2.cpp b/intern/decimation/intern/LOD_ManMesh2.cpp new file mode 100644 index 00000000000..f0bf40f577c --- /dev/null +++ b/intern/decimation/intern/LOD_ManMesh2.cpp @@ -0,0 +1,617 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +#include "LOD_ManMesh2.h" + +#include "MT_assert.h" +#include +#include "LOD_MeshException.h" +#include "CTR_TaggedSetOps.h" +#include "CTR_UHeap.h" +#include "LOD_ExternBufferEditor.h" + + +using namespace std; + +LOD_ManMesh2:: +LOD_ManMesh2( +) : + m_bbox_min(0,0,0), + m_bbox_max(0,0,0) +{ +} + + + LOD_ManMesh2 * +LOD_ManMesh2:: +New( +){ + MEM_SmartPtr output(new LOD_ManMesh2()); + if (output == NULL) return NULL; + + // build the vertex, edge and face sets. + + MEM_SmartPtr > verts(new vector); + MEM_SmartPtr > faces(new vector); + MEM_SmartPtr > edges(new vector); + + if ((faces == NULL) || (edges == NULL) || (verts == NULL)) { + return NULL; + } + + output->m_verts = verts.Release(); + output->m_faces = faces.Release(); + output->m_edges = edges.Release(); + + return output.Release(); +} + +// take ownership of the vertices. + + bool +LOD_ManMesh2:: +SetVertices( + MEM_SmartPtr > verts +){ + + + // take ownership of vertices + m_verts = verts; + + // create a polygon and edge buffer of half the size + // and just use the automatic resizing feature of vector<> + // to worry about the dynamic array resizing + + m_faces->clear(); + m_edges->clear(); + + m_faces->reserve(m_verts->size()/2); + m_edges->reserve(m_verts->size()/2); + + return true; + +} + + +// add a triangle to the mesh + + void +LOD_ManMesh2:: +AddTriangle( + int verts[3] +) { + + MT_assert(verts[0] < int(m_verts->size())); + MT_assert(verts[1] < int(m_verts->size())); + MT_assert(verts[2] < int(m_verts->size())); + + LOD_TriFace face; + face.m_verts[0] = verts[0]; + face.m_verts[1] = verts[1]; + face.m_verts[2] = verts[2]; + + LOD_FaceInd face_index = m_faces->size(); + + m_faces->push_back(face); + + // now work out if any of the directed edges or their + // companion edges exist already. + // We go through the edges associated with each of the given vertices + + // the safest thing to do is iterate through each of the edge sets + // check against each of the 2 other triangle edges to see if they are there + + vector new_edges; + new_edges.reserve(3); + + InsertEdge(verts[0],verts[1],face_index,new_edges); + InsertEdge(verts[1],verts[2],face_index,new_edges); + InsertEdge(verts[2],verts[0],face_index,new_edges); + +} + +// Adds the index of any created edges to new_edges + + bool +LOD_ManMesh2:: +InsertEdge( + const LOD_VertexInd v1, + const LOD_VertexInd v2, + const LOD_FaceInd f, + vector &new_edges +){ + + MT_assert(!v1.IsEmpty()); + MT_assert(!v2.IsEmpty()); + MT_assert(!f.IsEmpty()); + + vector &verts = VertexSet(); + vector &edges = EdgeSet(); + + LOD_EdgeInd e; + + e = FindEdge(v1,v2); + + if (e.IsEmpty()) { + // This edge does not exist -- make a new one + + LOD_Edge temp_e; + temp_e.m_verts[0] = v1; + temp_e.m_verts[1] = v2; + + e = m_edges->size(); + + // set the face ptr for this half-edge + temp_e.m_faces[0] = f; + + m_edges->push_back(temp_e); + + // add the edge index to it's vertices + + verts[v1].AddEdge(e); + verts[v2].AddEdge(e); + + new_edges.push_back(e); + + } else { + + // edge already exists + // insure that there is no polygon already + // attached to the other side of this edge + + // swap the empty face pointer in edge with f + + LOD_Edge &edge = edges[e]; + + edge.SwapFace(LOD_FaceInd::Empty(),f); + } + + + return true; + +} + + void +LOD_ManMesh2:: +ConnectTriangle( + LOD_FaceInd fi, + std::vector & new_edges +){ + + vector &faces = FaceSet(); + + MT_assert(!faces[fi].Degenerate()); + + LOD_TriFace & face = faces[fi]; + + InsertEdge(face.m_verts[0],face.m_verts[1],fi,new_edges); + InsertEdge(face.m_verts[1],face.m_verts[2],fi,new_edges); + InsertEdge(face.m_verts[2],face.m_verts[0],fi,new_edges); +}; + + + + +// geometry access +////////////////// + + vector & +LOD_ManMesh2:: +VertexSet( +) const { + return m_verts.Ref(); +} + + vector & +LOD_ManMesh2:: +FaceSet( +) const { + return m_faces.Ref(); +} + + vector & +LOD_ManMesh2:: +EdgeSet( +) const { + return m_edges.Ref(); +}; + +LOD_ManMesh2:: +~LOD_ManMesh2( +){ + //auto ptr takes care of vertex arrays etc. +} + + LOD_EdgeInd +LOD_ManMesh2:: +FindEdge( + const LOD_VertexInd v1, + const LOD_VertexInd v2 +) { + + vector &verts = VertexSet(); + vector &edges = EdgeSet(); + + LOD_Edge e; + e.m_verts[0] = v1; + e.m_verts[1] = v2; + + vector &v1_edges = verts[v1].m_edges; + vector::const_iterator v1_end = v1_edges.end(); + vector::iterator v1_begin = v1_edges.begin(); + + for (; v1_begin != v1_end; ++v1_begin) { + if (edges[*v1_begin] == e) return *v1_begin; + } + + return LOD_EdgeInd::Empty(); +} + +// face queries +/////////////// + + void +LOD_ManMesh2:: +FaceVertices( + LOD_FaceInd fi, + vector &output +){ + const vector &faces = FaceSet(); + const LOD_TriFace & f = faces[fi]; + + output.push_back(f.m_verts[0]); + output.push_back(f.m_verts[1]); + output.push_back(f.m_verts[2]); +} + + void +LOD_ManMesh2:: +FaceEdges( + LOD_FaceInd fi, + vector &output +){ + const vector &faces = FaceSet(); + vector &edges = EdgeSet(); + vector &verts = VertexSet(); + + const LOD_TriFace & f = faces[fi]; + // intersect vertex edges + + vector & v0_edges = verts[f.m_verts[0]].m_edges; + vector & v1_edges = verts[f.m_verts[1]].m_edges; + vector & v2_edges = verts[f.m_verts[2]].m_edges; + + CTR_TaggedSetOps::IntersectPair(v0_edges,v1_edges,edges,output); + CTR_TaggedSetOps::IntersectPair(v1_edges,v2_edges,edges,output); + CTR_TaggedSetOps::IntersectPair(v2_edges,v0_edges,edges,output); + + MT_assert(output.size() == 3); + if (output.size() != 3) { + LOD_MeshException e(LOD_MeshException::e_non_manifold); + throw(e); + } +} + + +// edge queries +/////////////// + + void +LOD_ManMesh2:: +EdgeVertices( + LOD_EdgeInd ei, + vector &output +){ + const vector &edges = EdgeSet(); + const LOD_Edge & e = edges[ei]; + + output.push_back(e.m_verts[0]); + output.push_back(e.m_verts[1]); +} + + void +LOD_ManMesh2:: +EdgeFaces( + LOD_EdgeInd ei, + vector &output +){ + const vector &edges = EdgeSet(); + const LOD_Edge & e = edges[ei]; + + if (!e.m_faces[0].IsEmpty()) { + output.push_back(e.m_faces[0]); + } + if (!e.m_faces[1].IsEmpty()) { + output.push_back(e.m_faces[1]); + } +} + +// vertex queries +///////////////// + + void +LOD_ManMesh2:: +VertexEdges( + LOD_VertexInd vi, + vector &output +){ + // iterate through the edges of v and push them onto the + // output + + vector &verts = VertexSet(); + + vector & v_edges = verts[vi].m_edges; + vector::iterator v_it = v_edges.begin(); + + for (; v_it != v_edges.end(); ++v_it) { + output.push_back(*v_it); + } +} + + void +LOD_ManMesh2:: +VertexFaces( + LOD_VertexInd vi, + vector &output +){ + const vector &verts = VertexSet(); + vector &edges = EdgeSet(); + vector &faces = FaceSet(); + + const vector &v_edges = verts[vi].m_edges; + vector::const_iterator e_it = v_edges.begin(); + + for (; e_it != v_edges.end(); ++e_it) { + + LOD_Edge &e = edges[*e_it]; + + if ((!e.m_faces[0].IsEmpty()) && (!faces[e.m_faces[0]].SelectTag())) { + output.push_back(e.m_faces[0]); + faces[e.m_faces[0]].SetSelectTag(true); + } + + if ((!e.m_faces[1].IsEmpty()) && (!faces[e.m_faces[1]].SelectTag())) { + output.push_back(e.m_faces[1]); + faces[e.m_faces[1]].SetSelectTag(true); + } + } + + vector::iterator f_it = output.begin(); + + for (; f_it != output.end(); ++f_it) { + faces[*f_it].SetSelectTag(false); + } +}; + + void +LOD_ManMesh2:: +SetBBox( + MT_Vector3 bbox_min, + MT_Vector3 bbox_max +){ + m_bbox_min = bbox_min; + m_bbox_max = bbox_max; +}; + + void +LOD_ManMesh2:: +SC_TriFace( + LOD_FaceInd f +){ + LOD_TriFace face = (*m_faces)[f]; + + // check for unique vertices + + if ( + (face.m_verts[0] == face.m_verts[1]) || + (face.m_verts[1] == face.m_verts[2]) || + (face.m_verts[2] == face.m_verts[0]) + ) { + MT_assert(false); + } + +} + + + void +LOD_ManMesh2:: +SC_EdgeList( + LOD_VertexInd v +){ + vector &edges = EdgeSet(); + vector &verts = VertexSet(); + + vector::iterator e_it = verts[v].m_edges.begin(); + + for (;e_it != verts[v].m_edges.end(); ++e_it) { + MT_assert( (edges[*e_it].m_verts[0] == v) || (edges[*e_it].m_verts[1] == v)); + } + +}; + + void +LOD_ManMesh2:: +DeleteVertex( + LOD_ExternBufferEditor & extern_editor, + LOD_VertexInd v +){ + + vector &edges = EdgeSet(); + vector &verts = VertexSet(); + vector &faces = FaceSet(); + + // need to update all the edge and polygons pointing to + // the last vertex in m_verts + + if (verts.size() == 1) { + verts.clear(); + return; + } + + LOD_VertexInd last = LOD_VertexInd(verts.end() - verts.begin() - 1); + + if (!(last == v)) { + + // we asume that v is already disconnected + + vector v_faces; + vector v_edges; + + v_faces.reserve(64); + v_edges.reserve(64); + + VertexFaces(last,v_faces); + VertexEdges(last,v_edges); + + // map the faces and edges to look at v + + vector::iterator face_it = v_faces.begin(); + + for(; face_it != v_faces.end(); ++face_it) { + faces[*face_it].SwapVertex(last,v); + } + vector::iterator edge_it = v_edges.begin(); + + for (; edge_it != v_edges.end(); ++edge_it) { + edges[*edge_it].SwapVertex(last,v); + } + + // copy the last vertex onto v and pop off the back. + + verts[v] = verts[last]; + + // tidy external buffer + extern_editor.CopyModifiedFaces(*this,v_faces); + } + + verts.pop_back(); + extern_editor.CopyBackVertex(v); + + +}; + + void +LOD_ManMesh2:: +DeleteEdge( + LOD_EdgeInd e, + CTR_UHeap * heap +){ + vector &edges = EdgeSet(); + vector &verts = VertexSet(); + + if (edges.size() == 1) { + edges.clear(); + return; + } + + LOD_EdgeInd last = LOD_EdgeInd(edges.end() - edges.begin() - 1); + + if (!(last == e)) { + vector e_verts; + e_verts.reserve(2); + EdgeVertices(last,e_verts); + // something is wrong if there arent two! + + verts[e_verts[0]].SwapEdge(last,e); + verts[e_verts[1]].SwapEdge(last,e); + + // edges[e] should already have been removed from the heap + + MT_assert(edges[e].HeapPos() == 0xffffffff); + + edges[e] = edges[last]; + // also have to swap there heap positions.!!!!! + + heap->HeapVector()[edges[e].HeapPos()] = e; + + + } + edges.pop_back(); +}; + + void +LOD_ManMesh2:: +DeleteFace( + LOD_ExternBufferEditor & extern_editor, + LOD_FaceInd f +){ + + vector &edges = EdgeSet(); + vector &faces = FaceSet(); + + if (faces.size() == 1) { + faces.clear(); + return; + } + + LOD_FaceInd last = LOD_FaceInd(faces.end() - faces.begin() - 1); + + if (!(last == f)) { + + // we have to update the edges which point to the last + // face + + vector f_edges; + f_edges.reserve(3); + + FaceEdges(last,f_edges); + + vector::iterator edge_it = f_edges.begin(); + vector::const_iterator edge_end = f_edges.end(); + + for (; edge_it != edge_end; ++edge_it) { + edges[*edge_it].SwapFace(last,f); + } + + faces[f] = faces[last]; + + } + faces.pop_back(); + + // tidy external buffers + extern_editor.CopyBackFace(f); +}; + + + + + + + + + + + + + + + + diff --git a/intern/decimation/intern/LOD_ManMesh2.h b/intern/decimation/intern/LOD_ManMesh2.h new file mode 100644 index 00000000000..e208155c1f0 --- /dev/null +++ b/intern/decimation/intern/LOD_ManMesh2.h @@ -0,0 +1,264 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +#ifndef NAN_INCLUDED_ManMesh2_h + +#define NAN_INCLUDED_ManMesh2_h + +#include "LOD_MeshPrimitives.h" +#include "MEM_SmartPtr.h" +#include + +template class CTR_UHeap; + +class LOD_ExternBufferEditor; + +class LOD_ManMesh2 // Manifold 2 dimensional mesh +{ + +public: + + static + LOD_ManMesh2 * + New( + ); + + // take ownership of the vertices. + + bool + SetVertices( + MEM_SmartPtr > verts + ); + + // Add a triangle to the mesh + + void + AddTriangle( + int verts[3] + ); + + void + ConnectTriangle( + LOD_FaceInd fi, + std::vector & new_edges + ); + + // geometry access + ////////////////// + + std::vector & + VertexSet( + ) const ; + + std::vector & + FaceSet( + ) const ; + + std::vector & + EdgeSet( + ) const; + + ~LOD_ManMesh2( + ); + + // local geometry queries + ///////////////////////// + + // face queries + /////////////// + + void + FaceVertices( + LOD_FaceInd f, + std::vector &output + ); + + void + FaceEdges( + LOD_FaceInd f, + std::vector &output + ); + + // edge queries + /////////////// + + void + EdgeVertices( + LOD_EdgeInd e, + std::vector &output + ); + + void + EdgeFaces( + LOD_EdgeInd e, + std::vector &output + ); + + // vertex queries + ///////////////// + + void + VertexEdges( + LOD_VertexInd v, + std::vector &output + ); + + void + VertexFaces( + LOD_VertexInd v, + std::vector &output + ); + + void + SetBBox( + MT_Vector3 bbox_min, + MT_Vector3 bbox_max + ); + + MT_Vector3 + BBoxMin( + ) const { + return m_bbox_min; + }; + + MT_Vector3 + BBoxMax( + ) const { + return m_bbox_max; + }; + + // Remove a primitive from the mesh + /////////////////////////////////// + + // These methods assume you have correctly + // tidied up the index pointers in other primitives, + // so that nothing refers to this object any more + + // These methods exchange the primitive with the + // last primitive in the vector. It modifies everything + // pointing to the last primitive correctly. + + // FIXME refactor extern editor out of primitive deletion + // insead return a vector of primitives that need to be + // modified and do this externally + + void + DeleteVertex( + LOD_ExternBufferEditor & extern_editor, + LOD_VertexInd v + ); + + void + DeleteEdge( + LOD_EdgeInd e, + CTR_UHeap *heap + ); + + void + DeleteFace( + LOD_ExternBufferEditor & extern_editor, + LOD_FaceInd f + ); + + // Sanity Check routines + //////////////////////// + + // Make sure the edge sets and the vertex sets are + // consistent + + void + SC_TriFace( + LOD_FaceInd f + ); + + // basic sanity checking of an edge list bails out if there are more than 1024 + // edges + + void + SC_EdgeList( + LOD_EdgeInd e + ); + + + // Check to see that the edges of v1 and v2 are unique. + + bool + SC_UniqueEdge( + LOD_EdgeInd e + ); + + +private : + + + // Returns the edge index of the edge from v1 to v2. + // Does this by searching the edge sets of v1 - but not v2. + // If you are paranoid you should check both and make sure the + // indices are the same. If the edge doe not exist edgeInd is empty. + + LOD_EdgeInd + FindEdge( + const LOD_VertexInd v1, + const LOD_VertexInd v2 + ); + + // Insert an edge into the mesh + // Tie up the ptrs and create space for the edge + // returns manifold errors - need to sort out memory edges + + bool + InsertEdge( + const LOD_VertexInd v1, + const LOD_VertexInd v2, + const LOD_FaceInd f, + std::vector &new_edges + ); + + +private : + + LOD_ManMesh2( + ); + + MEM_SmartPtr< std::vector > m_verts; + MEM_SmartPtr< std::vector > m_faces; + MEM_SmartPtr< std::vector > m_edges; + + // not sure of these descrtiptions of the mesh should + // reside in this class coz may lead to very bloated interface. + + MT_Vector3 m_bbox_min; + MT_Vector3 m_bbox_max; + + +}; + +#endif \ No newline at end of file diff --git a/intern/decimation/intern/LOD_MeshBounds.h b/intern/decimation/intern/LOD_MeshBounds.h new file mode 100644 index 00000000000..bb74bdb3945 --- /dev/null +++ b/intern/decimation/intern/LOD_MeshBounds.h @@ -0,0 +1,134 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +#ifndef NAN_INCLUDED_MeshBounds_h + +#define NAN_INCLUDED_MeshBounds_h + + +#include "MEM_SmartPtr.h" +#include "LOD_MeshPrimitives.h" +#include "LOD_ManMesh2.h" +#include "MT_assert.h" + +// simple class to compute the mesh bounds of a manifold mesh, + +class LOD_MeshBounds { + +public : + static + LOD_MeshBounds * + New( + ){ + + MEM_SmartPtr output(new LOD_MeshBounds()); + return output.Release(); + } + + void + ComputeBounds( + const LOD_ManMesh2 * mesh + ){ + MT_assert(mesh!=NULL); + MT_assert(mesh->VertexSet().size() > 0); + + const std::vector &verts = mesh->VertexSet(); + + m_min = verts[0].pos; + m_max = verts[0].pos; + + // iterate through the verts + + int t; + const int size = verts.size(); + + for (t=1; t< size ; ++t) { + + UpdateBounds(verts[t].pos,m_min,m_max); + } + } + + MT_Vector3 + Min( + ) const { + return m_min; + } + + MT_Vector3 + Max( + ) const { + return m_max; + } + +private : + + void + UpdateBounds( + MT_Vector3 vertex, + MT_Vector3& min, + MT_Vector3& max + ) { + if (vertex.x() < min.x()) { + min.x() = vertex.x(); + } else + if (vertex.x() > max.x()) { + max.x()= vertex.x(); + } + + if (vertex.y() < min.y()) { + min.y() = vertex.y(); + } else + if (vertex.y() > max.y()) { + max.y()= vertex.y(); + } + + if (vertex.z() < min.z()) { + min.z() = vertex.z(); + } else + if (vertex.z() > max.z()) { + max.z()= vertex.z(); + } + } + + LOD_MeshBounds( + ) : + m_min(0,0,0), + m_max(0,0,0) + { + }; + + MT_Vector3 m_min; + MT_Vector3 m_max; + +}; + + +#endif diff --git a/intern/decimation/intern/LOD_MeshException.h b/intern/decimation/intern/LOD_MeshException.h new file mode 100644 index 00000000000..4f0b8f99c38 --- /dev/null +++ b/intern/decimation/intern/LOD_MeshException.h @@ -0,0 +1,55 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +#ifndef NAN_INCLUDED_MeshExceptions_h + +#define NAN_INCLUDED_MeshExceptions_h + + +class LOD_MeshException { + +public : + + // stick in more error types as you think of them + + enum ExceptionType{ + e_non_manifold, + e_search_error + } m_e_type; + + LOD_MeshException ( + ExceptionType type + ) : m_e_type (type) + { + } +}; + +#endif diff --git a/intern/decimation/intern/LOD_MeshPrimitives.cpp b/intern/decimation/intern/LOD_MeshPrimitives.cpp new file mode 100644 index 00000000000..147e107cb4b --- /dev/null +++ b/intern/decimation/intern/LOD_MeshPrimitives.cpp @@ -0,0 +1,407 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +#include "LOD_MeshPrimitives.h" + +#include "MT_assert.h" +#include "LOD_MeshException.h" +#include + +using namespace std; + +// Vertex Methods +///////////////// + +LOD_Vertex:: +LOD_Vertex( +) : + pos (MT_Vector3()), + m_select_tag(false) +{ +}; + + bool +LOD_Vertex:: +RemoveEdge( + LOD_EdgeInd e +){ + + vector::iterator result = find(m_edges.begin(),m_edges.end(),e); + if (result == m_edges.end()) { + return false; + } + LOD_EdgeInd last = m_edges.back(); + m_edges.pop_back(); + if (m_edges.empty()) return true; + + *result = last; + return true; +}; + + void +LOD_Vertex:: +AddEdge( + LOD_EdgeInd e +){ + m_edges.push_back(e); +}; + + void +LOD_Vertex:: +SwapEdge( + LOD_EdgeInd e_old, + LOD_EdgeInd e_new +){ + + vector::iterator result = + find(m_edges.begin(),m_edges.end(),e_old); + if (result == m_edges.end()) { + MT_assert(false); + LOD_MeshException e(LOD_MeshException::e_search_error); + throw(e); + } + + *result = e_new; +}; + + bool +LOD_Vertex:: +SelectTag( +) const { + return m_select_tag; +}; + + void +LOD_Vertex:: +SetSelectTag( + bool tag +){ + m_select_tag = tag; +}; + + bool +LOD_Vertex:: +Degenerate( +){ + return m_edges.empty(); +} + + void +LOD_Vertex:: +CopyPosition( + float *float_ptr +){ + pos.getValue(float_ptr); +} + + + +// Edge Methods +/////////////// + +LOD_Edge:: +LOD_Edge ( +) { + m_verts[0] = m_verts[1] = LOD_VertexInd::Empty(); + m_faces[0] = m_faces[1] = LOD_FaceInd::Empty(); +} + + bool +LOD_Edge:: +operator == ( + LOD_Edge & rhs +) { + // edges are the same if their vertex indices are the + // same!!! Other properties are not checked + + int matches = 0; + + if (this->m_verts[0] == rhs.m_verts[0]) { + ++matches; + } + if (this->m_verts[1] == rhs.m_verts[0]) { + ++matches; + } + if (this->m_verts[0] == rhs.m_verts[1]) { + ++matches; + } + if (this->m_verts[1] == rhs.m_verts[1]) { + ++matches; + } + + if (matches >= 2) { + return true; + } + return false; +} + +// Elementary helper methods +//////////////////////////// + + LOD_FaceInd +LOD_Edge:: +OpFace( + LOD_FaceInd f +) const { + if (f == m_faces[0]) { + return m_faces[1]; + } else + if (f == m_faces[1]) { + return m_faces[0]; + } else { + MT_assert(false); + LOD_MeshException e(LOD_MeshException::e_search_error); + throw(e); + + return LOD_FaceInd::Empty(); + } +} + + void +LOD_Edge:: +SwapFace( + LOD_FaceInd old_f, + LOD_FaceInd new_f +) { + if (old_f == m_faces[0]) { + m_faces[0] = new_f; + } else + if (old_f == m_faces[1]) { + m_faces[1] = new_f; + } else { + MT_assert(false); + + LOD_MeshException e(LOD_MeshException::e_search_error); + throw(e); + } +} + + +// return the half edge face - the half edge is defined +// by the {vertex,edge} tuple. + + LOD_FaceInd +LOD_Edge:: +HalfEdgeFace( + LOD_VertexInd vi +){ + if (vi == m_verts[0]) return m_faces[0]; + if (vi == m_verts[1]) return m_faces[1]; + MT_assert(false); + + LOD_MeshException e(LOD_MeshException::e_search_error); + throw(e); + + return LOD_FaceInd::Empty(); +} + + + LOD_VertexInd +LOD_Edge:: +OpVertex( + LOD_VertexInd vi +) { + if (vi == m_verts[0]) return m_verts[1]; + if (vi == m_verts[1]) return m_verts[0]; + MT_assert(false); + + LOD_MeshException e(LOD_MeshException::e_search_error); + throw(e); + + return LOD_VertexInd::Empty(); +} + +// replace the vertex v_old with vertex v_new +// error if v_old is not one of the original vertices + + void +LOD_Edge:: +SwapVertex( + LOD_VertexInd v_old, + LOD_VertexInd v_new +) { + if (v_old == m_verts[0]) { + m_verts[0] = v_new; + } else + if (v_old == m_verts[1]) { + m_verts[1] = v_new; + } else { + + MT_assert(false); + + LOD_MeshException e(LOD_MeshException::e_search_error); + throw(e); + } + if(m_verts[0] == m_verts[1]) { + MT_assert(false); + + LOD_MeshException e(LOD_MeshException::e_non_manifold); + throw(e); + } + +} + + bool +LOD_Edge:: +SelectTag( +) const { + return bool(m_verts[1].Tag() & 0x1); +}; + + void +LOD_Edge:: +SetSelectTag( + bool tag +) { + m_verts[1].SetTag(int(tag)); +}; + + int +LOD_Edge:: +OpenTag( +) const { + return m_faces[0].Tag(); +} + + void +LOD_Edge:: +SetOpenTag( + int tag +) { + m_faces[0].SetTag(tag); +} + + bool +LOD_Edge:: +Degenerate( +) const { + return ( + (m_faces[0].IsEmpty() && m_faces[1].IsEmpty()) || + (m_verts[0] == m_verts[1]) + ); +}; + +// TriFace Methods +////////////////// + +LOD_TriFace:: +LOD_TriFace( +) { + m_verts[0] = m_verts[1] = m_verts[2] = LOD_VertexInd::Empty(); +} + +// Elementary helper methods +//////////////////////////// + + void +LOD_TriFace:: +SwapVertex( + LOD_VertexInd old_v, + LOD_VertexInd new_v +) { + // could save branching here... + + if (m_verts[0] == old_v) { + m_verts[0] = new_v; + } else + if (m_verts[1] == old_v) { + m_verts[1] = new_v; + } else + if (m_verts[2] == old_v) { + m_verts[2] = new_v; + } else { + MT_assert(false); + + LOD_MeshException excep(LOD_MeshException::e_search_error); + throw(excep); + } +} + + bool +LOD_TriFace:: +SelectTag( +) const { + return bool(m_verts[1].Tag() & 0x1); +}; + + void +LOD_TriFace:: +SetSelectTag( + bool tag +) { + m_verts[1].SetTag(int(tag)); +}; + + int +LOD_TriFace:: +OpenTag( +) { + return m_verts[2].Tag(); +} + + void +LOD_TriFace:: +SetOpenTag( + int tag +) { + m_verts[2].SetTag(tag); +} + + bool +LOD_TriFace:: +Degenerate( +) { + + return ( + (m_verts[0] == m_verts[1]) || + (m_verts[1] == m_verts[2]) || + (m_verts[2] == m_verts[0]) + ); +} + + void +LOD_TriFace:: +CopyVerts( + int * index_ptr +){ + index_ptr[0] = m_verts[0]; + index_ptr[1] = m_verts[1]; + index_ptr[2] = m_verts[2]; +}; + + + + + + + + + diff --git a/intern/decimation/intern/LOD_MeshPrimitives.h b/intern/decimation/intern/LOD_MeshPrimitives.h new file mode 100644 index 00000000000..12214c7528d --- /dev/null +++ b/intern/decimation/intern/LOD_MeshPrimitives.h @@ -0,0 +1,221 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +#ifndef NAN_INCLUDED_MeshPrimitives_h + +#define NAN_INCLUDED_MeshPrimitives_h + +#include "MT_Vector3.h" +#include "CTR_TaggedIndex.h" +#include "CTR_UHeap.h" +#include + +typedef CTR_TaggedIndex<24,0x00ffffff> LOD_VertexInd; +typedef CTR_TaggedIndex<24,0x00ffffff> LOD_EdgeInd; +typedef CTR_TaggedIndex<24,0x00ffffff> LOD_FaceInd; +typedef CTR_TaggedIndex<24,0x00ffffff> LOD_HeapInd; + +class LOD_Vertex { +public : + MT_Vector3 pos; + std::vector m_edges; + bool m_select_tag; + + LOD_Vertex( + ) ; + + bool + RemoveEdge( + LOD_EdgeInd e + ); + + void + AddEdge( + LOD_EdgeInd e + ); + + void + SwapEdge( + LOD_EdgeInd e_old, + LOD_EdgeInd e_new + ); + + bool + SelectTag( + ) const; + + void + SetSelectTag( + bool tag + ); + + bool + Degenerate( + ); + + void + CopyPosition( + float *float_ptr + ); + +private : + + +}; + +class LOD_Edge : public CTR_UHeapable { +public : + LOD_VertexInd m_verts[2]; + LOD_FaceInd m_faces[2]; + + LOD_Edge ( + ); + + bool operator == ( + LOD_Edge & rhs + ); + + // Elementary helper methods + //////////////////////////// + + LOD_FaceInd + OpFace( + LOD_FaceInd f + ) const ; + + void + SwapFace( + LOD_FaceInd old_f, + LOD_FaceInd new_f + ) ; + + + // return the half edge face - the half edge is defined + // by the {vertex,edge} tuple. + + LOD_FaceInd + HalfEdgeFace( + LOD_VertexInd vi + ); + + + LOD_VertexInd + OpVertex( + LOD_VertexInd vi + ); + + // replace the vertex v_old with vertex v_new + // error if v_old is not one of the original vertices + + void + SwapVertex( + LOD_VertexInd v_old, + LOD_VertexInd v_new + ) ; + + bool + SelectTag( + ) const ; + + void + SetSelectTag( + bool tag + ); + + int + OpenTag( + ) const; + + void + SetOpenTag( + int tag + ) ; + + bool + Degenerate( + ) const; + + bool + BoundaryEdge( + ) const { + return (m_faces[0].IsEmpty() || m_faces[1].IsEmpty()); + }; + + +}; + +class LOD_TriFace { +public: + + LOD_VertexInd m_verts[3]; + + LOD_TriFace( + ); + + // Elementary helper methods + //////////////////////////// + + void + SwapVertex( + LOD_VertexInd old_v, + LOD_VertexInd new_v + ); + + bool + SelectTag( + ) const; + + void + SetSelectTag( + bool tag + ); + + int + OpenTag( + ); + void + SetOpenTag( + int tag + ); + + bool + Degenerate( + ); + + void + CopyVerts( + int * index_ptr + ); + +}; + +#endif + diff --git a/intern/decimation/intern/LOD_QSDecimator.cpp b/intern/decimation/intern/LOD_QSDecimator.cpp new file mode 100644 index 00000000000..6620fa15ad3 --- /dev/null +++ b/intern/decimation/intern/LOD_QSDecimator.cpp @@ -0,0 +1,324 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +#include "LOD_QSDecimator.h" + +#include "LOD_ExternBufferEditor.h" + +using namespace std; + + LOD_QSDecimator * +LOD_QSDecimator:: +New( + LOD_ManMesh2 &mesh, + LOD_ExternNormalEditor &face_editor, + LOD_ExternBufferEditor &extern_editor +){ + + MEM_SmartPtr output + = new LOD_QSDecimator(mesh,face_editor,extern_editor); + + MEM_SmartPtr collapser(LOD_EdgeCollapser::New()); + MEM_SmartPtr q_editor(LOD_QuadricEditor::New(mesh)); + + if ( + output == NULL || + collapser == NULL || + q_editor == NULL + ) { + return NULL; + } + output->m_collapser = collapser.Release(); + output->m_quadric_editor = q_editor.Release(); + return output.Release(); +} + + + + bool +LOD_QSDecimator:: +Arm( +){ + MT_assert(!m_is_armed); + bool heap_result = BuildHeap(); + if (!heap_result) { + return false; + } + m_is_armed = true; + return true; +} + + bool +LOD_QSDecimator:: +Step( +){ + return CollapseEdge(); +} + + +LOD_QSDecimator:: +LOD_QSDecimator( + LOD_ManMesh2 &mesh, + LOD_ExternNormalEditor &face_editor, + LOD_ExternBufferEditor &extern_editor +) : + m_mesh(mesh), + m_face_editor(face_editor), + m_extern_editor(extern_editor), + m_is_armed (false) +{ + m_deg_edges.reserve(32); + m_deg_faces.reserve(32); + m_deg_vertices.reserve(32); + m_update_faces.reserve(32); + m_new_edges.reserve(32); + m_update_vertices.reserve(32); +}; + + bool +LOD_QSDecimator:: +CollapseEdge( +){ + + // find an edge to collapse + + // FIXME force an edge collapse + // or return false + + std::vector & edges = m_mesh.EdgeSet(); + std::vector & verts = m_mesh.VertexSet(); + std::vector & quadrics = m_quadric_editor->Quadrics(); + int size = edges.size(); + + if (size == 0) return false; + + const int heap_top = m_heap->Top(); + + if (heap_top == -1 || edges[heap_top].HeapKey() <= -MT_INFINITY) { + return false; + } + + // compute the target position + MT_Vector3 new_vertex = m_quadric_editor->TargetVertex(edges[heap_top]); + LOD_Quadric & q0 = quadrics[edges[heap_top].m_verts[0]]; + LOD_Quadric & q1 = quadrics[edges[heap_top].m_verts[1]]; + + LOD_Vertex &v0 = verts[edges[heap_top].m_verts[0]]; + LOD_Vertex &v1 = verts[edges[heap_top].m_verts[1]]; + + LOD_Quadric sum = q0; + sum += q1; + + + if (m_collapser->CollapseEdge( + heap_top, + m_mesh, + m_deg_edges, + m_deg_faces, + m_deg_vertices, + m_new_edges, + m_update_faces, + m_update_vertices + )) { + + // assign new vertex position + + v0.pos = new_vertex; + v1.pos = new_vertex; + + // sum the quadrics of v0 and v1 + q0 = sum; + q1 = sum; + + // ok update the primitive properties + + m_face_editor.Update(m_update_faces); + m_face_editor.UpdateVertexNormals(m_update_vertices); + + // update the external vertex buffer + m_extern_editor.CopyModifiedVerts(m_mesh,m_update_vertices); + + // update the external face buffer + m_extern_editor.CopyModifiedFaces(m_mesh,m_update_faces); + + // update the edge heap + UpdateHeap(m_deg_edges,m_new_edges); + + m_quadric_editor->Remove(m_deg_vertices); + m_face_editor.Remove(m_deg_faces); + m_face_editor.RemoveVertexNormals(m_deg_vertices); + + // delete the primitives + + DeletePrimitives(m_deg_edges,m_deg_faces,m_deg_vertices); + + } else { + // the edge could not be collapsed at the moment - so + // we adjust it's priority and add it back to the heap. + m_heap->Remove(edges.begin(),0); + edges[heap_top].HeapKey() = - MT_INFINITY; + m_heap->Insert(edges.begin(),heap_top); + } + + //clear all the temporary buffers + + m_deg_faces.clear(); + m_deg_edges.clear(); + m_deg_vertices.clear(); + + m_update_faces.clear(); + m_update_vertices.clear(); + m_new_edges.clear(); + + return true; + +} + + void +LOD_QSDecimator:: +DeletePrimitives( + const vector & degenerate_edges, + const vector & degenerate_faces, + const vector & degenerate_vertices +) { + + // assumes that the 3 vectors are sorted in descending order. + + // Delete Degnerate primitives + ////////////////////////////// + + + // delete the old edges - we have to be very careful here + // mesh.delete() swaps edges to be deleted with the last edge in + // the edge buffer. However the next edge to be deleted may have + // been the last edge in the buffer! + + // One way to solve this is to sort degenerate_edges in descending order. + // And then delete them in that order. + + // it is also vital that degenerate_edges contains no duplicates + + vector::const_iterator edge_it = degenerate_edges.begin(); + vector::const_iterator edge_end = degenerate_edges.end(); + + for (; edge_it != edge_end; ++edge_it) { + m_mesh.DeleteEdge(*edge_it,m_heap); + } + + + + vector::const_iterator face_it = degenerate_faces.begin(); + vector::const_iterator face_end = degenerate_faces.end(); + + for (;face_it != face_end; ++face_it) { + m_mesh.DeleteFace(m_extern_editor,*face_it); + } + + vector::const_iterator vertex_it = degenerate_vertices.begin(); + vector::const_iterator vertex_end = degenerate_vertices.end(); + + for (;vertex_it != vertex_end; ++vertex_it) { + m_mesh.DeleteVertex(m_extern_editor,*vertex_it); + } +} + + + bool +LOD_QSDecimator:: +BuildHeap( +){ + // build the quadrics + + if (m_quadric_editor->BuildQuadrics(m_face_editor,true) == false) return false; + + + m_heap = CTR_UHeap::New(); + // load in edge pointers to the heap + + std::vector & edge_set= m_mesh.EdgeSet(); + std::vector::const_iterator edge_end = edge_set.end(); + std::vector::iterator edge_start = edge_set.begin(); + + std::vector & heap_vector = m_heap->HeapVector(); + + for (int i = 0; i < edge_set.size(); ++i) { + edge_set[i].HeapPos() = i; + heap_vector.push_back(i); + } + + m_heap->MakeHeap(edge_set.begin()); + + return true; +} + + void +LOD_QSDecimator:: +UpdateHeap( + std::vector °_edges, + std::vector &new_edges +){ + // first of all compute values for the new edges + // and bung them on the heap. + + std::vector & edge_set= m_mesh.EdgeSet(); + + std::vector::const_iterator edge_it = new_edges.begin(); + std::vector::const_iterator end_it = new_edges.end(); + + + // insert all the new edges + /////////////////////////// + + // compute edge costs ffor the new edges + + m_quadric_editor->ComputeEdgeCosts(new_edges); + + // inser the new elements into the heap + + for (; edge_it != end_it; ++edge_it) { + m_heap->Insert(edge_set.begin(),*edge_it); + } + + + // remove all the old values from the heap + + edge_it = deg_edges.begin(); + end_it = deg_edges.end(); + + for (; edge_it != end_it; ++edge_it) { + LOD_Edge &e = edge_set[*edge_it]; + m_heap->Remove(edge_set.begin(),e.HeapPos()); + + e.HeapPos() = 0xffffffff; + + } +} + diff --git a/intern/decimation/intern/LOD_QSDecimator.h b/intern/decimation/intern/LOD_QSDecimator.h new file mode 100644 index 00000000000..c5ae915db29 --- /dev/null +++ b/intern/decimation/intern/LOD_QSDecimator.h @@ -0,0 +1,128 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +#ifndef NAN_INCLUDED_LOD_QSDecimator_H + +#define NAN_INCLUDED_LOD_QSDecimator_H + +#include "MEM_NonCopyable.h" +#include "LOD_ManMesh2.h" +#include "LOD_ExternNormalEditor.h" +#include "LOD_EdgeCollapser.h" +#include "LOD_QuadricEditor.h" + +class LOD_ExternBufferEditor; + +class LOD_QSDecimator : public MEM_NonCopyable { + +public : + + static + LOD_QSDecimator * + New( + LOD_ManMesh2 &mesh, + LOD_ExternNormalEditor &face_editor, + LOD_ExternBufferEditor &extern_editor + ); + + + bool + Arm( + ); + + + bool + Step( + ); + +private : + + LOD_QSDecimator( + LOD_ManMesh2 &mesh, + LOD_ExternNormalEditor &face_editor, + LOD_ExternBufferEditor &extern_editor + ); + + bool + CollapseEdge( + ); + + bool + BuildHeap( + ); + + void + UpdateHeap( + std::vector °_edges, + std::vector &new_edges + ); + + void + DeletePrimitives( + const std::vector & degenerate_edges, + const std::vector & degenerate_faces, + const std::vector & degenerate_vertices + ); + + +private : + + // owned by this class + ////////////////////// + + MEM_SmartPtr m_collapser; + MEM_SmartPtr > m_heap; + MEM_SmartPtr m_quadric_editor; + + bool m_is_armed; + + // arguments to New(...) + //////////////////////// + + LOD_ManMesh2 & m_mesh; + LOD_ExternNormalEditor &m_face_editor; + LOD_ExternBufferEditor & m_extern_editor; + + // temporary buffers + //////////////////// + + std::vector m_deg_faces; + std::vector m_deg_edges; + std::vector m_deg_vertices; + + std::vector m_update_faces; + std::vector m_new_edges; + std::vector m_update_vertices; + + +}; +#endif + diff --git a/intern/decimation/intern/LOD_Quadric.h b/intern/decimation/intern/LOD_Quadric.h new file mode 100644 index 00000000000..16e7dec17e9 --- /dev/null +++ b/intern/decimation/intern/LOD_Quadric.h @@ -0,0 +1,168 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +#ifndef NAN_INCLUDED_LOD_Quadric_h + +#define NAN_INCLUDED_LOD_Quadric_h + +#include "MT_Vector3.h" +#include "MT_Matrix3x3.h" + + +class LOD_Quadric { + +private: + MT_Scalar a2, ab, ac, ad; + MT_Scalar b2, bc, bd; + MT_Scalar c2, cd; + MT_Scalar d2; + + void init(MT_Scalar a, MT_Scalar b, MT_Scalar c, MT_Scalar d); + +public: + + LOD_Quadric( + ) { + Clear(); + }; + + LOD_Quadric( + const MT_Vector3 & vec, + const MT_Scalar & offset + ) { + a2 = vec[0] *vec[0]; + b2 = vec[1] *vec[1]; + c2 = vec[2] *vec[2]; + + ab = vec[0]*vec[1]; + ac = vec[0]*vec[2]; + bc = vec[1]*vec[2]; + + MT_Vector3 temp = vec*offset; + ad = temp[0]; + bd = temp[1]; + cd = temp[2]; + + d2 = offset*offset; + }; + + MT_Matrix3x3 + Tensor( + ) const { + // return a symmetric matrix + + return MT_Matrix3x3( + a2,ab,ac, + ab,b2,bc, + ac,bc,c2 + ); + }; + + + MT_Vector3 + Vector( + ) const { + return MT_Vector3(ad, bd, cd); + }; + + void + Clear( + MT_Scalar val=0.0 + ) { + a2=ab=ac=ad=b2=bc=bd=c2=cd=d2=val; + }; + + LOD_Quadric & + operator=( + const LOD_Quadric& Q + ) { + + a2 = Q.a2; ab = Q.ab; ac = Q.ac; ad = Q.ad; + b2 = Q.b2; bc = Q.bc; bd = Q.bd; + c2 = Q.c2; cd = Q.cd; + d2 = Q.d2; + return *this; + }; + + LOD_Quadric& + operator+=( + const LOD_Quadric& Q + ) { + a2 += Q.a2; ab += Q.ab; ac += Q.ac; ad += Q.ad; + b2 += Q.b2; bc += Q.bc; bd += Q.bd; + c2 += Q.c2; cd += Q.cd; + d2 += Q.d2; + return *this; + }; + + LOD_Quadric& + operator*=( + const MT_Scalar & s + ) { + a2 *= s; ab *= s; ac *= s; ad *= s; + b2 *= s; bc *= s; bd *= s; + c2 *= s; cd *= s; + d2 *= s; + return *this; + }; + + + MT_Scalar + Evaluate( + const MT_Vector3 &v + ) const { + // compute the LOD_Quadric error + + return v[0]*v[0]*a2 + 2*v[0]*v[1]*ab + 2*v[0]*v[2]*ac + 2*v[0]*ad + +v[1]*v[1]*b2 + 2*v[1]*v[2]*bc + 2*v[1]*bd + +v[2]*v[2]*c2 + 2*v[2]*cd + + d2; + }; + + bool + Optimize( + MT_Vector3& v + ) const { + + MT_Scalar det = Tensor().determinant(); + if (MT_fuzzyZero(det)) { + return false; + } + + v = -((Tensor().inverse()) * Vector()); + return true; + }; + +}; + + +#endif + diff --git a/intern/decimation/intern/LOD_QuadricEditor.cpp b/intern/decimation/intern/LOD_QuadricEditor.cpp new file mode 100644 index 00000000000..751f5d1e7e0 --- /dev/null +++ b/intern/decimation/intern/LOD_QuadricEditor.cpp @@ -0,0 +1,279 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +#include "LOD_QuadricEditor.h" + +#include "LOD_ExternNormalEditor.h" + +// Creation +/////////// + +using namespace std; + + +LOD_QuadricEditor:: +LOD_QuadricEditor( + LOD_ManMesh2 &mesh +) : + m_quadrics(NULL), + m_mesh(mesh) +{ +}; + + LOD_QuadricEditor * +LOD_QuadricEditor:: +New( + LOD_ManMesh2 &mesh +){ + //same number of quadrics as vertices in the mesh + + MEM_SmartPtr output(new LOD_QuadricEditor(mesh)); + + if (output == NULL) { + return NULL; + } + return output.Release(); +} + + +// Property editor interface +//////////////////////////// + + void +LOD_QuadricEditor:: +Remove( + std::vector &sorted_vertices +){ + vector & quadrics = *m_quadrics; + + vector::const_iterator it_start = sorted_vertices.begin(); + vector::const_iterator it_end = sorted_vertices.end(); + + for (; it_start != it_end; ++it_start) { + + if (quadrics.size() > 0) { + LOD_Quadric temp = quadrics[*it_start]; + + quadrics[*it_start] = quadrics.back(); + quadrics.back() = temp; + + quadrics.pop_back(); + } + } +}; + + +// Editor specific methods +////////////////////////// + + bool +LOD_QuadricEditor:: +BuildQuadrics( + LOD_ExternNormalEditor& normal_editor, + bool preserve_boundaries +){ + if (m_quadrics != NULL) delete(m_quadrics); + + m_quadrics =new vector (m_mesh.VertexSet().size()); + if (m_quadrics == NULL) return false; + + // iterate through the face set of the mesh + // compute a quadric based upon that face and + // add it to each of it's vertices quadrics. + + const vector &faces = m_mesh.FaceSet(); + const vector &verts = m_mesh.VertexSet(); + vector &edges = m_mesh.EdgeSet(); + + const vector &normals = normal_editor.Normals(); + vector::const_iterator normal_it = normals.begin(); + + vector::const_iterator face_it = faces.begin(); + vector::const_iterator face_end = faces.end(); + + vector & quadrics = *m_quadrics; + + + for (; face_it != face_end; ++face_it, ++normal_it) { + + MT_Vector3 normal = *normal_it; + MT_Scalar offset = -normal.dot(verts[face_it->m_verts[0]].pos); + + LOD_Quadric q(normal,offset); + + quadrics[face_it->m_verts[0]] += q; + quadrics[face_it->m_verts[1]] += q; + quadrics[face_it->m_verts[2]] += q; + } + + if (preserve_boundaries) { + + // iterate through the edge set and add a boundary quadric to + // each of the boundary edges vertices. + + vector::const_iterator edge_it = edges.begin(); + vector::const_iterator edge_end = edges.end(); + + for (; edge_it != edge_end; ++edge_it) { + if (edge_it->BoundaryEdge()) { + + // compute a plane perpendicular to the edge and the normal + // of the edges single polygon. + const MT_Vector3 & v0 = verts[edge_it->m_verts[0]].pos; + const MT_Vector3 & v1 = verts[edge_it->m_verts[1]].pos; + + MT_Vector3 edge_vector = v1 - v0; + + LOD_FaceInd edge_face = edge_it->OpFace(LOD_EdgeInd::Empty()); + edge_vector = edge_vector.cross(normals[edge_face]); + + if (!edge_vector.fuzzyZero()) { + edge_vector.normalize(); + + LOD_Quadric boundary_q(edge_vector, - edge_vector.dot(v0)); + boundary_q *= 100; + + quadrics[edge_it->m_verts[0]] += boundary_q; + quadrics[edge_it->m_verts[1]] += boundary_q; + } + } + } + } + + + // initiate the heap keys of the edges by computing the edge costs. + + vector::iterator edge_it = edges.begin(); + vector::const_iterator edge_end = edges.end(); + + for (; edge_it != edge_end; ++edge_it) { + + MT_Vector3 target = TargetVertex(*edge_it); + + LOD_Edge &e = *edge_it; + LOD_Quadric q0 = quadrics[e.m_verts[0]]; + const LOD_Quadric &q1 = quadrics[e.m_verts[1]]; + + e.HeapKey() = -float(q0.Evaluate(target) + q1.Evaluate(target)); + } + + return true; + +}; + + MT_Vector3 +LOD_QuadricEditor:: +TargetVertex( + LOD_Edge & e +){ + + // compute an edge contration target for edge ei + // this is computed by summing it's vertices quadrics and + // optimizing the result. + vector &verts = m_mesh.VertexSet(); + + vector &quadrics = *m_quadrics; + + LOD_VertexInd v0 = e.m_verts[0]; + LOD_VertexInd v1 = e.m_verts[1]; + + LOD_Quadric q0 = quadrics[v0]; + q0 += quadrics[v1]; + + MT_Vector3 result; + + if (q0.Optimize(result)) { + return result; + } else { + // the quadric was degenerate -> just take the average of + // v0 and v1 + + return ((verts[v0].pos + verts[v1].pos) * 0.5); + } +}; + + void +LOD_QuadricEditor:: +ComputeEdgeCosts( + vector &edges +){ + + // for each we compute the target vertex and then compute + // the quadric error e = Q1(v') + Q2(v') + vector &edge_set = m_mesh.EdgeSet(); + + vector &quadrics = *m_quadrics; + + vector::const_iterator edge_it = edges.begin(); + vector::const_iterator edge_end = edges.end(); + + for (; edge_it != edge_end; ++edge_it) { + + MT_Vector3 target = TargetVertex(edge_set[*edge_it]); + + LOD_Edge &e = edge_set[*edge_it]; + LOD_Quadric q0 = quadrics[e.m_verts[0]]; + const LOD_Quadric &q1 = quadrics[e.m_verts[1]]; + + e.HeapKey() = -float(q0.Evaluate(target) + q1.Evaluate(target)); + } +}; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/intern/decimation/intern/LOD_QuadricEditor.h b/intern/decimation/intern/LOD_QuadricEditor.h new file mode 100644 index 00000000000..bb3a5e957b9 --- /dev/null +++ b/intern/decimation/intern/LOD_QuadricEditor.h @@ -0,0 +1,119 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +#ifndef NAN_INCLUDED_LOD_QuadricEditor_h + +#define NAN_INCLUDED_LOD_QuadricEditor_h + +#include "MEM_NonCopyable.h" +#include "LOD_ManMesh2.h" +#include "MT_Vector3.h" +#include "LOD_Quadric.h" + +class LOD_ExternNormalEditor; + + +class LOD_QuadricEditor : public MEM_NonCopyable +{ + +public : + + // Creation + /////////// + + static + LOD_QuadricEditor * + New( + LOD_ManMesh2 &mesh + ); + + // Property editor interface + //////////////////////////// + + void + Remove( + std::vector &sorted_vertices + ); + + void + Update( + std::vector &sorted_vertices + ); + + + std::vector & + Quadrics( + ) const { + return *m_quadrics; + }; + + + // Editor specific methods + ////////////////////////// + + bool + BuildQuadrics( + LOD_ExternNormalEditor& normal_editor, + bool preserve_boundaries + ); + + + void + ComputeEdgeCosts( + std::vector &edges + ); + + MT_Vector3 + TargetVertex( + LOD_Edge &e + ); + + ~LOD_QuadricEditor( + ){ + delete(m_quadrics); + }; + + +private : + + std::vector * m_quadrics; + + LOD_ManMesh2 &m_mesh; + +private : + + LOD_QuadricEditor(LOD_ManMesh2 &mesh); + + + +}; + +#endif diff --git a/intern/decimation/intern/LOD_decimation.cpp b/intern/decimation/intern/LOD_decimation.cpp new file mode 100644 index 00000000000..7bbc0945424 --- /dev/null +++ b/intern/decimation/intern/LOD_decimation.cpp @@ -0,0 +1,156 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +// implementation of external c api + + +#include "../extern/LOD_decimation.h" +#include "LOD_DecimationClass.h" + +using namespace std; + + int +LOD_LoadMesh( + LOD_Decimation_InfoPtr info +) { + if (info == NULL) return 0; + if ( + info->vertex_buffer == NULL || + info->vertex_normal_buffer == NULL || + info->triangle_index_buffer == NULL + ) { + return 0; + } + + + // create the intern object to hold all + // the decimation classes + + MEM_SmartPtr intern(LOD_DecimationClass::New(info)); + + if (intern == NULL) return 0; + + MEM_SmartPtr > intern_vertex_buffer(new vector(info->vertex_num)); + if (intern_vertex_buffer == NULL) return 0; + + vector::iterator intern_vertex_it(intern_vertex_buffer->begin()); + + // now load in the vertices to the mesh + + const int vertex_stride = 3; + + float * vertex_ptr = info->vertex_buffer; + const float * vertex_end = vertex_ptr + info->vertex_num*vertex_stride; + + LOD_ManMesh2 &mesh = intern->Mesh(); + + for (;vertex_ptr < vertex_end; vertex_ptr += vertex_stride,++intern_vertex_it) { + intern_vertex_it->pos = MT_Vector3(vertex_ptr); + } + + mesh.SetVertices(intern_vertex_buffer); + + // load in the triangles + + const int triangle_stride = 3; + + int * triangle_ptr = info->triangle_index_buffer; + const int * triangle_end = triangle_ptr + info->face_num*triangle_stride; + + try { + + for (;triangle_ptr < triangle_end; triangle_ptr += triangle_stride) { + mesh.AddTriangle(triangle_ptr); + } + } + + catch (...) { + return 0; + } + + // ok we have built the mesh + + intern->m_e_decimation_state = LOD_DecimationClass::e_loaded; + + info->intern = (void *) (intern.Release()); + + return 1; +} + + int +LOD_PreprocessMesh( + LOD_Decimation_InfoPtr info +) { + if (info == NULL) return 0; + if (info->intern == NULL) return 0; + + LOD_DecimationClass *intern = (LOD_DecimationClass *) info->intern; + if (intern->m_e_decimation_state != LOD_DecimationClass::e_loaded) return 0; + + // arm the various internal classes so that we are ready to step + // through decimation + + intern->FaceEditor().BuildNormals(); + if (intern->Decimator().Arm() == false) return 0; + + // ok preprocessing done + intern->m_e_decimation_state = LOD_DecimationClass::e_preprocessed; + + return 1; +} + + int +LOD_CollapseEdge( + LOD_Decimation_InfoPtr info +){ + if (info == NULL) return 0; + if (info->intern == NULL) return 0; + LOD_DecimationClass *intern = (LOD_DecimationClass *) info->intern; + if (intern->m_e_decimation_state != LOD_DecimationClass::e_preprocessed) return 0; + + bool step_result = intern->Decimator().Step(); + + return step_result == true ? 1 : 0; +} + + + int +LOD_FreeDecimationData( + LOD_Decimation_InfoPtr info +){ + if (info == NULL) return 0; + if (info->intern == NULL) return 0; + LOD_DecimationClass *intern = (LOD_DecimationClass *) info->intern; + delete(intern); + info->intern = NULL; + return 1; +} + diff --git a/intern/decimation/intern/Makefile b/intern/decimation/intern/Makefile new file mode 100644 index 00000000000..d7c9d89d9c7 --- /dev/null +++ b/intern/decimation/intern/Makefile @@ -0,0 +1,45 @@ +# +# $Id$ +# +# ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. The Blender +# Foundation also sells licenses for use in proprietary software under +# the Blender License. See http://www.blender.org/BL/ for information +# about this. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software Foundation, +# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +# The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. +# All rights reserved. +# +# The Original Code is: all of this file. +# +# Contributor(s): none yet. +# +# ***** END GPL/BL DUAL LICENSE BLOCK ***** +# decimation intern Makefile +# + +LIBNAME = decimation +DIR = $(OCGDIR)/intern/$(LIBNAME) + +include nan_compile.mk + +CCFLAGS += $(NAN_LEVEL_2_CPP_WARNINGS) + +CPPFLAGS += -I$(NAN_MOTO)/include +CPPFLAGS += -I$(NAN_MEMUTIL)/include +CPPFLAGS += -I$(NAN_CONTAINER)/include + + diff --git a/intern/decimation/make/msvc_6_0/decimation.dsp b/intern/decimation/make/msvc_6_0/decimation.dsp new file mode 100644 index 00000000000..32d6928c61a --- /dev/null +++ b/intern/decimation/make/msvc_6_0/decimation.dsp @@ -0,0 +1,188 @@ +# Microsoft Developer Studio Project File - Name="decimation" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Static Library" 0x0104 + +CFG=decimation - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "decimation.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "decimation.mak" CFG="decimation - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "decimation - Win32 Release" (based on "Win32 (x86) Static Library") +!MESSAGE "decimation - Win32 Debug" (based on "Win32 (x86) Static Library") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "decimation - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Target_Dir "" +LINK32=link.exe -lib +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c +# ADD CPP /nologo /W3 /GX /O2 /Ob2 /I "..\..\..\..\lib\windows\container\include\\" /I "..\..\..\..\lib\windows\memutil\include\\" /I "..\..\..\..\lib\windows\moto\include\\" /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /FD /c +# SUBTRACT CPP /YX +# ADD BASE RSC /l 0x413 /d "NDEBUG" +# ADD RSC /l 0x413 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LIB32=link.exe -lib +# ADD BASE LIB32 /nologo +# ADD LIB32 /nologo /out:"Release\libdecimation.lib" +# Begin Special Build Tool +SOURCE="$(InputPath)" +PostBuild_Cmds=ECHO Copying header files COPY "..\..\extern\*.h" "..\..\..\..\lib\windows\decimation\include" ECHO Copying lib COPY "Release\libdecimation.lib" "..\..\..\..\lib\windows\decimation\lib\libdecimation.a" ECHO Done +# End Special Build Tool + +!ELSEIF "$(CFG)" == "decimation - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Target_Dir "" +LINK32=link.exe -lib +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c +# ADD CPP /nologo /W4 /Gm /GX /ZI /Od /I "..\..\..\..\lib\windows\container\include\\" /I "..\..\..\..\lib\windows\memutil\include\\" /I "..\..\..\..\lib\windows\moto\include\\" /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /FD /GZ /c +# SUBTRACT CPP /YX +# ADD BASE RSC /l 0x413 /d "_DEBUG" +# ADD RSC /l 0x413 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LIB32=link.exe -lib +# ADD BASE LIB32 /nologo +# ADD LIB32 /nologo /out:"Debug\libdecimation.lib" +# Begin Special Build Tool +SOURCE="$(InputPath)" +PostBuild_Cmds=ECHO Copying header files COPY "..\..\extern\*.h" "..\..\..\..\lib\windows\decimation\include" ECHO Copying lib COPY "Debug\libdecimation.lib" "..\..\..\..\lib\windows\decimation\lib\debug\libdecimation.a" ECHO Copying Debug info. COPY "Debug\vc60.*" "..\..\..\..\lib\windows\decimation\lib\debug\" ECHO Done +# End Special Build Tool + +!ENDIF + +# Begin Target + +# Name "decimation - Win32 Release" +# Name "decimation - Win32 Debug" +# Begin Group "intern" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\..\intern\LOD_decimation.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\intern\LOD_DecimationClass.h +# End Source File +# Begin Source File + +SOURCE=..\..\intern\LOD_EdgeCollapser.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\intern\LOD_EdgeCollapser.h +# End Source File +# Begin Source File + +SOURCE=..\..\intern\LOD_ExternBufferEditor.h +# End Source File +# Begin Source File + +SOURCE=..\..\intern\LOD_ExternNormalEditor.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\intern\LOD_ExternNormalEditor.h +# End Source File +# Begin Source File + +SOURCE=..\..\intern\LOD_FaceNormalEditor.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\intern\LOD_FaceNormalEditor.h +# End Source File +# Begin Source File + +SOURCE=..\..\intern\LOD_ManMesh2.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\intern\LOD_ManMesh2.h +# End Source File +# Begin Source File + +SOURCE=..\..\intern\LOD_MeshBounds.h +# End Source File +# Begin Source File + +SOURCE=..\..\intern\LOD_MeshException.h +# End Source File +# Begin Source File + +SOURCE=..\..\intern\LOD_MeshPrimitives.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\intern\LOD_MeshPrimitives.h +# End Source File +# Begin Source File + +SOURCE=..\..\intern\LOD_QSDecimator.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\intern\LOD_QSDecimator.h +# End Source File +# Begin Source File + +SOURCE=..\..\intern\LOD_Quadric.h +# End Source File +# Begin Source File + +SOURCE=..\..\intern\LOD_QuadricEditor.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\intern\LOD_QuadricEditor.h +# End Source File +# End Group +# Begin Group "extern" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\..\extern\LOD_decimation.h +# End Source File +# End Group +# End Target +# End Project diff --git a/intern/decimation/make/msvc_6_0/decimation.dsw b/intern/decimation/make/msvc_6_0/decimation.dsw new file mode 100644 index 00000000000..f874b324725 --- /dev/null +++ b/intern/decimation/make/msvc_6_0/decimation.dsw @@ -0,0 +1,33 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Project: "decimation"=.\decimation.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + + + + + -- cgit v1.2.3