From cc72b3e3e19558e6e6ad220fdc09f97f0e8c9540 Mon Sep 17 00:00:00 2001 From: cignoni Date: Mon, 25 Nov 2013 10:32:41 +0000 Subject: [PATCH] Include header cleaning and reordering. --- .../create/extended_marching_cubes.h | 715 +++++---- .../algorithms/create/marching_cubes.h | 1303 ++++++++--------- vcg/complex/algorithms/create/platonic.h | 395 +++-- vcg/complex/algorithms/create/zonohedron.h | 399 +++-- 4 files changed, 1399 insertions(+), 1413 deletions(-) diff --git a/vcg/complex/algorithms/create/extended_marching_cubes.h b/vcg/complex/algorithms/create/extended_marching_cubes.h index 3270a1bc..982a9f7b 100644 --- a/vcg/complex/algorithms/create/extended_marching_cubes.h +++ b/vcg/complex/algorithms/create/extended_marching_cubes.h @@ -27,342 +27,337 @@ #define __VCG_EXTENDED_MARCHING_CUBES #include -#include -#include -#include #include #include #include -#include #include -#include #include "emc_lookup_table.h" #include namespace vcg { - namespace tri - { - // Doxygen documentation - /** \addtogroup trimesh */ - /*@{*/ + namespace tri + { + // Doxygen documentation + /** \addtogroup trimesh */ + /*@{*/ - /* - * Cube description: - * 3 ________ 2 _____2__ - * /| /| / | /| - * / | / | 11/ 3 10/ | - * 7 /_______ / | /__6_|__ / |1 - * | | |6 | | | | - * | 0|__|_____|1 | |__|_0|__| - * | / | / 7 8/ 5 / - * | / | / | / | /9 - * |/_______|/ |/___4___|/ - * 4 5 - */ + /* + * Cube description: + * 3 ________ 2 _____2__ + * /| /| / | /| + * / | / | 11/ 3 10/ | + * 7 /_______ / | /__6_|__ / |1 + * | | |6 | | | | + * | 0|__|_____|1 | |__|_0|__| + * | / | / 7 8/ 5 / + * | / | / | / | /9 + * |/_______|/ |/___4___|/ + * 4 5 + */ - //! This class implements the Extended Marching Cubes algorithm. - /*! - * The implementation is enough generic: this class works only on one volume cell for each - * call to ProcessCell. Using the field value at the cell corners, it adds to the - * mesh the triangles set approximating the surface that cross that cell. - * @param TRIMESH_TYPE (Template parameter) the mesh type that will be constructed - * @param WALKER_TYPE (Template parameter) the class that implements the traversal ordering of the volume. - **/ - template - class ExtendedMarchingCubes - { - public: + //! This class implements the Extended Marching Cubes algorithm. + /*! + * The implementation is enough generic: this class works only on one volume cell for each + * call to ProcessCell. Using the field value at the cell corners, it adds to the + * mesh the triangles set approximating the surface that cross that cell. + * @param TRIMESH_TYPE (Template parameter) the mesh type that will be constructed + * @param WALKER_TYPE (Template parameter) the class that implements the traversal ordering of the volume. + **/ + template + class ExtendedMarchingCubes + { + public: #if defined(__GNUC__) - typedef unsigned int size_t; + typedef unsigned int size_t; #else #ifdef _WIN64 - typedef unsigned __int64 size_t; + typedef unsigned __int64 size_t; #else - typedef _W64 unsigned int size_t; + typedef _W64 unsigned int size_t; #endif #endif - typedef typename vcg::tri::Allocator< TRIMESH_TYPE > AllocatorType; - typedef typename TRIMESH_TYPE::ScalarType ScalarType; - typedef typename TRIMESH_TYPE::VertexType VertexType; - typedef typename TRIMESH_TYPE::VertexPointer VertexPointer; - typedef typename TRIMESH_TYPE::VertexIterator VertexIterator; - typedef typename TRIMESH_TYPE::FaceType FaceType; - typedef typename TRIMESH_TYPE::FacePointer FacePointer; - typedef typename TRIMESH_TYPE::FaceIterator FaceIterator; - typedef typename TRIMESH_TYPE::CoordType CoordType; - typedef typename TRIMESH_TYPE::CoordType* CoordPointer; + typedef typename vcg::tri::Allocator< TRIMESH_TYPE > AllocatorType; + typedef typename TRIMESH_TYPE::ScalarType ScalarType; + typedef typename TRIMESH_TYPE::VertexType VertexType; + typedef typename TRIMESH_TYPE::VertexPointer VertexPointer; + typedef typename TRIMESH_TYPE::VertexIterator VertexIterator; + typedef typename TRIMESH_TYPE::FaceType FaceType; + typedef typename TRIMESH_TYPE::FacePointer FacePointer; + typedef typename TRIMESH_TYPE::FaceIterator FaceIterator; + typedef typename TRIMESH_TYPE::CoordType CoordType; + typedef typename TRIMESH_TYPE::CoordType* CoordPointer; - struct LightEdge - { - LightEdge(size_t _face, size_t _edge):face(_face), edge(_edge) { } - size_t face, edge; - }; + struct LightEdge + { + LightEdge(size_t _face, size_t _edge):face(_face), edge(_edge) { } + size_t face, edge; + }; - /*! - * Constructor - * \param mesh The mesh that will be constructed - * \param volume The volume describing the field - * \param walker The class implementing the traversal policy - * \param angle The feature detection threshold misuring the sharpness of a feature(default is 30 degree) - */ - ExtendedMarchingCubes(TRIMESH_TYPE &mesh, WALKER_TYPE &walker, ScalarType angle=30) - { - _mesh = &mesh; - _walker = &walker; - _featureAngle = vcg::math::ToRad(angle); - _initialized = _finalized = false; - }; + /*! + * Constructor + * \param mesh The mesh that will be constructed + * \param volume The volume describing the field + * \param walker The class implementing the traversal policy + * \param angle The feature detection threshold misuring the sharpness of a feature(default is 30 degree) + */ + ExtendedMarchingCubes(TRIMESH_TYPE &mesh, WALKER_TYPE &walker, ScalarType angle=30) + { + _mesh = &mesh; + _walker = &walker; + _featureAngle = vcg::math::ToRad(angle); + _initialized = _finalized = false; + }; - /*! - * Execute the initialiazation. - * This method must be executed before the first call to ApplyEMC - */ - void Initialize() - { - assert(!_initialized && !_finalized); - _featureFlag = VertexType::NewBitFlag(); - _initialized = true; - }; + /*! + * Execute the initialiazation. + * This method must be executed before the first call to ApplyEMC + */ + void Initialize() + { + assert(!_initialized && !_finalized); + _featureFlag = VertexType::NewBitFlag(); + _initialized = true; + }; - /*! - * - * This method must be executed after the last call to ApplyEMC - */ - void Finalize() - { - assert(_initialized && !_finalized); - FlipEdges(); + /*! + * + * This method must be executed after the last call to ApplyEMC + */ + void Finalize() + { + assert(_initialized && !_finalized); + FlipEdges(); - VertexIterator v_iter = _mesh->vert.begin(); - VertexIterator v_end = _mesh->vert.end(); - for ( ; v_iter!=v_end; v_iter++) - v_iter->ClearUserBit( _featureFlag ); - VertexType::DeleteBitFlag( _featureFlag ); - _featureFlag = 0; - _mesh = NULL; - _walker = NULL; - _finalized = true; - }; + VertexIterator v_iter = _mesh->vert.begin(); + VertexIterator v_end = _mesh->vert.end(); + for ( ; v_iter!=v_end; v_iter++) + v_iter->ClearUserBit( _featureFlag ); + VertexType::DeleteBitFlag( _featureFlag ); + _featureFlag = 0; + _mesh = NULL; + _walker = NULL; + _finalized = true; + }; - /*! - * Apply the extended marching cubes algorithm to the volume cell identified by the two points min and max. - * All the three coordinates of the first point must be smaller than the respectives three coordinatas of the second point. - * \param min the first point - * \param max the second point - */ - void ProcessCell(const vcg::Point3i &min, const vcg::Point3i &max) - { - assert(_initialized && !_finalized); - assert(min[0]extended marching cubes algorithm to the volume cell identified by the two points min and max. + * All the three coordinates of the first point must be smaller than the respectives three coordinatas of the second point. + * \param min the first point + * \param max the second point + */ + void ProcessCell(const vcg::Point3i &min, const vcg::Point3i &max) + { + assert(_initialized && !_finalized); + assert(min[0]V(_corners[0].X(), _corners[0].Y(), _corners[0].Z())) >= 0) cubetype+= 1; - if ((_field[1] = _walker->V(_corners[1].X(), _corners[1].Y(), _corners[1].Z())) >= 0) cubetype+= 2; - if ((_field[2] = _walker->V(_corners[2].X(), _corners[2].Y(), _corners[2].Z())) >= 0) cubetype+= 4; - if ((_field[3] = _walker->V(_corners[3].X(), _corners[3].Y(), _corners[3].Z())) >= 0) cubetype+= 8; - if ((_field[4] = _walker->V(_corners[4].X(), _corners[4].Y(), _corners[4].Z())) >= 0) cubetype+= 16; - if ((_field[5] = _walker->V(_corners[5].X(), _corners[5].Y(), _corners[5].Z())) >= 0) cubetype+= 32; - if ((_field[6] = _walker->V(_corners[6].X(), _corners[6].Y(), _corners[6].Z())) >= 0) cubetype+= 64; - if ((_field[7] = _walker->V(_corners[7].X(), _corners[7].Y(), _corners[7].Z())) >= 0) cubetype+=128; + unsigned char cubetype = 0; + if ((_field[0] = _walker->V(_corners[0].X(), _corners[0].Y(), _corners[0].Z())) >= 0) cubetype+= 1; + if ((_field[1] = _walker->V(_corners[1].X(), _corners[1].Y(), _corners[1].Z())) >= 0) cubetype+= 2; + if ((_field[2] = _walker->V(_corners[2].X(), _corners[2].Y(), _corners[2].Z())) >= 0) cubetype+= 4; + if ((_field[3] = _walker->V(_corners[3].X(), _corners[3].Y(), _corners[3].Z())) >= 0) cubetype+= 8; + if ((_field[4] = _walker->V(_corners[4].X(), _corners[4].Y(), _corners[4].Z())) >= 0) cubetype+= 16; + if ((_field[5] = _walker->V(_corners[5].X(), _corners[5].Y(), _corners[5].Z())) >= 0) cubetype+= 32; + if ((_field[6] = _walker->V(_corners[6].X(), _corners[6].Y(), _corners[6].Z())) >= 0) cubetype+= 64; + if ((_field[7] = _walker->V(_corners[7].X(), _corners[7].Y(), _corners[7].Z())) >= 0) cubetype+=128; - if (cubetype==0 || cubetype==255) - return; + if (cubetype==0 || cubetype==255) + return; - size_t vertices_idx[12]; - memset(vertices_idx, -1, 12*sizeof(size_t)); - int code = EMCLookUpTable::EdgeTable(cubetype); - VertexPointer vp = NULL; - if ( 1&code ) { _walker->GetXIntercept(_corners[0], _corners[1], vp); vertices_idx[ 0] = vp - &_mesh->vert[0]; } - if ( 2&code ) { _walker->GetYIntercept(_corners[1], _corners[2], vp); vertices_idx[ 1] = vp - &_mesh->vert[0]; } - if ( 4&code ) { _walker->GetXIntercept(_corners[3], _corners[2], vp); vertices_idx[ 2] = vp - &_mesh->vert[0]; } - if ( 8&code ) { _walker->GetYIntercept(_corners[0], _corners[3], vp); vertices_idx[ 3] = vp - &_mesh->vert[0]; } - if ( 16&code ) { _walker->GetXIntercept(_corners[4], _corners[5], vp); vertices_idx[ 4] = vp - &_mesh->vert[0]; } - if ( 32&code ) { _walker->GetYIntercept(_corners[5], _corners[6], vp); vertices_idx[ 5] = vp - &_mesh->vert[0]; } - if ( 64&code ) { _walker->GetXIntercept(_corners[7], _corners[6], vp); vertices_idx[ 6] = vp - &_mesh->vert[0]; } - if ( 128&code ) { _walker->GetYIntercept(_corners[4], _corners[7], vp); vertices_idx[ 7] = vp - &_mesh->vert[0]; } - if ( 256&code ) { _walker->GetZIntercept(_corners[0], _corners[4], vp); vertices_idx[ 8] = vp - &_mesh->vert[0]; } - if ( 512&code ) { _walker->GetZIntercept(_corners[1], _corners[5], vp); vertices_idx[ 9] = vp - &_mesh->vert[0]; } - if (1024&code ) { _walker->GetZIntercept(_corners[2], _corners[6], vp); vertices_idx[10] = vp - &_mesh->vert[0]; } - if (2048&code ) { _walker->GetZIntercept(_corners[3], _corners[7], vp); vertices_idx[11] = vp - &_mesh->vert[0]; } + size_t vertices_idx[12]; + memset(vertices_idx, -1, 12*sizeof(size_t)); + int code = EMCLookUpTable::EdgeTable(cubetype); + VertexPointer vp = NULL; + if ( 1&code ) { _walker->GetXIntercept(_corners[0], _corners[1], vp); vertices_idx[ 0] = vp - &_mesh->vert[0]; } + if ( 2&code ) { _walker->GetYIntercept(_corners[1], _corners[2], vp); vertices_idx[ 1] = vp - &_mesh->vert[0]; } + if ( 4&code ) { _walker->GetXIntercept(_corners[3], _corners[2], vp); vertices_idx[ 2] = vp - &_mesh->vert[0]; } + if ( 8&code ) { _walker->GetYIntercept(_corners[0], _corners[3], vp); vertices_idx[ 3] = vp - &_mesh->vert[0]; } + if ( 16&code ) { _walker->GetXIntercept(_corners[4], _corners[5], vp); vertices_idx[ 4] = vp - &_mesh->vert[0]; } + if ( 32&code ) { _walker->GetYIntercept(_corners[5], _corners[6], vp); vertices_idx[ 5] = vp - &_mesh->vert[0]; } + if ( 64&code ) { _walker->GetXIntercept(_corners[7], _corners[6], vp); vertices_idx[ 6] = vp - &_mesh->vert[0]; } + if ( 128&code ) { _walker->GetYIntercept(_corners[4], _corners[7], vp); vertices_idx[ 7] = vp - &_mesh->vert[0]; } + if ( 256&code ) { _walker->GetZIntercept(_corners[0], _corners[4], vp); vertices_idx[ 8] = vp - &_mesh->vert[0]; } + if ( 512&code ) { _walker->GetZIntercept(_corners[1], _corners[5], vp); vertices_idx[ 9] = vp - &_mesh->vert[0]; } + if (1024&code ) { _walker->GetZIntercept(_corners[2], _corners[6], vp); vertices_idx[10] = vp - &_mesh->vert[0]; } + if (2048&code ) { _walker->GetZIntercept(_corners[3], _corners[7], vp); vertices_idx[11] = vp - &_mesh->vert[0]; } - int m, n, vertices_num; - int components = EMCLookUpTable::TriTable(cubetype, 1)[0]; //unsigned int components = triTable[cubetype][1][0]; - int *indices = &EMCLookUpTable::TriTable(cubetype, 1)[components+1]; //int *indices = &EMCLookUpTable::TriTable(cubetype, 1, components+1); + int m, n, vertices_num; + int components = EMCLookUpTable::TriTable(cubetype, 1)[0]; //unsigned int components = triTable[cubetype][1][0]; + int *indices = &EMCLookUpTable::TriTable(cubetype, 1)[components+1]; //int *indices = &EMCLookUpTable::TriTable(cubetype, 1, components+1); - std::vector< size_t > vertices_list; - for (m=1; m<=components; m++) - { - // current sheet contains vertices_num vertices - vertices_num = EMCLookUpTable::TriTable(cubetype, 1)[m]; //vertices_num = triTable[cubetype][1][m]; + std::vector< size_t > vertices_list; + for (m=1; m<=components; m++) + { + // current sheet contains vertices_num vertices + vertices_num = EMCLookUpTable::TriTable(cubetype, 1)[m]; //vertices_num = triTable[cubetype][1][m]; - // collect vertices - vertices_list.clear(); - for (n=0; n create triangle fan around feature vertex - size_t feature_idx = feature - &_mesh->vert[0]; - size_t face_idx = _mesh->face.size(); - vertices_list.push_back( vertices_list[0] ); - AllocatorType::AddFaces(*_mesh, (int) vertices_num); - for (int j=0; jface[face_idx].V(0) = &_mesh->vert[ vertices_list[j ] ]; - _mesh->face[face_idx].V(1) = &_mesh->vert[ vertices_list[j+1] ]; - _mesh->face[face_idx].V(2) = &_mesh->vert[ feature_idx ]; - } - } - else - { - // no feature -> old marching cubes triangle table - for (int j=0; EMCLookUpTable::PolyTable(vertices_num, j) != -1; j+=3) //for (int j=0; polyTable[vertices_num][j] != -1; j+=3) - { - size_t face_idx = _mesh->face.size(); - AllocatorType::AddFaces(*_mesh, 1); - //_mesh->face[ face_idx].V(0) = &_mesh->vert[ vertices_idx[ indices[ polyTable[vertices_num][j ] ] ] ]; - //_mesh->face[ face_idx].V(1) = &_mesh->vert[ vertices_idx[ indices[ polyTable[vertices_num][j+1] ] ] ]; - //_mesh->face[ face_idx].V(2) = &_mesh->vert[ vertices_idx[ indices[ polyTable[vertices_num][j+2] ] ] ]; - _mesh->face[ face_idx].V(0) = &_mesh->vert[ vertices_idx[ indices[ EMCLookUpTable::PolyTable(vertices_num, j ) ] ] ]; - _mesh->face[ face_idx].V(1) = &_mesh->vert[ vertices_idx[ indices[ EMCLookUpTable::PolyTable(vertices_num, j+1) ] ] ]; - _mesh->face[ face_idx].V(2) = &_mesh->vert[ vertices_idx[ indices[ EMCLookUpTable::PolyTable(vertices_num, j+2) ] ] ]; - } - } - indices += vertices_num; + VertexPointer feature = FindFeature( vertices_list ); + if (feature != NULL) // i.e. is a valid vertex + { + // feature -> create triangle fan around feature vertex + size_t feature_idx = feature - &_mesh->vert[0]; + size_t face_idx = _mesh->face.size(); + vertices_list.push_back( vertices_list[0] ); + AllocatorType::AddFaces(*_mesh, (int) vertices_num); + for (int j=0; jface[face_idx].V(0) = &_mesh->vert[ vertices_list[j ] ]; + _mesh->face[face_idx].V(1) = &_mesh->vert[ vertices_list[j+1] ]; + _mesh->face[face_idx].V(2) = &_mesh->vert[ feature_idx ]; + } + } + else + { + // no feature -> old marching cubes triangle table + for (int j=0; EMCLookUpTable::PolyTable(vertices_num, j) != -1; j+=3) //for (int j=0; polyTable[vertices_num][j] != -1; j+=3) + { + size_t face_idx = _mesh->face.size(); + AllocatorType::AddFaces(*_mesh, 1); + //_mesh->face[ face_idx].V(0) = &_mesh->vert[ vertices_idx[ indices[ polyTable[vertices_num][j ] ] ] ]; + //_mesh->face[ face_idx].V(1) = &_mesh->vert[ vertices_idx[ indices[ polyTable[vertices_num][j+1] ] ] ]; + //_mesh->face[ face_idx].V(2) = &_mesh->vert[ vertices_idx[ indices[ polyTable[vertices_num][j+2] ] ] ]; + _mesh->face[ face_idx].V(0) = &_mesh->vert[ vertices_idx[ indices[ EMCLookUpTable::PolyTable(vertices_num, j ) ] ] ]; + _mesh->face[ face_idx].V(1) = &_mesh->vert[ vertices_idx[ indices[ EMCLookUpTable::PolyTable(vertices_num, j+1) ] ] ]; + _mesh->face[ face_idx].V(2) = &_mesh->vert[ vertices_idx[ indices[ EMCLookUpTable::PolyTable(vertices_num, j+2) ] ] ]; + } + } + indices += vertices_num; - } - }; // end of ApplyEMC + } + }; // end of ApplyEMC - private: - /*! - */ - WALKER_TYPE *_walker; - /*! - */ - TRIMESH_TYPE *_mesh; - /*! - */ - bool _initialized;; - /*! - */ - bool _finalized; - /*! - * The feature detection threshold misuring the sharpness of a feature - */ - ScalarType _featureAngle; - /*! - * The flag used for marking the feature vertices. - */ - int _featureFlag; - /*! - * Array of the 8 corners of the volume cell being processed - */ - vcg::Point3i _corners[8]; - /*! - * The field value at the cell corners - */ - ScalarType _field[8]; + private: + /*! + */ + WALKER_TYPE *_walker; + /*! + */ + TRIMESH_TYPE *_mesh; + /*! + */ + bool _initialized;; + /*! + */ + bool _finalized; + /*! + * The feature detection threshold misuring the sharpness of a feature + */ + ScalarType _featureAngle; + /*! + * The flag used for marking the feature vertices. + */ + int _featureFlag; + /*! + * Array of the 8 corners of the volume cell being processed + */ + vcg::Point3i _corners[8]; + /*! + * The field value at the cell corners + */ + ScalarType _field[8]; - /*! - * Tests if the surface patch crossing the current cell contains a sharp feature - * \param vertices_idx The list of vertex indices intersecting the edges of the current cell - * \return The pointer to the new Vertex if a feature is detected; NULL otherwise. - */ - VertexPointer FindFeature(const std::vector &vertices_idx) - { - unsigned int i, j, rank; - size_t vertices_num = (size_t) vertices_idx.size(); + /*! + * Tests if the surface patch crossing the current cell contains a sharp feature + * \param vertices_idx The list of vertex indices intersecting the edges of the current cell + * \return The pointer to the new Vertex if a feature is detected; NULL otherwise. + */ + VertexPointer FindFeature(const std::vector &vertices_idx) + { + unsigned int i, j, rank; + size_t vertices_num = (size_t) vertices_idx.size(); - CoordType *points = new CoordType[ vertices_num ]; - CoordType *normals = new CoordType[ vertices_num ]; - Box3 bb; - for (i=0; ivert[ vertices_idx[i] ].P(); - normals[i].Import(_mesh->vert[ vertices_idx[i] ].N()); - bb.Add(points[i]); - } + CoordType *points = new CoordType[ vertices_num ]; + CoordType *normals = new CoordType[ vertices_num ]; + Box3 bb; + for (i=0; ivert[ vertices_idx[i] ].P(); + normals[i].Import(_mesh->vert[ vertices_idx[i] ].N()); + bb.Add(points[i]); + } - // move barycenter of points into (0, 0, 0) - CoordType center((ScalarType) 0.0, (ScalarType) 0.0, (ScalarType) 0.0); - for (i=0; i cos(_featureAngle)) - return NULL; // invalid vertex + if (minC > cos(_featureAngle)) + return NULL; // invalid vertex - // ok, we have a feature: is it edge or corner, i.e. rank 2 or 3 ? - axis.Normalize(); - for (minC=1.0, maxC=-1.0, i=0; i maxC) maxC = c; - } - c = std::max< double >(fabs(minC), fabs(maxC)); - c = sqrt(1.0-c*c); - rank = (c > cos(_featureAngle) ? 2 : 3); + // ok, we have a feature: is it edge or corner, i.e. rank 2 or 3 ? + axis.Normalize(); + for (minC=1.0, maxC=-1.0, i=0; i maxC) maxC = c; + } + c = std::max< double >(fabs(minC), fabs(maxC)); + c = sqrt(1.0-c*c); + rank = (c > cos(_featureAngle) ? 2 : 3); - // setup linear system (find intersection of tangent planes) - //--vcg::ndim::Matrix A((unsigned int) vertices_num, 3); - Eigen::MatrixXd A(vertices_num,3); + // setup linear system (find intersection of tangent planes) + //--vcg::ndim::Matrix A((unsigned int) vertices_num, 3); + Eigen::MatrixXd A(vertices_num,3); - //--double *b = new double[ vertices_num ]; - Eigen::MatrixXd b(vertices_num,1); + //--double *b = new double[ vertices_num ]; + Eigen::MatrixXd b(vertices_num,1); - for (i=0; i svd(A, Eigen::ComputeThinU | Eigen::ComputeThinV); - Eigen::MatrixXd sol(3,1); - sol=svd.solve(b); + // SVD of matrix A + Eigen::JacobiSVD svd(A, Eigen::ComputeThinU | Eigen::ComputeThinV); + Eigen::MatrixXd sol(3,1); + sol=svd.solve(b); - // vcg::ndim::Matrix V(3, 3); - // double *w = new double[vertices_num]; - // vcg::SingularValueDecomposition< typename vcg::ndim::Matrix > (A, w, V, LeaveUnsorted, 100); + // vcg::ndim::Matrix V(3, 3); + // double *w = new double[vertices_num]; + // vcg::SingularValueDecomposition< typename vcg::ndim::Matrix > (A, w, V, LeaveUnsorted, 100); - // rank == 2 -> suppress smallest singular value + // rank == 2 -> suppress smallest singular value // if (rank == 2) // { // double smin = DBL_MAX; // the max value, as defined in @@ -384,91 +379,91 @@ namespace vcg // double *x = new double[3]; // vcg::SingularValueBacksubstitution< vcg::ndim::Matrix >(A, w, V, x, b); - // transform x to world coords - //--CoordType point((ScalarType) x[0], (ScalarType) x[1], (ScalarType) x[2]); - CoordType point((ScalarType) sol(0), (ScalarType) sol(1), (ScalarType) sol(2)); - point += center; + // transform x to world coords + //--CoordType point((ScalarType) x[0], (ScalarType) x[1], (ScalarType) x[2]); + CoordType point((ScalarType) sol(0), (ScalarType) sol(1), (ScalarType) sol(2)); + point += center; // Safety check if the feature point found by svd is // out of the bbox of the vertices perhaps it is better to put it back in the center... if(!bb.IsIn(point)) point = center; - // insert the feature-point - VertexPointer mean_point = &*AllocatorType::AddVertices( *_mesh, 1); - mean_point->SetUserBit(_featureFlag); - mean_point->P() = point; - mean_point->N().SetZero(); + // insert the feature-point + VertexPointer mean_point = &*AllocatorType::AddVertices( *_mesh, 1); + mean_point->SetUserBit(_featureFlag); + mean_point->P() = point; + mean_point->N().SetZero(); // delete []x; - delete []points; - delete []normals; - return mean_point; - } // end of FindFeature + delete []points; + delete []normals; + return mean_point; + } // end of FindFeature - /*! - * Postprocessing step performed during the finalization tha flip some of the mesh edges. - * The flipping criterion is quite simple: each edge is flipped if it will connect two - * feature samples after the flip. - */ - void FlipEdges() - { - std::vector< LightEdge > edges; - for (FaceIterator fi = _mesh->face.begin(); fi!=_mesh->face.end(); fi++) - { - size_t i = tri::Index(*_mesh,*fi); - if (fi->V(1) > fi->V(0)) edges.push_back( LightEdge(i,0) ); - if (fi->V(2) > fi->V(1)) edges.push_back( LightEdge(i,1) ); - if (fi->V(0) > fi->V(2)) edges.push_back( LightEdge(i,2) ); - } - vcg::tri::UpdateTopology< TRIMESH_TYPE >::FaceFace( *_mesh ); + /*! + * Postprocessing step performed during the finalization tha flip some of the mesh edges. + * The flipping criterion is quite simple: each edge is flipped if it will connect two + * feature samples after the flip. + */ + void FlipEdges() + { + std::vector< LightEdge > edges; + for (FaceIterator fi = _mesh->face.begin(); fi!=_mesh->face.end(); fi++) + { + size_t i = tri::Index(*_mesh,*fi); + if (fi->V(1) > fi->V(0)) edges.push_back( LightEdge(i,0) ); + if (fi->V(2) > fi->V(1)) edges.push_back( LightEdge(i,1) ); + if (fi->V(0) > fi->V(2)) edges.push_back( LightEdge(i,2) ); + } + vcg::tri::UpdateTopology< TRIMESH_TYPE >::FaceFace( *_mesh ); - // Select all the triangles that has a vertex shared with a non manifold edge. - int nonManifEdge = tri::Clean< TRIMESH_TYPE >::CountNonManifoldEdgeFF(*_mesh,true); - if(nonManifEdge >0) - tri::UpdateSelection< TRIMESH_TYPE >::FaceFromVertexLoose(*_mesh); - //qDebug("Got %i non manif edges",nonManifEdge); + // Select all the triangles that has a vertex shared with a non manifold edge. + int nonManifEdge = tri::Clean< TRIMESH_TYPE >::CountNonManifoldEdgeFF(*_mesh,true); + if(nonManifEdge >0) + tri::UpdateSelection< TRIMESH_TYPE >::FaceFromVertexLoose(*_mesh); + //qDebug("Got %i non manif edges",nonManifEdge); - typename std::vector< LightEdge >::iterator e_it = edges.begin(); - typename std::vector< LightEdge >::iterator e_end = edges.end(); + typename std::vector< LightEdge >::iterator e_it = edges.begin(); + typename std::vector< LightEdge >::iterator e_end = edges.end(); - FacePointer g, f; - int w, z; - for( ; e_it!=e_end; e_it++) - { - f = &_mesh->face[e_it->face]; - z = (int) e_it->edge; + FacePointer g, f; + int w, z; + for( ; e_it!=e_end; e_it++) + { + f = &_mesh->face[e_it->face]; + z = (int) e_it->edge; - // v2------v1 swap the diagonal only if v2 and v3 are feature and v0 and v1 are not. - // | / | - // | / | - // v0------v3 - if (!(f->IsS()) && vcg::face::CheckFlipEdge< FaceType >(*f, z)) - { - VertexPointer v0, v1, v2, v3; - v0 = f->V(z); - v1 = f->V1(z); - v2 = f->V2(z); - g = f->FFp(z); - w = f->FFi(z); - v3 = g->V2(w); - bool b0, b1, b2, b3; - b0 = !v0->IsUserBit(_featureFlag) ; - b1 = !v1->IsUserBit(_featureFlag) ; - b2 = v2->IsUserBit(_featureFlag) ; - b3 = v3->IsUserBit(_featureFlag) ; - if( b0 && b1 && b2 && b3) - vcg::face::FlipEdge< FaceType >(*f, z); + // v2------v1 swap the diagonal only if v2 and v3 are feature and v0 and v1 are not. + // | / | + // | / | + // v0------v3 + if (!(f->IsS()) && vcg::face::CheckFlipEdge< FaceType >(*f, z)) + { + VertexPointer v0, v1, v2, v3; + v0 = f->V(z); + v1 = f->V1(z); + v2 = f->V2(z); + g = f->FFp(z); + w = f->FFi(z); + v3 = g->V2(w); + bool b0, b1, b2, b3; + b0 = !v0->IsUserBit(_featureFlag) ; + b1 = !v1->IsUserBit(_featureFlag) ; + b2 = v2->IsUserBit(_featureFlag) ; + b3 = v3->IsUserBit(_featureFlag) ; + if( b0 && b1 && b2 && b3) + vcg::face::FlipEdge< FaceType >(*f, z); - } // end if (vcg::face::CheckFlipEdge< _Face >(*f, z)) - } // end for( ; e_it!=e_end; e_it++) + } // end if (vcg::face::CheckFlipEdge< _Face >(*f, z)) + } // end for( ; e_it!=e_end; e_it++) - } //end of FlipEdges + } //end of FlipEdges - }; // end of class ExtendedMarchingCubes - // /*! @} */ - // end of Doxygen documentation + }; // end of class ExtendedMarchingCubes + // /*! @} */ + // end of Doxygen documentation - } // end of namespace tri + } // end of namespace tri }; // end of namespace vcg #endif // __VCG_EXTENDED_MARCHING_CUBES diff --git a/vcg/complex/algorithms/create/marching_cubes.h b/vcg/complex/algorithms/create/marching_cubes.h index 08cd94b3..3f981ffd 100644 --- a/vcg/complex/algorithms/create/marching_cubes.h +++ b/vcg/complex/algorithms/create/marching_cubes.h @@ -8,7 +8,7 @@ * \ * * All rights reserved. * * * -* This program is free software; you can redistribute it and/or modify * +* 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. * @@ -25,706 +25,703 @@ #ifndef __VCG_MARCHING_CUBES #define __VCG_MARCHING_CUBES -#include -#include -#include #include "mc_lookup_table.h" namespace vcg { - namespace tri - { - // Doxygen documentation - /** \addtogroup trimesh */ - /*@{*/ + namespace tri + { + // Doxygen documentation + /** \addtogroup trimesh */ + /*@{*/ - /* - * Cube description: - * 3 ________ 2 _____2__ - * /| /| / | /| - * / | / | 11/ 3 10/ | - * 7 /_______ / | /__6_|__ / |1 - * | | |6 | | | | | - * | 0|__|_____|1 | |__|__0__| - * | / | / 7 8/ 5 / - * | / | / | / | /9 - * |/_______|/ |/___4___|/ - * 4 5 - */ + /* + * Cube description: + * 3 ________ 2 _____2__ + * /| /| / | /| + * / | / | 11/ 3 10/ | + * 7 /_______ / | /__6_|__ / |1 + * | | |6 | | | | | + * | 0|__|_____|1 | |__|__0__| + * | / | / 7 8/ 5 / + * | / | / | / | /9 + * |/_______|/ |/___4___|/ + * 4 5 + */ - //! This class implements the Marching Cubes algorithm. - /*! - * The implementation is enough generic: this class works only on one volume cell for each - * call to ProcessCell. Using the field value at the cell corners, it adds to the - * mesh the triangles set approximating the surface that cross that cell. The ambiguities - * are resolved using an enhanced topologically controlled lookup table. - * @param TRIMESH_TYPE (Template parameter) the mesh type that will be constructed - * @param WALKER_TYPE (Template parameter) the class that implement the traversal ordering of the volume - **/ - template - class MarchingCubes - { - public: - enum Dimension {X, Y, Z}; + //! This class implements the Marching Cubes algorithm. + /*! + * The implementation is enough generic: this class works only on one volume cell for each + * call to ProcessCell. Using the field value at the cell corners, it adds to the + * mesh the triangles set approximating the surface that cross that cell. The ambiguities + * are resolved using an enhanced topologically controlled lookup table. + * @param TRIMESH_TYPE (Template parameter) the mesh type that will be constructed + * @param WALKER_TYPE (Template parameter) the class that implement the traversal ordering of the volume + **/ + template + class MarchingCubes + { + public: + enum Dimension {X, Y, Z}; #if defined(__GNUC__) - typedef unsigned int size_t; + typedef unsigned int size_t; #else #ifdef _WIN64 - typedef unsigned __int64 size_t; + typedef unsigned __int64 size_t; #else - typedef _W64 unsigned int size_t; + typedef _W64 unsigned int size_t; #endif -#endif - typedef typename vcg::tri::Allocator< TRIMESH_TYPE > AllocatorType; - typedef typename TRIMESH_TYPE::ScalarType ScalarType; - typedef typename TRIMESH_TYPE::VertexType VertexType; - typedef typename TRIMESH_TYPE::VertexPointer VertexPointer; - typedef typename TRIMESH_TYPE::VertexIterator VertexIterator; - typedef typename TRIMESH_TYPE::FaceType FaceType; - typedef typename TRIMESH_TYPE::FacePointer FacePointer; - typedef typename TRIMESH_TYPE::FaceIterator FaceIterator; - typedef typename TRIMESH_TYPE::CoordType CoordType; - typedef typename TRIMESH_TYPE::CoordType* CoordPointer; +#endif + typedef typename vcg::tri::Allocator< TRIMESH_TYPE > AllocatorType; + typedef typename TRIMESH_TYPE::ScalarType ScalarType; + typedef typename TRIMESH_TYPE::VertexType VertexType; + typedef typename TRIMESH_TYPE::VertexPointer VertexPointer; + typedef typename TRIMESH_TYPE::VertexIterator VertexIterator; + typedef typename TRIMESH_TYPE::FaceType FaceType; + typedef typename TRIMESH_TYPE::FacePointer FacePointer; + typedef typename TRIMESH_TYPE::FaceIterator FaceIterator; + typedef typename TRIMESH_TYPE::CoordType CoordType; + typedef typename TRIMESH_TYPE::CoordType* CoordPointer; - /*! - * Constructor - * \param mesh the mesh that will be constructed - * \param walker the class implementing the traversal policy - */ - MarchingCubes(TRIMESH_TYPE &mesh, WALKER_TYPE &walker) - { - _mesh = &mesh; - _walker = &walker; - }; + /*! + * Constructor + * \param mesh the mesh that will be constructed + * \param walker the class implementing the traversal policy + */ + MarchingCubes(TRIMESH_TYPE &mesh, WALKER_TYPE &walker) + { + _mesh = &mesh; + _walker = &walker; + }; - /*! - * Execute the initialiazation. - * This method must be executed before the first call to ApplyMC - */ - void Initialize() - { - _mesh->Clear(); - }; // end of Initialize() + /*! + * Execute the initialiazation. + * This method must be executed before the first call to ApplyMC + */ + void Initialize() + { + _mesh->Clear(); + }; // end of Initialize() - /*! - * - * This method must be executed after the last call to ApplyMC - */ - void Finalize() - { - _mesh = NULL; - _walker = NULL; - }; // end of Finalize() + /*! + * + * This method must be executed after the last call to ApplyMC + */ + void Finalize() + { + _mesh = NULL; + _walker = NULL; + }; // end of Finalize() - /*! - * Apply the marching cubes algorithm to the volume cell identified by the two points min and max. - * All the three coordinates of the first point must be smaller than the respectives three coordinatas of the second point. - * \param min the first point - * \param max the second point - */ - void ProcessCell(const vcg::Point3i &min, const vcg::Point3i &max) - { - _case = _subconfig = _config = -1; - assert(min[0]marching cubes algorithm to the volume cell identified by the two points min and max. + * All the three coordinates of the first point must be smaller than the respectives three coordinatas of the second point. + * \param min the first point + * \param max the second point + */ + void ProcessCell(const vcg::Point3i &min, const vcg::Point3i &max) + { + _case = _subconfig = _config = -1; + assert(min[0]V( _corners[i].X(), _corners[i].Y(), _corners[i].Z() ); + for (int i=0; i<8; i++) + _field[i] = _walker->V( _corners[i].X(), _corners[i].Y(), _corners[i].Z() ); - unsigned char cubetype = 0; - for (int i=0; i<8; i++) - if (_field[i]>0) cubetype += 1<0) cubetype += 1<= 0 ; // face and A invert signs - }; // end of TestFace + return face * A * ( A*C - B*D ) >= 0 ; // face and A invert signs + }; // end of TestFace - /*! - * Tests if the components of the tesselation of the cube should be connected - * through the interior of the cube - */ - inline bool TestInterior(signed char s) - { - ScalarType t, At=0, Bt=0, Ct=0, Dt=0, a, b ; - char test = 0 ; - char edge = -1 ; // reference edge of the triangulation + /*! + * Tests if the components of the tesselation of the cube should be connected + * through the interior of the cube + */ + inline bool TestInterior(signed char s) + { + ScalarType t, At=0, Bt=0, Ct=0, Dt=0, a, b ; + char test = 0 ; + char edge = -1 ; // reference edge of the triangulation - switch( _case ) - { - case 4 : - case 10 : - { - a = (_field[4]-_field[0])*(_field[6]-_field[2]) - (_field[7]-_field[3])*(_field[5]-_field[1]); - b = _field[2]*(_field[4]-_field[0])+_field[0]*(_field[6]-_field[2])-_field[1]*(_field[7]-_field[3])-_field[3]*(_field[5]-_field[1]); - t = - b / (2*a) ; - if( t<0 || t>1 ) - return s>0 ; + switch( _case ) + { + case 4 : + case 10 : + { + a = (_field[4]-_field[0])*(_field[6]-_field[2]) - (_field[7]-_field[3])*(_field[5]-_field[1]); + b = _field[2]*(_field[4]-_field[0])+_field[0]*(_field[6]-_field[2])-_field[1]*(_field[7]-_field[3])-_field[3]*(_field[5]-_field[1]); + t = - b / (2*a) ; + if( t<0 || t>1 ) + return s>0 ; - At = _field[0] + ( _field[4] - _field[0] ) * t ; - Bt = _field[3] + ( _field[7] - _field[3] ) * t ; - Ct = _field[2] + ( _field[6] - _field[2] ) * t ; - Dt = _field[1] + ( _field[5] - _field[1] ) * t ; - break ; - } - case 6 : - case 7 : - case 12 : - case 13 : - switch( _case ) - { - case 6 : edge = MCLookUpTable::Test6 (_config, 2) ; break ; - case 7 : edge = MCLookUpTable::Test7 (_config, 4) ; break ; - case 12 : edge = MCLookUpTable::Test12(_config, 3) ; break ; - case 13 : edge = MCLookUpTable::Tiling13_5_1(_config, _subconfig)[0] ; break ; - } - switch( edge ) - { - case 0 : - t = _field[0] / ( _field[0] - _field[1] ) ; - At = 0 ; - Bt = _field[3] + ( _field[2] - _field[3] ) * t ; - Ct = _field[7] + ( _field[6] - _field[7] ) * t ; - Dt = _field[4] + ( _field[5] - _field[4] ) * t ; - break ; - case 1 : - t = _field[1] / ( _field[1] - _field[2] ) ; - At = 0 ; - Bt = _field[0] + ( _field[3] - _field[0] ) * t ; - Ct = _field[4] + ( _field[7] - _field[4] ) * t ; - Dt = _field[5] + ( _field[6] - _field[5] ) * t ; - break ; - case 2 : - t = _field[2] / ( _field[2] - _field[3] ) ; - At = 0 ; - Bt = _field[1] + ( _field[0] - _field[1] ) * t ; - Ct = _field[5] + ( _field[4] - _field[5] ) * t ; - Dt = _field[6] + ( _field[7] - _field[6] ) * t ; - break ; - case 3 : - t = _field[3] / ( _field[3] - _field[0] ) ; - At = 0 ; - Bt = _field[2] + ( _field[1] - _field[2] ) * t ; - Ct = _field[6] + ( _field[5] - _field[6] ) * t ; - Dt = _field[7] + ( _field[4] - _field[7] ) * t ; - break ; - case 4 : - t = _field[4] / ( _field[4] - _field[5] ) ; - At = 0 ; - Bt = _field[7] + ( _field[6] - _field[7] ) * t ; - Ct = _field[3] + ( _field[2] - _field[3] ) * t ; - Dt = _field[0] + ( _field[1] - _field[0] ) * t ; - break ; - case 5 : - t = _field[5] / ( _field[5] - _field[6] ) ; - At = 0 ; - Bt = _field[4] + ( _field[7] - _field[4] ) * t ; - Ct = _field[0] + ( _field[3] - _field[0] ) * t ; - Dt = _field[1] + ( _field[2] - _field[1] ) * t ; - break ; - case 6 : - t = _field[6] / ( _field[6] - _field[7] ) ; - At = 0 ; - Bt = _field[5] + ( _field[4] - _field[5] ) * t ; - Ct = _field[1] + ( _field[0] - _field[1] ) * t ; - Dt = _field[2] + ( _field[3] - _field[2] ) * t ; - break ; - case 7 : - t = _field[7] / ( _field[7] - _field[4] ) ; - At = 0 ; - Bt = _field[6] + ( _field[5] - _field[6] ) * t ; - Ct = _field[2] + ( _field[1] - _field[2] ) * t ; - Dt = _field[3] + ( _field[0] - _field[3] ) * t ; - break ; - case 8 : - t = _field[0] / ( _field[0] - _field[4] ) ; - At = 0 ; - Bt = _field[3] + ( _field[7] - _field[3] ) * t ; - Ct = _field[2] + ( _field[6] - _field[2] ) * t ; - Dt = _field[1] + ( _field[5] - _field[1] ) * t ; - break ; - case 9 : - t = _field[1] / ( _field[1] - _field[5] ) ; - At = 0 ; - Bt = _field[0] + ( _field[4] - _field[0] ) * t ; - Ct = _field[3] + ( _field[7] - _field[3] ) * t ; - Dt = _field[2] + ( _field[6] - _field[2] ) * t ; - break ; - case 10 : - t = _field[2] / ( _field[2] - _field[6] ) ; - At = 0 ; - Bt = _field[1] + ( _field[5] - _field[1] ) * t ; - Ct = _field[0] + ( _field[4] - _field[0] ) * t ; - Dt = _field[3] + ( _field[7] - _field[3] ) * t ; - break ; - case 11 : - t = _field[3] / ( _field[3] - _field[7] ) ; - At = 0 ; - Bt = _field[2] + ( _field[6] - _field[2] ) * t ; - Ct = _field[1] + ( _field[5] - _field[1] ) * t ; - Dt = _field[0] + ( _field[4] - _field[0] ) * t ; - break ; - default: { assert(false); /* Invalid edge */ break ; } - } - break ; + At = _field[0] + ( _field[4] - _field[0] ) * t ; + Bt = _field[3] + ( _field[7] - _field[3] ) * t ; + Ct = _field[2] + ( _field[6] - _field[2] ) * t ; + Dt = _field[1] + ( _field[5] - _field[1] ) * t ; + break ; + } + case 6 : + case 7 : + case 12 : + case 13 : + switch( _case ) + { + case 6 : edge = MCLookUpTable::Test6 (_config, 2) ; break ; + case 7 : edge = MCLookUpTable::Test7 (_config, 4) ; break ; + case 12 : edge = MCLookUpTable::Test12(_config, 3) ; break ; + case 13 : edge = MCLookUpTable::Tiling13_5_1(_config, _subconfig)[0] ; break ; + } + switch( edge ) + { + case 0 : + t = _field[0] / ( _field[0] - _field[1] ) ; + At = 0 ; + Bt = _field[3] + ( _field[2] - _field[3] ) * t ; + Ct = _field[7] + ( _field[6] - _field[7] ) * t ; + Dt = _field[4] + ( _field[5] - _field[4] ) * t ; + break ; + case 1 : + t = _field[1] / ( _field[1] - _field[2] ) ; + At = 0 ; + Bt = _field[0] + ( _field[3] - _field[0] ) * t ; + Ct = _field[4] + ( _field[7] - _field[4] ) * t ; + Dt = _field[5] + ( _field[6] - _field[5] ) * t ; + break ; + case 2 : + t = _field[2] / ( _field[2] - _field[3] ) ; + At = 0 ; + Bt = _field[1] + ( _field[0] - _field[1] ) * t ; + Ct = _field[5] + ( _field[4] - _field[5] ) * t ; + Dt = _field[6] + ( _field[7] - _field[6] ) * t ; + break ; + case 3 : + t = _field[3] / ( _field[3] - _field[0] ) ; + At = 0 ; + Bt = _field[2] + ( _field[1] - _field[2] ) * t ; + Ct = _field[6] + ( _field[5] - _field[6] ) * t ; + Dt = _field[7] + ( _field[4] - _field[7] ) * t ; + break ; + case 4 : + t = _field[4] / ( _field[4] - _field[5] ) ; + At = 0 ; + Bt = _field[7] + ( _field[6] - _field[7] ) * t ; + Ct = _field[3] + ( _field[2] - _field[3] ) * t ; + Dt = _field[0] + ( _field[1] - _field[0] ) * t ; + break ; + case 5 : + t = _field[5] / ( _field[5] - _field[6] ) ; + At = 0 ; + Bt = _field[4] + ( _field[7] - _field[4] ) * t ; + Ct = _field[0] + ( _field[3] - _field[0] ) * t ; + Dt = _field[1] + ( _field[2] - _field[1] ) * t ; + break ; + case 6 : + t = _field[6] / ( _field[6] - _field[7] ) ; + At = 0 ; + Bt = _field[5] + ( _field[4] - _field[5] ) * t ; + Ct = _field[1] + ( _field[0] - _field[1] ) * t ; + Dt = _field[2] + ( _field[3] - _field[2] ) * t ; + break ; + case 7 : + t = _field[7] / ( _field[7] - _field[4] ) ; + At = 0 ; + Bt = _field[6] + ( _field[5] - _field[6] ) * t ; + Ct = _field[2] + ( _field[1] - _field[2] ) * t ; + Dt = _field[3] + ( _field[0] - _field[3] ) * t ; + break ; + case 8 : + t = _field[0] / ( _field[0] - _field[4] ) ; + At = 0 ; + Bt = _field[3] + ( _field[7] - _field[3] ) * t ; + Ct = _field[2] + ( _field[6] - _field[2] ) * t ; + Dt = _field[1] + ( _field[5] - _field[1] ) * t ; + break ; + case 9 : + t = _field[1] / ( _field[1] - _field[5] ) ; + At = 0 ; + Bt = _field[0] + ( _field[4] - _field[0] ) * t ; + Ct = _field[3] + ( _field[7] - _field[3] ) * t ; + Dt = _field[2] + ( _field[6] - _field[2] ) * t ; + break ; + case 10 : + t = _field[2] / ( _field[2] - _field[6] ) ; + At = 0 ; + Bt = _field[1] + ( _field[5] - _field[1] ) * t ; + Ct = _field[0] + ( _field[4] - _field[0] ) * t ; + Dt = _field[3] + ( _field[7] - _field[3] ) * t ; + break ; + case 11 : + t = _field[3] / ( _field[3] - _field[7] ) ; + At = 0 ; + Bt = _field[2] + ( _field[6] - _field[2] ) * t ; + Ct = _field[1] + ( _field[5] - _field[1] ) * t ; + Dt = _field[0] + ( _field[4] - _field[0] ) * t ; + break ; + default: { assert(false); /* Invalid edge */ break ; } + } + break ; - default : assert(false); /* Invalid ambiguous case */ break; - } + default : assert(false); /* Invalid ambiguous case */ break; + } - if( At >= 0 ) test ++ ; - if( Bt >= 0 ) test += 2 ; - if( Ct >= 0 ) test += 4 ; - if( Dt >= 0 ) test += 8 ; - switch( test ) - { - case 0 : return s>0 ; - case 1 : return s>0 ; - case 2 : return s>0 ; - case 3 : return s>0 ; - case 4 : return s>0 ; - case 5 : if( At * Ct < Bt * Dt ) return s>0 ; break ; - case 6 : return s>0 ; - case 7 : return s<0 ; - case 8 : return s>0 ; - case 9 : return s>0 ; - case 10 : if( At * Ct >= Bt * Dt ) return s>0 ; break ; - case 11 : return s<0 ; - case 12 : return s>0 ; - case 13 : return s<0 ; - case 14 : return s<0 ; - case 15 : return s<0 ; - } - return s<0 ; - }; //end of TestInterior + if( At >= 0 ) test ++ ; + if( Bt >= 0 ) test += 2 ; + if( Ct >= 0 ) test += 4 ; + if( Dt >= 0 ) test += 8 ; + switch( test ) + { + case 0 : return s>0 ; + case 1 : return s>0 ; + case 2 : return s>0 ; + case 3 : return s>0 ; + case 4 : return s>0 ; + case 5 : if( At * Ct < Bt * Dt ) return s>0 ; break ; + case 6 : return s>0 ; + case 7 : return s<0 ; + case 8 : return s>0 ; + case 9 : return s>0 ; + case 10 : if( At * Ct >= Bt * Dt ) return s>0 ; break ; + case 11 : return s<0 ; + case 12 : return s>0 ; + case 13 : return s<0 ; + case 14 : return s<0 ; + case 15 : return s<0 ; + } + return s<0 ; + }; //end of TestInterior - /*! - * Adds a vertex inside the current cube - * \param v The pointer to the new vertex along the edge - */ - inline void ComputeCVertex(VertexPointer &v12) - { - v12 = &*AllocatorType::AddVertices(*_mesh, 1); - v12->P() = CoordType(0.0, 0.0, 0.0); + /*! + * Adds a vertex inside the current cube + * \param v The pointer to the new vertex along the edge + */ + inline void ComputeCVertex(VertexPointer &v12) + { + v12 = &*AllocatorType::AddVertices(*_mesh, 1); + v12->P() = CoordType(0.0, 0.0, 0.0); - unsigned int count = 0; - VertexPointer v = NULL; - if (_walker->Exist(_corners[0], _corners[1], v) ) - { - count++; - v12->P() += v->P(); - } - if (_walker->Exist(_corners[1], _corners[2], v) ) - { - count++; - v12->P() += v->P(); - } - if (_walker->Exist(_corners[3], _corners[2], v) ) - { - count++; - v12->P() += v->P(); - } - if (_walker->Exist(_corners[0], _corners[3], v) ) - { - count++; - v12->P() += v->P(); - } - if (_walker->Exist(_corners[4], _corners[5], v) ) - { - count++; - v12->P() += v->P(); - } - if (_walker->Exist(_corners[5], _corners[6], v) ) - { - count++; - v12->P() += v->P(); - } - if (_walker->Exist(_corners[7], _corners[6], v) ) - { - count++; - v12->P() += v->P(); - } - if (_walker->Exist(_corners[4], _corners[7], v) ) - { - count++; - v12->P() += v->P(); - } - if (_walker->Exist(_corners[0], _corners[4], v) ) - { - count++; - v12->P() += v->P(); - } - if (_walker->Exist(_corners[1], _corners[5], v) ) - { - count++; - v12->P() += v->P(); - } - if (_walker->Exist(_corners[2], _corners[6], v) ) - { - count++; - v12->P() += v->P(); - } - if (_walker->Exist(_corners[3], _corners[7], v) ) - { - count++; - v12->P() += v->P(); - } - v12->P() /= (float) count; - } // end of AddCVertex - /*! - * Adds new triangles to the mesh - * \param vertices_list The list of vertex indices - * \param n The number of triangles that will be added to the mesh - * \param v12 The pointer to the vertex inside the current cell - */ - inline void AddTriangles(const char *vertices_list, char n, VertexPointer v12=NULL) - { - VertexPointer vp = NULL; - size_t face_idx = _mesh->face.size(); - size_t v12_idx = -1; - size_t vertices_idx[3]; - if (v12 != NULL) v12_idx = v12 - &_mesh->vert[0]; - AllocatorType::AddFaces(*_mesh, (int) n); + unsigned int count = 0; + VertexPointer v = NULL; + if (_walker->Exist(_corners[0], _corners[1], v) ) + { + count++; + v12->P() += v->P(); + } + if (_walker->Exist(_corners[1], _corners[2], v) ) + { + count++; + v12->P() += v->P(); + } + if (_walker->Exist(_corners[3], _corners[2], v) ) + { + count++; + v12->P() += v->P(); + } + if (_walker->Exist(_corners[0], _corners[3], v) ) + { + count++; + v12->P() += v->P(); + } + if (_walker->Exist(_corners[4], _corners[5], v) ) + { + count++; + v12->P() += v->P(); + } + if (_walker->Exist(_corners[5], _corners[6], v) ) + { + count++; + v12->P() += v->P(); + } + if (_walker->Exist(_corners[7], _corners[6], v) ) + { + count++; + v12->P() += v->P(); + } + if (_walker->Exist(_corners[4], _corners[7], v) ) + { + count++; + v12->P() += v->P(); + } + if (_walker->Exist(_corners[0], _corners[4], v) ) + { + count++; + v12->P() += v->P(); + } + if (_walker->Exist(_corners[1], _corners[5], v) ) + { + count++; + v12->P() += v->P(); + } + if (_walker->Exist(_corners[2], _corners[6], v) ) + { + count++; + v12->P() += v->P(); + } + if (_walker->Exist(_corners[3], _corners[7], v) ) + { + count++; + v12->P() += v->P(); + } + v12->P() /= (float) count; + } // end of AddCVertex + /*! + * Adds new triangles to the mesh + * \param vertices_list The list of vertex indices + * \param n The number of triangles that will be added to the mesh + * \param v12 The pointer to the vertex inside the current cell + */ + inline void AddTriangles(const char *vertices_list, char n, VertexPointer v12=NULL) + { + VertexPointer vp = NULL; + size_t face_idx = _mesh->face.size(); + size_t v12_idx = -1; + size_t vertices_idx[3]; + if (v12 != NULL) v12_idx = v12 - &_mesh->vert[0]; + AllocatorType::AddFaces(*_mesh, (int) n); - for (int trig=0; trig<3*n; face_idx++ ) - { - vp = NULL; - memset(vertices_idx, -1, 3*sizeof(size_t)); - for (int vert=0; vert<3; vert++, trig++) //ok - { + for (int trig=0; trig<3*n; face_idx++ ) + { + vp = NULL; + memset(vertices_idx, -1, 3*sizeof(size_t)); + for (int vert=0; vert<3; vert++, trig++) //ok + { - switch ( vertices_list[trig] ) - { - case 0: { _walker->GetXIntercept(_corners[0], _corners[1], vp); vertices_idx[vert] = vp - &_mesh->vert[0]; break; } - case 1: { _walker->GetYIntercept(_corners[1], _corners[2], vp); vertices_idx[vert] = vp - &_mesh->vert[0]; break; } - case 2: { _walker->GetXIntercept(_corners[3], _corners[2], vp); vertices_idx[vert] = vp - &_mesh->vert[0]; break; } - case 3: { _walker->GetYIntercept(_corners[0], _corners[3], vp); vertices_idx[vert] = vp - &_mesh->vert[0]; break; } - case 4: { _walker->GetXIntercept(_corners[4], _corners[5], vp); vertices_idx[vert] = vp - &_mesh->vert[0]; break; } - case 5: { _walker->GetYIntercept(_corners[5], _corners[6], vp); vertices_idx[vert] = vp - &_mesh->vert[0]; break; } - case 6: { _walker->GetXIntercept(_corners[7], _corners[6], vp); vertices_idx[vert] = vp - &_mesh->vert[0]; break; } - case 7: { _walker->GetYIntercept(_corners[4], _corners[7], vp); vertices_idx[vert] = vp - &_mesh->vert[0]; break; } - case 8: { _walker->GetZIntercept(_corners[0], _corners[4], vp); vertices_idx[vert] = vp - &_mesh->vert[0]; break; } - case 9: { _walker->GetZIntercept(_corners[1], _corners[5], vp); vertices_idx[vert] = vp - &_mesh->vert[0]; break; } - case 10: { _walker->GetZIntercept(_corners[2], _corners[6], vp); vertices_idx[vert] = vp - &_mesh->vert[0]; break; } - case 11: { _walker->GetZIntercept(_corners[3], _corners[7], vp); vertices_idx[vert] = vp - &_mesh->vert[0]; break; } - case 12: { assert(v12 != NULL); vertices_idx[vert] = v12_idx; break; } - default: { assert(false); /* Invalid edge identifier */ } - } // end of switch + switch ( vertices_list[trig] ) + { + case 0: { _walker->GetXIntercept(_corners[0], _corners[1], vp); vertices_idx[vert] = vp - &_mesh->vert[0]; break; } + case 1: { _walker->GetYIntercept(_corners[1], _corners[2], vp); vertices_idx[vert] = vp - &_mesh->vert[0]; break; } + case 2: { _walker->GetXIntercept(_corners[3], _corners[2], vp); vertices_idx[vert] = vp - &_mesh->vert[0]; break; } + case 3: { _walker->GetYIntercept(_corners[0], _corners[3], vp); vertices_idx[vert] = vp - &_mesh->vert[0]; break; } + case 4: { _walker->GetXIntercept(_corners[4], _corners[5], vp); vertices_idx[vert] = vp - &_mesh->vert[0]; break; } + case 5: { _walker->GetYIntercept(_corners[5], _corners[6], vp); vertices_idx[vert] = vp - &_mesh->vert[0]; break; } + case 6: { _walker->GetXIntercept(_corners[7], _corners[6], vp); vertices_idx[vert] = vp - &_mesh->vert[0]; break; } + case 7: { _walker->GetYIntercept(_corners[4], _corners[7], vp); vertices_idx[vert] = vp - &_mesh->vert[0]; break; } + case 8: { _walker->GetZIntercept(_corners[0], _corners[4], vp); vertices_idx[vert] = vp - &_mesh->vert[0]; break; } + case 9: { _walker->GetZIntercept(_corners[1], _corners[5], vp); vertices_idx[vert] = vp - &_mesh->vert[0]; break; } + case 10: { _walker->GetZIntercept(_corners[2], _corners[6], vp); vertices_idx[vert] = vp - &_mesh->vert[0]; break; } + case 11: { _walker->GetZIntercept(_corners[3], _corners[7], vp); vertices_idx[vert] = vp - &_mesh->vert[0]; break; } + case 12: { assert(v12 != NULL); vertices_idx[vert] = v12_idx; break; } + default: { assert(false); /* Invalid edge identifier */ } + } // end of switch - // Note that vp can be zero if we are in case 12 and that vertices_idx is surely >0 so the following assert has to be corrected as below. - // assert((vp - &_mesh->vert[0])>=0 && vertices_idx[vert]<_mesh->vert.size()); - assert(vertices_idx[vert]<_mesh->vert.size()); - } // end for (int vert=0 ...) + // Note that vp can be zero if we are in case 12 and that vertices_idx is surely >0 so the following assert has to be corrected as below. + // assert((vp - &_mesh->vert[0])>=0 && vertices_idx[vert]<_mesh->vert.size()); + assert(vertices_idx[vert]<_mesh->vert.size()); + } // end for (int vert=0 ...) - _mesh->face[face_idx].V(0) = &_mesh->vert[vertices_idx[0]]; - _mesh->face[face_idx].V(1) = &_mesh->vert[vertices_idx[1]]; - _mesh->face[face_idx].V(2) = &_mesh->vert[vertices_idx[2]]; - } // end for (int trig=0...) - }; // end of AddTriangles + _mesh->face[face_idx].V(0) = &_mesh->vert[vertices_idx[0]]; + _mesh->face[face_idx].V(1) = &_mesh->vert[vertices_idx[1]]; + _mesh->face[face_idx].V(2) = &_mesh->vert[vertices_idx[2]]; + } // end for (int trig=0...) + }; // end of AddTriangles - }; // end of class MarchingCubes + }; // end of class MarchingCubes - /*! @} */ - //end of Doxygen documentation + /*! @} */ + //end of Doxygen documentation - }; // end of namespace tri + }; // end of namespace tri }; // end of namespace vcg #endif //__VCG_MARCHING_CUBES diff --git a/vcg/complex/algorithms/create/platonic.h b/vcg/complex/algorithms/create/platonic.h index 859c8dea..f360222e 100644 --- a/vcg/complex/algorithms/create/platonic.h +++ b/vcg/complex/algorithms/create/platonic.h @@ -25,7 +25,6 @@ #define __VCGLIB_PLATONIC #include -#include #include #include #include @@ -42,9 +41,9 @@ namespace tri { that represent surfaces of platonic solids, and other simple shapes. - The 1st parameter is the mesh that will - be filled with the solid. - */ + The 1st parameter is the mesh that will + be filled with the solid. + */ template void Tetrahedron(TetraMeshType &in) { @@ -135,31 +134,31 @@ void Dodecahedron(DodMeshType & in) int h,i,j,m=0; - bool used[N_points]; - for (i=0; i index(in.vn); @@ -167,19 +166,19 @@ void Dodecahedron(DodMeshType & in) FaceIterator fi=in.face.begin(); - for (i=0; i<12; i++) { - for (j=0; j<5; j++){ - (*fi).V(0)=index[added[i] ]; - (*fi).V(1)=index[reindex[penta[i*9 + order[j ] ] -1 ] ]; - (*fi).V(2)=index[reindex[penta[i*9 + order[(j+1)%5] ] -1 ] ]; - if (HasPerFaceFlags(in)) { - // tag faux edges - (*fi).SetF(0); - (*fi).SetF(2); - } - fi++; - } - } + for (i=0; i<12; i++) { + for (j=0; j<5; j++){ + (*fi).V(0)=index[added[i] ]; + (*fi).V(1)=index[reindex[penta[i*9 + order[j ] ] -1 ] ]; + (*fi).V(2)=index[reindex[penta[i*9 + order[(j+1)%5] ] -1 ] ]; + if (HasPerFaceFlags(in)) { + // tag faux edges + (*fi).SetF(0); + (*fi).SetF(2); + } + fi++; + } + } } template @@ -233,24 +232,24 @@ void Icosahedron(IcoMeshType &in) CoordType ( 0,-L, 1), CoordType ( 0,-L,-1), - CoordType ( L, 1, 0), - CoordType ( L,-1, 0), - CoordType (-L, 1, 0), - CoordType (-L,-1, 0), + CoordType ( L, 1, 0), + CoordType ( L,-1, 0), + CoordType (-L, 1, 0), + CoordType (-L,-1, 0), - CoordType ( 1, 0, L), - CoordType (-1, 0, L), - CoordType ( 1, 0,-L), - CoordType (-1, 0,-L) - }; + CoordType ( 1, 0, L), + CoordType (-1, 0, L), + CoordType ( 1, 0,-L), + CoordType (-1, 0,-L) + }; - int ff[20][3]={ - {1,0,4},{0,1,6},{2,3,5},{3,2,7}, - {4,5,10},{5,4,8},{6,7,9},{7,6,11}, - {8,9,2},{9,8,0},{10,11,1},{11,10,3}, - {0,8,4},{0,6,9},{1,4,10},{1,11,6}, - {2,5,8},{2,9,7},{3,10,5},{3,7,11} - }; + int ff[20][3]={ + {1,0,4},{0,1,6},{2,3,5},{3,2,7}, + {4,5,10},{5,4,8},{6,7,9},{7,6,11}, + {8,9,2},{9,8,0},{10,11,1},{11,10,3}, + {0,8,4},{0,6,9},{1,4,10},{1,11,6}, + {2,5,8},{2,9,7},{3,10,5},{3,7,11} + }; in.Clear(); @@ -368,33 +367,33 @@ void Sphere(MeshType &in, const int subdiv = 3 ) typedef typename MeshType::FaceIterator FaceIterator; if(in.vn==0 && in.fn==0) Icosahedron(in); - VertexIterator vi; - for(vi = in.vert.begin(); vi!=in.vert.end();++vi) - vi->P().Normalize(); + VertexIterator vi; + for(vi = in.vert.begin(); vi!=in.vert.end();++vi) + vi->P().Normalize(); - tri::UpdateFlags::FaceBorderFromNone(in); - tri::UpdateTopology::FaceFace(in); + tri::UpdateFlags::FaceBorderFromNone(in); + tri::UpdateTopology::FaceFace(in); - size_t lastsize = 0; - for(int i = 0 ; i < subdiv; ++i) - { - Refine< MeshType, MidPoint >(in, MidPoint(&in), 0); + size_t lastsize = 0; + for(int i = 0 ; i < subdiv; ++i) + { + Refine< MeshType, MidPoint >(in, MidPoint(&in), 0); - for(vi = in.vert.begin() + lastsize; vi != in.vert.end(); ++vi) - vi->P().Normalize(); + for(vi = in.vert.begin() + lastsize; vi != in.vert.end(); ++vi) + vi->P().Normalize(); - lastsize = in.vert.size(); - } + lastsize = in.vert.size(); + } } - /// r1 = raggio 1, r2 = raggio2, h = altezza (asse y) + /// r1 = raggio 1, r2 = raggio2, h = altezza (asse y) template void Cone( MeshType& in, - const typename MeshType::ScalarType r1, - const typename MeshType::ScalarType r2, - const typename MeshType::ScalarType h, - const int SubDiv = 36 ) + const typename MeshType::ScalarType r1, + const typename MeshType::ScalarType r2, + const typename MeshType::ScalarType h, + const int SubDiv = 36 ) { typedef typename MeshType::ScalarType ScalarType; typedef typename MeshType::CoordType CoordType; @@ -433,14 +432,14 @@ void Cone( MeshType& in, b2 += SubDiv; } - if(r2!=0) - { - for(i=0;i void FaceGrid(MeshType & in, int w, int h) { - assert(in.vn == (int)in.vert.size()); // require a compact vertex vector - assert(in.vn >= w*h); // the number of vertices should match the number of expected grid vertices + assert(in.vn == (int)in.vert.size()); // require a compact vertex vector + assert(in.vn >= w*h); // the number of vertices should match the number of expected grid vertices - Allocator::AddFaces(in,(w-1)*(h-1)*2); + Allocator::AddFaces(in,(w-1)*(h-1)*2); // i+0,j+0 -- i+0,j+1 // | \ | @@ -694,8 +693,8 @@ void FaceGrid(MeshType & in, int w, int h) template void FaceGrid(MeshType & in, const std::vector &grid, int w, int h) { - assert(in.vn == (int)in.vert.size()); // require a compact vertex vector - assert(in.vn <= w*h); // the number of vertices should match the number of expected grid vertices + assert(in.vn == (int)in.vert.size()); // require a compact vertex vector + assert(in.vn <= w*h); // the number of vertices should match the number of expected grid vertices // V0 V1 // i+0,j+0 -- i+0,j+1 @@ -715,27 +714,27 @@ void FaceGrid(MeshType & in, const std::vector &grid, int w, int h) int V2i= grid[(i+1)*w+j+0]; int V3i= grid[(i+1)*w+j+1]; - int ndone=0; - bool quad = (V0i>=0 && V1i>=0 && V2i>=0 && V3i>=0 ) && tri::HasPerFaceFlags(in); + int ndone=0; + bool quad = (V0i>=0 && V1i>=0 && V2i>=0 && V3i>=0 ) && tri::HasPerFaceFlags(in); - if(V0i>=0 && V2i>=0 && V3i>=0 ) - { - typename MeshType::FaceIterator f= Allocator::AddFaces(in,1); - f->V(0)=&(in.vert[V3i]); - f->V(1)=&(in.vert[V2i]); - f->V(2)=&(in.vert[V0i]); - if (quad) f->SetF(2); - ndone++; - } - if(V0i>=0 && V1i>=0 && V3i>=0 ) - { - typename MeshType::FaceIterator f= Allocator::AddFaces(in,1); - f->V(0)=&(in.vert[V0i]); - f->V(1)=&(in.vert[V1i]); - f->V(2)=&(in.vert[V3i]); - if (quad) f->SetF(2); - ndone++; - } + if(V0i>=0 && V2i>=0 && V3i>=0 ) + { + typename MeshType::FaceIterator f= Allocator::AddFaces(in,1); + f->V(0)=&(in.vert[V3i]); + f->V(1)=&(in.vert[V2i]); + f->V(2)=&(in.vert[V0i]); + if (quad) f->SetF(2); + ndone++; + } + if(V0i>=0 && V1i>=0 && V3i>=0 ) + { + typename MeshType::FaceIterator f= Allocator::AddFaces(in,1); + f->V(0)=&(in.vert[V0i]); + f->V(1)=&(in.vert[V1i]); + f->V(2)=&(in.vert[V3i]); + if (quad) f->SetF(2); + ndone++; + } if (ndone==0) { // try diag the other way if(V2i>=0 && V0i>=0 && V1i>=0 ) @@ -850,49 +849,49 @@ void OrientedDisk(MeshType &m, int slices, Point3f center, Point3f norm, float r template void Cylinder(int slices, int stacks, MeshType & m){ - typename MeshType::VertexIterator vi = vcg::tri::Allocator::AddVertices(m,slices*(stacks+1)); - for ( int i = 0; i < stacks+1; ++i) - for ( int j = 0; j < slices; ++j) - { - float x,y,h; - x = cos( 2.0 * M_PI / slices * j); - y = sin( 2.0 * M_PI / slices * j); - h = 2 * i / (float)(stacks) - 1; + typename MeshType::VertexIterator vi = vcg::tri::Allocator::AddVertices(m,slices*(stacks+1)); + for ( int i = 0; i < stacks+1; ++i) + for ( int j = 0; j < slices; ++j) + { + float x,y,h; + x = cos( 2.0 * M_PI / slices * j); + y = sin( 2.0 * M_PI / slices * j); + h = 2 * i / (float)(stacks) - 1; - (*vi).P() = typename MeshType::CoordType(x,h,y); - ++vi; - } + (*vi).P() = typename MeshType::CoordType(x,h,y); + ++vi; + } - typename MeshType::FaceIterator fi ; - for ( int j = 0; j < stacks; ++j) - for ( int i = 0; i < slices; ++i) - { - int a,b,c,d; - a = (j+0)*slices + i; - b = (j+1)*slices + i; - c = (j+1)*slices + (i+1)%slices; - d = (j+0)*slices + (i+1)%slices; - if(((i+j)%2) == 0){ - fi = vcg::tri::Allocator::AddFaces(m,1); - (*fi).V(0) = &m.vert[ a ]; - (*fi).V(1) = &m.vert[ b ]; - (*fi).V(2) = &m.vert[ c ]; + typename MeshType::FaceIterator fi ; + for ( int j = 0; j < stacks; ++j) + for ( int i = 0; i < slices; ++i) + { + int a,b,c,d; + a = (j+0)*slices + i; + b = (j+1)*slices + i; + c = (j+1)*slices + (i+1)%slices; + d = (j+0)*slices + (i+1)%slices; + if(((i+j)%2) == 0){ + fi = vcg::tri::Allocator::AddFaces(m,1); + (*fi).V(0) = &m.vert[ a ]; + (*fi).V(1) = &m.vert[ b ]; + (*fi).V(2) = &m.vert[ c ]; - fi = vcg::tri::Allocator::AddFaces(m,1); - (*fi).V(0) = &m.vert[ c ]; - (*fi).V(1) = &m.vert[ d ]; - (*fi).V(2) = &m.vert[ a ]; - } - else{ - fi = vcg::tri::Allocator::AddFaces(m,1); - (*fi).V(0) = &m.vert[ b ]; - (*fi).V(1) = &m.vert[ c ]; - (*fi).V(2) = &m.vert[ d ]; + fi = vcg::tri::Allocator::AddFaces(m,1); + (*fi).V(0) = &m.vert[ c ]; + (*fi).V(1) = &m.vert[ d ]; + (*fi).V(2) = &m.vert[ a ]; + } + else{ + fi = vcg::tri::Allocator::AddFaces(m,1); + (*fi).V(0) = &m.vert[ b ]; + (*fi).V(1) = &m.vert[ c ]; + (*fi).V(2) = &m.vert[ d ]; - fi = vcg::tri::Allocator::AddFaces(m,1); - (*fi).V(0) = &m.vert[ d ]; - (*fi).V(1) = &m.vert[ a ]; - (*fi).V(2) = &m.vert[ b ]; + fi = vcg::tri::Allocator::AddFaces(m,1); + (*fi).V(0) = &m.vert[ d ]; + (*fi).V(1) = &m.vert[ a ]; + (*fi).V(2) = &m.vert[ b ]; } } @@ -908,47 +907,47 @@ void Cylinder(int slices, int stacks, MeshType & m){ template void GenerateCameraMesh(MeshType &in){ - typedef typename MeshType::CoordType MV; - MV vv[52]={ - MV(-0.000122145 , -0.2 ,0.35), - MV(0.000122145 , -0.2 ,-0.35),MV(-0.000122145 , 0.2 ,0.35),MV(0.000122145 , 0.2 ,-0.35),MV(0.999878 , -0.2 ,0.350349),MV(1.00012 , -0.2 ,-0.349651),MV(0.999878 , 0.2 ,0.350349),MV(1.00012 , 0.2 ,-0.349651),MV(1.28255 , 0.1 ,0.754205),MV(1.16539 , 0.1 ,1.03705),MV(0.88255 , 0.1 ,1.15421), - MV(0.599707 , 0.1 ,1.03705),MV(0.48255 , 0.1 ,0.754205),MV(0.599707 , 0.1 ,0.471362),MV(0.88255 , 0.1 ,0.354205),MV(1.16539 , 0.1 ,0.471362),MV(1.28255 , -0.1 ,0.754205),MV(1.16539 , -0.1 ,1.03705),MV(0.88255 , -0.1 ,1.15421),MV(0.599707 , -0.1 ,1.03705),MV(0.48255 , -0.1 ,0.754205), - MV(0.599707 , -0.1 ,0.471362),MV(1.16539 , -0.1 ,0.471362),MV(0.88255 , -0.1 ,0.354205),MV(3.49164e-005 , 0 ,-0.1),MV(1.74582e-005 , -0.0866025 ,-0.05),MV(-1.74582e-005 , -0.0866025 ,0.05),MV(-3.49164e-005 , 8.74228e-009 ,0.1),MV(-1.74582e-005 , 0.0866025 ,0.05),MV(1.74582e-005 , 0.0866025 ,-0.05),MV(-0.399913 , 1.99408e-022 ,-0.25014), - MV(-0.399956 , -0.216506 ,-0.12514),MV(-0.400044 , -0.216506 ,0.12486),MV(-0.400087 , 2.18557e-008 ,0.24986),MV(-0.400044 , 0.216506 ,0.12486),MV(-0.399956 , 0.216506 ,-0.12514),MV(0.479764 , 0.1 ,0.754205),MV(0.362606 , 0.1 ,1.03705),MV(0.0797637 , 0.1 ,1.15421),MV(-0.203079 , 0.1 ,1.03705),MV(-0.320236 , 0.1 ,0.754205), - MV(-0.203079 , 0.1 ,0.471362),MV(0.0797637 , 0.1 ,0.354205),MV(0.362606 , 0.1 ,0.471362),MV(0.479764 , -0.1 ,0.754205),MV(0.362606 , -0.1 ,1.03705),MV(0.0797637 , -0.1 ,1.15421),MV(-0.203079 , -0.1 ,1.03705),MV(-0.320236 , -0.1 ,0.754205),MV(0.0797637 , -0.1 ,0.354205),MV(0.362606 , -0.1 ,0.471362), - MV(-0.203079 , -0.1 ,0.471362), }; - int ff[88][3]={ - {0,2,3}, - {3,1,0},{4,5,7},{7,6,4},{0,1,5},{5,4,0},{1,3,7},{7,5,1},{3,2,6},{6,7,3},{2,0,4}, - {4,6,2},{10,9,8},{10,12,11},{10,13,12},{10,14,13},{10,15,14},{10,8,15},{8,17,16},{8,9,17},{9,18,17}, - {9,10,18},{10,19,18},{10,11,19},{11,20,19},{11,12,20},{12,21,20},{12,13,21},{13,23,21},{13,14,23},{14,22,23}, - {14,15,22},{15,16,22},{15,8,16},{23,16,17},{23,17,18},{23,18,19},{23,19,20},{23,20,21},{23,22,16},{25,27,26}, - {25,28,27},{25,29,28},{25,24,29},{24,31,30},{24,25,31},{25,32,31},{25,26,32},{26,33,32},{26,27,33},{27,34,33}, - {27,28,34},{28,35,34},{28,29,35},{29,30,35},{29,24,30},{35,30,31},{35,31,32},{35,32,33},{35,33,34},{42,37,36}, - {42,38,37},{42,39,38},{42,40,39},{42,41,40},{42,36,43},{36,45,44},{36,37,45},{37,46,45},{37,38,46},{38,47,46}, - {38,39,47},{39,48,47},{39,40,48},{40,51,48},{40,41,51},{41,49,51},{41,42,49},{42,50,49},{42,43,50},{43,44,50}, - {43,36,44},{51,44,45},{51,45,46},{51,46,47},{51,47,48},{51,49,50},{51,50,44}, - }; + typedef typename MeshType::CoordType MV; + MV vv[52]={ + MV(-0.000122145 , -0.2 ,0.35), + MV(0.000122145 , -0.2 ,-0.35),MV(-0.000122145 , 0.2 ,0.35),MV(0.000122145 , 0.2 ,-0.35),MV(0.999878 , -0.2 ,0.350349),MV(1.00012 , -0.2 ,-0.349651),MV(0.999878 , 0.2 ,0.350349),MV(1.00012 , 0.2 ,-0.349651),MV(1.28255 , 0.1 ,0.754205),MV(1.16539 , 0.1 ,1.03705),MV(0.88255 , 0.1 ,1.15421), + MV(0.599707 , 0.1 ,1.03705),MV(0.48255 , 0.1 ,0.754205),MV(0.599707 , 0.1 ,0.471362),MV(0.88255 , 0.1 ,0.354205),MV(1.16539 , 0.1 ,0.471362),MV(1.28255 , -0.1 ,0.754205),MV(1.16539 , -0.1 ,1.03705),MV(0.88255 , -0.1 ,1.15421),MV(0.599707 , -0.1 ,1.03705),MV(0.48255 , -0.1 ,0.754205), + MV(0.599707 , -0.1 ,0.471362),MV(1.16539 , -0.1 ,0.471362),MV(0.88255 , -0.1 ,0.354205),MV(3.49164e-005 , 0 ,-0.1),MV(1.74582e-005 , -0.0866025 ,-0.05),MV(-1.74582e-005 , -0.0866025 ,0.05),MV(-3.49164e-005 , 8.74228e-009 ,0.1),MV(-1.74582e-005 , 0.0866025 ,0.05),MV(1.74582e-005 , 0.0866025 ,-0.05),MV(-0.399913 , 1.99408e-022 ,-0.25014), + MV(-0.399956 , -0.216506 ,-0.12514),MV(-0.400044 , -0.216506 ,0.12486),MV(-0.400087 , 2.18557e-008 ,0.24986),MV(-0.400044 , 0.216506 ,0.12486),MV(-0.399956 , 0.216506 ,-0.12514),MV(0.479764 , 0.1 ,0.754205),MV(0.362606 , 0.1 ,1.03705),MV(0.0797637 , 0.1 ,1.15421),MV(-0.203079 , 0.1 ,1.03705),MV(-0.320236 , 0.1 ,0.754205), + MV(-0.203079 , 0.1 ,0.471362),MV(0.0797637 , 0.1 ,0.354205),MV(0.362606 , 0.1 ,0.471362),MV(0.479764 , -0.1 ,0.754205),MV(0.362606 , -0.1 ,1.03705),MV(0.0797637 , -0.1 ,1.15421),MV(-0.203079 , -0.1 ,1.03705),MV(-0.320236 , -0.1 ,0.754205),MV(0.0797637 , -0.1 ,0.354205),MV(0.362606 , -0.1 ,0.471362), + MV(-0.203079 , -0.1 ,0.471362), }; + int ff[88][3]={ + {0,2,3}, + {3,1,0},{4,5,7},{7,6,4},{0,1,5},{5,4,0},{1,3,7},{7,5,1},{3,2,6},{6,7,3},{2,0,4}, + {4,6,2},{10,9,8},{10,12,11},{10,13,12},{10,14,13},{10,15,14},{10,8,15},{8,17,16},{8,9,17},{9,18,17}, + {9,10,18},{10,19,18},{10,11,19},{11,20,19},{11,12,20},{12,21,20},{12,13,21},{13,23,21},{13,14,23},{14,22,23}, + {14,15,22},{15,16,22},{15,8,16},{23,16,17},{23,17,18},{23,18,19},{23,19,20},{23,20,21},{23,22,16},{25,27,26}, + {25,28,27},{25,29,28},{25,24,29},{24,31,30},{24,25,31},{25,32,31},{25,26,32},{26,33,32},{26,27,33},{27,34,33}, + {27,28,34},{28,35,34},{28,29,35},{29,30,35},{29,24,30},{35,30,31},{35,31,32},{35,32,33},{35,33,34},{42,37,36}, + {42,38,37},{42,39,38},{42,40,39},{42,41,40},{42,36,43},{36,45,44},{36,37,45},{37,46,45},{37,38,46},{38,47,46}, + {38,39,47},{39,48,47},{39,40,48},{40,51,48},{40,41,51},{41,49,51},{41,42,49},{42,50,49},{42,43,50},{43,44,50}, + {43,36,44},{51,44,45},{51,45,46},{51,46,47},{51,47,48},{51,49,50},{51,50,44}, + }; - in.Clear(); - Allocator::AddVertices(in,52); - Allocator::AddFaces(in,88); + in.Clear(); + Allocator::AddVertices(in,52); + Allocator::AddFaces(in,88); - in.vn=52;in.fn=88; - int i,j; - for(i=0;i index(in.vn); + std::vector index(in.vn); - typename MeshType::VertexIterator vi; - for(j=0,vi=in.vert.begin();j diff --git a/vcg/complex/algorithms/create/zonohedron.h b/vcg/complex/algorithms/create/zonohedron.h index 8a686e19..160d3cf9 100644 --- a/vcg/complex/algorithms/create/zonohedron.h +++ b/vcg/complex/algorithms/create/zonohedron.h @@ -24,33 +24,28 @@ #ifndef __VCGLIB_ZONOHEDRON #define __VCGLIB_ZONOHEDRON - -#include -#include -typedef unsigned int uint; - namespace vcg { namespace tri { /** \addtogroup trimesh */ //@{ /** - A class to build a Zonohedron. + A class to build a Zonohedron. - Given a set of input vectors, a zonohedron is defined - as the convex hull of all the points which can be costructed by summing - together any subset of input vectors. - The surface closing this solid is composed only of flat parallelograms, - (which have the input vectors as sides). - It is always point-symmetric. + Given a set of input vectors, a zonohedron is defined + as the convex hull of all the points which can be costructed by summing + together any subset of input vectors. + The surface closing this solid is composed only of flat parallelograms, + (which have the input vectors as sides). + It is always point-symmetric. - Mesh created by this class are pure-quad meshes (triangular bit-quad), - (when coplanar vectors are fed, then planar groups of quads can be seen as - forming planar faces with more than 4 vertices). + Mesh created by this class are pure-quad meshes (triangular bit-quad), + (when coplanar vectors are fed, then planar groups of quads can be seen as + forming planar faces with more than 4 vertices). - USAGE: - 1) Instantiate a Zonohedron. - 2) Add input vectors at will to it, with addVector(s) - 3) When you are done, call createMesh. + USAGE: + 1) Instantiate a Zonohedron. + 2) Add input vectors at will to it, with addVector(s) + 3) When you are done, call createMesh. */ @@ -59,185 +54,185 @@ template class Zonohedron{ public: - typedef Point3 Vec3; + typedef Point3 Vec3; - Zonohedron(){} + Zonohedron(){} - void addVector(Scalar x, Scalar y, Scalar z); - void addVector(Vec3 v); - void addVectors(const std::vector< Vec3 > ); + void addVector(Scalar x, Scalar y, Scalar z); + void addVector(Vec3 v); + void addVectors(const std::vector< Vec3 > ); - const std::vector< Vec3 >& vectors() const { - return vec; - } + const std::vector< Vec3 >& vectors() const { + return vec; + } - template - void createMesh( MeshType& output ); + template + void createMesh( MeshType& output ); private: - /* classes for internal use */ - /****************************/ + /* classes for internal use */ + /****************************/ - typedef int VecIndex; // a number in [0..n) + typedef int VecIndex; // a number in [0..n) - /* the signature of a vertex (a 0 or 1 per input vector) */ - struct Signature { - std::vector< bool > v; - Signature(){} - Signature(int n){ v.resize(n,false); } + /* the signature of a vertex (a 0 or 1 per input vector) */ + struct Signature { + std::vector< bool > v; + Signature(){} + Signature(int n){ v.resize(n,false); } - bool operator == (const Signature & b) const { - return (b.v == v); - } - bool operator < (const Signature & b) const { - return (b.v < v); - } - Signature& set(VecIndex i, bool value){ - v[i] = value; - return *this; - } - Signature& set(VecIndex i, bool valueI, VecIndex j, bool valueJ){ - v[i] = valueI; - v[j] = valueJ; - return *this; - } - }; + bool operator == (const Signature & b) const { + return (b.v == v); + } + bool operator < (const Signature & b) const { + return (b.v < v); + } + Signature& set(VecIndex i, bool value){ + v[i] = value; + return *this; + } + Signature& set(VecIndex i, bool valueI, VecIndex j, bool valueJ){ + v[i] = valueI; + v[j] = valueJ; + return *this; + } + }; - struct Face { - int vert[4]; // index to vertex array - }; + struct Face { + int vert[4]; // index to vertex array + }; - /* precomputed cross products for all pairs of vectors */ - std::vector< Vec3 > precomputedCross; + /* precomputed cross products for all pairs of vectors */ + std::vector< Vec3 > precomputedCross; - void precompteAllCrosses(){ - precomputedCross.resize(n*n); - for (int i=0; i0) return v; - else if (v.X()<0) return -v; - else if (v.Y()>0) return v; - else if (v.Y()<0) return -v; - else if (v.Z()>0) return v; - return -v; - } + // given a vector, returns a copy pointing a unique verse + static Vec3 uniqueVerse(Vec3 v){ + if (v.X()>0) return v; + else if (v.X()<0) return -v; + else if (v.Y()>0) return v; + else if (v.Y()<0) return -v; + else if (v.Z()>0) return v; + return -v; + } - static Vec3 altVec(int i) { - return Vec3(1, i, i*i); - } + static Vec3 altVec(int i) { + return Vec3(1, i, i*i); + } - static Scalar tripleProduct( const Vec3 &a, const Vec3 &b, const Vec3 & c){ - return ( a ^ b ) * c; - } + static Scalar tripleProduct( const Vec3 &a, const Vec3 &b, const Vec3 & c){ + return ( a ^ b ) * c; + } - // returns signof: (i x j) * k - bool signOf_IxJoK(VecIndex i, VecIndex j, VecIndex k){ - const float EPSILON_SQUARED = 1e-12; - bool invert = false; - // sort i,j,k - if (i=0) != invert ); // XOR - } + return ( (res>=0) != invert ); // XOR + } - int n; // number of input vectors - std::vector vec; // input vectors + int n; // number of input vectors + std::vector vec; // input vectors - int vertCount; - std::vector _face; + int vertCount; + std::vector _face; - typedef std::map< Signature, int > VertexMap; - VertexMap vertexMap; + typedef std::map< Signature, int > VertexMap; + VertexMap vertexMap; - // given a vertex signature, returns index of vert (newly created or not) - VecIndex vertexIndex(const Signature &s){ - typename VertexMap::iterator i; - //Vec3 pos = s; //toPos(s); - i = vertexMap.find( s ); - if (i!= vertexMap.end() ) return i->second; - else { - int newVertex = vertCount++; - //vertexMap.insert(s) - vertexMap[s] = newVertex; - return newVertex; - } - } + // given a vertex signature, returns index of vert (newly created or not) + VecIndex vertexIndex(const Signature &s){ + typename VertexMap::iterator i; + //Vec3 pos = s; //toPos(s); + i = vertexMap.find( s ); + if (i!= vertexMap.end() ) return i->second; + else { + int newVertex = vertCount++; + //vertexMap.insert(s) + vertexMap[s] = newVertex; + return newVertex; + } + } - // given two index of vectors, returns face - Face& face(VecIndex i, VecIndex j){ - assert(i!=j); - assert( i*n + j < (int) _face.size() ); - return _face[i*n + j]; - } + // given two index of vectors, returns face + Face& face(VecIndex i, VecIndex j){ + assert(i!=j); + assert( i*n + j < (int) _face.size() ); + return _face[i*n + j]; + } - Vec3 toPos(const Signature &s) const{ - Vec3 res(0,0,0); - for (int i=0; i void Zonohedron::addVectors(std::vector< Zonohedron::Vec3 > input){ - for (uint i=0; i void Zonohedron::addVector(Scalar x, Scalar y, Scalar z) { - addVector( Vec3(x,y,z) ); + addVector( Vec3(x,y,z) ); } template void Zonohedron::addVector(Zonohedron::Vec3 v){ - vec.push_back(v); + vec.push_back(v); } template template void Zonohedron::createMesh(MeshType &m){ - typedef MeshType Mesh; - typedef typename Mesh::VertexPointer MeshVertexPointer; - typedef typename Mesh::VertexIterator MeshVertexIterator; - typedef typename Mesh::FaceIterator MeshFaceIterator; - typedef typename Mesh::FaceType MeshFace; + typedef MeshType Mesh; + typedef typename Mesh::VertexPointer MeshVertexPointer; + typedef typename Mesh::VertexIterator MeshVertexIterator; + typedef typename Mesh::FaceIterator MeshFaceIterator; + typedef typename Mesh::FaceType MeshFace; - createInternalMesh(); + createInternalMesh(); - m.Clear(); - Allocator::AddVertices(m,vertexMap.size()); + m.Clear(); + Allocator::AddVertices(m,vertexMap.size()); Allocator::AddFaces(m,n*(n-1) * 2); - // assign vertex positions - MeshVertexIterator vi=m.vert.begin(); - for (typename VertexMap::iterator i=vertexMap.begin(); i!=vertexMap.end(); i++){ - (vi + i->second )->P() = toPos( i->first ); - } + // assign vertex positions + MeshVertexIterator vi=m.vert.begin(); + for (typename VertexMap::iterator i=vertexMap.begin(); i!=vertexMap.end(); i++){ + (vi + i->second )->P() = toPos( i->first ); + } - // assegn FV connectivity + // assegn FV connectivity MeshFaceIterator fi=m.face.begin(); - for (int i=0; iV(w) = &* (vi + f.vert[(w+k*2)%4] ); - } - if (tri::HasPerFaceNormal(m)) { - fi->N() = cross(i,j).normalized(); - } - if (tri::HasPerFaceFlags(m)) { - fi->SetF(2); // quad diagonals are faux - } - fi++; - } - } - } + for (int i=0; iV(w) = &* (vi + f.vert[(w+k*2)%4] ); + } + if (tri::HasPerFaceNormal(m)) { + fi->N() = cross(i,j).normalized(); + } + if (tri::HasPerFaceFlags(m)) { + fi->SetF(2); // quad diagonals are faux + } + fi++; + } + } + } }