qutemol/0000755000175000017500000000000011633404241010622 5ustar mbambaqutemol/Makefile0000444000175000017500000000115010503734376012267 0ustar mbamba INCDIRS = -Ivcg -Isrc -I. OPTFLAGS = -Os -Wall -g CXXFLAGS = $(INCDIRS) $(OPTFLAGS) `wx-config --cppflags` LIBS = $(CXXFLAGS) `wx-config --libs core,base --gl-libs` -lGLEW -lGLU -lGL OBJS = \ src/AO.o \ src/AOgpu.o \ src/AtomColor.o \ src/CgUtil.o \ src/Common.o \ src/HardSettings.o \ src/Mol.o \ src/MyTab.o \ src/Sampling.o \ src/ShadowMap.o \ src/main.o \ src/wx_trackball.o \ vcg/wrap/gui/trackball.o \ vcg/wrap/gui/trackmode.o all: qutemol clean: find . -name "*.o" | xargs rm qutemol: $(OBJS) $(CXX) -o qutemol $(CFLAGS) $(OBJS) $(LIBS) qutemol/compile.txt0000444000175000017500000000044410462063650013017 0ustar mbambaQuteMol depends on the following libraries vcglib available on cvs access from http://vcg.sourceforge.net wxWidgets http://www.wxwidgets.org/ The standard building environment of QuteMol is DevCpp. and it assume that the cvs root of QuteMol is at the same level of the cvs root of vcglib qutemol/vcg/0000755000175000017500000000000011633404241011401 5ustar mbambaqutemol/vcg/vcg/0000755000175000017500000000000011633404241012160 5ustar mbambaqutemol/vcg/vcg/math/0000755000175000017500000000000011633404241013111 5ustar mbambaqutemol/vcg/vcg/math/gen_normal.h0000444000175000017500000001346310722106134015406 0ustar mbamba/**************************************************************************** * VCGLib o o * * Visual and Computer Graphics Library o o * * _ O _ * * Copyright(C) 2004 \/)\/ * * Visual Computing Lab /\/| * * ISTI - Italian National Research Council | * * \ * * All rights reserved. * * * * 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. * * * * 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 (http://www.gnu.org/licenses/gpl.txt) * * for more details. * * * ****************************************************************************/ /**************************************************************************** History $Log: gen_normal.h,v $ ****************************************************************************/ #ifndef __VCG_GEN_NORMAL #define __VCG_GEN_NORMAL #include namespace vcg { template class GenNormal { public: typedef Point3 Point3x; static void Random(int vn, std::vector > &NN) { NN.clear(); while(NN.size() > &NN, ScalarType AngleRad, Point3x dir=Point3x(0,1,0)) { std::vector > NNT; NN.clear(); // per prima cosa si calcola il volume della spherical cap di angolo AngleRad ScalarType Height= 1.0 - cos(AngleRad); // height is measured from top... // Surface is the one of the tangent cylinder ScalarType CapArea = 2.0*M_PI*Height; ScalarType Ratio = CapArea / (4.0*M_PI ); printf("----------AngleRad %f Angledeg %f ratio %f vn %i vn2 %i \n",AngleRad,math::ToDeg(AngleRad),Ratio,vn,int(vn/Ratio)); Uniform(vn/Ratio,NNT); printf("asked %i got %i (expecting %i instead of %i)\n", int(vn/Ratio), NNT.size(), int(NNT.size()*Ratio), vn); typename std::vector >::iterator vi; ScalarType DotProd = cos(AngleRad); for(vi=NNT.begin();vi!=NNT.end();++vi) { if(dir*(*vi) >= DotProd) NN.push_back(*vi); } } static void Uniform(int vn, std::vector > &NN) { OctaLevel pp; int ll=10; while(pow(4.0f,ll)+2>vn) ll--; pp.Init(ll); sort(pp.v.begin(),pp.v.end()); int newsize = unique(pp.v.begin(),pp.v.end())-pp.v.begin(); pp.v.resize(newsize); NN=pp.v; Perturb(NN); } static void Perturb(std::vector > &NN) { float width=0.2f/sqrt(float(NN.size())); typename std::vector >::iterator vi; for(vi=NN.begin(); vi!=NN.end();++vi) { Point3x pp(((float)rand())/RAND_MAX, ((float)rand())/RAND_MAX, ((float)rand())/RAND_MAX); pp=pp*2.0-Point3x(1,1,1); pp*=width; (*vi)+=pp; (*vi).Normalize(); } } /* Trova la normale piu vicina a quella data. Assume che tutte normale in ingresso sia normalizzata; */ static int BestMatchingNormal(const Point3x &n, std::vector &nv) { int ret=-1; ScalarType bestang=-1; ScalarType cosang; typename std::vector::iterator ni; for(ni=nv.begin();ni!=nv.end();++ni) { cosang=(*ni)*n; if(cosang>bestang) { bestang=cosang; ret=ni-nv.begin(); } } assert(ret>=0 && ret v; int level; int sz; Point3x &Val(int i, int j) { assert(i>=0 && i=0 && j >::iterator vi; for(vi=v.begin(); vi!=v.end();++vi) (*vi).Normalize(); } } }; }; } #endif qutemol/vcg/vcg/math/polar_decomposition.h0000444000175000017500000000565010337364477017357 0ustar mbamba/**************************************************************************** * VCGLib o o * * Visual and Computer Graphics Library o o * * _ O _ * * Copyright(C) 2004 \/)\/ * * Visual Computing Lab /\/| * * ISTI - Italian National Research Council | * * \ * * All rights reserved. * * * * 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. * * * * 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 (http://www.gnu.org/licenses/gpl.txt) * * for more details. * * * ****************************************************************************/ /**************************************************************************** History $Log: polar_decomposition.h,v $ Revision 1.1 2005/11/18 14:46:23 ganovelli created ****************************************************************************/ #ifndef POLAR_DECOMPOSITION_VCG #define POLAR_DECOMPOSITION_VCG #include #include #include namespace vcg{ /** \addtogroup math */ /* @{ */ /// Extract the rotational part of a matrix by polar decomposition /// m = R*S. Polar decomposition is computed by taking r = m * sqrt(m^t*m)^{-1} template void RotationalPartByPolarDecomposition( const vcg::Matrix33 & m, vcg::Matrix33 &r ){ vcg::Matrix33 tmp,s; r.SetZero(); s.SetZero(); tmp= m; tmp.Transpose(); tmp = m*tmp; Matrix33 res; Point3 e; bool ss = SingularValueDecomposition >(tmp,&e[0],res); res.Transpose(); e[0]=math::Sqrt(e[0]); e[1]=math::Sqrt(e[1]); e[2]=math::Sqrt(e[2]); tmp = tmp*Matrix33Diag(e)*res; bool s1 = SingularValueDecomposition >(tmp,&e[0],res); tmp.Transpose(); e[0]=1/e[0]; e[1]=1/e[1]; e[2]=1/e[2]; tmp = res*Matrix33Diag(e)*tmp; r = m*tmp; } /*! @} */ }; #endif qutemol/vcg/vcg/math/base.h0000444000175000017500000001614610651322635014207 0ustar mbamba/**************************************************************************** * VCGLib o o * * Visual and Computer Graphics Library o o * * _ O _ * * Copyright(C) 2004 \/)\/ * * Visual Computing Lab /\/| * * ISTI - Italian National Research Council | * * \ * * All rights reserved. * * * * 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. * * * * 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 (http://www.gnu.org/licenses/gpl.txt) * * for more details. * * * ****************************************************************************/ /**************************************************************************** History $Log: base.h,v $ Revision 1.22 2007/07/24 07:09:17 cignoni Added IsNAN Revision 1.21 2007/01/08 09:23:49 pietroni added explicit cast in function inline float Sqrt(const int v) in order to avoid warnings Revision 1.20 2006/10/13 13:14:50 cignoni Added two sqrt templates for resolving ambiguity of sqrt(int) Revision 1.19 2005/12/01 01:03:37 cignoni Removed excess ';' from end of template functions, for gcc compiling Revision 1.18 2004/08/31 15:42:59 fasano Aggiunte macro sin/cos/atan per C++ Builder Revision 1.17 2004/05/10 13:00:14 ganovelli limits function cancelled Revision 1.16 2004/05/03 08:38:08 ganovelli correction on templates Revision 1.15 2004/04/15 09:36:59 ganovelli Min and Max changed from const members to static class function Use: Value::Min() Revision 1.14 2004/03/31 12:41:55 tarini debugged Max and Min const values (to make them linkable) Revision 1.13 2004/03/31 10:09:19 cignoni int64 -> long long for GCC compatibility Revision 1.12 2004/03/16 00:23:50 tarini - added VoidType - added "static_assert" Revision 1.11 2004/03/10 17:37:54 tarini Added Atan2. Added common utilities: Max, Min, Swap, Sort(a,b), Sort(a,b,c). Changed Max values syntax. example: Value::Max Revision 1.10 2004/03/10 16:54:57 tarini Added Atan2. Added common utilities: Max, Min, Swap, Sort(a,b), Sort(a,b,c). Changed Max values syntax. example: Value::Max Revision 1.7 2004/03/08 19:38:29 tarini Added Min e Max. usage: Min::Value (tarini) Revision 1.6 2004/03/08 14:49:37 ponchio Aggiunti un po di inline davanti alle funzioni Revision 1.5 2004/03/04 00:21:00 ponchio added Acos e Asin Revision 1.4 2004/03/03 22:51:49 cignoni changed math from class to template Revision 1.2 2004/02/13 02:18:57 cignoni Edited Comments and GPL license ****************************************************************************/ #ifndef __VCGLIB_MATH_BASE #define __VCGLIB_MATH_BASE #include #include #include /// static_assert: implemented as a macro for "assert", but it is separated for clarity. /// Should be used for checking integrity constraints that can be tested at complile time, /// as the ones involving templated constants in templated classes. #define static_assert assert #ifdef __BORLANDC__ float sqrtf (float v) {return sqrt(v);} float fabsf (float v) {return fabs(v);} float cosf (float v) {return cos(v);} float sinf (float v) {return sin(v);} float acosf (float v) {return acos(v);} float asinf (float v) {return asin(v);} float atan2f (float v0, float v1) {return atan2(v0,v1);} #endif namespace vcg { namespace math { template class MagnitudoComparer { public: inline bool operator() ( const SCALAR a, const SCALAR b ) { return fabs(a)>fabs(b); } }; inline float Sqrt(const short v) { return sqrtf(v); } inline float Sqrt(const int v) { return sqrtf((float)v); } inline float Sqrt(const float v) { return sqrtf(v); } inline float Abs(const float v) { return fabsf(v); } inline float Cos(const float v) { return cosf(v); } inline float Sin(const float v) { return sinf(v); } inline float Acos(const float v) { return acosf(v); } inline float Asin(const float v) { return asinf(v); } inline float Atan2(const float v0,const float v1) { return atan2f(v0,v1); } inline double Sqrt(const double v) { return sqrt(v); } inline double Abs(const double v) { return fabs(v); } inline double Cos(const double v) { return cos(v); } inline double Sin(const double v) { return sin(v); } inline double Acos(const double v) { return acos(v); } inline double Asin(const double v) { return asin(v); } inline double Atan2(const double v0,const double v1) { return atan2(v0,v1); } template inline const T & Min(const T &a, const T &b){ if (a inline const T & Max(const T &a, const T &b){ if (a inline void Swap(T &a, T &b){ T tmp=a; a=b; b=tmp; } template inline void Sort(T &a, T &b){ if (a>b) Swap(a,b); } template inline void Sort(T &a, T &b, T &c){ if (a>b) Swap(a,b); if (b>c) {Swap(b,c); if (a>b) Swap(a,b);} } /* Some files do not define M_PI... */ #ifndef M_PI #define M_PI 3.14159265358979323846 #endif template inline SCALAR Clamp( const SCALAR & val, const SCALAR& minval, const SCALAR& maxval) { if(val < minval) return minval; if(val > maxval) return maxval; return val; } inline float ToDeg(const float &a){return a*180.0f/float(M_PI);} inline float ToRad(const float &a){return float(M_PI)*a/180.0f;} inline double ToDeg(const double &a){return a*180.0/M_PI;} inline double ToRad(const double &a){return M_PI*a/180.0;} #if defined(_MSC_VER) // Microsoft Visual C++ template int IsNAN(T t) { return _isnan(t); } #elif defined(__GNUC__) // GCC template int IsNAN(T t) { return isnan(t); } #else // generic template int IsNAN(T t) { if(std::numeric_limits::has_infinity) return !(t <= std::numeric_limits::infinity()); else return t != t; } #endif } // End math namespace /// a type that stands for "void". Useful for Parameter type of a point. class VoidType{ public: VoidType(){}; }; } // End vcg namespace #endif qutemol/vcg/vcg/math/matrix44.h0000444000175000017500000006757610645540353014770 0ustar mbamba/**************************************************************************** * VCGLib o o * * Visual and Computer Graphics Library o o * * _ O _ * * Copyright(C) 2004 \/)\/ * * Visual Computing Lab /\/| * * ISTI - Italian National Research Council | * * \ * * All rights reserved. * * * * 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. * * * * 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 (http://www.gnu.org/licenses/gpl.txt) * * for more details. * * * ****************************************************************************/ /**************************************************************************** History $Log: matrix44.h,v $ Revision 1.35 2007/07/13 00:01:47 cignoni added a static (unefficient!) identity member Revision 1.34 2007/07/12 06:42:01 cignoni added the missing static Construct() member Revision 1.33 2007/07/03 16:06:48 corsini add DCM to Euler Angles conversion Revision 1.32 2007/03/08 14:39:27 corsini final fix to euler angles transformation Revision 1.31 2007/02/06 09:57:40 corsini fix euler angles computation Revision 1.30 2007/02/05 14:16:33 corsini add from euler angles to rotation matrix conversion Revision 1.29 2005/12/02 09:46:49 croccia Corrected bug in == and != Matrix44 operators Revision 1.28 2005/06/28 17:42:47 ganovelli added Matrix44Diag Revision 1.27 2005/06/17 05:28:47 cignoni Completed Shear Matrix code and comments, Added use of swap inside Transpose Added more complete comments on the usage of Decompose Revision 1.26 2005/06/10 15:04:12 cignoni Added Various missing functions: SetShearXY, SetShearXZ, SetShearYZ, SetScale for point3 and Decompose Completed *=(scalar); made uniform GetRow and GetColumn Revision 1.25 2005/04/14 11:35:09 ponchio *** empty log message *** Revision 1.24 2005/03/18 00:14:39 cignoni removed small gcc compiling issues Revision 1.23 2005/03/15 11:40:56 cignoni Added operator*=( std::vector ...) to apply a matrix to a vector of vertexes (replacement of the old style mesh.Apply(tr). Revision 1.22 2004/12/15 18:45:50 tommyfranken *** empty log message *** Revision 1.21 2004/10/22 14:41:30 ponchio return in operator+ added. Revision 1.20 2004/10/18 15:03:14 fiorin Updated interface: all Matrix classes have now the same interface Revision 1.19 2004/10/07 14:23:57 ganovelli added function to take rows and comlumns. Added toMatrix and fromMatrix to comply RotationTYpe prototype in Similarity.h Revision 1.18 2004/05/28 13:01:50 ganovelli changed scalar to ScalarType Revision 1.17 2004/05/26 15:09:32 cignoni better comments in set rotate Revision 1.16 2004/05/07 10:05:50 cignoni Corrected abuse of for index variable scope Revision 1.15 2004/05/04 23:19:41 cignoni Clarified initial comment, removed vector*matrix operator (confusing!) Corrected translate and Rotate, removed gl stuff. Revision 1.14 2004/05/04 02:34:03 ganovelli wrong use of operator [] corrected Revision 1.13 2004/04/07 10:45:54 cignoni Added: [i][j] access, V() for the raw float values, constructor from T[16] Revision 1.12 2004/03/25 14:57:49 ponchio ****************************************************************************/ #ifndef __VCGLIB_MATRIX44 #define __VCGLIB_MATRIX44 #include #include #include #include #include namespace vcg { /* Annotations: Opengl stores matrix in column-major order. That is, the matrix is stored as: a0 a4 a8 a12 a1 a5 a9 a13 a2 a6 a10 a14 a3 a7 a11 a15 Usually in opengl (see opengl specs) vectors are 'column' vectors so usually matrix are PRE-multiplied for a vector. So the command glTranslate generate a matrix that is ready to be premultipled for a vector: 1 0 0 tx 0 1 0 ty 0 0 1 tz 0 0 0 1 Matrix44 stores matrix in row-major order i.e. a0 a1 a2 a3 a4 a5 a6 a7 a8 a9 a10 a11 a12 a13 a14 a15 So for the use of that matrix in opengl with their supposed meaning you have to transpose them before feeding to glMultMatrix. This mechanism is hidden by the templated function defined in wrap/gl/math.h; If your machine has the ARB_transpose_matrix extension it will use the appropriate; The various gl-like command SetRotate, SetTranslate assume that you are making matrix for 'column' vectors. */ template class Matrix44Diag:public Point4{ public: /** @name Matrix33 Class Matrix33Diag. This is the class for definition of a diagonal matrix 4x4. @param S (Templete Parameter) Specifies the ScalarType field. */ Matrix44Diag(const S & p0,const S & p1,const S & p2,const S & p3):Point4(p0,p1,p2,p3){}; Matrix44Diag( const Point4 & p ):Point4(p){}; }; /** This class represent a 4x4 matrix. T is the kind of element in the matrix. */ template class Matrix44 { protected: T _a[16]; public: typedef T ScalarType; ///@{ /** $name Constructors * No automatic casting and default constructor is empty */ Matrix44() {}; ~Matrix44() {}; Matrix44(const Matrix44 &m); Matrix44(const T v[]); /// Number of columns inline unsigned int ColumnsNumber() const { return 4; }; /// Number of rows inline unsigned int RowsNumber() const { return 4; }; T &ElementAt(const int row, const int col); T ElementAt(const int row, const int col) const; //T &operator[](const int i); //const T &operator[](const int i) const; T *V(); const T *V() const ; T *operator[](const int i); const T *operator[](const int i) const; // return a copy of the i-th column Point4 GetColumn4(const int& i)const{ assert(i>=0 && i<4); return Point4(ElementAt(0,i),ElementAt(1,i),ElementAt(2,i),ElementAt(3,i)); //return Point4(_a[i],_a[i+4],_a[i+8],_a[i+12]); } Point3 GetColumn3(const int& i)const{ assert(i>=0 && i<4); return Point3(ElementAt(0,i),ElementAt(1,i),ElementAt(2,i)); } Point4 GetRow4(const int& i)const{ assert(i>=0 && i<4); return Point4(ElementAt(i,0),ElementAt(i,1),ElementAt(i,2),ElementAt(i,3)); // return *((Point4*)(&_a[i<<2])); alternativa forse + efficiente } Point3 GetRow3(const int& i)const{ assert(i>=0 && i<4); return Point3(ElementAt(i,0),ElementAt(i,1),ElementAt(i,2)); // return *((Point4*)(&_a[i<<2])); alternativa forse + efficiente } Matrix44 operator+(const Matrix44 &m) const; Matrix44 operator-(const Matrix44 &m) const; Matrix44 operator*(const Matrix44 &m) const; Matrix44 operator*(const Matrix44Diag &m) const; Point4 operator*(const Point4 &v) const; bool operator==(const Matrix44 &m) const; bool operator!= (const Matrix44 &m) const; Matrix44 operator-() const; Matrix44 operator*(const T k) const; void operator+=(const Matrix44 &m); void operator-=(const Matrix44 &m); void operator*=( const Matrix44 & m ); void operator*=( const T k ); template void ToMatrix(Matrix44Type & m) const {for(int i = 0; i < 16; i++) m.V()[i]=V()[i];} void ToEulerAngles(T &alpha, T &beta, T &gamma); template void FromMatrix(const Matrix44Type & m){for(int i = 0; i < 16; i++) V()[i]=m.V()[i];} void FromEulerAngles(T alpha, T beta, T gamma); void SetZero(); void SetIdentity(); void SetDiagonal(const T k); Matrix44 &SetScale(const T sx, const T sy, const T sz); Matrix44 &SetScale(const Point3 &t); Matrix44 &SetTranslate(const Point3 &t); Matrix44 &SetTranslate(const T sx, const T sy, const T sz); Matrix44 &SetShearXY(const T sz); Matrix44 &SetShearXZ(const T sy); Matrix44 &SetShearYZ(const T sx); ///use radiants for angle. Matrix44 &SetRotate(T AngleRad, const Point3 & axis); T Determinant() const; template void Import(const Matrix44 &m) { for(int i = 0; i < 16; i++) _a[i] = (T)(m.V()[i]); } template static inline Matrix44 Construct( const Matrix44 & b ) { Matrix44 tmp; tmp.FromMatrix(b); return tmp; } static inline const Matrix44 &Identity( ) { static Matrix44 tmp; tmp.SetIdentity(); return tmp; } }; /** Class for solving A * x = b. */ template class LinearSolve: public Matrix44 { public: LinearSolve(const Matrix44 &m); Point4 Solve(const Point4 &b); // solve A x = b ///If you need to solve some equation you can use this function instead of Matrix44 one for speed. T Determinant() const; protected: ///Holds row permutation. int index[4]; //hold permutation ///Hold sign of row permutation (used for determinant sign) T d; bool Decompose(); }; /*** Postmultiply */ //template Point3 operator*(const Point3 &p, const Matrix44 &m); ///Premultiply template Point3 operator*(const Matrix44 &m, const Point3 &p); template Matrix44 &Transpose(Matrix44 &m); //return NULL matrix if not invertible template Matrix44 &Invert(Matrix44 &m); template Matrix44 Inverse(const Matrix44 &m); typedef Matrix44 Matrix44s; typedef Matrix44 Matrix44i; typedef Matrix44 Matrix44f; typedef Matrix44 Matrix44d; template Matrix44::Matrix44(const Matrix44 &m) { memcpy((T *)_a, (T *)m._a, 16 * sizeof(T)); } template Matrix44::Matrix44(const T v[]) { memcpy((T *)_a, v, 16 * sizeof(T)); } template T &Matrix44::ElementAt(const int row, const int col) { assert(row >= 0 && row < 4); assert(col >= 0 && col < 4); return _a[(row<<2) + col]; } template T Matrix44::ElementAt(const int row, const int col) const { assert(row >= 0 && row < 4); assert(col >= 0 && col < 4); return _a[(row<<2) + col]; } //template T &Matrix44::operator[](const int i) { // assert(i >= 0 && i < 16); // return ((T *)_a)[i]; //} // //template const T &Matrix44::operator[](const int i) const { // assert(i >= 0 && i < 16); // return ((T *)_a)[i]; //} template T *Matrix44::operator[](const int i) { assert(i >= 0 && i < 4); return _a+i*4; } template const T *Matrix44::operator[](const int i) const { assert(i >= 0 && i < 4); return _a+i*4; } template T *Matrix44::V() { return _a;} template const T *Matrix44::V() const { return _a;} template Matrix44 Matrix44::operator+(const Matrix44 &m) const { Matrix44 ret; for(int i = 0; i < 16; i++) ret.V()[i] = V()[i] + m.V()[i]; return ret; } template Matrix44 Matrix44::operator-(const Matrix44 &m) const { Matrix44 ret; for(int i = 0; i < 16; i++) ret.V()[i] = V()[i] - m.V()[i]; return ret; } template Matrix44 Matrix44::operator*(const Matrix44 &m) const { Matrix44 ret; for(int i = 0; i < 4; i++) for(int j = 0; j < 4; j++) { T t = 0.0; for(int k = 0; k < 4; k++) t += ElementAt(i, k) * m.ElementAt(k, j); ret.ElementAt(i, j) = t; } return ret; } template Matrix44 Matrix44::operator*(const Matrix44Diag &m) const { Matrix44 ret = (*this); for(int i = 0; i < 4; ++i) for(int j = 0; j < 4; ++j) ret[i][j]*=m[i]; return ret; } template Point4 Matrix44::operator*(const Point4 &v) const { Point4 ret; for(int i = 0; i < 4; i++){ T t = 0.0; for(int k = 0; k < 4; k++) t += ElementAt(i,k) * v[k]; ret[i] = t; } return ret; } template bool Matrix44::operator==(const Matrix44 &m) const { for(int i = 0; i < 4; ++i) for(int j = 0; j < 4; ++j) if(ElementAt(i,j) != m.ElementAt(i,j)) return false; return true; } template bool Matrix44::operator!=(const Matrix44 &m) const { for(int i = 0; i < 4; ++i) for(int j = 0; j < 4; ++j) if(ElementAt(i,j) != m.ElementAt(i,j)) return true; return false; } template Matrix44 Matrix44::operator-() const { Matrix44 res; for(int i = 0; i < 16; i++) res.V()[i] = -V()[i]; return res; } template Matrix44 Matrix44::operator*(const T k) const { Matrix44 res; for(int i = 0; i < 16; i++) res.V()[i] =V()[i] * k; return res; } template void Matrix44::operator+=(const Matrix44 &m) { for(int i = 0; i < 16; i++) V()[i] += m.V()[i]; } template void Matrix44::operator-=(const Matrix44 &m) { for(int i = 0; i < 16; i++) V()[i] -= m.V()[i]; } template void Matrix44::operator*=( const Matrix44 & m ) { *this = *this *m; /*for(int i = 0; i < 4; i++) { //sbagliato Point4 t(0, 0, 0, 0); for(int k = 0; k < 4; k++) { for(int j = 0; j < 4; j++) { t[k] += ElementAt(i, k) * m.ElementAt(k, j); } } for(int l = 0; l < 4; l++) ElementAt(i, l) = t[l]; } */ } template < class PointType , class T > void operator*=( std::vector &vert, const Matrix44 & m ) { typename std::vector::iterator ii; for(ii=vert.begin();ii!=vert.end();++ii) (*ii).P()=m * (*ii).P(); } template void Matrix44::operator*=( const T k ) { for(int i = 0; i < 16; i++) _a[i] *= k; } template void Matrix44::ToEulerAngles(T &alpha, T &beta, T &gamma) { alpha = atan2(ElementAt(1,2), ElementAt(2,2)); beta = asin(-ElementAt(0,2)); gamma = atan2(ElementAt(0,1), ElementAt(1,1)); } template void Matrix44::FromEulerAngles(T alpha, T beta, T gamma) { this->SetZero(); T cosalpha = cos(alpha); T cosbeta = cos(beta); T cosgamma = cos(gamma); T sinalpha = sin(alpha); T sinbeta = sin(beta); T singamma = sin(gamma); ElementAt(0,0) = cosbeta * cosgamma; ElementAt(1,0) = -cosalpha * singamma + sinalpha * sinbeta * cosgamma; ElementAt(2,0) = sinalpha * singamma + cosalpha * sinbeta * cosgamma; ElementAt(0,1) = cosbeta * singamma; ElementAt(1,1) = cosalpha * cosgamma + sinalpha * sinbeta * singamma; ElementAt(2,1) = -sinalpha * cosgamma + cosalpha * sinbeta * singamma; ElementAt(0,2) = -sinbeta; ElementAt(1,2) = sinalpha * cosbeta; ElementAt(2,2) = cosalpha * cosbeta; ElementAt(3,3) = 1; } template void Matrix44::SetZero() { memset((T *)_a, 0, 16 * sizeof(T)); } template void Matrix44::SetIdentity() { SetDiagonal(1); } template void Matrix44::SetDiagonal(const T k) { SetZero(); ElementAt(0, 0) = k; ElementAt(1, 1) = k; ElementAt(2, 2) = k; ElementAt(3, 3) = 1; } template Matrix44 &Matrix44::SetScale(const Point3 &t) { SetScale(t[0], t[1], t[2]); return *this; } template Matrix44 &Matrix44::SetScale(const T sx, const T sy, const T sz) { SetZero(); ElementAt(0, 0) = sx; ElementAt(1, 1) = sy; ElementAt(2, 2) = sz; ElementAt(3, 3) = 1; return *this; } template Matrix44 &Matrix44::SetTranslate(const Point3 &t) { SetTranslate(t[0], t[1], t[2]); return *this; } template Matrix44 &Matrix44::SetTranslate(const T tx, const T ty, const T tz) { SetIdentity(); ElementAt(0, 3) = tx; ElementAt(1, 3) = ty; ElementAt(2, 3) = tz; return *this; } template Matrix44 &Matrix44::SetRotate(T AngleRad, const Point3 & axis) { //angle = angle*(T)3.14159265358979323846/180; e' in radianti! T c = math::Cos(AngleRad); T s = math::Sin(AngleRad); T q = 1-c; Point3 t = axis; t.Normalize(); ElementAt(0,0) = t[0]*t[0]*q + c; ElementAt(0,1) = t[0]*t[1]*q - t[2]*s; ElementAt(0,2) = t[0]*t[2]*q + t[1]*s; ElementAt(0,3) = 0; ElementAt(1,0) = t[1]*t[0]*q + t[2]*s; ElementAt(1,1) = t[1]*t[1]*q + c; ElementAt(1,2) = t[1]*t[2]*q - t[0]*s; ElementAt(1,3) = 0; ElementAt(2,0) = t[2]*t[0]*q -t[1]*s; ElementAt(2,1) = t[2]*t[1]*q +t[0]*s; ElementAt(2,2) = t[2]*t[2]*q +c; ElementAt(2,3) = 0; ElementAt(3,0) = 0; ElementAt(3,1) = 0; ElementAt(3,2) = 0; ElementAt(3,3) = 1; return *this; } /* Shear Matrixes XY 1 k 0 0 x x+ky 0 1 0 0 y y 0 0 1 0 z z 0 0 0 1 1 1 1 0 k 0 x x+kz 0 1 0 0 y y 0 0 1 0 z z 0 0 0 1 1 1 1 1 0 0 x x 0 1 k 0 y y+kz 0 0 1 0 z z 0 0 0 1 1 1 */ template Matrix44 & Matrix44:: SetShearXY( const T sh) {// shear the X coordinate as the Y coordinate change SetIdentity(); ElementAt(0,1) = sh; return *this; } template Matrix44 & Matrix44:: SetShearXZ( const T sh) {// shear the X coordinate as the Z coordinate change SetIdentity(); ElementAt(0,2) = sh; return *this; } template Matrix44 &Matrix44:: SetShearYZ( const T sh) {// shear the Y coordinate as the Z coordinate change SetIdentity(); ElementAt(1,2) = sh; return *this; } /* Given a non singular, non projective matrix (e.g. with the last row equal to [0,0,0,1] ) This procedure decompose it in a sequence of Scale,Shear,Rotation e Translation - ScaleV and Tranv are obiviously scaling and translation. - ShearV contains three scalars with, respectively ShearXY, ShearXZ e ShearYZ - RotateV contains the rotations (in degree!) around the x,y,z axis The input matrix is modified leaving inside it a simple roto translation. To obtain the original matrix the above transformation have to be applied in the strict following way: OriginalMatrix = Trn * Rtx*Rty*Rtz * ShearYZ*ShearXZ*ShearXY * Scl Example Code: double srv() { return (double(rand()%40)-20)/2.0; } // small random value srand(time(0)); Point3d ScV(10+srv(),10+srv(),10+srv()),ScVOut(-1,-1,-1); Point3d ShV(srv(),srv(),srv()),ShVOut(-1,-1,-1); Point3d RtV(10+srv(),srv(),srv()),RtVOut(-1,-1,-1); Point3d TrV(srv(),srv(),srv()),TrVOut(-1,-1,-1); Matrix44d Scl; Scl.SetScale(ScV); Matrix44d Sxy; Sxy.SetShearXY(ShV[0]); Matrix44d Sxz; Sxz.SetShearXZ(ShV[1]); Matrix44d Syz; Syz.SetShearYZ(ShV[2]); Matrix44d Rtx; Rtx.SetRotate(math::ToRad(RtV[0]),Point3d(1,0,0)); Matrix44d Rty; Rty.SetRotate(math::ToRad(RtV[1]),Point3d(0,1,0)); Matrix44d Rtz; Rtz.SetRotate(math::ToRad(RtV[2]),Point3d(0,0,1)); Matrix44d Trn; Trn.SetTranslate(TrV); Matrix44d StartM = Trn * Rtx*Rty*Rtz * Syz*Sxz*Sxy *Scl; Matrix44d ResultM=StartM; Decompose(ResultM,ScVOut,ShVOut,RtVOut,TrVOut); Scl.SetScale(ScVOut); Sxy.SetShearXY(ShVOut[0]); Sxz.SetShearXZ(ShVOut[1]); Syz.SetShearYZ(ShVOut[2]); Rtx.SetRotate(math::ToRad(RtVOut[0]),Point3d(1,0,0)); Rty.SetRotate(math::ToRad(RtVOut[1]),Point3d(0,1,0)); Rtz.SetRotate(math::ToRad(RtVOut[2]),Point3d(0,0,1)); Trn.SetTranslate(TrVOut); // Now Rebuild is equal to StartM Matrix44d RebuildM = Trn * Rtx*Rty*Rtz * Syz*Sxz*Sxy * Scl ; */ template bool Decompose(Matrix44 &M, Point3 &ScaleV, Point3 &ShearV, Point3 &RotV,Point3 &TranV) { if(!(M[3][0]==0 && M[3][1]==0 && M[3][2]==0 && M[3][3]==1) ) // the matrix is projective return false; if(math::Abs(M.Determinant())<1e-10) return false; // matrix should be at least invertible... // First Step recover the traslation TranV=M.GetColumn3(3); // Second Step Recover Scale and Shearing interleaved ScaleV[0]=Norm(M.GetColumn3(0)); Point3d R[3]; R[0]=M.GetColumn3(0); R[0].Normalize(); ShearV[0]=R[0]*M.GetColumn3(1); // xy shearing R[1]= M.GetColumn3(1)-R[0]*ShearV[0]; assert(math::Abs(R[1]*R[0])<1e-10); ScaleV[1]=Norm(R[1]); // y scaling R[1]=R[1]/ScaleV[1]; ShearV[0]=ShearV[0]/ScaleV[1]; ShearV[1]=R[0]*M.GetColumn3(2); // xz shearing R[2]= M.GetColumn3(2)-R[0]*ShearV[1]; assert(math::Abs(R[2]*R[0])<1e-10); R[2] = R[2]-R[1]*(R[2]*R[1]); assert(math::Abs(R[2]*R[1])<1e-10); assert(math::Abs(R[2]*R[0])<1e-10); ScaleV[2]=Norm(R[2]); ShearV[1]=ShearV[1]/ScaleV[2]; R[2]=R[2]/ScaleV[2]; assert(math::Abs(R[2]*R[1])<1e-10); assert(math::Abs(R[2]*R[0])<1e-10); ShearV[2]=R[1]*M.GetColumn3(2); // yz shearing ShearV[2]=ShearV[2]/ScaleV[2]; int i,j; for(i=0;i<3;++i) for(j=0;j<3;++j) M[i][j]=R[j][i]; // Third and last step: Recover the rotation //now the matrix should be a pure rotation matrix so its determinant is +-1 double det=M.Determinant(); if(math::Abs(det)<1e-10) return false; // matrix should be at least invertible... assert(math::Abs(math::Abs(det)-1.0)<1e-10); // it should be +-1... if(det<0) { ScaleV *= -1; M *= -1; } double alpha,beta,gamma; // rotations around the x,y and z axis beta=asin( M[0][2]); double cosbeta=cos(beta); if(math::Abs(cosbeta) > 1e-5) { alpha=asin(-M[1][2]/cosbeta); if((M[2][2]/cosbeta) < 0 ) alpha=M_PI-alpha; gamma=asin(-M[0][1]/cosbeta); if((M[0][0]/cosbeta)<0) gamma = M_PI-gamma; } else { alpha=asin(-M[1][0]); if(M[1][1]<0) alpha=M_PI-alpha; gamma=0; } RotV[0]=math::ToDeg(alpha); RotV[1]=math::ToDeg(beta); RotV[2]=math::ToDeg(gamma); return true; } template T Matrix44::Determinant() const { LinearSolve solve(*this); return solve.Determinant(); } template Point3 operator*(const Matrix44 &m, const Point3 &p) { T w; Point3 s; s[0] = m.ElementAt(0, 0)*p[0] + m.ElementAt(0, 1)*p[1] + m.ElementAt(0, 2)*p[2] + m.ElementAt(0, 3); s[1] = m.ElementAt(1, 0)*p[0] + m.ElementAt(1, 1)*p[1] + m.ElementAt(1, 2)*p[2] + m.ElementAt(1, 3); s[2] = m.ElementAt(2, 0)*p[0] + m.ElementAt(2, 1)*p[1] + m.ElementAt(2, 2)*p[2] + m.ElementAt(2, 3); w = m.ElementAt(3, 0)*p[0] + m.ElementAt(3, 1)*p[1] + m.ElementAt(3, 2)*p[2] + m.ElementAt(3, 3); if(w!= 0) s /= w; return s; } //template Point3 operator*(const Point3 &p, const Matrix44 &m) { // T w; // Point3 s; // s[0] = m.ElementAt(0, 0)*p[0] + m.ElementAt(1, 0)*p[1] + m.ElementAt(2, 0)*p[2] + m.ElementAt(3, 0); // s[1] = m.ElementAt(0, 1)*p[0] + m.ElementAt(1, 1)*p[1] + m.ElementAt(2, 1)*p[2] + m.ElementAt(3, 1); // s[2] = m.ElementAt(0, 2)*p[0] + m.ElementAt(1, 2)*p[1] + m.ElementAt(2, 2)*p[2] + m.ElementAt(3, 2); // w = m.ElementAt(0, 3)*p[0] + m.ElementAt(1, 3)*p[1] + m.ElementAt(2, 3)*p[2] + m.ElementAt(3, 3); // if(w != 0) s /= w; // return s; //} template Matrix44 &Transpose(Matrix44 &m) { for(int i = 1; i < 4; i++) for(int j = 0; j < i; j++) { math::Swap(m.ElementAt(i, j), m.ElementAt(j, i)); } return m; } template Matrix44 &Invert(Matrix44 &m) { LinearSolve solve(m); for(int j = 0; j < 4; j++) { //Find inverse by columns. Point4 col(0, 0, 0, 0); col[j] = 1.0; col = solve.Solve(col); for(int i = 0; i < 4; i++) m.ElementAt(i, j) = col[i]; } return m; } template Matrix44 Inverse(const Matrix44 &m) { LinearSolve solve(m); Matrix44 res; for(int j = 0; j < 4; j++) { //Find inverse by columns. Point4 col(0, 0, 0, 0); col[j] = 1.0; col = solve.Solve(col); for(int i = 0; i < 4; i++) res.ElementAt(i, j) = col[i]; } return res; } /* LINEAR SOLVE IMPLEMENTATION */ template LinearSolve::LinearSolve(const Matrix44 &m): Matrix44(m) { if(!Decompose()) { for(int i = 0; i < 4; i++) index[i] = i; Matrix44::SetZero(); } } template T LinearSolve::Determinant() const { T det = d; for(int j = 0; j < 4; j++) det *= this-> ElementAt(j, j); return det; } /*replaces a matrix by its LU decomposition of a rowwise permutation. d is +or -1 depeneing of row permutation even or odd.*/ #define TINY 1e-100 template bool LinearSolve::Decompose() { /* Matrix44 A; for(int i = 0; i < 16; i++) A[i] = operator[](i); SetIdentity(); Point4 scale; // Set scale factor, scale(i) = max( |a(i,j)| ), for each row for(int i = 0; i < 4; i++ ) { index[i] = i; // Initialize row index list T scalemax = (T)0.0; for(int j = 0; j < 4; j++) scalemax = (scalemax > math::Abs(A.ElementAt(i,j))) ? scalemax : math::Abs(A.ElementAt(i,j)); scale[i] = scalemax; } // Loop over rows k = 1, ..., (N-1) int signDet = 1; for(int k = 0; k < 3; k++ ) { // Select pivot row from max( |a(j,k)/s(j)| ) T ratiomax = (T)0.0; int jPivot = k; for(int i = k; i < 4; i++ ) { T ratio = math::Abs(A.ElementAt(index[i], k))/scale[index[i]]; if(ratio > ratiomax) { jPivot = i; ratiomax = ratio; } } // Perform pivoting using row index list int indexJ = index[k]; if( jPivot != k ) { // Pivot indexJ = index[jPivot]; index[jPivot] = index[k]; // Swap index jPivot and k index[k] = indexJ; signDet *= -1; // Flip sign of determinant } // Perform forward elimination for(int i=k+1; i < 4; i++ ) { T coeff = A.ElementAt(index[i],k)/A.ElementAt(indexJ,k); for(int j=k+1; j < 4; j++ ) A.ElementAt(index[i],j) -= coeff*A.ElementAt(indexJ,j); A.ElementAt(index[i],k) = coeff; //for( j=1; j< 4; j++ ) // ElementAt(index[i],j) -= A.ElementAt(index[i], k)*ElementAt(indexJ, j); } } for(int i = 0; i < 16; i++) operator[](i) = A[i]; d = signDet; // this = A; return true; */ d = 1; //no permutation still T scaling[4]; int i,j,k; //Saving the scvaling information per row for(i = 0; i < 4; i++) { T largest = 0.0; for(j = 0; j < 4; j++) { T t = math::Abs(this->ElementAt(i, j)); if (t > largest) largest = t; } if (largest == 0.0) { //oooppps there is a zero row! return false; } scaling[i] = (T)1.0 / largest; } int imax; for(j = 0; j < 4; j++) { for(i = 0; i < j; i++) { T sum = this->ElementAt(i,j); for(int k = 0; k < i; k++) sum -= this->ElementAt(i,k)*this->ElementAt(k,j); this->ElementAt(i,j) = sum; } T largest = 0.0; for(i = j; i < 4; i++) { T sum = this->ElementAt(i,j); for(k = 0; k < j; k++) sum -= this->ElementAt(i,k)*this->ElementAt(k,j); this->ElementAt(i,j) = sum; T t = scaling[i] * math::Abs(sum); if(t >= largest) { largest = t; imax = i; } } if (j != imax) { for (int k = 0; k < 4; k++) { T dum = this->ElementAt(imax,k); this->ElementAt(imax,k) = this->ElementAt(j,k); this->ElementAt(j,k) = dum; } d = -(d); scaling[imax] = scaling[j]; } index[j]=imax; if (this->ElementAt(j,j) == 0.0) this->ElementAt(j,j) = (T)TINY; if (j != 3) { T dum = (T)1.0 / (this->ElementAt(j,j)); for (i = j+1; i < 4; i++) this->ElementAt(i,j) *= dum; } } return true; } template Point4 LinearSolve::Solve(const Point4 &b) { Point4 x(b); int first = -1, ip; for(int i = 0; i < 4; i++) { ip = index[i]; T sum = x[ip]; x[ip] = x[i]; if(first!= -1) for(int j = first; j <= i-1; j++) sum -= this->ElementAt(i,j) * x[j]; else if(sum) first = i; x[i] = sum; } for (int i = 3; i >= 0; i--) { T sum = x[i]; for (int j = i+1; j < 4; j++) sum -= this->ElementAt(i, j) * x[j]; x[i] = sum / this->ElementAt(i, i); } return x; } } //namespace #endif qutemol/vcg/vcg/math/disjoint_set.h0000444000175000017500000001250010524140351015751 0ustar mbamba/**************************************************************************** * VCGLib o o * * Visual and Computer Graphics Library o o * * _ O _ * * Copyright(C) 2004 \/)\/ * * Visual Computing Lab /\/| * * ISTI - Italian National Research Council | * * \ * * All rights reserved. * * * * 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. * * * * 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 (http://www.gnu.org/licenses/gpl.txt) * * for more details. * * * ****************************************************************************/ #ifndef VCG_MATH_UNIONSET_H #define VCG_MATH_UNIONSET_H // some stuff for portable hashes... #ifdef WIN32 #ifndef __MINGW32__ #include #include #define STDEXT stdext #else #include #include #define STDEXT __gnu_cxx #endif #else #include #include #define STDEXT __gnu_cxx // It's terrible but gnu's hash_map needs an instantiation of hash() for // every key type! So we cast the pointer to void* namespace __gnu_cxx { template <> class hash: private hash { public: size_t operator()(const void *ptr) const { return hash::operator()((unsigned long)ptr); } }; } #endif #include #include namespace vcg { /*! * Given a set of elements, it is often useful to break them up or partition them into a number of separate, nonoverlapping groups. * A disjoint-set data structure is a data structure that keeps track of such a partitioning. See * Diskoint-set data structure on Wikipedia for more details. */ template class DisjointSet { /************************************************* * Inner class definitions **************************************************/ struct DisjointSetNode { DisjointSetNode(OBJECT_TYPE *x) {obj=x; parent=obj; rank=0;} OBJECT_TYPE *obj; OBJECT_TYPE *parent; int rank; }; typedef OBJECT_TYPE* ObjectPointer; typedef std::pair< ObjectPointer, int > hPair; struct SimpleObjHashFunc{ inline size_t operator ()(const ObjectPointer &p) const {return size_t(p);} }; #ifdef _MSC_VER STDEXT::hash_map< OBJECT_TYPE*, int > inserted_objects; typedef typename STDEXT::hash_map< ObjectPointer, int >::iterator hIterator; #else STDEXT::hash_map< OBJECT_TYPE*, int, SimpleObjHashFunc > inserted_objects; typedef typename STDEXT::hash_map< ObjectPointer, int, SimpleObjHashFunc >::iterator hIterator; #endif typedef std::pair< hIterator, bool > hInsertResult; public: /*! * Default constructor */ DisjointSet() {} /*! * Makes a group containing only a given element (a singleton). */ void MakeSet(OBJECT_TYPE *x) { int object_count = int(inserted_objects.size()); assert(inserted_objects.find(x)==inserted_objects.end()); //the map mustn't already contain the object x nodes.push_back(DisjointSetNode(x)); inserted_objects.insert( hPair(x,object_count) ); } /*! * Combine or merge two groups into a single group. */ void Union(OBJECT_TYPE *x, OBJECT_TYPE *y) { OBJECT_TYPE *s0 = FindSet(x); OBJECT_TYPE *s1 = FindSet(y); Link(s0, s1); } /*! * Determine which group a particular element is in. */ OBJECT_TYPE* FindSet(OBJECT_TYPE *x) { hIterator pos = inserted_objects.find(x); assert(pos!=inserted_objects.end()); DisjointSetNode *node = &nodes[pos->second]; if (node->parent!=x) node->parent = FindSet(node->parent); return node->parent; } private: /* */ void Link(OBJECT_TYPE *x, OBJECT_TYPE *y) { hIterator xPos = inserted_objects.find(x); hIterator yPos = inserted_objects.find(y); assert(xPos!=inserted_objects.end() && yPos!=inserted_objects.end()); DisjointSetNode *xNode = &nodes[xPos->second]; DisjointSetNode *yNode = &nodes[yPos->second]; if (xNode->rank>yNode->rank) xNode->parent = y; else { yNode->parent = x; if (xNode->rank==yNode->rank) yNode->rank++; } } protected: std::vector< DisjointSetNode > nodes; }; };// end of namespace vcg #endif //VCG_MATH_UNIONSET_H qutemol/vcg/vcg/math/perlin_noise.h0000444000175000017500000001351110272076117015754 0ustar mbamba/*#*************************************************************************** * perlin_noise.h o o * * o o * * Visual Computing Group _ O _ * * IEI Institute, CNUCE Institute, CNR Pisa \/)\/ * * /\/| * * Copyright(C) 1999 by Paolo Cignoni, Paolo Pingi, Claudio Rocchini | * * All rights reserved. \ * * * * Permission to use, copy, modify, distribute and sell this software and * * its documentation for any purpose is hereby granted without fee, provided * * that the above copyright notice appear in all copies and that both that * * copyright notice and this permission notice appear in supporting * * documentation. the author makes no representations about the suitability * * of this software for any purpose. It is provided "as is" without express * * or implied warranty. * * * *****************************************************************************/ /**************************************************************************** History $Log: perlin_noise.h,v $ Revision 1.1 2005/07/28 06:33:51 cignoni First working version *****************************************************************************/ #ifndef __VCGLIB_PERLIN_NOISE #define __VCGLIB_PERLIN_NOISE namespace vcg { namespace math { // based on the java reference implementation published // on http://mrl.nyu.edu/~perlin/noise/ // updated on 13/7/2005 class Perlin { public: /// 3D Perlin noise /// return a value in the 0..1 range with period 255 static double Noise(double x, double y, double z) { int X = (int)floor(x) & 255, // FIND UNIT CUBE THAT Y = (int)floor(y) & 255, // CONTAINS POINT. Z = (int)floor(z) & 255; x -= floor(x); // FIND RELATIVE X,Y,Z y -= floor(y); // OF POINT IN CUBE. z -= floor(z); double u = fade(x), // COMPUTE FADE CURVES v = fade(y), // FOR EACH OF X,Y,Z. w = fade(z); int A = P(X )+Y, AA = P(A)+Z, AB = P(A+1)+Z, // HASH COORDINATES OF B = P(X+1)+Y, BA = P(B)+Z, BB = P(B+1)+Z; // THE 8 CUBE CORNERS, return lerp(w, lerp(v, lerp(u, grad(P(AA ), x , y , z ), // AND ADD grad(P(BA ), x-1, y , z )), // BLENDED lerp(u, grad(P(AB ), x , y-1, z ), // RESULTS grad(P(BB ), x-1, y-1, z ))),// FROM 8 lerp(v, lerp(u, grad(P(AA+1), x , y , z-1 ), // CORNERS grad(P(BA+1), x-1, y , z-1 )), // OF CUBE lerp(u, grad(P(AB+1), x , y-1, z-1 ), grad(P(BB+1), x-1, y-1, z-1 )))); } static double fade(double t) { return t * t * t * (t * (t * 6 - 15) + 10); } static double lerp(double t, double a, double b) { return a + t * (b - a); } static double grad(int hash, double x, double y, double z) { int h = hash & 15; // CONVERT LO 4 BITS OF HASH CODE double u = h<8 ? x : y, // INTO 12 GRADIENT DIRECTIONS. v = h<4 ? y : h==12||h==14 ? x : z; return ((h&1) == 0 ? u : -u) + ((h&2) == 0 ? v : -v); } static int P(int i) { static int p[512]= { 151,160,137,91,90,15, 131,13,201,95,96,53,194,233,7,225,140,36,103,30,69,142,8,99,37,240,21,10,23, 190, 6,148,247,120,234,75,0,26,197,62,94,252,219,203,117,35,11,32,57,177,33, 88,237,149,56,87,174,20,125,136,171,168, 68,175,74,165,71,134,139,48,27,166, 77,146,158,231,83,111,229,122,60,211,133,230,220,105,92,41,55,46,245,40,244, 102,143,54, 65,25,63,161, 1,216,80,73,209,76,132,187,208, 89,18,169,200,196, 135,130,116,188,159,86,164,100,109,198,173,186, 3,64,52,217,226,250,124,123, 5,202,38,147,118,126,255,82,85,212,207,206,59,227,47,16,58,17,182,189,28,42, 223,183,170,213,119,248,152, 2,44,154,163, 70,221,153,101,155,167, 43,172,9, 129,22,39,253, 19,98,108,110,79,113,224,232,178,185, 112,104,218,246,97,228, 251,34,242,193,238,210,144,12,191,179,162,241, 81,51,145,235,249,14,239,107, 49,192,214, 31,181,199,106,157,184, 84,204,176,115,121,50,45,127, 4,150,254, 138,236,205,93,222,114,67,29,24,72,243,141,128,195,78,66,215,61,156,180, 151,160,137,91,90,15, 131,13,201,95,96,53,194,233,7,225,140,36,103,30,69,142,8,99,37,240,21,10,23, 190, 6,148,247,120,234,75,0,26,197,62,94,252,219,203,117,35,11,32,57,177,33, 88,237,149,56,87,174,20,125,136,171,168, 68,175,74,165,71,134,139,48,27,166, 77,146,158,231,83,111,229,122,60,211,133,230,220,105,92,41,55,46,245,40,244, 102,143,54, 65,25,63,161, 1,216,80,73,209,76,132,187,208, 89,18,169,200,196, 135,130,116,188,159,86,164,100,109,198,173,186, 3,64,52,217,226,250,124,123, 5,202,38,147,118,126,255,82,85,212,207,206,59,227,47,16,58,17,182,189,28,42, 223,183,170,213,119,248,152, 2,44,154,163, 70,221,153,101,155,167, 43,172,9, 129,22,39,253, 19,98,108,110,79,113,224,232,178,185, 112,104,218,246,97,228, 251,34,242,193,238,210,144,12,191,179,162,241, 81,51,145,235,249,14,239,107, 49,192,214, 31,181,199,106,157,184, 84,204,176,115,121,50,45,127, 4,150,254, 138,236,205,93,222,114,67,29,24,72,243,141,128,195,78,66,215,61,156,180 }; return p[i]; } }; } // end namespace } // end namespace #endif qutemol/vcg/vcg/math/point_matching.h0000444000175000017500000003536610757610037016310 0ustar mbamba/**************************************************************************** * VCGLib o o * * Visual and Computer Graphics Library o o * * _ O _ * * Copyright(C) 2004 \/)\/ * * Visual Computing Lab /\/| * * ISTI - Italian National Research Council | * * \ * * All rights reserved. * * * * 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. * * * * 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 (http://www.gnu.org/licenses/gpl.txt) * * for more details. * * * ****************************************************************************/ /**************************************************************************** History $Log: point_matching.h,v $ ****************************************************************************/ #ifndef _VCG_MATH_POINTMATCHING_H #define _VCG_MATH_POINTMATCHING_H #include #include #include namespace vcg { template class PointMatching { public: typedef Point3 Point3x; typedef Matrix33 Matrix33x; typedef Matrix44 Matrix44x; typedef Quaternion Quaternionx; /* Compute a similarity matching (rigid + uniform scaling) simply create a temporary point set with the correct scaling factor */ static bool ComputeSimilarityMatchMatrix( Matrix44x &res, std::vector &Pfix, // vertici corrispondenti su fix (rossi) std::vector &Pmov) // normali scelti su mov (verdi) { Quaternionx qtmp; Point3x tr; std::vector Pnew(Pmov.size()); ScalarType scalingFactor=0; for(size_t i=0;i<( Pmov.size()-1);++i) { scalingFactor += Distance(Pmov[i],Pmov[i+1])/ Distance(Pfix[i],Pfix[i+1]); qDebug("Scaling Factor is %f",scalingFactor/(i+1)); } scalingFactor/=(Pmov.size()-1); for(size_t i=0;i &Pfix, // vertici corrispondenti su fix (rossi) std::vector &Pmov) // normali scelti su mov (verdi) { Quaternionx qtmp; Point3x tr; return ComputeRigidMatchMatrix(res,Pfix,Pmov,qtmp,tr); } static bool ComputeRigidMatchMatrix(std::vector weights, Matrix44x &res, std::vector &Pfix, // vertici corrispondenti su fix (rossi) std::vector &Pmov) // normali scelti su mov (verdi) { Quaterniond qtmp; Point3d tr; return ComputeRigidMatchMatrix(res,Pfix,Pmov,qtmp,tr); } /* Calcola la matrice di rototraslazione che porta i punti Pmov su Pfix Basata sul paper Besl, McKay A method for registration o f 3d Shapes IEEE TPAMI Vol 14, No 2 1992 Esempio d'uso const int np=1000; std::vector pfix(np),pmov(np); Matrix44x Rot,Trn,RotRes; Rot.Rotate(30,Point3x(1,0,1)); Trn.Translate(0,0,100); Rot=Trn*Rot; for(int i=0;i &Pfix, std::vector &Pmov, std::vector weights, Quaternionx &q, Point3x &tr ) { Matrix33x tmp; Matrix33x ccm; Point3x bfix,bmov; // baricenter of src e trg ccm.WeightedCrossCovariance(weights,Pmov,Pfix,bmov,bfix); Matrix33x cyc; // the cyclic components of the cross covariance matrix. cyc=ccm; tmp=ccm; tmp.Trasp(); cyc-=tmp; Matrix44x QQ; QQ.Zero(); Point3x D(cyc[1][2],cyc[2][0],cyc[0][1]); Matrix33x RM; RM.Zero(); RM[0][0]=-ccm.Trace(); RM[1][1]=-ccm.Trace(); RM[2][2]=-ccm.Trace(); RM+=ccm; ccm.Trasp(); RM+=ccm; QQ[0][0] = ccm.Trace(); QQ[0][1] = D[0]; QQ[0][2] = D[1]; QQ[0][3] = D[2]; QQ[1][0] = D[0]; QQ[2][0] = D[1]; QQ[3][0] = D[2]; int i,j; for(i=0;i<3;i++) for(j=0;j<3;j++) QQ[i+1][j+1]=RM[i][j]; // printf(" Quaternion Matrix\n"); // print(QQ); Point4d d; Matrix44x v; int nrot; QQ.Jacobi(d,v,nrot); // printf("Done %i iterations\n %f %f %f %f\n",nrot,d[0],d[1],d[2],d[3]); // print(v); // Now search the maximum eigenvalue double maxv=0; int maxind=-1; for(i=0;i<4;i++) if(maxv &Pfix, std::vector &Pmov, Quaternionx &q, Point3x &tr) { Matrix33x tmp; Matrix33x ccm; Point3x bfix,bmov; // baricenter of src e trg ccm.CrossCovariance(Pmov,Pfix,bmov,bfix); Matrix33x cyc; // the cyclic components of the cross covariance matrix. cyc=ccm; tmp=ccm; tmp.Transpose(); cyc-=tmp; Matrix44x QQ; QQ.SetZero(); Point3x D(cyc[1][2],cyc[2][0],cyc[0][1]); Matrix33x RM; RM.SetZero(); RM[0][0]=-ccm.Trace(); RM[1][1]=-ccm.Trace(); RM[2][2]=-ccm.Trace(); RM+=ccm; ccm.Transpose(); RM+=ccm; QQ[0][0] = ccm.Trace(); QQ[0][1] = D[0]; QQ[0][2] = D[1]; QQ[0][3] = D[2]; QQ[1][0] = D[0]; QQ[2][0] = D[1]; QQ[3][0] = D[2]; int i,j; for(i=0;i<3;i++) for(j=0;j<3;j++) QQ[i+1][j+1]=RM[i][j]; // printf(" Quaternion Matrix\n"); // print(QQ); Point4d d; Matrix44x v; int nrot; //QQ.Jacobi(d,v,nrot); Jacobi(QQ,d,v,nrot); // printf("Done %i iterations\n %f %f %f %f\n",nrot,d[0],d[1],d[2],d[3]); // print(v); // Now search the maximum eigenvalue double maxv=0; int maxind=-1; for(i=0;i<4;i++) if(maxv &Ps, // vertici corrispondenti su src (rossi) std::vector &Ns, // normali corrispondenti su src (rossi) std::vector &Pt) // vertici scelti su trg (verdi) // vector &Nt) // normali scelti su trg (verdi) { int sz=Ps.size(); assert(0); // Da qui in poi non compila che ha bisogno dei minimiquadrati #if 0 Matrix A(sz,12); Vector b(sz); Vector x(12); //inizializzo il vettore per minimi quadrati // la matrice di trasf che calcolo con LeastSquares cerca avvicinare il piu' // possibile le coppie di punti che trovo ho scelto // Le coppie di punti sono gia' trasformate secondo la matrice quindi come scelta iniziale // per il metodo minimiquadrati scelgo l'identica (e.g. se ho allineato a mano perfettamente e // le due mesh sono perfettamente uguali DEVE restituire l'identica) res.SetIdentity(); int i,j,k; for(i=0; i<=2; ++i) for(j=0; j<=3; ++j) x[i*4+j] = res[i][j]; //costruzione della matrice for(i=0;i & A2, const Point3x & p, const Point3x & n, double d ) { double t1 = p[0]*p[0]; double t2 = n[0]*n[0]; double t4 = t1*n[0]; double t5 = t4*n[1]; double t6 = t4*n[2]; double t7 = p[0]*t2; double t8 = t7*p[1]; double t9 = p[0]*n[0]; double t10 = p[1]*n[1]; double t11 = t9*t10; double t12 = p[1]*n[2]; double t13 = t9*t12; double t14 = t7*p[2]; double t15 = p[2]*n[1]; double t16 = t9*t15; double t17 = p[2]*n[2]; double t18 = t9*t17; double t19 = t9*n[1]; double t20 = t9*n[2]; double t21 = t9*d; double t22 = n[1]*n[1]; double t25 = t1*n[1]*n[2]; double t26 = p[0]*t22; double t27 = t26*p[1]; double t28 = p[0]*n[1]; double t29 = t28*t12; double t30 = t26*p[2]; double t31 = t28*t17; double t32 = t28*n[2]; double t33 = t28*d; double t34 = n[2]*n[2]; double t36 = p[0]*t34; double t41 = p[1]*p[1]; double t43 = t41*n[0]; double t46 = p[1]*t2; double t48 = p[1]*n[0]; double t49 = t48*t15; double t50 = t48*t17; double t51 = t48*n[1]; double t52 = t48*n[2]; double t57 = p[1]*t22; double t59 = t10*t17; double t60 = t10*n[2]; double t63 = p[1]*t34; double t66 = p[2]*p[2]; double t68 = t66*n[0]; double t72 = p[2]*n[0]; double t73 = t72*n[1]; double t74 = t72*n[2]; double t80 = t15*n[2]; A2[0][0] = t1*t2; A2[0][1] = t5; A2[0][2] = t6; A2[0][3] = t8; A2[0][4] = t11; A2[0][5] = t13; A2[0][6] = t14; A2[0][7] = t16; A2[0][8] = t18; A2[0][9] = t7; A2[0][10] = t19; A2[0][11] = t20; A2[0][12] = -t21; A2[1][1] = t1*t22; A2[1][2] = t25; A2[1][3] = t11; A2[1][4] = t27; A2[1][5] = t29; A2[1][6] = t16; A2[1][7] = t30; A2[1][8] = t31; A2[1][9] = t19; A2[1][10] = t26; A2[1][11] = t32; A2[1][12] = -t33; A2[2][2] = t1*t34; A2[2][3] = t13; A2[2][4] = t29; A2[2][5] = t36*p[1]; A2[2][6] = t18; A2[2][7] = t31; A2[2][8] = t36*p[2]; A2[2][9] = t20; A2[2][10] = t32; A2[2][11] = t36; A2[2][12] = -p[0]*n[2]*d; A2[3][3] = t41*t2; A2[3][4] = t43*n[1]; A2[3][5] = t43*n[2]; A2[3][6] = t46*p[2]; A2[3][7] = t49; A2[3][8] = t50; A2[3][9] = t46; A2[3][10] = t51; A2[3][11] = t52; A2[3][12] = -t48*d; A2[4][4] = t41*t22; A2[4][5] = t41*n[1]*n[2]; A2[4][6] = t49; A2[4][7] = t57*p[2]; A2[4][8] = t59; A2[4][9] = t51; A2[4][10] = t57; A2[4][11] = t60; A2[4][12] = -t10*d; A2[5][5] = t41*t34; A2[5][6] = t50; A2[5][7] = t59; A2[5][8] = t63*p[2]; A2[5][9] = t52; A2[5][10] = t60; A2[5][11] = t63; A2[5][12] = -t12*d; A2[6][6] = t66*t2; A2[6][7] = t68*n[1]; A2[6][8] = t68*n[2]; A2[6][9] = p[2]*t2; A2[6][10] = t73; A2[6][11] = t74; A2[6][12] = -t72*d; A2[7][7] = t66*t22; A2[7][8] = t66*n[1]*n[2]; A2[7][9] = t73; A2[7][10] = p[2]*t22; A2[7][11] = t80; A2[7][12] = -t15*d; A2[8][8] = t66*t34; A2[8][9] = t74; A2[8][10] = t80; A2[8][11] = p[2]*t34; A2[8][12] = -t17*d; A2[9][9] = t2; A2[9][10] = n[0]*n[1]; A2[9][11] = n[0]*n[2]; A2[9][12] = -n[0]*d; A2[10][10] = t22; A2[10][11] = n[1]*n[2]; A2[10][12] = -n[1]*d; A2[11][11] = t34; A2[11][12] = -n[2]*d; A2[12][12] = d*d; } // Dati due insiemi di punti e normali corrispondenti calcola la migliore trasformazione // che li fa corrispondere static bool ComputeMatchMatrix2( Matrix44x &res, std::vector &Ps, // vertici corrispondenti su src (rossi) std::vector &Ns, // normali corrispondenti su src (rossi) std::vector &Pt) // vertici scelti su trg (verdi) //vector &Nt) // normali scelti su trg (verdi) { const int N = 13; int i,j,k; Matrixd AT(N,N); Matrixd TT(N,N); // Azzeramento matrice totale (solo tri-superiore) for(i=0;i q; double error; affine_ls2(AT,q,error); //printf("error: %g \n",error); res[0][0] = q[0]; res[0][1] = q[1]; res[0][2] = q[2]; res[0][3] = 0; res[1][0] = q[3]; res[1][1] = q[4]; res[1][2] = q[5]; res[1][3] = 0; res[2][0] = q[6]; res[2][1] = q[7]; res[2][2] = q[8]; res[2][3] = 0; res[3][0] = q[9]; res[3][1] = q[10]; res[3][2] = q[11]; res[3][3] = q[12]; return true; } */ }; } // end namespace #endif qutemol/vcg/vcg/math/matrix.h0000444000175000017500000004743410504552536014607 0ustar mbamba/**************************************************************************** * VCGLib o o * * Visual and Computer Graphics Library o o * * _ O _ * * Copyright(C) 2004 \/)\/ * * Visual Computing Lab /\/| * * ISTI - Italian National Research Council | * * \ * * All rights reserved. * * * * 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. * * * * 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 (http://www.gnu.org/licenses/gpl.txt) * * for more details. * * * ****************************************************************************/ /*************************************************************************** $Log: matrix.h,v $ Revision 1.10 2006/09/21 18:09:34 fiorin Added SetIdentity method Revision 1.9 2006/09/11 16:11:39 marfr960 Added const to declarations of the overloaded (operators *). Otherwise the * operator would always attempt to convert any type of data passed as an argument to Point3 Revision 1.8 2006/08/23 15:24:45 marfr960 Copy constructor : faster memcpy instead of slow 'for' cycle empty constructor Revision 1.7 2006/04/29 10:26:04 fiorin Added some utility methods (swapping of columns and rows, matrix-vector multiplication) Revision 1.6 2006/04/11 08:09:35 zifnab1974 changes necessary for gcc 3.4.5 on linux 64bit. Please take note of case-sensitivity of filenames Revision 1.5 2005/12/12 11:25:00 ganovelli added diagonal matrix, outer produce and namespace ***************************************************************************/ #ifndef MATRIX_VCGLIB #define MATRIX_VCGLIB #include #include #include #include #include #include #include namespace vcg{ namespace ndim{ /** \addtogroup math */ /* @{ */ /*! * This class represent a diagonal mm matrix. */ class MatrixDiagBase{public: virtual const int & Dimension()const =0; virtual const float operator[](const int & i)const = 0; }; template class MatrixDiag: public PointBase, public MatrixDiagBase{ public: const int & Dimension() const {return N;} MatrixDiag(const PointBase&p):PointBase(p){} }; /*! * This class represent a generic mn matrix. The class is templated over the scalar type field. * @param TYPE (Templete Parameter) Specifies the ScalarType field. */ template class Matrix { public: typedef TYPE ScalarType; /*! * Default constructor * All the elements are initialized to zero. * \param m the number of matrix rows * \param n the number of matrix columns */ Matrix(unsigned int m, unsigned int n) { _rows = m; _columns = n; _data = new ScalarType[m*n]; memset(_data, 0, m*n*sizeof(ScalarType)); }; /*! * Constructor * The matrix elements are initialized with the values of the elements in \i values. * \param m the number of matrix rows * \param n the number of matrix columns * \param values the values of the matrix elements */ Matrix(unsigned int m, unsigned int n, TYPE *values) { _rows = m; _columns = n; unsigned int dim = m*n; _data = new ScalarType[dim]; memcpy(_data, values, dim*sizeof(ScalarType)); //unsigned int i; //for (i=0; i<_rows*_columns; i++) // _data[i] = values[i]; }; /*! * Empty constructor * Just create the object */ Matrix() { _rows = 0; _columns = 0; _data = NULL; }; /*! * Copy constructor * The matrix elements are initialized with the value of the corresponding element in \i m * \param m the matrix to be copied */ Matrix(const Matrix &m) { _rows = m._rows; _columns = m._columns; _data = new ScalarType[_rows*_columns]; unsigned int dim = _rows * _columns; memcpy(_data, m._data, dim * sizeof(ScalarType)); // for (unsigned int i=0; i<_rows*_columns; i++) // _data[i] = m._data[i]; }; /*! * Default destructor */ ~Matrix() { delete []_data; }; /*! * Number of columns */ inline unsigned int ColumnsNumber() const { return _columns; }; /*! * Number of rows */ inline unsigned int RowsNumber() const { return _rows; }; /*! * Equality operator. * \param m * \return true iff the matrices have same size and its elements have same values. */ bool operator==(const Matrix &m) const { if (_rows==m._rows && _columns==m._columns) { bool result = true; for (unsigned int i=0; i<_rows*_columns && result; i++) result = (_data[i]==m._data[i]); return result; } return false; }; /*! * Inequality operator * \param m * \return true iff the matrices have different size or if their elements have different values. */ bool operator!=(const Matrix &m) const { if (_rows==m._rows && _columns==m._columns) { bool result = false; for (unsigned int i=0; i<_rows*_columns && !result; i++) result = (_data[i]!=m._data[i]); return result; } return true; }; /*! * Return the element stored in the i-th rows at the j-th column * \param i the row index * \param j the column index * \return the element */ inline TYPE ElementAt(unsigned int i, unsigned int j) { assert(i>=0 && i<_rows); assert(j>=0 && j<_columns); return _data[i*_columns+j]; }; /*! * Calculate and return the matrix determinant (Laplace) * \return the matrix determinant */ TYPE Determinant() const { assert(_rows == _columns); switch (_rows) { case 2: { return _data[0]*_data[3]-_data[1]*_data[2]; break; }; case 3: { return _data[0]*(_data[4]*_data[8]-_data[5]*_data[7]) - _data[1]*(_data[3]*_data[8]-_data[5]*_data[6]) + _data[2]*(_data[3]*_data[7]-_data[4]*_data[6]) ; break; }; default: { // da migliorare: si puo' cercare la riga/colonna con maggior numero di zeri ScalarType det = 0; for (unsigned int j=0; j<_columns; j++) if (_data[j]!=0) det += _data[j]*this->Cofactor(0, j); return det; } }; }; /*! * Return the cofactor Ai,j of the ai,j element * \return ... */ TYPE Cofactor(unsigned int i, unsigned int j) const { assert(_rows == _columns); assert(_rows>2); TYPE *values = new TYPE[(_rows-1)*(_columns-1)]; unsigned int u, v, p, q, s, t; for (u=0, p=0, s=0, t=0; u<_rows; u++, t+=_rows) { if (i==u) continue; for (v=0, q=0; v<_columns; v++) { if (j==v) continue; values[s+q] = _data[t+v]; q++; } p++; s+=(_rows-1); } Matrix temp(_rows-1, _columns-1, values); return (pow(-1, i+j)*temp.Determinant()); }; /*! * Subscript operator: * \param i the index of the row * \return a reference to the i-th matrix row */ inline TYPE* operator[](const unsigned int i) { assert(i>=0 && i<_rows); return _data + i*_columns; }; /*! * Const subscript operator * \param i the index of the row * \return a reference to the i-th matrix row */ inline const TYPE* operator[](const unsigned int i) const { assert(i>=0 && i<_rows); return _data + i*_columns; }; /*! * Get the j-th column on the matrix. * \param j the column index. * \return the reference to the column elements. This pointer must be deallocated by the caller. */ TYPE* GetColumn(const unsigned int j) { assert(j>=0 && j<_columns); ScalarType *v = new ScalarType[_columns]; unsigned int i, p; for (i=0, p=j; i<_rows; i++, p+=_columns) v[i] = _data[p]; return v; }; /*! * Get the i-th row on the matrix. * \param i the column index. * \return the reference to the row elements. This pointer must be deallocated by the caller. */ TYPE* GetRow(const unsigned int i) { assert(i>=0 && i<_rows); ScalarType *v = new ScalarType[_rows]; unsigned int j, p; for (j=0, p=i*_columns; j<_columns; j++, p++) v[j] = _data[p]; return v; }; /*! * Swaps the values of the elements between the i-th and the j-th column. * \param i the index of the first column * \param j the index of the second column */ void SwapColumns(const unsigned int i, const unsigned int j) { assert(0<=i && i<_columns); assert(0<=j && j<_columns); if (i==j) return; unsigned int r, e0, e1; for (r=0, e0=i, e1=j; r<_rows; r++, e0+=_columns, e1+=_columns) std::swap(_data[e0], _data[e1]); }; /*! * Swaps the values of the elements between the i-th and the j-th row. * \param i the index of the first row * \param j the index of the second row */ void SwapRows(const unsigned int i, const unsigned int j) { assert(0<=i && i<_rows); assert(0<=j && j<_rows); if (i==j) return; unsigned int r, e0, e1; for (r=0, e0=i*_columns, e1=j*_columns; r<_columns; r++, e0++, e1++) std::swap(_data[e0], _data[e1]); }; /*! * Assignment operator * \param m ... */ Matrix& operator=(const Matrix &m) { if (this != &m) { assert(_rows == m._rows); assert(_columns == m._columns); for (unsigned int i=0; i<_rows*_columns; i++) _data[i] = m._data[i]; } return *this; }; /*! * Adds a matrix m to this matrix. * \param m reference to matrix to add to this * \return the matrix sum. */ Matrix& operator+=(const Matrix &m) { assert(_rows == m._rows); assert(_columns == m._columns); for (unsigned int i=0; i<_rows*_columns; i++) _data[i] += m._data[i]; return *this; }; /*! * Subtracts a matrix m to this matrix. * \param m reference to matrix to subtract * \return the matrix difference. */ Matrix& operator-=(const Matrix &m) { assert(_rows == m._rows); assert(_columns == m._columns); for (unsigned int i=0; i<_rows*_columns; i++) _data[i] -= m._data[i]; return *this; }; /*! * (Modifier) Add to each element of this matrix the scalar constant k. * \param k the scalar constant * \return the modified matrix */ Matrix& operator+=(const TYPE k) { for (unsigned int i=0; i<_rows*_columns; i++) _data[i] += k; return *this; }; /*! * (Modifier) Subtract from each element of this matrix the scalar constant k. * \param k the scalar constant * \return the modified matrix */ Matrix& operator-=(const TYPE k) { for (unsigned int i=0; i<_rows*_columns; i++) _data[i] -= k; return *this; }; /*! * (Modifier) Multiplies each element of this matrix by the scalar constant k. * \param k the scalar constant * \return the modified matrix */ Matrix& operator*=(const TYPE k) { for (unsigned int i=0; i<_rows*_columns; i++) _data[i] *= k; return *this; }; /*! * (Modifier) Divides each element of this matrix by the scalar constant k. * \param k the scalar constant * \return the modified matrix */ Matrix& operator/=(const TYPE k) { assert(k!=0); for (unsigned int i=0; i<_rows*_columns; i++) _data[i] /= k; return *this; }; /*! * Matrix multiplication: calculates the cross product. * \param m reference to the matrix to multiply by * \return the matrix product */ Matrix operator*(const Matrix &m) const { assert(_columns == m._rows); Matrix result(_rows, m._columns); unsigned int i, j, k, p, q, r; for (i=0, p=0, r=0; i void DotProduct(PointBase &m,PointBase &result) { unsigned int i, j, p, r; for (i=0, p=0, r=0; i operator*(const MatrixDiagBase &m) const { assert(_columns == _rows); assert(_columns == m.Dimension()); int i,j; Matrix result(_rows, _columns); for (i=0; i void OuterProduct(const PointBase a, const PointBase< M,TYPE> b) { assert(N == _rows); assert(M == _columns); Matrix result(_rows,_columns); unsigned int i, j; for (i=0; i operator*(Point3 &p) const { assert(_columns==3 && _rows==3); vcg::Point3 result; result[0] = _data[0]*p[0]+_data[1]*p[1]+_data[2]*p[2]; result[1] = _data[3]*p[0]+_data[4]*p[1]+_data[5]*p[2]; result[2] = _data[6]*p[0]+_data[7]*p[1]+_data[8]*p[2]; return result; }; /*! * Scalar sum. * \param k * \return the resultant matrix */ Matrix operator+(const TYPE k) { Matrix result(_rows, _columns); for (unsigned int i=0; i<_rows*_columns; i++) result._data[i] = _data[i]+k; return result; }; /*! * Scalar difference. * \param k * \return the resultant matrix */ Matrix operator-(const TYPE k) { Matrix result(_rows, _columns); for (unsigned int i=0; i<_rows*_columns; i++) result._data[i] = _data[i]-k; return result; }; /*! * Negate all matrix elements * \return the modified matrix */ Matrix operator-() const { Matrix result(_rows, _columns, _data); for (unsigned int i=0; i<_columns*_rows; i++) result._data[i] = -1*_data[i]; return result; }; /*! * Scalar multiplication. * \param k value to multiply every member by * \return the resultant matrix */ Matrix operator*(const TYPE k) const { Matrix result(_rows, _columns); for (unsigned int i=0; i<_rows*_columns; i++) result._data[i] = _data[i]*k; return result; }; /*! * Scalar division. * \param k value to divide every member by * \return the resultant matrix */ Matrix operator/(const TYPE k) { Matrix result(_rows, _columns); for (unsigned int i=0; i<_rows*_columns; i++) result._data[i] = _data[i]/k; return result; }; /*! * Set all the matrix elements to zero. */ void SetZero() { for (unsigned int i=0; i<_rows*_columns; i++) _data[i] = ScalarType(0.0); }; /*! * Set the matrix to identity. */ void SetIdentity() { assert(_rows==_columns); for (unsigned int i=0; i<_rows; i++) for (unsigned int j=0; j<_columns; j++) _data[i] = (i==j) ? ScalarType(1.0) : ScalarType(0.0f); }; /*! * Set the values of j-th column to v[j] * \param j the column index * \param v ... */ void SetColumn(const unsigned int j, TYPE* v) { assert(j>=0 && j<_columns); unsigned int i, p; for (i=0, p=j; i<_rows; i++, p+=_columns) _data[p] = v[i]; }; /*! * Set the elements of the i-th row to v[j] * \param i the row index * \param v ... */ void SetRow(const unsigned int i, TYPE* v) { assert(i>=0 && i<_rows); unsigned int j, p; for (j=0, p=i*_rows; j<_columns; j++, p++) _data[p] = v[j]; }; /*! * Set the diagonal elements vi,i to v[i] * \param v */ void SetDiagonal(TYPE *v) { assert(_rows == _columns); for (unsigned int i=0, p=0; i<_rows; i++, p+=_rows) _data[p+i] = v[i]; }; /*! * Resize the current matrix. * \param m the number of matrix rows. * \param n the number of matrix columns. */ void Resize(const unsigned int m, const unsigned int n) { assert(m>=2); assert(n>=2); _rows = m; _columns = n; delete []_data; _data = new ScalarType[m*n]; for (unsigned int i=0; i MatrixMNd; typedef vcg::ndim::Matrix MatrixMNf; /*! @} */ template void Invert(MatrixType & m){ typedef typename MatrixType::ScalarType X; X *diag; diag = new X [m.ColumnsNumber()]; MatrixType res(m.RowsNumber(),m.ColumnsNumber()); vcg::SingularValueDecomposition (m,&diag[0],res,50 ); m.Transpose(); // prodotto per la diagonale unsigned int i,j; for (i=0; i::Axis changed Row3 to GetRow3 . row3 was the old method name of Matrix44 Revision 1.15 2005/12/01 01:03:37 cignoni Removed excess ';' from end of template functions, for gcc compiling Revision 1.14 2005/11/23 14:18:35 ganovelli added access to similarity (just for symmetry with Camera() ) Revision 1.13 2005/11/23 11:58:52 ganovelli Empty constructor added, untemplated class Shotf and Shotd added usage: Shotf myShot; corrected member access rights Revision 1.12 2005/07/11 13:12:35 cignoni small gcc-related compiling issues (typenames,ending cr, initialization order) Revision 1.11 2005/01/22 11:20:20 ponchio <...Point3.h> -> <...point3.h> Revision 1.10 2005/01/05 13:26:15 ganovelli corretto cambiamento di sistema di rif. Revision 1.9 2004/12/15 18:45:50 tommyfranken *** empty log message *** Revision 1.4 2004/10/07 14:41:31 fasano Little fix on ViewPoint() method Revision 1.3 2004/10/07 14:24:53 ganovelli added LookAt,LookToward Revision 1.2 2004/10/05 19:04:25 ganovelli version 5-10-2004 in progress Revision 1.1 2004/09/15 22:58:05 ganovelli re-creation Revision 1.2 2004/09/06 21:41:30 ganovelli *** empty log message *** Revision 1.1 2004/09/03 13:01:51 ganovelli creation ****************************************************************************/ #ifndef __VCGLIB_SHOT #define __VCGLIB_SHOT #include #include #include #include namespace vcg{ template class Shot { public: typedef Camera CameraType; typedef S ScalarType; Camera Intrinsics; // the camera that made the shot Similarity > Extrinsics; // the position and orientation of the camera Shot(Camera c) { Intrinsics = c; Extrinsics.SetIdentity(); } Shot() { Extrinsics.SetIdentity(); } /// GET the i-th axis of the coordinate system of the camera vcg::Point3 Axis(const int & i)const; /// GET the viewpoint const vcg::Point3 GetViewPoint()const; /// SET the viewpoint void SetViewPoint(const vcg::Point3 & viewpoint); /// look at (dir+up) void LookAt(const vcg::Point3 & z_dir,const vcg::Point3 & up); /// look at (opengl-like) void LookAt(const S & eye_x,const S & eye_y,const S & eye_z, const S & at_x,const S & at_y,const S & at_z, const S & up_x,const S & up_y,const S & up_z); /// look towards void LookTowards(const vcg::Point3 & z_dir,const vcg::Point3 & up); /// convert a 3d point from world to camera coordinates vcg::Point3 ConvertWorldToCameraCoordinates(const vcg::Point3 & p) const; /// convert a 3d point from camera to world coordinates vcg::Point3 ConvertCameraToWorldCoordinates(const vcg::Point3 & p) const; /// project a 3d point from world coordinates to 2d camera viewport (pixel) vcg::Point2 Project(const vcg::Point3 & p) const; /// inverse projection from 2d camera viewport (pixel) + Zdepth to 3d world coordinates vcg::Point3 UnProject(const vcg::Point2 & p, const S & d) const; /// returns distance of point p from camera plane (z depth), used for unprojection S Depth(const vcg::Point3 & p)const; // accessors public: vcg::Similarity > * GetExtrinsics(){return &Extrinsics;} void SetExtrinsics(vcg::Similarity > &m44) { Extrinsics.tra = m44.tra; Extrinsics.rot.FromMatrix(m44.rot); Extrinsics.sca = m44.sca; } }; // end class definition //--- /// GET the viewpoint template const vcg::Point3 Shot::GetViewPoint() const { return -Extrinsics.tra; } /// SET the viewpoint template void Shot::SetViewPoint(const vcg::Point3 & viewpoint) { Extrinsics.tra = -viewpoint; } //--- /// GET the i-th axis of the coordinate system of the camera template vcg::Point3 Shot::Axis(const int & i) const { vcg::Matrix44 m; Extrinsics.rot.ToMatrix(m); vcg::Point3 aa = m.GetCol3(i); return aa; } /// look at (dir+up) template void Shot::LookAt(const vcg::Point3 & z_dir,const vcg::Point3 & up) { LookTowards(z_dir-GetViewPoint(),up); } /// look at (opengl-like) template void Shot::LookAt(const S & eye_x, const S & eye_y, const S & eye_z, const S & at_x, const S & at_y, const S & at_z, const S & up_x,const S & up_y,const S & up_z) { SetViewPoint(Point3(eye_x,eye_y,eye_z)); LookAt(Point3(at_x,at_y,at_z),Point3(up_x,up_y,up_z)); } /// look towards template void Shot::LookTowards(const vcg::Point3 & z_dir,const vcg::Point3 & up) { vcg::Point3 x_dir = up ^-z_dir; vcg::Point3 y_dir = -z_dir ^x_dir; Matrix44 m; m.SetIdentity(); *(vcg::Point3 *)&m[0][0] = x_dir/x_dir.Norm(); *(vcg::Point3 *)&m[1][0] = y_dir/y_dir.Norm(); *(vcg::Point3 *)&m[2][0] = -z_dir/z_dir.Norm(); Extrinsics.rot.FromMatrix(m); } //--- Space transformation methods /// convert a 3d point from world to camera coordinates template vcg::Point3 Shot::ConvertWorldToCameraCoordinates(const vcg::Point3 & p) const { Matrix44 rotM; Extrinsics.rot.ToMatrix(rotM); Invert(rotM); vcg::Point3 cp = rotM * (p + Extrinsics.tra); cp[2]=-cp[2]; // note: camera reference system is right handed return cp; } /// convert a 3d point from camera to world coordinates template vcg::Point3 Shot::ConvertCameraToWorldCoordinates(const vcg::Point3 & p) const { Matrix44 rotM; vcg::Point3 cp = p; cp[2]=-cp[2]; // note: World reference system is left handed Extrinsics.rot.ToMatrix(rotM); cp = rotM * cp-Extrinsics.tra; return cp; } /// project a 3d point from world coordinates to 2d camera viewport (pixel) template vcg::Point2 Shot::Project(const vcg::Point3 & p) const { Point3 cp = ConvertWorldToCameraCoordinates(p); Point2 pp = Intrinsics.Project(cp); Point2 vp = Intrinsics.LocalToViewportPx(pp); return vp; } /// inverse projection from 2d camera viewport (pixel) + Zdepth to 3d world coordinates template vcg::Point3 Shot::UnProject(const vcg::Point2 & p, const S & d) const { Point2 lp = Intrinsics.ViewportPxToLocal(p); Point3 cp = Intrinsics.UnProject(lp,d); Point3 wp = ConvertCameraToWorldCoordinates(cp); return wp; } /// returns distance of point p from camera plane (z depth), used for unprojection template S Shot::Depth(const vcg::Point3 & p)const { return ConvertWorldToCameraCoordinates(p).Z(); } //-------------------------------- //--- utility definitions class Shotf: public Shot{}; class Shotd: public Shot{}; //----------------------- } // end name space #endif qutemol/vcg/vcg/math/linear.h0000444000175000017500000000622110416662077014546 0ustar mbamba/**************************************************************************** * VCGLib o o * * Visual and Computer Graphics Library o o * * _ O _ * * Copyright(C) 2004 \/)\/ * * Visual Computing Lab /\/| * * ISTI - Italian National Research Council | * * \ * * All rights reserved. * * * * 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. * * * * 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 (http://www.gnu.org/licenses/gpl.txt) * * for more details. * * * ****************************************************************************/ /**************************************************************************** History $Log: linear.h,v $ Revision 1.3 2006/04/11 08:09:35 zifnab1974 changes necessary for gcc 3.4.5 on linux 64bit. Please take note of case-sensitivity of filenames Revision 1.2 2005/12/12 11:24:09 ganovelli missing type added Revision 1.1 2004/03/16 03:08:17 tarini first version ****************************************************************************/ #ifndef __VCGLIB_LINEAR #define __VCGLIB_LINEAR namespace vcg { /*@{*/ /** This class represents the common interface for any linear objects. It consists (the declaration of) a set of functions and types that each such object mush have. Linear have the Zero element (neutral element for sums) moltiplication (for a scalar), and two linear elements of a given type can be summed. In this way it is possible to interpolate between two different linear entities. For example: LinearType a,b,c,d,e,f; ... d = a * 0.1 + b * 0.9; e = a + (b - a) * 0.9; */ template class Linear{ public: typedef T ScalarType; inline void Zero(); T operator + ( T const & p) const; T operator - ( T const & p) const; T operator * ( const ScalarType ); T operator / ( const ScalarType ) const; T & operator += ( T const & ); T & operator -= ( T const & ); T & operator *= ( const ScalarType ); T & operator /= ( const ScalarType ); T operator - () const; }; }; #endif qutemol/vcg/vcg/math/histogram.h0000444000175000017500000002423410763745523015300 0ustar mbamba/**************************************************************************** * VCGLib o o * * Visual and Computer Graphics Library o o * * _ O _ * * Copyright(C) 2004 \/)\/ * * Visual Computing Lab /\/| * * ISTI - Italian National Research Council | * * \ * * All rights reserved. * * * * 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. * * * * 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 (http://www.gnu.org/licenses/gpl.txt) * * for more details. * * * ****************************************************************************/ /**************************************************************************** History $Log: histogram.h,v $ Revision 1.19 2008/03/06 10:45:39 cignoni added missing include limits Revision 1.18 2008/03/05 11:21:49 cignoni Heavily refactored the whole structure. Some interfaces have been changed. Be careful. Revision 1.17 2008/02/29 12:15:06 cignoni added maxcount Revision 1.16 2006/11/28 21:29:21 cignoni Re added typedef Histogramf and Histogramd Revision 1.15 2006/11/28 09:47:42 corsini add documentation fix typo Revision 1.14 2006/05/04 00:09:53 cignoni minor change: removed unused vars Revision 1.13 2006/03/29 09:25:47 zifnab1974 extra includes necessary for compilation of meshlab on AMD 64 with gcc 3.4.5 Revision 1.12 2006/01/12 13:12:54 callieri in FileWrite, added file closing after finishing Revision 1.11 2005/09/16 11:51:23 cignoni removed signed/unsigned warning Revision 1.10 2005/06/17 00:54:55 cignoni Corrected small bug in SetRange (H was resized to n instead of n+1) Revision 1.9 2005/06/14 14:27:00 ganovelli added include of algorithm Revision 1.8 2005/06/10 14:59:39 cignoni Added include assert.h and cast to ScalarType for a pow in SetRange() function. Revision 1.7 2005/06/09 14:19:55 cignoni Added typedef Histogramf and Histogramd Revision 1.6 2005/06/07 09:37:33 ponchio Added fabs() to variance, which can sometime be negative in case of rounding errors (and sqrt chokes on it). Revision 1.5 2005/06/07 07:44:08 cignoni Added Percentile and removed small bug in Add Revision 1.4 2005/04/04 10:48:35 cignoni Added missing functions Avg, rms etc, now fully (almost) functional Revision 1.3 2005/03/14 09:23:40 cignoni Added missing include Revision 1.2 2004/08/25 15:15:26 ganovelli minor changes to comply gcc compiler (typename's and stuff) Revision 1.1 2004/06/24 09:12:28 cignoni Initial Release ****************************************************************************/ #ifndef __VCG_HISTOGRAM #define __VCG_HISTOGRAM #include #include #include #include #include namespace vcg { /** * Histogram. * * This class implements a single-value histogram. */ template class Histogram { // public data members private: std::vector H; //! Counters for bins. std::vector R; //! Range for bins. ScalarType minv; //! Minimum value. ScalarType maxv; //! Maximum value. int n; //! Number of vaild intervals stored between minv and maxv. /// incrementally updated values int cnt; //! Number of accumulated samples. ScalarType avg; //! Average. ScalarType rms; //! Root mean square. /** * Returns the index of the bin which contains a given value. */ int BinIndex(ScalarType val) ; // public methods public: /** * Set the histogram values. * * This method is used to correctly initialize the bins of the histogram. * n is the number of valid intervals between minv and maxv. * for a more robust working, the Histogram class stores also the two out of range intervals (-inf, minv] and [maxv, +inf) * Each bin is left closed (eg it contains the value * The \a gamma parameter is applied to modify the distribution of the ranges of the bins. Default uniform distibution. * */ void SetRange(ScalarType _minv, ScalarType _maxv, int _n,ScalarType gamma=1.0 ); ScalarType MinV() {return minv;}; //! Minimum value. ScalarType MaxV() {return maxv;}; //! Minimum value. /** * Add a new value to the histogram. * * The statistics related to the histogram data (average, RMS, etc.) are * also updated. */ void Add(ScalarType v); int MaxCount() const; int BinCount(ScalarType v); int BinCount(ScalarType v, ScalarType width); int RangeCount(ScalarType rangeMin, ScalarType rangeMax); ScalarType BinWidth(ScalarType v); /** * Returns the value corresponding to a given percentile of the data. * * The percentile range between 0 and 1. */ ScalarType Percentile(ScalarType frac) const; //! Returns the average of the data. ScalarType Avg(){ return avg/cnt;} //! Returns the Root Mean Square of the data. ScalarType RMS(){ return sqrt(rms/double(cnt));} //! Returns the variance of the data. ScalarType Variance(){ return fabs(rms/cnt-Avg()*Avg());} //! Returns the standard deviation of the data. ScalarType StandardDeviation(){ return sqrt(Variance());} //! Dump the histogram to a file. void FileWrite(const std::string &filename); //! Reset histogram data. void Clear(); }; template void Histogram::Clear() { H.clear(); R.clear(); cnt=0; avg=0; rms=0; n=0; minv=0; maxv=1; } /* Note that the histogram holds valid bins plus two semi-infinite bins. R[0] = -inf R[1] = minv R[n+1] = maxv R[n+2] = +inf Eg. SetRange(0, 10, 5) asks for 5 intervals covering the 0..10 range H[0] H[1] H[2] H[3] H[4] H[5] H[6] -inf 0 2 4 6 8 10 +inf R[0] R[1] R[2] R[3] R[4] R[5] R[6] R[7] */ template void Histogram::SetRange(ScalarType _minv, ScalarType _maxv, int _n, ScalarType gamma) { // reset data Clear(); minv=_minv;maxv=_maxv;n=_n; H.resize(n+2); fill(H.begin(),H.end(),0); R.resize(n+3); R[0] = - std::numeric_limits< ScalarType >::max(); R[n+2] = std::numeric_limits< ScalarType >::max(); double delta=(maxv-minv); if(gamma==1) { for(int i=0; i<=n; ++i) R[i+1] = minv + delta*ScalarType(i)/n; } else { for(int i=0; i<=n; ++i) R[i+1] = minv + delta*pow(ScalarType(i)/n,gamma); } } template int Histogram::BinIndex(ScalarType val) { // lower_bound returns the furthermost iterator i in [first, last) such that, for every iterator j in [first, i), *j < value. // E.g. An iterator pointing to the first element "not less than" val, or end() if every element is less than val. typename std::vector::iterator it = lower_bound(R.begin(),R.end(),val); assert(it!=R.begin()); assert(it!=R.end()); assert((*it)>=val); int pos = it-R.begin(); assert(pos >=1); pos -= 1; assert (R[pos] < val); assert ( val <= R[pos+1] ); return pos; } /* H[0] H[1] H[2] H[3] H[4] H[5] H[6] -inf 0 2 4 6 8 10 +inf R[0] R[1] R[2] R[3] R[4] R[5] R[6] R[7] asking for 3.14 lower bound will return an iterator pointing to R[3]==4; and will increase H[2] asking for 4 lower bound will return an iterator pointing to R[3]==4; and will increase H[2] */ template void Histogram::Add(ScalarType v) { int pos=BinIndex(v); if(pos>=0 && pos<=n) { ++H[pos]; ++cnt; avg+=v; rms += v*v; } } template int Histogram::BinCount(ScalarType v) { return H[BinIndex(v)]; } template int Histogram::BinCount(ScalarType v, ScalarType width) { return RangeCount(v-width/2.0,v+width/2.0); } template int Histogram::RangeCount(ScalarType rangeMin, ScalarType rangeMax) { int firstBin=BinIndex(rangeMin); int lastBin=BinIndex (rangeMax); int sum=0; for(int i=firstBin; i<=lastBin;++i) sum+=H[i]; return sum; } template ScalarType Histogram::BinWidth(ScalarType v) { int pos=BinIndex(v); return R[pos+1]-R[pos]; } template void Histogram::FileWrite(const std::string &filename) { FILE *fp; fp=fopen(filename.c_str(),"w"); for(unsigned int i=0; i int Histogram::MaxCount() const { return *(std::max_element(H.begin(),H.end())); } // Return the scalar value such that there are samples <= . // E.g. Percentile(0.0) will return R[1] e.g. min value // E.g. Percentile(1.0) will return R[n+1] e.g max value template ScalarType Histogram::Percentile(ScalarType frac) const { if(H.size()==0 && R.size()==0) return 0; // check percentile range assert(frac >= 0 && frac <= 1); ScalarType sum=0,partsum=0; int i; // useless summation just to be sure for(i=0;i=sum) break; } assert(i Histogramd ; typedef Histogram Histogramf ; } // end namespace (vcg) #endif /* __VCG_HISTOGRAM */ qutemol/vcg/vcg/math/quaternion.h0000444000175000017500000003124010757604357015465 0ustar mbamba/**************************************************************************** * VCGLib o o * * Visual and Computer Graphics Library o o * * _ O _ * * Copyright(C) 2004 \/)\/ * * Visual Computing Lab /\/| * * ISTI - Italian National Research Council | * * \ * * All rights reserved. * * * * 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. * * * * 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 (http://www.gnu.org/licenses/gpl.txt) * * for more details. * * * ****************************************************************************/ /**************************************************************************** History $Log: quaternion.h,v $ Revision 1.19 2008/02/22 17:39:59 ponchio ToMatrix returned the inverse matrix. OUCH. This affects trackball and shot.h Added a const also. Revision 1.18 2007/07/03 16:07:09 corsini add DCM to Euler Angles method (to implement) Revision 1.17 2007/02/06 12:24:07 tarini added a missing "Quaternion::" in "FromEulerAngles" Revision 1.16 2007/02/05 13:55:21 corsini add euler angle to quaternion conversion Revision 1.15 2006/06/22 08:00:26 ganovelli toMatrix with matrix33 added Revision 1.14 2005/04/17 21:57:03 ganovelli tolto il const a interpolate Revision 1.13 2005/04/15 09:19:50 ponchio Typo: Point3 -> Point4 Revision 1.12 2005/04/14 17:22:34 ponchio *** empty log message *** Revision 1.11 2005/04/14 11:35:09 ponchio *** empty log message *** Revision 1.10 2004/12/15 18:45:50 tommyfranken *** empty log message *** Revision 1.9 2004/10/22 14:35:42 ponchio m.element(x, y) -> m[x][y] Revision 1.8 2004/10/07 13:54:03 ganovelli added SetIdentity Revision 1.7 2004/04/07 10:48:37 cignoni updated access to matrix44 elements through V() instead simple [] Revision 1.6 2004/03/25 14:57:49 ponchio Microerror. ($LOG$ -> $Log: quaternion.h,v $ Microerror. ($LOG$ -> Revision 1.19 2008/02/22 17:39:59 ponchio Microerror. ($LOG$ -> ToMatrix returned the inverse matrix. OUCH. Microerror. ($LOG$ -> This affects trackball and shot.h Microerror. ($LOG$ -> Added a const also. Microerror. ($LOG$ -> Microerror. ($LOG$ -> Revision 1.18 2007/07/03 16:07:09 corsini Microerror. ($LOG$ -> add DCM to Euler Angles method (to implement) Microerror. ($LOG$ -> Microerror. ($LOG$ -> Revision 1.17 2007/02/06 12:24:07 tarini Microerror. ($LOG$ -> added a missing "Quaternion::" in "FromEulerAngles" Microerror. ($LOG$ -> Microerror. ($LOG$ -> Revision 1.16 2007/02/05 13:55:21 corsini Microerror. ($LOG$ -> add euler angle to quaternion conversion Microerror. ($LOG$ -> Microerror. ($LOG$ -> Revision 1.15 2006/06/22 08:00:26 ganovelli Microerror. ($LOG$ -> toMatrix with matrix33 added Microerror. ($LOG$ -> Microerror. ($LOG$ -> Revision 1.14 2005/04/17 21:57:03 ganovelli Microerror. ($LOG$ -> tolto il const a interpolate Microerror. ($LOG$ -> Microerror. ($LOG$ -> Revision 1.13 2005/04/15 09:19:50 ponchio Microerror. ($LOG$ -> Typo: Point3 -> Point4 Microerror. ($LOG$ -> Microerror. ($LOG$ -> Revision 1.12 2005/04/14 17:22:34 ponchio Microerror. ($LOG$ -> *** empty log message *** Microerror. ($LOG$ -> Microerror. ($LOG$ -> Revision 1.11 2005/04/14 11:35:09 ponchio Microerror. ($LOG$ -> *** empty log message *** Microerror. ($LOG$ -> Microerror. ($LOG$ -> Revision 1.10 2004/12/15 18:45:50 tommyfranken Microerror. ($LOG$ -> *** empty log message *** Microerror. ($LOG$ -> Microerror. ($LOG$ -> Revision 1.9 2004/10/22 14:35:42 ponchio Microerror. ($LOG$ -> m.element(x, y) -> m[x][y] Microerror. ($LOG$ -> Microerror. ($LOG$ -> Revision 1.8 2004/10/07 13:54:03 ganovelli Microerror. ($LOG$ -> added SetIdentity Microerror. ($LOG$ -> Microerror. ($LOG$ -> Revision 1.7 2004/04/07 10:48:37 cignoni Microerror. ($LOG$ -> updated access to matrix44 elements through V() instead simple [] Microerror. ($LOG$ -> ****************************************************************************/ #ifndef QUATERNION_H #define QUATERNION_H #include #include #include #include #include namespace vcg { /** Classe quaternion. A quaternion is a point in the unit sphere in four dimension: all rotations in three-dimensional space can be represented by a quaternion. */ template class Quaternion: public Point4 { public: Quaternion() {} Quaternion(const S v0, const S v1, const S v2, const S v3): Point4(v0,v1,v2,v3){} Quaternion(const Point4 p) : Point4(p) {} Quaternion(const S phi, const Point3 &a); Quaternion operator*(const S &s) const; //Quaternion &operator*=(S d); Quaternion operator*(const Quaternion &q) const; Quaternion &operator*=(const Quaternion &q); void Invert(); void SetIdentity(); void FromAxis(const S phi, const Point3 &a); void ToAxis(S &phi, Point3 &a ) const; void FromMatrix(const Matrix44 &m); void ToMatrix(Matrix44 &m) const; void ToMatrix(Matrix33 &m) const; void ToEulerAngles(S &alpha, S &beta, S &gamma); void FromEulerAngles(S alpha, S beta, S gamma); Point3 Rotate(const Point3 vec) const; //duplicated ... because of gcc new confoming to ISO template derived classes //do no 'see' parent members (unless explicitly specified) const S & V ( const int i ) const { assert(i>=0 && i<4); return Point4::V(i); } S & V ( const int i ) { assert(i>=0 && i<4); return Point4::V(i); } }; template Quaternion Interpolate( Quaternion a, Quaternion b, double t); template Quaternion &Invert(Quaternion &q); template Quaternion Inverse(const Quaternion &q); //Implementation template void Quaternion::SetIdentity(){ FromAxis(0, Point3(1, 0, 0)); } template Quaternion::Quaternion(const S phi, const Point3 &a) { FromAxis(phi, a); } template Quaternion Quaternion::operator*(const S &s) const { return (Quaternion(V(0)*s,V(1)*s,V(2)*s,V(3)*s)); } template Quaternion Quaternion::operator*(const Quaternion &q) const { Point3 t1(V(1), V(2), V(3)); Point3 t2(q.V(1), q.V(2), q.V(3)); S d = t2 * t1; Point3 t3 = t1 ^ t2; t1 *= q.V(0); t2 *= V(0); Point3 tf = t1 + t2 +t3; Quaternion t; t.V(0) = V(0) * q.V(0) - d; t.V(1) = tf[0]; t.V(2) = tf[1]; t.V(3) = tf[2]; return t; } template Quaternion &Quaternion::operator*=(const Quaternion &q) { S ww = V(0) * q.V(0) - V(1) * q.V(1) - V(2) * q.V(2) - V(3) * q.V(3); S xx = V(0) * q.V(1) + V(1) * q.V(0) + V(2) * q.V(3) - V(3) * q.V(2); S yy = V(0) * q.V(2) - V(1) * q.V(3) + V(2) * q.V(0) + V(3) * q.V(1); V(0) = ww; V(1) = xx; V(2) = yy; V(3) = V(0) * q.V(3) + V(1) * q.V(2) - V(2) * q.V(1) + V(3) * q.V(0); return *this; } template void Quaternion::Invert() { V(1)*=-1; V(2)*=-1; V(3)*=-1; } template void Quaternion::FromAxis(const S phi, const Point3 &a) { Point3 b = a; b.Normalize(); S s = math::Sin(phi/(S(2.0))); V(0) = math::Cos(phi/(S(2.0))); V(1) = b[0]*s; V(2) = b[1]*s; V(3) = b[2]*s; } template void Quaternion::ToAxis(S &phi, Point3 &a) const { S s = math::Asin(V(0))*S(2.0); phi = math::Acos(V(0))*S(2.0); if(s < 0) phi = - phi; a.V(0) = V(1); a.V(1) = V(2); a.V(2) = V(3); a.Normalize(); } template Point3 Quaternion::Rotate(const Point3 p) const { Quaternion co = *this; co.Invert(); Quaternion tmp(0, p.V(0), p.V(1), p.V(2)); tmp = (*this) * tmp * co; return Point3(tmp.V(1), tmp.V(2), tmp.V(3)); } template void Quaternion::ToMatrix(Matrix44 &m) const { S q00 = V(1)*V(1); S q01 = V(1)*V(2); S q02 = V(1)*V(3); S q03 = V(1)*V(0); S q11 = V(2)*V(2); S q12 = V(2)*V(3); S q13 = V(2)*V(0); S q22 = V(3)*V(3); S q23 = V(3)*V(0); m[0][0] = (S)(1.0-(q11 + q22)*2.0); m[0][1] = (S)((q01 - q23)*2.0); m[0][2] = (S)((q02 + q13)*2.0); m[0][3] = (S)0.0; m[1][0] = (S)((q01 + q23)*2.0); m[1][1] = (S)(1.0-(q22 + q00)*2.0); m[1][2] = (S)((q12 - q03)*2.0); m[1][3] = (S)0.0; m[2][0] = (S)((q02 - q13)*2.0); m[2][1] = (S)((q12 + q03)*2.0); m[2][2] = (S)(1.0-(q11 + q00)*2.0); m[2][3] = (S)0.0; m[3][0] = (S)0.0; m[3][1] = (S)0.0; m[3][2] = (S)0.0; m[3][3] = (S)1.0; } template void Quaternion::ToMatrix(Matrix33 &m) const { S q00 = V(1)*V(1); S q01 = V(1)*V(2); S q02 = V(1)*V(3); S q03 = V(1)*V(0); S q11 = V(2)*V(2); S q12 = V(2)*V(3); S q13 = V(2)*V(0); S q22 = V(3)*V(3); S q23 = V(3)*V(0); m[0][0] = (S)(1.0-(q11 + q22)*2.0); m[0][1] = (S)((q01 - q23)*2.0); m[0][2] = (S)((q02 + q13)*2.0); m[1][0] = (S)((q01 + q23)*2.0); m[1][1] = (S)(1.0-(q22 + q00)*2.0); m[1][2] = (S)((q12 - q03)*2.0); m[2][0] = (S)((q02 - q13)*2.0); m[2][1] = (S)((q12 + q03)*2.0); m[2][2] = (S)(1.0-(q11 + q00)*2.0); } ///warning m deve essere una matrice di rotazione pena il disastro. template void Quaternion::FromMatrix(const Matrix44 &m) { S Sc; S t = (m.V()[0] + m.V()[5] + m.V()[10] + (S)1.0); if(t > 0) { Sc = (S)0.5 / math::Sqrt(t); V(0) = (S)0.25 / Sc; V(1) = ( m.V()[9] - m.V()[6] ) * Sc; V(2) = ( m.V()[2] - m.V()[8] ) * Sc; V(3) = ( m.V()[4] - m.V()[1] ) * Sc; } else { if(m.V()[0] > m.V()[5] && m.V()[0] > m.V()[10]) { Sc = math::Sqrt( (S)1.0 + m.V()[0] - m.V()[5] - m.V()[10] ) * (S)2.0; V(1) = (S)0.5 / Sc; V(2) = (m.V()[1] + m.V()[4] ) / Sc; V(3) = (m.V()[2] + m.V()[8] ) / Sc; V(0) = (m.V()[6] + m.V()[9] ) / Sc; } else if( m.V()[5] > m.V()[10]) { Sc = math::Sqrt( (S)1.0 + m.V()[5] - m.V()[0] - m.V()[10] ) * (S)2.0; V(1) = (m.V()[1] + m.V()[4] ) / Sc; V(2) = (S)0.5 / Sc; V(3) = (m.V()[6] + m.V()[9] ) / Sc; V(0) = (m.V()[2] + m.V()[8] ) / Sc; } else { Sc = math::Sqrt( (S)1.0 + m.V()[10] - m.V()[0] - m.V()[5] ) * (S)2.0; V(1) = (m.V()[2] + m.V()[8] ) / Sc; V(2) = (m.V()[6] + m.V()[9] ) / Sc; V(3) = (S)0.5 / Sc; V(0) = (m.V()[1] + m.V()[4] ) / Sc; } } } template void Quaternion::ToEulerAngles(S &alpha, S &beta, S &gamma) { //...TODO... } template void Quaternion::FromEulerAngles(S alpha, S beta, S gamma) { S cosalpha = cos(alpha / 2.0); S cosbeta = cos(beta / 2.0); S cosgamma = cos(gamma / 2.0); S sinalpha = sin(alpha / 2.0); S sinbeta = sin(beta / 2.0); S singamma = sin(gamma / 2.0); V(0) = cosalpha * cosbeta * cosgamma + sinalpha * sinbeta * singamma; V(1) = sinalpha * cosbeta * cosgamma - cosalpha * sinbeta * singamma; V(2) = cosalpha * sinbeta * cosgamma + sinalpha * cosbeta * singamma; V(3) = cosalpha * cosbeta * singamma - sinalpha * sinbeta * cosgamma; } template Quaternion &Invert(Quaternion &m) { m.Invert(); return m; } template Quaternion Inverse(const Quaternion &m) { Quaternion a = m; a.Invert(); return a; } template Quaternion Interpolate( Quaternion a , Quaternion b , double t) { double v = a.V(0) * b.V(0) + a.V(1) * b.V(1) + a.V(2) * b.V(2) + a.V(3) * b.V(3); double phi = math::Acos(v); if(phi > 0.01) { a = a * (math::Sin(phi *(1-t))/math::Sin(phi)); b = b * (math::Sin(phi * t)/math::Sin(phi)); } Quaternion c; c.V(0) = a.V(0) + b.V(0); c.V(1) = a.V(1) + b.V(1); c.V(2) = a.V(2) + b.V(2); c.V(3) = a.V(3) + b.V(3); if(v < -0.999) { //almost opposite double d = t * (1 - t); if(c.V(0) == 0) c.V(0) += d; else c.V(1) += d; } c.Normalize(); return c; } typedef Quaternion Quaternionf; typedef Quaternion Quaterniond; } // end namespace #endif qutemol/vcg/vcg/math/similarity.h0000444000175000017500000002246310760330527015462 0ustar mbamba/**************************************************************************** * VCGLib o o * * Visual and Computer Graphics Library o o * * _ O _ * * Copyright(C) 2004 \/)\/ * * Visual Computing Lab /\/| * * ISTI - Italian National Research Council | * * \ * * All rights reserved. * * * * 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. * * * * 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 (http://www.gnu.org/licenses/gpl.txt) * * for more details. * * * ****************************************************************************/ /**************************************************************************** History $Log: similarity.h,v $ Revision 1.17 2008/02/24 18:03:03 ponchio Returrned to s*r*t decomposition. Revision 1.16 2008/02/22 17:40:27 ponchio Fixed determinantt problem and quaternion problem. Revision 1.15 2008/02/21 11:34:08 ponchio refixed bug in FromMatrix Revision 1.14 2008/02/21 10:57:59 ponchio fixed bug in FromMatrix Revision 1.13 2008/02/21 10:30:18 benedetti corrected bug in FromMatrix Revision 1.12 2007/02/05 14:17:48 corsini add new ctor (build similarity from euler angles) Revision 1.11 2004/12/15 18:45:50 tommyfranken *** empty log message *** Revision 1.10 2004/10/07 13:55:47 ganovelli templated on the kind of class used to implement rotation (default is QUternion but it can be Matrix44 as well) Revision 1.9 2004/06/04 13:35:07 cignoni added InverseMatrix, Revision 1.8 2004/05/07 10:09:13 cignoni missing final newline Revision 1.7 2004/05/04 23:23:45 cignoni unified to the gl stlyle matix*vector. removed vector*matrix operator Revision 1.6 2004/03/25 14:57:49 ponchio Microerror. ($LOG$ -> $Log: similarity.h,v $ Microerror. ($LOG$ -> Revision 1.17 2008/02/24 18:03:03 ponchio Microerror. ($LOG$ -> Returrned to s*r*t decomposition. Microerror. ($LOG$ -> Microerror. ($LOG$ -> Revision 1.16 2008/02/22 17:40:27 ponchio Microerror. ($LOG$ -> Fixed determinantt problem and quaternion problem. Microerror. ($LOG$ -> Microerror. ($LOG$ -> Revision 1.15 2008/02/21 11:34:08 ponchio Microerror. ($LOG$ -> refixed bug in FromMatrix Microerror. ($LOG$ -> Microerror. ($LOG$ -> Revision 1.14 2008/02/21 10:57:59 ponchio Microerror. ($LOG$ -> fixed bug in FromMatrix Microerror. ($LOG$ -> Microerror. ($LOG$ -> Revision 1.13 2008/02/21 10:30:18 benedetti Microerror. ($LOG$ -> corrected bug in FromMatrix Microerror. ($LOG$ -> Microerror. ($LOG$ -> Revision 1.12 2007/02/05 14:17:48 corsini Microerror. ($LOG$ -> add new ctor (build similarity from euler angles) Microerror. ($LOG$ -> Microerror. ($LOG$ -> Revision 1.11 2004/12/15 18:45:50 tommyfranken Microerror. ($LOG$ -> *** empty log message *** Microerror. ($LOG$ -> Microerror. ($LOG$ -> Revision 1.10 2004/10/07 13:55:47 ganovelli Microerror. ($LOG$ -> templated on the kind of class used to implement rotation Microerror. ($LOG$ -> (default is QUternion but it can be Matrix44 as well) Microerror. ($LOG$ -> Microerror. ($LOG$ -> Revision 1.9 2004/06/04 13:35:07 cignoni Microerror. ($LOG$ -> added InverseMatrix, Microerror. ($LOG$ -> Microerror. ($LOG$ -> Revision 1.8 2004/05/07 10:09:13 cignoni Microerror. ($LOG$ -> missing final newline Microerror. ($LOG$ -> Microerror. ($LOG$ -> Revision 1.7 2004/05/04 23:23:45 cignoni Microerror. ($LOG$ -> unified to the gl stlyle matix*vector. removed vector*matrix operator Microerror. ($LOG$ -> ****************************************************************************/ #ifndef SIMILARITY_H #define SIMILARITY_H #include #include namespace vcg { template > class Similarity { public: Similarity() {} Similarity(const RotationType &q) { SetRotate(q); } Similarity(const Point3 &p) { SetTranslate(p); } Similarity(S s) { SetScale(s); } Similarity(S alpha, S beta, S gamma) { rot.FromEulerAngles(alpha, beta, gamma); tra = Point3(0, 0, 0); sca = 1; } Similarity operator*(const Similarity &affine) const; Similarity &operator*=(const Similarity &affine); //Point3 operator*(const Point3 &p) const; Similarity &SetIdentity(); Similarity &SetScale(const S s); Similarity &SetTranslate(const Point3 &t); ///use radiants for angle. Similarity &SetRotate(S angle, const Point3 & axis); Similarity &SetRotate(const RotationType &q); Matrix44 Matrix() const; Matrix44 InverseMatrix() const; void FromMatrix(const Matrix44 &m); RotationType rot; Point3 tra; S sca; }; template Similarity &Invert(Similarity &m); template Similarity Inverse(const Similarity &m); template Point3 operator*(const Similarity &m, const Point3 &p); template Similarity Similarity::operator*(const Similarity &a) const { Similarity r; r.rot = rot * a.rot; r.sca = sca * a.sca; r.tra = (rot.Rotate(a.tra)) * sca + tra; return r; } template Similarity &Similarity::operator*=(const Similarity &a) { rot = rot * a.rot; sca = sca * a.sca; tra = (rot.Rotate(a.tra)) * sca + tra; return *this; } template Similarity &Similarity::SetIdentity() { rot.SetIdentity(); tra = Point3(0, 0, 0); sca = 1; return *this; } template Similarity &Similarity::SetScale(const S s) { SetIdentity(); sca = s; return *this; } template Similarity &Similarity::SetTranslate(const Point3 &t) { SetIdentity(); tra = t; return *this; } template Similarity &Similarity::SetRotate(S angle, const Point3 &axis) { SetIdentity(); rot.FromAxis(angle, axis); return *this; } template Similarity &Similarity::SetRotate(const RotationType &q) { SetIdentity(); rot = q; return *this; } template Matrix44 Similarity::Matrix() const { Matrix44 r; rot.ToMatrix(r); Matrix44 s = Matrix44().SetScale(sca, sca, sca); Matrix44 t = Matrix44().SetTranslate(tra[0], tra[1], tra[2]); return s*r*t; // trans * scale * rot; } template Matrix44 Similarity::InverseMatrix() const { return Inverse(Matrix()); } template void Similarity::FromMatrix(const Matrix44 &m) { //Computes a t*s*r decomposition S det = m.Determinant(); assert(det > 0); sca = (S)pow(det, 1/3.0); Matrix44 t = m*Matrix44().SetScale(1/sca, 1/sca, 1/sca); rot.FromMatrix(t); tra[0] = t.ElementAt(0, 3); tra[1] = t.ElementAt(1, 3); tra[2] = t.ElementAt(2, 3); //Compute a s*r*t decomposition Quaternion irot = rot; irot.Invert(); tra = irot.Rotate(tra); tra /= sca; } template Similarity &Invert(Similarity &a) { a.rot.Invert(); a.sca = 1/a.sca; a.tra = a.rot.Rotate(-a.tra)*a.sca; return a; } template Similarity Inverse(const Similarity &m) { Similarity a = m; return Invert(a); } template Similarity Interpolate(const Similarity &a, const Similarity &b, const S t) { Similarity r; r.rot = interpolate(a.rot, b.rot, t); r.tra = t * a.tra + (1-t) * b.tra; r.sca = t * a.sca + (1-t) * b.sca; return r; } template Point3 operator*(const Similarity &m, const Point3 &p) { Point3 r = m.rot.Rotate(p); r *= m.sca; r += m.tra; return r; } //typedef Similarity Similarityf; //typedef SimilaritySimilarityd; class Similarityf:public Similarity{}; class Similarityd:public Similarity{}; } //namespace #endif qutemol/vcg/vcg/math/lin_algebra.h0000444000175000017500000004323110767453705015542 0ustar mbamba/**************************************************************************** * VCGLib o o * * Visual and Computer Graphics Library o o * * _ O _ * * Copyright(C) 2006 \/)\/ * * Visual Computing Lab /\/| * * ISTI - Italian National Research Council | * * \ * * All rights reserved. * * * * 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. * * * * 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 (http://www.gnu.org/licenses/gpl.txt) * * for more details. * * * ****************************************************************************/ /**************************************************************************** History $Log: lin_algebra.h,v $ Revision 1.17 2008/03/17 11:36:37 ganovelli removed printf Revision 1.16 2007/01/29 00:18:20 pietroni -added some explicit CASTs in order to avoid warning if one use float instead of double as ScalarType Revision 1.15 2006/09/29 08:36:10 cignoni Added missing typedef for gcc compiing Revision 1.14 2006/09/28 22:49:49 fiorin Removed some warnings Revision 1.13 2006/07/28 12:39:05 zifnab1974 added some typename directives Revision 1.12 2006/07/24 07:26:47 fiorin Changed the template argument in JacobiRotate and added method for sorting eigenvalues and eigenvectors (SortEigenvaluesAndEigenvectors) Revision 1.11 2006/05/25 09:35:55 cignoni added missing internal prototype to Sort function Revision 1.10 2006/05/17 09:26:35 cignoni Added initial disclaimer ****************************************************************************/ #ifndef __VCGLIB_LINALGEBRA_H #define __VCGLIB_LINALGEBRA_H #include #include namespace vcg { /** \addtogroup math */ /* @{ */ /*! * */ template< typename MATRIX_TYPE > static void JacobiRotate(MATRIX_TYPE &A, typename MATRIX_TYPE::ScalarType s, typename MATRIX_TYPE::ScalarType tau, int i,int j,int k,int l) { typename MATRIX_TYPE::ScalarType g=A[i][j]; typename MATRIX_TYPE::ScalarType h=A[k][l]; A[i][j]=g-s*(h+g*tau); A[k][l]=h+s*(g-h*tau); }; /*! * Computes all eigenvalues and eigenvectors of a real symmetric matrix . * On output, elements of the input matrix above the diagonal are destroyed. * \param d returns the eigenvalues of a. * \param v is a matrix whose columns contain, the normalized eigenvectors * \param nrot returns the number of Jacobi rotations that were required. */ template static void Jacobi(MATRIX_TYPE &w, POINT_TYPE &d, MATRIX_TYPE &v, int &nrot) { typedef typename MATRIX_TYPE::ScalarType ScalarType; assert(w.RowsNumber()==w.ColumnsNumber()); int dimension = w.RowsNumber(); int j,iq,ip,i; //assert(w.IsSymmetric()); typename MATRIX_TYPE::ScalarType tresh, theta, tau, t, sm, s, h, g, c; POINT_TYPE b, z; v.SetIdentity(); for (ip=0;ip4 && (float)(fabs(d[ip])+g) == (float)fabs(d[ip]) && (float)(fabs(d[iq])+g) == (float)fabs(d[iq])) w[ip][iq]=ScalarType(0.0); else if (fabs(w[ip][iq]) > tresh) { h=d[iq]-d[ip]; if ((float)(fabs(h)+g) == (float)fabs(h)) t=(w[ip][iq])/h; //t =1/(2#) else { theta=ScalarType(0.5)*h/(w[ip][iq]); //Equation (11.1.10). t=ScalarType(1.0)/(fabs(theta)+sqrt(ScalarType(1.0)+theta*theta)); if (theta < ScalarType(0.0)) t = -t; } c=ScalarType(1.0)/sqrt(ScalarType(1.0)+t*t); s=t*c; tau=s/(ScalarType(1.0)+c); h=t*w[ip][iq]; z[ip] -= h; z[iq] += h; d[ip] -= h; d[iq] += h; w[ip][iq]=ScalarType(0.0); for (j=0;j<=ip-1;j++) { //Case of rotations 1 <= j < p. JacobiRotate(w,s,tau,j,ip,j,iq) ; } for (j=ip+1;j<=iq-1;j++) { //Case of rotations p < j < q. JacobiRotate(w,s,tau,ip,j,j,iq); } for (j=iq+1;j(w,s,tau,ip,j,iq,j); } for (j=0;j(v,s,tau,j,ip,j,iq); } ++nrot; } } } for (ip=0;ip void SortEigenvaluesAndEigenvectors(POINT_TYPE &eigenvalues, MATRIX_TYPE &eigenvectors) { assert(eigenvectors.ColumnsNumber()==eigenvectors.RowsNumber()); int dimension = eigenvectors.ColumnsNumber(); int i, j, k; float p; for (i=0; i= p) p = eigenvalues[ k=j ]; if (k != i) { eigenvalues[k] = eigenvalues[i]; // i.e. eigenvalues[i] = p; // swaps the value of the elements i-th and k-th for (j=0; j inline static TYPE pythagora(TYPE a, TYPE b) { TYPE abs_a = fabs(a); TYPE abs_b = fabs(b); if (abs_a > abs_b) return abs_a*sqrt((TYPE)1.0+sqr(abs_b/abs_a)); else return (abs_b == (TYPE)0.0 ? (TYPE)0.0 : abs_b*sqrt((TYPE)1.0+sqr(abs_a/abs_b))); }; template inline static TYPE sign(TYPE a, TYPE b) { return (b >= 0.0 ? fabs(a) : -fabs(a)); }; template inline static TYPE sqr(TYPE a) { TYPE sqr_arg = a; return (sqr_arg == 0 ? 0 : sqr_arg*sqr_arg); } /*! * */ enum SortingStrategy {LeaveUnsorted=0, SortAscending=1, SortDescending=2}; template< typename MATRIX_TYPE > void Sort(MATRIX_TYPE &U, typename MATRIX_TYPE::ScalarType W[], MATRIX_TYPE &V, const SortingStrategy sorting) ; /*! * Given a matrix Amxn, this routine computes its singular value decomposition, * i.e. A=UxWxVT. The matrix A will be destroyed! * (This is the implementation described in Numerical Recipies). * \param A the matrix to be decomposed * \param W the diagonal matrix of singular values W, stored as a vector W[1...N] * \param V the matrix V (not the transpose VT) * \param max_iters max iteration number (default = 30). * \return */ template static bool SingularValueDecomposition(MATRIX_TYPE &A, typename MATRIX_TYPE::ScalarType *W, MATRIX_TYPE &V, const SortingStrategy sorting=LeaveUnsorted, const int max_iters=30) { typedef typename MATRIX_TYPE::ScalarType ScalarType; int m = (int) A.RowsNumber(); int n = (int) A.ColumnsNumber(); int flag,i,its,j,jj,k,l,nm; ScalarType anorm, c, f, g, h, s, scale, x, y, z, *rv1; bool convergence = true; rv1 = new ScalarType[n]; g = scale = anorm = 0; // Householder reduction to bidiagonal form. for (i=0; i( sqrt(s), f ); h = f*g - s; A[i][i]=f-g; for (j=l; j(sqrt(s),f); h = f*g - s; A[i][l] = f-g; for (k=l; k=0; i--) { //Accumulation of right-hand transformations. if (i < (n-1)) { if (g) { for (j=l; j=0; i--) { l = i+1; g = W[i]; for (j=l; j=0; k--) { for (its=1; its<=max_iters; its++) { flag=1; for (l=k; l>=0; l--) { // Test for splitting. nm=l-1; // Note that rv1[1] is always zero. if ((double)(fabs(rv1[l])+anorm) == anorm) { flag=0; break; } if ((double)(fabs(W[nm])+anorm) == anorm) break; } if (flag) { c=0.0; //Cancellation of rv1[l], if l > 1. s=1.0; for (i=l ;i<=k; i++) { f = s*rv1[i]; rv1[i] = c*rv1[i]; if ((double)(fabs(f)+anorm) == anorm) break; g = W[i]; h = pythagora(f,g); W[i] = h; h = (ScalarType)1.0/h; c = g*h; s = -f*h; for (j=0; j(f,1.0); f=((x-z)*(x+z) + h*((y/(f+sign(g,f)))-h))/x; c=s=1.0; //Next QR transformation: for (j=l; j<= nm;j++) { i = j+1; g = rv1[i]; y = W[i]; h = s*g; g = c*g; z = pythagora(f,h); rv1[j] = z; c = f/z; s = h/z; f = x*c + g*s; g = g*c - x*s; h = y*s; y *= c; for (jj=0; jj(f,h); W[j] = z; // Rotation can be arbitrary if z = 0. if (z) { z = (ScalarType)1.0/z; c = f*z; s = h*z; } f = c*g + s*y; x = c*y - s*g; for (jj=0; jj(A, W, V, sorting); return convergence; }; /*! * Sort the singular values computed by the SingularValueDecomposition procedure and * modify the matrices U and V accordingly. */ // TODO modify the last parameter type template< typename MATRIX_TYPE > void Sort(MATRIX_TYPE &U, typename MATRIX_TYPE::ScalarType W[], MATRIX_TYPE &V, const SortingStrategy sorting) { typedef typename MATRIX_TYPE::ScalarType ScalarType; assert(U.ColumnsNumber()==V.ColumnsNumber()); int mu = U.RowsNumber(); int mv = V.RowsNumber(); int n = U.ColumnsNumber(); //ScalarType* u = &U[0][0]; //ScalarType* v = &V[0][0]; for (int i=0; i p) { k = j; p = W[j]; } } break; } } if (k != i) { W[k] = W[i]; // i.e. W[i] = p; // swaps the i-th and the k-th elements int j = mu; //ScalarType* uji = u + i; // uji = &U[0][i] //ScalarType* ujk = u + k; // ujk = &U[0][k] //ScalarType* vji = v + i; // vji = &V[0][i] //ScalarType* vjk = v + k; // vjk = &V[0][k] //if (j) //{ // for(;;) for( ; j!=0; --j, uji+=n, ujk+=n) // { { // p = *uji; p = *uji; // i.e. // *uji = *ujk; *uji = *ujk; // swap( U[s][i], U[s][k] ) // *ujk = p; *ujk = p; // // if (!(--j)) } // break; // uji += n; // ujk += n; // } //} for(int s=0; j!=0; ++s, --j) std::swap(U[s][i], U[s][k]); j = mv; //if (j!=0) //{ // for(;;) for ( ; j!=0; --j, vji+=n, ujk+=n) // { { // p = *vji; p = *vji; // i.e. // *vji = *vjk; *vji = *vjk; // swap( V[s][i], V[s][k] ) // *vjk = p; *vjk = p; // // if (!(--j)) } // break; // vji += n; // vjk += n; // } //} for (int s=0; j!=0; ++s, --j) std::swap(V[s][i], V[s][k]); } } } /*! * Solves AxX = B for a vector X, where A is specified by the matrices Umxn, * Wnx1 and Vnxn as returned by SingularValueDecomposition. * No input quantities are destroyed, so the routine may be called sequentially with different bxs. * \param x is the output solution vector (xnx1) * \param b is the input right-hand side (bnx1) */ template static void SingularValueBacksubstitution(const MATRIX_TYPE &U, const typename MATRIX_TYPE::ScalarType *W, const MATRIX_TYPE &V, typename MATRIX_TYPE::ScalarType *x, const typename MATRIX_TYPE::ScalarType *b) { typedef typename MATRIX_TYPE::ScalarType ScalarType; unsigned int jj, j, i; unsigned int columns_number = U.ColumnsNumber(); unsigned int rows_number = U.RowsNumber(); ScalarType s; ScalarType *tmp = new ScalarType[columns_number]; for (j=0; j class Legendre { private : /** * Legendre Polynomial three term Recurrence Relation */ static inline ScalarType legendre_next(unsigned l, ScalarType P_lm1, ScalarType P_lm2, ScalarType x) { return ((2 * l + 1) * x * P_lm1 - l * P_lm2) / (l + 1); } /** * Associated Legendre Polynomial three term Recurrence Relation. * Raises the band index. */ static inline double legendre_next(unsigned l, unsigned m, ScalarType P_lm1, ScalarType P_lm2, ScalarType x) { return ((2 * l + 1) * x * P_lm1 - (l + m) * P_lm2) / (l + 1 - m); } /** * Recurrence relation to compute P_m_(m+1) given P_m_m at the same x */ static inline double legendre_P_m_mplusone(unsigned m, ScalarType p_m_m, ScalarType x) { return x * (2.0 * m + 1.0) * p_m_m; } /** * Starting relation to compute P_m_m according to the formula: * * pow(-1, m) * double_factorial(2 * m - 1) * pow(1 - x*x, abs(m)/2) * * which becomes, if x = cos(theta) : * * pow(-1, m) * double_factorial(2 * m - 1) * pow(sin(theta), abs(m)/2) */ static inline double legendre_P_m_m(unsigned m, ScalarType sin_theta) { ScalarType p_m_m = 1.0; if (m > 0) { ScalarType fact = 1.0; //Double factorial here for (unsigned i = 1; i <= m; ++i) { p_m_m *= fact * sin_theta; //raising sin_theta to the power of m/2 fact += 2.0; } if (m&1) //odd m { // Condon-Shortley Phase term p_m_m *= -1; } } return p_m_m; } static inline double legendre_P_l(unsigned l, ScalarType x) { ScalarType p0 = 1; ScalarType p1 = x; if (l == 0) return p0; for (unsigned n = 1; n < l; ++n) { Swap(p0, p1); p1 = legendre_next(n, p0, p1, x); } return p1; } /** * Computes the Associated Legendre Polynomial for any given * positive m and l, with m <= l and -1 <= x <= 1. */ static inline double legendre_P_l_m(unsigned l, unsigned m, ScalarType cos_theta, ScalarType sin_theta) { if(m > l) return 0; if(m == 0) return legendre_P_l(l, cos_theta); //OK else { ScalarType p_m_m = legendre_P_m_m(m, sin_theta); //OK if (l == m) return p_m_m; ScalarType p_m_mplusone = legendre_P_m_mplusone(m, p_m_m, cos_theta); //OK if (l == m + 1) return p_m_mplusone; unsigned n = m + 1; while(n < l) { Swap(p_m_m, p_m_mplusone); p_m_mplusone = legendre_next(n, m, p_m_m, p_m_mplusone, cos_theta); ++n; } return p_m_mplusone; } } public : static double Polynomial(unsigned l, ScalarType x) { assert (x <= 1 && x >= -1); return legendre_P_l(l, x); } static double AssociatedPolynomial(unsigned l, unsigned m, ScalarType x) { assert (m <= l && x <= 1 && x >= -1); return legendre_P_l_m(l, m, x, Sqrt(1.0 - x * x) ); } static double AssociatedPolynomial(unsigned l, unsigned m, ScalarType cos_theta, ScalarType sin_theta) { assert (m <= l && cos_theta <= 1 && cos_theta >= -1 && sin_theta <= 1 && sin_theta >= -1); return legendre_P_l_m(l, m, cos_theta, Abs(sin_theta)); } }; }} //vcg::math namespace #endifqutemol/vcg/vcg/math/quadric.h0000444000175000017500000002434710600461543014723 0ustar mbamba/**************************************************************************** * VCGLib o o * * Visual and Computer Graphics Library o o * * _ O _ * * Copyright(C) 2004 \/)\/ * * Visual Computing Lab /\/| * * ISTI - Italian National Research Council | * * \ * * All rights reserved. * * * * 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. * * * * 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 (http://www.gnu.org/licenses/gpl.txt) * * for more details. * * * ****************************************************************************/ /**************************************************************************** History $Log: quadric.h,v $ Revision 1.8 2007/03/22 11:07:15 cignoni Solved an issue related to different casting double-float between gcc 3 and gcc 4 Revision 1.7 2006/11/13 12:53:40 ponchio just added an #include Revision 1.6 2006/10/09 20:23:00 cignoni Added a minimum method that uses SVD. Unfortunately it is much much slower. Revision 1.5 2004/12/10 01:31:59 cignoni added an alternative QuadricMinimization (we should use LRU decomposition!!) Revision 1.3 2004/10/25 16:23:51 ponchio typedef ScalarType ScalarType; was a problem on g++ Revision 1.2 2004/10/25 16:15:59 ganovelli template changed Revision 1.1 2004/09/14 19:48:27 ganovelli created ****************************************************************************/ #ifndef __VCGLIB_QUADRIC #define __VCGLIB_QUADRIC #include #include #include namespace vcg { namespace math { template class Quadric { public: typedef Scalar ScalarType; ScalarType a[6]; // Matrice 3x3 simmetrica: a11 a12 a13 a22 a23 a33 ScalarType b[3]; // Vettore r3 ScalarType c; // Fattore scalare (se -1 quadrica nulla) inline Quadric() { c = -1; } // Necessari se si utilizza stl microsoft // inline bool operator < ( const Quadric & q ) const { return false; } // inline bool operator == ( const Quadric & q ) const { return true; } bool IsValid() const { return c>=0; } void SetInvalid() { c = -1.0; } template< class PlaneType > void ByPlane( const PlaneType & p ) // Init dato un piano { a[0] = (ScalarType)p.Direction()[0]*p.Direction()[0]; // a11 a[1] = (ScalarType)p.Direction()[1]*p.Direction()[0]; // a12 (=a21) a[2] = (ScalarType)p.Direction()[2]*p.Direction()[0]; // a13 (=a31) a[3] = (ScalarType)p.Direction()[1]*p.Direction()[1]; // a22 a[4] = (ScalarType)p.Direction()[2]*p.Direction()[1]; // a23 (=a32) a[5] = (ScalarType)p.Direction()[2]*p.Direction()[2]; // a33 b[0] = (ScalarType)(-2.0)*p.Offset()*p.Direction()[0]; b[1] = (ScalarType)(-2.0)*p.Offset()*p.Direction()[1]; b[2] = (ScalarType)(-2.0)*p.Offset()*p.Direction()[2]; c = (ScalarType)p.Offset()*p.Offset(); } void Zero() // Azzera la quadrica { a[0] = 0; a[1] = 0; a[2] = 0; a[3] = 0; a[4] = 0; a[5] = 0; b[0] = 0; b[1] = 0; b[2] = 0; c = 0; } void operator = ( const Quadric & q ) // Assegna una quadrica { //assert( IsValid() ); assert( q.IsValid() ); a[0] = q.a[0]; a[1] = q.a[1]; a[2] = q.a[2]; a[3] = q.a[3]; a[4] = q.a[4]; a[5] = q.a[5]; b[0] = q.b[0]; b[1] = q.b[1]; b[2] = q.b[2]; c = q.c; } void operator += ( const Quadric & q ) // Somma una quadrica { assert( IsValid() ); assert( q.IsValid() ); a[0] += q.a[0]; a[1] += q.a[1]; a[2] += q.a[2]; a[3] += q.a[3]; a[4] += q.a[4]; a[5] += q.a[5]; b[0] += q.b[0]; b[1] += q.b[1]; b[2] += q.b[2]; c += q.c; } template ResultScalarType Apply( const Point3 & p ) const // Applica la quadrica al punto p { assert( IsValid() ); /* // Versione Lenta Point3d t; t[0] = p[0]*a[0] + p[1]*a[1] + p[2]*a[2]; t[1] = p[0]*a[1] + p[1]*a[3] + p[2]*a[4]; t[2] = p[0]*a[2] + p[1]*a[4] + p[2]*a[5]; double k = b[0]*p[0] + b[1]*p[1] + b[2]*p[2]; double tp = t*p ; assert(tp+k+c >= 0); return tp + k + c; */ /* Versione veloce */ return ResultScalarType ( p[0]*p[0]*a[0] + 2*p[0]*p[1]*a[1] + 2*p[0]*p[2]*a[2] + p[0]*b[0] + p[1]*p[1]*a[3] + 2*p[1]*p[2]*a[4] + p[1]*b[1] + p[2]*p[2]*a[5] + p[2]*b[2] + c); } // spostare..risolve un sistema 3x3 template bool Gauss33( FLTYPE x[], FLTYPE C[3][3+1] ) { const FLTYPE keps = (FLTYPE)1e-3; int i,j,k; FLTYPE eps; // Determina valore cond. eps = math::Abs(C[0][0]); for(i=1;i<3;++i) { FLTYPE t = math::Abs(C[i][i]); if( eps vma) { vma = t; ma = k; } } if (vma=0; i--) // Sostituzione { FLTYPE t; for (t = 0.0, j = i + 1; j < 3; j++) t += C[i][j] * x[j]; x[i] = (C[i][3] - t) / C[i][i]; } return true; } // determina il punto di errore minimo template bool Minimum(Point3 &x) { ReturnScalarType C[3][4]; C[0][0]=a[0]; C[0][1]=a[1]; C[0][2]=a[2]; C[1][0]=a[1]; C[1][1]=a[3]; C[1][2]=a[4]; C[2][0]=a[2]; C[2][1]=a[4]; C[2][2]=a[5]; C[0][3]=-b[0]/2; C[1][3]=-b[1]/2; C[2][3]=-b[2]/2; return Gauss33(&(x[0]),C); } // determina il punto di errore minimo usando le fun di inversione di matrice che usano svd // Molto + lento template bool MinimumSVD(Point3 &x) { Matrix33 C; C[0][0]=a[0]; C[0][1]=a[1]; C[0][2]=a[2]; C[1][0]=a[1]; C[1][1]=a[3]; C[1][2]=a[4]; C[2][0]=a[2]; C[2][1]=a[4]; C[2][2]=a[5]; Invert(C); C[0][3]=-b[0]/2; C[1][3]=-b[1]/2; C[2][3]=-b[2]/2; x = C * Point3(-b[0]/2,-b[1]/2,-b[2]/2) ; return true; } bool MinimumNew(Point3 &x) const { ScalarType c0=-b[0]/2; ScalarType c1=-b[1]/2; ScalarType c2=-b[2]/2; ScalarType t125 = a[4]*a[1]; ScalarType t124 = a[4]*a[4]-a[3]*a[5]; ScalarType t123 = -a[1]*a[5]+a[4]*a[2]; ScalarType t122 = a[2]*a[3]-t125; ScalarType t121 = -a[2]*a[1]+a[0]*a[4]; ScalarType t120 = a[2]*a[2]; ScalarType t119 = a[1]*a[1]; ScalarType t117 = 1.0/(-a[3]*t120+2*a[2]*t125-t119*a[5]-t124*a[0]); x[0] = -(t124*c0+t122*c2-t123*c1)*t117; x[1] = (t123*c0-t121*c2+(-t120+a[0]*a[5])*c1)*t117; x[2] = -(t122*c0+(t119-a[0]*a[3])*c2+t121*c1)*t117; return true; } // determina il punto di errore minimo vincolato nel segmento (a,b) bool Minimum(Point3 &x,Point3 &pa,Point3 &pb){ ScalarType t1,t2, t4, t5, t8, t9, t11,t12,t14,t15,t17,t18,t25,t26,t30,t34,t35, t41,t42,t44,t45,t50,t52,t54, t56,t21,t23,t37,t64,lambda; t1 = a[4]*pb.z(); t2 = t1*pa.y(); t4 = a[1]*pb.y(); t5 = t4*pa.x(); t8 = a[1]*pa.y(); t9 = t8*pa.x(); t11 = a[4]*pa.z(); t12 = t11*pa.y(); t14 = pa.z()*pa.z(); t15 = a[5]*t14; t17 = a[2]*pa.z(); t18 = t17*pa.x(); t21 = 2.0*t11*pb.y(); t23 = a[5]*pb.z()*pa.z(); t25 = a[2]*pb.z(); t26 = t25*pa.x(); t30 = a[0]*pb.x()*pa.x(); t34 = 2.0*a[3]*pb.y()*pa.y(); t35 = t17*pb.x(); t37 = t8*pb.x(); t41 = pa.x()*pa.x(); t42 = a[0]*t41; t44 = pa.y()*pa.y(); t45 = a[3]*t44; t50 = 2.0*t30+t34+2.0*t35+2.0*t37-(-b[2]/2)*pa.z()-(-b[0]/2)*pa.x()-2.0*t42-2.0*t45+(-b[1]/2)*pb.y() +(-b[0]/2)*pb.x()-(-b[1]/2)*pa.y(); t52 = pb.y()*pb.y(); t54 = pb.z()*pb.z(); t56 = pb.x()*pb.x(); t64 = t5+t37-t9+t30-t18+t35+t26-t25*pb.x()+t2-t1*pb.y()+t23; lambda = (2.0*t2+2.0*t5+(-b[2]/2)*pb.z()-4.0*t9-4.0*t12-2.0*t15-4.0*t18+t21+2.0*t23+ 2.0*t26+t50)/(-t45-a[3]*t52-a[5]*t54-a[0]*t56-t15-t42+t34-2.0*t12+t21-2.0*t4*pb.x()+ 2.0*t64)/2.0; if(lambda<0) lambda=0; else if(lambda>1) lambda = 1; x = pa*(1.0-lambda)+pb*lambda; return true; } void operator *= ( const ScalarType & w ) // Amplifica una quadirca { assert( IsValid() ); a[0] *= w; a[1] *= w; a[2] *= w; a[3] *= w; a[4] *= w; a[5] *= w; b[0] *= w; b[1] *= w; b[2] *= w; c *= w; } }; typedef Quadric Quadrics; typedef Quadric Quadrici; typedef Quadric Quadricf; typedef Quadric Quadricd; } // end namespace math } // end namespace vcg #endif qutemol/vcg/vcg/math/camera.h0000444000175000017500000002636010551220576014524 0ustar mbamba/**************************************************************************** * VCGLib o o * * Visual and Computer Graphics Library o o * * _ O _ * * Copyright(C) 2004 \/)\/ * * Visual Computing Lab /\/| * * ISTI - Italian National Research Council | * * \ * * All rights reserved. * * * * 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. * * * * 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 (http://www.gnu.org/licenses/gpl.txt) * * for more details. * * * ****************************************************************************/ /**************************************************************************** History $Log: camera.h,v $ Revision 1.29 2007/01/10 17:25:18 matteodelle *** empty log message *** Revision 1.28 2006/12/21 00:13:27 cignoni Corrected a syntax error detected only by gcc. Corrected the order of initialization in the constructor to match the declaration order Revision 1.27 2006/12/18 16:02:55 matteodelle minor eroor correction on variable names Revision 1.26 2006/12/18 09:46:38 callieri camera+shot revamp: changed field names to something with more sense, cleaning of various functions, correction of minor bugs/incongruences, removal of the infamous reference in shot. Revision 1.25 2005/12/12 16:52:55 callieri Added Unproject, from 2D local space + Zdepth to 3D camera space. Added ViewportToLocal, inverse of LocalToViewport Revision 1.24 2005/12/01 01:03:37 cignoni Removed excess ';' from end of template functions, for gcc compiling Revision 1.23 2005/10/12 16:43:32 ponchio Added IsOrtho... Revision 1.22 2005/07/11 13:12:34 cignoni small gcc-related compiling issues (typenames,ending cr, initialization order) Revision 1.21 2005/07/01 10:55:42 cignoni Removed default values from the implementation of SetCavalieri and SetIsometric Revision 1.20 2005/06/29 14:59:03 spinelli aggiunto: - l' enum dei tipi PERSPECTIVE, ORTHO, ISOMETRIC, CAVALIERI - inline void SetCavalieri(...) - inline void SetIsometric(...) - modificato - void SetOrtho( .. ) Revision 1.19 2005/02/22 10:57:58 tommyfranken Corrected declaration and some syntax errors in GetFrustum Revision 1.18 2005/02/21 18:11:07 ganovelli GetFrustum moved from gl/camera to math/camera.h Revision 1.17 2005/02/15 14:55:52 tommyfranken added principal point Revision 1.16 2005/01/18 16:40:50 ricciodimare *** empty log message *** Revision 1.15 2005/01/18 15:14:22 ponchio Far and end are reserved. Revision 1.14 2005/01/14 15:28:33 ponchio vcg/Point.h -> vcg/point.h (again!) Revision 1.13 2005/01/05 13:25:29 ganovelli aggiunte conversione di coordinate Revision 1.12 2004/12/16 11:22:30 ricciodimare *** empty log message *** Revision 1.11 2004/12/16 11:21:03 ricciodimare *** empty log message *** Revision 1.10 2004/12/15 18:45:50 tommyfranken *** empty log message *** <<<<<<< camera.h ======= Revision 1.8 2004/11/23 10:15:38 cignoni removed comment in comment gcc warning Revision 1.7 2004/11/03 09:40:53 ganovelli Point?.h to point?.h Revision 1.6 2004/11/03 09:32:50 ganovelli SetPerspective and SetFrustum added (same parameters as in opengl) >>>>>>> 1.8 Revision 1.4 2004/10/07 14:39:57 fasano Remove glew.h include Revision 1.3 2004/10/07 14:22:38 ganovelli y axis reverse in projecting (!) Revision 1.2 2004/10/05 19:04:25 ganovelli version 5-10-2004 in progress Revision 1.1 2004/09/15 22:58:05 ganovelli re-creation Revision 1.2 2004/09/06 21:41:30 ganovelli *** empty log message *** Revision 1.1 2004/09/03 13:01:51 ganovelli creation ****************************************************************************/ #ifndef __VCGLIB_CAMERA #define __VCGLIB_CAMERA // VCG #include #include #include namespace vcg{ enum { PERSPECTIVE = 0, ORTHO = 1, ISOMETRIC = 2, CAVALIERI = 3 }; template class Camera { public: typedef S ScalarType; Camera(): FocalMm(0.f), ViewportPx(vcg::Point2(0,0)), PixelSizeMm(vcg::Point2(0.0,0.0)), CenterPx(vcg::Point2(0.0,0.0)), DistorCenterPx(vcg::Point2(0.0,0.0)), cameraType(0) {} //------ camera intrinsics ScalarType FocalMm; /// Focal Distance: the distance between focal center and image plane. Expressed in mm Point2 ViewportPx; /// Dimension of the Image Plane (in pixels) Point2 PixelSizeMm; /// Dimension in mm of a single pixel Point2 CenterPx; /// Position of the projection of the focal center on the image plane. Expressed in pixels Point2 DistorCenterPx; /// Position of the radial distortion center on the image plane in pixels S k[4]; /// 1st & 2nd order radial lens distortion coefficient (only the first 2 terms are used) //------------------------ int cameraType; /// Type of camera: PERSPECTIVE,ORTHO,ISOMETRIC,CAVALIERI void SetOrtho(S dist) { cameraType = ORTHO; ViewportPx = ( ((ViewportPx[0] * PixelSizeMm[0]) * (ViewportPx[1] * PixelSizeMm[1])) / FocalMm ) * dist; }; bool IsOrtho() const { return ( cameraType == ORTHO ); } //--- Set-up methods /// set the camera specifying the perspecive view inline void SetPerspective(S AngleDeg, S AspectRatio, S Focal, vcg::Point2 Viewport); /// set the camera specifying the cavalieri view inline void SetCavalieri(S sx, S dx, S bt, S tp, S Focal, vcg::Point2 Viewport); /// set the camera specifying the isometric view inline void SetIsometric(S sx, S dx, S bt, S tp, S Focal, vcg::Point2 Viewport); /// set the camera specifying the frustum view inline void SetFrustum(S dx, S sx, S bt, S tp, S Focal, vcg::Point2 Viewport); //------------------ /// returns the frustum inline void GetFrustum(S & sx, S & dx, S & bt, S & tp, S & nr); //--- Space transformation methods /// project a point from 3d CAMERA space to the camera local plane inline vcg::Point2 Project(const vcg::Point3 & p) const; /// unproject a point from the camera local plane (plus depth) to 3d CAMERA space inline vcg::Point3 UnProject(const vcg::Point2 & p, const S & d) const; /// transforms local plane coords to vieport (pixel) coords inline vcg::Point2 LocalToViewportPx(const vcg::Point2 & p) const; /// transforms vieport (pixel) coords to local plane coords inline vcg::Point2 ViewportPxToLocal(const vcg::Point2 & p) const; /// transforms local plane coords to [0 1] coords inline vcg::Point2 LocalTo_0_1(const vcg::Point2 & p) const; /// transforms local plane coords to [-1 1] coords inline vcg::Point2 LocalTo_neg1_1(const vcg::Point2 & p) const; //-------------------------------- }; /// project a point from 3d CAMERA space to the camera's plane] template vcg::Point2 Camera::Project(const vcg::Point3 & p) const { vcg::Point2 q = Point2(p[0],p[1]); if(!IsOrtho()) { q[0] *= FocalMm/p.Z(); q[1] *= FocalMm/p.Z(); } return q; } /// unproject a point from the camera 2d plane [-1,-1]x[1,1] (plus depth) to 3d CAMERA space template vcg::Point3 Camera::UnProject(const vcg::Point2 & p, const S & d) const { vcg::Point3 np = Point3(p[0], p[1], d); if(!IsOrtho()) { np[0] /= FocalMm/d; np[1] /= FocalMm/d; } return np; } /// transforms local plane coords to vieport (pixel) coords template vcg::Point2 Camera::LocalToViewportPx(const vcg::Point2 & p) const { vcg::Point2 np; np[0] = (p[0] / PixelSizeMm.X()) + CenterPx.X(); np[1] = (p[1] / PixelSizeMm.Y()) + CenterPx.Y(); return np; } /// transforms vieport (pixel) coords to local plane coords template vcg::Point2 Camera::ViewportPxToLocal(const vcg::Point2 & p) const { vcg::Point2 ps; ps[0] = (p[0]-CenterPx.X()) * PixelSizeMm.X(); ps[1] = (p[1]-CenterPx.Y()) * PixelSizeMm.Y(); return ps; } /// transforms local plane coords to [0-1] coords template vcg::Point2 Camera::LocalTo_0_1(const vcg::Point2 & p) const { vcg::Point2 ps; ps[0] = ( p[0]/PixelSizeMm.X() + CenterPx.X() ) / (S)ViewportPx[0]; ps[1] = ( p[1]/PixelSizeMm.Y() + CenterPx.Y() ) / (S)ViewportPx[1]; return ps; } /// transforms local plane coords to [-1 1] coords template vcg::Point2 Camera::LocalTo_neg1_1(const vcg::Point2 & p) const { vcg::Point2 ps; ps[0] = 2.0f * p[0] / ( PixelSizeMm.X() * (S)ViewportPx[0] ); ps[1] = 2.0f * p[1] / ( PixelSizeMm.Y() * (S)ViewportPx[1] ); return ps; } //--- basic camera setup (GL-like) /// set the camera specifying the perspective view template void Camera::SetPerspective( S AngleDeg, S AspectRatio, S Focal, vcg::Point2 Viewport) { cameraType = PERSPECTIVE; S halfsize[2]; halfsize[1] = tan(math::ToRad(AngleDeg/2.0f)) * Focal; halfsize[0] = halfsize[1]*AspectRatio; SetFrustum(-halfsize[0],halfsize[0],-halfsize[1],halfsize[1],Focal,Viewport); } /// set the camera specifying the frustum view template void Camera::SetFrustum( S sx, S dx, S bt, S tp, S Focal, vcg::Point2 Viewport) { S vp[2]; vp[0] = dx-sx; vp[1] = tp-bt; ViewportPx[0] = Viewport[0]; if(vp[1] != -1) ViewportPx[1] = Viewport[1]; // the user specified the viewport else ViewportPx[1] = ViewportPx[0]; // default viewport PixelSizeMm[0] = vp[0] / (S)Viewport[0]; PixelSizeMm[1] = vp[1] / (S)Viewport[1]; CenterPx[0] = -sx/vp[0] * (S)Viewport[0]; CenterPx[1] = -bt/vp[1] * (S)Viewport[1]; FocalMm =Focal; } //--- special cameras setup /// set the camera specifying the cavalieri view template void Camera::SetCavalieri(S sx, S dx, S bt, S tp, S Focal, vcg::Point2 Viewport) { cameraType = CAVALIERI; SetFrustum(sx, dx, bt, tp, Focal,Viewport); } /// set the camera specifying the isometric view template void Camera::SetIsometric(S sx, S dx, S bt, S tp, S Focal, vcg::Point2 Viewport) { cameraType = ISOMETRIC; SetFrustum(sx, dx, bt, tp, Focal,Viewport); } /// returns the frustum template void Camera:: GetFrustum( S & sx, S & dx, S & bt, S & tp, S & nr) { dx = CenterPx.X()* PixelSizeMm.X(); //scaled center sx = -( (S)ViewportPx.X() - CenterPx.X() ) * PixelSizeMm.X(); bt = -CenterPx.Y()* PixelSizeMm.Y(); tp = ( (S)ViewportPx.Y() - CenterPx.Y() ) * PixelSizeMm.Y(); nr = FocalMm; } } #endif qutemol/vcg/vcg/math/matrix33.h0000444000175000017500000004117110737217001014736 0ustar mbamba/**************************************************************************** * VCGLib o o * * Visual and Computer Graphics Library o o * * _ O _ * * Copyright(C) 2004 \/)\/ * * Visual Computing Lab /\/| * * ISTI - Italian National Research Council | * * \ * * All rights reserved. * * * * 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. * * * * 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 (http://www.gnu.org/licenses/gpl.txt) * * for more details. * * * ****************************************************************************/ /**************************************************************************** History $Log: matrix33.h,v $ Revision 1.19 2008/01/03 17:40:17 ganovelli added RandomRotation Revision 1.18 2007/04/19 14:30:26 pietroni added RotationMatrix method to calculate rotation matrix along an axis Revision 1.17 2007/04/07 23:06:47 pietroni Added function RotationMatrix Revision 1.16 2007/01/29 00:20:25 pietroni -Used scalar type passed as template argument istead of double to prevent warnings.. in Rotate function Revision 1.15 2006/09/25 23:05:29 ganovelli added constructor from matrix44 excluding a row and colum Revision 1.14 2006/06/22 08:00:05 ganovelli bug in operator + with MatrixxDig Revision 1.13 2006/01/20 16:41:44 pietroni added operators: operator -= ( const Matrix33Diag &p ) Matrix33 operator - ( const Matrix33Diag &p ) Matrix33 operator + ( const Matrix33 &m ) Matrix33 operator + ( const Matrix33Diag &p ) Revision 1.12 2005/11/14 10:28:25 cignoni Changed Invert -> FastInvert for the function based on the maple expansion Revision 1.11 2005/10/13 15:45:23 ponchio Changed a Zero in SetZero in WeightedCrossCovariance() (again) Revision 1.10 2005/10/05 17:06:12 pietroni corrected sintax error on singular value decomposition Revision 1.9 2005/09/29 09:53:58 ganovelli added inverse by SVD Revision 1.8 2005/06/10 14:51:54 cignoni Changed a Zero in SetZero in WeightedCrossCovariance() Revision 1.7 2005/06/10 11:46:49 pietroni Added Norm Function Revision 1.6 2005/06/07 14:29:56 ganovelli changed from Matrix33Ide to MatrixeeDiag Revision 1.5 2005/05/23 15:05:26 ganovelli Matrix33Diag Added: it implements diagonal matrix. Added only operator += in Matrix33 Revision 1.4 2005/04/11 14:11:22 pietroni changed swap to math::Swap in Traspose Function Revision 1.3 2004/10/18 15:03:02 fiorin Updated interface: all Matrix classes have now the same interface Revision 1.2 2004/07/13 06:48:26 cignoni removed uppercase references in include Revision 1.1 2004/05/28 13:09:05 ganovelli created Revision 1.1 2004/05/28 13:00:39 ganovelli created ****************************************************************************/ #ifndef __VCGLIB_MATRIX33_H #define __VCGLIB_MATRIX33_H #include #include #include #include #include namespace vcg { template class Matrix33Diag:public Point3{ public: /** @name Matrix33 Class Matrix33Diag. This is the class for definition of a diagonal matrix 3x3. @param S (Templete Parameter) Specifies the ScalarType field. */ Matrix33Diag(const S & p0,const S & p1,const S & p2):Point3(p0,p1,p2){}; Matrix33Diag(const Point3&p ):Point3(p){}; }; template /** @name Matrix33 Class Matrix33. This is the class for definition of a matrix 3x3. @param S (Templete Parameter) Specifies the ScalarType field. */ class Matrix33 { public: typedef S ScalarType; /// Default constructor inline Matrix33() {} /// Copy constructor Matrix33( const Matrix33 & m ) { for(int i=0;i<9;++i) a[i] = m.a[i]; } /// create from array Matrix33( const S * v ) { for(int i=0;i<9;++i) a[i] = v[i]; } /// create from Matrix44 excluding row and column k Matrix33 (const Matrix44 & m, const int & k) { int i,j, r=0, c=0; for(i = 0; i< 4;++i)if(i!=k){c=0; for(j=0; j < 4;++j)if(j!=k) { (*this)[r][c] = m[i][j]; ++c;} ++r; } } /// Number of columns inline unsigned int ColumnsNumber() const { return 3; }; /// Number of rows inline unsigned int RowsNumber() const { return 3; }; /// Assignment operator Matrix33 & operator = ( const Matrix33 & m ) { for(int i=0;i<9;++i) a[i] = m.a[i]; return *this; } /// Operatore di indicizzazione inline S * operator [] ( const int i ) { return a+i*3; } /// Operatore const di indicizzazione inline const S * operator [] ( const int i ) const { return a+i*3; } /// Modificatore somma per matrici 3x3 Matrix33 & operator += ( const Matrix33 &m ) { for(int i=0;i<9;++i) a[i] += m.a[i]; return *this; } /// Modificatore somma per matrici 3x3 Matrix33 & operator += ( const Matrix33Diag &p ) { a[0] += p[0]; a[4] += p[1]; a[8] += p[2]; return *this; } /// Modificatore sottrazione per matrici 3x3 Matrix33 & operator -= ( const Matrix33 &m ) { for(int i=0;i<9;++i) a[i] -= m.a[i]; return *this; } /// Modificatore somma per matrici 3x3 Matrix33 & operator -= ( const Matrix33Diag &p ) { a[0] -= p[0]; a[4] -= p[1]; a[8] -= p[2]; return *this; } /// Modificatore divisione per scalare Matrix33 & operator /= ( const S &s ) { for(int i=0;i<9;++i) a[i] /= s; return *this; } /// Modificatore prodotto per matrice Matrix33 operator * ( const Matrix33< S> & t ) const { Matrix33 r; int i,j; for(i=0;i<3;++i) for(j=0;j<3;++j) r[i][j] = (*this)[i][0]*t[0][j] + (*this)[i][1]*t[1][j] + (*this)[i][2]*t[2][j]; return r; } /// Modificatore prodotto per matrice void operator *=( const Matrix33< S> & t ) { int i,j; for(i=0;i<3;++i) for(j=0;j<3;++j) (*this)[i][j] = (*this)[i][0]*t[0][j] + (*this)[i][1]*t[1][j] + (*this)[i][2]*t[2][j]; } /// Dot product with a diagonal matrix Matrix33 operator * ( const Matrix33Diag< S> & t ) const { Matrix33 r; int i,j; for(i=0;i<3;++i) for(j=0;j<3;++j) r[i][j] = (*this)[i][j]*t[j]; return r; } /// Dot product modifier with a diagonal matrix void operator *=( const Matrix33Diag< S> & t ) { int i,j; for(i=0;i<3;++i) for(j=0;j<3;++j) (*this)[i][j] = (*this)[i][j]*t[j]; } /// Modificatore prodotto per costante Matrix33 & operator *= ( const S t ) { for(int i=0;i<9;++i) a[i] *= t; return *this; } /// Operatore prodotto per costante Matrix33 operator * ( const S t ) { Matrix33 r; for(int i=0;i<9;++i) r.a[i] = a[i]* t; return r; } /// Operatore sottrazione per matrici 3x3 Matrix33 operator - ( const Matrix33 &m ) { Matrix33 r; for(int i=0;i<9;++i) r.a[i] = a[i] - m.a[i]; return r; } /// Operatore sottrazione di matrici 3x3 con matrici diagonali Matrix33 operator - ( const Matrix33Diag &p ) { Matrix33 r=a; r[0][0] -= p[0]; r[1][1] -= p[1]; r[2][2] -= p[2]; return r; } /// Operatore sottrazione per matrici 3x3 Matrix33 operator + ( const Matrix33 &m ) { Matrix33 r; for(int i=0;i<9;++i) r.a[i] = a[i] + m.a[i]; return r; } /// Operatore addizione di matrici 3x3 con matrici diagonali Matrix33 operator + ( const Matrix33Diag &p ) { Matrix33 r=(*this); r[0][0] += p[0]; r[1][1] += p[1]; r[2][2] += p[2]; return r; } /** Operatore per il prodotto matrice-vettore. @param v A point in $R^{3}$ @return Il vettore risultante in $R^{3}$ */ Point3 operator * ( const Point3 & v ) const { Point3 t; t[0] = a[0]*v[0] + a[1]*v[1] + a[2]*v[2]; t[1] = a[3]*v[0] + a[4]*v[1] + a[5]*v[2]; t[2] = a[6]*v[0] + a[7]*v[1] + a[8]*v[2]; return t; } void OuterProduct(Point3 const &p0, Point3 const &p1) { Point3 row; row = p1*p0[0]; a[0] = row[0];a[1] = row[1];a[2] = row[2]; row = p1*p0[1]; a[3] = row[0]; a[4] = row[1]; a[5] = row[2]; row = p1*p0[2]; a[6] = row[0];a[7] = row[1];a[8] = row[2]; } void SetZero() { for(int i=0;i<9;++i) a[i] =0; } void SetIdentity() { for(int i=0;i<9;++i) a[i] =0; a[0]=a[4]=a[8]=1.0; } void Rotate(S angle, const Point3 & axis ) { angle = angle*(S)3.14159265358979323846/180; S c = cos(angle); S s = sin(angle); S q = 1-c; Point3 t = axis; t.Normalize(); a[0] = t[0]*t[0]*q + c; a[1] = t[0]*t[1]*q - t[2]*s; a[2] = t[0]*t[2]*q + t[1]*s; a[3] = t[1]*t[0]*q + t[2]*s; a[4] = t[1]*t[1]*q + c; a[5] = t[1]*t[2]*q - t[0]*s; a[6] = t[2]*t[0]*q -t[1]*s; a[7] = t[2]*t[1]*q +t[0]*s; a[8] = t[2]*t[2]*q +c; } /// Funzione per eseguire la trasposta della matrice Matrix33 & Transpose() { math::Swap(a[1],a[3]); math::Swap(a[2],a[6]); math::Swap(a[5],a[7]); return *this; } /// Funzione per costruire una matrice diagonale dati i tre elem. Matrix33 & SetDiagonal(S *v) {int i,j; for(i=0;i<3;i++) for(j=0;j<3;j++) if(i==j) (*this)[i][j] = v[i]; else (*this)[i][j] = 0; return *this; } /// Assegna l'n-simo vettore colonna void SetColumn(const int n, S* v){ assert( (n>=0) && (n<3) ); a[n]=v[0]; a[n+3]=v[1]; a[n+6]=v[2]; }; /// Assegna l'n-simo vettore riga void SetRow(const int n, S* v){ assert( (n>=0) && (n<3) ); int m=n*3; a[m]=v[0]; a[m+1]=v[1]; a[m+2]=v[2]; }; /// Assegna l'n-simo vettore colonna void SetColumn(const int n, const Point3 v){ assert( (n>=0) && (n<3) ); a[n]=v[0]; a[n+3]=v[1]; a[n+6]=v[2]; }; /// Assegna l'n-simo vettore riga void SetRow(const int n, const Point3 v){ assert( (n>=0) && (n<3) ); int m=n*3; a[m]=v[0]; a[m+1]=v[1]; a[m+2]=v[2]; }; /// Restituisce l'n-simo vettore colonna Point3 GetColumn(const int n) const { assert( (n>=0) && (n<3) ); Point3 t; t[0]=a[n]; t[1]=a[n+3]; t[2]=a[n+6]; return t; }; /// Restituisce l'n-simo vettore riga Point3 GetRow(const int n) const { assert( (n>=0) && (n<3) ); Point3 t; int m=n*3; t[0]=a[m]; t[1]=a[m+1]; t[2]=a[m+2]; return t; }; /// Funzione per il calcolo del determinante S Determinant() const { return a[0]*(a[4]*a[8]-a[5]*a[7]) - a[1]*(a[3]*a[8]-a[5]*a[6]) + a[2]*(a[3]*a[7]-a[4]*a[6]) ; } // Warning, this Inversion code can be HIGHLY NUMERICALLY UNSTABLE! // In most case you are advised to use the Invert() method based on SVD decomposition. Matrix33 & FastInvert() { // Maple produsse: S t4 = a[0]*a[4]; S t6 = a[0]*a[5]; S t8 = a[1]*a[3]; S t10 = a[2]*a[3]; S t12 = a[1]*a[6]; S t14 = a[2]*a[6]; S t17 = 1/(t4*a[8]-t6*a[7]-t8*a[8]+t10*a[7]+t12*a[5]-t14*a[4]); S a0 = a[0]; S a1 = a[1]; S a3 = a[3]; S a4 = a[4]; a[0] = (a[4]*a[8]-a[5]*a[7])*t17; a[1] = -(a[1]*a[8]-a[2]*a[7])*t17; a[2] = (a1 *a[5]-a[2]*a[4])*t17; a[3] = -(a[3]*a[8]-a[5]*a[6])*t17; a[4] = (a0 *a[8]-t14 )*t17; a[5] = -(t6 - t10)*t17; a[6] = (a3 *a[7]-a[4]*a[6])*t17; a[7] = -(a[0]*a[7]-t12)*t17; a[8] = (t4-t8)*t17; return *this; } void show(FILE * fp) { for(int i=0;i<3;++i) printf("| %g \t%g \t%g |\n",a[3*i+0],a[3*i+1],a[3*i+2]); } // return the Trace of the matrix i.e. the sum of the diagonal elements S Trace() const { return a[0]+a[4]+a[8]; } /* compute the matrix generated by the product of a * b^T */ void ExternalProduct(const Point3 &a, const Point3 &b) { for(int i=0;i<3;++i) for(int j=0;j<3;++j) (*this)[i][j] = a[i]*b[j]; } /* Compute the Frobenius Norm of the Matrix */ ScalarType Norm() { ScalarType SQsum=0; for(int i=0;i<3;++i) for(int j=0;j<3;++j) SQsum += a[i]*a[i]; return (math::Sqrt(SQsum)); } /* It compute the cross covariance matrix of two set of 3d points P and X; it returns also the barycenters of P and X. fonte: Besl, McKay A method for registration o f 3d Shapes IEEE TPAMI Vol 14, No 2 1992 */ template void CrossCovariance(const STLPOINTCONTAINER &P, const STLPOINTCONTAINER &X, Point3 &bp, Point3 &bx) { SetZero(); assert(P.size()==X.size()); bx.Zero(); bp.Zero(); Matrix33 tmp; typename std::vector >::const_iterator pi,xi; for(pi=P.begin(),xi=X.begin();pi!=P.end();++pi,++xi){ bp+=*pi; bx+=*xi; tmp.ExternalProduct(*pi,*xi); (*this)+=tmp; } bp/=P.size(); bx/=X.size(); (*this)/=P.size(); tmp.ExternalProduct(bp,bx); (*this)-=tmp; } template void WeightedCrossCovariance(const STLREALCONTAINER & weights, const STLPOINTCONTAINER &P, const STLPOINTCONTAINER &X, Point3 &bp, Point3 &bx) { SetZero(); assert(P.size()==X.size()); bx.Zero(); bp.Zero(); Matrix33 tmp; typename std::vector >::const_iterator pi,xi; typename STLREALCONTAINER::const_iterator pw; for(pi=P.begin(),xi=X.begin();pi!=P.end();++pi,++xi){ bp+=(*pi); bx+=(*xi); } bp/=P.size(); bx/=X.size(); for(pi=P.begin(),xi=X.begin(),pw = weights.begin();pi!=P.end();++pi,++xi,++pw){ tmp.ExternalProduct(((*pi)-(bp)),((*xi)-(bp))); (*this)+=tmp*(*pw); } } private: S a[9]; }; template void Invert(Matrix33 &m) { Matrix33 v; Point3::ScalarType> e; SingularValueDecomposition(m,&e[0],v); e[0]=1/e[0];e[1]=1/e[1];e[2]=1/e[2]; m.Transpose(); m = v * Matrix33Diag(e) * m; } template Matrix33 Inverse(const Matrix33&m) { Matrix33 v,m_copy=m; Point3 e; SingularValueDecomposition(m_copy,&e[0],v); m_copy.Transpose(); e[0]=1/e[0];e[1]=1/e[1];e[2]=1/e[2]; return v * Matrix33Diag(e) * m_copy; } ///given 2 vector centered into origin calculate the rotation matrix from first to the second template Matrix33 RotationMatrix(vcg::Point3 v0,vcg::Point3 v1,bool normalized=true) { typedef typename vcg::Point3 CoordType; Matrix33 rotM; const S epsilon=0.00001; if (!normalized) { v0.Normalize(); v1.Normalize(); } S dot=(v0*v1); ///control if there is no rotation if (dot>((S)1-epsilon)) { rotM.SetIdentity(); return rotM; } ///find the axis of rotation CoordType axis; axis=v0^v1; axis.Normalize(); ///construct rotation matrix S u=axis.X(); S v=axis.Y(); S w=axis.Z(); S phi=acos(dot); S rcos = cos(phi); S rsin = sin(phi); rotM[0][0] = rcos + u*u*(1-rcos); rotM[1][0] = w * rsin + v*u*(1-rcos); rotM[2][0] = -v * rsin + w*u*(1-rcos); rotM[0][1] = -w * rsin + u*v*(1-rcos); rotM[1][1] = rcos + v*v*(1-rcos); rotM[2][1] = u * rsin + w*v*(1-rcos); rotM[0][2] = v * rsin + u*w*(1-rcos); rotM[1][2] = -u * rsin + v*w*(1-rcos); rotM[2][2] = rcos + w*w*(1-rcos); return rotM; } ///return the rotation matrix along axis template Matrix33 RotationMatrix(const vcg::Point3 &axis, const float &angleRad) { vcg::Matrix44 matr44; vcg::Matrix33 matr33; matr44.SetRotate(angleRad,axis); for (int i=0;i<3;i++) for (int j=0;j<3;j++) matr33[i][j]=matr44[i][j]; return matr33; } /// return a random rotation matrix, from the paper: /// Fast Random Rotation Matrices, James Arvo /// Graphics Gems III pp. 117-120 template Matrix33 RandomRotation(){ S x1,x2,x3; Matrix33 R,H,M,vv; Point3 v; R.SetIdentity(); H.SetIdentity(); x1 = rand()/S(RAND_MAX); x2 = rand()/S(RAND_MAX); x3 = rand()/S(RAND_MAX); R[0][0] = cos(S(2)*M_PI*x1); R[0][1] = sin(S(2)*M_PI*x1); R[1][0] = - R[0][1]; R[1][1] = R[0][0]; v[0] = cos(2.0 * M_PI * x2)*sqrt(x3); v[1] = sin(2.0 * M_PI * x2)*sqrt(x3); v[2] = sqrt(1-x3); vv.OuterProduct(v,v); H -= vv*S(2); M = H*R*S(-1); return M; } /// typedef Matrix33 Matrix33s; typedef Matrix33 Matrix33i; typedef Matrix33 Matrix33f; typedef Matrix33 Matrix33d; } // end of namespace #endif qutemol/vcg/vcg/math/random_generator.h0000444000175000017500000000640110272076133016612 0ustar mbamba/*#*************************************************************************** * RandomGenerator.h o o * * o o * * Visual Computing Group _ O _ * * IEI Institute, CNUCE Institute, CNR Pisa \/)\/ * * /\/| * * Copyright(C) 1999 by Paolo Cignoni, Paolo Pingi, Claudio Rocchini | * * All rights reserved. \ * * * * Permission to use, copy, modify, distribute and sell this software and * * its documentation for any purpose is hereby granted without fee, provided * * that the above copyright notice appear in all copies and that both that * * copyright notice and this permission notice appear in supporting * * documentation. the author makes no representations about the suitability * * of this software for any purpose. It is provided "as is" without express * * or implied warranty. * * * *****************************************************************************/ /**************************************************************************** History $Log: random_generator.h,v $ Revision 1.1 2005/07/28 06:34:03 cignoni First working version *****************************************************************************/ // RandomGenerator is derived from a STL extension of sgi: // it is based on the Subtractive Ring method. // See section 3.6 of Knuth for an implementation of the subtractive method in FORTRAN. // Section 3.2.2 of Knuth analyzes this class of algorithms. // (D. E. Knuth, The Art of Computer Programming. Volume 2: Seminumerical Algorithms, second edition. Addison-Wesley, 1981.) . // Note: this code assumes that int is 32 bits. #ifndef __VCG_RandomGenerator #define __VCG_RandomGenerator namespace vcg { namespace math { class RandomGenerator : public std::unary_function { private: unsigned int _M_table[55]; size_t _M_index1; size_t _M_index2; public: unsigned int operator()(unsigned int __limit) { _M_index1 = (_M_index1 + 1) % 55; _M_index2 = (_M_index2 + 1) % 55; _M_table[_M_index1] = _M_table[_M_index1] - _M_table[_M_index2]; return _M_table[_M_index1] % __limit; } void _M_initialize(unsigned int __seed) { unsigned int __k = 1; _M_table[54] = __seed; size_t __i; for (__i = 0; __i < 54; __i++) { size_t __ii = (21 * (__i + 1) % 55) - 1; _M_table[__ii] = __k; __k = __seed - __k; __seed = _M_table[__ii]; } for (int __loop = 0; __loop < 4; __loop++) { for (__i = 0; __i < 55; __i++) _M_table[__i] = _M_table[__i] - _M_table[(1 + __i + 30) % 55]; } _M_index1 = 0; _M_index2 = 31; } RandomGenerator(unsigned int __seed) { _M_initialize(__seed); } RandomGenerator() { _M_initialize(161803398u); } }; } // end namespace math } // end namespace vcg #endifqutemol/vcg/vcg/simplex/0000755000175000017500000000000011633404241013641 5ustar mbambaqutemol/vcg/vcg/simplex/vertex/0000755000175000017500000000000011633404241015156 5ustar mbambaqutemol/vcg/vcg/simplex/vertex/base.h0000444000175000017500000006054510575271660016264 0ustar mbamba/**************************************************************************** * VCGLib o o * * Visual and Computer Graphics Library o o * * _ O _ * * Copyright(C) 2004 \/)\/ * * Visual Computing Lab /\/| * * ISTI - Italian National Research Council | * * \ * * All rights reserved. * * * * 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. * * * * 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 (http://www.gnu.org/licenses/gpl.txt) * * for more details. * * * ****************************************************************************/ /**************************************************************************** History $Log: base.h,v $ Revision 1.31 2007/03/12 15:37:20 tarini Texture coord name change! "TCoord" and "Texture" are BAD. "TexCoord" is GOOD. Revision 1.30 2007/02/26 14:21:44 turini VTb moved to VTp Revision 1.29 2007/02/20 14:08:34 ganovelli added QualityType to comply vertexplus type Revision 1.28 2006/08/23 15:34:20 marfr960 added minimal comments Revision 1.26 2005/11/12 18:41:14 cignoni Added HasFlags and initialization of flags at construction. Revision 1.25 2005/10/14 13:25:50 cignoni Added cVFp member Revision 1.24 2005/10/06 14:26:39 pietroni added getBBox method Revision 1.23 2005/03/18 16:38:36 fiorin Minor changes Revision 1.22 2005/03/18 00:13:45 cignoni Removed NormalizedNormalV (out of standard and wrong) and added the member functions Normal and NormalizedNormal() (just like for faces) Revision 1.21 2004/10/28 00:50:49 cignoni Better Doxygen documentation Revision 1.20 2004/10/11 17:45:05 ganovelli added template on corrdinate type (default Point3) Revision 1.19 2004/09/28 15:24:56 fiorin DUMMY classes definition moved into vcg namespace Revision 1.18 2004/08/25 15:15:27 ganovelli minor changes to comply gcc compiler (typename's and stuff) Revision 1.17 2004/07/20 15:24:53 pietroni corrected NormalizedNormalV function... Revision 1.16 2004/07/15 11:25:01 ganovelli VFb moved to VFp, userbit to bitflag,setV, inclusion of pos.h Revision 1.15 2004/07/15 10:13:48 pietroni adde NormalizedNormalV funtion to compute the normal on a vertex Revision 1.14 2004/05/13 22:44:40 ganovelli syntax error (typo) Revision 1.13 2004/05/13 22:40:02 ganovelli default template parameters Revision 1.12 2004/05/13 12:49:22 pietroni no default template parameters... each one must be specified Revision 1.12 2004/05/10 13:31:13 ganovelli function for edge adjacency added $Log: base.h,v $ Revision 1.31 2007/03/12 15:37:20 tarini Texture coord name change! "TCoord" and "Texture" are BAD. "TexCoord" is GOOD. Revision 1.30 2007/02/26 14:21:44 turini VTb moved to VTp Revision 1.29 2007/02/20 14:08:34 ganovelli added QualityType to comply vertexplus type Revision 1.28 2006/08/23 15:34:20 marfr960 added minimal comments Revision 1.26 2005/11/12 18:41:14 cignoni Added HasFlags and initialization of flags at construction. Revision 1.25 2005/10/14 13:25:50 cignoni Added cVFp member Revision 1.24 2005/10/06 14:26:39 pietroni added getBBox method Revision 1.23 2005/03/18 16:38:36 fiorin Minor changes Revision 1.22 2005/03/18 00:13:45 cignoni Removed NormalizedNormalV (out of standard and wrong) and added the member functions Normal and NormalizedNormal() (just like for faces) Revision 1.21 2004/10/28 00:50:49 cignoni Better Doxygen documentation Revision 1.20 2004/10/11 17:45:05 ganovelli added template on corrdinate type (default Point3) Revision 1.19 2004/09/28 15:24:56 fiorin DUMMY classes definition moved into vcg namespace Revision 1.18 2004/08/25 15:15:27 ganovelli minor changes to comply gcc compiler (typename's and stuff) Revision 1.17 2004/07/20 15:24:53 pietroni corrected NormalizedNormalV function... Revision 1.16 2004/07/15 11:25:01 ganovelli VFb moved to VFp, userbit to bitflag,setV, inclusion of pos.h Revision 1.15 2004/07/15 10:13:48 pietroni adde NormalizedNormalV funtion to compute the normal on a vertex Revision 1.14 2004/05/13 22:44:40 ganovelli syntax error (typo) Revision 1.13 2004/05/13 22:40:02 ganovelli default template parameters Revision 1.12 2004/05/13 12:49:22 pietroni no default template parameters... each one must be specified Revision 1.11 2004/05/10 13:31:13 ganovelli function for edge adjacency added Revision 1.10 2004/05/10 13:13:17 cignoni added void to Convert, corrected return object in VFp Revision 1.9 2004/05/06 15:28:10 pietroni changed names to VF topology function (was missed) Revision 1.8 2004/05/05 17:03:25 pietroni changed name to topology functions Revision 1.7 2004/04/28 11:37:14 pietroni *** empty log message *** Revision 1.6 2004/04/26 09:40:15 pietroni *** empty log message *** Revision 1.6 2004/04/23 14:55:06 pietroni conversion funtion Revision 1.5 2004/03/10 00:59:06 cignoni minor changes Revision 1.4 2004/03/03 16:07:57 cignoni Yet another cr lf mismatch Revision 1.3 2004/02/24 21:36:39 cignoni grouped documentation, changed typenames and reflection mechanism Revision 1.2 2004/02/13 02:09:39 cignoni First working release, with doxygen comment structure Revision 1.1 2004/02/10 01:11:28 cignoni Edited Comments and GPL license ****************************************************************************/ #ifndef VERTEX_TYPE #pragma message("\nYou should never directly include this file\_n") #else #include #include #include #include #include namespace vcg { class DUMMYFACETYPE; class DUMMYEDGETYPE; class DUMMYTETRATYPE; /** \addtogroup vertex */ //@{ /*! * This class represent the generic configurable Vertex; * Usually you never direclty use this class with this name but you build * your own type by directly including one of the .h files under the face/with * directory. Each file specify a class type with the desired fields. So for example * including 'vcg/simplex/vertex/with/VCVN.h' allow you to use the class VertVCVN that has per-vertex color and normal stored inside. */ template , class CoordTYPE= Point3 > class VERTEX_TYPE { public: /// The scalar type used to represent coords (i.e. float, double, ...) typedef FLTYPE ScalarType; /// The coordinate type used to represent the point (i.e. Point3f, Point3d, ...) typedef CoordTYPE CoordType; typedef Point3 NormalType; /// The type base of the vertex, useful for recovering the original typename after user subclassing typedef VERTEX_TYPE BaseVertexType; /// The type of the face pointed by the vertex if vertex edge topology is present typedef VETYPE EdgeType; /// The type base of the vertex, useful for recovering the original typename after user subclassing typedef VFTYPE FaceType; /// The type of the quality (same as scalar) typedef ScalarType QualityType; /***********************************************/ /** @name Vertex Coords blah blah **/ //@{ protected: /// Spatial coordinates of the vertex CoordType _p; public: /// Return the spatial coordinate of the vertex inline CoordType & P() { assert( (_flags & DELETED) == 0 ); assert( (_flags & NOTREAD) == 0 ); assert( (_flags & NOTWRITE) == 0 ); return _p; } /// Return the constant spatial coordinate of the vertex inline const CoordType & P() const { assert( (_flags & DELETED) == 0 ); assert( (_flags & NOTREAD) == 0 ); return _p; } /// Return the constant spatial coordinate of the vertex inline const CoordType & cP() const { assert( (_flags & DELETED) == 0 ); assert( (_flags & NOTREAD) == 0 ); return _p; } /// Return the spatial coordinate of the vertex, senza effettuare controlli sul flag inline CoordType & UberP() { return _p; } /// Return the constant spatial coordinate of the vertex, senza effettuare controlli sul flag inline const CoordType & UberP() const { return _p; } //@} /***********************************************/ /** @name Vertex Flags For each vertex we store a set of boolean values packed in a int. The default value for each flag is 0. Most commonly used flags are the \a deleted and the \a selected ones. Users can ask and dispose for a bit for their own purposes with the vcg::VertexFull::NewUserBit() and vcg::VertexFull::DeleteUserBit() functions. The value returned by these functions has to be passed to the vcg::VertexFull::SetUserBit() vcg::VertexFull::ClearUserBit() and vcg::VertexFull::IsUserBit() functions to check and modify the obtained bit flag. **/ //@{ protected: /// This are the flags of vertex, the default (reasonable) value is 0 int _flags; public: /// Return the vector of _flags inline int & Flags () { assert( (_flags & DELETED) == 0 ); assert( (_flags & NOTREAD) == 0 ); return _flags; } /// Return the vector of _flags, senza effettuare controlli sui bit inline int & UberFlags () { return _flags; } inline const int UberFlags() const { return _flags; } /// checks if the vertex is deleted bool IsD() const {return (_flags & DELETED) != 0;} /// checks if the vertex is readable bool IsR() const {return (_flags & NOTREAD) == 0;} /// checks if the vertex is modifiable bool IsW() const {return (_flags & NOTWRITE)== 0;} /// This funcion checks whether the vertex is both readable and modifiable bool IsRW() const {return (_flags & (NOTREAD | NOTWRITE)) == 0;} /// checks if the vertex is Modified bool IsS() const {return (_flags & SELECTED) != 0;} /// checks if the vertex is readable bool IsB() const {return (_flags & BORDER) != 0;} /// checks if the vertex is visited bool IsV() const {return (_flags & VISITED) != 0;} /** Set the flag value @param flagp Valore da inserire nel flag */ void SetFlags(int flagp) {_flags=flagp;} /** Set the flag value @param flagp Valore da inserire nel flag */ void ClearFlags() {_flags=0;} /// deletes the vertex from the mesh void SetD() {_flags |=DELETED;} /// un-delete a vertex void ClearD() {_flags &=(~DELETED);} /// marks the vertex as readable void SetR() {_flags &=(~NOTREAD);} /// marks the vertex as not readable void ClearR() {_flags |=NOTREAD;} /// marks the vertex as writable void ClearW() {_flags |=NOTWRITE;} /// marks the vertex as not writable void SetW() {_flags &=(~NOTWRITE);} /// select the vertex void SetS() {_flags |=SELECTED;} /// Un-select a vertex void ClearS() {_flags &= ~SELECTED;} /// Set vertex as ob border void SetB() {_flags |=BORDER;} void ClearB() {_flags &=~BORDER;} /// checks if the vertex is visited void ClearV() {_flags &= ~VISITED;} /// checks if the vertex is visited void SetV() {_flags |=VISITED;} /// Return the first bit that is not still used static int &LastBitFlag() { static int b =USER0; return b; } /// allocate a bit among the flags that can be used by user. static inline int NewBitFlag() { LastBitFlag()=LastBitFlag()<<1; return LastBitFlag(); } // de-allocate a bit among the flags that can be used by user. static inline bool DeleteBitFlag(int bitval) { if(LastBitFlag()==bitval) { LastBitFlag()= LastBitFlag()>>1; return true; } assert(0); return false; } /// This function checks if the given user bit is true bool IsUserBit(int userBit){return (_flags & userBit) != 0;} /// This function set the given user bit void SetUserBit(int userBit){_flags |=userBit;} /// This function clear the given user bit void ClearUserBit(int userBit){_flags &= (~userBit);} //@} /*#******************* * Bounding box * **********************/ void GetBBox( Box3 & bb ) const { bb.Set( cP() ); } /***********************************************/ /** @name Vertex Texture Coords blah blah **/ //@{ #ifdef __VCGLIB_VERTEX_VT protected: TCTYPE _t; #endif public: TCTYPE & T() { #ifdef __VCGLIB_VERTEX_VT return _t; #else assert(0); return *(TCTYPE*)(&_flags); #endif } const TCTYPE & T() const { #ifdef __VCGLIB_VERTEX_VT return _t; #else assert(0); return *(TCTYPE*)(&_flags); #endif } //@} /***********************************************/ /** @name Per vertex Color blah blah **/ //@{ #ifdef __VCGLIB_VERTEX_VC protected: Color4b _c; #endif public: Color4b & C() { #ifdef __VCGLIB_VERTEX_VC return _c; #else assert(0); return *(Color4b*)(&_flags); #endif } const Color4b & C() const { #ifdef __VCGLIB_VERTEX_VC return _c; #else return Color4b(Color4b::White); #endif } //@} /***********************************************/ /** @name Vertex Quality blah blah **/ //@{ #ifdef __VCGLIB_VERTEX_VQ protected: float _q; #endif public: float & Q() { #ifdef __VCGLIB_VERTEX_VQ return _q; #else assert(0); return *(float*)(&_flags); #endif } const float & Q() const { #ifdef __VCGLIB_VERTEX_VQ return _q; #else return 1; #endif } //@} /** @name Vertex-Edge Adjacency blah blah **/ //@{ #if ((defined __VCGLIB_VERTEX_EA) || (defined __VCGLIB_VERTEX_EAS)) // Puntatore ad un edge appartenente alla stella del vertice, implementa l'adiacenza vertice-edge protected: EdgeType *_ep; int _ei; #endif public: inline EdgeType * & Ep() { #if ((defined __VCGLIB_VERTEX_EA) || (defined __VCGLIB_VERTEX_EAS)) return _ep; #else assert(0);// you are probably trying to use VF topology in a vertex without it return *((EdgeType **)(_flags)); #endif } inline const EdgeType * & Ep() const { #if ((defined __VCGLIB_VERTEX_EA) || (defined __VCGLIB_VERTEX_EAS)) return _ep; #else assert(0);// you are probably trying to use VF topology in a vertex without it return (EdgeType *)this; #endif } inline int & Ei() { #if ((defined __VCGLIB_VERTEX_EA) || (defined __VCGLIB_VERTEX_EAS)) return _ei; #else assert(0);// you are probably trying to use VF topology in a vertex without it return _flags; #endif } inline const int & Ei() const { #if ((defined __VCGLIB_VERTEX_EA) || (defined __VCGLIB_VERTEX_EAS)) return _ei; #else assert(0);// you are probably trying to use VF topology in a vertex without it return (void *)this; #endif } //@} /***********************************************/ /** @name Vertex-Face Adjacency blah blah **/ //@{ #if ((defined __VCGLIB_VERTEX_AF) || (defined __VCGLIB_VERTEX_AFS)) // Puntatore ad una faccia appartenente alla stella del vertice, implementa l'adiacenza vertice-faccia protected: VFTYPE *_vfb; int _vfi; #endif public: inline VFTYPE * & VFp() { #if ((defined __VCGLIB_VERTEX_AF) || (defined __VCGLIB_VERTEX_AFS)) return _vfb; #else assert(0);// you are probably trying to use VF topology in a vertex without it static VFTYPE *dum; return dum; #endif } inline const VFTYPE * & VFp() const { #if ((defined __VCGLIB_VERTEX_AF) || (defined __VCGLIB_VERTEX_AFS)) return _vfb; #else assert(0);// you are probably trying to use VF topology in a vertex without it return (VFTYPE *)0; #endif } inline const VFTYPE * cVFp() const { #if ((defined __VCGLIB_VERTEX_AF) || (defined __VCGLIB_VERTEX_AFS)) return _vfb; #else assert(0);// you are probably trying to use VF topology in a vertex without it return (VFTYPE *)0; #endif } inline int & VFi() { #if ((defined __VCGLIB_VERTEX_AF) || (defined __VCGLIB_VERTEX_AFS)) return _vfi; #else assert(0);// you are probably trying to use VF topology in a vertex without it return _flags; #endif } inline const int & VFi() const { #if ((defined __VCGLIB_VERTEX_AF) || (defined __VCGLIB_VERTEX_AFS)) return _vfi; #else assert(0);// you are probably trying to use VF topology in a vertex without it return (void *)this; #endif } //@} /***********************************************/ /** @name Vertex-Tetrahedron Adjacency blah blah **/ //@{ #if ((defined __VCGLIB_VERTEX_AT) || (defined __VCGLIB_VERTEX_ATS)) // Pointer to first tetrahedron of the start implements the Vertex-Tetrahedron Topology protected: VTTYPE *_vtp; int _vti; #endif public: inline VTTYPE * & VTp() { #if ((defined __VCGLIB_VERTEX_AT) || (defined __VCGLIB_VERTEX_ATS)) return _vtp; #else assert(0);// you are probably trying to use VF topology in a vertex without it return *((VTTYPE **)(_flags)); #endif } inline const VTTYPE * & VTp() const { #if ((defined __VCGLIB_VERTEX_AT) || (defined __VCGLIB_VERTEX_ATS)) return _vtp; #else assert(0);// you are probably trying to use VF topology in a vertex without it return (VTTYPE *)this; #endif } inline int & VTi() { #if ((defined __VCGLIB_VERTEX_AT) || (defined __VCGLIB_VERTEX_ATS)) return _vti; #else assert(0);// you are probably trying to use VF topology in a vertex without it return _flags; #endif } inline const int & VTi() const { #if ((defined __VCGLIB_VERTEX_AT) || (defined __VCGLIB_VERTEX_ATS)) return _vti; #else assert(0);// you are probably trying to use VF topology in a vertex without it return (void *)this; #endif } //@} /***********************************************/ /** @name Vertex Incremental Mark blah blah **/ //@{ #ifdef __VCGLIB_VERTEX_VM protected: /// The incremental vertex mark int _imark; #endif // Mark public: #ifdef __VCGLIB_VERTEX_VM /// This function return the vertex incremental mark inline int & IMark() { assert( (_flags & DELETED) == 0 ); assert( (_flags & NOTREAD) == 0 ); assert( (_flags & NOTWRITE) == 0 ); return _imark; } /// This function return the constant vertex incremental mark inline const int & IMark() const { assert( (_flags & DELETED) == 0 ); assert( (_flags & NOTREAD) == 0 ); return _imark; } #endif /// Initialize the _imark system of the vertex inline void InitIMark() { #ifdef __VCGLIB_VERTEX_VM _imark = 0; #endif } //@} /***********************************************/ /** @name Vertex Normal blah blah **/ //@{ #ifdef __VCGLIB_VERTEX_VN protected: CoordType _n; #endif public: /// Return the vertex normal inline CoordType & N() { assert( (_flags & DELETED) == 0 ); assert( (_flags & NOTREAD) == 0 ); assert( (_flags & NOTWRITE) == 0 ); #ifdef __VCGLIB_VERTEX_VN return _n; #else assert(0); return *(CoordType *)this; #endif } /// Return the constant vertex normal inline const CoordType & N() const { assert( (_flags & DELETED) == 0 ); assert( (_flags & NOTREAD) == 0 ); #ifdef __VCGLIB_VERTEX_VN return _n; #else assert(0); return *(CoordType *)this; #endif } inline const CoordType cN() const { assert( (_flags & DELETED) == 0 ); assert( (_flags & NOTREAD) == 0 ); #ifdef __VCGLIB_VERTEX_VN return _n; #else return CoordType(0,0,0); #endif } /// Return the Normal of the vertex inline CoordType & UberN() { #ifdef __VCGLIB_VERTEX_VN return _n; #else assert(0); return *(CoordType *)this; #endif } /// Return the constant normal of the vertex inline const CoordType & UberN() const { #ifdef __VCGLIB_VERTEX_VN return _n; #else assert(0); return *(CoordType *)this; #endif } template const CoordType GenericNormal() { if (!HasVFAdjacency()) { assert(0); return (VERTEX_TYPE::CoordType (0,0,0)); } else { vcg::face::VFIterator VFi=vcg::face::VFIterator(); VFi.f=VFp(); VFi.z=VFi(); typename VERTEX_TYPE::CoordType N= typename VERTEX_TYPE::CoordType(0,0,0); while (!VFi.End()) { N+=VFi.f->Normal(); VFi++; } if(NormalizeFlag) N.Normalize(); return N; } } /// Return the un-normalized value of the vertex normal as it correspond to the current geometry. /// It is always computed and never use any stored value. /// REQUIRES vertex-face topology const CoordType Normal() { return GenericNormal(); } /// Return the normalized value of the vertex normal as it correspond to the current geometry. /// It is always computed and never use any stored value. /// REQUIRES vertex-face topology const CoordType NormalizedNormal() { return GenericNormal(); } //@} /***********************************************/ /** @name Reflection Functions Static functions that give information about the current vertex type. Reflection is a mechanism making it possible to investigate yourself. Reflection is used to investigate format of objects at runtime, invoke methods and access fields of these objects. Here we provide static const functions that are resolved at compile time and they give information about the data (normal, color etc.) supported by the current vertex type. **/ //@{ static bool HasFlags() { // Note the plural because ONE vertex has many Flags (but just one color, normal, mark, quality ecc.) return true; } static bool HasNormal() { #ifdef __VCGLIB_VERTEX_VN return true; #else return false; #endif } static bool HasColor() { #ifdef __VCGLIB_VERTEX_VC return true; #else return false; #endif } static bool HasMark() { #ifdef __VCGLIB_VERTEX_VM return true; #else return false; #endif } static bool HasQuality() { #ifdef __VCGLIB_VERTEX_VQ return true; #else return false; #endif } static bool HasTexCoord() { #ifdef __VCGLIB_VERTEX_VT return true; #else return false; #endif } static bool HasVFAdjacency() { #ifdef __VCGLIB_VERTEX_AF return true; #else return false; #endif } static bool HasVTAdjacency() { #ifdef __VCGLIB_VERTEX_AT return true; #else return false; #endif } static bool HasVEAdjacency() { #ifdef __VCGLIB_VERTEX_EA return true; #else return false; #endif } //@} /***********************************************/ /** @Conversion to other vertex **/ //@{ template inline void Convert( VERT_TYPE &v ) { P()=v.P(); Flags()=v.Flags(); if ((HasNormal())&&(v.HasNormal())) N()=v.N(); if ((HasColor())&&(v.HasColor())) C()=v.C(); #ifdef __VCGLIB_VERTEX_VM if ((HasMark())&&(v.HasMark())) IMark()=v.IMark(); #endif if ((HasQuality())&&(v.HasQuality())) Q()=v.Q(); if ((HasTexCoord())&&(v.HasTexCoord())) T()=v.T(); } //@} enum { // This bit indicate that the vertex is deleted from the mesh DELETED = 0x0001, // cancellato // This bit indicate that the vertex of the mesh is not readable NOTREAD = 0x0002, // non leggibile (ma forse modificabile) // This bit indicate that the vertex is not modifiable NOTWRITE = 0x0004, // non modificabile (ma forse leggibile) // This bit indicate that the vertex is modified MODIFIED = 0x0008, // modificato // This bit can be used to mark the visited vertex VISITED = 0x0010, // Visited // This bit can be used to select SELECTED = 0x0020, // Selection flag // Border Flag BORDER = 0x0100, // First user bit USER0 = 0x0200 // Fisrt user bit }; /** Return the i-th spatial value of the vertex coordinate. @param i Index of the spatial vertex coordinate (x=0 y=1 z=2). */ inline ScalarType & operator [] ( const int i ){ assert(i>=0 && i<3); return P().V(i); } /** Return the i-th spatial value of the const vertex coordinate. @param i Index of the spatial vertex coordinate (x=0 y=1 z=2). */ inline const FLTYPE & operator [] ( const int i ) const { assert(i>=0 && i<3); return P().V(i); } /// Operator to compare two vertices using lexicographic order inline bool operator < ( const VERTEX_TYPE & ve) const { return _p < ve._p; } inline VERTEX_TYPE() { //#ifdef _DEBUG _flags=0; //#endif }; }; //@} } // end namespace #endif qutemol/vcg/vcg/simplex/vertex/vertex.h0000444000175000017500000000077610575271660016667 0ustar mbamba#ifndef __VCGLIB_VERTEX__BASE__TYPE #define __VCGLIB_VERTEX__BASE__TYPE #define VERTEX_TYPE Vertex #include #undef VERTEX_TYPE namespace vcg { template < class VETYPE, class VFTYPE, class VTTYPE,class TCTYPE = TexCoord2, class CoordTYPE= Point3 > class Vertexf : public Vertex {}; template < class VETYPE, class VFTYPE, class VTTYPE> class Vertexd : public Vertex {}; } #endif qutemol/vcg/vcg/simplex/vertex/with/0000755000175000017500000000000011633404241016131 5ustar mbambaqutemol/vcg/vcg/simplex/vertex/with/vnvt.h0000444000175000017500000000104710740400220017266 0ustar mbamba#ifndef __VCGLIB_VERTEX__VNVT__TYPE #define __VCGLIB_VERTEX__VNVT__TYPE #define VERTEX_TYPE VertexVNVT #define __VCGLIB_VERTEX_VN #define __VCGLIB_VERTEX_VT #include #undef VERTEX_TYPE #undef __VCGLIB_VERTEX_VN #undef __VCGLIB_VERTEX_VT namespace vcg { template < class VETYPE, class VFTYPE, class VTTYPE> class VertexVNVTf : public VertexVNVT {}; template < class VETYPE, class VFTYPE, class VTTYPE> class VertexVNVTd : public VertexVNVT {}; } #endif qutemol/vcg/vcg/simplex/vertex/with/afvn.h0000444000175000017500000000105010050667346017237 0ustar mbamba#ifndef __VCGLIB_VERTEX__AFVN__TYPE #define __VCGLIB_VERTEX__AFVN__TYPE #define VERTEX_TYPE VertexAFVN #define __VCGLIB_VERTEX_AF #define __VCGLIB_VERTEX_VN #include #undef VERTEX_TYPE #undef __VCGLIB_VERTEX_AF #undef __VCGLIB_VERTEX_VN namespace vcg { template < class VETYPE, class VFTYPE, class VTTYPE> class VertexAFVNf : public VertexAFVN {}; template < class VETYPE, class VFTYPE, class VTTYPE> class VertexAFVNd : public VertexAFVN {}; } #endifqutemol/vcg/vcg/simplex/vertex/with/afvmvn.h0000444000175000017500000000122610120050637017572 0ustar mbamba#ifndef __VCGLIB_VERTEX__AF__TYPE #define __VCGLIB_VERTEX__VM__TYPE #define __VCGLIB_VERTEX__VN__TYPE #define VERTEX_TYPE VertexAFVMVN #define __VCGLIB_VERTEX_AF #define __VCGLIB_VERTEX_VM #define __VCGLIB_VERTEX_VN #include #undef VERTEX_TYPE #undef __VCGLIB_VERTEX__AF__TYPE #undef __VCGLIB_VERTEX__VM__TYPE #undef __VCGLIB_VERTEX__VN__TYPE namespace vcg { template < class VETYPE, class VFTYPE, class VTTYPE> class VertexAFVMVNf : public VertexAFVMVN {}; template < class VETYPE, class VFTYPE, class VTTYPE> class VertexAFVMVNd : public VertexAFVMVN {}; } #endif qutemol/vcg/vcg/simplex/vertex/with/atvnvm.h0000444000175000017500000000112510073204727017616 0ustar mbamba#ifndef __VCGLIB_VERTEX__AT__TYPE #define __VCGLIB_VERTEX__AT__TYPE #define VERTEX_TYPE VertexATVN #define __VCGLIB_VERTEX_AT #define __VCGLIB_VERTEX_VN #define __VCGLIB_VERTEX_VM #include #undef VERTEX_TYPE #undef __VCGLIB_VERTEX_VM #undef __VCGLIB_VERTEX_AT #undef __VCGLIB_VERTEX_VN namespace vcg { template < class VETYPE, class VFTYPE, class VTTYPE> class VertexATVNf : public VertexATVN {}; template < class VETYPE, class VFTYPE, class VTTYPE> class VertexATVNd : public VertexATVN {}; } #endif qutemol/vcg/vcg/simplex/vertex/with/at.h0000444000175000017500000000074110050667346016717 0ustar mbamba#ifndef __VCGLIB_VERTEX__AT__TYPE #define __VCGLIB_VERTEX__AT__TYPE #define VERTEX_TYPE VertexAT #define __VCGLIB_VERTEX_AT #include #undef VERTEX_TYPE #undef __VCGLIB_VERTEX_AT namespace vcg { template < class VETYPE, class VFTYPE, class VTTYPE> class VertexATf : public VertexAT {}; template < class VETYPE, class VFTYPE, class VTTYPE> class VertexATd : public VertexAT {}; } #endif qutemol/vcg/vcg/simplex/vertex/with/vq.h0000444000175000017500000000047310262710666016742 0ustar mbamba#ifndef __VCGLIB_VERTEX__VQ__TYPE #define __VCGLIB_VERTEX__VQ__TYPE #define VERTEX_TYPE VertexVQ #define __VCGLIB_VERTEX_VQ #include #undef VERTEX_TYPE #undef __VCGLIB_VERTEX_VQ namespace vcg { typedef VertexVQ VertexVQf; typedef VertexVQ VertexVQd; } #endif qutemol/vcg/vcg/simplex/vertex/with/af.h0000444000175000017500000000074110050667346016701 0ustar mbamba#ifndef __VCGLIB_VERTEX__AF__TYPE #define __VCGLIB_VERTEX__AF__TYPE #define VERTEX_TYPE VertexAF #define __VCGLIB_VERTEX_AF #include #undef VERTEX_TYPE #undef __VCGLIB_VERTEX_AF namespace vcg { template < class VETYPE, class VFTYPE, class VTTYPE> class VertexAFf : public VertexAF {}; template < class VETYPE, class VFTYPE, class VTTYPE> class VertexAFd : public VertexAF {}; } #endif qutemol/vcg/vcg/simplex/vertex/with/vcvnvq.h0000444000175000017500000000070110051012477017620 0ustar mbamba#ifndef __VCGLIB_VERTEX__VCVNVQ__TYPE #define __VCGLIB_VERTEX__VCVNVQ__TYPE #define VERTEX_TYPE VertexVCVNVQ #define __VCGLIB_VERTEX_VC #define __VCGLIB_VERTEX_VN #define __VCGLIB_VERTEX_VQ #include #undef VERTEX_TYPE #undef __VCGLIB_VERTEX_VC #undef __VCGLIB_VERTEX_VN #undef __VCGLIB_VERTEX_VQ namespace vcg { typedef VertexVCVNVQ VertexVCVNVQf; typedef VertexVCVNVQ VertexVCVNVQd; } #endif qutemol/vcg/vcg/simplex/vertex/with/vc.h0000444000175000017500000000075110136215237016715 0ustar mbamba#ifndef __VCGLIB_VERTEX__VCVN__TYPE #define __VCGLIB_VERTEX__VCVN__TYPE #define VERTEX_TYPE VertexVC #define __VCGLIB_VERTEX_VC #include #undef VERTEX_TYPE #undef __VCGLIB_VERTEX_VC namespace vcg { template < class VETYPE, class VFTYPE, class VTTYPE> class VertexVCf : public VertexVC {}; template < class VETYPE, class VFTYPE, class VTTYPE> class VertexVCd : public VertexVC {}; } #endif qutemol/vcg/vcg/simplex/vertex/with/afvcvnvq.h0000444000175000017500000000125710416665673020157 0ustar mbamba#ifndef __VCGLIB_VERTEX__AFVCVNVQ__TYPE #define __VCGLIB_VERTEX__AFVCVNVQ__TYPE #define VERTEX_TYPE VertexAFVCVNVQ #define __VCGLIB_VERTEX_AF #define __VCGLIB_VERTEX_VC #define __VCGLIB_VERTEX_VN #define __VCGLIB_VERTEX_VQ #include #undef VERTEX_TYPE #undef __VCGLIB_VERTEX_AF #undef __VCGLIB_VERTEX_VC #undef __VCGLIB_VERTEX_VN #undef __VCGLIB_VERTEX_VQ namespace vcg { template < class VETYPE, class VFTYPE, class VTTYPE> class VertexAFVCVNVQf : public VertexAFVCVNVQ {}; template < class VETYPE, class VFTYPE, class VTTYPE> class VertexAFVCVNVQd : public VertexAFVCVNVQ {}; } #endif qutemol/vcg/vcg/simplex/vertex/with/atvn.h0000444000175000017500000000104010050667346017254 0ustar mbamba#ifndef __VCGLIB_VERTEX__AT__TYPE #define __VCGLIB_VERTEX__AT__TYPE #define VERTEX_TYPE VertexATVN #define __VCGLIB_VERTEX_AT #define __VCGLIB_VERTEX_VN #include #undef VERTEX_TYPE #undef __VCGLIB_VERTEX_AT #undef __VCGLIB_VERTEX_VN namespace vcg { template < class VETYPE, class VFTYPE, class VTTYPE> class VertexATVNf : public VertexATVN {}; template < class VETYPE, class VFTYPE, class VTTYPE> class VertexATVNd : public VertexATVN {}; } #endif qutemol/vcg/vcg/simplex/vertex/with/vcvn.h0000444000175000017500000000105010050667346017261 0ustar mbamba#ifndef __VCGLIB_VERTEX__VCVN__TYPE #define __VCGLIB_VERTEX__VCVN__TYPE #define VERTEX_TYPE VertexVCVN #define __VCGLIB_VERTEX_VN #define __VCGLIB_VERTEX_VC #include #undef VERTEX_TYPE #undef __VCGLIB_VERTEX_VN #undef __VCGLIB_VERTEX_VC namespace vcg { template < class VETYPE, class VFTYPE, class VTTYPE> class VertexVCVNf : public VertexVCVN {}; template < class VETYPE, class VFTYPE, class VTTYPE> class VertexVCVNd : public VertexVCVN {}; } #endif qutemol/vcg/vcg/simplex/vertex/with/vmvn.h0000444000175000017500000000104710540251702017266 0ustar mbamba#ifndef __VCGLIB_VERTEX__VMVN__TYPE #define __VCGLIB_VERTEX__VMVN__TYPE #define VERTEX_TYPE VertexVMVN #define __VCGLIB_VERTEX_VN #define __VCGLIB_VERTEX_VM #include #undef VERTEX_TYPE #undef __VCGLIB_VERTEX_VM #undef __VCGLIB_VERTEX_VN namespace vcg { template < class VETYPE, class VFTYPE, class VTTYPE> class VertexVMVNf : public VertexVMVN {}; template < class VETYPE, class VFTYPE, class VTTYPE> class VertexVMVNd : public VertexVMVN {}; } #endif qutemol/vcg/vcg/simplex/vertex/with/vm.h0000444000175000017500000000074410317232333016726 0ustar mbamba#ifndef __VCGLIB_VERTEX__VM__TYPE #define __VCGLIB_VERTEX__VM__TYPE #define VERTEX_TYPE VertexVM #define __VCGLIB_VERTEX_VM #include #undef VERTEX_TYPE #undef __VCGLIB_VERTEX_VM namespace vcg { template < class VETYPE, class VFTYPE, class VTTYPE> class VertexVMf : public VertexVM {}; template < class VETYPE, class VFTYPE, class VTTYPE> class VertexVMd : public VertexVM {}; } #endifqutemol/vcg/vcg/simplex/vertex/with/vcvq.h0000444000175000017500000000057610051012477017266 0ustar mbamba#ifndef __VCGLIB_VERTEX__VCVQ__TYPE #define __VCGLIB_VERTEX__VCVQ__TYPE #define VERTEX_TYPE VertexVCVQ #define __VCGLIB_VERTEX_VC #define __VCGLIB_VERTEX_VQ #include #undef VERTEX_TYPE #undef __VCGLIB_VERTEX_VC #undef __VCGLIB_VERTEX_VQ namespace vcg { typedef VertexVCVQ VertexVCVQf; typedef VertexVCVQ VertexVCVQd; } #endif qutemol/vcg/vcg/simplex/vertex/with/ae.h0000444000175000017500000000074210050667346016701 0ustar mbamba#ifndef __VCGLIB_VERTEX__AE__TYPE #define __VCGLIB_VERTEX__AE__TYPE #define VERTEX_TYPE VertexAE #define __VCGLIB_VERTEX_AE #include #undef VERTEX_TYPE #undef __VCGLIB_VERTEX_AE namespace vcg { template < class VETYPE, class VFTYPE, class VTTYPE> class VertexAEf : public VertexAE {}; template < class VETYPE, class VFTYPE, class VTTYPE> class VertexAEd : public VertexAE {}; } #endif qutemol/vcg/vcg/simplex/vertex/with/vnvq.h0000444000175000017500000000057610262710666017312 0ustar mbamba#ifndef __VCGLIB_VERTEX__VNVQ__TYPE #define __VCGLIB_VERTEX__VNVQ__TYPE #define VERTEX_TYPE VertexVNVQ #define __VCGLIB_VERTEX_VN #define __VCGLIB_VERTEX_VQ #include #undef VERTEX_TYPE #undef __VCGLIB_VERTEX_VN #undef __VCGLIB_VERTEX_VQ namespace vcg { typedef VertexVNVQ VertexVNVQf; typedef VertexVNVQ VertexVNVQd; } #endif qutemol/vcg/vcg/simplex/vertex/with/vmvnvt.h0000444000175000017500000000121610506746771017657 0ustar mbamba#ifndef __VCGLIB_VERTEX__VMVNVT__TYPE #define __VCGLIB_VERTEX__VMVNVT__TYPE #define VERTEX_TYPE VertexVMVNVT #define __VCGLIB_VERTEX_VM #define __VCGLIB_VERTEX_VN #define __VCGLIB_VERTEX_VT #include #undef __VCGLIB_VERTEX_VM #undef __VCGLIB_VERTEX_VN #undef __VCGLIB_VERTEX_VT #undef VERTEX_TYPE namespace vcg { template < class VETYPE, class VFTYPE, class VTTYPE> class VertexVMVNVTf : public VertexVMVNVT {}; template < class VETYPE, class VFTYPE, class VTTYPE> class VertexVMVNVTd : public VertexVMVNVT {}; } #endif /* __VCGLIB_VERTEX__VMVNVT__TYPE */ qutemol/vcg/vcg/simplex/vertex/with/afvmvnvq.h0000444000175000017500000000137610260742447020163 0ustar mbamba#ifndef __VCGLIB_VERTEX__AF__TYPE #define __VCGLIB_VERTEX__VM__TYPE #define __VCGLIB_VERTEX__VN__TYPE #define __VCGLIB_VERTEX__VQ__TYPE #define VERTEX_TYPE VertexAFVMVNVQ #define __VCGLIB_VERTEX_AF #define __VCGLIB_VERTEX_VM #define __VCGLIB_VERTEX_VN #define __VCGLIB_VERTEX_VQ #include #undef VERTEX_TYPE #undef __VCGLIB_VERTEX__AF__TYPE #undef __VCGLIB_VERTEX__VM__TYPE #undef __VCGLIB_VERTEX__VN__TYPE #undef __VCGLIB_VERTEX__VQ__TYPE namespace vcg { template < class VETYPE, class VFTYPE, class VTTYPE> class VertexAFVMVNVQf : public VertexAFVMVNVQ {}; template < class VETYPE, class VFTYPE, class VTTYPE> class VertexAFVMVNVQd : public VertexAFVMVNVQ {}; } #endif qutemol/vcg/vcg/simplex/vertex/with/afatvcvnvq.h0000444000175000017500000000136110242372301020454 0ustar mbamba#ifndef __VCGLIB_VERTEX__AFATVCVNVQ__TYPE #define __VCGLIB_VERTEX__AFATVCVNVQ__TYPE #define VERTEX_TYPE VertexAFATVCVNVQ #define __VCGLIB_VERTEX_AF #define __VCGLIB_VERTEX_AT #define __VCGLIB_VERTEX_VC #define __VCGLIB_VERTEX_VN #define __VCGLIB_VERTEX_VQ #include #undef VERTEX_TYPE #undef __VCGLIB_VERTEX_AF #undef __VCGLIB_VERTEX_AT #undef __VCGLIB_VERTEX_VC #undef __VCGLIB_VERTEX_VN #undef __VCGLIB_VERTEX_VQ namespace vcg { template < class VETYPE, class VFTYPE, class VTTYPE> class VertexAFATVCVNVQf : public VertexAFATVCVNVQ {}; template < class VETYPE, class VFTYPE, class VTTYPE> class VertexAFATVCVNVQd : public VertexAFATVCVNVQ {}; } #endifqutemol/vcg/vcg/simplex/vertex/with/vcvmvnvq.h0000444000175000017500000000100510050774761020173 0ustar mbamba#ifndef __VCGLIB_VERTEX__VCVMVNVQ__TYPE #define __VCGLIB_VERTEX__VCVMVNVQ__TYPE #define VERTEX_TYPE VertexVCVMVNVQ #define __VCGLIB_VERTEX_VC #define __VCGLIB_VERTEX_VM #define __VCGLIB_VERTEX_VN #define __VCGLIB_VERTEX_VQ #include #undef VERTEX_TYPE #undef __VCGLIB_VERTEX_VC #undef __VCGLIB_VERTEX_VM #undef __VCGLIB_VERTEX_VN #undef __VCGLIB_VERTEX_VQ namespace vcg { typedef VertexVCVMVNVQ VertexVCVMVNVQf; typedef VertexVCVMVNVQ VertexVCVMVNVQd; } #endif qutemol/vcg/vcg/simplex/vertex/with/readme.txt0000444000175000017500000000444510214317062020132 0ustar mbamba/**************************************************************************** * VCGLib o o * * Visual and Computer Graphics Library o o * * _ O _ * * Copyright(C) 2004 \/)\/ * * Visual Computing Lab /\/| * * ISTI - Italian National Research Council | * * \ * * All rights reserved. * * * * 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. * * * * 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 (http://www.gnu.org/licenses/gpl.txt) * * for more details. * * * ****************************************************************************/ This folders contains most common VERTEX configuration files. The name of the file specifies the members that are added to the vertex class. The name is a sequence of letter pairs, in strict alphabetical order. The possible admitted letters pairs are: Adjacency Info AF - Vertex-Face adjacency AE - Vertex-Edge adjacency AT - Vertex-Tetra adjacency Per-Vertex Data VC - Color VN - Normal VM - Incremental Mark VQ - Quality VT - Texture Coords E.g. #include generate a type VertexAFVCVQ That can store V-F adjacency, color, normal and quality. qutemol/vcg/vcg/simplex/vertex/with/afvm.h0000444000175000017500000000105010227523626017234 0ustar mbamba#ifndef __VCGLIB_VERTEX__AFVM__TYPE #define __VCGLIB_VERTEX__AFVM__TYPE #define VERTEX_TYPE VertexAFVM #define __VCGLIB_VERTEX_AF #define __VCGLIB_VERTEX_VM #include #undef VERTEX_TYPE #undef __VCGLIB_VERTEX_AF #undef __VCGLIB_VERTEX_VM namespace vcg { template < class VETYPE, class VFTYPE, class VTTYPE> class VertexAFVMf : public VertexAFVM {}; template < class VETYPE, class VFTYPE, class VTTYPE> class VertexAFVMd : public VertexAFVM {}; } #endifqutemol/vcg/vcg/simplex/vertex/with/vn.h0000444000175000017500000000074410050667346016741 0ustar mbamba#ifndef __VCGLIB_VERTEX__VN__TYPE #define __VCGLIB_VERTEX__VN__TYPE #define VERTEX_TYPE VertexVN #define __VCGLIB_VERTEX_VN #include #undef VERTEX_TYPE #undef __VCGLIB_VERTEX_VN namespace vcg { template < class VETYPE, class VFTYPE, class VTTYPE> class VertexVNf : public VertexVN {}; template < class VETYPE, class VFTYPE, class VTTYPE> class VertexVNd : public VertexVN {}; } #endif qutemol/vcg/vcg/simplex/vertex/with/atvmvn.h0000444000175000017500000000127310575271660017631 0ustar mbamba#ifndef __VCGLIB_VERTEX__ATVMVN__TYPE #define __VCGLIB_VERTEX__ATVMVN__TYPE #define VERTEX_TYPE VertexATVMVN #define __VCGLIB_VERTEX_AT #define __VCGLIB_VERTEX_VM #define __VCGLIB_VERTEX_VN #include #undef VERTEX_TYPE #undef __VCGLIB_VERTEX_AT #undef __VCGLIB_VERTEX_VM #undef __VCGLIB_VERTEX_VN namespace vcg { template < class VETYPE, class VFTYPE, class VTTYPE,class TCTYPE = TexCoord2, class CoordTYPE= Point3 > class VertexATVMVNf : public VertexATVMVN {}; template < class VETYPE, class VFTYPE, class VTTYPE> class VertexATVMVNd : public VertexATVMVN {}; } #endif qutemol/vcg/vcg/simplex/vertex/with/afvcvmvn.h0000444000175000017500000000124610703360451020132 0ustar mbamba#ifndef __VCGLIB_VERTEX__VCVN__TYPE #define __VCGLIB_VERTEX__VCVN__TYPE #define VERTEX_TYPE VertexAFVCVMVN #define __VCGLIB_VERTEX_AF #define __VCGLIB_VERTEX_VN #define __VCGLIB_VERTEX_VC #define __VCGLIB_VERTEX_VM #include #undef VERTEX_TYPE #undef __VCGLIB_VERTEX_VM #undef __VCGLIB_VERTEX_AF #undef __VCGLIB_VERTEX_VN #undef __VCGLIB_VERTEX_VC namespace vcg { template < class VETYPE, class VFTYPE, class VTTYPE> class VertexAFVCVMVNf : public VertexAFVCVMVN {}; template < class VETYPE, class VFTYPE, class VTTYPE> class VertexAFVCVMVNd : public VertexAFVCVMVN {}; } #endif qutemol/vcg/vcg/simplex/vertex/with/vcvmvnvt.h0000444000175000017500000000132310427660571020202 0ustar mbamba#ifndef __VCGLIB_VERTEX__VCVMVNVT__TYPE #define __VCGLIB_VERTEX__VCVMVNVT__TYPE #define VERTEX_TYPE VertexVCVMVNVT #define __VCGLIB_VERTEX_VC #define __VCGLIB_VERTEX_VM #define __VCGLIB_VERTEX_VN #define __VCGLIB_VERTEX_VT #include #undef VERTEX_TYPE #undef __VCGLIB_VERTEX_VC #undef __VCGLIB_VERTEX_VM #undef __VCGLIB_VERTEX_VN #undef __VCGLIB_VERTEX_VT namespace vcg { template < class VETYPE, class VFTYPE, class VTTYPE> class VertexVCVMVNVTf : public VertexVCVMVNVT {}; template < class VETYPE, class VFTYPE, class VTTYPE> class VertexVCVMVNVTd : public VertexVCVMVNVT {}; } #endif /* __VCGLIB_VERTEX__VCVMVNVT__TYPE */ qutemol/vcg/vcg/simplex/vertex/distance.h0000444000175000017500000000626010473072710017126 0ustar mbamba/**************************************************************************** * VCGLib o o * * Visual and Computer Graphics Library o o * * _ O _ * * Copyright(C) 2004 \/)\/ * * Visual Computing Lab /\/| * * ISTI - Italian National Research Council | * * \ * * All rights reserved. * * * * 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. * * * * 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 (http://www.gnu.org/licenses/gpl.txt) * * for more details. * * * ****************************************************************************/ // marco : // comments // corrected bug /**************************************************************************** History ****************************************************************************/ #ifndef __VCGLIB_VERTEX_DISTANCE #define __VCGLIB_VERTEX_DISTANCE #include #include namespace vcg { namespace vertex{ class PointDistanceFunctor { public: template /* * @param v [IN] is a reference to the current object being tested, * @param p [IN] is the query point, * @param minDist [IN/OUT] is in input the reject distance and in output the closest distance, * @param q [OUT] is the closest point. * * @remarks The operator returns true if the closest distance is less than input reject distance. * */ inline bool operator () (const VERTEXTYPE & v, const Point3 & p, SCALARTYPE & minDist, Point3 & q) { // convert the coordinates of p from SCALARTYPE to VERTEXTYPE::ScalarType type const Point3 fp = Point3::Construct(p); typename VERTEXTYPE::ScalarType md; // distance between v and fp md = (v.P() - fp).Norm(); if (md <= minDist) { minDist = (SCALARTYPE)(md); // minDist is updated to the closest distance q = v.P(); // q is the current closest point return true; } return false; } }; } // end namespace vertex } // end namespace vcg #endif qutemol/vcg/vcg/simplex/face/0000755000175000017500000000000011633404241014537 5ustar mbambaqutemol/vcg/vcg/simplex/face/topology.h0000444000175000017500000003452410776107764016613 0ustar mbamba/**************************************************************************** * VCGLib o o * * Visual and Computer Graphics Library o o * * _ O _ * * Copyright(C) 2004 \/)\/ * * Visual Computing Lab /\/| * * ISTI - Italian National Research Council | * * \ * * All rights reserved. * * * * 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. * * * * 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 (http://www.gnu.org/licenses/gpl.txt) * * for more details. * * * ****************************************************************************/ /**************************************************************************** History $Log: topology.h,v $ Revision 1.31 2008/04/06 08:55:16 onnis FaceType::VerteType --> FaceType::VertexType Revision 1.30 2007/05/16 15:12:40 fiorin Added std:: prefix to swap call Revision 1.29 2006/12/06 00:08:21 cignoni Removed Oldstyle uberZ access to FF adjacency Revision 1.28 2006/11/09 17:28:42 cignoni Corrected Detach; added FFCorrectness; Corrected ComplexSize, Dissemination of a lot of assert() Revision 1.27 2006/05/03 21:38:57 cignoni Added possibility of not updating the topology during a SwapEdge Revision 1.26 2005/12/19 13:47:26 corsini Rewrite SwapEdge to fix problems with borders Revision 1.25 2005/12/16 11:01:26 corsini Remove trivial warnings Revision 1.24 2005/12/16 10:47:48 corsini Add further comment to FlipEdge Revision 1.23 2005/12/16 10:43:23 corsini Fix one bug Revision 1.22 2005/12/16 10:29:10 corsini Add CheckOrientation Reimplement SwapEdge function Revision 1.21 2005/12/01 23:54:59 cignoni Removed excess ';' from end of template functions, for gcc compiling Revision 1.20 2005/11/23 13:04:26 ganovelli changed IsBOrder Revision 1.19 2005/11/10 15:49:32 cignoni Made IsManifold Constant Revision 1.18 2005/10/13 08:34:19 cignoni Removed reference to IsBorder() member of face and substituted with the face templated function version. Revision 1.17 2005/04/11 09:17:24 pietroni Changed detach to FFdetach , compiled tested in manifold cases Revision 1.16 2005/03/18 16:35:53 fiorin minor changes to comply gcc compiler Revision 1.15 2004/10/22 13:41:06 fiorin Added CheckFlipEdge and FlipEdge Revision 1.14 2004/10/18 17:15:45 ganovelli minor change Revision 1.13 2004/08/06 01:47:57 pietroni corrected errors on vfappend Revision 1.12 2004/08/05 22:27:00 pietroni added VFAppend funtion Revision 1.10 2004/07/27 09:49:23 cignoni Removed warning about postfix incremnet of VFIterator Revision 1.9 2004/07/15 12:03:07 ganovelli minor changes Revision 1.8 2004/07/15 11:26:48 ganovelli VFDetach corrected Revision 1.7 2004/05/12 12:23:23 cignoni Conformed C++ syntax to GCC requirements Revision 1.6 2004/05/11 16:03:18 ganovelli changed from "thi" to "&f" in Vfdetach Revision 1.5 2004/05/10 15:20:49 cignoni Updated names of POS and adj functions to the new standards for many functions Revision 1.4 2004/03/18 16:00:10 cignoni minor changes ****************************************************************************/ #ifndef _VCG_FACE_TOPOLOGY #define _VCG_FACE_TOPOLOGY #include namespace vcg { namespace face { /** \addtogroup face */ /*@{*/ /** Return a boolean that indicate if the face is complex. @param j Index of the edge @return true se la faccia e' manifold, false altrimenti */ template inline bool IsManifold( FaceType const & f, const int j ) { assert(f.cFFp(j) != 0); // never try to use this on uncomputed topology if(FaceType::HasFFAdjacency()) return ( f.cFFp(j) == &f || &f == f.cFFp(j)->cFFp(f.cFFi(j)) ); else return true; } /** Return a boolean that indicate if the j-th edge of the face is a border. @param j Index of the edge @return true if j is an edge of border, false otherwise */ template inline bool IsBorder(FaceType const & f, const int j ) { if(FaceType::HasFFAdjacency()) return f.cFFp(j)==&f; //return f.IsBorder(j); assert(0); return true; } /// Count border edges of the face template inline int BorderCount(FaceType const & f) { if(FaceType::HasFFAdjacency()) { int t = 0; if( IsBorder(f,0) ) ++t; if( IsBorder(f,1) ) ++t; if( IsBorder(f,2) ) ++t; return t; } else return 3; } /// Counts the number of incident faces in a complex edge template inline int ComplexSize(FaceType & f, const int e) { if(FaceType::HasFFAdjacency()) { if(face::IsBorder(f,e)) return 1; if(face::IsManifold(f,e)) return 2; // Non manifold case Pos< FaceType > fpos(&f,e); int cnt=0; do { fpos.NextF(); assert(!fpos.IsBorder()); assert(!fpos.IsManifold()); ++cnt; } while(fpos.f!=&f); assert (cnt>2); return cnt; } assert(0); return 2; } /** This function check the FF topology correctness for an edge of a face. It's possible to use it also in non-two manifold situation. The function cannot be applicated if the adjacencies among faces aren't defined. @param f the face to be checked @param e Index of the edge to be checked */ template bool FFCorrectness(FaceType & f, const int e) { if(f.FFp(e)==0) return false; // Not computed or inconsistent topology if(f.FFp(e)==&f) // Border { if(f.FFi(e)==e) return true; else return false; } if(f.FFp(e)->FFp(f.FFi(e))==&f) // plain two manifold { if(f.FFp(e)->FFi(f.FFi(e))==e) return true; else return false; } // Non Manifold Case // all the faces must be connected in a loop. Pos< FaceType > curFace(&f,e); // Build the half edge int cnt=0; do { if(curFace.IsManifold()) return false; if(curFace.IsBorder()) return false; curFace.NextF(); cnt++; assert(cnt<100); } while ( curFace.f != &f); return true; } /** This function detach the face from the adjacent face via the edge e. It's possible to use it also in non-two manifold situation. The function cannot be applicated if the adjacencies among faces aren't defined. @param f the face to be detached @param e Index of the edge to be detached */ template void FFDetach(FaceType & f, const int e) { assert(FFCorrectness(f,e)); assert(!IsBorder(f,e)); // Never try to detach a border edge! int complexity; assert(complexity=ComplexSize(f,e)); Pos< FaceType > FirstFace(&f,e); // Build the half edge Pos< FaceType > LastFace(&f,e); // Build the half edge FirstFace.NextF(); LastFace.NextF(); int cnt=0; ///then in case of non manifold face continue to advance LastFace // until I find it become the one that ///preceed the face I want to erase while ( LastFace.f->FFp(LastFace.z) != &f) { assert(ComplexSize(*LastFace.f,LastFace.z)==complexity); assert(!LastFace.IsManifold()); // We enter in this loop only if we are on a non manifold edge assert(!LastFace.IsBorder()); LastFace.NextF(); cnt++; assert(cnt<100); } assert(LastFace.f->FFp(LastFace.z)==&f); assert(f.FFp(e)== FirstFace.f); // Now we link the last one to the first one, skipping the face to be detached; LastFace.f->FFp(LastFace.z) = FirstFace.f; LastFace.f->FFi(LastFace.z) = FirstFace.z; assert(ComplexSize(*LastFace.f,LastFace.z)==complexity-1); // At the end selfconnect the chosen edge to make a border. f.FFp(e) = &f; f.FFi(e) = e; assert(ComplexSize(f,e)==1); assert(FFCorrectness(*LastFace.f,LastFace.z)); assert(FFCorrectness(f,e)); } /** This function attach the face (via the edge z1) to another face (via the edge z2). It's possible to use it also in non-two manifold situation. The function cannot be applicated if the adjacencies among faces aren't define. @param z1 Index of the edge @param f2 Pointer to the face @param z2 The edge of the face f2 */ template void Attach(FaceType * &f, int z1, FaceType *&f2, int z2) { //typedef FEdgePosB< FACE_TYPE > ETYPE; Pos< FaceType > EPB(f2,z2); Pos< FaceType > TEPB; TEPB = EPB; EPB.NextF(); while( EPB.f != f2) //Alla fine del ciclo TEPB contiene la faccia che precede f2 { TEPB = EPB; EPB.NextF(); } //Salvo i dati di f1 prima di sovrascrivere FaceType *f1prec = f.FFp(z1); int z1prec = f.FFi(z1); //Aggiorno f1 f->FFp(z1) = TEPB.f->FFp(TEPB.z); f->FFi(z1) = TEPB.f->FFi(TEPB.z); //Aggiorno la faccia che precede f2 TEPB.f->FFp(TEPB.z) = f1prec; TEPB.f->FFi(TEPB.z) = z1prec; } template void AssertAdj(FaceType & f) { assert(f.FFp(0)->FFp(f.FFi(0))==&f); assert(f.FFp(1)->FFp(f.FFi(1))==&f); assert(f.FFp(2)->FFp(f.FFi(2))==&f); assert(f.FFp(0)->FFi(f.FFi(0))==0); assert(f.FFp(1)->FFi(f.FFi(1))==1); assert(f.FFp(2)->FFi(f.FFi(2))==2); } // Funzione di supporto usata da swap? //template //inline void Nexts( *&f, int &z ) //{ // int t; // t = z; // z = (*f).Z(z); // f = (*f).F(t); //} /** * Check if the given face is oriented as the one adjacent to the specified edge. * @param f Face to check the orientation * @param z Index of the edge */ template bool CheckOrientation(FaceType &f, int z) { if (IsBorder(f, z)) return true; else { FaceType *g = f.FFp(z); int gi = f.FFi(z); if (f.V0(z) == g->V1(gi)) return true; else return false; } } /** * This function change the orientation of the face by inverting the index of two vertex. * @param z Index of the edge */ template void SwapEdge(FaceType &f, const int z) { SwapEdge(f,z); } template void SwapEdge(FaceType &f, const int z) { // swap V0(z) with V1(z) std::swap(f.V0(z), f.V1(z)); if(f.HasFFAdjacency() && UpdateTopology) { // store information to preserve topology int z1 = (z+1)%3; int z2 = (z+2)%3; FaceType *g1p = f.FFp(z1); FaceType *g2p = f.FFp(z2); int g1i = f.FFi(z1); int g2i = f.FFi(z2); // g0 face topology is not affected by the swap if (g1p != &f) { g1p->FFi(g1i) = z2; f.FFi(z2) = g1i; } else { f.FFi(z2) = z2; } if (g2p != &f) { g2p->FFi(g2i) = z1; f.FFi(z1) = g2i; } else { f.FFi(z1) = z1; } // finalize swap f.FFp(z1) = g2p; f.FFp(z2) = g1p; } } /*! * Check if the z-th edge of the face f can be flipped. * \param f pointer to the face * \param z the edge index */ template static bool CheckFlipEdge(FaceType &f, int z) { if (z<0 || z>2) return false; // boundary edges cannot be flipped if (face::IsBorder(f, z)) return false; FaceType *g = f.FFp(z); int w = f.FFi(z); // check if the vertices of the edge are the same if (g->V(w)!=f.V1(z) || g->V1(w)!=f.V(z) ) return false; // check if the flipped edge is already present in the mesh typedef typename FaceType::VertexType VertexType; VertexType *f_v2 = f.V2(z); VertexType *g_v2 = g->V2(w); if (f_v2 == g_v2) return false; vcg::face::Pos< FaceType > pos(&f, (z+2)%3, f.V2(z)); do { pos.NextE(); if (g_v2==pos.f->V1(pos.z)) return false; } while (&f!=pos.f); return true; } /*! * Flip the z-th edge of the face f. * Check for topological correctness first using CheckFlipFace(). * \param f pointer to the face * \param z the edge index * * Note: For edge flip we intend the swap of the diagonal of the rectangle * formed by the face \a f and the face adjacent to the specified edge. */ template static void FlipEdge(FaceType &f, const int z) { assert(z>=0); assert(z<3); assert( !IsBorder(f,z) ); assert( face::IsManifold(f, z)); FaceType *g = f.FFp(z); int w = f.FFi(z); assert( g->V(w) == f.V1(z) ); assert( g->V1(w)== f.V(z) ); assert( g->V2(w)!= f.V(z) ); assert( g->V2(w)!= f.V1(z) ); assert( g->V2(w)!= f.V2(z) ); f.V1(z) = g->V2(w); g->V1(w) = f.V2(z); f.FFp(z) = g->FFp1(w); f.FFi(z) = g->FFi((w+1)%3); g->FFp(w) = f.FFp1(z); g->FFi(w) = f.FFi((z+1)%3); f.FFp1(z) = g; f.FFi((z+1)%3) = (w+1)%3; g->FFp1(w) = &f; g->FFi((w+1)%3) = (z+1)%3; if(f.FFp(z)==g) { f.FFp(z) = &f; f.FFi(z) = z; } else { f.FFp(z)->FFp( f.FFi(z) ) = &f; f.FFp(z)->FFi( f.FFi(z) ) = z; } if(g->FFp(w)==&f) { g->FFp(w)=g; g->FFi(w)=w; } else { g->FFp(w)->FFp( g->FFi(w) ) = g; g->FFp(w)->FFi( g->FFi(w) ) = w; } } // Stacca la faccia corrente dalla catena di facce incidenti sul vertice z, // NOTA funziona SOLO per la topologia VF!!! // usata nelle classi di collapse template void VFDetach(FaceType & f, int z) { if(f.V(z)->VFp()==&f ) //if it is the first face detach from the begin { int fz = f.V(z)->VFi(); f.V(z)->VFp() = f.VFp(fz); f.V(z)->VFi() = f.VFi(fz); } else // scan the list of faces in order to finde the current face f to be detached { VFIterator x(f.V(z)->VFp(),f.V(z)->VFi()); VFIterator y; for(;;) { y = x; ++x; assert(x.f!=0); if(x.f==&f) // found! { y.f->VFp(y.z) = f.VFp(z); y.f->VFi(y.z) = f.VFi(z); break; } } } } /// Append a face in VF list of vertex f->V(z) template void VFAppend(FaceType* & f, int z) { typename FaceType::VertexType *v = f->V(z); if (v->VFp()!=0) { FaceType *f0=v->VFp(); int z0=v->VFi(); //append f->VFp(z)=f0; f->VFi(z)=z0; } v->VFp()=f; v->VFi()=z; } /*@}*/ } // end namespace } // end namespace #endif qutemol/vcg/vcg/simplex/face/base.h0000444000175000017500000007657610616661326015656 0ustar mbamba/**************************************************************************** * VCGLib o o * * Visual and Computer Graphics Library o o * * _ O _ * * Copyright(C) 2004 \/)\/ * * Visual Computing Lab /\/| * * ISTI - Italian National Research Council | * * \ * * All rights reserved. * * * * 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. * * * * 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 (http://www.gnu.org/licenses/gpl.txt) * * for more details. * * * ****************************************************************************/ /**************************************************************************** History $Log: base.h,v $ Revision 1.44 2007/05/04 16:44:06 ganovelli changes to comply "plus" types Revision 1.43 2007/03/12 15:37:19 tarini Texture coord name change! "TCoord" and "Texture" are BAD. "TexCoord" is GOOD. Revision 1.42 2007/02/20 14:07:53 ganovelli added QualityType to comply faceplus type Revision 1.41 2007/01/13 00:25:36 cignoni Added #ifdefs to guarantee that ComputeNormal would be defined only once Revision 1.40 2007/01/11 10:13:11 cignoni Rewrote the template of ComputeNormal functions to a more readable form. Revision 1.39 2006/07/12 12:14:31 zifnab1974 changes for compilation on linux. Not sure about using either SphereOfTriangle or SphereOfTetra, please check. Revision 1.38 2006/07/06 12:45:08 ganovelli added SmallestEnclosingSphere Revision 1.37 2006/01/22 10:00:43 cignoni Very Important Change: Area->DoubleArea (and no more Area function) Revision 1.36 2005/12/16 11:42:23 corsini Add some user bit Revision 1.35 2005/12/01 23:54:29 cignoni Added HasFlags Revision 1.34 2005/11/23 14:40:09 pietroni added cFFi function Revision 1.33 2005/11/22 15:47:35 cignoni Moved ComputeNormal and ComputeNormalizedNormal out of the face class (no more a member function!) Revision 1.32 2005/11/12 18:39:54 cignoni Added dummy static member for avoiding annoying warning in empty functions... Revision 1.31 2005/11/01 18:16:36 cignoni Added intialization of _flags to zero in the default constructor of face Revision 1.30 2005/10/13 09:25:43 cignoni Added cFFp and cVFp const member functions Revision 1.29 2005/09/28 19:32:09 m_di_benedetto Added const qualifier in GetBBox method. Revision 1.28 2005/06/17 00:43:34 cignoni Added a named typedef for the per wedge TexCoordinate Revision 1.27 2005/03/18 16:35:53 fiorin minor changes to comply gcc compiler Revision 1.26 2005/03/11 14:14:14 ganovelli _ffi was a 4 for positions vector (only 3 used) Revision 1.25 2005/01/28 17:53:13 pietroni added HasEdgePlane function Revision 1.24 2004/10/28 00:50:48 cignoni Better Doxygen documentation Revision 1.23 2004/10/25 08:22:40 ganovelli IsBOrder (typecast on return type) Revision 1.22 2004/10/20 08:28:31 fiorin Added constant access function FFp and renamed F1 F2 to FFp1 FFp2 Revision 1.21 2004/10/18 17:13:50 ganovelli added ::IsBorder Revision 1.20 2004/09/15 11:20:15 ganovelli changed P() to cP() Revision 1.19 2004/09/14 19:47:02 ganovelli removed "&" in FFp Revision 1.18 2004/08/25 15:15:27 ganovelli minor changes to comply gcc compiler (typename's and stuff) Revision 1.17 2004/07/15 12:03:07 ganovelli minor changes Revision 1.16 2004/07/15 11:31:59 ganovelli minor changes Revision 1.15 2004/07/12 12:17:09 pietroni added function NormalizedNormal Revision 1.14 2004/05/13 11:01:06 turini Changed ComputeMormalizedNormal() using Triangle3 Revision 1.13 2004/05/12 18:49:05 ganovelli dist and coputeRT removed (see distance.h and updateEdges) Revision 1.12 2004/05/12 14:43:36 cignoni removed warning of unused variables Revision 1.11 2004/05/12 12:50:20 turini include color4 Revision 1.10 2004/05/10 14:01:09 ganovelli assert(i*0) for using "i" and preventing the compiler warning for unreferenced variable Revision 1.9 2004/05/10 13:19:38 cignoni Added mandatory template params for edge and face class names to the face class Changed type of return face pointer to the one passed by templ params Changed name of func FV to VF (it stores Vertex-Face Topology) Revision 1.8 2004/05/06 09:06:59 pietroni changed names to topology functions Revision 1.7 2004/05/04 02:46:23 ganovelli added function Dist Revision 1.5 2004/04/05 11:51:22 cignoni wrong define FACE_N instead of FACE_FN Revision 1.4 2004/03/29 08:37:09 cignoni missing include Revision 1.3 2004/03/10 00:52:38 cignoni Moved geometric stuff to the space/triangle class Revision 1.2 2004/03/03 16:08:38 cignoni First working version Revision 1.1 2004/02/13 00:44:45 cignoni First commit... ****************************************************************************/ #ifndef FACE_TYPE #pragma error message("\nYou should never directly include this file\_n") #else #include #include #include #include #include #include #include #include #include namespace vcg { class DUMMYEDGETYPE; class DUMMYFACETYPE; class DUMMYTETRATYPE; /** \addtogroup face */ //@{ /*! * This class represent the generic configurable Face; * Usually you never direclty use this class with this name but you build * your own type by directly including one of the .h files under the face/with * directory. Each file specify a class type with the desired fields. So for example * including 'vcg/simplex/face/with/FCFN.h' allow you to use the class FaceFCFN that has per-face color and normal stored inside. */ template > class FACE_TYPE { public: /// The base type of the face typedef FACE_TYPE BaseFaceType; /// The base type of the face itself typedef FFTYPE FaceType; /// The vertex type typedef FVTYPE VertexType; /// The vertex type typedef FETYPE EdgeType; /// The Texture Coordinate type typedef TCTYPE TexCoordType; /// The type of the scalar field of the vertex coordinate typedef typename VertexType::ScalarType ScalarType; /// The type of the the vertex coordinate typedef Point3< ScalarType > CoordType; typedef Point3< ScalarType > NormalType; /// The geometric type of the face typedef Triangle3 GeometricType; /// The type of the quality (same as scalar) typedef ScalarType QualityType; typedef typename FVTYPE::FaceType FaceFromVertType; /// The bounding box type typedef Box3 BoxType; /// Default Empty Costructor inline FACE_TYPE(){_flags=0;} /// This are the _flags of face, the default value is 0 int _flags; /***********************************************/ /** @name Vertex Pointer Functions to access to the vertexes of the face; **/ //@{ protected: /// Vector of vertex pointer incident in the face VertexType *v[3]; public: /** Return the pointer to the j-th vertex of the face. @param j Index of the face vertex. */ inline VertexType * & V( const int j ) { assert( (_flags & DELETED) == 0 ); assert( (_flags & NOTREAD) == 0 ); assert( (_flags & NOTWRITE) == 0 ); assert(j >= 0); assert(j < 3); return v[j]; } inline VertexType * const & V( const int j ) const { assert( (_flags & DELETED) == 0 ); assert( (_flags & NOTREAD) == 0 ); assert(j>=0); assert(j<3); return v[j]; } inline VertexType * const cV( const int j ) const { assert( (_flags & DELETED) == 0 ); assert( (_flags & NOTREAD) == 0 ); assert(j>=0); assert(j<3); return v[j]; } // Shortcut per accedere ai punti delle facce inline CoordType & P( const int j ) { assert( (_flags & DELETED) == 0 ); assert( (_flags & NOTREAD) == 0 ); assert( (_flags & NOTWRITE) == 0 ); assert(j>=0); assert(j<3); return v[j]->P(); } inline const CoordType & P( const int j ) const { assert( (_flags & DELETED) == 0 ); assert( (_flags & NOTREAD) == 0 ); assert(j>=0); assert(j<3); return v[j]->cP(); } inline const CoordType & cP( const int j ) const { assert( (_flags & DELETED) == 0 ); assert( (_flags & NOTREAD) == 0 ); assert(j>=0); assert(j<3); return v[j]->cP(); } /** Return the pointer to the ((j+1)%3)-th vertex of the face. @param j Index of the face vertex. */ inline VertexType * & V0( const int j ) { return V(j);} inline VertexType * & V1( const int j ) { return V((j+1)%3);} inline VertexType * & V2( const int j ) { return V((j+2)%3);} inline const VertexType * const & V0( const int j ) const { return V(j);} inline const VertexType * const & V1( const int j ) const { return V((j+1)%3);} inline const VertexType * const & V2( const int j ) const { return V((j+2)%3);} inline const VertexType * const & cV0( const int j ) const { return cV(j);} inline const VertexType * const & cV1( const int j ) const { return cV((j+1)%3);} inline const VertexType * const & cV2( const int j ) const { return cV((j+2)%3);} /// Shortcut per accedere ai punti delle facce inline CoordType & P0( const int j ) { return V(j)->P();} inline CoordType & P1( const int j ) { return V((j+1)%3)->P();} inline CoordType & P2( const int j ) { return V((j+2)%3)->P();} inline const CoordType & P0( const int j ) const { return V(j)->P();} inline const CoordType & P1( const int j ) const { return V((j+1)%3)->P();} inline const CoordType & P2( const int j ) const { return V((j+2)%3)->P();} inline const CoordType & cP0( const int j ) const { return cV(j)->P();} inline const CoordType & cP1( const int j ) const { return cV((j+1)%3)->P();} inline const CoordType & cP2( const int j ) const { return cV((j+2)%3)->P();} inline VertexType * & UberV( const int j ) { assert(j>=0); assert(j<3); return v[j]; } inline const VertexType * const & UberV( const int j ) const { assert(j>=0); assert(j<3); return v[j]; } //@} /***********************************************/ /** @name Normal blah blah **/ //@{ #ifdef __VCGLIB_FACE_FN /// This vector indicates the normal of the face (defines if FACE_N is defined) protected: CoordType _n; public: #endif /// Return the reference of the normal to the face (if __VCGLIB_FACE_FN is defined). inline CoordType & N() { #ifdef __VCGLIB_FACE_FN return _n; #else assert(0); return *(CoordType *)0; #endif } /// Return the reference of the normal to the face (if __VCGLIB_FACE_FN is defined). inline const CoordType & N() const { #ifdef __VCGLIB_FACE_FN return _n; #else return *(CoordType *)0; #endif } /// Return the reference of the normal to the face (if __VCGLIB_FACE_FN is defined). inline const CoordType cN() const { #ifdef __VCGLIB_FACE_FN return _n; #else return *(CoordType *)0; #endif } /// Return the value of the face normal as it correspond to the current geometry. /// it is always computed and never stored. const CoordType Normal() const { return vcg::Normal(*this); } /// Return the value of the face normal as it correspond to the current geometry. /// it is always computed and never stored. const CoordType NormalizedNormal() const { return vcg::NormalizedNormal(*this); } #ifdef __VCGLIB_FACE_WN /// This vector indicates per wedge normal CoordType _wn[3]; #endif public: CoordType & WN(const int i) { #ifdef __VCGLIB_FACE_WN return _wn[i]; #else assert(0); return *(CoordType *)(&_flags); #endif } const CoordType & WN(const int i) const { #ifdef __VCGLIB_FACE_WN return _wn[i]; #else return CoordType(); #endif } //@} /***********************************************/ /** @name Quality blah blah **/ //@{ #ifdef __VCGLIB_FACE_FQ protected: float _q; #endif public: float & Q() { #ifdef __VCGLIB_FACE_FQ return _q; #else assert(0); return *(float*)(&_flags); #endif } const float & Q() const { #ifdef __VCGLIB_FACE_FQ return _q; #else assert(0); return *(float*)(&_flags); #endif } //@} /***********************************************/ /** @name Texture blah blah **/ //@{ // Per Wedge Texture Coords protected: #ifdef __VCGLIB_FACE_WT TCTYPE _wt[3]; #endif public: TCTYPE & WT(const int i) { #ifdef __VCGLIB_FACE_WT return _wt[i]; #else assert(0); return *(TCTYPE*)(&_flags +i) ; #endif } const TCTYPE & WT(const int i) const { #ifdef __VCGLIB_FACE_WT return _wt[i]; #else assert(0); return *(TCTYPE*)(&_flags); #endif } //@} /***********************************************/ /** @name Colors blah blah **/ //@{ protected: #ifdef __VCGLIB_FACE_FC Color4b _c; #endif public: Color4b & C() { #ifdef __VCGLIB_FACE_FC return _c; #else assert(0); return *(Color4b*)(&_flags); #endif } const Color4b C() const { #ifdef __VCGLIB_FACE_FC return _c; #else return Color4b(Color4b::White); #endif } protected: #ifdef __VCGLIB_FACE_WC Color4b _wc[3]; #endif public: Color4b & WC(const int i) { #ifdef __VCGLIB_FACE_WC return _wc[i]; #else assert(0); return *(Color4b*)(&_flags + i); #endif } const Color4b WC(const int i) const { #ifdef __VCGLIB_FACE_WC return _wc[i]; #else assert(0); return Color4b(Color4b::White); #endif } //@} /***********************************************/ /** @name Adjacency blah blah **/ //@{ #if (defined(__VCGLIB_FACE_AF) && defined(__VCGLIB_FACE_AS)) #error Error: You cannot specify face-to-face and shared topology together #endif #if (defined(__VCGLIB_FACE_AV) && defined(__VCGLIB_FACE_AS)) #error Error: You cannot specify vertex-face and shared topology together #endif protected: #if defined(__VCGLIB_FACE_AF) /// Vector of face pointer, it's used to indicate the adjacency relations (defines if FACE_A is defined) FFTYPE *_ffp[3]; // Facce adiacenti /// Index of the face in the arrival face char _ffi[3]; #endif #ifdef __VCGLIB_FACE_AV ///Vettore di puntatori a faccia, utilizzato per indicare le adiacenze vertice faccia FFTYPE *_fvp[3]; char _fvi[3]; #endif #ifdef __VCGLIB_FACE_AS ///Vettore di puntatori a faccia, utilizzato per indicare le adiacenze vertice faccia FFTYPE *fs[3]; char zs[3]; #endif public: /** Return the pointer to the j-th adjacent face. @param j Index of the edge. */ inline FFTYPE * & FFp( const int j ) { assert( (_flags & DELETED) == 0 ); assert( (_flags & NOTREAD) == 0 ); assert( (_flags & NOTWRITE) == 0 ); assert(j>=0); assert(j<3); #if defined(__VCGLIB_FACE_AF) return _ffp[j]; #elif defined(__VCGLIB_FACE_AS) return fs[j]; #else assert(0); static FFTYPE *dum=0; dum+=j; return dum; #endif } inline const FFTYPE * FFp( const int j ) const { assert( (_flags & DELETED) == 0 ); assert( (_flags & NOTREAD) == 0 ); assert(j>=0 && j<3); #if defined(__VCGLIB_FACE_AF) return _ffp[j]; #elif defined(__VCGLIB_FACE_AS) return fs[j]; #else assert(0); static FFTYPE *dum=0; dum+=j; return dum; #endif } inline const FFTYPE * cFFp( const int j ) const {return FFp(j);} inline FFTYPE * & FFp1( const int j ) { return FFp((j+1)%3);} inline FFTYPE * & FFp2( const int j ) { return FFp((j+2)%3);} inline const FFTYPE * const& FFp1( const int j ) const { return FFp((j+1)%3);} inline const FFTYPE * const& FFp2( const int j ) const { return FFp((j+2)%3);} /** Return the pointer to the j-th adjacent face. @param j Index of the edge. */ inline FFTYPE * & UberF( const int j ) { assert(j>=0); assert(j<3); #if defined(__VCGLIB_FACE_AF) return _ffp[j]; #elif defined(__VCGLIB_FACE_AS) return fs[j]; #else assert(0); // if you stop here you are probably trying to use FF topology in a face without it return *((FFTYPE **)(_flags)); #endif } inline const FFTYPE * const & UberF( const int j ) const { assert(j>=0); assert(j<3); #if defined(__VCGLIB_FACE_AF) return _ffp[j]; #elif defined(__VCGLIB_FACE_AS) return fs[j]; #else assert(0); // if you stop here you are probably trying to use FF topology in a face without it return *((FFTYPE **)(_flags)); #endif } inline FFTYPE * & VFp( const int j ) { assert( (_flags & DELETED) == 0 ); assert( (_flags & NOTREAD) == 0 ); assert( (_flags & NOTWRITE) == 0 ); assert(j>=0); assert(j<3); #ifdef __VCGLIB_FACE_AV return _fvp[j]; #elif defined(__VCGLIB_FACE_AS) return fs[j]; #else assert(0); // you are probably trying to use VF topology in a vertex without it return *((FFTYPE **)(_flags)); #endif } inline const FFTYPE * const VFp( const int j ) const { assert( (_flags & DELETED) == 0 ); assert( (_flags & NOTREAD) == 0 ); assert(j>=0); assert(j<3); #ifdef __VCGLIB_FACE_AV return _fvp[j]; #elif defined(__VCGLIB_FACE_AS) return fs[j]; #else assert(0); static FFTYPE * const DummyVal=0; return DummyVal; #endif } inline const FFTYPE * cVFp( const int j ) const {return VFp(j);} /** Return the index that the face have in the j-th adjacent face. @param j Index of the edge. */ inline char & FFi( const int j ) { assert( (_flags & DELETED) == 0 ); assert( (_flags & NOTREAD) == 0 ); assert( (_flags & NOTWRITE) == 0 ); assert(j>=0); assert(j<3); #if defined(__VCGLIB_FACE_AF) return _ffi[j]; #elif defined(__VCGLIB_FACE_AS) return zs[j]; #else assert(0); return *(char *)&_flags; // tanto per farlo compilare... #endif } inline const char & FFi( const int j ) const { assert( (_flags & DELETED) == 0 ); assert( (_flags & NOTREAD) == 0 ); assert(j>=0); assert(j<3); #if defined(__VCGLIB_FACE_AF) return _ffi[j]; #elif defined(__VCGLIB_FACE_AS) return zs[j]; #else assert(0); return *(char *)&_flags; #endif } inline const char & cFFi( const int j ) const {return FFi(j);} /** Return the index that the face have in the j-th adjacent face. @param j Index of the edge. */ inline char & UberZ( const int j ) { assert(j>=0); assert(j<3); #if defined(__VCGLIB_FACE_AF) return _ffi[j]; #elif defined(__VCGLIB_FACE_AS) return zs[j]; #else assert(0); return *(char *)&_flags; #endif } inline const char & UberZ( const int j ) const { assert(j>=0); assert(j<3); #if defined(__VCGLIB_FACE_AF) return _ffi[j]; #elif defined(__VCGLIB_FACE_AS) return zs[j]; #else assert(0); return *(char *)&_flags; #endif } inline char & VFi( const int j ) { assert( (_flags & DELETED) == 0 ); assert( (_flags & NOTREAD) == 0 ); assert( (_flags & NOTWRITE) == 0 ); assert(j>=0); assert(j<3); #ifdef __VCGLIB_FACE_AV return _fvi[j]; #elif defined(__VCGLIB_FACE_AS) return zs[j]; #else assert(0); return *(char *)&_flags; #endif } inline const char & VFi( const int j ) const { assert( (_flags & DELETED) == 0 ); assert( (_flags & NOTREAD) == 0 ); assert(j>=0); assert(j<3); #ifdef __VCGLIB_FACE_AV return _fvi[j]; #elif defined(__VCGLIB_FACE_AS) return zs[j]; #else assert(0); return *(char *)&_flags; #endif } //@} /***********************************************/ /** @name Mark blah blah **/ //@{ #ifdef __VCGLIB_FACE_FM /// Incremental mark (defines if FACE_I is defined) int imark; inline int & IMark() { assert( (_flags & DELETED) == 0 ); assert( (_flags & NOTREAD) == 0 ); assert( (_flags & NOTWRITE) == 0 ); return imark; } inline const int & IMark() const { assert( (_flags & DELETED) == 0 ); assert( (_flags & NOTREAD) == 0 ); return imark; } #endif // Mark /// Initialize the imark system of the face inline void InitIMark() { #ifdef __VCGLIB_FACE_FM imark = 0; #endif } //@} /***********************************************/ /** @name Flags blah blah **/ //@{ enum { // This bit indicate that the face is deleted from the mesh DELETED = 0x00000001, // cancellato // This bit indicate that the face of the mesh is not readable NOTREAD = 0x00000002, // non leggibile (ma forse modificabile) // This bit indicate that the face is not modifiable NOTWRITE = 0x00000004, // non modificabile (ma forse leggibile) // This bit indicate that the face is modified SELECTED = 0x00000020, // Selection _flags // Border _flags, it is assumed that BORDERi = BORDER0<>1; return true; } assert(0); return false; } void ClearFlags() {_flags=0;} /// Return the _flags. inline int & Flags () { assert( (_flags & DELETED) == 0 ); assert( (_flags & NOTREAD) == 0 ); return _flags; } inline const int & Flags () const { assert( (_flags & DELETED) == 0 ); assert( (_flags & NOTREAD) == 0 ); return _flags; } /// Ritorna il _flags senza effettuare alcun controllo sui relativi bit inline int & UberFlags() { return _flags; } inline const int UberFlags() const { return _flags; } /// This function checks if the face is deleted bool IsD() const {return (_flags & DELETED) != 0;} /// This function mark the face as deleted void SetD() {_flags |=DELETED;} /// This function mark the face as not deleted void ClearD() {_flags &= (~DELETED);} /// This function checks if the face is deleted bool IsDeleted() const {return IsD();} /// This function checks if the face is readable bool IsR() const {return (_flags & NOTREAD) == 0;} /// This function marks the face as readable void SetR() {_flags &= (~NOTREAD);} /// This function marks the face as not readable void ClearR() {_flags |=NOTREAD;} /// This function checks if the face is readable bool IsW() const {return (_flags & NOTWRITE)== 0;} /// This function marks the vertex as not writable void SetW() {_flags &=(~NOTWRITE);} /// This function marks the face as not writable void ClearW() {_flags |=NOTWRITE;} /// This funcion checks whether the face is both readable and modifiable bool IsRW() const {return (_flags & (NOTREAD | NOTWRITE)) == 0;} /// This function checks if the face is selected bool IsS() const {return (_flags & SELECTED) != 0;} /// This function select the face void SetS() {_flags |=SELECTED;} /// This funcion execute the inverse operation of SetS() void ClearS() {_flags &= (~SELECTED);} /// This function checks if the face is selected bool IsB(int i) const {return (_flags & (BORDER0<P() ); bb.Add( v[1]->P() ); bb.Add( v[2]->P() ); } /***********************************************/ /** @name Reflection Functions Static functions that give information about the current vertex type. Reflection is a mechanism making it possible to investigate yourself. Reflection is used to investigate format of objects at runtime, invoke methods and access fields of these objects. Here we provide static const functions that are resolved at compile time and they give information about the data (normal, color etc.) supported by the current vertex type. **/ //@{ static bool HasFlags() { return true; } static bool HasFaceNormal() { #ifdef __VCGLIB_FACE_FN return true; #else return false; #endif } static bool HasFaceQuality() { #ifdef __VCGLIB_FACE_FQ return true; #else return false; #endif } static bool HasFaceColor() { #ifdef __VCGLIB_FACE_FC return true; #else return false; #endif } static bool HasEdgePlane() { #ifdef __VCGLIB_FACE_RT return true; #else return false; #endif } static bool HasFFAdjacency() { #if (defined(__VCGLIB_FACE_AF) || defined(__VCGLIB_FACE_AS)) return true; #else return false; #endif } static bool HasVFAdjacency() { #if (defined(__VCGLIB_FACE_AV) || defined(__VCGLIB_FACE_AS)) return true; #else return false; #endif } static bool HasSharedAdjacency() { #if defined(__VCGLIB_FACE_AS) return true; #else return false; #endif } static bool HasFaceMark() { #ifdef __VCGLIB_FACE_FC return true; #else return false; #endif } static bool HasWedgeColor() { #ifdef __VCGLIB_FACE_WC return true; #else return false; #endif } static bool HasWedgeTexCoord() { #ifdef __VCGLIB_FACE_WT return true; #else return false; #endif } static bool HasWedgeNormal() { #ifdef __VCGLIB_FACE_WN return true; #else return false; #endif } //@} /// operator to compare two faces inline bool operator == ( const FFTYPE & f ) const { for(int i=0; i<3; ++i) if( (V(i) != f.V(0)) && (V(i) != f.V(1)) && (V(i) != f.V(2)) ) return false; return true; } /** Calcola i coefficienti della combinazione convessa. @param bq Punto appartenente alla faccia @param a Valore di ritorno per il vertice V(0) @param b Valore di ritorno per il vertice V(1) @param _c Valore di ritorno per il vertice V(2) @return true se bq appartiene alla faccia, false altrimenti */ bool InterpolationParameters(const CoordType & bq, ScalarType &a, ScalarType &b, ScalarType &_c ) const { const ScalarType EPSILON = ScalarType(0.000001); #define x1 (cV(0)->P()[0]) #define y1 (cV(0)->P()[1]) #define z1 (cV(0)->P()[2]) #define x2 (cV(1)->P()[0]) #define y2 (cV(1)->P()[1]) #define z2 (cV(1)->P()[2]) #define x3 (cV(2)->P()[0]) #define y3 (cV(2)->P()[1]) #define z3 (cV(2)->P()[2]) #define px (bq[0]) #define py (bq[1]) #define pz (bq[2]) ScalarType t1 = px*y2; ScalarType t2 = px*y3; ScalarType t3 = py*x2; ScalarType t4 = py*x3; ScalarType t5 = x2*y3; ScalarType t6 = x3*y2; ScalarType t8 = x1*y2; ScalarType t9 = x1*y3; ScalarType t10 = y1*x2; ScalarType t11 = y1*x3; ScalarType t13 = t8-t9-t10+t11+t5-t6; if(fabs(t13)>=EPSILON) { ScalarType t15 = px*y1; ScalarType t16 = py*x1; a = (t1 -t2-t3 +t4+t5-t6 )/t13; b = -(t15-t2-t16+t4+t9-t11)/t13; _c = (t15-t1-t16+t3+t8-t10)/t13; return true; } t1 = px*z2; t2 = px*z3; t3 = pz*x2; t4 = pz*x3; t5 = x2*z3; t6 = x3*z2; t8 = x1*z2; t9 = x1*z3; t10 = z1*x2; t11 = z1*x3; t13 = t8-t9-t10+t11+t5-t6; if(fabs(t13)>=EPSILON) { ScalarType t15 = px*z1; ScalarType t16 = pz*x1; a = (t1 -t2-t3 +t4+t5-t6 )/t13; b = -(t15-t2-t16+t4+t9-t11)/t13; _c = (t15-t1-t16+t3+t8-t10)/t13; return true; } t1 = pz*y2; t2 = pz*y3; t3 = py*z2; t4 = py*z3; t5 = z2*y3; t6 = z3*y2; t8 = z1*y2; t9 = z1*y3; t10 = y1*z2; t11 = y1*z3; t13 = t8-t9-t10+t11+t5-t6; if(fabs(t13)>=EPSILON) { ScalarType t15 = pz*y1; ScalarType t16 = py*z1; a = (t1 -t2-t3 +t4+t5-t6 )/t13; b = -(t15-t2-t16+t4+t9-t11)/t13; _c = (t15-t1-t16+t3+t8-t10)/t13; return true; } #undef x1 #undef y1 #undef z1 #undef x2 #undef y2 #undef z2 #undef x3 #undef y3 #undef z3 #undef px #undef py #undef pz return false; } /// Return the DOUBLE of the area of the face // NOTE the old Area function has been removed to intentionally // cause compiling error that will help people to check their code... // A some people used Area assuming that it returns the double and some not. // So please check your codes!!! // And please DO NOT Insert any Area named function here! ScalarType DoubleArea() const { return ( (V(1)->cP() - V(0)->cP()) ^ (V(2)->cP() - V(0)->P()) ).Norm(); } CoordType Barycenter() const { return (V(0)->P()+V(1)->P()+V(2)->P())/ScalarType(3.0); } Sphere3 SmallestEnclosingSphere() const { return SmallestEnclosing::SphereOfTriangle(*this); } ScalarType Perimeter() const { return Distance(V(0)->P(),V(1)->P())+ Distance(V(1)->P(),V(2)->P())+ Distance(V(2)->P(),V(0)->P()); } /// Return the _q of the face, the return value is in [0,sqrt(3)/2] = [0 - 0.866.. ] ScalarType QualityFace( ) const { return Quality(V(0)->cP(), V(1)->cP(), V(2)->cP()); /* CoordType d10 = V(1)->P() - V(0)->P(); CoordType d20 = V(2)->P() - V(0)->P(); CoordType d12 = V(1)->P() - V(2)->P(); CoordType x = d10^d20; ScalarType a = Norm( x ); // doppio dell' Area ScalarType b; b = Norm2( d10 ); ScalarType t = b; t = Norm2( d20 ); if( b & Plane(){return plane;}; Plane3 cPlane()const{return plane;}; CoordType edges[3];; Plane3 plane; #endif /// return the index [0..2] of a vertex in a face inline int VertexIndex( const VertexType * w ) const { if( v[0]==w ) return 0; else if( v[1]==w ) return 1; else if( v[2]==w ) return 2; else return -1; } }; //end Class #ifndef __VCG_FACE_BASE_SINGLE #define __VCG_FACE_BASE_SINGLE // Note that while the whole file can be included more than once, this portion of the file MUST be included once /// Calculate the normal to the face, the value is store in the field _n of the face namespace face { template void ComputeNormal(FaceType &f) { f.N() = vcg::Normal< FaceType >(f); } template void ComputeNormalizedNormal(FaceType &f) { f.N() = vcg::NormalizedNormal< FaceType >(f); } } // end namespace face //@} #endif } // end namespace vcg #endif qutemol/vcg/vcg/simplex/face/pos.h0000444000175000017500000003646410777634524015545 0ustar mbamba/**************************************************************************** * VCGLib o o * * Visual and Computer Graphics Library o o * * _ O _ * * Copyright(C) 2004 \/)\/ * * Visual Computing Lab /\/| * * ISTI - Italian National Research Council | * * \ * * All rights reserved. * * * * 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. * * * * 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 (http://www.gnu.org/licenses/gpl.txt) * * for more details. * * * ****************************************************************************/ /**************************************************************************** History $Log: pos.h,v $ Revision 1.33 2008/04/11 10:11:32 cignoni better comments, renamed I() -> E() removed wrong coherent function Revision 1.32 2007/10/17 19:46:50 cignoni Added I() access function for the z member to the pos Revision 1.31 2007/05/28 14:09:41 fiorin Added Set method which takes a face pointer and a vertex pointer. Revision 1.30 2007/05/16 15:11:32 fiorin Replaced ambigous StarSize method with NumberOfIncidentVertices and NumberOfIncidentFaces Revision 1.29 2007/04/20 12:40:31 cignoni Corrected V() operator. It was plainly wrong. Luckly enough it was not very used Revision 1.28 2007/01/11 10:37:08 cignoni Added include assert.h Revision 1.27 2007/01/02 10:06:53 giec Added access functions F() Revision 1.26 2006/12/29 13:13:00 giec Corrected wrong assert in V(i) access function Revision 1.25 2006/12/04 16:06:12 cignoni Added FFlip() and const VFlip() operators Revision 1.24 2006/11/13 01:57:23 cignoni Added a missing prototype to ismanifold Revision 1.23 2006/11/09 17:22:56 cignoni Added ismanifold Revision 1.22 2006/10/07 14:24:26 cignoni Explained the use of V() operator of a pos Revision 1.21 2006/09/25 09:57:49 cignoni Better comment on usage of VF iterators Revision 1.20 2005/12/15 11:57:48 corsini Replace Pos with PosType Revision 1.19 2005/12/15 11:19:00 corsini Fix operators Revision 1.18 2005/12/15 10:53:16 corsini Add constructor which takes as input a face and a vertex Revision 1.17 2005/10/16 23:30:39 ponchio IsBorder(...) declaration needed. Revision 1.16 2005/10/13 09:29:10 cignoni Removed the reference to Deprecated f->IsBorder(i) now everyone should use IsBorder(*f,i); Revision 1.15 2005/01/03 11:22:31 cignoni Added better documentation (with an example and the V0 V1 V2 access members Revision 1.14 2004/10/28 00:50:48 cignoni Better Doxygen documentation Revision 1.13 2004/10/18 17:14:42 ganovelli error FFP -> FFp Revision 1.12 2004/09/14 19:46:10 ganovelli constructor added Revision 1.11 2004/08/25 15:15:27 ganovelli minor changes to comply gcc compiler (typename's and stuff) Revision 1.10 2004/07/27 09:47:49 cignoni Added V() access function instead of V(0) Revision 1.9 2004/07/18 07:45:30 cignoni Removed two const modifiers from the VFIterator Revision 1.8 2004/07/15 12:03:07 ganovelli minor changes Revision 1.7 2004/07/15 11:28:44 ganovelli basefacetype to facetype Revision 1.6 2004/07/06 06:25:44 cignoni changed the VFIterator ++ to return a facepointer instead of a bool Revision 1.5 2004/06/02 16:25:45 ganovelli changed F(.. to FFp changed Z( to FFi( Revision 1.4 2004/05/10 15:21:47 cignoni Added a constructor without vertex pointer Revision 1.3 2004/05/10 13:41:57 cignoni Added VFIterator Revision 1.2 2004/03/12 15:22:28 cignoni Written some documentation and added to the trimes doxygen module Revision 1.1 2004/03/10 08:32:30 cignoni Initial commit ****************************************************************************/ /** \file face/pos.h * Definition of vcg:face::Pos class. * This file contain the definition of vcg::face::Pos class and the derived vcg::face::PosN class. */ #ifndef __VCG_FACE_POS #define __VCG_FACE_POS #include namespace vcg { namespace face { /** \addtogroup face */ /*@{*/ // Needed Prototypes (pos is include before topology) template bool IsBorder(FaceType const & f, const int j ); template bool IsManifold(FaceType const & f, const int j ); /** Templated over the class face, it stores a \em position over a face in a mesh. It contain a pointer to the current face, the index of one edge and a pointer to one of the vertices of the edge. See also the JumpingPos in jumping_pos.h for an iterator that loops around the faces of a vertex without requiring the VF topology. */ template class Pos { public: /// The vertex type typedef typename FaceType::VertexType VertexType; ///The Pos type typedef Pos PosType; /// The scalar type typedef typename VertexType::ScalarType ScalarType; /// Pointer to the face of the half-edge typename FaceType::FaceType *f; /// Index of the edge int z; /// Pointer to the vertex VertexType *v; /// Default constructor Pos(){} /// Constructor which associates the half-edge element with a face, its edge and its vertex Pos(FaceType * const fp, int const zp, VertexType * const vp){f=fp; z=zp; v=vp;} Pos(FaceType * const fp, int const zp){f=fp; z=zp; v=f->V(zp);} Pos(FaceType * const fp, VertexType * const vp) { f = fp; v = vp; if (f->V(0) == v) z = 2; else if (f->V(1) == v) z = 0; else if (f->V(2) == v) z = 1; } // Official Access functions functions VertexType *& V(){ return v; } int & E(){ return z; } FaceType *& F(){ return f; } // Returns the face index of the vertex inside the face. // Note that this is DIFFERENT from using the z member that denotes the edge index inside the face. // It should holds that Vind != (z+1)%3 && Vind == z || Vind = z+2%3 int VInd() { if(v==f->V(0)) return 0; if(v==f->V(1)) return 1; if(v==f->V(2)) return 2; assert(0); } /// Operator to compare two half-edge inline bool operator == ( PosType const & p ) const { return (f==p.f && z==p.z && v==p.v); } /// Operator to compare two half-edge inline bool operator != ( PosType const & p ) const { return (f!=p.f || z!=p.z || v!=p.v); } /// Operator to order half-edge; it's compare at the first the face pointers, then the index of the edge and finally the vertex pointers inline bool operator <= ( PosType const & p) const { return (f!=p.f)?(fFFp(z); z = t->FFi(z); } // Paolo Cignoni 19/6/99 // Si muove sulla faccia adiacente a f, lungo uno spigolo che // NON e' j, e che e' adiacente a v // in questo modo si scandiscono tutte le facce incidenti in un // vertice f facendo Next() finche' non si ritorna all'inizio // Nota che sul bordo rimbalza, cioe' se lo spigolo !=j e' di bordo // restituisce sempre la faccia f ma con nj che e' il nuovo spigolo di bordo // vecchi parametri: FaceType * & f, VertexType * v, int & j /// It moves on the adjacent face incident to v, via a different edge that j void NextE() { assert( f->V(z)==v || f->V((z+1)%3)==v ); // L'edge j deve contenere v FlipE(); FlipF(); assert( f->V(z)==v || f->V((z+1)%3)==v ); } // Cambia edge mantenendo la stessa faccia e lo stesso vertice /// Changes edge maintaining the same face and the same vertex void FlipE() { assert(f->V((z+2)%3)!=v && (f->V((z+1)%3)==v || f->V((z+0)%3)==v)); if(f->V((z+1)%3)==v) z=(z+1)%3; else z=(z-1+3)%3; assert(f->V((z+2)%3)!=v && (f->V((z+1)%3)==v || f->V((z+0)%3)==v)); } // Cambia Faccia mantenendo lo stesso vertice e lo stesso edge // Vale che he.flipf.flipf= he // Se l'he e' di bordo he.flipf()==he // Si puo' usare SOLO se l'edge e' 2manifold altrimenti // si deve usare nextf /// Changes face maintaining the same vertex and the same edge void FlipF() { assert( f->FFp(z)->FFp(f->FFi(z))==f ); // two manifoldness check assert(f->V((z+2)%3)!=v && (f->V((z+1)%3)==v || f->V((z+0)%3)==v)); FaceType *nf=f->FFp(z); int nz=f->FFi(z); assert(nf->V((nz+2)%3)!=v && (nf->V((nz+1)%3)==v || nf->V((nz+0)%3)==v)); f=nf; z=nz; assert(f->V((z+2)%3)!=v && (f->V((z+1)%3)==v || f->V((z+0)%3)==v)); } /// Changes vertex maintaining the same face and the same edge void FlipV() { assert(f->V((z+2)%3)!=v && (f->V((z+1)%3)==v || f->V((z+0)%3)==v)); if(f->V((z+1)%3)==v) v=f->V((z+0)%3); else v=f->V((z+1)%3); assert(f->V((z+2)%3)!=v && (f->V((z+1)%3)==v || f->V((z+0)%3)==v)); } // return the vertex that it should have if we make FlipV; VertexType *VFlip() { assert(f->V((z+2)%3)!=v && (f->V((z+1)%3)==v || f->V((z+0)%3)==v)); if(f->V((z+1)%3)==v) return f->V((z+0)%3); else return f->V((z+1)%3); } // return the vertex that it should have if we make FlipV; const VertexType *VFlip() const { assert(f->cV((z+2)%3)!=v && (f->cV((z+1)%3)==v || f->cV((z+0)%3)==v)); if(f->cV((z+1)%3)==v) return f->cV((z+0)%3); else return f->cV((z+1)%3); } // return the face that it should have if we make FlipF; const FaceType *FFlip() const { assert( f->FFp(z)->FFp(f->FFi(z))==f ); assert(f->V((z+2)%3)!=v && (f->V((z+1)%3)==v || f->V((z+0)%3)==v)); FaceType *nf=f->FFp(z); return nf; } // Trova il prossimo half-edge di bordo (nhe) // tale che // --nhe.f adiacente per vertice a he.f // --nhe.v adiacente per edge di bordo a he.v // l'idea e' che se he e' un half edge di bordo // si puo scorrere tutto un bordo facendo // // hei=he; // do // hei.Nextb() // while(hei!=he); /// Finds the next half-edge border void NextB( ) { assert(f->V((z+2)%3)!=v && (f->V((z+1)%3)==v || f->V((z+0)%3)==v)); assert(f->FFp(z)==f); // f is border along j // Si deve cambiare faccia intorno allo stesso vertice v //finche' non si trova una faccia di bordo. do NextE(); while(!IsBorder()); // L'edge j e' di bordo e deve contenere v assert(IsBorder() &&( f->V(z)==v || f->V((z+1)%3)==v )); FlipV(); assert(f->V((z+2)%3)!=v && (f->V((z+1)%3)==v || f->V((z+0)%3)==v)); assert(f->FFp(z)==f); // f is border along j } /// Checks if the half-edge is of border bool IsBorder() { return face::IsBorder(*f,z); } bool IsManifold() { return face::IsManifold(*f,z); } /*! * Returns the number of vertices incident on the vertex pos is currently pointing to. */ int NumberOfIncidentVertices() { int count = 0; bool on_border = false; CheckIncidentFaces(count, on_border); if(on_border) return (count/2)+1; else return count; } /*! * Returns the number of faces incident on the vertex pos is currently pointing to. */ int NumberOfIncidentFaces() { int count = 0; bool on_border = false; CheckIncidentFaces(count, on_border); if(on_border) return count/2; else return count; } /** Function to inizialize an half-edge. @param fp Puntatore alla faccia @param zp Indice dell'edge @param vp Puntatore al vertice */ void Set(FaceType * const fp, int const zp, VertexType * const vp) { f=fp;z=zp;v=vp; assert(f->V((z+2)%3)!=v && (f->V((z+1)%3)==v || f->V((z+0)%3)==v)); } void Set(FaceType * const pFace, VertexType * const pVertex) { f = pFace; v = pVertex; if (f->V(0) == v) z = 2; else if (f->V(1) == v) z = 0; else if (f->V(2) == v) z = 1; } void Assert() #ifdef _DEBUG { FaceType ht=*this; ht.FlipF(); ht.FlipF(); assert(ht==*this); ht.FlipE(); ht.FlipE(); assert(ht==*this); ht.FlipV(); ht.FlipV(); assert(ht==*this); } #else {} #endif protected: void CheckIncidentFaces(int & count, bool & on_border) { PosType ht = *this; do { ++count; ht.NextE(); if(ht.IsBorder()) on_border=true; } while (ht != *this); } }; template /** Class PosN. This structure is equivalent to a Pos, but it contains a normal. @param FaceType (Template-Parameter) Specifies the type of the faces */ class PosN : public Pos { public: typedef typename FaceType::CoordType CoordType; //normale per visualizzazione creaseangle CoordType normal; }; /** Class VFIterator. This class is used as an iterator over the VF adjacency. It allow to easily traverse all the faces around a given vertex v; The faces are traversed in no particular order. No Manifoldness requirement. typical example: VertexPointer v; vcg::face::VFIterator vfi(v); for (;!vfi.End();++vfi) vfi.F()->ClearV(); // Alternative vcg::face::VFIterator vfi(f, 1); while (!vfi.End()){ vfi.F()->ClearV(); ++vfi; } See also the JumpingPos in jumping_pos.h for an iterator that loops around the faces of a vertex using FF topology and without requiring the VF topology. */ template class VFIterator { public: /// The vertex type typedef typename FaceType::VertexType VertexType; /// The Base face type typedef FaceType VFIFaceType; /// The vector type typedef typename VertexType::CoordType CoordType; /// The scalar type typedef typename VertexType::ScalarType ScalarType; /// Pointer to the face of the half-edge FaceType *f; /// Index of the vertex int z; /// Default constructor VFIterator(){} /// Constructor which associates the half-edge elementet with a face and its vertex VFIterator(FaceType * _f, const int & _z){f = _f; z = _z;} /// Constructor which takes a pointer to vertex VFIterator(VertexType * _v){f = _v->VFp(); z = _v->VFi();} VFIFaceType *& F() { return f;} int & I() { return z;} // Access to the vertex. Having a VFIterator vfi, it corresponds to // vfi.V() = vfi.F()->V(vfi.I()) inline VertexType *V() const { return f->V(z);} inline VertexType * const & V0() const { return f->V0(z);} inline VertexType * const & V1() const { return f->V1(z);} inline VertexType * const & V2() const { return f->V2(z);} bool End() const {return f==0;} VFIFaceType *operator++() { FaceType* t = f; f = f->VFp(z); z = t->VFi(z); return f; } }; /*@}*/ } // end namespace } // end namespace #endif qutemol/vcg/vcg/simplex/face/with/0000755000175000017500000000000011633404241015512 5ustar mbambaqutemol/vcg/vcg/simplex/face/with/fc.h0000444000175000017500000000031210023350577016251 0ustar mbamba#ifndef __VCGLIB_FACE_FC_TYPE #define __VCGLIB_FACE_FC_TYPE #define FACE_TYPE FaceFC #define __VCGLIB_FACE_FC #include #undef FACE_TYPE #undef __VCGLIB_FACE_FC #endif qutemol/vcg/vcg/simplex/face/with/affn.h0000444000175000017500000000040010234156515016571 0ustar mbamba#ifndef __VCGLIB_FACE_AFFN_TYPE #define __VCGLIB_FACE_AFFN_TYPE #define FACE_TYPE FaceAFFN #define __VCGLIB_FACE_AF #define __VCGLIB_FACE_FN #include #undef FACE_TYPE #undef __VCGLIB_FACE_AF #undef __VCGLIB_FACE_FN #endifqutemol/vcg/vcg/simplex/face/with/avfn.h0000444000175000017500000000040110050167476016616 0ustar mbamba#ifndef __VCGLIB_FACE_AVFN_TYPE #define __VCGLIB_FACE_AVFN_TYPE #define FACE_TYPE FaceAVFN #define __VCGLIB_FACE_FN #define __VCGLIB_FACE_AV #include #undef FACE_TYPE #undef __VCGLIB_FACE_FN #undef __VCGLIB_FACE_AV #endif qutemol/vcg/vcg/simplex/face/with/afav.h0000444000175000017500000000040110046451170016571 0ustar mbamba#ifndef __VCGLIB_FACE_AFAV_TYPE #define __VCGLIB_FACE_AFAV_TYPE #define FACE_TYPE FaceAFAV #define __VCGLIB_FACE_AV #define __VCGLIB_FACE_AF #include #undef FACE_TYPE #undef __VCGLIB_FACE_AF #undef __VCGLIB_FACE_AV #endif qutemol/vcg/vcg/simplex/face/with/fn.h0000444000175000017500000000031210422111130016243 0ustar mbamba#ifndef __VCGLIB_FACE_FN_TYPE #define __VCGLIB_FACE_FN_TYPE #define FACE_TYPE FaceFN #define __VCGLIB_FACE_FN #include #undef FACE_TYPE #undef __VCGLIB_FACE_FN #endif qutemol/vcg/vcg/simplex/face/with/afavfcfnfmrt.h0000444000175000017500000000073210230735570020332 0ustar mbamba#ifndef __VCGLIB_FACE_AFAVFCFNFMRT_TYPE #define __VCGLIB_FACE_AFAVFCFNFMRT_TYPE #define FACE_TYPE FaceAFAVFCFNFMRT #define __VCGLIB_FACE_AF #define __VCGLIB_FACE_AV #define __VCGLIB_FACE_FC #define __VCGLIB_FACE_FN #define __VCGLIB_FACE_FM #define __VCGLIB_FACE_RT #include #undef FACE_TYPE #undef __VCGLIB_FACE_AF #undef __VCGLIB_FACE_AV #undef __VCGLIB_FACE_FC #undef __VCGLIB_FACE_FN #undef __VCGLIB_FACE_FM #undef __VCGLIB_FACE_RT #endifqutemol/vcg/vcg/simplex/face/with/af.h0000444000175000017500000000031210046213155016242 0ustar mbamba#ifndef __VCGLIB_FACE_AF_TYPE #define __VCGLIB_FACE_AF_TYPE #define FACE_TYPE FaceAF #define __VCGLIB_FACE_AF #include #undef FACE_TYPE #undef __VCGLIB_FACE_AF #endif qutemol/vcg/vcg/simplex/face/with/fm.h0000444000175000017500000000034610427660562016300 0ustar mbamba#ifndef __VCGLIB_FACE_FM_TYPE #define __VCGLIB_FACE_FM_TYPE #define FACE_TYPE FaceFM #define __VCGLIB_FACE_FM #include #undef FACE_TYPE #undef __VCGLIB_FACE_FM #endif /* __VCGLIB_FACE_FM_TYPE */ qutemol/vcg/vcg/simplex/face/with/afavfnfmrtfq.h0000444000175000017500000000073310575271657020366 0ustar mbamba#ifndef __VCGLIB_FACE_AFAVFNFMRTFQ_TYPE #define __VCGLIB_FACE_AFAVFNFMRTFQ_TYPE #define FACE_TYPE FaceAFAVFNFMRTFQ #define __VCGLIB_FACE_AF #define __VCGLIB_FACE_FN #define __VCGLIB_FACE_AV #define __VCGLIB_FACE_FM #define __VCGLIB_FACE_RT #define __VCGLIB_FACE_FQ #include #undef FACE_TYPE #undef __VCGLIB_FACE_AF #undef __VCGLIB_FACE_FN #undef __VCGLIB_FACE_AV #undef __VCGLIB_FACE_FM #undef __VCGLIB_FACE_RT #undef __VCGLIB_FACE_FQ #endif qutemol/vcg/vcg/simplex/face/with/rt.h0000444000175000017500000000031010343335337016306 0ustar mbamba#ifndef __VCGLIB_FACE_RT_TYPE #define __VCGLIB_FACE_RT_TYPE #define FACE_TYPE FaceRT #define __VCGLIB_FACE_RT #include #undef FACE_TYPE #undef __VCGLIB_FACE_RT #endifqutemol/vcg/vcg/simplex/face/with/affc.h0000444000175000017500000000040110046213217016551 0ustar mbamba#ifndef __VCGLIB_FACE_AFFC_TYPE #define __VCGLIB_FACE_AFFC_TYPE #define FACE_TYPE FaceAFFC #define __VCGLIB_FACE_AF #define __VCGLIB_FACE_FC #include #undef FACE_TYPE #undef __VCGLIB_FACE_AF #undef __VCGLIB_FACE_FC #endif qutemol/vcg/vcg/simplex/face/with/afavfn.h0000444000175000017500000000046610050414235017124 0ustar mbamba#ifndef __VCGLIB_FACE_AFAVFN_TYPE #define __VCGLIB_FACE_AFAVFN_TYPE #define FACE_TYPE FaceAFAVFN #define __VCGLIB_FACE_AF #define __VCGLIB_FACE_FN #define __VCGLIB_FACE_AV #include #undef FACE_TYPE #undef __VCGLIB_FACE_AF #undef __VCGLIB_FACE_FN #undef __VCGLIB_FACE_AV #endifqutemol/vcg/vcg/simplex/face/with/afavfnfq.h0000444000175000017500000000055410215336653017463 0ustar mbamba#ifndef __VCGLIB_FACE_AFAVFNFQ_TYPE #define __VCGLIB_FACE_AFAVFNFQ_TYPE #define FACE_TYPE FaceAFAVFNFQ #define __VCGLIB_FACE_AF #define __VCGLIB_FACE_FN #define __VCGLIB_FACE_AV #define __VCGLIB_FACE_FQ #include #undef FACE_TYPE #undef __VCGLIB_FACE_AF #undef __VCGLIB_FACE_FN #undef __VCGLIB_FACE_AV #undef __VCGLIB_FACE_FQ #endifqutemol/vcg/vcg/simplex/face/with/fcfn.h0000444000175000017500000000040310070016056016567 0ustar mbamba#ifndef __VCGLIB_FACE_FCFN_TYPE #define __VCGLIB_FACE_FCFN_TYPE #define FACE_TYPE FaceFCFN #define __VCGLIB_FACE_FC #define __VCGLIB_FACE_FN #include #undef FACE_TYPE #define __VCGLIB_FACE_FC #define __VCGLIB_FACE_FN #endif qutemol/vcg/vcg/simplex/face/with/rtfcfmfn.h0000444000175000017500000000055210051126517017470 0ustar mbamba#ifndef __VCGLIB_FACE_RTFMFN_TYPE #define __VCGLIB_FACE_RTFMFN_TYPE #define FACE_TYPE FaceRTFCFMFN #define __VCGLIB_FACE_RT #define __VCGLIB_FACE_FC #define __VCGLIB_FACE_FM #define __VCGLIB_FACE_FN #include #undef FACE_TYPE #undef __VCGLIB_FACE_RT #undef __VCGLIB_FACE_FC #undef __VCGLIB_FACE_FM #undef __VCGLIB_FACE_FN #endif qutemol/vcg/vcg/simplex/face/with/fmfn.h0000444000175000017500000000040010310304572016576 0ustar mbamba#ifndef __VCGLIB_FACE_FMFN_TYPE #define __VCGLIB_FACE_FMFN_TYPE #define FACE_TYPE FaceFMFN #define __VCGLIB_FACE_FM #define __VCGLIB_FACE_FN #include #undef FACE_TYPE #undef __VCGLIB_FACE_FM #undef __VCGLIB_FACE_FN #endifqutemol/vcg/vcg/simplex/face/with/affm.h0000444000175000017500000000040110262467121016570 0ustar mbamba#ifndef __VCGLIB_FACE_AFFM_TYPE #define __VCGLIB_FACE_AFFM_TYPE #define FACE_TYPE FaceAFFM #define __VCGLIB_FACE_AF #define __VCGLIB_FACE_FM #include #undef FACE_TYPE #undef __VCGLIB_FACE_AF #undef __VCGLIB_FACE_FM #endif qutemol/vcg/vcg/simplex/face/with/afavfnfmrt.h0000444000175000017500000000064310174230415020015 0ustar mbamba#ifndef __VCGLIB_FACE_AFAVFNFMRT_TYPE #define __VCGLIB_FACE_AFAVFNFMRT_TYPE #define FACE_TYPE FaceAFAVFNFMRT #define __VCGLIB_FACE_AF #define __VCGLIB_FACE_FN #define __VCGLIB_FACE_AV #define __VCGLIB_FACE_FM #define __VCGLIB_FACE_RT #include #undef FACE_TYPE #undef __VCGLIB_FACE_AF #undef __VCGLIB_FACE_FN #undef __VCGLIB_FACE_AV #undef __VCGLIB_FACE_FM #undef __VCGLIB_FACE_RT #endifqutemol/vcg/vcg/simplex/face/with/av.h0000444000175000017500000000031210046213252016260 0ustar mbamba#ifndef __VCGLIB_FACE_AV_TYPE #define __VCGLIB_FACE_AV_TYPE #define FACE_TYPE FaceAV #define __VCGLIB_FACE_AV #include #undef FACE_TYPE #undef __VCGLIB_FACE_AV #endif qutemol/vcg/vcg/simplex/face/with/afavfnfqrt.h0000444000175000017500000000064310217767474020043 0ustar mbamba#ifndef __VCGLIB_FACE_AFAVFNFQRT_TYPE #define __VCGLIB_FACE_AFAVFNFQRT_TYPE #define FACE_TYPE FaceAFAVFNFQRT #define __VCGLIB_FACE_AF #define __VCGLIB_FACE_FN #define __VCGLIB_FACE_AV #define __VCGLIB_FACE_FQ #define __VCGLIB_FACE_RT #include #undef FACE_TYPE #undef __VCGLIB_FACE_AF #undef __VCGLIB_FACE_FN #undef __VCGLIB_FACE_AV #undef __VCGLIB_FACE_FQ #undef __VCGLIB_FACE_RT #endifqutemol/vcg/vcg/simplex/face/with/wt.h0000444000175000017500000000032310327771603016321 0ustar mbamba#ifndef __VCGLIB_FACE_WT_TYPE #define __VCGLIB_FACE_WT_TYPE #define FACE_TYPE FaceWT #define __VCGLIB_FACE_WT #include #undef FACE_TYPE #undef __VCGLIB_FACE_WT #endif qutemol/vcg/vcg/simplex/face/with/readme.txt0000444000175000017500000000471510214305370017512 0ustar mbamba/**************************************************************************** * VCGLib o o * * Visual and Computer Graphics Library o o * * _ O _ * * Copyright(C) 2004 \/)\/ * * Visual Computing Lab /\/| * * ISTI - Italian National Research Council | * * \ * * All rights reserved. * * * * 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. * * * * 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 (http://www.gnu.org/licenses/gpl.txt) * * for more details. * * * ****************************************************************************/ This folders contains most common FACE configuration files. The name of the file specifies the members that are added to the vertex class. The name is a sequence of letter pairs, in strict alphabetical order. The possible admitted letters pairs are: AF - Face-Face adjacency AS - Shared Vertex-Face and Face-Face Adjacency AV - Vertex-face adjacency FC - Per-Face Color FM - Per-Face Incremental Mark FN - Per-Face Normal FQ - Per-Face Quality RT - Data for Optimized Point-Face Distance and Ray-Tracing Stuff WC - Per-Wedge Color WN - Per-Wedge Normal WQ - Per-Wedge Quality WT - Per-Wedge Texture Coords E.g. #include generate a type VertexAFFNWT that can store F-F adjacency, Per-face normal and color and per-wedge texture coords. qutemol/vcg/vcg/simplex/face/with/avfnfq.h0000444000175000017500000000047010215435116017143 0ustar mbamba#ifndef __VCGLIB_FACE_AVFNFQ_TYPE #define __VCGLIB_FACE_AVFNFQ_TYPE #define FACE_TYPE FaceAVFNFQ #define __VCGLIB_FACE_FN #define __VCGLIB_FACE_AV #define __VCGLIB_FACE_FQ #include #undef FACE_TYPE #undef __VCGLIB_FACE_FN #undef __VCGLIB_FACE_AV #undef __VCGLIB_FACE_FQ #endif qutemol/vcg/vcg/simplex/face/with/fcfmfnwcwnwt.h0000444000175000017500000000100310506747177020404 0ustar mbamba#ifndef __VCGLIB_FACE_FCFMFNWCWNWT_TYPE #define __VCGLIB_FACE_FCFMFNWCWNWT_TYPE #define FACE_TYPE FaceFCFMFNWCWNWT #define __VCGLIB_FACE_FC #define __VCGLIB_FACE_FM #define __VCGLIB_FACE_FN #define __VCGLIB_FACE_WC #define __VCGLIB_FACE_WN #define __VCGLIB_FACE_WT #include #undef __VCGLIB_FACE_FC #undef __VCGLIB_FACE_FM #undef __VCGLIB_FACE_FN #undef __VCGLIB_FACE_WC #undef __VCGLIB_FACE_WN #undef __VCGLIB_FACE_WT #undef FACE_TYPE #endif /* __VCGLIB_FACE_FCFMFNWCWNWT_TYPE */ qutemol/vcg/vcg/simplex/face/with/rtfmfn.h0000444000175000017500000000046710045601257017166 0ustar mbamba#ifndef __VCGLIB_FACE_RTFMFN_TYPE #define __VCGLIB_FACE_RTFMFN_TYPE #define FACE_TYPE FaceRTFMFN #define __VCGLIB_FACE_RT #define __VCGLIB_FACE_FM #define __VCGLIB_FACE_FN #include #undef FACE_TYPE #undef __VCGLIB_FACE_RT #undef __VCGLIB_FACE_FM #undef __VCGLIB_FACE_FN #endif qutemol/vcg/vcg/simplex/face/with/affnfmrt.h0000444000175000017500000000056010233405621017463 0ustar mbamba#ifndef __VCGLIB_FACE_AFAVFNFMRT_TYPE #define __VCGLIB_FACE_AFAVFNFMRT_TYPE #define FACE_TYPE FaceAFFNFMRT #define __VCGLIB_FACE_AF #define __VCGLIB_FACE_FN #define __VCGLIB_FACE_FM #define __VCGLIB_FACE_RT #include #undef FACE_TYPE #undef __VCGLIB_FACE_AF #undef __VCGLIB_FACE_FN #undef __VCGLIB_FACE_FM #undef __VCGLIB_FACE_RT #endifqutemol/vcg/vcg/simplex/face/face.h0000444000175000017500000000430310136165362015611 0ustar mbamba/**************************************************************************** * VCGLib o o * * Visual and Computer Graphics Library o o * * _ O _ * * Copyright(C) 2004 \/)\/ * * Visual Computing Lab /\/| * * ISTI - Italian National Research Council | * * \ * * All rights reserved. * * * * 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. * * * * 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 (http://www.gnu.org/licenses/gpl.txt) * * for more details. * * * ****************************************************************************/ /**************************************************************************** History $Log: face.h,v $ Revision 1.3 2004/10/22 11:11:46 cignoni uppercase error in FACE_TYPE Revision 1.2 2004/07/15 11:31:06 ganovelli overwritten previous version (it was a copy of base.h) First commit... ****************************************************************************/ #ifndef __VCGLIB__BASICFACETYPE #define __VCGLIB__BASICFACETYPE #define FACE_TYPE Face #include #undef FACE_TYPE #endif qutemol/vcg/vcg/simplex/face/jumping_pos.h0000444000175000017500000000774010777634655017276 0ustar mbamba/**************************************************************************** * VCGLib o o * * Visual and Computer Graphics Library o o * * _ O _ * * Copyright(C) 2004 \/)\/ * * Visual Computing Lab /\/| * * ISTI - Italian National Research Council | * * \ * * All rights reserved. * * * * 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. * * * * 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 (http://www.gnu.org/licenses/gpl.txt) * * for more details. * * * ****************************************************************************/ /**************************************************************************** ****************************************************************************/ #ifndef __VCG_JUMPING_FACE_POS #define __VCG_JUMPING_FACE_POS #include #include namespace vcg { namespace face { /** \addtogroup face */ /*@{*/ template < class FACE_TYPE > class JumpingPos : public Pos< FACE_TYPE > { public: // Typedefs typedef FACE_TYPE FaceType; typedef Pos PosType; typedef JumpingPos JumpingPosType; typedef typename FaceType::VertexType VertexType; typedef typename VertexType::CoordType CoordType; typedef typename VertexType::ScalarType ScalarType; using Pos::f; using Pos::z; using Pos::FFlip; public: // Constructors JumpingPos() : Pos() { } JumpingPos(FaceType * const pFace, int const z, VertexType * const pVertex) : Pos(pFace, z, pVertex) { } JumpingPos(FaceType * const pFace, int const z) : Pos(pFace, z) { } JumpingPos(FaceType * const pFace, VertexType * const pVertex) : Pos(pFace, pVertex) { } bool FindBorder() { PosType startPos=*this; do { if(f==FFlip() ) { PosType::FlipE(); return true; // we are on a border } PosType::FlipF(); PosType::FlipE(); } while(*this != startPos); return false; } /*! * Returns the next edge skipping the border * _________ * /\ c | b /\ * / \ | / \ * / d \ | / a \ * /______\|/______\ * v * In this example, if a and d are of-border and the pos is iterating counterclockwise, this method iterate through the faces incident on vertex v, * producing the sequence a, b, c, d, a, b, c, ... */ bool NextFE() { if ( f==FFlip() ) // we are on a border { do { PosType::FlipF(); PosType::FlipE(); } while (f!=FFlip()); PosType::FlipE(); return false; } else { PosType::FlipF(); PosType::FlipE(); return true; } } }; /*@}*/ } // end of namespace face } // end of namespace vcg #endif // __VCG_JUMPING_FACE_POS qutemol/vcg/vcg/simplex/face/distance.h0000444000175000017500000002342610616661326016520 0ustar mbamba/**************************************************************************** * VCGLib o o * * Visual and Computer Graphics Library o o * * _ O _ * * Copyright(C) 2004 \/)\/ * * Visual Computing Lab /\/| * * ISTI - Italian National Research Council | * * \ * * All rights reserved. * * * * 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. * * * * 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 (http://www.gnu.org/licenses/gpl.txt) * * for more details. * * * ****************************************************************************/ /**************************************************************************** History $Log: distance.h,v $ Revision 1.11 2007/05/04 16:44:06 ganovelli changes to comply "plus" types Revision 1.10 2006/01/22 10:06:23 cignoni Corrected use of Area with the unambiguous DoubleArea Revision 1.9 2005/09/28 19:35:06 m_di_benedetto Added class PointDistanceFunctor. Revision 1.8 2005/09/14 12:58:44 pietroni changed min calls to Min of math.h of vcglib Revision 1.7 2005/09/14 09:58:32 pietroni removed vcg::math::Min definition generate warnings Revision 1.6 2005/09/14 09:03:54 pietroni added definition of vcg::math::Min function Revision 1.5 2005/02/02 16:44:34 pietroni 1 warning corrected added casting in const ScalarType EPSILON = ScalarType( 0.000001); Revision 1.4 2005/01/28 12:00:33 cignoni small gcc compiling issues for namespaces Revision 1.3 2005/01/24 15:35:25 cignoni Removed a 'using namespace' Revision 1.2 2005/01/21 17:11:03 pietroni changed Dist Function to PointDistance... the function is on vcg::face::PointDistance this file will contain all distance functions between a face and othe entities Revision 1.1 2004/05/12 18:50:25 ganovelli created ****************************************************************************/ #ifndef __VCGLIB_FACE_DISTANCE #define __VCGLIB_FACE_DISTANCE #include #include namespace vcg { namespace face{ /* Point face distance trova il punto

sulla faccia piu' vicino a , con possibilit di rejection veloce su se la distanza trovata maggiore di Commenti del 12/11/02 Funziona solo se la faccia e di quelle di tipo E (con edge e piano per faccia gia' calcolati) algoritmo: 1) si calcola la proiezione

di q sul piano della faccia 2) se la distanza punto piano e' > rejdist ritorna 3) si lavora sul piano migliore e si cerca di capire se il punto sta dentro il triangolo: a) prodotto vettore tra edge triangolo (v[i+1]-v[i]) e (p-v[i]) b) se il risultato e' negativo (gira in senso orario) allora il punto sta fuori da quella parte e si fa la distanza punto segmento. c) se il risultato sempre positivo allora sta dentro il triangolo 4) e si restituisce la distanza punto /piano gia` calcolata Note sulla robustezza: il calcolo del prodotto vettore e` la cosa piu` delicata: possibili fallimenti quando a^b ~= 0 1) doveva essere <= 0 e viene positivo (q era fuori o sulla linea dell'edge) allora capita che si faccia la distanza punto piano anziche` la distanza punto seg 2) doveva essere > 0 e viene <=0 (q era dentro il triangolo) */ template bool PointDistance( const FaceType &f, const vcg::Point3 & q, typename FaceType::ScalarType & dist, vcg::Point3 & p ) { typedef typename FaceType::ScalarType ScalarType; const ScalarType EPSILON = ScalarType( 0.000001); //const ScalarType EPSILON = 0.00000001; ScalarType b,b0,b1,b2; // Calcolo distanza punto piano ScalarType d = Distance( f.cPlane(), q ); if( d>dist || d<-dist ) // Risultato peggiore: niente di fatto return false; // Calcolo del punto sul piano // NOTA: aggiunto un '-d' in fondo Paolo C. Point3 t = f.cPlane().Direction(); t[0] *= -d; t[1] *= -d; t[2] *= -d; p = q; p += t; switch( f.Flags() & (FaceType::NORMX|FaceType::NORMY|FaceType::NORMZ) ) { case FaceType::NORMX: b0 = f.cEdge(1)[1]*(p[2] - f.cP(1)[2]) - f.cEdge(1)[2]*(p[1] - f.cP(1)[1]); if(b0<=0) { b0 = PSDist(q,f.V(1)->cP(),f.V(2)->cP(),p); if(dist>b0) { dist = b0; return true; } else return false; } b1 = f.cEdge(2)[1]*(p[2] - f.cP(2)[2]) - f.cEdge(2)[2]*(p[1] - f.cP(2)[1]); if(b1<=0) { b1 = PSDist(q,f.V(2)->cP(),f.V(0)->cP(),p); if(dist>b1) { dist = b1; return true; } else return false; } b2 = f.cEdge(0)[1]*(p[2] - f.cP(0)[2]) - f.cEdge(0)[2]*(p[1] - f.cP(0)[1]); if(b2<=0) { b2 = PSDist(q,f.V(0)->cP(),f.V(1)->cP(),p); if(dist>b2) { dist = b2; return true; } else return false; } // sono tutti e tre > 0 quindi dovrebbe essere dentro; // per sicurezza se il piu' piccolo dei tre e' < epsilon (scalato rispetto all'area della faccia // per renderlo dimension independent.) allora si usa ancora la distanza punto // segmento che e' piu robusta della punto piano, e si fa dalla parte a cui siamo piu' // vicini (come prodotto vettore) // Nota: si potrebbe rendere un pochino piu' veloce sostituendo Area() // con il prodotto vettore dei due edge in 2d lungo il piano migliore. if( (b=vcg::math::Min(b0,vcg::math::Min(b1,b2))) < EPSILON*DoubleArea(f)) { ScalarType bt; if(b==b0) bt = PSDist(q,f.V(1)->cP(),f.V(2)->cP(),p); else if(b==b1) bt = PSDist(q,f.V(2)->cP(),f.V(0)->cP(),p); else if(b==b2) bt = PSDist(q,f.V(0)->cP(),f.V(1)->cP(),p); //printf("Warning area:%g %g %g %g thr:%g bt:%g\n",Area(), b0,b1,b2,EPSILON*Area(),bt); if(dist>bt) { dist = bt; return true; } else return false; } break; case FaceType::NORMY: b0 = f.cEdge(1)[2]*(p[0] - f.cP(1)[0]) - f.cEdge(1)[0]*(p[2] - f.cP(1)[2]); if(b0<=0) { b0 = PSDist(q,f.V(1)->cP(),f.V(2)->cP(),p); if(dist>b0) { dist = b0; return true; } else return false; } b1 = f.cEdge(2)[2]*(p[0] - f.cP(2)[0]) - f.cEdge(2)[0]*(p[2] - f.cP(2)[2]); if(b1<=0) { b1 = PSDist(q,f.V(2)->cP(),f.V(0)->cP(),p); if(dist>b1) { dist = b1; return true; } else return false; } b2 = f.cEdge(0)[2]*(p[0] - f.cP(0)[0]) - f.cEdge(0)[0]*(p[2] - f.cP(0)[2]); if(b2<=0) { b2 = PSDist(q,f.V(0)->cP(),f.V(1)->cP(),p); if(dist>b2) { dist = b2; return true; } else return false; } if( (b=vcg::math::Min(b0,vcg::math::Min(b1,b2))) < EPSILON*DoubleArea(f)) { ScalarType bt; if(b==b0) bt = PSDist(q,f.V(1)->cP(),f.V(2)->cP(),p); else if(b==b1) bt = PSDist(q,f.V(2)->cP(),f.V(0)->cP(),p); else if(b==b2) bt = PSDist(q,f.V(0)->cP(),f.V(1)->cP(),p); //printf("Warning area:%g %g %g %g thr:%g bt:%g\n",Area(), b0,b1,b2,EPSILON*Area(),bt); if(dist>bt) { dist = bt; return true; } else return false; } break; case FaceType::NORMZ: b0 = f.cEdge(1)[0]*(p[1] - f.cP(1)[1]) - f.cEdge(1)[1]*(p[0] - f.cP(1)[0]); if(b0<=0) { b0 = PSDist(q,f.V(1)->cP(),f.V(2)->cP(),p); if(dist>b0) { dist = b0; return true; } else return false; } b1 = f.cEdge(2)[0]*(p[1] - f.cP(2)[1]) - f.cEdge(2)[1]*(p[0] - f.cP(2)[0]); if(b1<=0) { b1 = PSDist(q,f.V(2)->cP(),f.V(0)->cP(),p); if(dist>b1) { dist = b1; return true; } else return false; } b2 = f.cEdge(0)[0]*(p[1] - f.cP(0)[1]) - f.cEdge(0)[1]*(p[0] - f.cP(0)[0]); if(b2<=0) { b2 = PSDist(q,f.V(0)->cP(),f.V(1)->cP(),p); if(dist>b2) { dist = b2; return true; } else return false; } if( (b=vcg::math::Min(b0,vcg::math::Min(b1,b2))) < EPSILON*DoubleArea(f)) { ScalarType bt; if(b==b0) bt = PSDist(q,f.V(1)->cP(),f.V(2)->cP(),p); else if(b==b1) bt = PSDist(q,f.V(2)->cP(),f.V(0)->cP(),p); else if(b==b2) bt = PSDist(q,f.V(0)->cP(),f.V(1)->cP(),p); //printf("Warning area:%g %g %g %g thr:%g bt:%g\n",Area(), b0,b1,b2,EPSILON*Area(),bt); if(dist>bt) { dist = bt; return true; } else return false; } break; } dist = ScalarType(fabs(d)); //dist = Distance(p,q); return true; } class PointDistanceFunctor { public: template inline bool operator () (const FACETYPE & f, const Point3 & p, SCALARTYPE & minDist, Point3 & q) { const Point3 fp = Point3::Construct(p); Point3 fq; typename FACETYPE::ScalarType md = (typename FACETYPE::ScalarType)(minDist); const bool ret = PointDistance(f, fp, md, fq); minDist = (SCALARTYPE)(md); q = Point3::Construct(fq); return (ret); } }; } // end namespace face } // end namespace vcg #endif qutemol/vcg/vcg/simplex/tetrahedronplus/0000755000175000017500000000000011633404241017064 5ustar mbambaqutemol/vcg/vcg/simplex/tetrahedronplus/base.h0000444000175000017500000003227610631015745020163 0ustar mbamba/**************************************************************************** * VCGLib o o * * Visual and Computer Graphics Library o o * * _ O _ * * Copyright(C) 2004 \/)\/ * * Visual Computing Lab /\/| * * ISTI - Italian National Research Council | * * \ * * All rights reserved. * * * * 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. * * * * 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 (http://www.gnu.org/licenses/gpl.txt) * * for more details. * * * ****************************************************************************/ /**************************************************************************** History $Log: base.h,v $ Revision 1.2 2007/06/04 14:04:21 turini Minor changes in includes. Revision 1.1 2007/05/09 10:31:53 ganovelli added ****************************************************************************/ #ifndef __VCG_TETRA_PLUS #define __VCG_TETRA_PLUS #include #include #include #include namespace vcg { /*------------------------------------------------------------------*/ /* The base class of all the recusive definition chain. It is just a container of the typenames of the various simplexes. These typenames must be known form all the derived classes. */ template class TetraTypeHolder{ public: typedef BVT VertexType; typedef typename VertexType::CoordType CoordType; typedef typename VertexType::ScalarType ScalarType; typedef BET EdgeType; typedef BFT FaceType; typedef BTT TetraType; typedef BVT *VertPointer; typedef BET *EdgePointer; typedef BFT *FacePointer; typedef BTT *TetraPointer; static void Name(std::vector & name){} // prot }; /* The base class form which we start to add our components. it has the empty definition for all the standard members (coords, color flags) Note: in order to avoid both virtual classes and ambiguous definitions all the subsequent overrides must be done in a sequence of derivation. In other words we cannot derive and add in a single derivation step (with multiple ancestor), both the real (non-empty) normal and color but we have to build the type a step a time (deriving from a single ancestor at a time). */ template class TetraBase: public tetra::EmptyVertexRef< tetra::EmptyAdj< TetraTypeHolder > > { }; // Metaprogramming Core template class A> class TetraArity1: public A > {}; template class A, template class B> class TetraArity2: public B > {}; template class A, template class B, template class C > class TetraArity3: public C > {}; template class A, template class B, template class C, template class D> class TetraArity4: public D > {}; template class A, template class B, template class C, template class D, template class E > class TetraArity5: public E > {}; template class A, template class B, template class C, template class D, template class E, template class F > class TetraArity6: public F > {}; template class A, template class B, template class C, template class D, template class E, template class F, template class G > class TetraArity7: public G > {}; template class A, template class B, template class C, template class D, template class E, template class F, template class G, template class H > class TetraArity8: public H > {}; /* The Real Big Face class; The class __FaceArityMax__ is the one that is the Last to be derived, and therefore is the only one to know the real members (after the many overrides) so all the functions with common behaviour using the members defined in the various Empty/nonEmpty component classes MUST be defined here. I.e. IsD() that uses the overridden Flags() member must be defined here. */ template class A, template class B, template class C, template class D, template class E, template class F, template class G, template class H, template class I > class TetraArityMax: public I > { // ----- Flags stuff ----- public: inline int & UberFlags () { return this->Flags(); } inline const int UberFlags() const { return this->Flags(); } enum { DELETED = 0x00000001, // Face is deleted from the mesh NOTREAD = 0x00000002, // Face of the mesh is not readable NOTWRITE = 0x00000004, // Face of the mesh is not writable VISITED = 0x00000010, // Face has been visited. Usualy this is a per-algorithm used bit. SELECTED = 0x00000020, // Face is selected. Algorithms should try to work only on selected face (if explicitly requested) // Border _flags, it is assumed that BORDERi = BORDER0<Flags() & DELETED) != 0;} /// checks if the Face is readable bool IsR() const {return (this->Flags() & NOTREAD) == 0;} /// checks if the Face is modifiable bool IsW() const {return (this->Flags() & NOTWRITE)== 0;} /// This funcion checks whether the Face is both readable and modifiable bool IsRW() const {return (this->Flags() & (NOTREAD | NOTWRITE)) == 0;} /// checks if the Face is Modified bool IsS() const {return (this->Flags() & SELECTED) != 0;} /// checks if the Face is Modified bool IsV() const {return (this->Flags() & VISITED) != 0;} /** Set the flag value @param flagp Valore da inserire nel flag */ void SetFlags(int flagp) {this->Flags()=flagp;} /** Set the flag value @param flagp Valore da inserire nel flag */ void ClearFlags() {this->Flags()=0;} /// deletes the Face from the mesh void SetD() {this->Flags() |=DELETED;} /// un-delete a Face void ClearD() {this->Flags() &=(~DELETED);} /// marks the Face as readable void SetR() {this->Flags() &=(~NOTREAD);} /// marks the Face as not readable void ClearR() {this->Flags() |=NOTREAD;} /// marks the Face as writable void SetW() {this->Flags() &=(~NOTWRITE);} /// marks the Face as notwritable void ClearW() {this->Flags() |=NOTWRITE;} /// select the Face void SetS() {this->Flags() |=SELECTED;} /// Un-select a Face void ClearS() {this->Flags() &= ~SELECTED;} /// select the Face void SetV() {this->Flags() |=VISITED;} /// Un-select a Face void ClearV() {this->Flags() &= ~VISITED;} /// This function checks if the face is selected bool IsB(int i) const {return (this->Flags() & (BORDER0<Flags() |=(BORDER0<Flags() &= (~(BORDER0<>1; return true; } assert(0); return false; } /// This function checks if the given user bit is true bool IsUserBit(int userBit){return (this->Flags() & userBit) != 0;} /// This function set the given user bit void SetUserBit(int userBit){this->Flags() |=userBit;} /// This function clear the given user bit void ClearUserBit(int userBit){this->Flags() &= (~userBit);} template void GetBBox( BoxType & bb ) const { bb.Set(this->P(0)); bb.Add(this->P(1)); bb.Add(this->P(2)); } }; template < typename T=int> class TetraDefaultDeriver : public T {}; /* These are the three main classes that are used by the library user to define its own Facees. The user MUST specify the names of all the type involved in a generic complex. so for example when defining a Face of a trimesh you must know the name of the type of the edge and of the face. Typical usage example: A Face with coords, flags and normal for use in a standard trimesh: class MyFaceNf : public FaceSimp2< VertProto, EdgeProto, MyFaceNf, face::Flag, face::Normal3f > {}; A Face with coords, and normal for use in a tetrahedral mesh AND in a standard trimesh: class TetraFace : public FaceSimp3< VertProto, EdgeProto, TetraFace, TetraProto, face::Coord3d, face::Normal3f > {}; A summary of the components that can be added to a face (see components.h for details): VertexRef Mark //Incremental mark (int) VTAdj //Topology vertex face adjacency (pointers to next face in the ring of the vertex TTAdj //topology: face face adj pointers to adjacent faces */ template class A = TetraDefaultDeriver, template class B = TetraDefaultDeriver, template class C = TetraDefaultDeriver, template class D = TetraDefaultDeriver, template class E = TetraDefaultDeriver, template class F = TetraDefaultDeriver, template class G = TetraDefaultDeriver, template class H = TetraDefaultDeriver, template class I = TetraDefaultDeriver > class TetraSimp3: public TetraArityMax {}; class DumTT; template class A = TetraDefaultDeriver, template class B = TetraDefaultDeriver, template class C = TetraDefaultDeriver, template class D = TetraDefaultDeriver, template class E = TetraDefaultDeriver, template class F = TetraDefaultDeriver, template class G = TetraDefaultDeriver, template class H = TetraDefaultDeriver, template class I = TetraDefaultDeriver > class TetraSimp2: public TetraArityMax {}; }// end namespace #endif qutemol/vcg/vcg/simplex/tetrahedronplus/component.h0000444000175000017500000003102610631756162021250 0ustar mbamba/**************************************************************************** * VCGLib o o * * Visual and Computer Graphics Library o o * * _ O _ * * Copyright(C) 2004 \/)\/ * * Visual Computing Lab /\/| * * ISTI - Italian National Research Council | * * \ * * All rights reserved. * * * * 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. * * * * 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 (http://www.gnu.org/licenses/gpl.txt) * * for more details. * * * ****************************************************************************/ /**************************************************************************** History $Log: component.h,v $ Revision 1.2 2007/06/07 10:22:42 turini Minor changes in VT Adjacency component. Revision 1.1 2007/05/09 10:31:53 ganovelli added ****************************************************************************/ #ifndef __VCG_TETRAHEDRON_PLUS_COMPONENT #define __VCG_TETRAHEDRON_PLUS_COMPONENT #include #include namespace vcg { namespace tetra { /* Some naming Rules All the Components that can be added to a vertex should be defined in the namespace vert: */ /*-------------------------- VERTEX ----------------------------------------*/ template class EmptyVertexRef: public T { public: // typedef typename T::VertexType VertexType; // typedef typename T::CoordType CoordType; inline typename T::VertexType * & V( const int j ) { assert(0); static typename T::VertexType *vp=0; return vp; } inline typename T::VertexType * const & V( const int j ) const { assert(0); static typename T::VertexType *vp=0; return vp; } inline typename T::VertexType * const cV( const int j ) const { assert(0); static typename T::VertexType *vp=0; return vp; } inline typename T::CoordType & P( const int j ) { assert(0); static typename T::CoordType coord(0, 0, 0); return coord; } inline const typename T::CoordType & P( const int j ) const { assert(0); static typename T::CoordType coord(0, 0, 0); return coord; } inline const typename T::CoordType &cP( const int j ) const { assert(0); static typename T::CoordType coord(0, 0, 0); return coord; } static bool HasVertexRef() { return false; } static void Name(std::vector & name){T::Name(name);} }; template class VertexRef: public T { public: VertexRef(){ v[0]=0; v[1]=0; v[2]=0; } inline typename T::VertexType * & V( const int j ) { assert(j>=0 && j<4); return v[j]; } inline typename T::VertexType * const & V( const int j ) const { assert(j>=0 && j<4); return v[j]; } inline typename T::VertexType * const cV( const int j ) const { assert(j>=0 && j<4); return v[j]; } // Shortcut per accedere ai punti delle facce inline typename T::CoordType & P( const int j ) { assert(j>=0 && j<4); return v[j]->P(); } inline const typename T::CoordType & P( const int j ) const { assert(j>=0 && j<4); return v[j]->cP(); } inline const typename T::CoordType &cP( const int j ) const { assert(j>=0 && j<4); return v[j]->cP(); } /** Return the pointer to the ((j+1)%3)-th vertex of the face. @param j Index of the face vertex. */ inline typename T::VertexType * & V0( const int j ) { return V(j);} inline typename T::VertexType * & V1( const int j ) { return V((j+1)%4);} inline typename T::VertexType * & V2( const int j ) { return V((j+2)%4);} inline const typename T::VertexType * const & V0( const int j ) const { return V(j);} inline const typename T::VertexType * const & V1( const int j ) const { return V((j+1)%4);} inline const typename T::VertexType * const & V2( const int j ) const { return V((j+2)%4);} inline const typename T::VertexType * const & cV0( const int j ) const { return cV(j);} inline const typename T::VertexType * const & cV1( const int j ) const { return cV((j+1)%4);} inline const typename T::VertexType * const & cV2( const int j ) const { return cV((j+2)%4);} /// Shortcut to get vertex values inline typename T::CoordType & P0( const int j ) { return V(j)->P();} inline typename T::CoordType & P1( const int j ) { return V((j+1)%4)->P();} inline typename T::CoordType & P2( const int j ) { return V((j+2)%4)->P();} inline const typename T::CoordType & P0( const int j ) const { return V(j)->P();} inline const typename T::CoordType & P1( const int j ) const { return V((j+1)%4)->P();} inline const typename T::CoordType & P2( const int j ) const { return V((j+2)%4)->P();} inline const typename T::CoordType & cP0( const int j ) const { return cV(j)->P();} inline const typename T::CoordType & cP1( const int j ) const { return cV((j+1)%4)->P();} inline const typename T::CoordType & cP2( const int j ) const { return cV((j+2)%4)->P();} inline typename T::VertexType * & UberV( const int j ) { assert(j>=0 && j<4); return v[j]; } inline const typename T::VertexType * const & UberV( const int j ) const { assert(j>=0 && j<4); return v[j]; } static bool HasVertexRef() { return true; } static void Name(std::vector & name){name.push_back(std::string("VertexRef"));T::Name(name);} private: typename T::VertexType *v[4]; }; /*------------------------- FACE NORMAL -----------------------------------------*/ template class EmptyFaceNormal: public T { public: typedef ::vcg::Point3 NormalType; /// Return the vector of Flags(), senza effettuare controlli sui bit NormalType N(const int & ){ static int dummynormal(0); return dummynormal; } const NormalType cN(const int & ) const { return 0; } static bool HasFaceNormal() { return false; } static bool HasFaceNormalOcc() { return false; } static void Name(std::vector & name){T::Name(name);} }; template class FaceNormal: public T { public: typedef ::vcg::Point3 NormalType; NormalType N(const int & i){ assert((i>=0)&&(i < 4)); return _facenormals[i]; } const NormalType cN(const int & i) const { assert((i>=0)&&(i < 4)); return _facenormals[i]; } static bool HasFaceNormals() { return true; } static bool HasFaceNormalOcc() { return false; } static void Name(std::vector & name){name.push_back(std::string("FaceNormal"));T::Name(name);} private: NormalType _facenormals[4]; }; template class FaceNormal3f: public FaceNormal{ public:static void Name(std::vector & name){name.push_back(std::string("FaceNormal3f"));T::Name(name);} }; template class FaceNormal3d: public FaceNormal{ public:static void Name(std::vector & name){name.push_back(std::string("FaceNormal3d"));T::Name(name);} }; /*------------------------- FLAGS -----------------------------------------*/ template class EmptyBitFlags: public T { public: /// Return the vector of Flags(), senza effettuare controlli sui bit int &Flags() { static int dummyflags(0); return dummyflags; } const int Flags() const { return 0; } static bool HasFlags() { return false; } static bool HasFlagsOcc() { return false; } static void Name(std::vector & name){T::Name(name);} }; template class BitFlags: public T { public: BitFlags(){_flags=0;} int &Flags() {return _flags; } const int Flags() const {return _flags; } static bool HasFlags() { return true; } static void Name(std::vector & name){name.push_back(std::string("BitFlags"));T::Name(name);} private: int _flags; }; /*-------------------------- INCREMENTAL MARK ----------------------------------------*/ template class EmptyMark: public T { public: typedef int MarkType; static bool HasMark() { return false; } static bool HasMarkOcc() { return false; } inline void InitIMark() { } inline int & IMark() { assert(0); static int tmp=-1; return tmp;} inline const int IMark() const {return 0;} static void Name(std::vector & name){T::Name(name);} }; template class Mark: public T { public: static bool HasMark() { return true; } static bool HasMarkOcc() { return true; } inline void InitIMark() { _imark = 0; } inline int & IMark() { return _imark;} inline const int & IMark() const {return _imark;} static void Name(std::vector & name){name.push_back(std::string("Mark"));T::Name(name);} private: int _imark; }; /*----------------------------- VTADJ ------------------------------*/ template class EmptyAdj: public T { public: typedef int VFAdjType; typename T::TetraPointer & VTp( const int ) { static typename T::TetraPointer tp=0; return tp; } typename T::TetraPointer const cVTp( const int ) const { static typename T::TetraPointer const tp=0; return tp; } typename T::TetraPointer & TTp( const int ) { static typename T::TetraPointer tp=0; return tp; } typename T::TetraPointer const cTTp( const int ) const { static typename T::TetraPointer const tp=0; return tp; } char & VTi( const int j ) { static char z=0; return z; } char & TTi( const int j ) { static char z=0; return z; } static bool HasVTAdjacency() { return false; } static bool HasTTAdjacency() { return false; } static bool HasTTAdjacencyOcc() { return false; } static bool HasVTAdjacencyOcc() { return false; } static void Name( std::vector< std::string > & name ){ T::Name(name); } }; template class VTAdj: public T { public: VTAdj() { _vtp[0]=0; _vtp[1]=0; _vtp[2]=0; _vtp[3]=0; } typename T::TetraPointer & VTp( const int j ) { assert( j >= 0 && j < 4 ); return _vtp[j]; } typename T::TetraPointer const VTp( const int j ) const { assert( j >= 0 && j < 4 ); return _vtp[j]; } typename T::TetraPointer const cVTp( const int j ) const { assert( j >= 0 && j < 4 ); return _vtp[j]; } char & VTi( const int j ) { return _vti[j]; } const char & cVTi( const int j ) const { return _vti[j]; } static bool HasVTAdjacency() { return true; } static bool HasVTAdjacencyOcc() { return false; } static void Name( std::vector< std::string > & name ) { name.push_back( std::string("VTAdj") ); T::Name(name); } private: typename T::TetraPointer _vtp[4]; char _vti[4]; }; /*----------------------------- TTADJ ------------------------------*/ template class TTAdj: public T { public: TTAdj(){ _ttp[0]=0; _ttp[1]=0; _ttp[2]=0; _ttp[3]=0; } typename T::TetraPointer &TTp(const int j) { assert(j>=0 && j<4); return _ttp[j]; } typename T::TetraPointer const TTp(const int j) const { assert(j>=0 && j<4); return _ttp[j]; } typename T::TetraPointer const cTTp(const int j) const { assert(j>=0 && j<4); return _ttp[j]; } char &TTi(const int j) { return _tti[j]; } const char &cTTi(const int j) const { return _tti[j]; } typename T::TetraPointer &TTp1( const int j ) { return TTp((j+1)%4);} typename T::TetraPointer &TTp2( const int j ) { return TTp((j+2)%4);} typename T::TetraPointer const TTp1( const int j ) const { return TTp((j+1)%4);} typename T::TetraPointer const TTp2( const int j ) const { return TTp((j+2)%4);} bool IsBorderF(const int & i) const { assert( (i>=0) && (i < 4)); { return TTp(i) == this;}} static bool HasTTAdjacency() { return true; } static bool HasTTAdjacencyOcc() { return false; } static void Name(std::vector & name){name.push_back(std::string("TTAdj"));T::Name(name);} private: typename T::TetraPointer _ttp[4] ; char _tti[4] ; }; } // end namespace vert }// end namespace vcg #endif qutemol/vcg/vcg/simplex/faceplus/0000755000175000017500000000000011633404241015443 5ustar mbambaqutemol/vcg/vcg/simplex/faceplus/component_ocf.h0000444000175000017500000004747510767750655020510 0ustar mbamba/**************************************************************************** * VCGLib o o * * Visual and Computer Graphics Library o o * * _ O _ * * Copyright(C) 2004 \/)\/ * * Visual Computing Lab /\/| * * ISTI - Italian National Research Council | * * \ * * All rights reserved. * * * * 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. * * * * 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 (http://www.gnu.org/licenses/gpl.txt) * * for more details. * * * ****************************************************************************/ /**************************************************************************** History $Log: component_ocf.h,v $ Revision 1.26 2008/03/18 14:29:01 cignoni added missing include Revision 1.25 2008/03/11 09:22:07 cignoni Completed the garbage collecting functions CompactVertexVector and CompactFaceVector. Revision 1.24 2008/02/28 15:41:17 cignoni Added FFpi methods and better init of texture coords Revision 1.23 2008/02/05 10:11:34 cignoni A small typo (a T:: instead of TT::) Revision 1.22 2008/02/04 21:26:45 ganovelli added ImportLocal which imports all local attributes into vertexplus and faceplus. A local attribute is everything (N(), C(), Q()....) except pointers to other simplices (i.e. FFAdj, VFAdj, VertexRef) which are set to NULL. Added some function for const attributes Revision 1.21 2007/10/09 12:03:13 corsini remove signed/unsigned warning Revision 1.20 2007/03/12 15:37:19 tarini Texture coord name change! "TCoord" and "Texture" are BAD. "TexCoord" is GOOD. Revision 1.19 2006/11/28 22:34:28 cignoni Added default constructor with null initialization to adjacency members. AddFaces and AddVertices NEED to know if the topology is correctly computed to update it. Revision 1.18 2006/11/07 11:29:24 cignoni Corrected some errors in the reflections Has*** functions Revision 1.17 2006/10/31 16:02:18 ganovelli vesione 2005 compliant Revision 1.16 2006/10/27 14:15:10 ganovelli added overrides to HasFFAddAdjacency and HasVFAddAdjacency Revision 1.15 2006/10/16 08:49:29 cignoni Better managment of resize overloading when reducing the size of a vector Revision 1.14 2006/10/09 20:20:55 cignoni Added some missing Add***Ocf() for the default case. Revision 1.13 2006/05/25 09:39:09 cignoni missing std and other gcc detected syntax errors Revision 1.12 2006/05/03 21:37:02 cignoni Added Optional Mark Revision 1.11 2006/02/28 11:59:39 ponchio g++ compliance: begin() -> (*this).begin() and for end(), size(), Base(), Index() Revision 1.10 2006/01/30 08:47:40 cignoni Corrected HasPerWedgeTexture Revision 1.9 2006/01/05 15:46:06 cignoni Removed a syntax error (double >) in HasPerWedgeTexture/HasPerFaceColor Revision 1.8 2006/01/04 18:46:25 cignoni Corrected push_back (did not worked at all!) added missing cFFi Revision 1.7 2006/01/03 10:54:21 cignoni Corrected HasPerFaceColor and HasPerWedgeTexture to comply gcc Revision 1.6 2005/12/12 11:17:32 cignoni Corrected update function, now only the needed simplexes should be updated. Revision 1.5 2005/11/26 00:16:44 cignoni Corrected a lot of bugs about the use of enabled entities Revision 1.4 2005/11/21 21:46:20 cignoni Changed HasColor -> HasFaceColor and HasNormal ->HasFaceNormal Revision 1.3 2005/11/16 22:43:36 cignoni Added WedgeTexture component Revision 1.2 2005/10/22 13:16:46 cignoni Added a missing ';' in FFAdjOcf (thanks to Mario Latronico). Revision 1.1 2005/10/14 15:07:58 cignoni First Really Working version ****************************************************************************/ /* Note OCF = Optional Component Fast (hopefully) compare with OCC(Optional Component Compact) Mainly the trick here is to store a base pointer in each simplex... ****************************************************************************/ #ifndef __VCG_FACE_PLUS_COMPONENT_OCF #define __VCG_FACE_PLUS_COMPONENT_OCF #include #include #include namespace vcg { namespace face { /* All the Components that can be added to a faceex should be defined in the namespace face: */ template class vector_ocf: public std::vector { typedef std::vector BaseType; typedef typename vector_ocf::iterator ThisTypeIterator; public: vector_ocf():std::vector(){ ColorEnabled=false; MarkEnabled=false; NormalEnabled=false; WedgeTexEnabled=false; VFAdjacencyEnabled=false; FFAdjacencyEnabled=false; } // Auxiliary types to build internal vectors struct AdjTypePack { typename VALUE_TYPE::FacePointer _fp[3] ; char _zp[3] ; // Default constructor. // Needed because we need to know if adjacency is initialized or not // when resizing vectors and during an allocate face. AdjTypePack() { _fp[0]=0; _fp[1]=0; _fp[2]=0; } }; //template class WedgeTexTypePack { public: WedgeTexTypePack() { wt[0].U()=.5;wt[0].V()=.5; wt[1].U()=.5;wt[1].V()=.5; wt[2].U()=.5;wt[2].V()=.5; wt[0].N()=-1; wt[1].N()=-1; wt[2].N()=-1; } typename VALUE_TYPE::TexCoordType wt[3]; }; // override di tutte le funzioni che possono spostare // l'allocazione in memoria del container void push_back(const VALUE_TYPE & v) { BaseType::push_back(v); BaseType::back()._ovp = this; if (ColorEnabled) CV.push_back(vcg::Color4b(vcg::Color4b::White)); if (MarkEnabled) MV.push_back(0); if (NormalEnabled) NV.push_back(typename VALUE_TYPE::NormalType()); if (VFAdjacencyEnabled) AV.push_back(AdjTypePack()); if (FFAdjacencyEnabled) AF.push_back(AdjTypePack()); if (WedgeTexEnabled) WTV.push_back(WedgeTexTypePack()); } void pop_back(); void resize(const unsigned int & _size) { unsigned int oldsize = BaseType::size(); BaseType::resize(_size); if(oldsize<_size){ ThisTypeIterator firstnew = BaseType::begin(); advance(firstnew,oldsize); _updateOVP(firstnew,(*this).end()); } if (ColorEnabled) CV.resize(_size); if (MarkEnabled) MV.resize(_size); if (NormalEnabled) NV.resize(_size); if (VFAdjacencyEnabled) AV.resize(_size); if (FFAdjacencyEnabled) AF.resize(_size); if (WedgeTexEnabled) WTV.resize(_size,WedgeTexTypePack()); } void reserve(const unsigned int & _size) { ThisTypeIterator oldbegin=(*this).begin(); BaseType::reserve(_size); if (ColorEnabled) CV.reserve(_size); if (MarkEnabled) MV.reserve(_size); if (NormalEnabled) NV.reserve(_size); if (VFAdjacencyEnabled) AV.reserve(_size); if (FFAdjacencyEnabled) AF.reserve(_size); if (WedgeTexEnabled) WTV.reserve(_size); if(oldbegin!=(*this).begin()) _updateOVP((*this).begin(),(*this).end()); } void _updateOVP(ThisTypeIterator lbegin, ThisTypeIterator lend) { ThisTypeIterator fi; //for(fi=(*this).begin();vi!=(*this).end();++vi) for(fi=lbegin;fi!=lend;++fi) (*fi)._ovp=this; } // this function is called by the specialized Reorder function, that is called whenever someone call the allocator::CompactVertVector void ReorderFace(std::vector &newFaceIndex ) { size_t pos=0; size_t i=0; if (ColorEnabled) assert( CV.size() == newFaceIndex.size() ); if (MarkEnabled) assert( MV.size() == newFaceIndex.size() ); if (NormalEnabled) assert( NV.size() == newFaceIndex.size() ); if (VFAdjacencyEnabled)assert( AV.size() == newFaceIndex.size() ); if (FFAdjacencyEnabled)assert( AF.size() == newFaceIndex.size() ); if (WedgeTexEnabled) assert(WTV.size() == newFaceIndex.size() ); for(i=0;i::max() ) { assert(newFaceIndex[i] <= i); if (ColorEnabled) CV[newFaceIndex[i]] = CV[i]; if (MarkEnabled) MV[newFaceIndex[i]] = MV[i]; if (NormalEnabled) NV[newFaceIndex[i]] = NV[i]; if (VFAdjacencyEnabled) AV[newFaceIndex[i]] = AV[i]; if (FFAdjacencyEnabled) AF[newFaceIndex[i]] = AF[i]; if (WedgeTexEnabled) WTV[newFaceIndex[i]] = WTV[i]; } } if (ColorEnabled) CV.resize(BaseType::size()); if (MarkEnabled) MV.resize(BaseType::size()); if (NormalEnabled) NV.resize(BaseType::size()); if (VFAdjacencyEnabled) AV.resize(BaseType::size()); if (FFAdjacencyEnabled) AF.resize(BaseType::size()); if (WedgeTexEnabled) WTV.resize(BaseType::size()); } //////////////////////////////////////// // Enabling Functions bool IsColorEnabled() const {return ColorEnabled;} void EnableColor() { assert(VALUE_TYPE::HasFaceColorOcf()); ColorEnabled=true; CV.resize((*this).size()); } void DisableColor() { assert(VALUE_TYPE::HasFaceColorOcf()); ColorEnabled=false; CV.clear(); } bool IsMarkEnabled() const {return MarkEnabled;} void EnableMark() { assert(VALUE_TYPE::HasFaceMarkOcf()); MarkEnabled=true; MV.resize((*this).size()); } void DisableMark() { assert(VALUE_TYPE::HasFaceMarkOcf()); MarkEnabled=false; MV.clear(); } bool IsNormalEnabled() const {return NormalEnabled;} void EnableNormal() { assert(VALUE_TYPE::HasFaceNormalOcf()); NormalEnabled=true; NV.resize((*this).size()); } void DisableNormal() { assert(VALUE_TYPE::HasFaceNormalOcf()); NormalEnabled=false; NV.clear(); } bool IsVFAdjacencyEnabled() const {return VFAdjacencyEnabled;} void EnableVFAdjacency() { assert(VALUE_TYPE::HasVFAdjacencyOcf()); VFAdjacencyEnabled=true; AV.resize((*this).size()); } void DisableVFAdjacency() { assert(VALUE_TYPE::HasVFAdjacencyOcf()); VFAdjacencyEnabled=false; AV.clear(); } bool IsFFAdjacencyEnabled() const {return FFAdjacencyEnabled;} void EnableFFAdjacency() { assert(VALUE_TYPE::HasFFAdjacencyOcf()); FFAdjacencyEnabled=true; AF.resize((*this).size()); } void DisableFFAdjacency() { assert(VALUE_TYPE::HasFFAdjacencyOcf()); FFAdjacencyEnabled=false; AF.clear(); } bool IsWedgeTexEnabled() const {return WedgeTexEnabled;} void EnableWedgeTex() { assert(VALUE_TYPE::HasWedgeTexCoordOcf()); WedgeTexEnabled=true; WTV.resize((*this).size(),WedgeTexTypePack()); } void DisableWedgeTex() { assert(VALUE_TYPE::HasWedgeTexCoordOcf()); WedgeTexEnabled=false; WTV.clear(); } public: std::vector CV; std::vector MV; std::vector NV; std::vector AV; std::vector AF; std::vector WTV; bool ColorEnabled; bool MarkEnabled; bool NormalEnabled; bool WedgeTexEnabled; bool VFAdjacencyEnabled; bool FFAdjacencyEnabled; }; // end class vector_ocf //template<> void EnableAttribute(){ NormalEnabled=true;} /*------------------------- COORD -----------------------------------------*/ /*----------------------------- VFADJ ------------------------------*/ template class VFAdjOcf: public T { public: typename T::FacePointer &VFp(const int j) { assert((*this).Base().VFAdjacencyEnabled); return (*this).Base().AV[(*this).Index()]._fp[j]; } typename T::FacePointer cVFp(const int j) const { if(! (*this).Base().VFAdjacencyEnabled ) return 0; else return (*this).Base().AV[(*this).Index()]._fp[j]; } char &VFi(const int j) { assert((*this).Base().VFAdjacencyEnabled); return (*this).Base().AV[(*this).Index()]._zp[j]; } template void ImportLocal(const LeftF & leftF){VFp(0) = NULL; VFp(1) = NULL; VFp(2) = NULL; VFi(0) = -1; VFi(1) = -1; VFi(2) = -1; T::ImportLocal(leftF);} static bool HasVFAdjacency() { return true; } static bool HasVFAdjacencyOcf() { return true; } private: }; /*----------------------------- FFADJ ------------------------------*/ template class FFAdjOcf: public T { public: typename T::FacePointer &FFp(const int j) { assert((*this).Base().FFAdjacencyEnabled); return (*this).Base().AF[(*this).Index()]._fp[j]; } typename T::FacePointer const FFp(const int j) const { return cFFp(j);} typename T::FacePointer const cFFp(const int j) const { if(! (*this).Base().FFAdjacencyEnabled ) return 0; else return (*this).Base().AF[(*this).Index()]._fp[j]; } char &FFi(const int j) { assert((*this).Base().FFAdjacencyEnabled); return (*this).Base().AF[(*this).Index()]._zp[j]; } const char cFFi(const int j) const { assert((*this).Base().FFAdjacencyEnabled); return (*this).Base().AF[(*this).Index()]._zp[j]; } typename T::FacePointer &FFp1( const int j ) { return FFp((j+1)%3);} typename T::FacePointer &FFp2( const int j ) { return FFp((j+2)%3);} typename T::FacePointer const FFp1( const int j ) const { return FFp((j+1)%3);} typename T::FacePointer const FFp2( const int j ) const { return FFp((j+2)%3);} template void ImportLocal(const LeftF & leftF){FFp(0) = NULL; FFp(1) = NULL; FFp(2) = NULL; FFi(0) = -1; FFi(1) = -1; FFi(2) = -1; T::ImportLocal(leftF);} static bool HasFFAdjacency() { return true; } static bool HasFFAdjacencyOcf() { return true; } private: }; /*------------------------- Normal -----------------------------------------*/ template class NormalOcf: public T { public: typedef A NormalType; static bool HasFaceNormal() { return true; } static bool HasFaceNormalOcf() { return true; } NormalType &N() { // you cannot use Normals before enabling them with: yourmesh.face.EnableNormal() assert((*this).Base().NormalEnabled); return (*this).Base().NV[(*this).Index()]; } const NormalType &cN() const { // you cannot use Normals before enabling them with: yourmesh.face.EnableNormal() assert((*this).Base().NormalEnabled); return (*this).Base().NV[(*this).Index()]; } template void ImportLocal(const LeftF & leftF){N() = leftF.cN(); T::ImportLocal(leftF);} }; template class Normal3sOcf: public NormalOcf {}; template class Normal3fOcf: public NormalOcf {}; template class Normal3dOcf: public NormalOcf {}; ///*-------------------------- COLOR ----------------------------------*/ template class ColorOcf: public T { public: typedef A ColorType; ColorType &C() { assert((*this).Base().ColorEnabled); return (*this).Base().CV[(*this).Index()]; } template void ImportLocal(const LeftF & leftF){C() = leftF.cC(); T::ImportLocal(leftF);} static bool HasFaceColor() { return true; } static bool HasFaceColorOcf() { return true; } }; template class Color4bOcf: public ColorOcf {}; ///*-------------------------- MARK ----------------------------------*/ template class MarkOcf: public T { public: inline int & IMark() { assert((*this).Base().MarkEnabled); return (*this).Base().MV[(*this).Index()]; } inline int IMark() const { assert((*this).Base().MarkEnabled); return (*this).Base().MV[(*this).Index()]; } ; template void ImportLocal(const LeftF & leftF){IMark() = leftF.cIMark(); T::ImportLocal(leftF);} static bool HasFaceMark() { return true; } static bool HasFaceMarkOcf() { return true; } inline void InitIMark() { IMark() = 0; } }; ///*-------------------------- WEDGE TEXCOORD ----------------------------------*/ template class WedgeTexCoordOcf: public TT { public: WedgeTexCoordOcf(){ } typedef A TexCoordType; TexCoordType &WT(const int i) { assert((*this).Base().WedgeTexEnabled); return (*this).Base().WTV[(*this).Index()].wt[i]; } TexCoordType const &cWT(const int i) const { assert((*this).Base().WedgeTexEnabled); return (*this).Base().WTV[(*this).Index()].wt[i]; } template void ImportLocal(const LeftF & leftF){WT() = leftF.cWT(); TT::ImportLocal(leftF);} static bool HasWedgeTexCoord() { return true; } static bool HasWedgeTexCoordOcf() { return true; } }; template class WedgeTexCoordfOcf: public WedgeTexCoordOcf, T> {}; ///*-------------------------- InfoOpt ----------------------------------*/ template < class T> class InfoOcf: public T { public: vector_ocf &Base() const { return *_ovp;} template void ImportLocal(const LeftF & leftF){T::ImportLocal(leftF);} static bool HasFaceColorOcf() { return false; } static bool HasFaceNormalOcf() { return false; } static bool HasFaceMarkOcf() { return false; } static bool HasWedgeTexCoordOcf() { return false; } static bool HasFFAdjacencyOcf() { return false; } static bool HasVFAdjacencyOcf() { return false; } inline int Index() const { typename T::FaceType const *tp=static_cast(this); int tt2=tp- &*(_ovp->begin()); return tt2; } public: // ovp Optional Vector Pointer // Pointer to the base vector where each face element is stored. // used to access to the vectors of the other optional members. vector_ocf *_ovp; }; } // end namespace face template < class, class > class TriMesh; namespace tri { template < class VertContainerType, class FaceType > bool HasVFAdjacency (const TriMesh < VertContainerType , face::vector_ocf< FaceType > > & m) { if(FaceType::HasVFAdjacencyOcf()) return m.face.IsVFAdjacencyEnabled(); else return FaceType::FaceType::HasVFAdjacency(); } template < class VertContainerType, class FaceType > bool HasFFAdjacency (const TriMesh < VertContainerType , face::vector_ocf< FaceType > > & m) { if(FaceType::HasFFAdjacencyOcf()) return m.face.IsFFAdjacencyEnabled(); else return FaceType::FaceType::HasFFAdjacency(); } template < class VertContainerType, class FaceType > bool HasPerWedgeTexCoord (const TriMesh < VertContainerType , face::vector_ocf< FaceType > > & m) { if(FaceType::HasWedgeTexCoordOcf()) return m.face.IsWedgeTexEnabled(); else return FaceType::HasWedgeTexCoord(); } template < class VertContainerType, class FaceType > bool HasPerFaceColor (const TriMesh < VertContainerType , face::vector_ocf< FaceType > > & m) { if(FaceType::HasFaceColorOcf()) return m.face.IsColorEnabled(); else return FaceType::HasFaceColor(); } template < class VertContainerType, class FaceType > bool HasPerFaceMark (const TriMesh < VertContainerType , face::vector_ocf< FaceType > > & m) { if(FaceType::HasFaceMarkOcf()) return m.face.IsMarkEnabled(); else return FaceType::HasFaceMark(); } template < class FaceType > void ReorderFace( std::vector &newFaceIndex, face::vector_ocf< FaceType > &faceVec) { faceVec.ReorderFace(newFaceIndex); } } }// end namespace vcg #endif qutemol/vcg/vcg/simplex/faceplus/component_occ.h0000444000175000017500000003056510631551370020454 0ustar mbamba/**************************************************************************** * VCGLib o o * * Visual and Computer Graphics Library o o * * _ O _ * * Copyright(C) 2004 \/)\/ * * Visual Computing Lab /\/| * * ISTI - Italian National Research Council | * * \ * * All rights reserved. * * * * 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. * * * * 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 (http://www.gnu.org/licenses/gpl.txt) * * for more details. * * * ****************************************************************************/ /**************************************************************************** History $Log: component_occ.h,v $ Revision 1.7 2007/06/06 15:30:00 marfr960 Deleted redundant EdgePlane attribute: it is already defined in component_rt Revision 1.6 2007/03/12 15:37:19 tarini Texture coord name change! "TCoord" and "Texture" are BAD. "TexCoord" is GOOD. Revision 1.5 2007/01/18 01:29:48 cignoni commented UberP access method (syntax errors) Revision 1.4 2006/12/04 10:59:15 ganovelli aggiunte funzioni di override per Has* Revision 1.3 2006/06/08 20:32:10 ganovelli aggiunte wedge coord Revision 1.2 2005/10/18 14:27:22 ganovelli EdgePLaneType added (_RT) Revision 1.1 2005/10/15 16:23:39 ganovelli Working release (compilata solo su MSVC), component_occ migrato da component_opt ****************************************************************************/ /* Note OCC = Optional Component Compact compare with OCF(Optional Component Fast) ****************************************************************************/ #ifndef __VCG_FACE_PLUS_COMPONENT_OCC #define __VCG_FACE_PLUS_COMPONENT_OCC #include #include #include namespace vcg { namespace face { ///*-------------------------- WedgeTexCoordOcc ----------------------------------------*/ template class WedgeTexCoordOcc: public T { public: typedef A WedgeTexCoordType; WedgeTexCoordType &WT(const int&i) {return CAT< vector_occ,WedgeTexCoordType>::Instance()->Get((FaceType*)this);} static bool HasWedgeTexCoord() { return true; } static bool HasWedgeTexCoordOcc() { return true; } }; template class WedgeTexCoordfOcc: public WedgeTexCoordOcc, T> {}; ///*-------------------------- FACEINFO ----------------------------------------*/ template class InfoOccBase: public T { public: typedef A InfoType; InfoType &N() {return CAT< vector_occ,InfoType>::Instance()->Get((FaceType*)this);} static bool HasInfo() { return true; } static bool HasInfoOcc() { return true; } }; template class InfoOcc: public InfoOccBase {}; ///*-------------------------- NORMAL ----------------------------------------*/ template class NormalOcc: public T { public: typedef A NormalType; NormalType &N() {return CAT< vector_occ,NormalType>::Instance()->Get((FaceType*)this);} static bool HasFaceNormal() { return true; } static bool HasFaceNormalOcc() { return true; } }; template class Normal3sOcc: public NormalOcc {}; template class Normal3fOcc: public NormalOcc {}; template class Normal3dOcc: public NormalOcc {}; ///*-------------------------- MARK ----------------------------------------*/ template class MarkOcc: public T { public: typedef int MarkType; int &IMark() {return CAT< vector_occ,MarkType>::Instance()->Get((MarkType*)this);} static bool HasFaceMark() { return true; } static bool HasFaceMarkOcc() { return true; } inline void InitIMark() { IMark() = 0; } }; ///*-------------------------- COLOR ----------------------------------------*/ template class ColorOcc: public T { public: typedef A ColorType; ColorType &C() { return CAT< vector_occ,ColorType>::Instance()->Get((FaceType*)this); } static bool HasFaceColor() { return true; } static bool HasfaceColorOcc() { return true; } }; template class Color4bOcc: public ColorOcc {}; /*----------------------------- VFADJ ---------------------------------------*/ // questo tipo serve per tenere tutte le informazioni sull'adiacenza dentro una // singola classe template struct VFAdjTypeSup { FP _vfp[3]; char _vfi[3]; }; template class VFAdjOccBase: public T { public: typedef A VFAdjType; typename T::FacePointer &VFp(const int j) { return (CAT< vector_occ,VFAdjTypeSup >::Instance()->Get((FaceType*)this))._vfp[j];} typename T::FacePointer cVFp(const int j) const { return (CAT< vector_occ,VFAdjTypeSup >::Instance()->Get((FaceType*)this))._vfp[j];} char &VFi(const int j) { return (CAT< vector_occ,VFAdjTypeSup >::Instance()->Get((FaceType*)this))._vfi[j];} static bool HasVFAdjacency() { return true; } static bool HasVFAdjacencyOcc() { return true; } }; template class VFAdjOcc : public VFAdjOccBase,T>{}; /*----------------------------- FFADJ -----------------------------------*/ // questo tipo serve per tenere tutte le informazioni sull'adiacenza dentro una // singola classe template struct FFAdjTypeSup { FP _ffp[3]; char _ffi[3]; }; template class FFAdjOccBase: public T { public: // typedef A FFAdjType; typedef FFAdjTypeSup FFAdjType; typename T::FacePointer &FFp(const int j) { return (CAT< vector_occ,FFAdjTypeSup >::Instance()->Get((FaceType*)this))._ffp[j];} typename T::FacePointer const FFp(const int j) const { return (CAT< vector_occ,FFAdjTypeSup >::Instance()->Get((FaceType*)this))._ffp[j];} typename T::FacePointer const cFFp(const int j) const { return (CAT< vector_occ,FFAdjTypeSup >::Instance()->Get((FaceType*)this))._ffp[j];} char &FFi(const int j) { return (CAT< vector_occ,FFAdjTypeSup >::Instance()->Get((FaceType*)this))._ffi[j];} char cFFi(const int j) const{ return (CAT< vector_occ,FFAdjTypeSup >::Instance()->Get((FaceType*)this ))._ffi[j]; } static bool HasFFAdjacency() { return true; } static bool HasFFAdjacencyOcc() { return true; } }; template class FFAdjOcc : public FFAdjOccBase,T>{}; template class VertexRefOcc: public T { public: // typedef typename T::VertexType VertexType; // typedef typename T::VertexType::CoordType CoordType; inline typename T::VertexType * & V( const int j ) { assert(j>=0 && j<3); return (CAT< vector_occ,VertexRef >::Instance()->Get((FaceType*)this)).V(j); } inline typename T::VertexType * const & V( const int j ) const { assert(j>=0 && j<3); return (CAT< vector_occ,VertexRef >::Instance()->Get((FaceType*)this)).V(j); } inline typename T::VertexType * const cV( const int j ) const { assert(j>=0 && j<3); return (CAT< vector_occ,VertexRef >::Instance()->Get((FaceType*)this)).V(j); } // Shortcut per accedere ai punti delle facce inline typename T::CoordType & P( const int j ) { assert(j>=0 && j<3); return V(j)->P(); } inline const typename T::CoordType & P( const int j ) const { assert(j>=0 && j<3); return V(j)->cP(); } inline const typename T::CoordType &cP( const int j ) const { assert(j>=0 && j<3); return V(j)->cP(); } /** Return the pointer to the ((j+1)%3)-th vertex of the face. @param j Index of the face vertex. */ inline typename T::VertexType * & V0( const int j ) { return V(j);} inline typename T::VertexType * & V1( const int j ) { return V((j+1)%3);} inline typename T::VertexType * & V2( const int j ) { return V((j+2)%3);} inline const typename T::VertexType * const & V0( const int j ) const { return V(j);} inline const typename T::VertexType * const & V1( const int j ) const { return V((j+1)%3);} inline const typename T::VertexType * const & V2( const int j ) const { return V((j+2)%3);} inline const typename T::VertexType * const & cV0( const int j ) const { return cV(j);} inline const typename T::VertexType * const & cV1( const int j ) const { return cV((j+1)%3);} inline const typename T::VertexType * const & cV2( const int j ) const { return cV((j+2)%3);} /// Shortcut per accedere ai punti delle facce inline typename T::CoordType & P0( const int j ) { return V(j)->P();} inline typename T::CoordType & P1( const int j ) { return V((j+1)%3)->P();} inline typename T::CoordType & P2( const int j ) { return V((j+2)%3)->P();} inline const typename T::CoordType & P0( const int j ) const { return V(j)->P();} inline const typename T::CoordType & P1( const int j ) const { return V((j+1)%3)->P();} inline const typename T::CoordType & P2( const int j ) const { return V((j+2)%3)->P();} inline const typename T::CoordType & cP0( const int j ) const { return cV(j)->P();} inline const typename T::CoordType & cP1( const int j ) const { return cV((j+1)%3)->P();} inline const typename T::CoordType & cP2( const int j ) const { return cV((j+2)%3)->P();} //inline typename T::VertexType * & UberV( const int j ) { assert(j>=0 && j<3); return v[j]; } //inline const typename T::VertexType * const & UberV( const int j ) const { assert(j>=0 && j<3); return v[j]; } static bool HasVertexRef() { return true; } }; } // end namespace face template < class, class > class TriMesh; namespace tri { template < class VertContainerType, class FaceType > bool HasVFAdjacency (const TriMesh < VertContainerType , vector_occ< FaceType > > & m) { if(FaceType::HasVFAdjacencyOcc()) return m.face.IsEnabledAttribute(); else return FaceType::FaceType::HasVFAdjacency(); } template < class VertContainerType, class FaceType > bool HasFFAdjacency (const TriMesh < VertContainerType , vector_occ< FaceType > > & m) { if(FaceType::HasFFAdjacencyOcc()) return m.face.IsEnabledAttribute(); else return FaceType::FaceType::HasFFAdjacency(); } template < class VertContainerType, class FaceType > bool HasPerWedgeTexCoord (const TriMesh < VertContainerType , vector_occ< FaceType > > & m) { if(FaceType::HasWedgeTexCoordOcc()) return m.face.IsEnabledAttribute(); else return FaceType::FaceType::HasWedgeTexCoord(); } template < class VertContainerType, class FaceType > bool HasPerFaceColor (const TriMesh < VertContainerType , vector_occ< FaceType > > & m) { if(FaceType::HasFaceColorOcc()) return m.face.IsEnabledAttribute(); else return FaceType::FaceType::HasFaceColor(); } template < class VertContainerType, class FaceType > bool HasPerFaceMark (const TriMesh < VertContainerType , vector_occ< FaceType > > & m) { if(FaceType::HasFaceMarkOcc()) return m.face.IsEnabledAttribute(); else return FaceType::FaceType::HasFaceMark(); } }; // end namesace tri }// end namespace vcg #endif qutemol/vcg/vcg/simplex/faceplus/base.h0000444000175000017500000003703510751701424016537 0ustar mbamba/**************************************************************************** * VCGLib o o * * Visual and Computer Graphics Library o o * * _ O _ * * Copyright(C) 2004 \/)\/ * * Visual Computing Lab /\/| * * ISTI - Italian National Research Council | * * \ * * All rights reserved. * * * * 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. * * * * 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 (http://www.gnu.org/licenses/gpl.txt) * * for more details. * * * ****************************************************************************/ /**************************************************************************** History $Log: base.h,v $ Revision 1.14 2008/02/04 21:26:44 ganovelli added ImportLocal which imports all local attributes into vertexplus and faceplus. A local attribute is everything (N(), C(), Q()....) except pointers to other simplices (i.e. FFAdj, VFAdj, VertexRef) which are set to NULL. Added some function for const attributes Revision 1.13 2008/02/03 23:49:42 cignoni Important Change. Now GetBBox return a null bbox if called on a deleted face (instead of crashing) Revision 1.12 2007/05/04 16:40:11 ganovelli changes to comply "plus" types Revision 1.11 2007/03/27 09:22:11 cignoni Added Visited flags Revision 1.10 2007/03/12 15:37:19 tarini Texture coord name change! "TCoord" and "Texture" are BAD. "TexCoord" is GOOD. Revision 1.9 2007/02/12 19:01:23 ganovelli added Name(std:vector& n) that fills n with the names of the attribute of the face type Revision 1.8 2006/10/09 20:20:18 cignoni Increased the maximum number of possible template args from 8 to 9 Revision 1.7 2006/02/27 17:58:11 ponchio Added some documentation Revision 1.6 2005/12/16 13:28:09 cignoni Increased the maximum number of possible template args from 7 to 8 Revision 1.5 2005/12/02 00:41:38 cignoni Added and removed typenames for gcc compiling. Added this-> qualifier for referencing the elemntes of the templated base class (e.g. to refer the possibly overridden flags()) it seems to be needed by the standard Revision 1.4 2005/11/16 22:56:32 cignoni Added EmptyMark to base class Standardized name of flags. It is plural becouse each simplex has many flag. Revision 1.3 2005/11/12 18:42:18 cignoni Added ClearS and GetBBox Revision 1.2 2005/10/14 13:26:57 cignoni First Really Working version Revision 1.2 2004/04/03 13:33:55 cignoni Missing include Revision 1.1 2004/03/29 08:36:26 cignoni First working version! ****************************************************************************/ #ifndef __VCG_FACE_PLUS #define __VCG_FACE_PLUS #include #include #include #include namespace vcg { /*------------------------------------------------------------------*/ /* The base class of all the recusive definition chain. It is just a container of the typenames of the various simplexes. These typenames must be known form all the derived classes. */ template class FaceTypeHolder{ public: typedef BVT VertexType; typedef typename VertexType::CoordType CoordType; typedef typename VertexType::ScalarType ScalarType; typedef BET EdgeType; typedef BFT FaceType; typedef BTT TetraType; typedef BVT *VertPointer; typedef BET *EdgePointer; typedef BFT *FacePointer; typedef BTT *TetraPointer; template void ImportLocal(const LeftF & l){} static void Name(std::vector & name){} // prot }; /* The base class form which we start to add our components. it has the empty definition for all the standard members (coords, color flags) Note: in order to avoid both virtual classes and ambiguous definitions all the subsequent overrides must be done in a sequence of derivation. In other words we cannot derive and add in a single derivation step (with multiple ancestor), both the real (non-empty) normal and color but we have to build the type a step a time (deriving from a single ancestor at a time). */ template class FaceBase: public face::EmptyVertexRef< face::EmptyAdj< face::EmptyColorQuality< face::EmptyNormal< face::EmptyBitFlags< face::EmptyMark< face::EmptyWedgeTexCoord< FaceTypeHolder > > > > > > >{ }; // Metaprogramming Core template class A> class FaceArity1: public A > {}; template class A, template class B> class FaceArity2: public B > {}; template class A, template class B, template class C > class FaceArity3: public C > {}; template class A, template class B, template class C, template class D> class FaceArity4: public D > {}; template class A, template class B, template class C, template class D, template class E > class FaceArity5: public E > {}; template class A, template class B, template class C, template class D, template class E, template class F > class FaceArity6: public F > {}; template class A, template class B, template class C, template class D, template class E, template class F, template class G > class FaceArity7: public G > {}; template class A, template class B, template class C, template class D, template class E, template class F, template class G, template class H > class FaceArity8: public H > {}; /* The Real Big Face class; The class __FaceArityMax__ is the one that is the Last to be derived, and therefore is the only one to know the real members (after the many overrides) so all the functions with common behaviour using the members defined in the various Empty/nonEmpty component classes MUST be defined here. I.e. IsD() that uses the overridden Flags() member must be defined here. */ template class A, template class B, template class C, template class D, template class E, template class F, template class G, template class H, template class I > class FaceArityMax: public I > { // ----- Flags stuff ----- public: inline int & UberFlags () { return this->Flags(); } inline const int UberFlags() const { return this->Flags(); } enum { DELETED = 0x00000001, // Face is deleted from the mesh NOTREAD = 0x00000002, // Face of the mesh is not readable NOTWRITE = 0x00000004, // Face of the mesh is not writable VISITED = 0x00000010, // Face has been visited. Usualy this is a per-algorithm used bit. SELECTED = 0x00000020, // Face is selected. Algorithms should try to work only on selected face (if explicitly requested) // Border _flags, it is assumed that BORDERi = BORDER0<Flags() & DELETED) != 0;} /// checks if the Face is readable bool IsR() const {return (this->Flags() & NOTREAD) == 0;} /// checks if the Face is modifiable bool IsW() const {return (this->Flags() & NOTWRITE)== 0;} /// This funcion checks whether the Face is both readable and modifiable bool IsRW() const {return (this->Flags() & (NOTREAD | NOTWRITE)) == 0;} /// checks if the Face is Modified bool IsS() const {return (this->Flags() & SELECTED) != 0;} /// checks if the Face is Modified bool IsV() const {return (this->Flags() & VISITED) != 0;} /** Set the flag value @param flagp Valore da inserire nel flag */ void SetFlags(int flagp) {this->Flags()=flagp;} /** Set the flag value @param flagp Valore da inserire nel flag */ void ClearFlags() {this->Flags()=0;} /// deletes the Face from the mesh void SetD() {this->Flags() |=DELETED;} /// un-delete a Face void ClearD() {this->Flags() &=(~DELETED);} /// marks the Face as readable void SetR() {this->Flags() &=(~NOTREAD);} /// marks the Face as not readable void ClearR() {this->Flags() |=NOTREAD;} /// marks the Face as writable void SetW() {this->Flags() &=(~NOTWRITE);} /// marks the Face as notwritable void ClearW() {this->Flags() |=NOTWRITE;} /// select the Face void SetS() {this->Flags() |=SELECTED;} /// Un-select a Face void ClearS() {this->Flags() &= ~SELECTED;} /// select the Face void SetV() {this->Flags() |=VISITED;} /// Un-select a Face void ClearV() {this->Flags() &= ~VISITED;} /// This function checks if the face is selected bool IsB(int i) const {return (this->Flags() & (BORDER0<Flags() |=(BORDER0<Flags() &= (~(BORDER0<>1; return true; } assert(0); return false; } /// This function checks if the given user bit is true bool IsUserBit(int userBit){return (this->Flags() & userBit) != 0;} /// This function set the given user bit void SetUserBit(int userBit){this->Flags() |=userBit;} /// This function clear the given user bit void ClearUserBit(int userBit){this->Flags() &= (~userBit);} template void GetBBox( BoxType & bb ) const { if(this->IsD()) { bb.SetNull(); return; } bb.Set(this->P(0)); bb.Add(this->P(1)); bb.Add(this->P(2)); } }; template < typename T=int> class FaceDefaultDeriver : public T {}; /* These are the three main classes that are used by the library user to define its own Facees. The user MUST specify the names of all the type involved in a generic complex. so for example when defining a Face of a trimesh you must know the name of the type of the edge and of the face. Typical usage example: A Face with coords, flags and normal for use in a standard trimesh: class MyFaceNf : public FaceSimp2< VertProto, EdgeProto, MyFaceNf, face::Flag, face::Normal3f > {}; A Face with coords, and normal for use in a tetrahedral mesh AND in a standard trimesh: class TetraFace : public FaceSimp3< VertProto, EdgeProto, TetraFace, TetraProto, face::Coord3d, face::Normal3f > {}; A summary of the components that can be added to a face (see components.h for details): VertexRef NormalFromVert, WedgeNormal Normal3s, Normal3f, Normal3d WedgeTexCoord2s, WedgeTexCoord2f, WedgeTexCoord2d BitFlags WedgeColor, Color4b Qualitys, Qualityf, Qualityd Mark //Incremental mark (int) VFAdj //Topology vertex face adjacency (pointers to next face in the ring of the vertex FFAdj //topology: face face adj pointers to adjacent faces */ template class A = FaceDefaultDeriver, template class B = FaceDefaultDeriver, template class C = FaceDefaultDeriver, template class D = FaceDefaultDeriver, template class E = FaceDefaultDeriver, template class F = FaceDefaultDeriver, template class G = FaceDefaultDeriver, template class H = FaceDefaultDeriver, template class I = FaceDefaultDeriver > class FaceSimp3: public FaceArityMax {}; class DumTT; template class A = FaceDefaultDeriver, template class B = FaceDefaultDeriver, template class C = FaceDefaultDeriver, template class D = FaceDefaultDeriver, template class E = FaceDefaultDeriver, template class F = FaceDefaultDeriver, template class G = FaceDefaultDeriver, template class H = FaceDefaultDeriver, template class I = FaceDefaultDeriver > class FaceSimp2: public FaceArityMax {}; }// end namespace #endif qutemol/vcg/vcg/simplex/faceplus/component.h0000444000175000017500000005554610752027212017633 0ustar mbamba/**************************************************************************** * VCGLib o o * * Visual and Computer Graphics Library o o * * _ O _ * * Copyright(C) 2004 \/)\/ * * Visual Computing Lab /\/| * * ISTI - Italian National Research Council | * * \ * * All rights reserved. * * * * 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. * * * * 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 (http://www.gnu.org/licenses/gpl.txt) * * for more details. * * * ****************************************************************************/ /**************************************************************************** History $Log: component.h,v $ Revision 1.22 2008/02/05 09:38:18 ganovelli typo in EmptyVertexRef corrected Revision 1.21 2008/02/04 21:26:45 ganovelli added ImportLocal which imports all local attributes into vertexplus and faceplus. A local attribute is everything (N(), C(), Q()....) except pointers to other simplices (i.e. FFAdj, VFAdj, VertexRef) which are set to NULL. Added some function for const attributes Revision 1.20 2008/01/28 08:42:51 cignoni added assert when writing on empty data members Revision 1.19 2008/01/19 17:49:05 ganovelli missing const cVF added Revision 1.18 2007/11/20 09:43:53 ganovelli added missing include to color4 Revision 1.17 2007/05/04 16:16:04 ganovelli added include to texcoor2 Revision 1.16 2007/03/12 15:42:11 tarini Texture coord name change! "TCoord" and "Texture" are BAD. "TexCoord" is GOOD. Revision 1.15 2007/03/12 15:37:19 tarini Texture coord name change! "TCoord" and "Texture" are BAD. "TexCoord" is GOOD. Revision 1.14 2007/02/27 09:32:00 cignoni Added constructor to the VFadj component to comply to the allocator needs Revision 1.13 2007/02/12 19:01:23 ganovelli added Name(std:vector& n) that fills n with the names of the attribute of the face type Revision 1.12 2007/01/11 10:22:39 cignoni Added intialization of vertexRef to 0. Revision 1.11 2006/12/06 00:08:57 cignoni Added FFp1 and FFp2 shortcuts Revision 1.10 2006/12/04 11:00:02 ganovelli Cambiate Has*Opt in Has*Occ e aggiunti typedef per la compilazione di Occ Revision 1.9 2006/11/28 22:34:28 cignoni Added default constructor with null initialization to adjacency members. AddFaces and AddVertices NEED to know if the topology is correctly computed to update it. Revision 1.8 2006/10/07 09:59:42 cignoni Added missing const to EmptyFF Revision 1.7 2006/01/09 13:58:55 cignoni Added Initialization of Color in Vertex and Face Components Revision 1.6 2005/11/22 15:49:39 cignoni removed two spurious computenormal Revision 1.5 2005/11/21 21:44:47 cignoni Moved ComputeNormal and ComputeNormalizedNormal out of the face class (no more a member function!) Revision 1.4 2005/11/18 15:44:49 cignoni Access to constant normal changed from by val to by reference Revision 1.3 2005/11/16 22:58:17 cignoni Added IncrementalMark and WedgeTexCoord Standardized name of flags. It is plural becouse each simplex has many flag. Revision 1.2 2005/11/12 18:43:14 cignoni added missing cFFi Revision 1.1 2005/10/14 15:07:58 cignoni First Really Working version ****************************************************************************/ #ifndef __VCG_FACE_PLUS_COMPONENT #define __VCG_FACE_PLUS_COMPONENT #include #include #include #include namespace vcg { namespace face { /* Some naming Rules All the Components that can be added to a vertex should be defined in the namespace vert: */ /*-------------------------- VERTEX ----------------------------------------*/ template class EmptyVertexRef: public T { public: // typedef typename T::VertexType VertexType; // typedef typename T::CoordType CoordType; inline typename T::VertexType * & V( const int j ) { assert(0); static typename T::VertexType *vp=0; return vp; } inline typename T::VertexType * const & V( const int j ) const { assert(0); static typename T::VertexType *vp=0; return vp; } inline typename T::VertexType * const cV( const int j ) const { assert(0); static typename T::VertexType *vp=0; return vp; } inline typename T::CoordType & P( const int j ) { assert(0); static typename T::CoordType coord(0, 0, 0); return coord; } inline const typename T::CoordType & P( const int j ) const { assert(0); static typename T::CoordType coord(0, 0, 0); return coord; } inline const typename T::CoordType &cP( const int j ) const { assert(0); static typename T::CoordType coord(0, 0, 0); return coord; } template void ImportLocal(const LeftF & leftF) {T::ImportLocal(leftF);} static bool HasVertexRef() { return false; } static void Name(std::vector & name){T::Name(name);} }; template class VertexRef: public T { public: VertexRef(){ v[0]=0; v[1]=0; v[2]=0; } inline typename T::VertexType * & V( const int j ) { assert(j>=0 && j<3); return v[j]; } inline typename T::VertexType * const & V( const int j ) const { assert(j>=0 && j<3); return v[j]; } inline typename T::VertexType * const cV( const int j ) const { assert(j>=0 && j<3); return v[j]; } // Shortcut per accedere ai punti delle facce inline typename T::CoordType & P( const int j ) { assert(j>=0 && j<3); return v[j]->P(); } inline const typename T::CoordType & P( const int j ) const { assert(j>=0 && j<3); return v[j]->cP(); } inline const typename T::CoordType &cP( const int j ) const { assert(j>=0 && j<3); return v[j]->cP(); } /** Return the pointer to the ((j+1)%3)-th vertex of the face. @param j Index of the face vertex. */ inline typename T::VertexType * & V0( const int j ) { return V(j);} inline typename T::VertexType * & V1( const int j ) { return V((j+1)%3);} inline typename T::VertexType * & V2( const int j ) { return V((j+2)%3);} inline const typename T::VertexType * const & V0( const int j ) const { return V(j);} inline const typename T::VertexType * const & V1( const int j ) const { return V((j+1)%3);} inline const typename T::VertexType * const & V2( const int j ) const { return V((j+2)%3);} inline const typename T::VertexType * const & cV0( const int j ) const { return cV(j);} inline const typename T::VertexType * const & cV1( const int j ) const { return cV((j+1)%3);} inline const typename T::VertexType * const & cV2( const int j ) const { return cV((j+2)%3);} /// Shortcut per accedere ai punti delle facce inline typename T::CoordType & P0( const int j ) { return V(j)->P();} inline typename T::CoordType & P1( const int j ) { return V((j+1)%3)->P();} inline typename T::CoordType & P2( const int j ) { return V((j+2)%3)->P();} inline const typename T::CoordType & P0( const int j ) const { return V(j)->P();} inline const typename T::CoordType & P1( const int j ) const { return V((j+1)%3)->P();} inline const typename T::CoordType & P2( const int j ) const { return V((j+2)%3)->P();} inline const typename T::CoordType & cP0( const int j ) const { return cV(j)->P();} inline const typename T::CoordType & cP1( const int j ) const { return cV((j+1)%3)->P();} inline const typename T::CoordType & cP2( const int j ) const { return cV((j+2)%3)->P();} inline typename T::VertexType * & UberV( const int j ) { assert(j>=0 && j<3); return v[j]; } inline const typename T::VertexType * const & UberV( const int j ) const { assert(j>=0 && j<3); return v[j]; } template void ImportLocal(const LeftF & leftF){ V(0) = NULL; V(1) = NULL; V(2) = NULL; T::ImportLocal(leftF);} static bool HasVertexRef() { return true; } static void Name(std::vector & name){name.push_back(std::string("VertexRef"));T::Name(name);} private: typename T::VertexType *v[3]; }; /*-------------------------- NORMAL ----------------------------------------*/ template class EmptyNormal: public T { public: //typedef vcg::Point3s NormalType; typedef typename T::VertexType::NormalType NormalType; NormalType &N() { static NormalType dummy_normal(0, 0, 0); assert(0); return dummy_normal; } const NormalType &cN() const { static NormalType dummy_normal(0, 0, 0); return dummy_normal; } NormalType &WN(int) { static NormalType dummy_normal(0, 0, 0); assert(0); return dummy_normal; } const NormalType cWN(int) const { static NormalType dummy_normal(0, 0, 0); return dummy_normal; } template void ImportLocal(const LeftF & leftF){ T::ImportLocal(leftF);} static bool HasWedgeNormal() { return false; } static bool HasFaceNormal() { return false; } static bool HasWedgeNormalOcc() { return false; } static bool HasFaceNormalOcc() { return false; } // void ComputeNormal() {assert(0);} // void ComputeNormalizedNormal() {assert(0);} static void Name(std::vector & name){ T::Name(name);} }; template class NormalFromVert: public T { public: typedef typename T::VertexType::NormalType NormalType; NormalType &N() { return _norm; } NormalType &cN() const { return _norm; } template void ImportLocal(const LeftF & leftF){ N() = leftF.cN(); T::ImportLocal(leftF);} static bool HasFaceNormal() { return true; } // void ComputeNormal() { _norm = vcg::Normal(*(static_cast(this))); } // void ComputeNormalizedNormal() { _norm = vcg::NormalizedNormal(*this);} static void Name(std::vector & name){name.push_back(std::string("NormalFromVert"));T::Name(name);} private: NormalType _norm; }; template void ComputeNormal(T &f) { f.N() = vcg::Normal(f); } template void ComputeNormalizedNormal(T &f) { f.N() = vcg::NormalizedNormal(f); } template class NormalAbs: public T { public: typedef A NormalType; NormalType &N() { return _norm; } NormalType cN() const { return _norm; } template void ImportLocal(const LeftF & leftF){ N() = leftF.cN(); T::ImportLocal(leftF);} static bool HasFaceNormal() { return true; } static void Name(std::vector & name){name.push_back(std::string("NormalAbs"));T::Name(name);} private: NormalType _norm; }; template class WedgeNormal: public T { public: typedef typename T::VertexType::NormalType NormalType; NormalType &WN(const int j) { return _wnorm[j]; } const NormalType cWN(const int j) const { return _wnorm[j]; } template void ImportLocal(const LeftF & leftF){ WN() = leftF.cWN(); T::ImportLocal(leftF);} static bool HasWedgeNormal() { return true; } static void Name(std::vector & name){name.push_back(std::string("WedgeNormal"));T::Name(name);} private: NormalType _wnorm[3]; }; template class Normal3s: public NormalAbs { public:static void Name(std::vector & name){name.push_back(std::string("Normal3s"));T::Name(name);} }; template class Normal3f: public NormalAbs { public: static void Name(std::vector & name){name.push_back(std::string("Normal3f"));T::Name(name);} }; template class Normal3d: public NormalAbs { public: static void Name(std::vector & name){name.push_back(std::string("Normal3d"));T::Name(name);} }; /*-------------------------- TexCoord ----------------------------------------*/ template class EmptyWedgeTexCoord: public TT { public: typedef int WedgeTexCoordType; typedef vcg::TexCoord2 TexCoordType; TexCoordType &WT(const int) { static TexCoordType dummy_texture; assert(0); return dummy_texture;} TexCoordType const &cWT(const int) const { static TexCoordType dummy_texture; return dummy_texture;} template void ImportLocal(const LeftF & leftF){ TT::ImportLocal(leftF);} static bool HasWedgeTexCoord() { return false; } static bool HasWedgeTexCoordOcc() { return false; } static void Name(std::vector & name){TT::Name(name);} }; template class WedgeTexCoord: public TT { public: typedef int WedgeTexCoordType; typedef A TexCoordType; TexCoordType &WT(const int i) { return _wt[i]; } TexCoordType const &cWT(const int i) const { return _wt[i]; } template void ImportLocal(const LeftF & leftF){ WT() = leftF.cWT();TT::ImportLocal(leftF);} static bool HasWedgeTexCoord() { return true; } static void Name(std::vector & name){name.push_back(std::string("WedgeTexCoord"));TT::Name(name);} private: TexCoordType _wt[3]; }; template class WedgeTexCoord2s: public WedgeTexCoord, TT> { public: static void Name(std::vector & name){name.push_back(std::string("WedgeTexCoord2s"));TT::Name(name);} }; template class WedgeTexCoord2f: public WedgeTexCoord, TT> { public: static void Name(std::vector & name){name.push_back(std::string("WedgeTexCoord2f"));TT::Name(name);} }; template class WedgeTexCoord2d: public WedgeTexCoord, TT> { public: static void Name(std::vector & name){name.push_back(std::string("WedgeTexCoord2d"));TT::Name(name);} }; /*------------------------- FLAGS -----------------------------------------*/ template class EmptyBitFlags: public T { public: /// Return the vector of Flags(), senza effettuare controlli sui bit int &Flags() { static int dummyflags(0); assert(0); return dummyflags; } const int Flags() const { return 0; } template void ImportLocal(const LeftF & leftF){ T::ImportLocal(leftF);} static bool HasFlags() { return false; } static bool HasFlagsOcc() { return false; } static void Name(std::vector & name){T::Name(name);} }; template class BitFlags: public T { public: BitFlags(){_flags=0;} int &Flags() {return _flags; } const int Flags() const {return _flags; } const int & cFlags() const {return _flags; } template void ImportLocal(const LeftF & leftF){ Flags() = leftF.cFlags();T::ImportLocal(leftF);} static bool HasFlags() { return true; } static void Name(std::vector & name){name.push_back(std::string("BitFlags"));T::Name(name);} private: int _flags; }; /*-------------------------- COLOR ----------------------------------*/ template class EmptyColorQuality: public T { public: typedef float QualityType; typedef vcg::Color4b ColorType; ColorType &C() { static ColorType dumcolor(vcg::Color4b::White); assert(0); return dumcolor; } ColorType &WC(const int) { static ColorType dumcolor(vcg::Color4b::White); assert(0); return dumcolor; } QualityType &Q() { static QualityType dummyQuality(0); assert(0); return dummyQuality; } static bool HasFaceColor() { return false; } static bool HasWedgeColor() { return false; } static bool HasFaceQuality() { return false; } static bool HasFaceColorOcc() { return false;} static void Name(std::vector & name){T::Name(name);} }; template class Color: public T { public: typedef A ColorType; Color():_color(vcg::Color4b::White) {} ColorType &C() { return _color; } const ColorType &cC() { return _color; } template void ImportLocal(const LeftF & leftF){ C() = leftF.cC();T::ImportLocal(leftF);} static bool HasFaceColor() { return true; } static void Name(std::vector & name){name.push_back(std::string("Color"));T::Name(name);} private: ColorType _color; }; template class WedgeColor: public T { public: typedef A ColorType; ColorType &WC(const int i) { return _color[i]; } const ColorType &WC(const int i) const { return _color[i]; } template void ImportLocal(const LeftF & leftF){ WC() = leftF.cWC();T::ImportLocal(leftF);} static bool HasFaceColor() { return true; } static void Name(std::vector & name){name.push_back(std::string("WedgeColor"));T::Name(name);} private: ColorType _color[3]; }; template class Color4b: public Color { static void Name(std::vector & name){name.push_back(std::string("Color4b"));T::Name(name);} }; /*-------------------------- Quality ----------------------------------*/ template class EmptyQuality: public T { public: static void Name(std::vector & name){T::Name(name);} }; template class Quality: public T { public: typedef A QualityType; QualityType &Q() { return _quality; } const QualityType &cQ() const { return _quality; } template void ImportLocal(const LeftF & leftF){ Q() = leftF.cQ();T::ImportLocal(leftF);} static bool HasFaceQuality() { return true; } static bool HasFaceQualityOcc() { return true; } static void Name(std::vector & name){name.push_back(std::string("Quality"));T::Name(name);} private: QualityType _quality; }; template class Qualitys: public Quality { public: static void Name(std::vector & name){name.push_back(std::string("Qualitys"));T::Name(name);} }; template class Qualityf: public Quality { public: static void Name(std::vector & name){name.push_back(std::string("Qualityf"));T::Name(name);} }; template class Qualityd: public Quality { public: static void Name(std::vector & name){name.push_back(std::string("Qualityd"));T::Name(name);} }; /*-------------------------- INCREMENTAL MARK ----------------------------------------*/ template class EmptyMark: public T { public: typedef int MarkType; static bool HasMark() { return false; } static bool HasMarkOcc() { return false; } inline void InitIMark() { } inline int & IMark() { assert(0); static int tmp=-1; return tmp;} inline const int IMark() const {return 0;} template void ImportLocal(const LeftF & leftF){T::ImportLocal(leftF);} static void Name(std::vector & name){T::Name(name);} }; template class Mark: public T { public: static bool HasMark() { return true; } static bool HasMarkOcc() { return true; } inline void InitIMark() { _imark = 0; } inline int & IMark() { return _imark;} inline const int & IMark() const {return _imark;} template void ImportLocal(const LeftF & leftF){ IMark() = leftF.IMark();T::ImportLocal(leftF);} static void Name(std::vector & name){name.push_back(std::string("Mark"));T::Name(name);} private: int _imark; }; /*----------------------------- VFADJ ------------------------------*/ template class EmptyAdj: public T { public: typedef int VFAdjType; typename T::FacePointer &VFp(const int) { static typename T::FacePointer fp=0; assert(0); return fp; } typename T::FacePointer const cVFp(const int) const { static typename T::FacePointer const fp=0; return fp; } typename T::FacePointer &FFp(const int) { static typename T::FacePointer fp=0; assert(0); return fp; } typename T::FacePointer const cFFp(const int) const { static typename T::FacePointer const fp=0; return fp; } char &VFi(const int j){static char z=0; assert(0); return z;}; char &FFi(const int j){static char z=0; assert(0); return z;}; const char &cVFi(const int j){static char z=0; return z;}; const char &cFFi(const int j){static char z=0; return z;}; template void ImportLocal(const LeftF & leftF){ T::ImportLocal(leftF);} static bool HasVFAdjacency() { return false; } static bool HasFFAdjacency() { return false; } static bool HasFFAdjacencyOcc() { return false; } static bool HasVFAdjacencyOcc() { return false; } static void Name(std::vector & name){T::Name(name);} }; template class VFAdj: public T { public: VFAdj(){ _vfp[0]=0; _vfp[1]=0; _vfp[2]=0; } typename T::FacePointer &VFp(const int j) { assert(j>=0 && j<3); return _vfp[j]; } typename T::FacePointer const VFp(const int j) const { assert(j>=0 && j<3); return _vfp[j]; } typename T::FacePointer const cVFp(const int j) const { assert(j>=0 && j<3); return _vfp[j]; } char &VFi(const int j) {return _vfi[j]; } template void ImportLocal(const LeftF & leftF){T::ImportLocal(leftF);} static bool HasVFAdjacency() { return true; } static bool HasVFAdjacencyOcc() { return false; } static void Name(std::vector & name){name.push_back(std::string("VFAdj"));T::Name(name);} private: typename T::FacePointer _vfp[3] ; char _vfi[3] ; }; /*----------------------------- FFADJ ------------------------------*/ template class FFAdj: public T { public: FFAdj(){ _ffp[0]=0; _ffp[1]=0; _ffp[2]=0; } typename T::FacePointer &FFp(const int j) { assert(j>=0 && j<3); return _ffp[j]; } typename T::FacePointer const FFp(const int j) const { assert(j>=0 && j<3); return _ffp[j]; } typename T::FacePointer const cFFp(const int j) const { assert(j>=0 && j<3); return _ffp[j]; } char &FFi(const int j) { return _ffi[j]; } const char &cFFi(const int j) const { return _ffi[j]; } typename T::FacePointer &FFp1( const int j ) { return FFp((j+1)%3);} typename T::FacePointer &FFp2( const int j ) { return FFp((j+2)%3);} typename T::FacePointer const FFp1( const int j ) const { return FFp((j+1)%3);} typename T::FacePointer const FFp2( const int j ) const { return FFp((j+2)%3);} template void ImportLocal(const LeftF & leftF){T::ImportLocal(leftF);} static bool HasFFAdjacency() { return true; } static bool HasFFAdjacencyOcc() { return false; } static void Name(std::vector & name){name.push_back(std::string("FFAdj"));T::Name(name);} private: typename T::FacePointer _ffp[3] ; char _ffi[3] ; }; } // end namespace vert }// end namespace vcg #endif qutemol/vcg/vcg/simplex/faceplus/component_rt.h0000444000175000017500000000616710627030772020341 0ustar mbamba/**************************************************************************** * VCGLib o o * * Visual and Computer Graphics Library o o * * _ O _ * * Copyright(C) 2006 \/)\/ * * Visual Computing Lab /\/| * * ISTI - Italian National Research Council | * * \ * * All rights reserved. * * * * 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. * * * * 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 (http://www.gnu.org/licenses/gpl.txt) * * for more details. * * * ****************************************************************************/ /**************************************************************************** History $Log: component_rt.h,v $ Revision 1.3 2007/05/29 14:00:26 cignoni removed useless typename Revision 1.2 2007/05/04 16:16:40 ganovelli standardized to component style Revision 1.1 2006/10/13 14:11:49 cignoni first version ****************************************************************************/ #ifndef __VCG_FACE_PLUS_COMPONENT_RT #define __VCG_FACE_PLUS_COMPONENT_RT #include namespace vcg { namespace face { template struct EdgePlaneInfo{ CoordType edge[3]; ::vcg::Plane3 plane; typename CoordType::ScalarType edgescale; }; template class EdgePlane: public T { public: typedef EdgePlaneInfo EdgePlaneType; typename T::VertexType::CoordType &Edge(const int j) { return _ep.edge[j]; } typename T::VertexType::CoordType cEdge(const int j)const { return _ep.edge[j]; } typename vcg::Plane3 &Plane() { return _ep.plane; } typename vcg::Plane3 cPlane()const { return _ep.plane; } static bool HasEdgePlane() { return true; } static void Name(std::vector & name){name.push_back(std::string("EdgePlane"));T::Name(name);} private: EdgePlaneType _ep; }; } // end namespace face }// end namespace vcg #endif qutemol/vcg/vcg/simplex/edge/0000755000175000017500000000000011633404241014545 5ustar mbambaqutemol/vcg/vcg/simplex/edge/base.h0000444000175000017500000004542110575271657015655 0ustar mbamba/**************************************************************************** * VCGLib o o * * Visual and Computer Graphics Library o o * * _ O _ * * Copyright(C) 2004 \/)\/ * * Visual Computing Lab /\/| * * ISTI - Italian National Research Council | * * \ * * All rights reserved. * * * * 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. * * * * 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 (http://www.gnu.org/licenses/gpl.txt) * * for more details. * * * ****************************************************************************/ /**************************************************************************** History $Log: base.h,v $ Revision 1.12 2007/03/12 15:37:19 tarini Texture coord name change! "TCoord" and "Texture" are BAD. "TexCoord" is GOOD. Revision 1.11 2006/10/07 10:02:16 cignoni Added missing typename for interp.parameters Revision 1.10 2005/11/30 14:05:04 ponchio Fixed some UberZ fuynctions and non defined _flags Revision 1.9 2005/10/14 12:34:55 cignoni Added ordered constructor that build a edge with unique ordering among vertices (useful for edge-collapse simplification) Revision 1.8 2005/10/01 09:22:51 cignoni Major rewriting of the whole class edge. Removed default flags and nonsense attibutes. Given consistent naming to defines. Revision 1.7 2005/07/15 15:45:51 ganovelli template parametere Scalar removed Revision 1.6 2005/04/14 11:35:09 ponchio *** empty log message *** Revision 1.5 2004/10/25 16:25:12 ponchio inline Set(...) -> inline void Set(...) Revision 1.4 2004/10/25 08:21:17 ganovelli added: constructor,Set and some minor changes. Revision 1.3 2004/05/10 14:40:28 ganovelli name of adhacency function updated Revision 1.2 2004/05/10 14:02:29 ganovelli created Revision 1.1 2004/04/26 19:04:23 ganovelli created ****************************************************************************/ #ifndef __VCGLIB__EDGE_TYPE_BASE #define __VCGLIB__EDGE_TYPE_BASE #include #include namespace vcg { /** \ingroup segment @name segment Class Edge. This is the base class for definition of a face of the mesh. @param SVTYPE (Templete Parameter) Specifies the vertex class type. */ template > class EDGE_TYPE { public: /// The base type of the segment typedef EDGE_TYPE BaseEdgeType; /// The scalar type derived from the vertex typedef typename SVTYPE::ScalarType ScalarType; /// The vertex type typedef SVTYPE VertexType; /// The type of the the vertex coordinate typedef Point3< ScalarType > CoordType; /// The bounding box type typedef Box3 BoxType; /// Default Empty Costructor inline EDGE_TYPE(){} inline EDGE_TYPE(VertexType* v0,VertexType* v1){v[0]=v0;v[1]=v1;} static inline EDGE_TYPE OrderedEdge(VertexType* v0,VertexType* v1){ if(v0= 0 && j < 2); return v[j]; } inline const SVTYPE * const & V( const int j ) const { assert( !IsD() ); assert(j>=0 && j<2); return v[j]; } inline const SVTYPE * const & cV( const int j ) const { assert( !IsD() ); assert(j>=0 && j<2); return v[j]; } // Shortcut per accedere ai punti delle facce inline CoordType & P( const int j ) { assert( !IsD() ); assert(j>=0 && j<2); return v[j]->P(); } inline const CoordType & P( const int j ) const { assert( !IsD() ); assert(j>=0 && j<2); return v[j]->cP(); } inline const CoordType & cP( const int j ) const { assert( !IsD() ); assert(j>=0 && j<2); return v[j]->cP(); } /** Return the pointer to the ((j+1)%3)-th vertex of the face. @param j Index of the face vertex. */ inline SVTYPE * & V0( const int j ) { return V(j);} inline SVTYPE * & V1( const int j ) { return V((j+1)%2);} inline const SVTYPE * const & V0( const int j ) const { return V(j);} inline const SVTYPE * const & V1( const int j ) const { return V((j+1)%2);} inline const SVTYPE * const & cV0( const int j ) const { return cV(j);} inline const SVTYPE * const & cV1( const int j ) const { return cV((j+1)%2);} /// Shortcut per accedere ai punti delle facce inline CoordType & P0( const int j ) { return V(j)->P();} inline CoordType & P1( const int j ) { return V((j+1)%2)->P();} inline const CoordType & P0( const int j ) const { return V(j)->P();} inline const CoordType & P1( const int j ) const { return V((j+1)%2)->P();} inline const CoordType & cP0( const int j ) const { return cV(j)->P();} inline const CoordType & cP1( const int j ) const { return cV((j+1)%2)->P();} inline SVTYPE * & UberV( const int j ) { assert(j>=0 && j<2); return v[j]; } inline const SVTYPE * const & UberV( const int j ) const { assert(j>=0 && j<2); return v[j]; } //@} /***********************************************/ /** @name Normal blah blah **/ //@{ #ifdef __VCGLIB_EDGE_EN /// This vector indicates the normal of the face (defines if FACE_N is defined) protected: CoordType _n; public: #endif /// Return the reference of the normal to the face (if __VCGLIB_EDGE_FN is defined). inline CoordType & N() { #ifdef __VCGLIB_EDGE_EN return _n; #else assert(0); return *(CoordType *)0; #endif } /// Return the reference of the normal to the face (if __VCGLIB_EDGE_FN is defined). inline const CoordType & N() const { #ifdef __VCGLIB_EDGE_EN return _n; #else return *(CoordType *)0; #endif } /// Return the reference of the normal to the face (if __VCGLIB_EDGE_FN is defined). inline const CoordType cN() const { #ifdef __VCGLIB_EDGE_EN return _n; #else return *(CoordType *)0; #endif } //@} /***********************************************/ /** @name Quality blah blah **/ //@{ #ifdef __VCGLIB_EDGE_EQ protected: float _q; #endif public: float & Q() { #ifdef __VCGLIB_EDGE_EQ return _q; #else assert(0); return *(float*)(0); #endif } const float & Q() const { #ifdef __VCGLIB_EDGE_EQ return _q; #else assert(0); return *(float*)(0); #endif } //@} /***********************************************/ /** @name Colors blah blah **/ //@{ protected: #ifdef __VCGLIB_EDGE_EC Color4b _c; #endif public: Color4b & C() { #ifdef __VCGLIB_EDGE_EC return _c; #else assert(0); return *(Color4b*)(0); #endif } const Color4b C() const { #ifdef __VCGLIB_EDGE_EC return _c; #else return Color4b(Color4b::White); #endif } //@} /***********************************************/ /** @name Adjacency blah blah **/ //@{ protected: #if defined(__VCGLIB_EDGE_AE) /// Vector of face pointer, it's used to indicate the adjacency relations (defines if FACE_A is defined) EDGENAME *ee[2]; // edge adiacenti /// Index of the face in the arrival face char zs[2]; #endif #ifdef __VCGLIB_EDGE_AV ///Vettore di puntatori a edge, utilizzato per indicare le adiacenze vertice faccia EDGENAME *ev[2]; char zv[2]; #endif public: /** Return the pointer to the j-th adjacent edge. @param j Index of the edge. */ inline EDGENAME * & EEp( const int j ) { assert( !IsD() ); assert(j>=0 && j<2); #if defined(__VCGLIB_EDGE_AE) return ee[j]; #else assert(0); return *(EDGENAME **)(0);; #endif } inline const EDGENAME * const & EEp( const int j ) const { assert( !IsD() ); assert(j>=0 && j<2); #if defined(__VCGLIB_EDGE_AE) return ee[j]; #else assert(0); return (EDGENAME *)0; #endif } inline EDGENAME * & EEp1( const int j ) { return EEp((j+1)%2);} inline const EDGENAME * const& EEp1( const int j ) const { return EEp((j+1)%2);} /** Return the pointer to the j-th adjacent face. @param j Index of the edge. */ inline EDGENAME * & UberEEp( const int j ) { assert(j>=0 && j<2); #if defined(__VCGLIB_EDGE_AE) return ee[j]; #else assert(0); // if you stop here you are probably trying to use FF topology in a face without it return *(EDGENAME **)(0); #endif } inline const EDGENAME * const & UberEEp( const int j ) const { assert(j>=0 && j<2); #if defined(__VCGLIB_EDGE_AE) return ee[j]; #else assert(0); // if you stop here you are probably trying to use FF topology in a face without it return *(EDGENAME **)(0); #endif } inline EDGENAME * & VEp( const int j ) { assert( !IsD() ); assert(j>=0 && j<2); #ifdef __VCGLIB_EDGE_AV return ev[j]; #else assert(0); // you are probably trying to use VF topology in a vertex without it return *(EDGENAME **)(0); #endif } inline const EDGENAME * const & VEp( const int j ) const { assert( !IsD() ); assert(j>=0 && j<2); #ifdef __VCGLIB_EDGE_AV return ev[j]; #else assert(0); return *(EDGENAME **)(0); #endif } /** Return the index that the face have in the j-th adjacent face. @param j Index of the edge. */ inline char & EEi( const int j ) { assert( !IsD() ); assert(j>=0 && j<2); #if defined(__VCGLIB_EDGE_AE) return zs[j]; #else assert(0); return *(char *)0; // tanto per farlo compilare... #endif } inline const char & EEi( const int j ) const { assert( !IsD() ); assert(j>=0 && j<2); #if defined(__VCGLIB_EDGE_AE) return zs[j]; #else assert(0); return *(char *)0; #endif } /** Return the index that the face have in the j-th adjacent face. @param j Index of the edge. */ inline char & UberZ( const int j ) { assert(j>=0 && j<2); #if defined(__VCGLIB_EDGE_AE) return zs[j]; #elif defined(__VCGLIB_EDGE_SA) return zs[j]; #else assert(0); static char dummy = 0; return dummy; #endif } inline const char & UberZ( const int j ) const { assert(j>=0 & j<2); #if defined(__VCGLIB_EDGE_AE) return zs[j]; #elif defined(__VCGLIB_EDGE_SA) return zs[j]; #else assert(0); static int dummy = 0; return dummy; #endif } inline char & VEi( const int j ) { assert( !IsD() ); assert(j>=0 & j<2); #ifdef __VCGLIB_EDGE_VA return zv[j]; #elif defined(__VCGLIB_EDGE_SA) return zs[j]; #else assert(0); static char dummy = 0; return dummy; #endif } inline const char & VEi( const int j ) const { assert( !IsD() ); assert(j>=0 & j<2); #ifdef __VCGLIB_EDGE_VA return zv[j]; #elif defined(__VCGLIB_EDGE_SA) return zs[j]; #else assert(0); static char dummy = 0; return dummy; #endif } //@} /***********************************************/ /** @name Mark blah blah **/ //@{ #ifdef __VCGLIB_EDGE_EM /// Incremental mark (defines if FACE_I is defined) int imark; #endif // Mark inline int & IMark() { #ifdef __VCGLIB_EDGE_EM assert( !IsD() ); assert( (_flags & NOTREAD) == 0 ); assert( (_flags & NOTWRITE) == 0 ); return imark; #else return 0; #endif // Mark } inline const int & IMark() const { assert( !IsD() ); #ifdef __VCGLIB_EDGE_EM assert( (_flags & NOTREAD) == 0 ); return imark; #else static int dummy = 0; return dummy; #endif } /// Initialize the imark system of the face inline void InitIMark() { #ifdef __VCGLIB_EDGE_EM imark = 0; #endif } //@} /***********************************************/ /** @name Flags blah blah **/ //@{ /// This are the _flags of face, the default value is 0 #ifdef __VCGLIB_EDGE_EF int _flags; #endif enum { // This bit indicate that the face is deleted from the mesh DELETED = 0x00000001, // cancellato // This bit indicate that the face of the mesh is not readable NOTREAD = 0x00000002, // non leggibile (ma forse modificabile) // This bit indicate that the face is not modifiable NOTWRITE = 0x00000004, // non modificabile (ma forse leggibile) // This bit indicate that the face is modified SELECTED = 0x00000020, // Selection _flags // Border _flags, it is assumed that BORDERi = BORDER0<>1; return true; } assert(0); return false; } void ClearFlags() { #ifdef __VCGLIB_EDGE_EF _flags=0; #endif } /// Return the _flags. inline int & Flags () { #ifdef __VCGLIB_EDGE_EF assert( !IsD() ); return _flags; #else return *(int *)0; #endif } inline const int & Flags () const { #ifdef __VCGLIB_EDGE_EF assert( !IsD() ); return _flags; #else return 0; #endif } /// Ritorna il _flags senza effettuare alcun controllo sui relativi bit inline int & UberFlags() { #ifdef __VCGLIB_EDGE_EF return _flags; #else assert(0); return *(int *)0; #endif } inline const int UberFlags() const { #ifdef __VCGLIB_EDGE_EF return _flags; #else return 0; #endif } /// This function checks if the face is deleted bool IsD() const { #ifdef __VCGLIB_EDGE_EF return (_flags & DELETED) != 0; #else return false; #endif } /// This function mark the face as deleted void SetD() { #ifdef __VCGLIB_EDGE_EF _flags |=DELETED; #endif } /// This function mark the face as not deleted void ClearD() { #ifdef __VCGLIB_EDGE_EF _flags &= (~DELETED); #endif } /// This function checks if the face is selected bool IsS() const { #ifdef __VCGLIB_EDGE_EF return (_flags & SELECTED) != 0; #else return false; #endif } /// This function select the face void SetS() { #ifdef __VCGLIB_EDGE_EF _flags |=SELECTED; #endif } /// This funcion execute the inverse operation of SetS() void ClearS() { #ifdef __VCGLIB_EDGE_EF _flags &= (~SELECTED); #endif } /// This function checks if the edge is Border on a given side bool IsB(int i) const { #ifdef __VCGLIB_EDGE_EF return (_flags & (BORDER0<P() ); bb.Add( v[1]->P() ); } /***********************************************/ /** @name Reflection Functions Static functions that give information about the current vertex type. Reflection is a mechanism making it possible to investigate yourself. Reflection is used to investigate format of objects at runtime, invoke methods and access fields of these objects. Here we provide static const functions that are resolved at compile time and they give information about the data (normal, color etc.) supported by the current vertex type. **/ //@{ static bool HasEdgeNormal() { #ifdef __VCGLIB_EDGE_FN return true; #else return false; #endif } static bool HasEdgeQuality() { #ifdef __VCGLIB_EDGE_FQ return true; #else return false; #endif } static bool HasEdgeColor() { #ifdef __VCGLIB_EDGE_FC return true; #else return false; #endif } static bool HasEEAdjacency() { #if (defined(__VCGLIB_EDGE_AE) ) return true; #else return false; #endif } static bool HasVEAdjacency() { #if (defined(__VCGLIB_EDGE_AV) ) return true; #else return false; #endif } static bool HasEdgeMark() { #ifdef __VCGLIB_EDGE_FC return true; #else return false; #endif } //@} /// operator to compare two edges inline bool operator == ( const EDGENAME & f ) const { if( (V(0) != f.V(0)) && (V(0) != f.V(1)) ) return false; if( (V(1) != f.V(0)) && (V(1) != f.V(1)) ) return false; return true; } /** Calcola i coefficienti della combinazione convessa. @param bq Punto appartenente alla faccia @param a Valore di ritorno per il vertice V(0) @param b Valore di ritorno per il vertice V(1) @param _c Valore di ritorno per il vertice V(2) @return true se bq appartiene alla faccia, false altrimenti */ bool InterpolationParameters(const CoordType & bq, typename VertexType::ScalarType &a, ScalarType &_b) const { typedef typename VertexType::ScalarType ScalarType; const ScalarType EPSILON = ScalarType(0.000001); ScalarType l; #define x1 (cV(0)->P().x()) #define y1 (cV(0)->P().y()) #define z1 (cV(0)->P().z()) #define x2 (cV(1)->P().x()) #define y2 (cV(1)->P().y()) #define z2 (cV(1)->P().z()) #define px (bq.x()) #define py (bq.y()) #define pz (bq.z()) a = (px-x1)/(x2-x1); l = (py-y1)/(y2-y1); if( ( l < a -EPSILON) || ( l > a +EPSILON)) return false; l = (pz-z1)/(z2-z1); if( ( l < a -EPSILON) || ( l > a +EPSILON)) return false; _b = 1-a; return true; #undef x1 #undef y1 #undef z1 #undef x2 #undef y2 #undef z2 #undef px #undef py #undef pz } /// Return the DOUBLE of the area of the face ScalarType Length() const { return Norm( (V(1)->P() - V(0)->P()).Norm()); } CoordType Barycenter() const { return (V(0)->P()+V(1)->P())/ScalarType(2.0); } }; //end Class } // end namespace #endif qutemol/vcg/vcg/simplex/edge/pos.h0000444000175000017500000001642410627513753015537 0ustar mbamba/**************************************************************************** * VCGLib o o * * Visual and Computer Graphics Library o o * * _ O _ * * Copyright(C) 2004 \/)\/ * * Visual Computing Lab /\/| * * ISTI - Italian National Research Council | * * \ * * All rights reserved. * * * * 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. * * * * 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 (http://www.gnu.org/licenses/gpl.txt) * * for more details. * * * ****************************************************************************/ /**************************************************************************** History $Log: pos.h,v $ Revision 1.3 2007/05/31 09:39:55 cignoni Small gcc compiling issues Revision 1.2 2004/05/10 14:40:47 ganovelli name of adhacency function updated Revision 1.1 2004/05/10 14:01:56 ganovelli created ****************************************************************************/ #ifndef __VCG_EDGE_POS #define __VCG_EDGE_POS namespace vcg { namespace edge { /* Vertex_Edge: run over the fan of a vertex (no order is specified) */ /** Class VertexStar @param EDGETYPE Specifies the type of the faces */ template class VertexStar { public: /// Pointer to an edge EDGETYPE *e; /// Local index of the vertex int z; /// Default Constructor VertexStar() {} /// Constructor which associates the EdgePos elementet with a face and its edge VertexStar(EDGETYPE * const ep, int const zp) { e=ep; z=zp; } /// Function to jump on the next face of the list of vertex z void NextF() { EDGETYPE * t = e; e = (EDGETYPE *)t->VEp(z); z = t->VEi(z); } }; /* */ /** Class Pos. This structure is equivalent to a half-edge. @param MFTYPE (Template-Parameter) Specifies the type of the edges */ template class Pos { public: /// The vertex type typedef typename EDGETYPE::VertexType VertexType; /////The HEdgePos type typedef Pos< EDGETYPE> POSTYPE; ///// The vector type //typedef typename MVTYPE::coord_type vectorial_type; ///// The scalar type //typedef typename MVTYPE::scalar_type scalar_type; /// Pointer to the face of the half-edge EDGETYPE *e; /// Pointer to the vertex VertexType *v; /// Default constructor Pos(){} /// Constructor which associates the half-edge elementet with a face, its edge and its vertex Pos(EDGETYPE * const ep, int const zp, VertexType * const vp){e=ep;v=vp;} /// Operator to compare two half-edge inline bool operator == ( POSTYPE const & p ) const { return (e==p.e &&v==p.v); } /// Operator to compare two half-edge inline bool operator != ( POSTYPE const & p ) const { return (e!=p.e || v!=p.v); } /// Operator to order half-edge; it's compare at the first the face pointers, then the index of the edge and finally the vertex pointers inline bool operator <= ( POSTYPE const & p) const { return (e!=p.e)?(eV(0)==v)?e->V(1):e->V(0); } void FlipE() { assert( (e->V(0)==v) ||(e->V(1)==v)); e = (e->V(0)==v)?e->EEp(0):e->EEp(1); } int Z(){ return (e->V(0)==v)?0:1; } // return the vertex that it should have if we make FlipV; VertexType *VFlip() { return (e->V(0)==v)?e->V(1):e->V(0); } // Trova il prossimo half-edge di bordo (nhe) // tale che // --nhe.f adiacente per vertice a he.f // --nhe.v adiacente per edge di bordo a he.v // l'idea e' che se he e' un half edge di bordo // si puo scorrere tutto un bordo facendo // // hei=he; // do // hei.Nextb() // while(hei!=he); /// Finds the next half-edge border void NextB( ) { // assert(f->V((z+2)%3)!=v && (f->V((z+1)%3)==v || f->V((z+0)%3)==v)); // assert(f->F(z)==f); // f is border along j //// Si deve cambiare faccia intorno allo stesso vertice v ////finche' non si trova una faccia di bordo. // do // NextE(); // while(!f->IsBorder(z)); // // // L'edge j e' di bordo e deve contenere v // assert(f->IsBorder(z) &&( f->V(z)==v || f->V((z+1)%3)==v )); // // FlipV(); // assert(f->V((z+2)%3)!=v && (f->V((z+1)%3)==v || f->V((z+0)%3)==v)); // assert(f->F(z)==f); // f is border along j } /// Checks if the half-edge is of border //bool IsBorder() //{ //return f->IsBorder(z); //} /// Return the dimension of the star //int StarSize() //{ //int n=0; //POSTYPE ht=*this; //bool bf=false; //do //{ // ++n; // ht.NextE(); // if(ht.IsBorder()) bf=true; //} while(ht!=*this); //if(bf) return n/2; //else return n; //} /** Function to inizialize an half-edge. @param fp Puntatore alla faccia @param zp Indice dell'edge @param vp Puntatore al vertice */ void Set(EDGETYPE * const ep,VertexType * const vp) { e=ep;v=vp; } void Assert() #ifdef _DEBUG {/* POSTYPE ht=*this; ht.FlipE(); ht.FlipE(); assert(ht==*this); ht.FlipE(); ht.FlipE(); assert(ht==*this); ht.FlipV(); ht.FlipV(); assert(ht==*this);*/ } #else {} #endif // Controlla la coerenza di orientamento di un hpos con la relativa faccia /// Checks the orientation coherence of a half-edge with the face //inline bool Coherent() const //{ // return v == f->V(z); // e^(ip)+1=0 ovvero E=mc^2 //} }; } // end namespace } // end namespace #endif qutemol/vcg/vcg/simplex/edge/with/0000755000175000017500000000000011633404241015520 5ustar mbambaqutemol/vcg/vcg/simplex/edge/with/ae.h0000444000175000017500000000031210047712632016254 0ustar mbamba#ifndef __VCGLIB_EDGE_AE_TYPE #define __VCGLIB_EDGE_AE_TYPE #define EDGE_TYPE EdgeAE #define __VCGLIB_EDGE_AE #include #undef EDGE_TYPE #undef __VCGLIB_EDGE_AE #endif qutemol/vcg/vcg/simplex/edge/with/emef.h0000444000175000017500000000037310461622105016605 0ustar mbamba#ifndef __VCGLIB_EDGE_EM_TYPE #define __VCGLIB_EDGE_EM_TYPE #define EDGE_TYPE EdgeEMEF #define __VCGLIB_EDGE_EM #define __VCGLIB_EDGE_EF #include #undef EDGE_TYPE #undef __VCGLIB_EDGE_EF #undef __VCGLIB_EDGE_EM #endif qutemol/vcg/vcg/simplex/edge/with/readme.txt0000444000175000017500000000434410317453141017522 0ustar mbamba/**************************************************************************** * VCGLib o o * * Visual and Computer Graphics Library o o * * _ O _ * * Copyright(C) 2004 \/)\/ * * Visual Computing Lab /\/| * * ISTI - Italian National Research Council | * * \ * * All rights reserved. * * * * 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. * * * * 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 (http://www.gnu.org/licenses/gpl.txt) * * for more details. * * * ****************************************************************************/ This folders contains most common EDGE configuration files. The name of the file specifies the members that are added to the edge class. The name is a sequence of letter pairs, in strict alphabetical order. The possible admitted letters pairs are: Adjacency Info AV - Vertex-Edge adjacency AE - Edge-Edge adjacency Per-Edge Data EC - Color EN - Normal EM - Incremental Mark EQ - Quality E.g. #include generate a type VertexAEEM That can store E-E adjacency and an incremental mark. qutemol/vcg/vcg/simplex/edge/edge.h0000444000175000017500000000021610137222350015614 0ustar mbamba#ifndef __VCGLIB_EDGE_TYPE #define __VCGLIB_EDGE_TYPE #define EDGE_TYPE Edge #include #undef EDGE_TYPE #endif qutemol/vcg/vcg/simplex/edge/distance.h0000444000175000017500000000631310461621445016516 0ustar mbamba/**************************************************************************** * VCGLib o o * * Visual and Computer Graphics Library o o * * _ O _ * * Copyright(C) 2004 \/)\/ * * Visual Computing Lab /\/| * * ISTI - Italian National Research Council | * * \ * * All rights reserved. * * * * 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. * * * * 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 (http://www.gnu.org/licenses/gpl.txt) * * for more details. * * * ****************************************************************************/ /**************************************************************************** History ****************************************************************************/ #ifndef __VCGLIB_EDGE_DISTANCE #define __VCGLIB_EDGE_DISTANCE #include #include #include namespace vcg { namespace edge{ /*Point edge distance*/ template bool PointDistance( const EdgeType &e, const vcg::Point3 & q, typename EdgeType::ScalarType & dist, vcg::Point3 & p ) { vcg::Segment3 s; s.P0()=e.V(0)->P(); s.P1()=e.V(1)->P(); EdgeType::CoordType near; vcg::ClosestPoint(s,near); EdgeType::ScalarType d=(q-p).Norm(); if (d inline bool operator () (const EDGETYPE & e, const Point3 & p, SCALARTYPE & minDist, Point3 & q) { const Point3 fp = Point3::Construct(p); Point3 fq; typename EDGETYPE::ScalarType md = (typename EDGETYPE::ScalarType)(minDist); const bool ret = PointDistance(e, fp, md, fq); minDist = (SCALARTYPE)(md); q = Point3::Construct(fq); return (ret); } }; } // end namespace edge } // end namespace vcg #endif qutemol/vcg/vcg/simplex/vertexplus/0000755000175000017500000000000011633404241016062 5ustar mbambaqutemol/vcg/vcg/simplex/vertexplus/component_ocf.h0000444000175000017500000004310610775401103021066 0ustar mbamba/**************************************************************************** * VCGLib o o * * Visual and Computer Graphics Library o o * * _ O _ * * Copyright(C) 2004 \/)\/ * * Visual Computing Lab /\/| * * ISTI - Italian National Research Council | * * \ * * All rights reserved. * * * * 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. * * * * 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 (http://www.gnu.org/licenses/gpl.txt) * * for more details. * * * ****************************************************************************/ /**************************************************************************** History $Log: component_ocf.h,v $ Revision 1.17 2008/04/04 10:26:11 cignoni Cleaned up names, now Kg() gives back Gaussian Curvature (k1*k2), while Kh() gives back Mean Curvature 1/2(k1+k2) Revision 1.16 2008/04/03 23:15:40 cignoni added optional mark and cleaned up some nasty type bugs. Revision 1.15 2008/03/17 11:39:15 ganovelli added curvature and curvatruredir (compiled .net 2005 and gcc) Revision 1.14 2008/03/11 09:22:07 cignoni Completed the garbage collecting functions CompactVertexVector and CompactFaceVector. Revision 1.13 2008/02/05 20:42:43 cignoni Other small typos Revision 1.12 2008/02/04 21:26:49 ganovelli added ImportLocal which imports all local attributes into vertexplus and faceplus. A local attribute is everything (N(), C(), Q()....) except pointers to other simplices (i.e. FFAdj, VFAdj, VertexRef) which are set to NULL. Added some function for const attributes Revision 1.11 2007/12/11 18:25:31 cignoni added missing include limits Revision 1.10 2007/12/11 11:36:03 cignoni Added the CompactVertexVector garbage collecting function. Revision 1.9 2006/12/11 23:42:00 ganovelli bug Index()() instead of Index() Revision 1.8 2006/12/04 11:17:42 ganovelli added forward declaration of TriMesh Revision 1.7 2006/11/07 17:22:52 cignoni many gcc compiling issues Revision 1.6 2006/11/07 15:13:57 zifnab1974 Necessary changes for compilation with gcc 3.4.6. Especially the hash function is a problem Revision 1.5 2006/11/07 11:29:24 cignoni Corrected some errors in the reflections Has*** functions Revision 1.4 2006/10/31 16:02:59 ganovelli vesione 2005 compliant Revision 1.3 2006/02/28 11:59:55 ponchio g++ compliance: begin() -> (*this).begin() and for end(), size(), Base(), Index() Revision 1.2 2005/12/12 11:17:32 cignoni Corrected update function, now only the needed simplexes should be updated. Revision 1.1 2005/10/14 15:07:59 cignoni First Really Working version ****************************************************************************/ /* Note OCF = Optional Component Fast (hopefully) compare with OCC(Optional Component Compact) Mainly the trick here is to store a base pointer in each simplex... ****************************************************************************/ #ifndef __VCG_VERTEX_PLUS_COMPONENT_OCF #define __VCG_VERTEX_PLUS_COMPONENT_OCF #include #include #include namespace vcg { namespace vert { /* All the Components that can be added to a vertex should be defined in the namespace vert: */ template class vector_ocf: public std::vector { typedef std::vector BaseType; typedef typename vector_ocf::iterator ThisTypeIterator; public: vector_ocf():std::vector(){ QualityEnabled=false; ColorEnabled=false; MarkEnabled = false; NormalEnabled=false; VFAdjacencyEnabled=false; CurvatureEnabled = false; } // override di tutte le funzioni che possono spostare // l'allocazione in memoria del container void push_back(const VALUE_TYPE & v) { BaseType::push_back(v); BaseType::back()._ovp = this; if (ColorEnabled) CV.push_back(vcg::Color4b(vcg::Color4b::White)); if (MarkEnabled) MV.push_back(0); if (NormalEnabled) NV.push_back(typename VALUE_TYPE::NormalType()); if (VFAdjacencyEnabled) AV.push_back(VFAdjType()); } void pop_back(); void resize(const unsigned int & _size) { int oldsize = BaseType::size(); BaseType::resize(_size); if(oldsize<_size){ ThisTypeIterator firstnew = BaseType::begin(); advance(firstnew,oldsize); _updateOVP(firstnew,(*this).end()); } if (ColorEnabled) CV.resize(_size); if (MarkEnabled) MV.resize(_size); if (NormalEnabled) NV.resize(_size); if (VFAdjacencyEnabled) AV.resize(_size); } void reserve(const unsigned int & _size) { BaseType::reserve(_size); if (ColorEnabled) CV.reserve(_size); if (MarkEnabled) MV.reserve(_size); if (NormalEnabled) NV.reserve(_size); if (VFAdjacencyEnabled) AV.reserve(_size); } void _updateOVP(ThisTypeIterator lbegin, ThisTypeIterator lend) { ThisTypeIterator vi; for(vi=lbegin;vi!=lend;++vi) (*vi)._ovp=this; } // this function is called by the specialized Reorder function, that is called whenever someone call the allocator::CompactVertVector void ReorderVert(std::vector &newVertIndex ) { size_t pos=0; size_t i=0; if (ColorEnabled) assert( CV.size() == newVertIndex.size() ); if (MarkEnabled) assert( MV.size() == newVertIndex.size() ); if (NormalEnabled) assert( NV.size() == newVertIndex.size() ); if (VFAdjacencyEnabled) assert( AV.size() == newVertIndex.size() ); for(i=0;i::max() ) { assert(newVertIndex[i] <= i); if (ColorEnabled) CV[newVertIndex[i]] = CV[i]; if (MarkEnabled) MV[newVertIndex[i]] = MV[i]; if (NormalEnabled) NV[newVertIndex[i]] = NV[i]; if (VFAdjacencyEnabled) AV[newVertIndex[i]] = AV[i]; } } if (ColorEnabled) CV.resize(BaseType::size()); if (MarkEnabled) MV.resize(BaseType::size()); if (NormalEnabled) NV.resize(BaseType::size()); if (VFAdjacencyEnabled) AV.resize(BaseType::size()); } //////////////////////////////////////// // Enabling Eunctions bool IsQualityEnabled() const {return QualityEnabled;} void EnableQuality() { assert(VALUE_TYPE::HasQualityOcf()); QualityEnabled=true; QV.resize((*this).size()); } void DisableQuality() { assert(VALUE_TYPE::HasQualityOcf()); QualityEnabled=false; QV.clear(); } bool IsColorEnabled() const {return ColorEnabled;} void EnableColor() { assert(VALUE_TYPE::HasColorOcf()); ColorEnabled=true; CV.resize((*this).size()); } void DisableColor() { assert(VALUE_TYPE::HasColorOcf()); ColorEnabled=false; CV.clear(); } bool IsMarkEnabled() const {return MarkEnabled;} void EnableMark() { assert(VALUE_TYPE::HasFaceMarkOcf()); MarkEnabled=true; MV.resize((*this).size()); } void DisableMark() { assert(VALUE_TYPE::HasFaceMarkOcf()); MarkEnabled=false; MV.clear(); } bool IsNormalEnabled() const {return NormalEnabled;} void EnableNormal() { assert(VALUE_TYPE::HasNormalOcf()); NormalEnabled=true; NV.resize((*this).size()); } void DisableNormal() { assert(VALUE_TYPE::HasNormalOcf()); NormalEnabled=false; NV.clear(); } void EnableVFAdjacency() { assert(VALUE_TYPE::HasVFAdjacencyOcf()); VFAdjacencyEnabled=true; AV.resize((*this).size()); } void DisableVFAdjacency() { assert(VALUE_TYPE::HasVFAdjacencyOcf()); VFAdjacencyEnabled=false; AV.clear(); } void EnableCurvature() { assert(VALUE_TYPE::HasCurvatureOcf()); CurvatureEnabled=true; CuV.resize((*this).size()); } void DisableCurvature() { assert(VALUE_TYPE::HasCurvatureOcf()); CurvatureEnabled=false; CuV.clear(); } void EnableCurvatureDir() { assert(VALUE_TYPE::HasCurvatureDirOcf()); CurvatureDirEnabled=true; CuDV.resize((*this).size()); } void DisableCurvatureDir() { assert(VALUE_TYPE::HasCurvatureDirOcf()); CurvatureDirEnabled=false; CuDV.clear(); } struct VFAdjType { typename VALUE_TYPE::FacePointer _fp ; int _zp ; }; public: std::vector QV; std::vector CuV; std::vector CuDV; std::vector CV; std::vector NV; std::vector AV; std::vector MV; bool QualityEnabled; bool ColorEnabled; bool NormalEnabled; bool VFAdjacencyEnabled; bool CurvatureEnabled; bool CurvatureDirEnabled; bool MarkEnabled; }; //template<> void EnableAttribute(){ NormalEnabled=true;} /*------------------------- COORD -----------------------------------------*/ /*----------------------------- VFADJ ------------------------------*/ template class VFAdjOcf: public T { public: typename T::FacePointer &VFp() { assert((*this).Base().VFAdjacencyEnabled); return (*this).Base().AV[(*this).Index()]._fp; } typename T::FacePointer cVFp() const { if(! (*this).Base().VFAdjacencyEnabled ) return 0; else return (*this).Base().AV[(*this).Index()]._fp; } int &VFi() { assert((*this).Base().VFAdjacencyEnabled); return (*this).Base().AV[(*this).Index()]._zp; } template void ImportLocal(const LeftV & leftV){VFp() = NULL; VFi() = -1; T::ImporLocal(leftV);} static bool HasVFAdjacency() { return true; } static bool HasVFAdjacencyOcf() {assert(!T::HasVFAdjacencyOcf()); return true; } private: }; /*------------------------- Normal -----------------------------------------*/ template class NormalOcf: public T { public: typedef A NormalType; static bool HasNormal() { return true; } static bool HasNormalOcf() { return true; } NormalType &N() { // you cannot use Normals before enabling them with: yourmesh.vert.EnableNormal() assert((*this).Base().NormalEnabled); return (*this).Base().NV[(*this).Index()]; } const NormalType &N() const { // you cannot use Normals before enabling them with: yourmesh.vert.EnableNormal() assert((*this).Base().NormalEnabled); return (*this).Base().NV[(*this).Index()]; } template void ImportLocal(const LeftV & leftV){ N() = leftV.cN(); T::ImporLocal(leftV);} }; template class Normal3sOcf: public NormalOcf {}; template class Normal3fOcf: public NormalOcf {}; template class Normal3dOcf: public NormalOcf {}; ///*-------------------------- COLOR ----------------------------------*/ template class ColorOcf: public T { public: typedef A ColorType; ColorType &C() { assert((*this).Base().NormalEnabled); return (*this).Base().CV[(*this).Index()]; } const ColorType &cC() const { assert((*this).Base().NormalEnabled); return (*this).Base().CV[(*this).Index()]; } template void ImportLocal(const LeftV & leftV){ C() = leftV.cC(); T::ImporLocal(leftV);} static bool HasColor() { return true; } static bool HasColorOcf() { assert(!T::HasColorOcf()); return true; } }; template class Color4bOcf: public ColorOcf {}; ///*-------------------------- QUALITY ----------------------------------*/ template class QualityOcf: public T { public: typedef A QualityType; QualityType &Q() { assert((*this).Base().QualityEnabled); return (*this).Base().QV[(*this).Index()]; } template void ImportLocal(const LeftV & leftV){ Q() = leftV.cQ(); T::ImporLocal(leftV);} static bool HasQuality() { return true; } static bool HasQualityOcf() { assert(!T::HasQualityOcf()); return true; } }; template class QualityfOcf: public QualityOcf {}; ///*-------------------------- MARK ----------------------------------*/ template class MarkOcf: public T { public: inline int & IMark() { assert((*this).Base().MarkEnabled); return (*this).Base().MV[(*this).Index()]; } inline int IMark() const { assert((*this).Base().MarkEnabled); return (*this).Base().MV[(*this).Index()]; } ; template void ImportLocal(const LeftF & leftF){IMark() = leftF.cIMark(); T::ImportLocal(leftF);} static bool HasFaceMark() { return true; } static bool HasFaceMarkOcf() { return true; } inline void InitIMark() { IMark() = 0; } }; ///*-------------------------- CURVATURE ----------------------------------*/ template class CurvatureOcf: public TT { public: typedef Point2 CurvatureType; typedef typename CurvatureType::ScalarType ScalarType; ScalarType &Kh(){ assert((*this).Base().CurvatureEnabled); return (*this).Base().CuV[(*this).Index()][0];} ScalarType &Kg(){ assert((*this).Base().CurvatureEnabled); return (*this).Base().CuV[(*this).Index()][1];} const ScalarType &cKh() const { assert((*this).Base().CurvatureEnabled); return (*this).Base().CuV[(*this).Index()][0];} const ScalarType &cKg() const { assert((*this).Base().CurvatureEnabled); return (*this).Base().CuV[(*this).Index()][1];} template void ImportLocal(const LeftV & leftV){ (*this).Base().CuV[(*this).Index()][0] = leftV.cKh(); (*this).Base().CuV[(*this).Index()][1] = leftV.cKg(); TT::ImporLocal(leftV);} static bool HasCurvatureOcf() { return true; } static void Name(std::vector & name){name.push_back(std::string("CurvatureOcf"));TT::Name(name);} private: }; template class CurvaturefOcf: public CurvatureOcf {}; template class CurvaturedOcf: public CurvatureOcf {}; ///*-------------------------- CURVATURE DIR ----------------------------------*/ template struct CurvatureDirTypeOcf{ typedef Point3 VecType; typedef S ScalarType; CurvatureDirTypeOcf () {} Point3max_dir,min_dir; S k1,k2; }; template class CurvatureDirOcf: public TT { public: typedef A CurvatureDirType; typedef typename CurvatureDirType::VecType VecType; typedef typename CurvatureDirType::ScalarType ScalarType; VecType &PD1(){ assert((*this).Base().CurvatureDirEnabled); return (*this).Base().CuDV[(*this).Index()].max_dir;} VecType &PD2(){ assert((*this).Base().CurvatureDirEnabled); return (*this).Base().CuDV[(*this).Index()].max_dir;} const VecType &cPD1() const {assert((*this).Base().CurvatureDirEnabled); return (*this).Base().CuV[(*this).Index()].max_dir;} const VecType &cPD2() const {assert((*this).Base().CurvatureDirEnabled); return (*this).Base().CuV[(*this).Index()].max_dir;} ScalarType &K1(){ assert((*this).Base().CurvatureDirEnabled); return (*this).Base().CuDV[(*this).Index()].k1;} ScalarType &K2(){ assert((*this).Base().CurvatureDirEnabled); return (*this).Base().CuDV[(*this).Index()].k2;} const ScalarType &cK1() const {assert((*this).Base().CurvatureDirEnabled); return (*this).Base().CuDV[(*this).Index()].k1;} const ScalarType &cK2()const {assert((*this).Base().CurvatureDirEnabled); return (*this).Base().CuDV[(*this).Index()].k2;} static bool HasCurvatureDirOcf() { return true; } static void Name(std::vector & name){name.push_back(std::string("CurvatureDirOcf"));TT::Name(name);} private: CurvatureDirType _curv; }; template class CurvatureDirfOcf: public CurvatureDirOcf, T> { public: static void Name(std::vector & name){name.push_back(std::string("CurvatureDirfOcf"));T::Name(name);} }; template class CurvatureDirdOcf: public CurvatureDirOcf, T> { public: static void Name(std::vector & name){name.push_back(std::string("CurvatureDirdOcf"));T::Name(name);} }; ///*-------------------------- InfoOpt ----------------------------------*/ template < class T> class InfoOcf: public T { public: vector_ocf &Base() const { return *_ovp;} inline int Index() const { typename T::VertType const *tp=static_cast(this); int tt2=tp- &*(_ovp->begin()); return tt2; } public: vector_ocf *_ovp; static bool HasQualityOcf() { return false; } static bool HasVFAdjacencyOcf() { return false; } }; } // end namespace vert namespace tri { template < class, class > class TriMesh; template < class VertexType, class FaceContainerType > bool HasPerVertexQuality (const TriMesh < vert::vector_ocf< VertexType > , FaceContainerType > & m) { if(VertexType::HasQualityOcf()) return m.vert.IsQualityEnabled(); else return VertexType::HasQuality(); } template < class VertexType > void ReorderVert( std::vector &newVertIndex, vert::vector_ocf< VertexType > &vertVec) { vertVec.ReorderVert(newVertIndex); } } }// end namespace vcg #endif qutemol/vcg/vcg/simplex/vertexplus/component_occ.h0000444000175000017500000002431410767454142021077 0ustar mbamba/**************************************************************************** * VCGLib o o * * Visual and Computer Graphics Library o o * * _ O _ * * Copyright(C) 2004 \/)\/ * * Visual Computing Lab /\/| * * ISTI - Italian National Research Council | * * \ * * All rights reserved. * * * * 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. * * * * 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 (http://www.gnu.org/licenses/gpl.txt) * * for more details. * * * ****************************************************************************/ /**************************************************************************** History $Log: component_occ.h,v $ Revision 1.3 2008/03/17 11:39:14 ganovelli added curvature and curvatruredir (compiled .net 2005 and gcc) Revision 1.2 2007/03/12 15:37:21 tarini Texture coord name change! "TCoord" and "Texture" are BAD. "TexCoord" is GOOD. Revision 1.1 2005/10/15 16:24:10 ganovelli Working release (compilata solo su MSVC), component_occ � migrato da component_opt ****************************************************************************/ #ifndef __VCG_VERTEX_PLUS_COMPONENT_OCC #define __VCG_VERTEX_PLUS_COMPONENT_OCC #include #include namespace vcg { namespace vert { /* Some naming Rules All the Components that can be added to a vertex should be defined in the namespace vert: */ /*------------------------- COORD -----------------------------------------*/ template class CoordOcc: public T { public: typedef A CoordType; typedef typename CoordType::ScalarType ScalarType; typedef typename T::VertType VertType; CoordType &P() { return CAT< vector_occ,CoordType>::Instance()->Get((VertType*)this); } CoordType &UberP() { return CAT< vector_occ,CoordType>::Instance()->Get((VertType*)this); } }; template class Coord3fOcc: public CoordOcc {}; template class Coord3dOcc: public CoordOcc {}; /*-------------------------- NORMAL ----------------------------------------*/ template class NormalOcc: public T { public: typedef A NormalType; typedef typename T::VertType VertType; NormalType &N() {return CAT< vector_occ,NormalType>::Instance()->Get((VertType*)this); } /*private: NormalType _norm; */ }; template class Normal3sOcc: public NormalOcc {}; template class Normal3fOcc: public NormalOcc {}; template class Normal3dOcc: public NormalOcc {}; /*-------------------------- TEXCOORD ----------------------------------------*/ template class TexCoordOcc: public TT { public: typedef A TexCoordType; typedef typename TT::VertType VertType; TexCoordType &T() {return CAT< vector_occ,TexCoordType>::Instance()->Get((VertType*)this); } static bool HasTexCoord() { return true; } static bool HasTexCoordOcc() { return true; } /* private: TexCoordType _t; */ }; template class TexCoord2sOcc: public TexCoordOcc, T> {}; template class TexCoord2fOcc: public TexCoordOcc, T> {}; template class TexCoord2dOcc: public TexCoordOcc, T> {}; ///*------------------------- FLAGS -----------------------------------------*/ template class FlagOcc: public T { public: typedef typename T::VertType VertType; int &Flags() {return CAT< vector_occ,int>::Instance()->Get((VertType*)this); } const int Flags() const {return CAT< vector_occ,int>::Instance()->Get((VertType*)this); } static bool HasFlags() {return true;} static bool HasFlagsOcc() {return true;} }; ///*-------------------------- COLOR ----------------------------------*/ template class ColorOcc: public T { public: typedef A ColorType; typedef typename T::VertType VertType; ColorType &C() { return CAT< vector_occ,ColorType>::Instance()->Get((VertType*)this); } static bool HasColor() { return true; } /*private: ColorType _color; */ }; template class Color4bOcc: public ColorOcc {}; ///*-------------------------- Quality ----------------------------------*/ template class QualityOcc: public T { public: typedef A QualityType; typedef typename T::VertType VertType; QualityType &Q() { return CAT< vector_occ,QualityType>::Instance()->Get((VertType*)this);} static bool HasQuality() { return true; } /*private: QualityType _quality; */ }; template class QualitysOcc: public QualityOcc {}; template class QualityfOcc: public QualityOcc {}; template class QualitydOcc: public QualityOcc {}; // ///*-------------------------- Curvature ----------------------------------*/ template class CurvatureOcc: public TT { public: typedef Point2 CurvatureTypeOcc; typedef typename TT::VertType VertType; typedef typename CurvatureTypeOcc::ScalarType ScalarType; ScalarType &H(){ return CAT< vector_occ,CurvatureTypeOcc>::Instance()->Get((VertType*)this)[0];} ScalarType &K(){ return CAT< vector_occ,CurvatureTypeOcc>::Instance()->Get((VertType*)this)[1];} const ScalarType &cH() const { return CAT< vector_occ,CurvatureTypeOcc>::Instance()->Get((VertType*)this)[0];} const ScalarType &cK() const { return CAT< vector_occ,CurvatureTypeOcc>::Instance()->Get((VertType*)this)[1];} template void ImportLocal(const LeftV & leftV){ CAT< vector_occ,CurvatureTypeOcc>::Instance()->Get((VertType*)this)[0] = leftV.cH(); CAT< vector_occ,CurvatureTypeOcc>::Instance()->Get((VertType*)this)[1] = leftV.cK(); TT::ImporLocal(leftV); } static bool HasCurvature() { return true; } static bool HasCurvatureOcc() { return true; } static void Name(std::vector & name){name.push_back(std::string("CurvatureOcc"));TT::Name(name);} private: }; template class CurvaturefOcc: public CurvatureOcc { static void Name(std::vector & name){name.push_back(std::string("CurvaturefOcc"));T::Name(name);} }; template class CurvaturedOcc: public CurvatureOcc { static void Name(std::vector & name){name.push_back(std::string("CurvaturedOcc"));T::Name(name);} }; /*-------------------------- Curvature Direction ----------------------------------*/ template struct CurvatureDirTypeOcc{ typedef Point3 VecType; typedef S ScalarType; CurvatureDirTypeOcc () {} Point3max_dir,min_dir; // max and min curvature direction S k1,k2;// max and min curvature values }; template class CurvatureDirOcc: public TT { public: typedef A CurvatureDirTypeOcc; typedef typename CurvatureDirTypeOcc::VecType VecType; typedef typename CurvatureDirTypeOcc::ScalarType ScalarType; typedef typename TT::VertType VertType; VecType &PD1(){ return CAT< vector_occ,CurvatureDirTypeOcc>::Instance()->Get((VertType*)this).max_dir;} VecType &PD2(){ return CAT< vector_occ,CurvatureDirTypeOcc>::Instance()->Get((VertType*)this).min_dir;} const VecType &cPD1() const {return CAT< vector_occ,CurvatureDirTypeOcc>::Instance()->Get((VertType*)this).max_dir;} const VecType &cPD2() const {return CAT< vector_occ,CurvatureDirTypeOcc>::Instance()->Get((VertType*)this).min_dir;} ScalarType &K1(){ return CAT< vector_occ,CurvatureDirTypeOcc>::Instance()->Get((VertType*)this).k1;} ScalarType &K2(){ return CAT< vector_occ,CurvatureDirTypeOcc>::Instance()->Get((VertType*)this).k2;} const ScalarType &cK1() const {return CAT< vector_occ,CurvatureDirTypeOcc>::Instance()->Get((VertType*)this).k1;} const ScalarType &cK2()const {return CAT< vector_occ,CurvatureDirTypeOcc>::Instance()->Get((VertType*)this).k2;} static bool HasCurvatureDir() { return true; } static bool HasCurvatureDirOcc() { return true; } static void Name(std::vector & name){name.push_back(std::string("CurvatureDir"));TT::Name(name);} }; template class CurvatureDirfOcc: public CurvatureDirOcc, T> { public: static void Name(std::vector & name){name.push_back(std::string("CurvatureDirf"));T::Name(name);} }; template class CurvatureDirdOcc: public CurvatureDirOcc, T> { public: static void Name(std::vector & name){name.push_back(std::string("CurvatureDird"));T::Name(name);} }; ///*----------------------------- VFADJ ------------------------------*/ template class VFAdjOcc: public T { public: typedef typename T::VertType VertType; typedef typename T::FacePointer FacePointer; FacePointer &Fp() {return CAT< vector_occ,FacePointer>::Instance()->Get((VertType*)this); } int &Zp() {return _zp; } static bool HasVFAdjacency() { return true; } private: typename T::FacePointer _fp ; int _zp ; }; } // end namespace vert }// end namespace vcg #endif qutemol/vcg/vcg/simplex/vertexplus/base.h0000444000175000017500000004004310775260771017162 0ustar mbamba/**************************************************************************** * VCGLib o o * * Visual and Computer Graphics Library o o * * _ O _ * * Copyright(C) 2004 \/)\/ * * Visual Computing Lab /\/| * * ISTI - Italian National Research Council | * * \ * * All rights reserved. * * * * 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. * * * * 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 (http://www.gnu.org/licenses/gpl.txt) * * for more details. * * * ****************************************************************************/ /**************************************************************************** History $Log: base.h,v $ Revision 1.13 2008/04/03 23:02:17 cignoni Increased the derivation chain lenght. God save the compiler patience! Revision 1.12 2008/03/17 11:39:14 ganovelli added curvature and curvatruredir (compiled .net 2005 and gcc) Revision 1.11 2008/02/04 21:26:49 ganovelli added ImportLocal which imports all local attributes into vertexplus and faceplus. A local attribute is everything (N(), C(), Q()....) except pointers to other simplices (i.e. FFAdj, VFAdj, VertexRef) which are set to NULL. Added some function for const attributes Revision 1.10 2007/03/12 15:37:21 tarini Texture coord name change! "TCoord" and "Texture" are BAD. "TexCoord" is GOOD. Revision 1.9 2007/02/12 19:00:56 ganovelli added Name(std:vector& n) that fills n with the names of the attribute of the vertex type Revision 1.8 2006/09/28 17:34:11 cignoni Added Missing GetBBox function Revision 1.7 2006/02/27 17:42:43 ponchio Added some documentation. Revision 1.6 2005/12/05 15:58:10 cignoni Removed spurious definition of flags in Aritymax that was overriding the correct definition in EmplyBitFlags and BitFlags classes Revision 1.5 2005/12/02 00:44:41 cignoni Reformatted and compacted flags code. Revision 1.4 2005/11/16 22:59:35 cignoni Standardized name of flags. It is plural becouse each simplex has many flag. Revision 1.3 2005/11/12 18:36:51 cignoni Added 'Visited' flag functions Revision 1.2 2004/04/03 13:33:55 cignoni Missing include Revision 1.1 2004/03/29 08:36:26 cignoni First working version! ****************************************************************************/ #ifndef __VCG_VERTEX_PLUS #define __VCG_VERTEX_PLUS #include #include #include #include namespace vcg { class DumET {}; class DumFT {}; class DumTT {}; /*------------------------------------------------------------------*/ /* The base class of all the recusive definition chain. It is just a container of the typenames of the various simplexes. These typenames must be known form all the derived classes. */ template class VertexTypeHolder{ public: typedef BVT VertType; typedef BET EdgeType; typedef BFT FaceType; typedef BTT TetraType; typedef BVT *VertPointer; typedef BET *EdgePointer; typedef BFT *FacePointer; typedef BTT *TetraPointer; template < class LeftV> void ImportLocal(const LeftV & left ) { } static void Name(std::vector & name){} }; /* The base class form which we start to add our components. it has the empty definition for all the standard members (coords, color flags) Note: in order to avoid both virtual classes and ambiguous definitions all the subsequent overrides must be done in a sequence of derivation. In other words we cannot derive and add in a single derivation step (with multiple ancestor), both the real (non-empty) normal and color but we have to build the type a step a time (deriving from a single ancestor at a time). */ template class VertexBase: public vert::EmptyTexCoord< vert::EmptyVFAdj< vert::EmptyColorQuality< vert::EmptyBitFlags< vert::EmptyCoordNormal< vert::EmptyCurvature< vert::EmptyCurvatureDir< VertexTypeHolder > > > > > > >{ }; // Metaprogramming Core template class A> class VertexArity1: public A > { }; template class A, template class B> class VertexArity2: public B > {}; template class A, template class B, template class C > class VertexArity3: public C > {}; template class A, template class B, template class C, template class D> class VertexArity4: public D > {}; template class A, template class B, template class C, template class D, template class E > class VertexArity5: public E > {}; template class A, template class B, template class C, template class D, template class E, template class F > class VertexArity6: public F > {}; template class A, template class B, template class C, template class D, template class E, template class F, template class G> class VertexArity7: public G > {}; template class A, template class B, template class C, template class D, template class E, template class F, template class G, template class H> class VertexArity8: public H > {}; template class A, template class B, template class C, template class D, template class E, template class F, template class G, template class H, template class I> class VertexArity9: public I > {}; template class A, template class B, template class C, template class D, template class E, template class F, template class G, template class H, template class I, template class J> class VertexArity10: public J > {}; /* The Real Big Vertex class; The class __VertexArityMax__ is the one that is the Last to be derived, and therefore is the only one to know the real members (after the many overrides) so all the functions with common behaviour using the members defined in the various Empty/nonEmpty component classes MUST be defined here. I.e. IsD() that uses the overridden Flags() member must be defined here. */ template class A, template class B, template class C, template class D, template class E, template class F, template class G, template class H, template class I, template class J, template class K> class VertexArityMax: public K > { // ----- Flags stuff ----- public: enum { DELETED = 0x0001, // This bit indicate that the vertex is deleted from the mesh NOTREAD = 0x0002, // This bit indicate that the vertex of the mesh is not readable NOTWRITE = 0x0004, // This bit indicate that the vertex is not modifiable MODIFIED = 0x0008, // This bit indicate that the vertex is modified VISITED = 0x0010, // This bit can be used to mark the visited vertex SELECTED = 0x0020, // This bit can be used to select BORDER = 0x0100, // Border Flag USER0 = 0x0200 // First user bit }; inline int & UberFlags () { return this->Flags(); } inline const int UberFlags() const { return this->Flags(); } bool IsD() const {return (this->Flags() & DELETED) != 0;} /// checks if the vertex is deleted bool IsR() const {return (this->Flags() & NOTREAD) == 0;} /// checks if the vertex is readable bool IsW() const {return (this->Flags() & NOTWRITE)== 0;}/// checks if the vertex is modifiable bool IsRW() const {return (this->Flags() & (NOTREAD | NOTWRITE)) == 0;}/// This funcion checks whether the vertex is both readable and modifiable bool IsS() const {return (this->Flags() & SELECTED) != 0;}/// checks if the vertex is Selected bool IsB() const {return (this->Flags() & BORDER) != 0;}/// checks if the vertex is a border one bool IsV() const {return (this->Flags() & VISITED) != 0;}/// checks if the vertex Has been visited /** Set the flag value @param flagp Valore da inserire nel flag */ void SetFlags(int flagp) {this->Flags()=flagp;} /** Set the flag value @param flagp Valore da inserire nel flag */ void ClearFlags() {this->Flags()=0;} void SetD() {this->Flags() |=DELETED;}/// deletes the vertex from the mesh void ClearD() {this->Flags() &=(~DELETED);}/// un-delete a vertex void SetR() {this->Flags() &=(~NOTREAD);}/// marks the vertex as readable void ClearR() {this->Flags() |=NOTREAD;}/// marks the vertex as not readable void ClearW() {this->Flags() |=NOTWRITE;}/// marks the vertex as writable void SetW() {this->Flags() &=(~NOTWRITE);}/// marks the vertex as not writable void SetS() {this->Flags() |=SELECTED;}/// select the vertex void ClearS() {this->Flags() &= ~SELECTED;}/// Un-select a vertex void SetB() {this->Flags() |=BORDER;} void ClearB() {this->Flags() &=~BORDER;} void SetV() {this->Flags() |=VISITED;} void ClearV() {this->Flags() &=~VISITED;} /// Return the first bit that is not still used static int &LastBitFlag() { static int b =USER0; return b; } /// allocate a bit among the flags that can be used by user. static inline int NewBitFlag() { LastBitFlag()=LastBitFlag()<<1; return LastBitFlag(); } // de-allocate a bit among the flags that can be used by user. static inline bool DeleteBitFlag(int bitval) { if(LastBitFlag()==bitval) { LastBitFlag()= LastBitFlag()>>1; return true; } assert(0); return false; } /// This function checks if the given user bit is true bool IsUserBit(int userBit){return (this->Flags() & userBit) != 0;} /// This function set the given user bit void SetUserBit(int userBit){this->Flags() |=userBit;} /// This function clear the given user bit void ClearUserBit(int userBit){this->Flags() &= (~userBit);} template void GetBBox( BoxType & bb ) const { bb.Set(this->P()); } }; template < typename T=int> class DefaultDeriver : public T {}; /* These are the three main classes that are used by the library user to define its own vertexes. The user MUST specify the names of all the type involved in a generic complex. so for example when defining a vertex of a trimesh you must know the name of the type of the edge and of the face. Typical usage example: A vertex with coords, flags and normal for use in a standard trimesh: class VertexNf : public VertexSimp2< VertexNf, EdgeProto, FaceProto, vert::Coord3d, vert::Flag, vert::Normal3f > {}; A vertex with coords, and normal for use in a tetrahedral mesh AND in a standard trimesh: class TetraVertex : public VertexSimp3< TetraVertex, EdgeProto, FaceProto, TetraProto, vert::Coord3d, vert::Normal3f > {}; A summary of the available vertex attributes (see component.h for more details): Coord3f, Coord3d, Normal3s, Normal3f, Normal3d Mark //a int component (incremental mark) BitFlags TexCoord2s, TexCoord2f, TexCoord2d Color4b Qualitys, Qualityf, Qualityd VFAdj //topology (vertex->face adjacency) */ template class A = DefaultDeriver, template class B = DefaultDeriver, template class C = DefaultDeriver, template class D = DefaultDeriver, template class E = DefaultDeriver, template class F = DefaultDeriver, template class G = DefaultDeriver, template class H = DefaultDeriver, template class I = DefaultDeriver, template class J = DefaultDeriver, template class K = DefaultDeriver> class VertexSimp3: public VertexArityMax {}; template class A = DefaultDeriver, template class B = DefaultDeriver, template class C = DefaultDeriver, template class D = DefaultDeriver, template class E = DefaultDeriver, template class F = DefaultDeriver, template class G = DefaultDeriver, template class H = DefaultDeriver, template class I = DefaultDeriver, template class J = DefaultDeriver, template class K = DefaultDeriver> class VertexSimp2: public VertexArityMax {}; template class A = DefaultDeriver, template class B = DefaultDeriver, template class C = DefaultDeriver, template class D = DefaultDeriver, template class E = DefaultDeriver, template class F = DefaultDeriver, template class G = DefaultDeriver, template class H = DefaultDeriver, template class I = DefaultDeriver, template class J = DefaultDeriver, template class K = DefaultDeriver> class VertexSimp1: public VertexArityMax {}; }// end namespace #endif qutemol/vcg/vcg/simplex/vertexplus/with/0000755000175000017500000000000011633404241017035 5ustar mbambaqutemol/vcg/vcg/simplex/vertexplus/with/afvn.h0000444000175000017500000000076310321511124020134 0ustar mbamba#ifndef __VCGLIB_VERTEXPLUS_AFVN_TYPE #define __VCGLIB_VERTEXPLUS_AFVN_TYPE namespace vcg { template class VertexAFVNd : public VertexSimp2< VertexAFVNd, EdgeTemplate, FaceTemplate, vert::Normal3d, vert::VFAdj, vert::Flag, vert::Coord3d> {}; template class VertexAFVNf : public VertexSimp2< VertexAFVNf, EdgeTemplate, FaceTemplate, vert::Normal3f, vert::VFAdj, vert::Flag, vert::Coord3f> {}; } #endif qutemol/vcg/vcg/simplex/vertexplus/with/afvcvnvq.h0000444000175000017500000000072110321511124021026 0ustar mbamba#ifndef __VCGLIB_VERTEXPLUS_AFVCVNVQ_TYPE #define __VCGLIB_VERTEXPLUS_AFVCVNVQ_TYPE namespace vcg { template class VertexAFVCVNVQd : public VertexSimp2< VertexAFVCVNVQd, DumET, FaceTemplate, vert::Normal3d, vert::VFAdj, vert::Flag, vert::Coord3d> {}; template class VertexAFVCVNVQf : public VertexSimp2< VertexAFVCVNVQf, DumET, FaceTemplate, vert::Normal3f, vert::VFAdj, vert::Flag, vert::Coord3f> {}; } #endif qutemol/vcg/vcg/simplex/vertexplus/with/vcvn.h0000444000175000017500000000071410321511124020152 0ustar mbamba#ifndef __VCGLIB_VERTEXPLUS_VCVN_TYPE #define __VCGLIB_VERTEXPLUS_VCVN_TYPE namespace vcg { template class VertexVCVNf : public VertexSimp1< VertexVCVNf, DumET, vert::Normal3f, vert::Color4b, vert::Flag, vert::Coord3f> {}; template class VertexVCVNd : public VertexSimp1< VertexVCVNd, DumET, vert::Normal3d, vert::Color4b, vert::Flag, vert::Coord3d> {}; } #endif qutemol/vcg/vcg/simplex/vertexplus/with/readme.txt0000444000175000017500000000444510321511040021025 0ustar mbamba/**************************************************************************** * VCGLib o o * * Visual and Computer Graphics Library o o * * _ O _ * * Copyright(C) 2004 \/)\/ * * Visual Computing Lab /\/| * * ISTI - Italian National Research Council | * * \ * * All rights reserved. * * * * 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. * * * * 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 (http://www.gnu.org/licenses/gpl.txt) * * for more details. * * * ****************************************************************************/ This folders contains most common VERTEX configuration files. The name of the file specifies the members that are added to the vertex class. The name is a sequence of letter pairs, in strict alphabetical order. The possible admitted letters pairs are: Adjacency Info AF - Vertex-Face adjacency AE - Vertex-Edge adjacency AT - Vertex-Tetra adjacency Per-Vertex Data VC - Color VN - Normal VM - Incremental Mark VQ - Quality VT - Texture Coords E.g. #include generate a type VertexAFVCVQ That can store V-F adjacency, color, normal and quality. qutemol/vcg/vcg/simplex/vertexplus/with/vn.h0000444000175000017500000000075310321511124017624 0ustar mbamba#ifndef __VCGLIB_VERTEXPLUS_VN_TYPE #define __VCGLIB_VERTEXPLUS_VN_TYPE namespace vcg { template class VertexVNf : public VertexSimp2< VertexVNf, EdgeTemplate, FaceTemplate, vert::Normal3f, vert::Color4b, vert::Flag, vert::Coord3f> {}; template class VertexVNd : public VertexSimp2< VertexVNd, EdgeTemplate, FaceTemplate, vert::Normal3d, vert::Color4b, vert::Flag, vert::Coord3d> {}; } #endif qutemol/vcg/vcg/simplex/vertexplus/component.h0000444000175000017500000005113610775401103020241 0ustar mbamba/**************************************************************************** * VCGLib o o * * Visual and Computer Graphics Library o o * * _ O _ * * Copyright(C) 2004 \/)\/ * * Visual Computing Lab /\/| * * ISTI - Italian National Research Council | * * \ * * All rights reserved. * * * * 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. * * * * 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 (http://www.gnu.org/licenses/gpl.txt) * * for more details. * * * ****************************************************************************/ /**************************************************************************** History $Log: component.h,v $ Revision 1.28 2008/04/04 10:26:11 cignoni Cleaned up names, now Kg() gives back Gaussian Curvature (k1*k2), while Kh() gives back Mean Curvature 1/2(k1+k2) Revision 1.27 2008/04/03 23:12:28 cignoni compacted two pair of empty components to shorten derivation chains Revision 1.26 2008/03/17 11:39:14 ganovelli added curvature and curvatruredir (compiled .net 2005 and gcc) Revision 1.25 2008/02/05 10:11:34 cignoni A small typo (a T:: instead of TT::) Revision 1.24 2008/02/04 21:26:49 ganovelli added ImportLocal which imports all local attributes into vertexplus and faceplus. A local attribute is everything (N(), C(), Q()....) except pointers to other simplices (i.e. FFAdj, VFAdj, VertexRef) which are set to NULL. Added some function for const attributes Revision 1.23 2007/06/04 15:40:22 turini Add vertex-tetrahedron adjacency component VTAdj. Revision 1.22 2007/03/12 15:37:21 tarini Texture coord name change! "TCoord" and "Texture" are BAD. "TexCoord" is GOOD. Revision 1.21 2007/02/18 07:41:32 cignoni Corrected small syntax errors detected by gcc Revision 1.20 2007/02/12 19:00:56 ganovelli added Name(std:vector& n) that fills n with the names of the attribute of the vertex type Revision 1.19 2006/12/11 23:40:57 ganovelli Has*Opt migrated to Has*Occ Revision 1.18 2006/11/28 22:34:28 cignoni Added default constructor with null initialization to adjacency members. AddFaces and AddVertices NEED to know if the topology is correctly computed to update it. Revision 1.17 2006/01/09 13:58:56 cignoni Added Initialization of Color in Vertex and Face Components Revision 1.16 2005/11/22 23:58:03 cignoni Added intiailization of flags to zero in the constructor, Revision 1.15 2005/11/18 15:44:51 cignoni Access to constant normal changed from by val to by reference Revision 1.14 2005/11/16 23:02:37 cignoni Added some missing members to EmptyMark Standardized name of flags. It is plural becouse each simplex has many flag. Revision 1.13 2005/11/14 23:50:57 cignoni Added Incremental Mark Revision 1.12 2005/11/12 18:35:49 cignoni Changed HasFlag -> HasFlags Revision 1.11 2005/11/01 18:17:52 cignoni Added an assert(0) in all the accesses to empty components Revision 1.10 2005/10/15 16:24:10 ganovelli Working release (compilata solo su MSVC), component_occ � migrato da component_opt Revision 1.9 2005/10/14 13:30:07 cignoni Added constant access functions and reflective functions (HasSomething stuff) to all the components This is the first really working version... Revision 1.8 2005/10/07 15:19:54 cignoni minor updates to keep it in line with the rest of the library Revision 1.7 2004/05/10 13:50:32 cignoni Updated names of adj functions to the new standards Revision 1.6 2004/04/05 11:53:06 cignoni addend constant access funcs Revision 1.5 2004/04/03 13:35:51 cignoni minor changes Revision 1.4 2004/03/31 13:15:28 cignoni Added optional cpmponent Revision 1.3 2004/03/31 12:28:37 ganovelli *** empty log message *** Revision 1.2 2004/03/29 14:26:38 cignoni Error in color Revision 1.1 2004/03/29 08:36:26 cignoni First working version! ****************************************************************************/ #ifndef __VCG_VERTEX_PLUS_COMPONENT #define __VCG_VERTEX_PLUS_COMPONENT #include #include #include #include namespace vcg { namespace vert { /* Some naming Rules All the Components that can be added to a vertex should be defined in the namespace vert: */ /*------------------------- EMPTY COORD & NORMAL -----------------------------------------*/ template class EmptyCoordNormal: public T { public: typedef vcg::Point3f CoordType; typedef CoordType::ScalarType ScalarType; CoordType &P() { static CoordType coord(0, 0, 0); return coord; } const CoordType &P() const { static CoordType coord(0, 0, 0); assert(0); return coord; } const CoordType &cP() const { static CoordType coord(0, 0, 0); assert(0); return coord; } CoordType &UberP() { static CoordType coord(0, 0, 0); return coord; } static bool HasCoord() { return false; } typedef vcg::Point3s NormalType; NormalType &N() { static NormalType dummy_normal(0, 0, 0); assert(0); return dummy_normal; } const NormalType cN()const { static NormalType dummy_normal(0, 0, 0); assert(0); return dummy_normal; } static bool HasNormal() { return false; } static bool HasNormalOcc() { return false; } template < class LeftV> void ImportLocal(const LeftV & left ) { T::ImportLocal( left); } static void Name(std::vector & name){T::Name(name);} }; /*-------------------------- COORD ----------------------------------------*/ template class Coord: public T { public: typedef A CoordType; typedef typename CoordType::ScalarType ScalarType; CoordType &P() { return _coord; } const CoordType &P() const { return _coord; } const CoordType &cP() const { return _coord; } CoordType &UberP() { return _coord; } template < class LeftV> void ImportLocal(const LeftV & left ) { P() = left.cP(); T::ImportLocal( left); } static bool HasCoord() { return true; } static void Name(std::vector & name){name.push_back(std::string("Coord"));T::Name(name);} private: CoordType _coord; }; template class Coord3f: public Coord { public: static void Name(std::vector & name){name.push_back(std::string("Coord3f"));T::Name(name);} }; template class Coord3d: public Coord { public: static void Name(std::vector & name){name.push_back(std::string("Coord3d"));T::Name(name);} }; /*-------------------------- NORMAL ----------------------------------------*/ template class Normal: public T { public: typedef A NormalType; NormalType &N() { return _norm; } const NormalType &cN() const { return _norm; } template < class LeftV> void ImportLocal(const LeftV & left ) { N() = left.cN(); T::ImportLocal( left); } static bool HasNormal() { return true; } static void Name(std::vector & name){name.push_back(std::string("Normal"));T::Name(name);} private: NormalType _norm; }; template class Normal3s: public Normal { public:static void Name(std::vector & name){name.push_back(std::string("Normal3s"));T::Name(name);} }; template class Normal3f: public Normal { public: static void Name(std::vector & name){name.push_back(std::string("Normal3f"));T::Name(name);} }; template class Normal3d: public Normal { public: static void Name(std::vector & name){name.push_back(std::string("Normal3d"));T::Name(name);} }; /*-------------------------- INCREMENTAL MARK ----------------------------------------*/ template class EmptyMark: public T { public: static bool HasMark() { return false; } static bool HasMarkOcc() { return false; } inline void InitIMark() { } inline int & IMark() { assert(0); static int tmp=-1; return tmp;} inline const int & IMark() const {return 0;} template < class LeftV> void ImportLocal(const LeftV & left ) { T::ImportLocal( left); } static void Name(std::vector & name){T::Name(name);} }; template class Mark: public T { public: static bool HasMark() { return true; } static bool HasMarkOcc() { return true; } inline void InitIMark() { _imark = 0; } inline int & IMark() { return _imark;} inline const int & IMark() const {return _imark;} template < class LeftV> void ImportLocal(const LeftV & left ) { IMark() = left.IMark(); T::ImportLocal( left); } static void Name(std::vector & name){name.push_back(std::string("Mark"));T::Name(name);} private: int _imark; }; /*-------------------------- TEXCOORD ----------------------------------------*/ template class EmptyTexCoord: public TT { public: typedef vcg::TexCoord2 TexCoordType; TexCoordType &T() { static TexCoordType dummy_texcoord; assert(0); return dummy_texcoord; } template < class LeftV> void ImportLocal(const LeftV & left ) { TT::ImportLocal( left); } static bool HasTexCoord() { return false; } static void Name(std::vector & name){TT::Name(name);} }; template class TexCoord: public TT { public: typedef A TexCoordType; TexCoordType &T() { return _t; } const TexCoordType &cT() const { return _t; } template < class LeftV> void ImportLocal(const LeftV & left ) { T() = left.cT(); TT::ImportLocal( left); } static bool HasTexCoord() { return true; } static void Name(std::vector & name){name.push_back(std::string("TexCoord"));TT::Name(name);} private: TexCoordType _t; }; template class TexCoord2s: public TexCoord, TT> { static void Name(std::vector & name){name.push_back(std::string("TexCoord2s"));TT::Name(name);} }; template class TexCoord2f: public TexCoord, TT> { static void Name(std::vector & name){name.push_back(std::string("TexCoord2f"));TT::Name(name);} }; template class TexCoord2d: public TexCoord, TT> { static void Name(std::vector & name){name.push_back(std::string("TexCoord2d"));TT::Name(name);} }; /*------------------------- FLAGS -----------------------------------------*/ template class EmptyBitFlags: public T { public: typedef int FlagType; /// Return the vector of Flags(), senza effettuare controlli sui bit int &Flags() { static int dummyflags(0); assert(0); return dummyflags; } const int Flags() const { return 0; } template < class LeftV> void ImportLocal(const LeftV & left ) { T::ImportLocal( left); } static bool HasFlags() { return false; } static void Name(std::vector & name){T::Name(name);} }; template class BitFlags: public T { public: BitFlags(){_flags=0;} typedef int FlagType; int &Flags() {return _flags; } const int Flags() const {return _flags; } template < class LeftV> void ImportLocal(const LeftV & left ) { Flags() = left.cFlags(); T::ImportLocal( left); } static bool HasFlags() { return true; } static void Name(std::vector & name){name.push_back(std::string("BitFlags"));T::Name(name);} private: int _flags; }; /*-------------------------- EMPTY COLOR & QUALITY ----------------------------------*/ template class EmptyColorQuality: public T { public: typedef float QualityType; QualityType &Q() { static QualityType dummyQuality(0); assert(0); return dummyQuality; } static bool HasQuality() { return false; } typedef vcg::Color4b ColorType; ColorType &C() { static ColorType dumcolor(vcg::Color4b::White); assert(0); return dumcolor; } template < class LeftV> void ImportLocal(const LeftV & left ) { T::ImportLocal( left); } static bool HasColor() { return false; } static void Name(std::vector & name){T::Name(name);} }; /*-------------------------- Color ----------------------------------*/ template class Color: public T { public: Color():_color(vcg::Color4b::White) {} typedef A ColorType; ColorType &C() { return _color; } const ColorType &C() const { return _color; } const ColorType &cC() const { return _color; } template < class LeftV> void ImportLocal(const LeftV & left ) { C() = left.cC(); T::ImportLocal( left); } static bool HasColor() { return true; } static void Name(std::vector & name){name.push_back(std::string("Color"));T::Name(name);} private: ColorType _color; }; template class Color4b: public vert::Color { static void Name(std::vector & name){name.push_back(std::string("Color4b"));TT::Name(name);} }; /*-------------------------- Quality ----------------------------------*/ template class Quality: public TT { public: typedef A QualityType; QualityType &Q() { return _quality; } const QualityType & cQ() const {return _quality; } template < class LeftV> void ImportLocal(const LeftV & left ) { Q() = left.cQ(); TT::ImportLocal( left); } static bool HasQuality() { return true; } static void Name(std::vector & name){name.push_back(std::string("Quality"));TT::Name(name);} private: QualityType _quality; }; template class Qualitys: public Quality { static void Name(std::vector & name){name.push_back(std::string("Qualitys"));TT::Name(name);} }; template class Qualityf: public Quality { static void Name(std::vector & name){name.push_back(std::string("Qualityf"));TT::Name(name);} }; template class Qualityd: public Quality { static void Name(std::vector & name){name.push_back(std::string("Qualityd"));TT::Name(name);} }; /*-------------------------- Curvature ----------------------------------*/ template class EmptyCurvature: public TT { public: typedef vcg::Point2 CurvatureType; float &Kh() {static float dummy = 0.f; return dummy;;} float &Kg() { static float dummy = 0.f; return dummy;} const float &cKh() const {static float dummy = 0.f; return dummy;;} const float &cKg()const { static float dummy = 0.f; return dummy;} static bool HasCurvatureOcc() { return false; } static bool HasCurvatureOcf() { return false; } static bool HasCurvature() { return false; } static void Name(std::vector & name){TT::Name(name);} }; template class Curvature: public TT { public: typedef Point2 CurvatureType; typedef typename CurvatureType::ScalarType ScalarType; ScalarType &Kh(){ return _hk[0];} ScalarType &Kg(){ return _hk[1];} const ScalarType &cKh() const { return _hk[0];} const ScalarType &cKg() const { return _hk[1];} static bool HasCurvature() { return true; } static void Name(std::vector & name){name.push_back(std::string("Curvature"));TT::Name(name);} private: Point2 _hk; }; template class Curvaturef: public Curvature< float, T> { public: static void Name(std::vector & name){name.push_back(std::string("Curvaturef"));T::Name(name);} }; template class Curvatured: public Curvature { public: static void Name(std::vector & name){name.push_back(std::string("Curvatured"));T::Name(name);} }; /*-------------------------- Curvature Direction ----------------------------------*/ template struct CurvatureDirType{ typedef Point3 VecType; typedef S ScalarType; CurvatureDirType () {} Point3max_dir,min_dir; // max and min curvature direction S k1,k2;// max and min curvature values }; template class EmptyCurvatureDir: public TT { public: typedef CurvatureDirType CurvatureDirType; Point3f &PD1(){static Point3f dummy(0,0,0); return dummy;} Point3f &PD2(){static Point3f dummy(0,0,0); return dummy;} const Point3f &cPD1() const {static Point3f dummy(0,0,0); return dummy;} const Point3f &cPD2()const {static Point3f dummy(0,0,0); return dummy;} float &K1(){ static float dummy(0);assert(0);return dummy;} float &K2(){ static float dummy(0);assert(0);return dummy;} const float &cK1()const { static float dummy(0);assert(0);return dummy;} const float &cK2()const { static float dummy(0);assert(0);return dummy;} static bool HasCurvatureDir() { return false; } static void Name(std::vector & name){TT::Name(name);} }; template class CurvatureDir: public TT { public: typedef A CurvatureDirType; typedef typename CurvatureDirType::VecType VecType; typedef typename CurvatureDirType::ScalarType ScalarType; VecType &PD1(){ return _curv.max_dir;} VecType &PD2(){ return _curv.min_dir;} const VecType &cPD1() const {return _curv.max_dir;} const VecType &cPD2() const {return _curv.min_dir;} ScalarType &K1(){ return _curv.k1;} ScalarType &K2(){ return _curv.k2;} const ScalarType &cK1() const {return _curv.k1;} const ScalarType &cK2()const {return _curv.k2;} static bool HasCurvatureDir() { return true; } static void Name(std::vector & name){name.push_back(std::string("CurvatureDir"));TT::Name(name);} private: CurvatureDirType _curv; }; template class CurvatureDirf: public CurvatureDir, T> { public: static void Name(std::vector & name){name.push_back(std::string("CurvatureDirf"));T::Name(name);} }; template class CurvatureDird: public CurvatureDir, T> { public: static void Name(std::vector & name){name.push_back(std::string("CurvatureDird"));T::Name(name);} }; /*----------------------------- VFADJ ------------------------------*/ template class EmptyVFAdj: public T { public: typename T::FacePointer &VFp() { static typename T::FacePointer fp=0; assert(0); return fp; } typename T::FacePointer cVFp() { static typename T::FacePointer fp=0; assert(0); return fp; } int &VFi(){static int z=0; return z;}; template < class LeftV> void ImportLocal(const LeftV & left ) { T::ImportLocal( left); } static bool HasVFAdjacency() { return false; } static bool HasVFAdjacencyOcc() { return false; } static void Name(std::vector & name){ T::Name(name);} }; template class VFAdj: public T { public: VFAdj(){_fp=0;} typename T::FacePointer &VFp() {return _fp; } typename T::FacePointer cVFp() {return _fp; } int &VFi() {return _zp; } template < class LeftV> void ImportLocal(const LeftV & left ) { VFp() = NULL; T::ImportLocal( left); } static bool HasVFAdjacency() { return true; } static bool HasVFAdjacencyOcc() { return true; } static void Name(std::vector & name){name.push_back(std::string("VFAdj"));T::Name(name);} private: typename T::FacePointer _fp ; int _zp ; }; /*----------------------------- VTADJ ------------------------------*/ template class EmptyVTAdj: public T { public: typename T::TetraPointer &VTp() { static typename T::TetraPointer tp = 0; assert(0); return tp; } typename T::TetraPointer cVTp() { static typename T::TetraPointer tp = 0; assert(0); return tp; } int &VTi() { static int z = 0; return z; }; static bool HasVTAdjacency() { return false; } static bool HasVTAdjacencyOcc() { return false; } static void Name( std::vector< std::string > & name ) { T::Name(name); } }; template class VTAdj: public T { public: VTAdj() { _tp = 0; } typename T::TetraPointer &VTp() { return _tp; } typename T::TetraPointer cVTp() { return _tp; } int &VTi() {return _zp; } static bool HasVTAdjacency() { return true; } static bool HasVTAdjacencyOcc() { return true; } static void Name( std::vector< std::string > & name ) { name.push_back( std::string("VTAdj") ); T::Name(name); } private: typename T::TetraPointer _tp ; int _zp ; }; } // end namespace vert }// end namespace vcg #endif qutemol/vcg/vcg/simplex/tetrahedron/0000755000175000017500000000000011633404241016160 5ustar mbambaqutemol/vcg/vcg/simplex/tetrahedron/base.h0000444000175000017500000003506410454426674017267 0ustar mbamba/**************************************************************************** * VCGLib o o * * Visual and Computer Graphics Library o o * * _ O _ * * Copyright(C) 2004 \/)\/ * * Visual Computing Lab /\/| * * ISTI - Italian National Research Council | * * \ * * All rights reserved. * * * * 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. * * * * 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 (http://www.gnu.org/licenses/gpl.txt) * * for more details. * * * ****************************************************************************/ /**************************************************************************** History $Log: base.h,v $ Revision 1.16 2006/07/10 10:36:44 turini added include to sphere3.h for SmallestEnclosingSphere() Revision 1.15 2006/07/06 12:46:19 ganovelli added GeometicType e SmallestEnclosingSphere Revision 1.14 2005/12/12 11:10:36 ganovelli modifications to compile with gcc Revision 1.13 2004/10/04 17:07:58 pietroni changed Q() function Revision 1.12 2004/09/01 12:18:39 pietroni minor changes to comply gcc compiler (typename's ) Revision 1.11 2004/08/26 13:15:23 pietroni added IsS() function Revision 1.10 2004/07/09 10:13:00 ganovelli C() ,Q() ,hastetracolor(),hasqualityt().... plus some misuse of tetra3 corrected Revision 1.9 2004/07/08 08:43:22 pietroni changed functions used to compute the aspect ratio Revision 1.8 2004/05/20 13:04:23 pietroni modified setBorderV function Revision 1.7 2004/05/14 11:48:43 pietroni templated with also tetratype... Revision 1.6 2004/05/14 11:07:36 turini Changed swap in std::swap. Revision 1.5 2004/05/06 15:29:42 pietroni changed names to topology functions Revision 1.4 2004/04/28 11:37:14 pietroni *** empty log message *** Revision 1.3 2004/04/26 09:38:54 pietroni *** empty log message *** Revision 1.2 2004/04/20 12:42:37 pietroni *** empty log message *** Revision 1.1 2004/04/15 08:54:20 pietroni *** empty log message *** ****************************************************************************/ #ifndef TETRA_TYPE #pragma message("\nYou should never directly include this file\_n") #else #include #include #include namespace vcg { /** \ingroup tetrahedron @name Tetrahedron Class Tetrahedron. This is the base class for definition of a Tetrahedron of the mesh. @param VTYPE (Template Parameter) Specifies the type for the vertex. */ template < class VTYPE, class TTYPE > class TETRA_TYPE{ public: /// The base type of the face typedef TETRA_TYPE BaseTetraType; /// The vertex type typedef VTYPE VertexType; /// The coordinate type used to represent the point (i.e. Point3f, Point3d, ...) typedef typename VertexType::CoordType CoordType; /// The scalar type used to represent coords (i.e. float, double, ...) typedef typename VertexType::ScalarType ScalarType; /// The geometric type of the tetrahedron typedef Tetra3 GeometricType; /***********************************************/ /** @name Tetrahedron Flags For each Tetrahedron we store a set of boolean values packed in a int. The default value for each flag is 0. Most commonly used flags are the \a deleted and the \a selected ones. Users can ask and dispose for a bit for their own purposes with the vcg::TetrahedronFull::NewUserBit() and vcg::TetrahedronFull::DeleteUserBit() functions. The value returned by these functions has to be passed to the vcg::TetrahedronFull::SetUserBit() vcg::TetrahedronFull::ClearUserBit() and vcg::TetrahedronFull::IsUserBit() functions to check and modify the obtained bit flag. **/ //@{ /// This are the flags of tetrahedron, the default value is 0 int _flags; enum { DELETED = 0x00000001, // deleted tetrahedron flag SELECTED = 0x00000002, // Selection flag BORDERF0 = 0x00000004, // Border flag, Face 0 BORDERF1 = 0x00000008, // Border flag, Face 1 BORDERF2 = 0x00000010, // Border flag, Face 2 BORDERF3 = 0x00000020, // Border flag, Face 3 BORDERE0 = 0x00000040, // Border flag, Edge 0 BORDERE1 = 0x00000080, // Border flag, Edge 1 BORDERE2 = 0x00000100, // Border flag, Edge 2 BORDERE3 = 0x00000200, // Border flag, Edge 3 BORDERE4 = 0x00000400, // Border flag, Edge 4 BORDERE5 = 0x00000800, // Border flag, Edge 5 USER0 = 0x00001000, // new flag for user }; public: /// Return the vector of _flags inline int & Flags () { assert( (_flags & DELETED) == 0 ); return _flags; } static int &LastBitFlag() { static int b =USER0; return b; } static inline int NewBitFlag() { LastBitFlag()=LastBitFlag()<<1; return LastBitFlag(); } static inline bool DeleteBitFlag(int bitval) { if(LastBitFlag()==bitval) { LastBitFlag()= LastBitFlag()>>1; return true; } assert(0); return false; } /// Get the flags without any control inline int & UberFlags() { return _flags; } /// This function checks if the given user bit is true. bool IsUserBit(int userBit){return (_flags & userBit) != 0;} /// This function set the given user bit. void SetUserBit(int userBit){_flags |=userBit;} /// This function clear the given user bit. void ClearUserBit(int userBit){_flags &= (~userBit);} /// This function checks if the tetrahedron is deleted. bool IsD() const {return (_flags & DELETED) != 0;} /// This function mark the tetrahedron as deleted. void SetD() {_flags |=DELETED;} /// This function mark the tetrahedron as not deleted. void ClearD() {_flags &=~DELETED;} /// This answer true if a tetrahedron is selected bool IsS() const {return (_flags & SELECTED) != 0;} /// This function mark the tetrahedron as selected. void SetS() {_flags |=SELECTED;} /// This function mark the tetrahedron as not selected. void ClearS() {_flags &=~SELECTED;} /// This function return true if one face is extern. bool HaveBorderF() {return ((_flags & (BORDERF0 | BORDERF1 | BORDERF2 | BORDERF3)) != 0);} /// This function return true if the face is extern. bool IsBorderF(int face) { assert ((face<4)&&(face>-1)); return (this->TTp(face) == this); } //@} /***********************************************/ /** @name Vertex Pointers For each Tetrahedron we store 4 pointers to vertex **/ //@{ /// The 4 vertices of the tetrahedron protected: VertexType *_v[4]; public: /** Return the pointer to the j-th vertex of the terahedron. @param j Index of the tetrahedron's vertex. */ inline VertexType * & V( const int j ) { assert( (_flags & DELETED) == 0 ); assert(j >= 0); assert(j < 4); return _v[j]; } inline const VertexType * const & V( const int j ) const { assert( (_flags & DELETED) == 0 ); assert(j>=0); assert(j<4); return _v[j]; } inline const VertexType * const & cV( const int j ) const { assert( (_flags & DELETED) == 0 ); assert(j>=0); assert(j<4); return _v[j]; } inline CoordType & P( const int j ) { return V(j)->P();} inline const CoordType & cP( const int j ) const { return V(j)->cP();} /***********************************************/ /** @name Topology Structures For each Tetrahedron we store 2 array for Tatrahedron - Tetrahedron topology ( sharing Face) and 2 array to implement the list of Vertex - Tetrahedron Topology (List of Tetrahedron sharing a vertex). **/ //@{ #ifdef __VCGLIB_TETRA_AT protected: ///pointers to tetrahedron for tetrahedron-tetrahedron topology (sharing same face) TTYPE *_ttp[4]; ///index of face for tetrahedron-tetrahedron topology (sharing same face) int _tti[4]; public: ///Function to access the Tetrahedron that share the index-face (extern face returns a pointer to himself) TTYPE *&TTp(const int &index) { return _ttp[index]; } ///Function to see the index of the face as seen from the other tetrahedron (extern face returns -1) int &TTi(const int &index) { return _tti[index]; } #endif #ifdef __VCGLIB_TETRA_AV protected: ///pointers to tetrahedron for vertex-tetrahedron topology (sharing same vertex) TTYPE *_tvp[4]; ///index of vertex for vertex-tetrahedron topology (sharing same vertex) short int _tvi[4]; public: ///Function to access the Next Tetrahedron of the list that share the index-face (end of list is Null) TTYPE *&TVp(const int &index) { return _tvp[index]; } ///Function to see the index of the Vertex as seen from the next tetrahedron of the list ( end of list is -1) short int &TVi(const int &index) { return _tvi[index]; } #endif //@} /***********************************************/ /** @Default Tatrahedron Functions**/ //@{ public: ///Constructor TETRA_TYPE() { _flags=0; } ///initialize default parameters of tetrahedron virtual void Init(VertexType * p0,VertexType * p1,VertexType * p2,VertexType * p3) { _flags = 0; _v[0]=p0; _v[1]=p1; _v[2]=p2; _v[3]=p3; if(vcg::ComputeVolume(*this)<0 ) std::swap(_v[1],_v[2]); #ifdef __VCGLIB_TETRA_TA _z[0]=_z[1]=_z[2]=_z[3]=-1; _t[0]=_t[1]=_t[2]=_t[3]=NULL; #endif #ifdef __VCGLIB_TETRA_TV _zv[0]=_zv[1]=_zv[2]=_zv[3]=-1; _tv[0]=_tv[1]=_tv[2]=_tv[3]=NULL; #endif #ifdef __VCGLIB_TETRA_TQ ComputeAspectRatio(); #endif } ///set border vertices using TT-topology #ifdef __VCGLIB_TETRA_AT void setBorderV() { int i; for (i=0;i<4;i++) if (TTp(i)==this) { V(Tetra::VofF(i,0))->SetB(); V(Tetra::VofF(i,1))->SetB(); V(Tetra::VofF(i,2))->SetB(); } } #endif //@} /***********************************************/ /** @Generic geometric and quality funtions of a tetrahedron**/ //@{ #ifdef __VCGLIB_TETRA_TN private: CoordType _n[4]; public: #endif ///return the normal of a face of the tetrahedron CoordType N(const int &i){ assert((i>=0)&&(i<4)); #ifdef __VCGLIB_TETRA_TN return _n[i]; #else /* Tetra3 T=Tetra3(); T.P0(0)=V(0)->P(); T.P1(0)=V(1)->P(); T.P2(0)=V(2)->P(); T.P3(0)=V(3)->P();*/ return (Normal(*this,i)); #endif } /// Calculate the normal to all the faces of a tetrahedron, the value is store in a position of vecton _n for each face void ComputeNormal() { #ifdef __VCGLIB_TETRA_TN Tetra3 T=Tetra3(); T.P0(0)=V(0)->P(); T.P1(0)=V(1)->P(); T.P2(0)=V(2)->P(); T.P3(0)=V(3)->P(); for (int i=0;i<4;i++) _n[i]=(Normal >(T,i)); #else assert(0); #endif } //@} /***********************************************/ /** @Generic geometric and quality funtions of a tetrahedron**/ //@{ #ifdef __VCGLIB_TETRA_TQ ScalarType _volume; ScalarType _aspect_ratio; ScalarType _q; #endif ScalarType & Q(){ #ifdef __VCGLIB_TETRA_TQ return _q; #else assert(0); return *(ScalarType*)(&_flags); #endif } const ScalarType & Q()const{ #ifdef __VCGLIB_TETRA_TQ return _q; #else assert(0); return *(ScalarType*)(&_flags); #endif } ScalarType ComputeVolume(){ #ifdef __VCGLIB_TETRA_TQ _volume = vcg::ComputeVolume(*this); return _volume; #else return vcg::ComputeVolume(*this); #endif } ///return the volume of the tetrahedron const ScalarType & Volume(){ #ifdef __VCGLIB_TETRA_TQ return _volume; #else return (( V(2)->cP()-V(0)->cP())^(V(1)->cP()-V(0)->cP() ))*(V(3)->cP()-V(0)->cP())/6.0; #endif } ///return aspect ratio of the tetrahedron ScalarType AspectRatio(){ #ifdef __VCGLIB_TETRA_TQ return _aspect_ratio; #else return ComputeAspectRatio(); #endif } ///set if exist local value of aspect ratio ScalarType ComputeAspectRatio(){ //Tetra3 T=Tetra3(); //T.P0(0)=V(0)->cP(); //T.P1(0)=V(1)->cP(); //T.P2(0)=V(2)->cP(); //T.P3(0)=V(3)->cP(); #ifdef __VCGLIB_TETRA_TQ _aspect_ratio= ( (Tetra3* ) this) -> ComputeAspectRatio(); return(_aspect_ratio); #else return (( (Tetra3 *) this) -> ComputeAspectRatio()); #endif } CoordType Barycenter() const { return (V(0)->cP()+V(1)->cP()+V(2)->cP()+V(3)->cP())/ScalarType(4.0); } Sphere3 SmallestEnclosingSphere()const { return SmallestEnclosing::SphereOfTetra(*this); } //@} /***********************************************/ /** @name Color **/ //@{ #ifdef __VCGLIB_TETRA_TC Color4b c; #endif Color4b & C(){ #ifdef __VCGLIB_TETRA_TC return _c; #else assert(0); return (*new Color4b()); #endif } //@} /***********************************************/ /** @name Reflection Functions Static functions that give information about the current tetra type. Reflection is a mechanism making it possible to investigate yourself. Reflection is used to investigate format of objects at runtime, invoke methods and access fields of these objects. Here we provide static const functions that are resolved at compile time and they give information about the data supported by the current tetra type. **/ //@{ static bool HasTetraNormal() { #ifdef __VCGLIB_TETRA_TN return true; #else return false; #endif } static bool HasTetraMark() { #ifdef __VCGLIB_TETRA_TM return true; #else return false; #endif } static bool HasTetraQuality() { #ifdef __VCGLIB_TETRA_TQ return true; #else return false; #endif } static bool HasTetraColor() { #ifdef __VCGLIB_TETRA_TC return true; #else return false; #endif } static bool HasTTAdjacency() { #if (defined(__VCGLIB_TETRA_AT) || defined(__VCGLIB_TETRA_SAT)) return true; #else return false; #endif } static bool HasVTAdjacency() { #if (defined(__VCGLIB_TETRA_AV) || defined(__VCGLIB_TETRA_SAT)) return true; #else return false; #endif } //@} };//end class }//end namespace #endif qutemol/vcg/vcg/simplex/tetrahedron/pos.h0000444000175000017500000002461310347255254017147 0ustar mbamba/**************************************************************************** * VCGLib o o * * Visual and Computer Graphics Library o o * * _ O _ * * Copyright(C) 2004 \/)\/ * * Visual Computing Lab /\/| * * ISTI - Italian National Research Council | * * \ * * All rights reserved. * * * * 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. * * * * 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 (http://www.gnu.org/licenses/gpl.txt) * * for more details. * * * ****************************************************************************/ /**************************************************************************** History ****************************************************************************/ #ifndef __VCG_TETRA_POS #define __VCG_TETRA_POS namespace vcg { namespace tetra { /** \addtogroup tetra */ /*@{*/ /** Class VTIterator. This is a vertex - tetrahedron iterator @param MTTYPE (Template Parameter) Specifies the type of the tetrahedron. */ template < class MTTYPE> class VTIterator { public: /// The tetrahedron type typedef MTTYPE TetraType; private: /// Pointer to a tetrahedron TetraType *_vt; /// Index of one vertex int _vi; /// Default Constructor public: VTIterator(){} /// Constructor which associates the EdgePos elementet with a face and its edge VTIterator(TetraType * const tp, int const zp) { _vt=tp; _vi=zp; } ~VTIterator(){}; /// Return the tetrahedron stored in the half edge inline TetraType* & Vt() { return _vt; } /// Return the index of vertex as seen from the tetrahedron inline int & Vi() { return _vi; } /// Return the index of vertex as seen from the tetrahedron inline const int & Vi() const { return _vi; } inline bool End(){return (Vt()==NULL);} /// move on the next tetrahedron that share the vertex void operator++() { int vi=Vi(); TetraType * tw = Vt(); Vt() = tw->TVp(vi); Vi() = tw->TVi(vi); assert((Vt()==NULL)||((tw->V(vi))==(Vt()->V(Vi())))); } }; /** Templated over the class tetrahedron, it stores a \em position over a tetrahedron in a mesh. It contain a pointer to the current tetrahedron, the index of one face,edge and a edge's incident vertex. */ template < class MTTYPE> class Pos { public: /// The tetrahedron type typedef MTTYPE TetraType; /// The vertex type typedef typename TetraType::VertexType VertexType; /// The coordinate type typedef typename TetraType::VertexType::CoordType CoordType; ///The HEdgePos type typedef Pos BasePosType; private: /// Pointer to the tetrahedron of the half-edge TetraType *_t; /// Index of the face char _f; /// Index of the edge char _e; /// Pointer to the vertex char _v; public: /// Default constructor Pos(){SetNull();}; /// Constructor which associates the half-edge elementet with a face, its edge and its vertex Pos(TetraType * const tp, char const fap,char const ep, char const vp){_t=tp;_f=fap;_e=ep;_v=vp;} ~Pos(){}; /// Return the tetrahedron stored in the half edge inline TetraType* & T() { return _t; } /// Return the tetrahedron stored in the half edge inline TetraType* const & T() const { return _t; } /// Return the index of face as seen from the tetrahedron inline char & F() { return _f; } /// Return the index of face as seen from the tetrahedron inline const char & F() const { return _f; } /// Return the index of face as seen from the tetrahedron inline char & E() { return _e; } /// Return the index of face as seen from the tetrahedron inline const char & E() const { return _e; } /// Return the index of vertex as seen from the tetrahedron inline char & V() { return _v; } /// Return the index of vertex as seen from the tetrahedron inline const char & V() const { return _v; } /// Operator to compare two half-edge inline bool operator == ( BasePosType const & p ) const { return (T()==p.T() && F()==p.F() && E==p.E() && V==p.V()); } /// Operator to compare two half-edge inline bool operator != ( BasePosType const & p ) const { return (!((*this)==p)); } /// Set to null the half-edge void SetNull(){ T()=0; F()=-1; E()=-1; V()=-1; } /// Check if the half-edge is null bool IsNull() const { return ((T()==0) || (F()<0) || (E()<0) || (V()<0)); } /// Changes edge maintaining the same face and the same vertex void FlipE() { //take the absolute index of the tree edges of the faces char e0=vcg::Tetra::EofF(_f ,0); char e1=vcg::Tetra::EofF(_f ,1); char e2=vcg::Tetra::EofF(_f ,2); //eliminate the same as himself if (e0==E()) { e0=e1; e1=e2; } else if (e1==E()) { e1=e2; } //now choose the one that preserve the same vertex if ((vcg::Tetra::VofE(e1,0)==V())||(vcg::Tetra::VofE(e1,1)==V())) E()=e1; else E()=e0; } /// Changes vertex maintaining the same face and the same edge void FlipV() { // in the same edge choose the one that change char v0=vcg::Tetra::VofE(E(),0); char v1=vcg::Tetra::VofE(E(),1); if (v0!=V()) V()=v0; else V()=v1; } /// Changes face maintaining the same vertex and the same edge void FlipF() { char f0=vcg::Tetra::FofE(E(),0); char f1=vcg::Tetra::FofE(E(),1); if (f0!=F()) F()=f0; else F()=f1; } /// Changes tetrahedron maintaining the same face edge and vertex'... to finish void FlipT() { //save the two vertices of the old edge VertexType *v0=T()->V(vcg::Tetra::VofE(E(),0)); VertexType *v1=T()->V(vcg::Tetra::VofE(E(),1)); //get the current vertex VertexType *vcurr=T()->V(V()); //get new tetrahedron according to faceto face topology TetraType *nt=T()->TTp(F()); char nfa=T()->TTi(F()); if (nfa!=-1) { //find the right edge char ne0=vcg::Tetra::EofF(nfa,0); char ne1=vcg::Tetra::EofF(nfa,1); char ne2=vcg::Tetra::EofF(nfa,2); //the vertices of new edges VertexType *vn0=nt->V(vcg::Tetra::VofE(ne0,0)); VertexType *vn1=nt->V(vcg::Tetra::VofE(ne0,1)); //verify that the two vertices of tetrahedron are identical if (((vn0==v0)&&(vn1==v1))||((vn1==v0)&&(vn0==v1))) E()=ne0; else { vn0=nt->V(vcg::Tetra::VofE(ne1,0)); vn1=nt->V(vcg::Tetra::VofE(ne1,1)); if (((vn0==v0)&&(vn1==v1))||((vn1==v0)&&(vn0==v1))) E()=ne1; else { #ifdef _DEBUG vn0=nt->V(vcg::Tetra::VofE(ne2,0)); vn1=nt->V(vcg::Tetra::VofE(ne2,1)); assert(((vn0==v0)&&(vn1==v1))||((vn1==v0)&&(vn0==v1))); #endif E()=ne2; } } //find the right vertex vn0=nt->V(vcg::Tetra::VofE(E(),0)); #ifdef _DEBUG vn1=nt->V(vcg::Tetra::VofE(E(),1)); assert((vn0==vcurr)||(vn1==vcurr)); #endif if (vn0==vcurr) V()=vcg::Tetra::VofE(E(),0); else V()=vcg::Tetra::VofE(E(),1); T()=nt; assert(T()->V(V())==vcurr); F()=nfa; } } ///returns the next half edge on the same edge void NextT( ) { #ifdef _DEBUG VertexType *vold=T()->V(V()); #endif FlipT(); FlipF(); #ifdef _DEBUG VertexType *vnew=T()->V(V()); assert(vold==vnew); #endif } void Assert() #ifdef _DEBUG { HETYPE ht=*this; ht.FlipT(); ht.FlipT(); assert(ht==*this); ht=*this; ht.FlipF(); ht.FlipF(); assert(ht==*this); ht=*this; ht.FlipE(); ht.FlipE(); assert(ht==*this); ht=*this; ht.FlipV(); ht.FlipV(); assert(ht==*this); } #else {} #endif }; ///this pos structure jump on next tetrahedron if find an external face template < class MTTYPE> class PosJump:public Pos { private: MTTYPE *_t_initial; short int _back; public : typedef MTTYPE TetraType; PosJump(const TetraType* tp,const int fap,const int ep, int vp){this->T()=tp;this->F()=fap;this->E()=ep;this->V()=vp;_t_initial=tp;_back=0;} void NextT() { #ifdef _DEBUG int cont=0; #endif MTTYPE *tpred=this->T(); Pos::NextT(); //external face if (tpred==this->T()) { while (this->T()!=_t_initial) { Pos::NextT(); #ifdef _DEBUG cont++; assert (cont<500); #endif } _back++; if (_back==1) { Pos::NextT(); } } } }; ///this pos structure jump on next tetrahedron in rotational sense if find an external face template < class MTTYPE> class PosLoop:public Pos { private: MTTYPE *_t_initial; bool _jump; bool _loop; public : typedef MTTYPE TetraType; PosLoop(TetraType* tp,const int fap,const int ep, int vp){this->T()=tp;this->F()=fap;this->E()=ep;this->V()=vp;_t_initial=tp;_jump=false;_loop=false;} bool LoopEnd() { return (_loop); } bool Jump() { return(_jump); } void Reset() { _loop=false; _jump=false; } void NextT() { #ifdef _DEBUG TetraType *t_old=this->T(); #endif TetraType *tpred=this->T(); Pos::NextT(); _loop=false; _jump=false; //external face if (tpred==this->T()) { tpred=this->T(); //jump next one Pos::NextT(); //find the next external face while (tpred!=this->T()) { tpred=this->T(); Pos::NextT(); } ////reset right rotation sense // Pos::NextT(); _jump=true; } if (this->T()==_t_initial) _loop=true; #ifdef _DEBUG if (_loop==false) assert(t_old!=this->T()); #endif } }; //@} }//end namespace tetra }//end namespace vcg #endif qutemol/vcg/vcg/simplex/tetrahedron/with/0000755000175000017500000000000011633404241017133 5ustar mbambaqutemol/vcg/vcg/simplex/tetrahedron/with/at.h0000444000175000017500000000032710046153716017715 0ustar mbamba#ifndef __VCGLIB_TETRA_AT_TYPE #define __VCGLIB_TETRA_AT_TYPE #define TETRA_TYPE TetraAT #define __VCGLIB_TETRA_AT #include #undef TETRA_TYPE #undef __VCGLIB_TETRA_AT #endif qutemol/vcg/vcg/simplex/tetrahedron/with/tn.h0000444000175000017500000000033010046156275017727 0ustar mbamba#ifndef __VCGLIB_TETRA_TN_TYPE #define __VCGLIB_TETRA_TN_TYPE #define TETRA_TYPE TetraTN #define __VCGLIB_TETRA_TN #include #undef TETRA_TYPE #undef __VCGLIB_TETRA_TN #endif qutemol/vcg/vcg/simplex/tetrahedron/with/atavtn.h0000444000175000017500000000050310261011717020573 0ustar mbamba#ifndef __VCGLIB_TETRA_ATTN_TYPE #define __VCGLIB_TETRA_ATTN_TYPE #define TETRA_TYPE TetraATAVTN #define __VCGLIB_TETRA_AT #define __VCGLIB_TETRA_AV #define __VCGLIB_TETRA_TN #include #undef TETRA_TYPE #undef __VCGLIB_TETRA_AT #undef __VCGLIB_TETRA_AV #undef __VCGLIB_TETRA_TN #endifqutemol/vcg/vcg/simplex/tetrahedron/with/attn.h0000444000175000017500000000041610261011720020241 0ustar mbamba#ifndef __VCGLIB_TETRA_ATTN_TYPE #define __VCGLIB_TETRA_ATTN_TYPE #define TETRA_TYPE TetraATTN #define __VCGLIB_TETRA_AT #define __VCGLIB_TETRA_TN #include #undef TETRA_TYPE #undef __VCGLIB_TETRA_AT #undef __VCGLIB_TETRA_TN #endifqutemol/vcg/vcg/simplex/tetrahedron/with/tq.h0000444000175000017500000000033010046163621017723 0ustar mbamba#ifndef __VCGLIB_TETRA_TQ_TYPE #define __VCGLIB_TETRA_TQ_TYPE #define TETRA_TYPE TetraTQ #define __VCGLIB_TETRA_TQ #include #undef TETRA_TYPE #undef __VCGLIB_TETRA_TQ #endif qutemol/vcg/vcg/simplex/tetrahedron/with/atavtq.h0000444000175000017500000000051110073206643020602 0ustar mbamba#ifndef __VCGLIB_TETRA_ATAVTQ_TYPE #define __VCGLIB_TETRA_ATAVTQ_TYPE #define TETRA_TYPE TetraATAVTQ #define __VCGLIB_TETRA_AT #define __VCGLIB_TETRA_AV #define __VCGLIB_TETRA_TQ #include #undef TETRA_TYPE #undef __VCGLIB_TETRA_AT #undef __VCGLIB_TETRA_AV #undef __VCGLIB_TETRA_TQ #endif qutemol/vcg/vcg/simplex/tetrahedron/with/atav.h0000444000175000017500000000041710046154217020241 0ustar mbamba#ifndef __VCGLIB_TETRA_ATAV_TYPE #define __VCGLIB_TETRA_ATAV_TYPE #define TETRA_TYPE TetraATAV #define __VCGLIB_TETRA_AT #define __VCGLIB_TETRA_AV #include #undef TETRA_TYPE #undef __VCGLIB_TETRA_AT #undef __VCGLIB_TETRA_AV #endif qutemol/vcg/vcg/simplex/tetrahedron/tetrahedron.h0000444000175000017500000000021410130252676020647 0ustar mbamba#ifndef __VCGLIB_TETRAHEDRON #define __VCGLIB_TETRAHEDRON #define TETRA_TYPE Tetrahedron #include #endif qutemol/vcg/vcg/container/0000755000175000017500000000000011633404241014142 5ustar mbambaqutemol/vcg/vcg/container/container_allocation_table.h0000444000175000017500000002615410767452557021703 0ustar mbamba/**************************************************************************** * VCGLib o o * * Visual and Computer Graphics Library o o * * _ O _ * * Copyright(C) 2004 \/)\/ * * Visual Computing Lab /\/| * * ISTI - Italian National Research Council | * * \ * * All rights reserved. * * * * 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. * * * * 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 (http://www.gnu.org/licenses/gpl.txt) * * for more details. * * * ****************************************************************************/ /**************************************************************************** History $Log: container_allocation_table.h,v $ Revision 1.11 2008/03/17 11:26:39 ganovelli adding of Curvature, compilation with GCC Revision 1.9 2006/12/03 18:01:01 ganovelli versione compliant vs2005 Revision 1.8 2006/06/08 20:28:57 ganovelli aggiunto qualche const sui parametri Revision 1.7 2005/10/15 16:21:48 ganovelli Working release (compilata solo su MSVC), vector_occ � migrato da component_opt Revision 1.6 2005/07/07 13:33:51 ganovelli some comment Revision 1.5 2005/07/06 15:28:10 ganovelli aggiornamento di alcuni path Revision 1.4 2004/04/05 18:20:50 ganovelli Aggiunto typename Eliminata bug di ricorsione nell'istanzazione dei template Revision 1.3 2004/03/31 22:36:44 ganovelli First Working Release (with this comment) /****************************************************************************/ #ifndef __VCGLIB_CAT__ #define __VCGLIB_CAT__ #include #include #include #include #include namespace vcg { /*@{*/ /*! * CATBase is the abstract class for all the allocation tables. These table keep track of * where the traced vector (see traced_ector.h) are kept in memory. * The goal is to know (given a pointer to a memory location), which is the vector the pointed * element is in * */ template class CATBase{ public: typedef typename STL_CONT::value_type ValueType; virtual void Resort(ValueType*,ValueType*) =0; virtual void Remove(const STL_CONT&) = 0; virtual void AddDataElem(ValueType*,int)=0; virtual void Resize(ValueType*,int)=0; public: // ID serves as a type trait. static int & Id(){ static int id=0; return id; } }; /// CATEntry: first derivation templated on the type of entry /// It implements all the methods to trace and access vector_occ's elements template class CATEntry: public CATBase{ public: typedef typename STL_CONT::value_type ValueType; typedef ENTRY_TYPE EntryType; CATEntry(){if(Id()==0){ Id() = CATBase::Id()+1; CATBase::Id() = Id(); } } static unsigned int Ord(const ValueType *); static ENTRY_TYPE & GetEntry(typename STL_CONT::value_type*pt); static void Insert( STL_CONT & c,bool cond=false ); // insert a vector to trace virtual void Remove( const STL_CONT & c); // remove the container c static void RemoveIfEmpty( const STL_CONT & c); // remove the container c static void Remove( ValueType * v); // remove the container that contains v virtual void Resort( ValueType* old_start, // resort the allocation table ValueType* new_start); // after a container was moved protected: static std::list& AT(){ // tallocation table static std::list allocation_table; return allocation_table; } static bool & UTD(){ static bool upToDate; // true if Lower() and Upper() return upToDate; // are up to date } static ValueType *& Lower() { static ValueType * lower; // pointer to the first element return lower; // of the last container accessed } static ValueType *& Upper() { static ValueType * upper; // pointer to the first element return upper; // if the container next to the last accessed } static typename std::list::iterator & Curr(){ // container that was last accessed static typename std::list::iterator currEntry; return currEntry; } static bool IsTheSameAsLast(const ValueType *pt); // true if pt is in the container // that was accessed last static void Update(const ValueType*); // set Upper() e Lower() static typename std::list::iterator FindBase(const ValueType * pt); // find the container that contains pt (naive) virtual void AddDataElem(typename STL_CONT::value_type * pt,int n);// add n element to the auxiliary data virtual void Resize(typename STL_CONT::value_type * pt,int n);// resize the auxiliary data public: static int & Id(){ // unique identifier of the istance static int id=0; // (used as type trait) return id; } }; // --------------------------- CATEntry: implementation -------------------- // derivazione fatta per i membri Occ (Optional Component Compact) template unsigned int CATEntry:: Ord(const ValueType * pt) { Update(pt); return (pt-Lower()); } template typename std::list::iterator CATEntry:: FindBase(const ValueType * pt) { typename std::list::iterator ite,curr_base,_; ite = AT().begin(); curr_base = AT().end(); for(;ite != AT().end();ite++) if( pt < (*ite).Start()) return curr_base; else curr_base = ite; return curr_base; } template bool CATEntry< STL_CONT, ENTRY_TYPE>:: IsTheSameAsLast(const ValueType * pt) { return ( UTD() && ( !(Lower()> pt)) && (pt < Upper()) ); } template void CATEntry< STL_CONT, ENTRY_TYPE>:: Update(const ValueType * pt) { if(!IsTheSameAsLast(pt)){ typename std::list::iterator lower_ite,upper_ite; lower_ite = FindBase(pt); assert( lower_ite!=AT().end()); Lower() = (*lower_ite).Start(); if( (*lower_ite).Start() == AT().back().Start()) Upper() = (ValueType *) 0xffffffff; else { upper_ite = lower_ite; ++upper_ite; Upper() = (*upper_ite).Start(); } Curr() = lower_ite; UTD() = true; } } template void CATEntry< STL_CONT, ENTRY_TYPE>:: Resort(ValueType* old_start,ValueType* new_start) { AT().sort(); UTD() = false; } template void CATEntry:: Remove( const STL_CONT & c ) { typename std::list::iterator ite; for(ite = AT().begin(); ite != AT().end(); ++ite) if((*ite).C() == &c) { AT().erase(ite); break; } UTD() = false; } template void CATEntry:: RemoveIfEmpty( const STL_CONT & c ) { typename std::list::iterator ite; for(ite = AT().begin(); ite != AT().end(); ++ite) if((*ite).C() == &c) if(!(*ite).Empty()) AT().erase(ite); UTD() = false; } template void CATEntry:: Remove(ValueType * pt) { typename std::list::iterator lower_ite; lower_ite = FindBase(pt); AT().erase(lower_ite); UTD() = false; } template void CATEntry:: Insert( STL_CONT & c,bool cond ) { ENTRY_TYPE entry(c); typename std::list::iterator lower_ite,upper_ite; upper_ite = FindBase( c.Pointer2begin()); bool isIn = (upper_ite != AT().end()); if(isIn){ if((*upper_ite).C() != &c ) ++upper_ite; else return; } lower_ite = AT().insert(upper_ite,entry); lower_ite->Reserve(c.capacity()); lower_ite->Resize(c.size()); UTD() = false; } template ENTRY_TYPE & CATEntry:: GetEntry(typename STL_CONT::value_type*pt){ Update(pt); return *Curr(); } template void CATEntry:: AddDataElem(typename STL_CONT::value_type * pt,int n) { Update(pt); Curr()->Push_back(n); } template void CATEntry:: Resize(typename STL_CONT::value_type * pt,int n) { Update(pt); Curr()->Resize(n); } //-------------------------------------------------------------------------------------------- template class CAT:public CATEntry >{ typedef typename STL_CONT::value_type ValueType; typedef CATEntry > TT; public: static ATTR_TYPE & Get(const ValueType * pt); static CAT * New(); static CAT *& Instance(){ static CAT * instance=NULL; return instance;} }; //---------------------- CAT: implementation--------------------------------------------------- template ATTR_TYPE & CAT:: Get(const ValueType * pt) { int ord = Ord(pt); //int ord = pt- &(* ((*AT().begin()).C()->begin())); se AT() contiene un solo elemento funziona anche cos return TT::Curr()->Data()[ord]; } template CAT * CAT:: New(){ if(Instance()==NULL) { Instance() = new CAT(); } return Instance(); } //--------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------- // TempData implements a handle to one of the vector od data stored in EntryCATMulti template class TempData{ public: TempData(std::vector *d):item(d){}; typedef ATTR_TYPE attr_type; std::vector * Item(){return item;}; std::vector * item; ATTR_TYPE & operator []( typename STL_CONT::value_type * v) { int pos = CATEntry >::Ord(v); return (*item)[pos]; } }; //---------------------------------------------------------------------------------- };//end namespace vcg #endif qutemol/vcg/vcg/container/entries_allocation_table.h0000444000175000017500000001353010767452560021356 0ustar mbamba/**************************************************************************** * VCGLib o o * * Visual and Computer Graphics Library o o * * _ O _ * * Copyright(C) 2004 \/)\/ * * Visual Computing Lab /\/| * * ISTI - Italian National Research Council | * * \ * * All rights reserved. * * * * 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. * * * * 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 (http://www.gnu.org/licenses/gpl.txt) * * for more details. * * * ****************************************************************************/ /**************************************************************************** History $Log: entries_allocation_table.h,v $ Revision 1.9 2008/03/17 11:26:40 ganovelli adding of Curvature, compilation with GCC Revision 1.7 2007/01/18 01:31:12 cignoni Many small syntax changes for mac compiling Revision 1.6 2006/12/03 18:01:01 ganovelli versione compliant vs2005 Revision 1.5 2005/07/06 15:28:11 ganovelli aggiornamento di alcuni path Revision 1.4 2004/04/05 13:53:37 ganovelli Aggiunto typename Revision 1.3 2004/03/31 22:36:44 ganovelli First Working Release (with this comment) /****************************************************************************/ #ifndef __VCGLIB_ENTRIES__ #define __VCGLIB_ENTRIES__ namespace vcg { // EntryCATBase: base class for the entry of the allocation table // templated over the container type template class EntryCATBase{ public: EntryCATBase(STL_CONT & _c):c(_c){}; typename STL_CONT::value_type * Start() const; virtual bool Empty(){return true;}; const STL_CONT * C(); virtual void Push_back(const int &){}; virtual void Reserve(const int & s){}; virtual void Resize(const int & s){}; const bool operator < (const EntryCATBase & other) const; private: STL_CONT & c; }; //EntryCAT: entry for the case of optional core types (matches with CAT) template struct EntryCAT: public EntryCATBase{ typedef ATTR_TYPE attr_type; EntryCAT(STL_CONT & _c) : EntryCATBase(_c){}; std::vector & Data(){return data;} void Push_back(const int & n){ for(int i = 0; i < n ; ++i) data.push_back(ATTR_TYPE());} virtual void Reserve(const int & s){data.reserve(s);}; virtual void Resize(const int & s){data.resize(s);}; private: std::vector data; }; //----------------------EntryCAT: implementation ---------------------------------------- template const bool EntryCATBase:: operator < (const EntryCATBase & other) const{ return (Start() < other.Start()); } template typename STL_CONT::value_type * EntryCATBase::Start()const { return c.Pointer2begin(); } template const STL_CONT * EntryCATBase::C(){ return &c; } // ----------------------------------------------------------------------------------------- // WrapBase: used to implement a list of pointers to std::vector of different types // Wrap: derived from WrapBase (to take the function and from std::vector) struct WrapBase{ virtual void Push_back(const int & n)=0; virtual void Reserve(const int & n)=0; virtual void Resize(const int & n)=0; }; // (note) double hineritance is not necessary, just handy template struct Wrap: public WrapBase,std::vector{ virtual void Push_back(const int & n){for (int i = 0 ; i < n; ++i) push_back( ATTR_TYPE());} virtual void Reserve(const int & n){this->reserve(n);} virtual void Resize(const int & n){this->resize(n);} }; //------------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------- // EntryCATMulti: entry type for multiple user data template class EntryCATMulti: public EntryCATBase{ public: EntryCATMulti(STL_CONT & _c) : EntryCATBase(_c){}; std::list & Data(){return data;} void push_back(const int & n ){ std::list::iterator ite; for(ite = data.begin(); ite != data.end(); ++ite) (*ite)->Push_back(n); } virtual bool Empty(){return data.empty();}; virtual void Reserve(const int & n){ std::list::iterator ite; for(ite = data.begin(); ite != data.end(); ++ite) (*ite)->Reserve(n); }; virtual void Resize(const int & n){ std::list::iterator ite; for(ite = data.begin(); ite != data.end(); ++ite) (*ite)->Resize(n); }; private: std::list< WrapBase * > data; }; //---------------------------------------------------------------------------------- }; // end namespace vcg #endif qutemol/vcg/vcg/container/vector_occ.h0000444000175000017500000001775010767452560016467 0ustar mbamba/**************************************************************************** * VCGLib o o * * Visual and Computer Graphics Library o o * * _ O _ * * Copyright(C) 2004 \/)\/ * * Visual Computing Lab /\/| * * ISTI - Italian National Research Council | * * \ * * All rights reserved. * * * * 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. * * * * 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 (http://www.gnu.org/licenses/gpl.txt) * * for more details. * * * ****************************************************************************/ /**************************************************************************** History $Log: vector_occ.h,v $ Revision 1.6 2008/03/17 11:26:40 ganovelli adding of Curvature, compilation with GCC Revision 1.4 2006/12/04 11:11:07 ganovelli add const to IsEnabledAttribute Revision 1.3 2006/12/03 18:01:01 ganovelli versione compliant vs2005 Revision 1.2 2006/06/08 20:28:38 ganovelli Corretto IsEnabledAttribute Revision 1.1 2005/10/15 16:21:49 ganovelli Working release (compilata solo su MSVC), vector_occ � migrato da component_opt Revision 1.5 2005/07/07 13:33:52 ganovelli some comment Revision 1.4 2004/04/05 18:20:08 ganovelli Aggiunto typename Revision 1.3 2004/03/31 22:36:44 ganovelli First Working Release (with this comment) /****************************************************************************/ #ifndef __VCGLIB_TRACED_VECTOR__ #define __VCGLIB_TRACED_VECTOR__ #include #include #include namespace vcg { /*@{*/ /*! * This class represent a vector_occ. A vector_occ is derived by a std::vector. * The characteristic of a vector_occ is that you can add (at run time) new attributes * to the container::value_type elements contained in the vector. (see the example..) * The position in memory of a traced vector is kept by the Container Allocation Table, * which is a (unique) list of vector_occ positions. */ template class vector_occ: public std::vector{ typedef vector_occ ThisType; typedef std::vector TT; public: vector_occ():std::vector(){id = ID(); ID()=ID()+1; reserve(1);} ~vector_occ(); VALUE_TYPE * Pointer2begin(){ if(TT::empty()) return (VALUE_TYPE *)id; else return &*std::vector::begin(); } std::list < CATBase* > attributes; // override di tutte le funzioni che possono spostare // l'allocazione in memoria del container void push_back(const VALUE_TYPE & v); void pop_back(); void resize(const unsigned int & size); void reserve(const unsigned int & size); /// this function enable the use of an optional attribute (see...) template void EnableAttribute(){ CAT * cat = CAT::New(); cat->Insert(*this); attributes.push_back(cat); } /// this function returns true if the attribute in the template parameter is enabled /// Note: once an attribute is disabled, its data is lost (the memory freed) template bool IsEnabledAttribute() const{ typename std::list < CATBase * >::const_iterator ia; for(ia = attributes.begin(); ia != attributes.end(); ++ia) if((*ia)->Id() == CAT::Id()) return true; return false; } /// this function disable the use of an optional attribute (see...) /// Note: once an attribute is disabled, its data is lost (the memory freed) template void DisableAttribute(){ typename std::list < CATBase * >::iterator ia; for(ia = attributes.begin(); ia != attributes.end(); ++ia) if((*ia)->Id() == CAT::Id()) { (*ia)->Remove(*this); //delete (*ia); attributes.erase(ia); break; } } /// this function create a new attribute of type ATTR_TYPE and return an handle to /// access the value of the attribute. Ex: /// vector_occ tv; /// TempData handle = tv.NewTempData(); /// // now handle[&tv[123]] is the value of integer attribute associate with the position 123 on the vector /// // NOTE: it works also if you do some push_back, resize, pop_back, reserve that cause the relocation /// // of the vector_occ template TempData NewTempData(){ typedef typename CATEntry >::EntryType EntryTypeMulti; CATEntry::Insert(*this); EntryTypeMulti entry = CATEntry::GetEntry(Pointer2begin()); entry.Data().push_back(new Wrap< ATTR_TYPE>); ((Wrap*)entry.Data().back())->reserve(TT::capacity()); ((Wrap*)entry.Data().back())->resize(TT::size()); return TempData((Wrap*) entry.Data().back()); } /// reciprocal of NewTempData template void DeleteTempData(TempData & td){ typedef typename CATEntry >::EntryType EntryTypeMulti; CATEntry::RemoveIfEmpty(*this); EntryTypeMulti entry = CATEntry >::GetEntry(Pointer2begin); entry.Data().remove((Wrap*)td.Item()); delete ((Wrap*)td.Item()); } private: VALUE_TYPE * old_start; int id; static int & ID(){static int id; return id;} void Update(); }; /*@}*/ template void vector_occ::push_back(const VALUE_TYPE & v){ std::vector::push_back(v); Update(); typename std::list < CATBase * >::iterator ia; for(ia = attributes.begin(); ia != attributes.end(); ++ia) (*ia)->AddDataElem(&(*(this->begin())),1); } template void vector_occ::pop_back(){ std::vector::pop_back(); Update(); } template void vector_occ::resize(const unsigned int & size){ std::vector::resize(size); Update(); typename std::list < CATBase * >::iterator ia; for(ia = attributes.begin(); ia != attributes.end(); ++ia) (*ia)-> Resize(&(*(this->begin())),size); } template void vector_occ::reserve(const unsigned int & size){ std::vector::reserve(size); Update(); } template void vector_occ:: Update(){ typename std::list < CATBase * >::iterator ia; if(Pointer2begin() != old_start) for(ia = attributes.begin(); ia != attributes.end(); ++ia) (*ia)->Resort(old_start,Pointer2begin()); old_start = Pointer2begin(); } template vector_occ::~vector_occ(){ typename std::list < CATBase * >::iterator ia; for(ia = attributes.begin(); ia != attributes.end(); ++ia) { (*ia)->Remove(*this); delete *ia; } } }; // end namespace #endif qutemol/vcg/vcg/container/simple_temporary_data.h0000444000175000017500000001045511013256526020705 0ustar mbamba/**************************************************************************** * VCGLib o o * * Visual and Computer Graphics Library o o * * _ O _ * * Copyright(C) 2004 \/)\/ * * Visual Computing Lab /\/| * * ISTI - Italian National Research Council | * * \ * * All rights reserved. * * * * 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. * * * * 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 (http://www.gnu.org/licenses/gpl.txt) * * for more details. * * * ****************************************************************************/ /**************************************************************************** History $Log: simple_temporary_data.h,v $ Revision 1.8 2008/05/16 10:09:26 ganovelli added virtual destructor Revision 1.7 2008/05/16 08:48:49 ganovelli Enable() and Disable() removed. The memory is allocated by the contructor Revision 1.6 2008/05/15 16:35:17 ganovelli Start() Stop() removed. Allocation on creation, disallocaiton on distruction Revision 1.5 2007/02/02 00:01:54 tarini overloaded operator "[]" (once more) to make it possible to index the temp. structure with an iterator Revision 1.4 2005/07/11 13:12:34 cignoni small gcc-related compiling issues (typenames,ending cr, initialization order) Revision 1.3 2004/12/11 15:37:47 ganovelli added one more [], now it is polymorphic, added typenames Revision 1.2 2004/03/31 22:36:44 ganovelli First Working Release (with this comment) ****************************************************************************/ #ifndef __VCGLIB_SIMPLE__ #define __VCGLIB_SIMPLE__ #include namespace vcg { template class SimpleTempDataBase{ public: virtual ~SimpleTempDataBase() {}; SimpleTempDataBase() {}; virtual void Resize(const int & sz) = 0; virtual void Reorder(std::vector & newVertIndex)=0; }; template class SimpleTempData:public SimpleTempDataBase{ public: typedef SimpleTempData SimpTempDataType; typedef ATTR_TYPE AttrType; STL_CONT& c; std::vector data; SimpleTempData(STL_CONT &_c):c(_c){data.reserve(c.capacity());data.resize(c.size());}; SimpleTempData(STL_CONT &_c,ATTR_TYPE val):c(_c){ data.reserve(c.capacity());data.resize(c.size()); typename std::vector::iterator i; for(i = data.begin(); i!= data.end(); ++i) *i = val; }; ~SimpleTempData(){data.clear();} // access to data ATTR_TYPE & operator[](const typename STL_CONT::value_type & v){return data[&v-&*c.begin()];} ATTR_TYPE & operator[](const typename STL_CONT::value_type * v){return data[v-&*c.begin()];} ATTR_TYPE & operator[](const typename STL_CONT::iterator & cont){return data[&(*cont)-&*c.begin()];} ATTR_TYPE & operator[](const int & i){return data[i];} // update temporary data size bool UpdateSize(){ if(data.size() != c.size()) { data.resize(c.size()); return false; } return true; } void Resize(const int & sz){ data.resize(sz); } void Reorder(std::vector & newVertIndex){ for(unsigned int i = 0 ; i < data.size(); ++i){ if( newVertIndex[i] != std::numeric_limits::max()) data[newVertIndex[i]] = data[i]; } } }; }; // end namespace vcg #endif qutemol/vcg/vcg/complex/0000755000175000017500000000000011633404241013627 5ustar mbambaqutemol/vcg/vcg/complex/tetramesh/0000755000175000017500000000000011633404241015623 5ustar mbambaqutemol/vcg/vcg/complex/tetramesh/subset.h0000444000175000017500000001143610720526750017312 0ustar mbamba /**************************************************************************** * VCGLib o o * * Visual and Computer Graphics Library o o * * _ O _ * * Copyright(C) 2004 \/)\/ * * Visual Computing Lab /\/| * * ISTI - Italian National Research Council | * * \ * * All rights reserved. * * * * 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. * * * * 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 (http://www.gnu.org/licenses/gpl.txt) * * for more details. * * * ****************************************************************************/ /**************************************************************************** History $Log: subset.h,v $ Revision 1.5 2007/11/20 09:50:32 ganovelli compilation with gcc Revision 1.4 2005/02/08 14:36:20 turini Warnings Correction Revision 1.3 2004/05/17 08:22:45 turini Minor Changes and Now Use STLContainer of Tetrahedron Pointers. Revision 1.2 2004/05/14 15:51:47 turini Adjusted VCG Style Revision 1.1 2004/05/14 15:43:41 turini Initial Commit ****************************************************************************/ #ifndef __VCGLIB_TETRASUBSET #define __VCGLIB_TETRASUBSET namespace vcg { namespace tetra { /** \addtogroup tetramesh */ /*@{*/ template struct InsertedVT { typedef I_TETRAMESH_TYPE ITetraMeshType; typedef typename ITetraMeshType::VertexPointer VertexPointer; typedef typename ITetraMeshType::TetraPointer TetraPointer; InsertedVT(VertexPointer _v, TetraPointer _t, int _z) : v(_v), t(_t), z(_z) {} VertexPointer v; TetraPointer t; int z; const bool operator <(const InsertedVT & o) { return (v void SubSet(S_TETRAMESH_TYPE & m, STL_CONT & subSet) { std::vector< InsertedVT > newVertices; typename STL_CONT::iterator pfi; newVertices.clear(); for(pfi=subSet.begin(); pfi!=subSet.end(); ++pfi) m.tetra.push_back(*(*pfi)); typename S_TETRAMESH_TYPE::TetraIterator fi; for(fi=m.tetra.begin(); fi!=m.tetra.end(); ++fi) { newVertices.push_back(InsertedVT((*fi).V(0), &(*fi), 0)); newVertices.push_back(InsertedVT((*fi).V(1), &(*fi), 1)); newVertices.push_back(InsertedVT((*fi).V(2), &(*fi), 2)); newVertices.push_back(InsertedVT((*fi).V(3), &(*fi), 3)); } std::sort(newVertices.begin(), newVertices.end()); typename std::vector< InsertedVT >::iterator curr,next; int pos=0; curr=next=newVertices.begin(); while(next!=newVertices.end()) { if((*curr)!=(*next)) pos++; (*next).t->V((*next).z)=(typename S_TETRAMESH_TYPE::VertexPointer)pos; curr=next; next++; } typename std::vector< InsertedVT >::iterator newE=std::unique(newVertices.begin(), newVertices.end()); for(curr=newVertices.begin(); curr!=newE; ++curr) m.vert.push_back(*((*curr).v)); for(fi=m.tetra.begin(); fi!=m.tetra.end(); ++fi) { (*fi).V(0)=&(m.vert[(int)(*fi).V(0)]); (*fi).V(1)=&(m.vert[(int)(*fi).V(1)]); (*fi).V(2)=&(m.vert[(int)(*fi).V(2)]); (*fi).V(3)=&(m.vert[(int)(*fi).V(3)]); } m.vn=(int)m.vert.size(); m.tn=(int)m.tetra.size(); } /*@}*/ } // End namespace } // End namespace #endif qutemol/vcg/vcg/complex/tetramesh/edge_collapse.h0000444000175000017500000006320310347255253020574 0ustar mbamba/**************************************************************************** * VCGLib o o * * Visual and Computer Graphics Library o o * * _ O _ * * Copyright(C) 2004 \/)\/ * * Visual Computing Lab /\/| * * ISTI - Italian National Research Council | * * \ * * All rights reserved. * * * * 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. * * * * 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 (http://www.gnu.org/licenses/gpl.txt) * * for more details. * * * ****************************************************************************/ /**************************************************************************** History ****************************************************************************/ #ifndef __VCG_TETRA_EDGE_COLLAPSE #define __VCG_TETRA_EDGE_COLLAPSE #include #include #include namespace vcg{ namespace tetra{ /** \addtogroup tetramesh */ /*@{*/ /// This Class is used for the edge collapse template class EdgeCollapse { public: /// The tetrahedral mesh type typedef TETRA_MESH_TYPE TetraMeshType; /// The tetrahedron type typedef typename TetraMeshType::TetraType TetraType; /// The vertex type typedef typename TetraType::VertexType VertexType; /// The vertex iterator type typedef typename TetraMeshType::VertexIterator VertexIterator; /// The tetra iterator type typedef typename TetraMeshType::TetraIterator TetraIterator; /// The coordinate type typedef typename TetraType::VertexType::CoordType CoordType; /// The scalar type typedef typename TetraMeshType::VertexType::ScalarType ScalarType; ///the container of tetrahedron type typedef typename TetraMeshType::TetraContainer TetraContainer; ///the container of vertex type typedef typename TetraMeshType::VertexContainer VertexContainer; /// The HEdgePos type typedef Pos PosType; /// The HEdgePos Loop type typedef PosLoop PosLType; /// The topology updater type typedef typename vcg::tetra::UpdateTetraTopology Topology; ///the normal updater type typedef typename vcg::tetra::UpdateNormals UpdateNormals; /// Default Constructor EdgeCollapse() { }; ~EdgeCollapse() { }; private: typedef pair FacePair; struct Face { VertexType* v[3]; Face( VertexType* a, VertexType* b,VertexType* c) { assert((a!=b)&&(b!=c)&&(a!=c)); v[0]=a; v[1]=b; v[2]=c; sort(v,v+3); } const bool operator <(const Face & f) const { return ((v[0]==f.v[0])?((v[1]==f.v[1])?(v[2] v0; std::vector v1; std::vector v0_U_v1; std::vector no_E; std::vector E; std::vector indexE; std::vector indexv0; std::vector indexv1; void clear() { v0.clear(); v1.clear(); v0_U_v1.clear(); no_E.clear(); E.clear(); indexE.clear(); indexv0.clear(); indexv1.clear(); } }; static map & _EdgeMark(){ static map em; return em; }; static map & _FaceMark(){ static map fm; return fm; } static VertexType &_DummyV(){ static VertexType _dv; return _dv; } static TetraSets &_Sets(){ static TetraSets _s; return _s; } ///select the 2 faces that does not share the edge static FacePair _FindNoEdgeFace(TetraType *t,int edge) { //as first I find the 2 faces on the opposite sides of the egde int fa0=Tetra::FofE(edge,0); int fa1=Tetra::FofE(edge,1); //then find the faces that remain int fa2=(fa0+1)%4; while ((fa2==fa0)||(fa2==fa1)) { fa2=(fa2+1)%4; } int fa3=(fa2+1)%4; while ((fa3==fa0)||(fa3==fa1)||(fa3==fa2)) { fa3=(fa3+1)%4; } return FacePair(fa2,fa3); } #ifdef _DEBUG static void _AssertingVolume(TetraType *t) { //assert(t->ComputeVolume() >0); assert(vcg::ComputeVolume(*t)>0); } #endif ///collpse de edge specified by pos (the first vertex on edge remain) static int _Collapse(PosType p,CoordType NewP) { int n_deleted=0; vector To_Del; VertexType *Vrem=(p.T()->V(Tetra::VofE(p.E(),0))); VertexType *Vdel=(p.T()->V(Tetra::VofE(p.E(),1))); //Vrem->P()=(Vrem->P()*alfa)+(Vdel->P()*(1.f-alfa)); Vrem->P()=NewP; PosLType pos(p.T(),p.F(),p.E(),p.V()); pos.Reset(); To_Del.reserve(40); To_Del.clear(); while (!pos.LoopEnd()) { //get the two faces that doesn't share the edge FacePair fp=_FindNoEdgeFace(pos.T(),pos.E()); int fa0=fp.first; int fa1=fp.second; //now set the T-T topology on that faces TetraType *tleft=pos.T()->TTp(fa0); TetraType *tright=pos.T()->TTp(fa1); int ileft=pos.T()->TTi(fa0); int iright=pos.T()->TTi(fa1); //in this case I cannot do the collapse assert (!((pos.T()==tleft)&&(pos.T()==tright))); //case no one is extern face if ((!pos.T()->IsBorderF(fa0))&&(!pos.T()->IsBorderF(fa1))) //connect the 2 tetrahedrons Topology::_AttachTTTopology(tleft,ileft,tright,iright); else //case f2 is an extern face if (pos.T()->IsBorderF(fa0)) { tright->TTp(iright)=tright; tright->TTi(iright)=iright; } else //case fa1 is an extern face //if ((pos.T()->IsBorderF(fa3)) { tleft->TTp(ileft)=tleft; tleft->TTi(ileft)=ileft; } //end setting T-T topology //setting the V-T topology //i remove the tetrahedrons that have the edge // to collapse Topology::DetachVTTopology(pos.T()); //end setting the V-T topology To_Del.push_back(pos.T()); pos.NextT(); n_deleted++; // tm.tn--; } //delting old tetrahedrons typename vector::iterator ti; for (ti=To_Del.begin();tiSetD(); //now I cycle on the tetrahedron that had the old vertex //reassegning the new one. VTIterator VTi(Vdel->VTb(),Vdel->VTi()); while (!VTi.End()) { TetraType *T_Change=VTi.Vt(); int index=VTi.Vi(); //VTi++; //assegning the vertex that remain T_Change->V(index)=Vrem; Topology::DetachVTTopology(Vdel,T_Change); Topology::InsertVTTopology(Vrem,index,T_Change); //that's cause i restart everytime in the chain //from the vertex VTi.Vt()=Vdel->VTb(); VTi.Vi()=Vdel->VTi(); #ifdef _DEBUG _AssertingVolume(T_Change); #endif } if (Vdel->IsB()) Vrem->SetB(); //set as deleted the vertex Vdel->SetD(); return n_deleted; } static void orMarkE(Edge E,char M) { typename map::iterator EI; EI=_EdgeMark().find(E); if (EI==_EdgeMark().end()) _EdgeMark().insert (pair(E,M)); else (*EI).second|=M; } static bool isMarkedE(Edge E,char M) { typename map::iterator EI; EI=_EdgeMark().find(E); if (EI==_EdgeMark().end()) return false; else return (((*EI).second & M)!=0); } static void orMarkF(Face F,char M) { typename map< Face,char>::iterator FI; FI=_FaceMark().find(F); if (FI==_FaceMark().end()) _FaceMark().insert (pair(F,M)); else (*FI).second|=M; } static bool isMarkedF(Face F,char M) { typename map::iterator FI; FI=_FaceMark().find(F); if (FI==_FaceMark().end()) return false; else return (((*FI).second & M)!=0); } ///verify the link conditions on faces static bool _LinkConditionsF(PosType pos) { const int LINK_V0 = 0x00000001; const int LINK_EE = 0x00000002; _EdgeMark().clear(); // Mark edges of ve0 typename vector< TetraType *>::iterator ti=_Sets().v0.begin(); typename vector< char >::iterator en=_Sets().indexv0.begin(); VertexType *v0=(*ti)->V(*en); while (ti!=_Sets().v0.end()) { assert(v0==(*ti)->V(*en)); //put dummy face for (int f=0;f<3;f++) { int f_test=Tetra::FofV((*en),f); if ((*ti)->IsBorderF(f_test)) { orMarkF(Face((*ti)->V(Tetra::VofF(f_test,0)),(*ti)->V(Tetra::VofF(f_test,1)),&_DummyV()),LINK_V0); orMarkF(Face((*ti)->V(Tetra::VofF(f_test,1)),(*ti)->V(Tetra::VofF(f_test,2)),&_DummyV()),LINK_V0); orMarkF(Face((*ti)->V(Tetra::VofF(f_test,2)),(*ti)->V(Tetra::VofF(f_test,0)),&_DummyV()),LINK_V0); } } ti++; en++; } ti=_Sets().E.begin(); en=_Sets().indexE.begin(); //mark them as intersection while (ti!=_Sets().E.end()) { //faces on the edge int f0=Tetra::FofE((*en),0); int f1=Tetra::FofE((*en),1); if ((*ti)->IsBorderF(f0)) { orMarkF(Face((*ti)->V(Tetra::VofF(f0,0)),(*ti)->V(Tetra::VofF(f0,1)),&_DummyV()),LINK_EE); orMarkF(Face((*ti)->V(Tetra::VofF(f0,1)),(*ti)->V(Tetra::VofF(f0,2)),&_DummyV()),LINK_EE); orMarkF(Face((*ti)->V(Tetra::VofF(f0,2)),(*ti)->V(Tetra::VofF(f0,0)),&_DummyV()),LINK_EE); } if ((*ti)->IsBorderF(f1)) { orMarkF(Face((*ti)->V(Tetra::VofF(f1,0)),(*ti)->V(Tetra::VofF(f1,1)),&_DummyV()),LINK_EE); orMarkF(Face((*ti)->V(Tetra::VofF(f1,1)),(*ti)->V(Tetra::VofF(f1,2)),&_DummyV()),LINK_EE); orMarkF(Face((*ti)->V(Tetra::VofF(f1,2)),(*ti)->V(Tetra::VofF(f1,0)),&_DummyV()),LINK_EE); } ti++; en++; } //and at the end I verify if the intersection is equal to the star of the edge ti=_Sets().v1.begin(); en=_Sets().indexv1.begin(); VertexType *v1=(*ti)->V(*en); while (ti!=_Sets().v1.end()) { assert(v1==(*ti)->V(*en)); //dummy edges control for (int f=0;f<3;f++) { int f_test=Tetra::FofV((*en),f); if ((*ti)->IsBorderF(f_test)) { //control all the 3 edges Face f_test0=Face((*ti)->V(Tetra::VofF(f_test,0)),(*ti)->V(Tetra::VofF(f_test,1)),&_DummyV()); Face f_test1=Face((*ti)->V(Tetra::VofF(f_test,1)),(*ti)->V(Tetra::VofF(f_test,2)),&_DummyV()); Face f_test2=Face((*ti)->V(Tetra::VofF(f_test,2)),(*ti)->V(Tetra::VofF(f_test,0)),&_DummyV()); if (((isMarkedF(f_test0,LINK_V0))&&(!isMarkedF(f_test0,LINK_EE)))|| ((isMarkedF(f_test1,LINK_V0))&&(!isMarkedF(f_test1,LINK_EE)))|| ((isMarkedF(f_test2,LINK_V0))&&(!isMarkedF(f_test2,LINK_EE)))) { // FAIL::LKF(); return false; } } } ti++; en++; } return true; } ///verify the link conditions on edges static bool _LinkConditionsE(PosType pos) { const int LINK_V0 = 0x00000001; const int LINK_EE = 0x00000002; _FaceMark().clear(); // Mark edges of ve0 typename vector< TetraType *>::iterator ti=_Sets().v0.begin(); typename vector< char >::iterator en=_Sets().indexv0.begin(); while (ti!=_Sets().v0.end()) { //put dummy edge for (int f=0;f<3;f++) { int f_test=Tetra::FofV((*en),f); if ((*ti)->IsBorderF(f_test)) { orMarkE(Edge((*ti)->V(Tetra::VofF(f_test,0)),&_DummyV()),LINK_V0); orMarkE(Edge((*ti)->V(Tetra::VofF(f_test,1)),&_DummyV()),LINK_V0); orMarkE(Edge((*ti)->V(Tetra::VofF(f_test,2)),&_DummyV()),LINK_V0); } } ti++; en++; } ti=_Sets().E.begin(); en=_Sets().indexE.begin(); //mark them as intersection while (ti!=_Sets().E.end()) { //faces on the edge int f0=Tetra::FofE((*en),0); int f1=Tetra::FofE((*en),1); if ((*ti)->IsBorderF(f0)) { orMarkE(Edge((*ti)->V(Tetra::VofF(f0,0)),&_DummyV()),LINK_EE); orMarkE(Edge((*ti)->V(Tetra::VofF(f0,1)),&_DummyV()),LINK_EE); orMarkE(Edge((*ti)->V(Tetra::VofF(f0,2)),&_DummyV()),LINK_EE); } if ((*ti)->IsBorderF(f1)) { orMarkE(Edge((*ti)->V(Tetra::VofF(f1,0)),&_DummyV()),LINK_EE); orMarkE(Edge((*ti)->V(Tetra::VofF(f1,1)),&_DummyV()),LINK_EE); orMarkE(Edge((*ti)->V(Tetra::VofF(f1,2)),&_DummyV()),LINK_EE); } ti++; en++; } //and at the end I verify if the intersection is equal to the star of the edge ti=_Sets().v1.begin(); en=_Sets().indexv1.begin(); while (ti!=_Sets().v1.end()) { //dummy edges control for (int f=0;f<3;f++) { int f_test=Tetra::FofV((*en),f); if ((*ti)->IsBorderF(f_test)) { //control all the 3 edges Edge e_test0=Edge((*ti)->V(Tetra::VofF(f_test,0)),&_DummyV()); Edge e_test1=Edge((*ti)->V(Tetra::VofF(f_test,1)),&_DummyV()); Edge e_test2=Edge((*ti)->V(Tetra::VofF(f_test,2)),&_DummyV()); if (((isMarkedE(e_test0,LINK_V0))&&(!isMarkedE(e_test0,LINK_EE)))|| ((isMarkedE(e_test1,LINK_V0))&&(!isMarkedE(e_test1,LINK_EE)))|| ((isMarkedE(e_test2,LINK_V0))&&(!isMarkedE(e_test2,LINK_EE)))) { // FAIL::LKE(); return false; } } } ti++; en++; } return true; } static bool _QuickConditions(PosType pos) { VertexType *v0=pos.T()->V(Tetra::VofE(pos.E(),0)); VertexType *v1=pos.T()->V(Tetra::VofE(pos.E(),1)); //if the two vertices are of border and the edge is not a border edge //we can do it. bool border0=v0->IsB(); bool border1=v1->IsB(); bool bordere=Topology::IsExternEdge(pos.T(),pos.E()); //first case vertex external and edge internal if ((border0 && border1)&&(!bordere)) { return false; } else /// look if the 2 other faces that don't share the vertex are external on not { typename vector< TetraType *>::iterator ti=_Sets().E.begin(); typename vector< char >::iterator en=_Sets().indexE.begin(); //mark them as intersection while (ti!=_Sets().E.end()) { //get the two faces that doesn't share the edge FacePair fp=_FindNoEdgeFace(pos.T(),pos.E()); int fa0=fp.first; int fa1=fp.second; //now set the T-T topology on that faces TetraType *tleft=pos.T()->TTp(fa0); TetraType *tright=pos.T()->TTp(fa1); int ileft=pos.T()->TTi(fa0); int iright=pos.T()->TTi(fa1); //in this case I cannot do the collapse if (((pos.T()==tleft)&&(pos.T()==tright))) { return false; } ti++; en++; } } return true; } ///verify the link conditions on vertices static bool _LinkConditionsV() { const int LINK_V0 = VertexType::NewBitFlag(); const int LINK_V1 = VertexType::NewBitFlag(); const int LINK_EE = VertexType::NewBitFlag(); const int NOT_LINKED = ~(LINK_V0 | LINK_V1 | LINK_EE); _DummyV().Flags() &= NOT_LINKED; VertexType *vt0; VertexType *vt1; VertexType *vt2; VertexType *vt3; typename vector< TetraType *>::iterator ti=_Sets().v0_U_v1.begin(); //reset all link flags while (ti!=_Sets().v0_U_v1.end()) { for(int i=0;i<4;i++) (*ti)->V(i)->Flags() &= NOT_LINKED; ti++; } //also in the ones that appartain to the edge typename vector< char >::iterator en; ti=_Sets().E.begin(); en=_Sets().indexE.begin(); //reset all link flags for intersection and in the same //time mark them as intersection while (ti!=_Sets().E.end()) { for(int i=0;i<4;i++) { (*ti)->V(i)->Flags() &= NOT_LINKED; (*ti)->V(i)->Flags() |= LINK_EE; } //dummy vertex //faces on the edge int f0=Tetra::FofE((*en),0); int f1=Tetra::FofE((*en),1); if (((*ti)->IsBorderF(f0))||((*ti)->IsBorderF(f1))) _DummyV().Flags() |= LINK_EE; ti++; en++; } // Mark vertices of ve0 ti=_Sets().v0.begin(); en=_Sets().indexv0.begin(); while (ti!=_Sets().v0.end()) { for(int i=0;i<4;i++) (*ti)->V(i)->Flags() |= LINK_V0; //dummy faces on the vertex int f0=Tetra::FofV((*en),0); int f1=Tetra::FofV((*en),1); int f2=Tetra::FofV((*en),2); if (((*ti)->IsBorderF(f0))||((*ti)->IsBorderF(f1))||((*ti)->IsBorderF(f2))) _DummyV().Flags() |= LINK_V0; ti++; en++; } //and at the end I verify if the intersection is equal to the star of the edge bool correct=true; ti=_Sets().v1.begin(); en=_Sets().indexv1.begin(); while (ti!=_Sets().v1.end()) { vt0=(*ti)->V(0); vt1=(*ti)->V(1); vt2=(*ti)->V(2); vt3=(*ti)->V(3); if ((vt0->Flags()& LINK_V0)&&(!(vt0->Flags()& LINK_EE))) correct=false; else if ((vt1->Flags()& LINK_V0)&&(!(vt1->Flags()& LINK_EE))) correct=false; else if ((vt2->Flags()& LINK_V0)&&(!(vt2->Flags()& LINK_EE))) correct=false; else if ((vt3->Flags()& LINK_V0)&&(!(vt3->Flags()& LINK_EE))) correct=false; //dummy vertex control int f0=Tetra::FofV((*en),0); int f1=Tetra::FofV((*en),1); int f2=Tetra::FofV((*en),2); if (((*ti)->IsBorderF(f0))||((*ti)->IsBorderF(f1))||((*ti)->IsBorderF(f2))) if ((_DummyV().Flags()& LINK_V0)&&(!(_DummyV().Flags()& LINK_EE))) correct=false; if (!correct) { VertexType::DeleteBitFlag(LINK_EE); VertexType::DeleteBitFlag(LINK_V1); VertexType::DeleteBitFlag(LINK_V0); // FAIL::LKV(); return (false); } en++; ti++; } VertexType::DeleteBitFlag(LINK_EE); VertexType::DeleteBitFlag(LINK_V1); VertexType::DeleteBitFlag(LINK_V0); return true; } ///verify the flip condition static bool _FlipCondition(PosType pos,CoordType NewP) { int edge=pos.E(); VertexType *ve0=pos.T()->V(Tetra::VofE(edge,0)); VertexType *ve1=pos.T()->V(Tetra::VofE(edge,1)); CoordType oldpos0; CoordType oldpos1; typename vector< TetraType *>::iterator ti=_Sets().no_E.begin(); //saving old position oldpos0 = ve0->P(); oldpos1 = ve1->P(); //assegning new position ve0->P() =NewP; ve1->P() =NewP; while (ti!=_Sets().no_E.end()) { assert(!(*ti)->IsD()); assert((((*ti)->V(0)==ve0)||((*ti)->V(1)==ve0)||((*ti)->V(2)==ve0)||((*ti)->V(3)==ve0))^ (((*ti)->V(0)==ve1)||((*ti)->V(1)==ve1)||((*ti)->V(2)==ve1)||((*ti)->V(3)==ve1))); if (vcg::ComputeVolume(**ti)<=0) { // FAIL::VOL(); ve0->P()=oldpos0; ve1->P()=oldpos1; return false; } ti++; } //reset initial value ve0->P()=oldpos0; ve1->P()=oldpos1; return true; } ///update the normal of the modified tetrahedrons ond the normal of the vertex that remain after collapse static void _InitTetrahedronValues(VertexType* v) { VTIterator VTi= VTIterator(v->VTb(),v->VTi()); while (!VTi.End()) { if (TetraType::HasTetraQuality()) { VTi.Vt()->ComputeAspectRatio(); } if (TetraType::HasTetraNormal()) { VTi.Vt()->ComputeNormal(); } ++VTi; } VTi.Vt()=v->VTb(); VTi.Vi()=v->VTi(); while (!VTi.End()) { for (int i=0;i<4;i++) { if (VTi.Vt()->V(i)->IsB()) { if (VertexType::HasNormal()) UpdateNormals::PerVertex(VTi.Vt()->V(i)); } } ++VTi; } } public: /// clean everything static void Reset(){ _EdgeMark().clear(); _FaceMark().clear(); _Sets().clear(); _DummyV().ClearFlags(); } ///Return the aspect Ratio media of the tetrahedrons ///that share the adge to collapse static ScalarType AspectRatioCollapsed(PosType p) { //PosL pos=PosL(p.T(),p.F(),p.E(),p.V()); PosLoop pos=PosLoop(p.T(),p.F(),p.E(),p.V()); pos.Reset(); int num=0; ScalarType ratio_media=0.f; while(!pos.end()) { ratio_media+=pos.T()->AspectRatio(); pos.NextT(); num++; } ratio_media=ratio_media/num; return (ratio_media); } ///check the topologycal preserving conditions for the collapse indicated by pos static bool CheckPreconditions(PosType pos,CoordType NewP) { VertexType *v0=pos.T()->V(Tetra::VofE(pos.E(),0)); VertexType *v1=pos.T()->V(Tetra::VofE(pos.E(),1)); //if the two vertices are of border and the edge is not a border edge //we can do it. bool border0=v0->IsB(); bool border1=v1->IsB(); bool bordere=Topology::IsExternEdge(pos.T(),pos.E()); if (!_QuickConditions(pos)) { //FAIL::BOR(); return false; } // //first case vertex external and edge internal //if ((border0 && border1)&&(!bordere)) //{ // //FAIL::BOR(); // return false; //} else //if both vertex are internal so is enougth to verify flip conditions if ((!border0) && (!border1)) return (_FlipCondition(pos,NewP)); else //if the edge is internal is enougth to verify link condition on vertex if (!bordere) return((_FlipCondition(pos,NewP))&&(_LinkConditionsV())); else //at the end if trh edge is on the border we must verify also with the complete test return ((_FlipCondition(pos,NewP))&&(_LinkConditionsV())&&(_LinkConditionsE(pos))&&(_LinkConditionsF(pos))); //return false; } ///return the sum of volumes of the union of stars on vertices (the original volume of tetrahedrons) static ScalarType VolumeOriginal() { typename vector< TetraType *>::iterator ti=_Sets().v0_U_v1.begin(); ScalarType vol=0; while (ti!=_Sets().v0_U_v1.end()) { vol+=(*ti)->Volume(); ti++; } return vol; } ///Calculate the volume on the vertex resulting after collapse... static ScalarType VolumeSimulateCollapse(PosType Pos,CoordType &newP) { VertexType *Vrem=(Pos.T()->V(Tetra::VofE(Pos.E(),0))); VertexType *Vdel=(Pos.T()->V(Tetra::VofE(Pos.E(),1))); if (Vrem!=Pos.T()->V(Pos.V())) swap(Vdel,Vrem); ScalarType vol=0; CoordType oldpos = Vrem->P(); //move vertex that remain in the new position Vrem->P() = newP; typename vector< TetraType *>::iterator ti=_Sets().no_E.begin(); while (ti!=_Sets().no_E.end()) { /* Tetra3 T=Tetra3(); T.P0(0)=(*ti)->V(0)->cP(); T.P1(0)=(*ti)->V(1)->cP(); T.P2(0)=(*ti)->V(2)->cP(); T.P3(0)=(*ti)->V(3)->cP(); vol+=T.ComputeVolume(); */ // vol+= vcg::ComputeVolume(*((Tetra3*)&*ti)); vol+= vcg::ComputeVolume(**ti); ti++; } Vrem->P()=oldpos; return vol; } ///finds sets used for all test in edge collapse static void FindSets(vcg::tetra::Pos pos) { _Sets().clear(); int size=40; _Sets().v0.reserve(size); _Sets().indexv0.reserve(size); _Sets().v1.reserve(size); _Sets().indexv1.reserve(size); _Sets().v0_U_v1.reserve(size*2); _Sets().no_E.reserve(size*2); _Sets().E.reserve(size); _Sets().indexE.reserve(size); int edge =pos.E(); VertexType *ve0=pos.T()->V(Tetra::VofE(edge,0)); VertexType *ve1=pos.T()->V(Tetra::VofE(edge,1)); // put all tetrahedrons in the first one vector and in the union VTIterator vf0(ve0->VTb(),ve0->VTi()); while (!vf0.End()) { //set of ve0 _Sets().v0.push_back(vf0.Vt()); _Sets().indexv0.push_back(vf0.Vi()); //set of union _Sets().v0_U_v1.push_back(vf0.Vt()); //set of union minus intersection if ((vf0.Vt()->V(0)!=ve1)&&(vf0.Vt()->V(1)!=ve1)&&(vf0.Vt()->V(2)!=ve1)&&(vf0.Vt()->V(3)!=ve1)) _Sets().no_E.push_back(vf0.Vt()); ++vf0; } //second vertex iteration vf0.Vt()=ve1->VTb(); vf0.Vi()=ve1->VTi(); while (!vf0.End()) { //set of ve1 _Sets().v1.push_back(vf0.Vt()); _Sets().indexv1.push_back(vf0.Vi()); //set of union _Sets().v0_U_v1.push_back(vf0.Vt()); //set of union minus intersection if ((vf0.Vt()->V(0)!=ve0)&&(vf0.Vt()->V(1)!=ve0)&&(vf0.Vt()->V(2)!=ve0)&&(vf0.Vt()->V(3)!=ve0)) _Sets().no_E.push_back(vf0.Vt()); ++vf0; } //erase duplicated tetrahedrons from the union set sort(_Sets().v0_U_v1.begin(),_Sets().v0_U_v1.end()); unique(_Sets().v0_U_v1.begin(),_Sets().v0_U_v1.end()); //now compute the intersection PosLType PL(pos.T(),pos.F(),pos.E(),pos.V()); //mark the vertex on the edge while (!PL.LoopEnd()) { _Sets().E.push_back(PL.T()); _Sets().indexE.push_back(PL.E()); PL.NextT(); } } ///do the collapse on the edge in postype p static int DoCollapse(PosType p,CoordType newP) { VertexType *v=p.T()->V(p.V()); assert(p.T()->HasVTAdjacency()); int n_del=_Collapse(p,newP); _InitTetrahedronValues(v); return n_del; } }; }//end namespace }//end namespace #endif qutemol/vcg/vcg/complex/tetramesh/edge_split.h0000444000175000017500000003206510171202652020115 0ustar mbamba/**************************************************************************** * VCGLib o o * * Visual and Computer Graphics Library o o * * _ O _ * * Copyright(C) 2004 \/)\/ * * Visual Computing Lab /\/| * * ISTI - Italian National Research Council | * * \ * * All rights reserved. * * * * 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. * * * * 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 (http://www.gnu.org/licenses/gpl.txt) * * for more details. * * * ****************************************************************************/ /**************************************************************************** History ****************************************************************************/ #ifndef __VCG_TETRA_EDGE_SPLIT #define __VCG_TETRA_EDGE_SPLIT #include #include #include #include namespace vcg{ namespace tetra{ /** \addtogroup tetramesh */ /*@{*/ /// This Class is used for split the edges template class EdgeSplit { public: /// The tetrahedral mesh type typedef typename TETRA_MESH_TYPE TetraMeshType; /// The tetrahedron type typedef typename TetraMeshType::TetraType TetraType; /// The vertex type typedef typename TetraType::VertexType VertexType; /// The vertex iterator type typedef typename TetraMeshType::VertexIterator VertexIterator; /// The tetra iterator type typedef typename TetraMeshType::TetraIterator TetraIterator; /// The coordinate type typedef typename TetraType::VertexType::CoordType CoordType; ///the container of tetrahedron type typedef typename TetraMeshType::TetraContainer TetraContainer; ///the container of vertex type typedef typename TetraMeshType::VertexContainer VertexContainer; /// The HEdgePos type typedef PosLoop PosType; /// The topology updater type typedef vcg::tetra::UpdateTetraTopology Topology; /// The allocator type typedef vcg::tetra::Allocator TetraAllocator; /// Default Constructor EdgeSplit() { }; ~EdgeSplit() { }; private: ///the tetrahedron that must mark as Deleted after substitution TetraType* _toDel[30]; ///The number of tetrahedrons that are substituted int _nT; Topology _Topo; ///add a vertex into the edge at distance alfa ( 0 All= Allocator(); VertexIterator vn=All.AddVertices(tm,1); vn->Flags()=0; vn->VTb()=NULL; vn->VTi()=-1; vn->P()=(v0->P()*alfa)+(v1->P()*(1.0f-alfa)); return (&(*vn)); } ///set the default v-t topology void _SetDefultVTTopology(TetraType *t) { unsigned int j; for (j=0;j<4;j++) { t->TVp(j) = NULL; t->TVi(j) = -1; } } /// Transform the vertex index according to rotation of the tetraedron /// that trasform it in the basic case static int _GetMapVertEdgeRot(const int &indexE,const int &indexV) { static int mapvertedgerot[12][4]={ {0,3,1,2}, {0,1,2,3}, {0,2,3,1}, {1,3,2,0}, {1,0,3,2}, {2,1,3,0}, {1,2,0,3}, {2,3,0,1}, {3,1,0,2}, {2,0,1,3}, {3,2,1,0}, {3,0,2,1}, }; assert ((indexE<12)&&(indexV<4)); return mapvertedgerot[indexE][indexV]; } /// Transform the face index according to rotation of the tetraedron /// that trasform it in the basic case static int _GetMapFaceEdgeRot(const int &indexE,const int &indexF) { static int mapfaceedgerot[12][4]={ {1,2,0,3}, {0,1,2,3}, {2,0,1,3}, {3,1,0,2}, {1,0,3,2}, {3,0,2,1}, {0,3,1,2}, {2,3,0,1}, {1,3,2,0}, {0,2,3,1}, {3,2,1,0}, {2,1,3,0}, }; assert ((indexE<12)&&(indexF<4)); return mapfaceedgerot[indexE][indexF]; } /// Returns the rotation sense during the loop on the edge to divide /// according to rotation of the tetraedron that trasform it in the basic case static int _GetDirRot(int indexE,int indexF) { static int mapfaceedgerot[12][4]={ {2,0,-1,-1}, {0,-1,2,-1}, {-1,2,0,-1}, {2,-1,-1,0}, {-1,0,-1,2}, {-1,-1,2,0}, {0,2,-1,-1}, {2,-1,0,-1}, {-1,0,2,-1}, {0,-1,-1,2}, {-1,2,-1,0}, {-1,-1,0,2}, }; assert ((indexE<12)&&(indexF<4)); return mapfaceedgerot[indexE][indexF]; } ///Built an Half edge on tetrahedron t using edge edge PosType _FindPos(TetraType *t,int edge) { int face0=Tetra::FofE(edge,0); int ve0=Tetra::VofE(edge,0); PosType pos(t,face0,edge,ve0); return pos; } ///Assert the right order of vertex that compose the tetrahedron void _AssertOrder(TetraType *t,VertexType *v0,VertexType *v1,VertexType *v2,VertexType *v3) { assert(t->V(0)==v0); assert(t->V(1)==v1); assert(t->V(2)==v2); assert(t->V(3)==v3); } ///Connect trought Tetrahedron-Tetrahedron Topology t0 and t1 with faces i0 and i1 void _ConnectTTTopology(TetraType *t0,int i0,TetraType *t1,int i1) { assert((i0>=0)&&(i0<4)); assert((i1>=0)&&(i1<4)); assert((!t0->IsD())&&(!t1->IsD())); t0->TTp(i0)=t1; t0->TTi(i0)=i1; t1->TTp(i1)=t0; t1->TTi(i1)=i0; assert( (((t0->TTp(i0))->TTp(t0->TTi(i0)))==t0)); assert( (((t1->TTp(i1))->TTp(t1->TTi(i1)))==t1)); } ///Divide the tetrahadron in pos in two tetrahedrons using the new vertex vnew void _Divide(PosType pos,VertexType *vnew,TetraType *newtp0,TetraType *newtp1,bool invert) { int curredge=pos.E(); //control if the edge vertices arein the right order for the table if (invert) curredge+=6; //find the new position to vertex according int ie0=_GetMapVertEdgeRot(curredge,0); int ie1=_GetMapVertEdgeRot(curredge,2); int in0=_GetMapVertEdgeRot(curredge,1); int in1=_GetMapVertEdgeRot(curredge,3); //as first the ones that appartain to the selected curredge VertexType *ve0=pos.T()->V(ie0); VertexType *ve1=pos.T()->V(ie1); //and after the others that will be in the cutting plane VertexType *vn0=pos.T()->V(in0); VertexType *vn1=pos.T()->V(in1); newtp0->V(0)=ve0; newtp0->V(1)=vn0; newtp0->V(2)=vnew; newtp0->V(3)=vn1; newtp1->V(0)=vnew; newtp1->V(1)=vn0; newtp1->V(2)=ve1; newtp1->V(3)=vn1; //right order of the vertices #ifdef _DEBUG _AssertOrder(newtp0,ve0,vn0,vnew,vn1); _AssertOrder(newtp1,vnew,vn0,ve1,vn1); //end asserts #endif } bool _InvertRotation(PosType pos) { return (pos.V()!=Tetra::VofE(pos.E(),0)); } ///substitute the told tetrahedon on VT topology with newtp0 and newtp1 as created void _SubstituteVTTopology(TetraType *told,TetraType *newtp0,TetraType *newtp1) { _SetDefultVTTopology(newtp0); _SetDefultVTTopology(newtp1); //detach the old tetrahedron from VTtopology _Topo.DetachVTTopology(told); //tetrahedron 0 _Topo.InsertVTTopology(newtp0); //tetrahedron 1 _Topo.InsertVTTopology(newtp1); } ///control if the connections between tetrahedron created have the right shared vertices void _ControlConnection(TetraType *oldtp0,TetraType *newtp0) { VertexType *v00=oldtp0->V(0); VertexType *v01=oldtp0->V(1); VertexType *v02=oldtp0->V(2); VertexType *v03=oldtp0->V(3); VertexType *v10=newtp0->V(0); VertexType *v11=newtp0->V(1); VertexType *v12=newtp0->V(2); VertexType *v13=newtp0->V(3); assert(((v00==v10)&&(v02==v12))||((v00==v12)&&(v02==v10))); assert(((v01==v13)&&(v03!=v11))||((v01!=v13)&&(v03==v11))); } ///set as extern the 4 faces of the tetrahedron void _SetDefaultTTExtern(TetraType *t) { for (int y=0;y<4;y++) { t->TTp(y)=t; t->TTi(y)=y; } } ///substitute in Tetra Tetra Topology the tetrahedron old_t with new_t in according ///to face and edge void _SubstituteTTTopology(TetraType *old_t,TetraType *new_t,int edgerot,int face) { int indexface=_GetMapFaceEdgeRot(edgerot,face); if (old_t->IsBorderF(indexface)) { new_t->TTp(face)=new_t; new_t->TTi(face)=face; } else { TetraType *tetrad=old_t->TTp(indexface); int fad=old_t->TTi(indexface); _ConnectTTTopology(new_t,face,tetrad,fad); assert (!tetrad->IsD()); } } /// sobstitute the old tetrahedrons that share the edge in pos with new ones /// that share the vertex vnew that divide the old edge void _AddNewTetrahedrons(TetraMeshType &tm,PosType pos,VertexType *vnew) { TetraType *oldtp0=NULL; TetraType *oldtp1=NULL; TetraType *newtp0; TetraType *newtp1; TetraType *firsttp0=NULL; TetraType *firsttp1=NULL; int curredge; int direction=-1; bool invert=false; TetraAllocator All=TetraAllocator(); pos.Reset(); _nT=0; while (!pos.LoopEnd()) { assert(!pos.T()->IsD()); invert=_InvertRotation(pos); //CREATE THE NEW TETRAHEDRONS //create the new ones putting the veritices in the right order TetraIterator ti=All.AddTetra(tm,2); newtp0 = &(*ti); ti++; newtp1 = &(*ti); _Divide(pos,vnew,newtp0,newtp1,invert); #ifdef _DEBUG if ((oldtp0!=NULL)&&(!pos.Jump())) _ControlConnection(oldtp0,newtp0); if ((oldtp1!=NULL)&&(!pos.Jump())) _ControlConnection(oldtp1,newtp1); #endif // SUBSTITUTE NEW TETRAHEDRONS ON VT TOPOLOGY if (tm.HasVTTopology()) _SubstituteVTTopology(pos.T(),newtp0,newtp1); //THEN SET THE T-T TOPOLOGY _SetDefaultTTExtern(newtp0); _SetDefaultTTExtern(newtp1); curredge=pos.E(); if (invert) curredge+=6; //face3 _SubstituteTTTopology(pos.T(),newtp1,curredge,3); //face1 _SubstituteTTTopology(pos.T(),newtp0,curredge,1); //now I set t-t topology between themselfes _ConnectTTTopology(newtp0,3,newtp1,1); if (pos.Jump()) { vnew->SetB(); oldtp0=NULL; oldtp1=NULL; } direction=_GetDirRot(curredge,pos.F()); assert(direction!=-1); //control the direction of moving if ((oldtp0!=NULL)&&(oldtp1!=NULL)) { //direction=_GetDirRot(oldtp0,newtp0); //find direction of moving if (direction==0) { _ConnectTTTopology(oldtp0,0,newtp0,2); _ConnectTTTopology(oldtp1,0,newtp1,2); } else if (direction==2) { _ConnectTTTopology(oldtp0,2,newtp0,0); _ConnectTTTopology(oldtp1,2,newtp1,0); } } //assign if it is the first one if (firsttp0==NULL) firsttp0=newtp0; if (firsttp1==NULL) firsttp1=newtp1; oldtp0=newtp0; oldtp1=newtp1; _toDel[_nT]=pos.T(); _nT++; pos.NextT(); } //at the end I finish the connections if (!(pos.Jump())&&(direction==0)&&(firsttp0!=NULL)&&(firsttp1!=NULL)&&(oldtp0!=NULL)&&(oldtp1!=NULL)) { _ConnectTTTopology(oldtp0,0,firsttp0,2); _ConnectTTTopology(oldtp1,0,firsttp1,2); } else if (!(pos.Jump())&&(direction==2)&&(firsttp0!=NULL)&&(firsttp1!=NULL)&&(oldtp0!=NULL)&&(oldtp1!=NULL)) { _ConnectTTTopology(oldtp0,2,firsttp0,0); _ConnectTTTopology(oldtp1,2,firsttp1,0); } else if (pos.Jump()) vnew->SetB(); } ///Mark as deleted the tetrahedron that must be substituted void _DeleteOldTetra() { for (int i=0;i<_nT;i++) _toDel[i]->SetD(); } //========================================================================= public: /// Split the edge with local remeshing /// Tetrahedron-Tetrahedron topology is required VertexType* DoSplit(TetraMeshType &tm,TetraType *t,int edge,double alfa) { assert(!t->IsD()); assert(tm.HasTTTopology()); assert((alfa>0)&&(alfa<1)); assert((edge>=0)&&(edge<6)); VertexType *vnew=_AddVertexEdge(tm,*t,edge,alfa); _AddNewTetrahedrons(tm,_FindPos(t,edge),vnew); _DeleteOldTetra(); return(vnew); } };//end class }//end namespace tetra }//end namespace vcg #endifqutemol/vcg/vcg/complex/tetramesh/base.h0000444000175000017500000001714410720526750016721 0ustar mbamba/**************************************************************************** * VCGLib o o * * Visual and Computer Graphics Library o o * * _ O _ * * Copyright(C) 2004 \/)\/ * * Visual Computing Lab /\/| * * ISTI - Italian National Research Council | * * \ * * All rights reserved. * * * * 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. * * * * 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 (http://www.gnu.org/licenses/gpl.txt) * * for more details. * * * ****************************************************************************/ /**************************************************************************** History $Log: base.h,v $ Revision 1.14 2007/11/20 09:50:32 ganovelli compilation with gcc Revision 1.13 2007/03/12 15:38:03 tarini Texture coord name change! "TCoord" and "Texture" are BAD. "TexCoord" is GOOD. Revision 1.12 2005/12/12 11:10:35 ganovelli modifications to compile with gcc Revision 1.11 2005/01/12 11:06:54 ganovelli added InitVertexIMark Revision 1.10 2004/10/11 17:44:07 ganovelli added include of color4 Revision 1.9 2004/07/15 00:16:37 cignoni Better doxigen documentation Revision 1.8 2004/07/09 10:18:49 ganovelli added access functions to vn and tn Revision 1.7 2004/06/25 11:27:21 pietroni added function to access temporary mark for decimation Revision 1.6 2004/06/01 17:17:29 ganovelli pragma once removed , load ts removed to be put in io_tetramesh CLear() added Revision 1.5 2004/05/13 12:16:12 pietroni first version... add vertex to mesh Revision 1.4 2004/05/13 07:41:47 turini Chenged #include in #include Revision 1.3 2004/05/06 10:57:49 pietroni changed names to topology functions Revision 1.2 2004/04/28 11:37:14 pietroni *** empty log message *** Revision 1.1 2004/04/20 12:41:39 pietroni *** empty log message *** Revision 1.1 2004/04/15 08:54:20 pietroni *** empty log message *** ***************************************************************************/ #ifndef __VCG_TETRAMESH #define __VCG_TETRAMESH #include #include namespace vcg { namespace tetra { /** \addtogroup tetramesh */ /*@{*/ /** Class TetraMesh. This is class for definition of a mesh. @param STL_VERT_CONT (Template Parameter) Specifies the type of the vertices container any the vertex type. @param STL_FACE_CONT (Template Parameter) Specifies the type of the faces container any the face type. */ template < class STL_VERT_CONT ,class STL_TETRA_CONT > class Tetramesh{ public: /***********************************************/ /** @name Tetramesh Type Definitions **/ //@{ /// The mesh type typedef Tetramesh TetraMeshType; /// The vertex container typedef STL_VERT_CONT VertexContainer; /// The tethaedhron container typedef STL_TETRA_CONT TetraContainer; /// The vertex type typedef typename STL_VERT_CONT::value_type VertexType; /// The tetrahedron type typedef typename STL_TETRA_CONT::value_type TetraType; /// The type of vertex iterator typedef typename STL_VERT_CONT::iterator VertexIterator; /// The type of tetra iterator typedef typename STL_TETRA_CONT::iterator TetraIterator; /// The type of constant vertex iterator typedef typename STL_VERT_CONT::const_iterator const_VertexIterator; /// The type of constant face iterator typedef typename STL_TETRA_CONT::const_iterator const_TetraIterator; /// The vertex pointer type typedef VertexType * VertexPointer; /// The tetra pointer type typedef TetraType * TetraPointer; /// The type of the constant vertex pointer typedef const VertexType * const_VertexPointer; /// The type of the constant tetrahedron pointer typedef const VertexType * const_TetraPointer; typedef typename VertexType::ScalarType ScalarType; //@} /***********************************************/ /** @Common Attributes of a tetrahedral mesh **/ //@{ ///temporary mark for decimation int IMark; /// Set of vertices STL_VERT_CONT vert; /// Real number of vertices int vn; /// Set of tetrahedron STL_TETRA_CONT tetra; /// Real number of tetrahedron int tn; /// Real number of edges int en; ///Boundingbox della mesh Box3 bbox; //@} /***********************************************/ /** @Default Functions **/ //@{ /// Default constructor Tetramesh() { tn = vn = en = 0; } Tetramesh(VertexContainer v,TetraContainer t) { this->vert=v; this->tetra=t; vn=v.size(); tn=t.size(); } inline int MemUsed() const { return sizeof(Tetramesh)+sizeof(VertexType)*vert.size()+sizeof(TetraType)*tetra.size(); } void Clear(){ vert.clear(); tetra.clear(); tn = 0; vn = 0; } /// Initialize the imark-system of the vertices void InitVertexIMark() { VertexIterator vi; for(vi=vert.begin();vi!=vert.end();++vi) if( !(*vi).IsD() && (*vi).IsRW() ) (*vi).InitIMark(); } //@} /***********************************************/ /** @Functions used to retrieve informations**/ //@{ /// Reflection functions that speak about vertex and face properties. static bool HasPerVertexNormal() { return VertexType::HasNormal() ; } static bool HasPerVertexColor() { return VertexType::HasColor() ; } static bool HasPerVertexMark() { return VertexType::HasMark() ; } static bool HasPerVertexQuality() { return VertexType::HasQuality(); } static bool HasPerVertexTexCoord(){ return VertexType::HasTexCoord(); } static bool HasPerTetraNormal() { return TetraType::HasTetraNormal() ; } static bool HasPerTetraMark() { return TetraType::HasTetraMark() ; } static bool HasPerTetraQuality() { return TetraType::HasTetraQuality(); } static bool HasTTTopology() { return TetraType::HasTTAdjacency(); } static bool HasVTTopology() { return TetraType::HasVTAdjacency(); } static bool HasTopology() { return HasTTTopology() || HasVTTopology(); } int & SimplexNumber(){ return tn;} int & VertexNumber(){ return vn;} /***********************************************/ /** @Functions used for handle the temporany mark of a tetrahedron used in decimation**/ //@{ ///Increase the current mark. void UnMarkAll() { ++IMark; } ///Mark the vertex with current value void Mark(VertexType *v) { v->IMark()=IMark; } ///return the current mark int GetMark() { return (IMark); } ///Initialize the mark of all vertices void InitIMark() { VertexIterator vi; IMark=0; for(vi=vert.begin();vi!=vert.end();vi++) { (*vi).InitIMark(); } } //@} };//End class /*@}*/ };//end namespace };//end namespace #endif qutemol/vcg/vcg/complex/tetramesh/allocate.h0000444000175000017500000002006410073470545017567 0ustar mbamba/**************************************************************************** * VCGLib o o * * Visual and Computer Graphics Library o o * * _ O _ * * Copyright(C) 2004 \/)\/ * * Visual Computing Lab /\/| * * ISTI - Italian National Research Council | * * \ * * All rights reserved. * * * * 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. * * * * 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 (http://www.gnu.org/licenses/gpl.txt) * * for more details. * * * ****************************************************************************/ /**************************************************************************** History $Log: allocate.h,v $ Revision 1.5 2004/07/09 10:20:21 ganovelli addtetra corrected Revision 1.4 2004/06/01 17:12:46 ganovelli addVertices corrected (two copies instead of specializing te call) and put static (also addTetra) * g++ compliant * Revision 1.3 2004/05/31 16:01:56 pietroni added function addtetra Revision 1.2 2004/05/14 15:14:34 turini Added $Log: allocate.h,v $ Added Revision 1.5 2004/07/09 10:20:21 ganovelli Added addtetra corrected Added Added Revision 1.4 2004/06/01 17:12:46 ganovelli Added addVertices corrected (two copies instead of specializing te call) Added and put static (also addTetra) * g++ compliant * Added Added Revision 1.3 2004/05/31 16:01:56 pietroni Added added function addtetra Added for CVS History Log Revision 1.1 2004/19/04 13:05 pietroni Initial commit ****************************************************************************/ #ifndef __VCG_TETRA_ALLOCATE #define __VCG_TETRA_ALLOCATE #include using namespace std; namespace vcg { namespace tetra { /** \addtogroup tetramesh */ /*@{*/ /** Class Allocate. This is class for Allocate new vertices or tetrahedron on the mesh. @param TM_TYPE (Template Parameter) Specifies the type of the tetrahedral mesh. */ template < class TM_TYPE > class Allocator { public: /// The tetramesh type typedef TM_TYPE TetraMeshType; /// The vertex type typedef typename TM_TYPE::VertexType VertexType; /// The tetrahedron type typedef typename TM_TYPE::TetraType TetraType; /// The type of vertex iterator typedef typename TM_TYPE::VertexIterator VertexIterator; /// The type of tetra iterator typedef typename TM_TYPE::TetraIterator TetraIterator; /// The type of constant vertex iterator typedef typename TM_TYPE::const_VertexIterator const_VertexIterator; /// The type of constant face iterator typedef typename TM_TYPE::const_TetraIterator const_TetraIterator; public: /** Function to add n vertices to the mesh. The second parameter hold a vector of pointers to pointer to elements of the mesh that should be updated after a possible vector realloc. @param n Il numero di vertici che si vuole aggiungere alla mesh. @param local_var Vettore di variabili locali che rappresentano puntatori a vertici. restituisce l'iteratore al primo elemento aggiunto. */ static VertexIterator AddVertices(TetraMeshType &m,int n, vector &local_var) { VertexIterator oldbegin, newbegin; oldbegin = m.vert.begin(); VertexIterator last=m.vert.end(); if(m.vert.empty()) last=(VertexIterator)0; // if the vector is empty we cannot find the last valid element else --last; unsigned int siz=0; #ifdef __STL_CONFIG_H if(last!=(VertexIterator)0) distance(m.vert.begin(),last,siz); #else if(last!=(VertexIterator)0) siz=distance(m.vert.begin(),last); #endif for(unsigned int i=0; i empty_var; return AddVertices(m,n,empty_var); } struct InsertedVT{ InsertedVT(VertexType *_v, TetraType *_t, int _z):v(_v),t(_t),z(_z){} VertexType *v; TetraType *t; int z; const bool operator <(const InsertedVT & o){ return (v static void SubSetT(STL_CONT & subSet, TetraMeshType & m) { vector< InsertedVT > newVertices; typename STL_CONT :: iterator pfi; newVertices.clear(); for(pfi = subSet.begin(); pfi != subSet.end(); ++pfi) m.tetra.push_back((*pfi)); TetraIterator fi; for(fi = m.tetra.begin(); fi != m.tetra.end(); ++fi) { newVertices.push_back(InsertedVT( (*fi).V(0),&(*fi),0)); newVertices.push_back(InsertedVT( (*fi).V(1),&(*fi),1)); newVertices.push_back(InsertedVT( (*fi).V(2),&(*fi),2)); newVertices.push_back(InsertedVT( (*fi).V(3),&(*fi),3)); } sort(newVertices.begin(),newVertices.end()); typename std::vector< InsertedVT >::iterator curr,next; int pos = 0; curr = next = newVertices.begin(); while( next != newVertices.end()) { if((*curr)!=(*next)) pos++; (*next).t->V( (*next).z) = (VertexType *)pos; curr = next; next++; } typename std::vector::iterator newE = unique(newVertices.begin(),newVertices.end()); for(curr = newVertices.begin();curr!= newE;++curr) m.vert.push_back(*((*curr).v)); for(fi = m.tetra.begin(); fi != m.tetra.end(); ++fi) { (*fi).V(0) = &(m.vert[(int)(*fi).V(0)]); (*fi).V(1) = &(m.vert[(int)(*fi).V(1)]); (*fi).V(2) = &(m.vert[(int)(*fi).V(2)]); (*fi).V(3) = &(m.vert[(int)(*fi).V(3)]); } m.vn = m.vert.size(); m.tn = m.tetra.size(); } }; // end class /*@}*/ } // End namespace } // End namespace #endif qutemol/vcg/vcg/complex/tetramesh/update/0000755000175000017500000000000011633404241017105 5ustar mbambaqutemol/vcg/vcg/complex/tetramesh/update/topology.h0000444000175000017500000004274510631755755021164 0ustar mbamba/**************************************************************************** * VCGLib o o * * Visual and Computer Graphics Library o o * * _ O _ * * Copyright(C) 2004 \/)\/ * * Visual Computing Lab /\/| * * ISTI - Italian National Research Council | * * \ * * All rights reserved. * * * * 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. * * * * 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 (http://www.gnu.org/licenses/gpl.txt) * * for more details. * * * ****************************************************************************/ /**************************************************************************** History $Log: topology.h,v $ Revision 1.18 2007/06/07 10:20:29 turini Minor changes : replaced TVp and TVi calls with VTp and VTi respectively. Revision 1.17 2006/12/03 14:56:30 ganovelli *** empty log message *** Revision 1.16 2006/06/29 13:07:33 ganovelli Aggiunta superclasse UpdateTopology templated sui container e con funzioni sui container Revision 1.1 2004/16/04 14:32 pietroni Initial commit ****************************************************************************/ #ifndef __VCG_TETRA_UPDATE_TOPOLOGY #define __VCG_TETRA_UPDATE_TOPOLOGY #include #include #include #include using namespace std; namespace vcg { namespace tetra { /** Class Facet. This is class for definition of a face of tethahedron @param STL_VERT_CONT (Template Parameter) Specifies the type of the vertices container any the vertex type. */ template < class VERT_TYPE , class TETRA_TYPE> class Facet{ public: /// The vertex type typedef VERT_TYPE MVTYPE; typedef TETRA_TYPE MTTYPE; private: MTTYPE *Tr; int numface; MVTYPE * vertex[3]; public: Facet(MVTYPE *v0,MVTYPE *v1,MVTYPE *v2,TETRA_TYPE * t,int index) { vertex[0]=v0; vertex[1]=v1; vertex[2]=v2; if(vertex[0] > vertex[1]) std::swap(vertex[0], vertex[1]); if(vertex[1] > vertex[2]) { std::swap(vertex[1], vertex[2]); if(vertex[0] > vertex[1]) { std::swap(vertex[0], vertex[1]); } } Tr = t; numface = index; } inline const MVTYPE * V(int index) const { return vertex[index]; } TETRA_TYPE *getTetrahedron() { return Tr; } void setTetrahedron(TETRA_TYPE * t) { Tr=t; } inline bool operator == ( Facet const & f) const { return ((vertex[0]==f.V(0))&&(vertex[1]==f.V(1))&&(vertex[2]==f.V(2))); } inline bool operator != ( Facet const & f) const { return !((*this) == f); } inline bool operator > ( Facet const & f) const { if (vertex[0]!=f.V(0)) { if (vertex[0]>f.V(0)) return true; else return false; } else if (vertex[1]!=f.V(1)) { if (vertex[1]>f.V(1)) return true; else return false; } else if (vertex[2]!=f.V(2)) { if (vertex[2]>f.V(2)) return true; else return false; }else return false; } inline bool operator < ( Facet const & f) const { return (!((*this)>f)&&((*this)!=f)); } inline bool operator <= ( Facet const & f) const { return (((*this)= ( Facet const & f) const { return (((*this)>f)||((*this)==f)); } int getFaceIndex()const { return numface; } };//end class /** \addtogroup tetramesh */ /*@{*/ /** Class UpdateTopology. This is class for Topology of a tetrahedralmesh. @param STL_VERT_CONT (Template Parameter) Specifies the type of the vertices container any the vertex type. @param STL_TETRA_CONT (Template Parameter) Specifies the type of the tetrahedrons container any the tetrahedrons type. */ template < class STL_VERT_CONT ,class STL_TETRA_CONT > class UpdateTopologyBase { public: /// The vertex container typedef STL_VERT_CONT VertexContainer; /// The tethaedhron container typedef STL_TETRA_CONT TetraContainer; /// The vertex type typedef typename STL_VERT_CONT::value_type VertexType; /// The tetrahedron type typedef typename STL_TETRA_CONT::value_type TetraType; /// The type of vertex iterator typedef typename STL_VERT_CONT::iterator VertexIterator; /// The type of tetra iterator typedef typename STL_TETRA_CONT::iterator TetraIterator; /// The type of constant vertex iterator typedef typename STL_VERT_CONT::const_iterator const_VertexIterator; /// The type of constant face iterator typedef typename STL_TETRA_CONT::const_iterator const_TetraIterator; public: /***********************************************/ /** @Vertex-Tetrahedron Topology Funtions **/ //@{ /// Create the VT topology for tetrahedrons that are into containers. static void VTTopology( VertexContainer & vert, TetraContainer & tetra ) { ClearVTTopology( vert, tetra ); for( TetraIterator t = tetra.begin(); t != tetra.end(); ++t ) if( !(*t).IsD() ) for( int j = 0; j < 4; ++j ) { (*t).VTp(j) = (*t).V(j)->VTp(); (*t).VTi(j) = (*t).V(j)->VTi(); (*t).V(j)->VTp() = &(*t); (*t).V(j)->VTi() = j; } } /// Clear the vertex-tetra (VT) topology. static void ClearVTTopology( VertexContainer & vert, TetraContainer & tetra ) { for( VertexIterator v = vert.begin(); v != vert.end(); ++v ) { v->VTp() = 0; v->VTi() = 0; } for( TetraIterator t = tetra.begin(); t != tetra.end(); ++t ) if( ! (*t).IsD() ) for( int j = 0; j < 4; ++j ) { (*t).VTp(j) = 0; (*t).VTi(j) = 0; } } /// Erase one tetrahedron from VTTopology of all his vertices. static void DetachVTTopology( TetraType *t ) { if( ! (*t).IsD() ) for( int i = 0; i < 4; i++ ) DetachVTTopology( t->V(i), t ); } /// Erase one tetrahedron from VTTopology of one specified vertex. static void DetachVTTopology( VertexType *v, TetraType *t ) { TetraType *lastt; int lastz; VTIterator Et( v->VTb(), v->VTi() ); if( Et.Vt() == t ) { v->VTb() = (TetraType *) t->VTp( v->VTi() ); v->VTi() = t->VTi( v->VTi() ); } else { lastz = Et.Vi(); while( ( Et.Vt() != t ) && ( !Et.End() ) ) { lastz = Et.Vi(); lastt = Et.Vt(); ++Et; } /// In the list of the vertex v must be present the tetrahedron that you want to detach assert( Et.Vt() != NULL ); lastt->VTp(lastz) = Et.Vt()->VTp( Et.Vi() ); lastt->VTi(lastz) = Et.Vt()->VTi( Et.Vi() ); } } /// Insert the tetrahedron t in VT topology for vertex v of index z. static void InsertVTTopology( VertexType *v, int z, TetraType *t ) { if( ! (*t).IsD() ) { t->VTp(z) = v->VTb(); t->VTi(z) = v->VTi(); v->VTb() = &(*t); v->VTi() = z; } } /// Insert the tetrahedron t in VT topology for all his vertices. static void InsertVTTopology( TetraType *t ) { assert( !( t->IsD() ) ); for( int k = 0; k < 4; k++ ) { assert( !( t->V(k)->IsD() ) ); InsertVTTopology( t->V(k), k, t ); } } /// Test the Tetrahedron-Tetrahedron (TT) topology (by face). static void TestVTTopology( VertexContainer & vert, TetraContainer & tetra ) { int i; for( VertexIterator vi = vert.begin(); vi != vert.end(); vi++ ) if( !(*vi).IsD() ) { TetraType *nextT = vi->VTb(); int nextI = vi->VTi(); int oldI; while( nextT != NULL ) { assert( ( nextT->V(nextI) == &(*vi) ) ); oldI = nextI; nextI = nextT->VTi(nextI); nextT = nextT->VTp(oldI); } } } /*@}*/ /***********************************************/ /** @Tetrahedron-Tetrahedron Topology Funtions **/ //@{ ///Build the Tetrahedron-Tetrahedron Topology (by Face) static void TTTopology(const VertexContainer &vert,TetraContainer &tetra) { vector > VF; VertexType* v0; VertexType* v1; VertexType* v2; for (TetraIterator ti=tetra.begin();ti!=tetra.end();ti++) if (!(*ti).IsD()) { (*ti).TTi(0)=0; (*ti).TTi(1)=1; (*ti).TTi(2)=2; (*ti).TTi(3)=3; (*ti).TTp(0)=(&(*ti)); (*ti).TTp(1)=(&(*ti)); (*ti).TTp(2)=(&(*ti)); (*ti).TTp(3)=(&(*ti)); v0=(*ti).V(Tetra::VofF(0,0)); v1=(*ti).V(Tetra::VofF(0,1)); v2=(*ti).V(Tetra::VofF(0,2)); VF.push_back(Facet(v0,v1,v2,&(*ti),0)); v0=(*ti).V(Tetra::VofF(1,0)); v1=(*ti).V(Tetra::VofF(1,1)); v2=(*ti).V(Tetra::VofF(1,2)); VF.push_back(Facet(v0,v1,v2,&(*ti),1)); v0=(*ti).V(Tetra::VofF(2,0)); v1=(*ti).V(Tetra::VofF(2,1)); v2=(*ti).V(Tetra::VofF(2,2)); VF.push_back(Facet(v0,v1,v2,&(*ti),2)); v0=(*ti).V(Tetra::VofF(3,0)); v1=(*ti).V(Tetra::VofF(3,1)); v2=(*ti).V(Tetra::VofF(3,2)); VF.push_back(Facet(v0,v1,v2,&(*ti),3)); } sort(VF.begin(),VF.end()); TetraType *t0; TetraType *t1; int faceindex0; int faceindex1; int j; unsigned int i; for (i=0;iTTp(faceindex0)=(t1); t1->TTp(faceindex1)=(t0); t0->TTi(faceindex0)=(faceindex1); t1->TTi(faceindex1)=(faceindex0); i++; } } } ///Connect trought Tetrahedron-Tetrahedron Topology t0 and t1 with faces i0 and i1 static void _AttachTTTopology(TetraType *t0,int i0,TetraType *t1,int i1) { assert((i0>=0)&&(i0<4)); assert((i1>=0)&&(i1<4)); assert((!t0->IsD())&&(!t1->IsD())); t0->TTp(i0)=t1; t0->TTi(i0)=i1; t1->TTp(i1)=t0; t1->TTi(i1)=i0; assert( (((t0->TTp(i0))->TTp(t0->TTi(i0)))==t0)); assert( (((t1->TTp(i1))->TTp(t1->TTi(i1)))==t1)); } ///Detach Tetrahedron-Tetrahedron Topology static void DetachTTTopology(TetraType *t) { assert(!t->IsD()); int i; for(i=0; i < 4; ++i) t->TTp(i)->TTp(t->TTi(i)) = t->TTp(i); } ///Test the Tetrahedron-Tetrahedron Topology (by Face) static void TestTTTopology(VertexContainer &vert,TetraContainer &tetra) { int i; for (TetraIterator ti=tetra.begin();ti!=tetra.end();ti++) if ((!(*ti).IsD())) for (i=0;i<4;i++) { { assert( ((((*ti).TTp(i))->TTp((*ti).TTi(i)))==&(*ti))); VertexType *v0=(*ti).V(Tetra::VofF(i,0)); VertexType *v1=(*ti).V(Tetra::VofF(i,1)); VertexType *v2=(*ti).V(Tetra::VofF(i,2)); TetraType *t1=(TetraType*)(*ti).TTp(i); assert (!t1->IsD()); int z1=(*ti).TTi(i); VertexType *vo0=(*t1).V(Tetra::VofF(z1,0)); VertexType *vo1=(*t1).V(Tetra::VofF(z1,1)); VertexType *vo2=(*t1).V(Tetra::VofF(z1,2)); assert((v0!=v1)&&(v0!=v2)&&(v1!=v2)); assert((vo0!=vo1)&&(vo0!=vo2)&&(vo1!=vo2)); assert ((v0==vo0)||(v0==vo1)||(v0==vo2)); assert ((v1==vo0)||(v1==vo1)||(v1==vo2)); assert ((v2==vo0)||(v2==vo1)||(v2==vo2)); } } } ///test if all and only the exernal vertex are set of border static void TestExternalVertex(VertexContainer &vert,TetraContainer &tetra) { TetraIterator ti; VertexIterator vi; typedef pair VertBoolPair; map Inserted; typename map::iterator MapIte; for (ti=tetra.begin();tiIsD()) { for (i=0;i<4;i++) if (ti->IsBorderF(i)) { VertexType *v0=ti->V(Tetra::VofF(i,0)); VertexType *v1=ti->V(Tetra::VofF(i,1)); VertexType *v2=ti->V(Tetra::VofF(i,2)); MapIte = Inserted.find(v0); if ( MapIte == Inserted.end( ) ) Inserted.insert (VertBoolPair(v0,true)); MapIte = Inserted.find(v1); if ( MapIte == Inserted.end( ) ) Inserted.insert (VertBoolPair(v1,true)); MapIte = Inserted.find(v2); if ( MapIte == Inserted.end( ) ) Inserted.insert (VertBoolPair(v2,true)); assert(!((v0->IsD())||(v1->IsD())||(v2->IsD()))); assert ((v0->IsB())&&(v1->IsB())&&(v2->IsB())); } } } for (vi=vert.begin();viIsD()) { if (vi->IsB()) { MapIte = Inserted.find(&(*vi)); //control if the extrenal vertex appartain to an external face assert ( MapIte != Inserted.end( ) ); } } } } ///set the external vertex according to Tetra-Tetra topology static void setExternalVertices(VertexContainer &vert,TetraContainer &tetra) { TetraIterator tt; VertexIterator vi; int i; for (vi=vert.begin();viClearB(); for (tt=tetra.begin();ttSetB(); (*tt).V(Tetra::VofF(i,1))->SetB(); (*tt).V(Tetra::VofF(i,2))->SetB(); } } } } /*@}*/ private: struct _triV { VertexType *v[3]; _triV(VertexType *v0,VertexType *v1,VertexType *v2) { v[0]=v0; v[1]=v1; v[2]=v2; sort(v,v+3); } inline const VertexType * V(int index) const { return v[index]; } inline bool operator == ( _triV const & tv) const { return ((v[0]==tv.V(0))&&(v[1]==tv.V(1))&&(v[2]==tv.V(2))); } inline bool operator != ( _triV const & tv) const { return !((*this) == tv); } inline bool operator > ( _triV const & tv ) const { if (v[0]!=tv.V(0)) { if (v[0]>tv.V(0)) return true; else return false; } else if (v[1]!=tv.V(1)) { if (v[1]>tv.V(1)) return true; else return false; } else if (v[2]!=tv.V(2)) { if (v[2]>tv.V(2)) return true; else return false; }else return false; } inline bool operator < (_triV const & tv) const { return !(((*this)>tv)&&((*this)!=tv)); } inline bool operator <= (_triV const & tv) const { return (((*this)= ( _triV const & tv) const { return (((*this)>tv)||((*this)==tv)); } }; public: ///this function is used to test if an edge is extern static bool IsExternEdge(TetraType *t,int edge) { std::vector < _triV > Faces; assert((t->HasTTAdjacency())||(t->HasVTAdjacency())); if ((!t->V(Tetra::VofE(edge,0))->IsB())||(!t->V(Tetra::VofE(edge,1))->IsB())) return (false); if (t->HasTTAdjacency()) { PosLoop pl(t,Tetra::FofE(edge,0),edge,Tetra::VofE(edge,0)); pl.Reset(); //stops if one of faces incident to the edge is an extern face while ((!pl.LoopEnd())&&(!pl.T()->IsBorderF(Tetra::FofE(pl.E(),0)))&&(!pl.T()->IsBorderF(Tetra::FofE(pl.E(),1)))) pl.NextT(); if (pl.LoopEnd()) return false; else return true; } else { //using vt adiacency VertexType *v0=t->V(Tetra::VofE(edge,0)); VertexType *v1=t->V(Tetra::VofE(edge,1)); assert(v0!=v1); VTIterator Vti(v0->VTb(),v0->VTi()); int num=0; Faces.clear(); Faces.reserve(40); while (!Vti.End()) { //take the three faces incident on one vertex int f0=Tetra::FofV(Vti.Vi(),0); int f1=Tetra::FofV(Vti.Vi(),1); int f2=Tetra::FofV(Vti.Vi(),2); VertexType *vf0=Vti.Vt()->V(Tetra::VofF(f0,0)); VertexType *vf1=Vti.Vt()->V(Tetra::VofF(f0,1)); VertexType *vf2=Vti.Vt()->V(Tetra::VofF(f0,2)); //if there is the edge then put the three vertex in the vector if ((vf0==v1)||(vf1==v1)||(vf2==v1)) { Faces.push_back(_triV(vf0,vf1,vf2)); num++; } } sort(Faces.begin(),Faces.end()); //now look if one face is no shared from other tetrahedron //2 instances of same face in vector means it is internal face bool isExtern=false; typename std::vector < _triV >::iterator TVIo; typename std::vector < _triV >::iterator TVIn; TVIo=Faces.begin(); TVIn=Faces.begin(); TVIn++; int j=0; while (((*TVIo)==(*TVIn))&&(j=num) return false; else return true; } } }; // end class template class UpdateTopology: public UpdateTopologyBase{ public: static void TTTopology(TetraMeshType & tmesh){ UpdateTopologyBase:: TTTopology(tmesh.vert,tmesh.tetra); } static void VTTopology(TetraMeshType & tmesh){ UpdateTopologyBase:: VTTopology(tmesh.vert,tmesh.tetra); } }; /*@}*/ } // End namespace } // End namespace #endif qutemol/vcg/vcg/complex/tetramesh/update/normal.h0000444000175000017500000001404510347255254020561 0ustar mbamba/**************************************************************************** * VCGLib o o * * Visual and Computer Graphics Library o o * * _ O _ * * Copyright(C) 2004 \/)\/ * * Visual Computing Lab /\/| * * ISTI - Italian National Research Council | * * \ * * All rights reserved. * * * * 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. * * * * 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 (http://www.gnu.org/licenses/gpl.txt) * * for more details. * * * ****************************************************************************/ /**************************************************************************** History $Log: normal.h,v $ Revision 1.9 2005/12/12 11:10:36 ganovelli modifications to compile with gcc Revision 1.8 2004/10/28 00:54:34 cignoni Better Doxygen documentation Revision 1.7 2004/09/01 12:17:25 pietroni minor changes to comply gcc compiler (typename's ) Revision 1.6 2004/06/25 11:25:07 pietroni changrd update for a vertex normal functions void PerVertex(VertexType *v) Revision 1.5 2004/06/15 16:01:26 pietroni added functions to update local vertices normal Revision 1.4 2004/05/26 11:59:09 turini Changed : Use Of vector In Use Of std::vector. Revision 1.3 2004/05/26 11:53:17 pietroni modified face declaration Revision 1.2 2004/05/26 11:48:53 turini Changed : include Path. Revision 1.1 2004/05/12 13:52:11 pietroni *** empty log message *** Revision 1.2 2004/03/12 15:22:19 pietroni Written some documentation and added to the trimes doxygen module ****************************************************************************/ #ifndef __VCG_TETRA_UPDATE_NORMALS #define __VCG_TETRA_UPDATE_NORMALS #include #include #include #include #include #include namespace vcg { namespace tetra { /** \addtogroup tetramesh */ /*@{*/ /// Management, updating and computation of per-vertex and per-face normals. /// This class is used to compute or update the normals that can be stored in the vertex or face component of a mesh. template class UpdateNormals { public: typedef ComputeMeshType TetraMeshType; typedef typename TetraMeshType::VertexType VertexType; typedef typename TetraMeshType::VertexPointer VertexPointer; typedef typename TetraMeshType::VertexIterator VertexIterator; typedef typename TetraMeshType::TetraType TetraType; typedef typename TetraMeshType::TetraPointer TetraPointer; typedef typename TetraMeshType::TetraIterator TetraIterator; typedef typename VertexType::NormalType NormalType; typedef vcg::Face FaceTemp; typedef vcg::tri::TriMesh< std::vector,std::vector > TriMeshTemp; /// Calculates the vertex normal (if stored in the current face type) static void PerTetraFace(TetraMeshType &m) { if( !m.HasPerTetraNormal()) return; TetraIterator t; for(t=m.tetra.begin();t!=m.tetra.end();++t) if( !(*t).IsD() ) (*t).ComputeNormal(); } /// Calculates the vertex normal of a vertex. static void PerVertex(VertexType *v) { if( !VertexType::HasNormal()) return; VTIterator VTi=VTIterator(v->VTb(),v->VTi()); NormalType Norm=NormalType(0,0,0); int iter=0; while (!VTi.End()) { //take the tree faces on the vertex's tetrahedron for (int j=0;j<3;j++) { int f=Tetra::FofV(VTi.Vi(),j); if (VTi.Vt()->IsBorderF(f)) { iter++; Norm+=VTi.Vt()->N(f); } } ++VTi; } Norm/=(float)iter; v->N()=Norm.Normalize(); } /// Calculates the vertex normal. Without exploiting or touching face normals /// The normal of a vertex v is the weigthed average of the normals of the faces incident on v. static void PerVertex(TetraMeshType &m) { if( !m.HasPerVertexNormal()) return; _ClearNormal(m); TriMeshTemp tri_mesh=TriMeshTemp(); TriConverter tric=TriConverter(); tric.Convert(m.tetra,tri_mesh); vcg::tri::UpdateNormals UNT=vcg::tri::UpdateNormals(); UNT.PerVertexNormalized(tri_mesh); } private: static void _ClearNormal(TetraMeshType &m) { if( !m.HasPerVertexNormal()) return; VertexIterator vi; for(vi=m.vert.begin();vi!=m.vert.end();++vi) if( !(*vi).IsD() && (*vi).IsRW() ) (*vi).N() = VertexType::NormalType(0,0,0); } ///// Calculates both vertex and face normals. ///// The normal of a vertex v is the weigthed average of the normals of the faces incident on v. //static void PerVertexPerFace(ComputeTetraMeshType &m) //{ // if( !m.HasPerVertexNormal() || !m.HasPerFaceNormal()) return; // // //} // // //static void PerFaceNormalized(ComputeTetraMeshType &m) //{ // //} // // ///// Calculates the vertex normal //static void PerVertexNormalized(ComputeTetraMeshType &m) //{ // //} }; // end class } // End namespace } // End namespace #endif qutemol/vcg/vcg/complex/tetramesh/update/triconvert.h0000444000175000017500000001465710347255254021501 0ustar mbamba/**************************************************************************** * VCGLib o o * * Visual and Computer Graphics Library o o * * _ O _ * * Copyright(C) 2004 \/)\/ * * Visual Computing Lab /\/| * * ISTI - Italian National Research Council | * * \ * * All rights reserved. * * * * 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. * * * * 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 (http://www.gnu.org/licenses/gpl.txt) * * for more details. * * * ****************************************************************************/ /**************************************************************************** History Revision 1.1 2004/22/04 14:32 pietroni Initial commit ****************************************************************************/ #ifndef __VCG_TETRA_TRI_CONVERTER #define __VCG_TETRA_TRI_CONVERTER #include #include #include namespace vcg { namespace tetra { /** Class TriConverter. This is class for convetr tetrahedral mesh into triangle mesh @param STL_VERT_CONT (Template Parameter) Specifies the type of the vertices container any the vertex type. @param STL_TETRA_CONT (Template Parameter) Specifies the type of the tetrahedrons container any the tetrahedrons type. */ template < class TETRA_MESH ,class TRI_MESH > class TriConverter { public: /// The tetrahedral mesh type typedef TETRA_MESH TetraMeshType; /// The triangle mesh type typedef TRI_MESH TriangleMeshType; /// The tetrahedron type typedef typename TetraMeshType::TetraType TetraType; /// The triangle type typedef typename TriangleMeshType::FaceType FaceType; /// The vertex type of tetrahedreal Mesh typedef typename TetraMeshType::VertexType TetraVertexType; /// The vertex type of triangular Mesh typedef typename TriangleMeshType::VertexType TriVertexType; /// The type of vertex iterator on tetrahedral mesh typedef typename TetraMeshType::VertexIterator TetraVertexIterator; /// The type of vertex iterator on tetrahedral mesh typedef typename TriangleMeshType::VertexIterator TriVertexIterator; /// The type of tetra iterator typedef typename TetraMeshType::TetraIterator TetraIterator; /// The type of tetra iterator typedef typename TriangleMeshType::FaceIterator FaceIterator; /// The type of const tetra iterator typedef typename TetraMeshType::const_TetraIterator const_TetraIterator; /// The type of const face iterator typedef typename TriangleMeshType::ConstFaceIterator ConstFaceIterator; /// The type of tetrahedrons container typedef typename TetraMeshType::TetraContainer TetraContainer; /// The type of const vertex pointer of tetrahedral mesh typedef typename TetraMeshType::const_VertexPointer const_VertexPointer; public: /***********************************************/ /** @Convert to triangle-mesh functions **/ //@{ ///this function build a triangle mesh using the same pointers to the tetrahedral mesh vertex void Convert(TetraContainer &tetra,TriangleMeshType &trim) { TetraIterator ti; TetraVertexType *v0; TetraVertexType *v1; TetraVertexType *v2; trim.Clear(); for (ti=tetra.begin();tiIsD())) { if ((ti->IsBorderF(0))||(ti->IsBorderF(1))||(ti->IsBorderF(2))||(ti->IsBorderF(3))) for (int i=0;i<4;i++) if (ti->IsBorderF(i)) { v0=ti->V(Tetra::VofF(i,0)); v1=ti->V(Tetra::VofF(i,1)); v2=ti->V(Tetra::VofF(i,2)); FaceType f=FaceType(); f.ClearFlags(); f.V(0)=v0; f.V(1)=v1; f.V(2)=v2; trim.face.push_back(f); } } } } struct InsertedV{ InsertedV( TriVertexType *_v, FaceType* _f, int _z):v(_v),f(_f),z(_z){} TriVertexType *v; FaceType* f; int z; const bool operator <(const InsertedV & o){ return (v newVertices; typename vector::iterator curr,next; TriVertexIterator vi; vector redirect; Convert(tetra,trim); FaceIterator fi; for(fi = trim.face.begin(); fi != trim.face.end(); ++fi){ newVertices.push_back(InsertedV( (*fi).V(0),&(*fi),0)); newVertices.push_back(InsertedV( (*fi).V(1),&(*fi),1)); newVertices.push_back(InsertedV( (*fi).V(2),&(*fi),2)); } sort(newVertices.begin(),newVertices.end()); int pos = 0; curr = next = newVertices.begin(); while( next != newVertices.end()){ if((*curr)!=(*next)) pos++; (*next).f->V( (*next).z) = (TriVertexType*)pos; curr = next; next++; } typename vector::iterator newE = unique(newVertices.begin(),newVertices.end()); for(curr = newVertices.begin();curr!= newE;++curr) trim.vert.push_back(*((*curr).v)); for(vi = trim.vert.begin(); vi != trim.vert.end(); ++vi) redirect.push_back(&(*vi)); for(fi = trim.face.begin(); fi != trim.face.end(); ++fi){ (*fi).V(0) = redirect[(int)(*fi).V(0)]; (*fi).V(1) = redirect[(int)(*fi).V(1)]; (*fi).V(2) = redirect[(int)(*fi).V(2)]; } trim.vn = trim.vert.size(); trim.fn = trim.face.size(); } };// End class } // End namespace } // End namespace #endif qutemol/vcg/vcg/complex/tetramesh/update/bounding.h0000444000175000017500000000573310046415126021072 0ustar mbamba/**************************************************************************** * VCGLib o o * * Visual and Computer Graphics Library o o * * _ O _ * * Copyright(C) 2004 \/)\/ * * Visual Computing Lab /\/| * * ISTI - Italian National Research Council | * * \ * * All rights reserved. * * * * 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. * * * * 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 (http://www.gnu.org/licenses/gpl.txt) * * for more details. * * * ****************************************************************************/ /**************************************************************************** History $Log: bounding.h,v $ Revision 1.1 2004/05/06 10:58:30 pietroni first commit: update bounding box of tetrahedral mesh Revision 1.1 2004/05/04 11:15:13 pietroni First working version! ****************************************************************************/ #ifndef __VCG_TETRA_UPDATE_BOUNDING #define __VCG_TETRA_UPDATE_BOUNDING namespace vcg { namespace tetra { /** \addtogroup tetramesh */ /*@{*/ /// Management, updating and computation of bonding box on a tetrahedral mesh template class UpdateBounding { public: typedef ComputeMeshType MeshType; typedef typename MeshType::VertexType VertexType; typedef typename MeshType::VertexPointer VertexPointer; typedef typename MeshType::VertexIterator VertexIterator; typedef typename MeshType::TetraType TetraType; typedef typename MeshType::TetraPointer TetraPointer; typedef typename MeshType::TetraIterator TetraIterator; /// Calculates the limits of bounding box of tetrahedral mesh static void Box(ComputeMeshType &m) { m.bbox.SetNull(); VertexIterator vi; for(vi=m.vert.begin();vi!=m.vert.end();++vi) if( !(*vi).IsD() ) m.bbox.Add((*vi).P()); } }; // end class } // End namespace } // End namespace #endif qutemol/vcg/vcg/complex/tetramesh/visit.h0000444000175000017500000000555210643216404017141 0ustar mbamba /**************************************************************************** * VCGLib o o * * Visual and Computer Graphics Library o o * * _ O _ * * Copyright(C) 2004 \/)\/ * * Visual Computing Lab /\/| * * ISTI - Italian National Research Council | * * \ * * All rights reserved. * * * * 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. * * * * 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 (http://www.gnu.org/licenses/gpl.txt) * * for more details. * * * ****************************************************************************/ /**************************************************************************** History $Log: visit.h,v $ Revision 1.2 2007/07/05 16:32:04 ganovelli added return type Revision 1.1 2006/12/03 14:55:44 ganovelli created ****************************************************************************/ #ifndef __VCGLIB_TETRASUBSET #define __VCGLIB_TETRASUBSET #include namespace vcg { namespace tetra { /** \addtogroup tetramesh */ /*@{*/ /// assumes TTTopology has been computed template void Component(TetraPtrContainer & src, TetraPtrContainer & conn_com){ typename TetraPtrContainer::iterator ti; typedef typename TetraPtrContainer::value_type TetraPointer; for(ti = src.begin(); ti != src.end(); ++ti) (*ti)->SetS(); while(!src.empty()){ TetraPointer tp = src.back(); src.pop_back(); conn_com.push_back(tp); for(unsigned int i = 0; i < 4; ++i) if(!tp->TTp(i)->IsD()) if(!tp->TTp(i)->IsS()){ tp->TTp(i)->SetS(); src.push_back(tp->TTp(i)); } } for(ti = conn_com.begin(); ti != conn_com.end(); ++ti) (*ti)->ClearS(); } /*@}*/ } // End namespace } // End namespace #endif qutemol/vcg/vcg/complex/trimesh/0000755000175000017500000000000011633404241015302 5ustar mbambaqutemol/vcg/vcg/complex/trimesh/hole.h0000444000175000017500000006766110713725543016431 0ustar mbamba/**************************************************************************** * VCGLib o o * * Visual and Computer Graphics Library o o * * _ O _ * * Copyright(C) 2004 \/)\/ * * Visual Computing Lab /\/| * * ISTI - Italian National Research Council | * * \ * * All rights reserved. * * * * 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. * * * * 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 (http://www.gnu.org/licenses/gpl.txt) * * for more details. * * * ****************************************************************************/ /**************************************************************************** History $Log: hole.h,v $ Revision 1.35 2007/11/05 23:46:43 cignoni removed past end access in an assert Revision 1.34 2007/01/31 15:25:49 giec Remove some usless code in Minimum Weight Triangulation. Revision 1.33 2007/01/31 11:46:12 giec Bug fix Revision 1.32 2007/01/18 18:15:14 cignoni added missing typenames Revision 1.31 2007/01/18 11:17:43 giec The minimum weight algorithm keep the topology consistent. Revision 1.30 2007/01/10 12:07:54 giec Bugfixed ComputeDihedralAngle function Revision 1.29 2006/12/27 15:09:52 giec Bug fix on ComputeDihedralAngle function Revision 1.28 2006/12/12 11:14:51 cignoni Commented some variant of the quality measure of weighted ears Revision 1.27 2006/12/07 00:40:18 cignoni Added many this-> for gcc compiling Revision 1.26 2006/12/06 13:03:59 cignoni Corrected bugs on selfintersection Revision 1.25 2006/12/06 00:12:53 cignoni Heavily restructured and corrected. Now a single Close ear function Corrected Hole search function, and management of double non manifold vertex in a hole Changed priority strategy in the heap, now a mix of quality and dihedral angle. Changed but still untested IntersectionEar Revision 1.24 2006/12/01 21:24:16 cignoni Corrected bug in the search of holes. Removed output prints Revision 1.23 2006/12/01 08:53:55 cignoni Corrected pop_heap vs pop_back issue in heap usage Revision 1.22 2006/12/01 00:11:17 cignoni Added Callback, Corrected some spelling errors (adiacense -> adjacency). Added Validity Check function for hole loops Revision 1.21 2006/11/30 11:49:20 cignoni small gcc compiling issues Revision 1.20 2006/11/29 16:21:45 cignoni Made static exposed funtions of the class Revision 1.19 2006/11/29 15:25:22 giec Removed limit. Revision 1.18 2006/11/29 15:18:49 giec Code refactory and bugfix. Revision 1.17 2006/11/24 10:42:39 mariolatronico Now compiles on gcc under linux. Revision 1.16 2006/11/22 13:43:28 giec Code refactory and added minimum weight triangolation. Revision 1.15 2006/11/13 10:11:38 giec Clear some useless code Revision 1.14 2006/11/07 15:13:56 zifnab1974 Necessary changes for compilation with gcc 3.4.6. Especially the hash function is a problem Revision 1.13 2006/11/07 11:47:11 cignoni gcc compiling issues Revision 1.12 2006/11/07 07:56:43 cignoni Added missing std:: Revision 1.11 2006/11/06 16:12:29 giec Leipa ear now compute max dihedral angle. Revision 1.10 2006/10/31 11:30:41 ganovelli changed access throught iterator with static call to comply 2005 compiler Revision 1.9 2006/10/20 07:44:45 cignoni Added missing std:: Revision 1.8 2006/10/18 15:06:47 giec New policy for compute quality in TrivialEar. Bugfixed LeipaEar. Added new algorithm "selfintersection" with test for self intersection. Revision 1.7 2006/10/10 09:12:02 giec Bugfix and added a new type of ear (Liepa like) Revision 1.6 2006/10/09 10:07:07 giec Optimized version of "EAR HOLE FILLING", the Ear is selected according to its dihedral angle. Revision 1.5 2006/10/06 15:28:14 giec first working implementationof "EAR HOLE FILLING". Revision 1.4 2006/10/02 12:06:40 giec BugFix Revision 1.3 2006/09/27 15:33:32 giec It close one simple hole . . . Revision 1.2 2006/09/27 09:29:53 giec Frist working release whit a few bugs. It almost fills the hole ... Revision 1.1 2006/09/25 09:17:44 cignoni First Non working Version ****************************************************************************/ #ifndef __VCG_TRI_UPDATE_HOLE #define __VCG_TRI_UPDATE_HOLE #include #include #include #include #include #include namespace vcg { namespace tri { /* Un ear e' identificato da due hedge pos. i vertici dell'ear sono e0.VFlip().v e0.v e1.v Vale che e1== e0.NextB(); e che e1.FlipV() == e0; Situazioni ear non manifold, e degeneri (buco triangolare) T XXXXXXXXXXXXX A /XXXXX B en/XXXXX /XXXXXXXXXXXXXXX /XXXXXX /XXXXXX XXXXXXep==en XXX ep\ /en XXXX /e1 XXXX XXXXXX ----/| XX ------ ----/| XX ------ ----/|XXX XXXXXX| /e1 XX XXXXXX| /e1 XX XXXXXX| o/e0 XX XXXXXX| /XXXXXX XXXXXX| /XXXXXX XXXXXX| /XXXXXX XXX e0|o/XXXXXXX XXX e0|o/XXXXXXX XXX ep| /XXXXXXX XXX \|/XXXXXXXX XXX \|/XXXXXXXX XXX \|/XXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX */ template class TrivialEar { public: typedef typename MESH::FaceType FaceType; typedef typename MESH::FacePointer FacePointer; typedef typename face::Pos PosType; typedef typename MESH::ScalarType ScalarType; typedef typename MESH::CoordType CoordType; PosType e0; PosType e1; CoordType n; // the normal of the face defined by the ear const char * Dump() {return 0;} const CoordType &cP(int i) const {return P(i);} const CoordType &P(int i) const { switch(i) { case 0 : return e0.v->cP(); case 1 : return e1.v->cP(); case 2 : return e0.VFlip()->cP(); default: assert(0); } return e0.v->cP(); } ScalarType quality; ScalarType angle; //std::vector* vf; TrivialEar(){} TrivialEar(const PosType & ep) { e0=ep; assert(e0.IsBorder()); e1=e0; e1.NextB(); n=Normal(*this); ComputeQuality(); ComputeAngle(); } /// Compute the angle of the two edges of the ear. // it tries to make the computation in a precision safe way. // the angle computation takes into account the case of reversed ears void ComputeAngle() { angle=Angle(cP(2)-cP(0), cP(1)-cP(0)); ScalarType flipAngle = n * e0.v->N(); if(flipAngle<0) angle = (2.0 *(float)M_PI) - angle; } virtual inline bool operator < ( const TrivialEar & c ) const { return quality < c.quality; } bool IsNull(){return e0.IsNull() || e1.IsNull();} void SetNull(){e0.SetNull();e1.SetNull();} virtual void ComputeQuality() { quality = QualityFace(*this) ; }; bool IsUpToDate() {return ( e0.IsBorder() && e1.IsBorder());}; // An ear is degenerated if both of its two endpoints are non manifold. bool IsDegen(const int nonManifoldBit) { if(e0.VFlip()->IsUserBit(nonManifoldBit) && e1.V()->IsUserBit(nonManifoldBit)) return true; else return false; } bool IsConcave() const {return(angle > (float)M_PI);} virtual bool Close(PosType &np0, PosType &np1, FaceType * f) { // simple topological check if(e0.f==e1.f) { //printf("Avoided bad ear"); return false; } //usato per generare una delle due nuove orecchie. PosType ep=e0; ep.FlipV(); ep.NextB(); ep.FlipV(); // he precedente a e0 PosType en=e1; en.NextB(); // he successivo a e1 (*f).V(0) = e0.VFlip(); (*f).V(1) = e0.v; (*f).V(2) = e1.v; ComputeNormal(*f); (*f).FFp(0) = e0.f; (*f).FFi(0) = e0.z; (*f).FFp(1) = e1.f; (*f).FFi(1) = e1.z; (*f).FFp(2) = f; (*f).FFi(2) = 2; e0.f->FFp(e0.z)=f; e0.f->FFi(e0.z)=0; e1.f->FFp(e1.z)=f; e1.f->FFi(e1.z)=1; // caso ear degenere per buco triangolare if(ep==en) { //printf("Closing the last triangle"); f->FFp(2)=en.f; f->FFi(2)=en.z; en.f->FFp(en.z)=f; en.f->FFi(en.z)=2; np0.SetNull(); np1.SetNull(); } // Caso ear non manifold a else if(ep.v==en.v) { //printf("Ear Non manif A\n"); PosType enold=en; en.NextB(); f->FFp(2)=enold.f; f->FFi(2)=enold.z; enold.f->FFp(enold.z)=f; enold.f->FFi(enold.z)=2; np0=ep; np1=en; } // Caso ear non manifold b else if(ep.VFlip()==e1.v) { //printf("Ear Non manif B\n"); PosType epold=ep; ep.FlipV(); ep.NextB(); ep.FlipV(); f->FFp(2)=epold.f; f->FFi(2)=epold.z; epold.f->FFp(epold.z)=f; epold.f->FFi(epold.z)=2; np0=ep; // assign the two new np1=en; // pos that denote the ears } else // caso standard // Now compute the new ears; { np0=ep; np1=PosType(f,2,e1.v); } return true; } }; //Ear with FillHoleMinimumWeight's quality policy template class MinimumWeightEar : public TrivialEar { public: static float &DiedralWeight() { static float _dw=1.0; return _dw;} typedef TrivialEar TE; typename MESH::ScalarType dihedralRad; typename MESH::ScalarType aspectRatio; const char * Dump() { static char buf[200]; if(this->IsConcave()) sprintf(buf,"Dihedral -(deg) %6.2f Quality %6.2f\n",math::ToDeg(dihedralRad),aspectRatio); else sprintf(buf,"Dihedral (deg) %6.2f Quality %6.2f\n",math::ToDeg(dihedralRad),aspectRatio); return buf; } MinimumWeightEar(){} //MinimumWeightEar(const PosType & ep) : TrivialEar(ep) MinimumWeightEar(const typename face::Pos& ep) : TrivialEar(ep) { ComputeQuality(); } // In the heap, by default, we retrieve the LARGEST value, // so if we need the ear with minimal dihedral angle, we must reverse the sign of the comparison. // The concave elements must be all in the end of the heap, sorted accordingly, // So if only one of the two ear is Concave that one is always the minimum one. // the pow function is here just to give a way to play with different weighting schemas, balancing in a different way virtual inline bool operator < ( const MinimumWeightEar & c ) const { if(TE::IsConcave() == c.IsConcave()) { return (pow(dihedralRad,DiedralWeight())/aspectRatio) > (pow(c.dihedralRad,DiedralWeight())/c.aspectRatio); } if(TE::IsConcave()) return true; // assert(c.IsConcave()); return false; } // the real core of the whole hole filling strategy. virtual void ComputeQuality() { //compute quality by (dihedral ancgle, area/sum(edge^2) ) Point3f n1=TE::e0.FFlip()->cN(); Point3f n2=TE::e1.FFlip()->cN(); dihedralRad = std::max(Angle(TE::n,n1),Angle(TE::n,n2)); aspectRatio = QualityFace(*this); } }; //Ear for selfintersection algorithm template class SelfIntersectionEar : public MinimumWeightEar { public: typedef typename MESH::FaceType FaceType; typedef typename MESH::FacePointer FacePointer; typedef typename face::Pos PosType; typedef typename MESH::ScalarType ScalarType; typedef typename MESH::CoordType CoordType; static std::vector &AdjacencyRing() { static std::vector ar; return ar; } SelfIntersectionEar(){} SelfIntersectionEar(const PosType & ep):MinimumWeightEar(ep){} virtual bool Close(PosType &np0, PosType &np1, FacePointer f) { PosType ep=this->e0; ep.FlipV(); ep.NextB(); ep.FlipV(); // he precedente a e0 PosType en=this->e1; en.NextB(); // he successivo a e1 //costruisco la faccia e poi testo, o copio o butto via. (*f).V(0) = this->e0.VFlip(); (*f).V(1) = this->e0.v; (*f).V(2) = this->e1.v; (*f).FFp(0) = this->e0.f; (*f).FFi(0) = this->e0.z; (*f).FFp(1) = this->e1.f; (*f).FFi(1) = this->e1.z; (*f).FFp(2) = f; (*f).FFi(2) = 2; int a1, a2; a1= this->e0.z; a2= this->e1.z; this->e0.f->FFp(this->e0.z)=f; this->e0.f->FFi(this->e0.z)=0; this->e1.f->FFp(this->e1.z)=f; this->e1.f->FFi(this->e1.z)=1; typename std::vector< FacePointer >::iterator it; for(it = this->AdjacencyRing().begin();it!= this->AdjacencyRing().end();++it) { if(!(*it)->IsD()) if( tri::Clean::TestIntersection(&(*f),*it)) { this->e0.f->FFp(this->e0.z)= this->e0.f; this->e0.f->FFi(this->e0.z)=a1; this->e1.f->FFp(this->e1.z)= this->e1.f; this->e1.f->FFi(this->e1.z)=a2; return false; } } //return ((TrivialEar *)this)->Close(np0,np1,f); this->e0.f->FFp(this->e0.z)= this->e0.f; this->e0.f->FFi(this->e0.z)=a1; this->e1.f->FFp(this->e1.z)=this->e1.f; this->e1.f->FFi(this->e1.z)=a2; bool ret=TrivialEar::Close(np0,np1,f); if(ret) AdjacencyRing().push_back(f); return ret; } }; // Funzione principale per chiudier un buco in maniera topologicamente corretta. // Gestisce situazioni non manifold ragionevoli // (tutte eccetto quelle piu' di 2 facce per 1 edge). // Controlla che non si generino nuove situazioni non manifold chiudendo orecchie // che sottendono un edge che gia'esiste. template class Hole { public: typedef typename MESH::VertexType VertexType; typedef typename MESH::VertexPointer VertexPointer; typedef typename MESH::ScalarType ScalarType; typedef typename MESH::FaceType FaceType; typedef typename MESH::FacePointer FacePointer; typedef typename MESH::FaceIterator FaceIterator; typedef typename MESH::CoordType CoordType; typedef typename vcg::Box3 Box3Type; typedef typename face::Pos PosType; public: class Info { public: Info(){} Info(PosType const &pHole, int const pHoleSize, Box3 &pHoleBB) { p=pHole; size=pHoleSize; bb=pHoleBB; } PosType p; int size; Box3Type bb; bool operator < (const Info & hh) const {return size < hh.size;} ScalarType Perimeter() { ScalarType sum=0; PosType ip = p; do { sum+=Distance(ip.v->cP(),ip.VFlip()->cP()); ip.NextB(); } while (ip != p); return sum; } // Support function to test the validity of a single hole loop // for now it test only that all the edges are border; // The real test should check if all non manifold vertices // are touched only by edges belonging to this hole loop. bool CheckValidity() { if(!p.IsBorder()) return false; PosType ip=p;ip.NextB(); for(;ip!=p;ip.NextB()) { if(!ip.IsBorder()) return false; } return true; } }; template static void FillHoleEar(MESH &m, Info &h ,int UBIT, std::vector &app,std::vector *vf =0) { //Aggiungo le facce e aggiorno il puntatore alla faccia! FaceIterator f = tri::Allocator::AddFaces(m, h.size-2, app); assert(h.p.f >= &*m.face.begin()); assert(h.p.f <= &m.face.back()); assert(h.p.IsBorder());//test fondamentale altrimenti qualcosa s'e' rotto! std::vector< EAR > H; H.reserve(h.size); int nmBit= VertexType::NewBitFlag(); // non manifoldness bit //First loops around the hole to mark non manifold vertices. PosType ip = h.p; // Pos iterator do{ ip.V()->ClearUserBit(nmBit); ip.V()->ClearV(); ip.NextB(); } while(ip!=h.p); ip = h.p; // Re init the pos iterator for another loop (useless if everithing is ok!!) do{ if(!ip.V()->IsV()) ip.V()->SetV(); // All the vertexes that are visited more than once are non manifold else ip.V()->SetUserBit(nmBit); ip.NextB(); } while(ip!=h.p); PosType fp = h.p; do{ EAR app = EAR(fp); H.push_back( app ); //printf("Adding ear %s ",app.Dump()); fp.NextB(); assert(fp.IsBorder()); }while(fp!=h.p); int cnt=h.size; make_heap(H.begin(), H.end()); //finche' il buco non e' chiuso o non ci sono piu' orecchie da analizzare. while( cnt > 2 && !H.empty() ) { //printf("Front of the heap is %s", H.front().Dump()); pop_heap(H.begin(), H.end()); // retrieve the MAXIMUM value and put in the back; PosType ep0,ep1; EAR BestEar=H.back(); H.pop_back(); if(BestEar.IsUpToDate() && !BestEar.IsDegen(nmBit)) { if(BestEar.Close(ep0,ep1,&*f)) { if(!ep0.IsNull()){ H.push_back(EAR(ep0)); push_heap( H.begin(), H.end()); } if(!ep1.IsNull()){ H.push_back(EAR(ep1)); push_heap( H.begin(), H.end()); } --cnt; f->SetUserBit(UBIT); if(vf != 0) (*vf).push_back(*f); ++f; } }//is update() }//fine del while principale. //tolgo le facce non utilizzate. while(f!=m.face.end()) { (*f).SetD(); ++f; m.fn--; } VertexType::DeleteBitFlag(nmBit); // non manifoldness bit } template static void EarCuttingFill(MESH &m, int sizeHole,bool Selected = false, CallBackPos *cb=0) { std::vector< Info > vinfo; int UBIT = GetInfo(m, Selected,vinfo); typename std::vector::iterator ith; //Info app; int ind=0; std::vector vfp; for(ith = vinfo.begin(); ith!= vinfo.end(); ++ith) vfp.push_back( &(*ith).p.f ); for(ith = vinfo.begin(); ith!= vinfo.end(); ++ith) { ind++; if(cb) (*cb)(ind*100/vinfo.size(),"Closing Holes"); if((*ith).size < sizeHole){ FillHoleEar< EAR >(m, *ith,UBIT,vfp); } } FaceIterator fi; for(fi = m.face.begin(); fi!=m.face.end(); ++fi) { if(!(*fi).IsD()) (*fi).ClearUserBit(UBIT); } } template static void EarCuttingIntersectionFill(MESH &m, int sizeHole,bool Selected = false) { std::vector vinfo; int UBIT = GetInfo(m, Selected,vinfo); std::vector vf; PosType sp; PosType ap; typename std::vector::iterator ith; // collect the face pointer that has to be updated by the various addfaces std::vector vfpOrig; for(ith = vinfo.begin(); ith!= vinfo.end(); ++ith) vfpOrig.push_back( &(*ith).p.f ); for(ith = vinfo.begin(); ith!= vinfo.end(); ++ith) { if((*ith).size < sizeHole){ std::vector vfp; vfp=vfpOrig; EAR::AdjacencyRing().clear(); //Loops around the hole to collect the races . PosType ip = (*ith).p; do { PosType inp = ip; do { inp.FlipE(); inp.FlipF(); EAR::AdjacencyRing().push_back(inp.f); } while(!inp.IsBorder()); ip.NextB(); }while(ip != (*ith).p); typename std::vector::iterator fpi; for(fpi=EAR::AdjacencyRing().begin();fpi!=EAR::AdjacencyRing().end();++fpi) vfp.push_back( &*fpi ); FillHoleEar(m, *ith,UBIT,vfp,&vf); EAR::AdjacencyRing().clear(); } } FaceIterator fi; for(fi = m.face.begin(); fi!=m.face.end(); ++fi) { if(!(*fi).IsD()) (*fi).ClearUserBit(UBIT); } } static int GetInfo(MESH &m,bool Selected ,std::vector& VHI) { FaceIterator fi; int UBIT = FaceType::LastBitFlag(); for(fi = m.face.begin(); fi!=m.face.end(); ++fi) { if(!(*fi).IsD()) { if(Selected && !(*fi).IsS()) { //se devo considerare solo i triangoli selezionati e //quello che sto considerando non lo e' lo marchio e vado avanti (*fi).SetUserBit(UBIT); } else { for(int j =0; j<3 ; ++j) { if( face::IsBorder(*fi,j) && !(*fi).IsUserBit(UBIT) ) {//Trovato una faccia di bordo non ancora visitata. (*fi).SetUserBit(UBIT); PosType sp(&*fi, j, (*fi).V(j)); PosType fp=sp; int holesize=0; Box3Type hbox; hbox.Add(sp.v->cP()); //printf("Looping %i : (face %i edge %i) \n", VHI.size(),sp.f-&*m.face.begin(),sp.z); sp.f->SetUserBit(UBIT); do { sp.f->SetUserBit(UBIT); hbox.Add(sp.v->cP()); ++holesize; sp.NextB(); sp.f->SetUserBit(UBIT); assert(sp.IsBorder()); }while(sp != fp); //ho recuperato l'inofrmazione su tutto il buco VHI.push_back( Info(sp,holesize,hbox) ); } }//for sugli edge del triangolo }//S & !S }//!IsD() }//for principale!!! return UBIT; } //Minimum Weight Algorithm class Weight { public: Weight() { ang = 180; ar = FLT_MAX ;} Weight( float An, float Ar ) { ang=An ; ar= Ar;} ~Weight() {} float angle() const { return ang; } float area() const { return ar; } Weight operator+( const Weight & other ) const {return Weight( std::max( angle(), other.angle() ), area() + other.area());} bool operator<( const Weight & rhs ) const {return ( angle() < rhs.angle() ||(angle() == rhs.angle() && area() < rhs.area())); } private: float ang; float ar; }; /* \ / \/ v1*---------*v4 / \ / / \ / / \ / /ear \ / *---------*- | v3 v2\ */ static float ComputeDihedralAngle(CoordType p1,CoordType p2,CoordType p3,CoordType p4) { CoordType n1 = NormalizedNormal(p1,p3,p2); CoordType n2 = NormalizedNormal(p1,p2,p4); return math::ToDeg(AngleN(n1,n2)); } static bool existEdge(PosType pi,PosType pf) { PosType app = pi; PosType appF = pi; PosType tmp; assert(pi.IsBorder()); appF.NextB(); appF.FlipV(); do { tmp = app; tmp.FlipV(); if(tmp.v == pf.v) return true; app.FlipE(); app.FlipF(); if(app == pi)return false; }while(app != appF); return false; } static Weight computeWeight( int i, int j, int k, std::vector pv, std::vector< std::vector< int > > v) { PosType pi = pv[i]; PosType pj = pv[j]; PosType pk = pv[k]; //test complex edge if(existEdge(pi,pj) || existEdge(pj,pk)|| existEdge(pk,pi) ) { return Weight(); } // Return an infinite weight, if one of the neighboring patches // could not be created. if(v[i][j] == -1){return Weight();} if(v[j][k] == -1){return Weight();} //calcolo il massimo angolo diedrale, se esiste. float angle = 0.0f; PosType px; if(i + 1 == j) { px = pj; px.FlipE(); px.FlipV(); angle = std::max(angle , ComputeDihedralAngle(pi.v->P(), pj.v->P(), pk.v->P(), px.v->P()) ); } else { angle = std::max( angle, ComputeDihedralAngle(pi.v->P(),pj.v->P(), pk.v->P(), pv[ v[i][j] ].v->P())); } if(j + 1 == k) { px = pk; px.FlipE(); px.FlipV(); angle = std::max(angle , ComputeDihedralAngle(pj.v->P(), pk.v->P(), pi.v->P(), px.v->P()) ); } else { angle = std::max( angle, ComputeDihedralAngle(pj.v->P(),pk.v->P(), pi.v->P(), pv[ v[j][k] ].v->P())); } if( i == 0 && k == (int)v.size() - 1) { px = pi; px.FlipE(); px.FlipV(); angle = std::max(angle , ComputeDihedralAngle(pk.v->P(), pi.v->P(), pj.v->P(),px.v->P() ) ); } ScalarType area = ( (pj.v->P() - pi.v->P()) ^ (pk.v->P() - pi.v->P()) ).Norm() * 0.5; return Weight(angle, area); } static void calculateMinimumWeightTriangulation(MESH &m, FaceIterator f,std::vector vv ) { std::vector< std::vector< Weight > > w; //matrice dei pesi minimali di ogni orecchio preso in conzideraione std::vector< std::vector< int > > vi;//memorizza l'indice del terzo vertice del triangolo //hole size int nv = vv.size(); w.clear(); w.resize( nv, std::vector( nv, Weight() ) ); vi.resize( nv, std::vector( nv, 0 ) ); //inizializzo tutti i pesi possibili del buco for ( int i = 0; i < nv-1; ++i ) w[i][i+1] = Weight( 0, 0 ); //doppio ciclo for per calcolare di tutti i possibili triangoli i loro pesi. for ( int j = 2; j < nv; ++j ) { for ( int i = 0; i + j < nv; ++i ) { //per ogni triangolazione mi mantengo il minimo valore del peso tra i triangoli possibili Weight minval; //indice del vertice che da il peso minimo nella triangolazione corrente int minIndex = -1; //ciclo tra i vertici in mezzo a i due prefissati for ( int m = i + 1; m < i + j; ++m ) { Weight a = w[i][m]; Weight b = w[m][i+j]; Weight newval = a + b + computeWeight( i, m, i+j, vv, vi); if ( newval < minval ) { minval = newval; minIndex = m; } } w[i][i+j] = minval; vi[i][i+j] = minIndex; } } //Triangulate int i, j; i=0; j=nv-1; triangulate(m,f, i, j, vi, vv); while(f!=m.face.end()) { (*f).SetD(); ++f; m.fn--; } } static void triangulate(MESH &m, FaceIterator &f,int i, int j, std::vector< std::vector > vi, std::vector vv) { if(i + 1 == j){return;} if(i==j)return; int k = vi[i][j]; if(k == -1) return; //Setto i vertici f->V(0) = vv[i].v; f->V(1) = vv[k].v; f->V(2) = vv[j].v; f++; triangulate(m,f,i,k,vi,vv); triangulate(m,f,k,j,vi,vv); } static void MinimumWeightFill(MESH &m, int holeSize, bool Selected) { FaceIterator fi; std::vector vvi; std::vector vfp; std::vector vinfo; typename std::vector::iterator VIT; int UBIT = GetInfo(m, Selected,vinfo); for(VIT = vinfo.begin(); VIT != vinfo.end();++VIT) { vvi.push_back(VIT->p); } typename std::vector::iterator ith; typename std::vector::iterator ithn; typename std::vector::iterator itf; std::vector app; PosType ps; std::vector tr; std::vector vf; for(ith = vvi.begin(); ith!= vvi.end(); ++ith) { tr.clear(); vf.clear(); app.clear(); vfp.clear(); ps = *ith; getBoundHole(ps,app); if(app.size() <= holeSize) { typename std::vector::iterator itP; std::vector vfp; for(ithn = vvi.begin(); ithn!= vvi.end(); ++ithn) vfp.push_back(&(ithn->f)); for(itP = app.begin (); itP != app.end ();++itP) vfp.push_back( &(*itP).f ); //aggiungo le facce FaceIterator f = tri::Allocator::AddFaces(m, (app.size()-2) , vfp); calculateMinimumWeightTriangulation(m,f, app); } } } static void getBoundHole (PosType sp,std::vector&ret) { PosType fp = sp; //take vertex around the hole do { assert(fp.IsBorder()); ret.push_back(fp); fp.NextB(); }while(sp != fp); } };//close class Hole } // end namespace } #endif qutemol/vcg/vcg/complex/trimesh/subset.h0000444000175000017500000001303710755305357016776 0ustar mbamba/**************************************************************************** * VCGLib o o * * Visual and Computer Graphics Library o o * * _ O _ * * Copyright(C) 2004 \/)\/ * * Visual Computing Lab /\/| * * ISTI - Italian National Research Council | * * \ * * All rights reserved. * * * * 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. * * * * 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 (http://www.gnu.org/licenses/gpl.txt) * * for more details. * * * ****************************************************************************/ /**************************************************************************** History $Log: subset.h,v $ Revision 1.13 2008/02/15 12:51:59 ganovelli changes to use vcg::vert::ImportLocal Revision 1.12 2007/05/31 09:39:55 cignoni Small gcc compiling issues Revision 1.11 2006/07/06 12:30:32 ganovelli misleading comment removed Revision 1.10 2005/12/14 17:14:13 pietroni added assert on deleted flag condition Revision 1.9 2005/02/08 14:38:05 turini Warnings Correction Revision 1.8 2004/05/17 08:26:28 turini Changed : Parameters Order As In vcg::tetra::SubSet. Revision 1.7 2004/05/17 07:58:16 turini Minor Changes To Compile Even Without using namespace std. Revision 1.6 2004/05/14 11:43:17 turini Changed mesh ClearFlag call. Revision 1.5 2004/05/13 09:59:20 turini Added typedef typename in InsertedV Revision 1.4 2004/05/07 10:06:46 turini include Plane3 removed. Revision 1.3 2004/05/07 09:35:09 turini Added History Info ****************************************************************************/ #ifndef __VCGLIB_TRISUBSET #define __VCGLIB_TRISUBSET #include namespace vcg { namespace tri { template struct InsertedV { typedef I_MESH_TYPE IMeshType; typedef typename IMeshType::VertexPointer VertexPointer; typedef typename IMeshType::FacePointer FacePointer; InsertedV(VertexPointer _v, FacePointer _f, int _z) : v(_v), f(_f), z(_z) {} VertexPointer v; FacePointer f; int z; const bool operator <(const InsertedV & o) { return (v void SubSet(S_MESH_TYPE & m, STL_CONT & subSet) { std::vector< InsertedV > newVertices; typename STL_CONT::iterator pfi; typename S_MESH_TYPE::VertexIterator vi; typename S_MESH_TYPE::FaceIterator fi; typedef typename S_MESH_TYPE::VertexType S_VertexType; std::vector redirect; fi = vcg::tri::Allocator::AddFaces(m,subSet.size()); for(pfi=subSet.begin(); pfi!=subSet.end(); ++pfi) { assert(!(*pfi)->IsD()); // m.face.push_back(*(*pfi)); (*fi).ImportLocal(**pfi); (*fi).V(0) = (S_VertexType*)(void*)(*pfi)->V(0); (*fi).V(1) = (S_VertexType*)(void*)(*pfi)->V(1); (*fi).V(2) = (S_VertexType*)(void*)(*pfi)->V(2); ++fi; } for(fi=m.face.begin(); fi!=m.face.end(); ++fi) { newVertices.push_back(InsertedV((*fi).V(0), &(*fi),0)); newVertices.push_back(InsertedV((*fi).V(1), &(*fi),1)); newVertices.push_back(InsertedV((*fi).V(2), &(*fi),2)); } sort(newVertices.begin(), newVertices.end()); typename std::vector< InsertedV >::iterator curr, next; int pos=0; curr=next=newVertices.begin(); while(next!=newVertices.end()) { if((*curr)!=(*next)) pos++; (*next).f->V((*next).z)=(typename S_MESH_TYPE::VertexPointer)pos; curr=next; next++; } typename std::vector< InsertedV >::iterator newE=unique(newVertices.begin(), newVertices.end()); vi = vcg::tri::Allocator::AddVertices(m,newVertices.size()); for(curr=newVertices.begin(); curr!=newE; ++curr,++vi) (*vi).ImportLocal(*((*curr).v)); for(vi=m.vert.begin(); vi!=m.vert.end(); ++vi) redirect.push_back(&(*vi)); for(fi=m.face.begin(); fi!=m.face.end(); ++fi) { (*fi).V(0)=redirect[(int)(*fi).V(0)]; (*fi).V(1)=redirect[(int)(*fi).V(1)]; (*fi).V(2)=redirect[(int)(*fi).V(2)]; } m.vn=(int)m.vert.size(); m.fn=(int)m.face.size(); } } // End Namespace TriMesh } // End Namespace vcg #endif qutemol/vcg/vcg/complex/trimesh/clip.h0000444000175000017500000006372510425665000016415 0ustar mbamba/**************************************************************************** * VCGLib o o * * Visual and Computer Graphics Library o o * * _ O _ * * Copyright(C) 2004 \/)\/ * * Visual Computing Lab /\/| * * ISTI - Italian National Research Council | * * \ * * All rights reserved. * * * * 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. * * * * 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 (http://www.gnu.org/licenses/gpl.txt) * * for more details. * * * ****************************************************************************/ /**************************************************************************** History $Log: clip.h,v $ Revision 1.1 2006/05/02 14:17:36 m_di_benedetto First Commit. ****************************************************************************/ #ifndef __VCGLIB_TRI_CLIP #define __VCGLIB_TRI_CLIP #include #include namespace vcg { namespace tri { template class TriMeshClipper { public: typedef TriMeshClipper ClassType; typedef TRIMESHTYPE TriMeshType; typedef typename TriMeshType::FaceType FaceType; typedef typename FaceType::VertexType VertexType; typedef typename VertexType::CoordType CoordType; typedef typename CoordType::ScalarType ScalarType; /* static inline void Box(const Box3 & b, VERTEXINTEPOLATOR & vInterp, TriMeshType & m); Clip mesh "m" against an axis aligned box (in place version); Notes: 1) faces marked as deleted are skipped; 2) faces completely outside box are marked as deleted; 3) faces completely inside box are left unchanged; 4) faces intersecting box's sides are marked as deleted: they are replaced with proper tesselation; new vertices and faces are created, so reallocation could occour; previously saved pointers could not to be valid anymore, thus they should be updated; 5) vInterp functor must implement a n operator with signature void operator () (const VERTEX & v0, const VERTEX & v1, const VERTEX & v2, const Scalar & a, const Scalar & b, VERTEX & r); its semantic is to intepolate vertex attribute across triangle; a typical implementation is; r.P() = v0.P() + a * (v1.P() - v0.P()) + b * (v2.P() - v0.P()); // interpolate position r.N() = v0.N() + a * (v1.N() - v0.N()) + b * (v2.N() - v0.N()); // interpolate normal ... // interpolate other vertex attributes */ template static inline void Box(const Box3 & b, VERTEXINTEPOLATOR & vInterp, TriMeshType & m) { std::vector facesToDelete; ClassType::Box(b, vInterp, m, facesToDelete); for (size_t i=0; i static inline void Box(const Box3 & b, VERTEXINTEPOLATOR & vInterp, TriMeshType & m, FACEINDEXCONTAINER & facesToDelete) { if (m.fn <= 0) { return; } class VertexInfo { public: typedef VertexInfo ClassType; ScalarType fU; ScalarType fV; unsigned int idx; unsigned int tref; }; typedef std::vector VertexInfoVec; class TriangleInfo { public: typedef TriangleInfo ClassType; unsigned int v[3]; unsigned int idx; }; typedef std::vector TriangleInfoVec; class EdgeIsect { public: CoordType p; unsigned int idx; }; class EdgeIntersections { public: unsigned int n; EdgeIsect isects[6]; EdgeIntersections(void) { this->n = 0; } }; typedef stdext::hash_map UIntHMap; typedef typename UIntHMap::iterator UIntHMap_i; typedef typename UIntHMap::value_type UIntHMap_v; typedef stdext::hash_map EdgeMap; typedef typename EdgeMap::iterator EdgeMap_i; typedef typename EdgeMap::value_type EdgeMap_v; typedef typename TriMeshType::FaceIterator FaceIterator; EdgeMap edges; VertexInfoVec vInfos; TriangleInfoVec tInfos; CoordType vTriangle[4]; CoordType vClipped[64]; CoordType pvP0[64]; CoordType pvP1[64]; unsigned int numDeletedTris = 0; unsigned int numTriangles = 0; unsigned int numVertices = 0; unsigned int vIdx = (unsigned int)(m.vn); unsigned int tIdx = (unsigned int)(m.fn); ScalarType boxOffsets[6]; boxOffsets[0] = b.min[0]; boxOffsets[1] = -b.max[0]; boxOffsets[2] = b.min[1]; boxOffsets[3] = -b.max[1]; boxOffsets[4] = b.min[2]; boxOffsets[5] = -b.max[2]; UIntHMap emptyMap; EdgeIntersections emptyIsects; const ScalarType eps = (ScalarType)(1e-6); for (FaceIterator it=m.face.begin(); it!=m.face.end(); ++it) { if ((*it).IsD()) { continue; } unsigned int cc[3]; cc[0] = ClassType::BoxClipCode(boxOffsets, (*it).V(0)->P()); cc[1] = ClassType::BoxClipCode(boxOffsets, (*it).V(1)->P()); cc[2] = ClassType::BoxClipCode(boxOffsets, (*it).V(2)->P()); if ((cc[0] | cc[1] | cc[2]) == 0) { continue; } const unsigned int refT = (unsigned int)(std::distance(m.face.begin(), it)); if ((cc[0] & cc[1] & cc[2]) != 0) { facesToDelete.push_back(refT); (*it).SetD(); numDeletedTris++; continue; } facesToDelete.push_back(refT); vTriangle[0] = (*it).V(0)->P(); vTriangle[1] = (*it).V(1)->P(); vTriangle[2] = (*it).V(2)->P(); vTriangle[3] = (*it).V(0)->P(); unsigned int n, n0, n1; ClipPolygonLine(0, b.min[0], vTriangle, 4, pvP1, n1); ClipPolygonLine(1, b.max[0], pvP1, n1, pvP0, n0); ClipPolygonLine(2, b.min[1], pvP0, n0, pvP1, n1); ClipPolygonLine(3, b.max[1], pvP1, n1, pvP0, n0); ClipPolygonLine(4, b.min[2], pvP0, n0, pvP1, n1); ClipPolygonLine(5, b.max[2], pvP1, n1, vClipped, n); assert(n < 64); unsigned int firstV, lastV; if (n > 2) { if (vClipped[0] == vClipped[n - 1]) { n--; } const CoordType vU = vTriangle[1] - vTriangle[0]; const CoordType vV = vTriangle[2] - vTriangle[0]; const ScalarType tArea = (vU ^ vV).SquaredNorm(); if (tArea < eps) { continue; } unsigned int tvidx[3]; tvidx[0] = (*it).V(0) - &(*(m.vert.begin())); tvidx[1] = (*it).V(1) - &(*(m.vert.begin())); tvidx[2] = (*it).V(2) - &(*(m.vert.begin())); numTriangles += n - 2; size_t vBegin = vInfos.size(); VertexInfo vnfo; TriangleInfo tnfo; unsigned int vmin[3]; unsigned int vmax[3]; if (tvidx[0] < tvidx[1]) { vmin[0] = tvidx[0]; vmax[0] = tvidx[1]; } else { vmin[0] = tvidx[1]; vmax[0] = tvidx[0]; } if (tvidx[0] < tvidx[2]) { vmin[1] = tvidx[0]; vmax[1] = tvidx[2]; } else { vmin[1] = tvidx[2]; vmax[1] = tvidx[0]; } if (tvidx[1] < tvidx[2]) { vmin[2] = tvidx[1]; vmax[2] = tvidx[2]; } else { vmin[2] = tvidx[2]; vmax[2] = tvidx[1]; } for (unsigned int i=0; i mi = edges.insert(std::make_pair(vmin[1], emptyMap)); std::pair hi = (*(mi.first)).second.insert(std::make_pair(vmax[1], emptyIsects)); bool found = false; for (unsigned int s=0; s<(*(hi.first)).second.n; ++s) { if (vClipped[i] == (*(hi.first)).second.isects[s].p) { found = true; vnfo.idx = (*(hi.first)).second.isects[s].idx; break; } } if (!found) { vnfo.idx = vIdx++; numVertices++; vInfos.push_back(vnfo); (*(hi.first)).second.isects[(*(hi.first)).second.n].p = vClipped[i]; (*(hi.first)).second.isects[(*(hi.first)).second.n].idx = vnfo.idx; (*(hi.first)).second.n++; } } else if (vnfo.fU < eps) { std::pair mi = edges.insert(std::make_pair(vmin[0], emptyMap)); std::pair hi = (*(mi.first)).second.insert(std::make_pair(vmax[0], emptyIsects)); bool found = false; for (unsigned int s=0; s<(*(hi.first)).second.n; ++s) { if (vClipped[i] == (*(hi.first)).second.isects[s].p) { found = true; vnfo.idx = (*(hi.first)).second.isects[s].idx; break; } } if (!found) { vnfo.idx = vIdx++; numVertices++; vInfos.push_back(vnfo); (*(hi.first)).second.isects[(*(hi.first)).second.n].p = vClipped[i]; (*(hi.first)).second.isects[(*(hi.first)).second.n].idx = vnfo.idx; (*(hi.first)).second.n++; } } else if ((vnfo.fU + vnfo.fV) >= ((ScalarType)(1.0 - 1e-5))) { std::pair mi = edges.insert(std::make_pair(vmin[2], emptyMap)); std::pair hi = (*(mi.first)).second.insert(std::make_pair(vmax[2], emptyIsects)); bool found = false; for (unsigned int s=0; s<(*(hi.first)).second.n; ++s) { if (vClipped[i] == (*(hi.first)).second.isects[s].p) { found = true; vnfo.idx = (*(hi.first)).second.isects[s].idx; break; } } if (!found) { vnfo.idx = vIdx++; numVertices++; vInfos.push_back(vnfo); (*(hi.first)).second.isects[(*(hi.first)).second.n].p = vClipped[i]; (*(hi.first)).second.isects[(*(hi.first)).second.n].idx = vnfo.idx; (*(hi.first)).second.n++; } } else { vnfo.idx = vIdx++; numVertices++; vInfos.push_back(vnfo); } if (i == 0) { firstV = vnfo.idx; } if (i > 1) { tnfo.idx = tIdx++; tnfo.v[0] = firstV; tnfo.v[1] = lastV; tnfo.v[2] = vnfo.idx; tInfos.push_back(tnfo); } lastV = vnfo.idx; } } } if (numTriangles == 0) { return; } const unsigned int vSize = (unsigned int)(m.vn); const unsigned int tSize = (unsigned int)(m.fn); typedef Allocator TriMeshAllocatorType; TriMeshAllocatorType::AddVertices(m, numVertices); TriMeshAllocatorType::AddFaces(m, numTriangles); unsigned int j = vSize; for (size_t i=0; i= vSize) { const unsigned int tref = vInfos[i].tref; vInterp(*(m.face[tref].V(0)), *(m.face[tref].V(1)), *(m.face[tref].V(2)), vInfos[i].fV, vInfos[i].fU, m.vert[j]); j++; } } j = tSize; for (size_t i=0; i & b, VERTEXINTEPOLATOR & vInterp, const TriMeshType & m, TriMeshType & r); Clip mesh "m" against an axis aligned box and put resulting data in mesh "r" (out of place version); Notes: 1) input mesh is not modified; 2) faces marked as deleted are skipped; 3) vInterp functor must implement a n operator with signature void operator () (const VERTEX & v0, const VERTEX & v1, const VERTEX & v2, const Scalar & a, const Scalar & b, VERTEX & r); its semantic is to intepolate vertex attribute across triangle; a typical implementation is; r.P() = v0.P() + a * (v1.P() - v0.P()) + b * (v2.P() - v0.P()); // interpolate position r.N() = v0.N() + a * (v1.N() - v0.N()) + b * (v2.N() - v0.N()); // interpolate normal ... // interpolate other vertex attributes */ template static inline void Box(const Box3 & b, VERTEXINTEPOLATOR & vInterp, const TriMeshType & m, TriMeshType & r) { r.Clear(); if (m.fn <= 0) { return; } class VertexInfo { public: typedef VertexInfo ClassType; ScalarType fU; ScalarType fV; unsigned int idx; unsigned int tref; }; typedef std::vector VertexInfoVec; class TriangleInfo { public: typedef TriangleInfo ClassType; unsigned int v[3]; unsigned int idx; }; typedef std::vector TriangleInfoVec; class EdgeIsect { public: CoordType p; unsigned int idx; }; class EdgeIntersections { public: unsigned int n; EdgeIsect isects[6]; EdgeIntersections(void) { this->n = 0; } }; typedef stdext::hash_map UIntHMap; typedef typename UIntHMap::iterator UIntHMap_i; typedef typename UIntHMap::value_type UIntHMap_v; typedef stdext::hash_map EdgeMap; typedef typename EdgeMap::iterator EdgeMap_i; typedef typename EdgeMap::value_type EdgeMap_v; typedef stdext::hash_map UIHMap; typedef typename UIHMap::iterator UIHMap_i; typedef typename TriMeshType::ConstFaceIterator ConstFaceIterator; UIHMap origVertsMap; EdgeMap edges; VertexInfoVec vInfos; TriangleInfoVec tInfos; CoordType vTriangle[4]; CoordType vClipped[64]; CoordType pvP0[64]; CoordType pvP1[64]; unsigned int numDeletedTris = 0; unsigned int numTriangles = 0; unsigned int numVertices = 0; unsigned int vIdx = 0; unsigned int tIdx = 0; ScalarType boxOffsets[6]; boxOffsets[0] = b.min[0]; boxOffsets[1] = -b.max[0]; boxOffsets[2] = b.min[1]; boxOffsets[3] = -b.max[1]; boxOffsets[4] = b.min[2]; boxOffsets[5] = -b.max[2]; UIntHMap emptyMap; EdgeIntersections emptyIsects; const ScalarType eps = (ScalarType)(1e-6); for (ConstFaceIterator it=m.face.begin(); it!=m.face.end(); ++it) { if ((*it).IsD()) { continue; } unsigned int cc[3]; cc[0] = ClassType::BoxClipCode(boxOffsets, (*it).V(0)->P()); cc[1] = ClassType::BoxClipCode(boxOffsets, (*it).V(1)->P()); cc[2] = ClassType::BoxClipCode(boxOffsets, (*it).V(2)->P()); if ((cc[0] | cc[1] | cc[2]) == 0) { TriangleInfo tnfo; VertexInfo vnfo; tnfo.idx = tIdx++; for (int i=0; i<3; ++i) { const unsigned int v = (*it).V(i) - &(*(m.vert.begin())); std::pair hi = origVertsMap.insert(std::make_pair(v, vIdx)); if (hi.second) { vnfo.idx = v; vInfos.push_back(vnfo); tnfo.v[i] = vIdx++; } else { tnfo.v[i] = (*(hi.first)).second; } } tInfos.push_back(tnfo); continue; } if ((cc[0] & cc[1] & cc[2]) != 0) { numDeletedTris++; continue; } vTriangle[0] = (*it).V(0)->P(); vTriangle[1] = (*it).V(1)->P(); vTriangle[2] = (*it).V(2)->P(); vTriangle[3] = (*it).V(0)->P(); unsigned int n, n0, n1; ClipPolygonLine(0, b.min[0], vTriangle, 4, pvP1, n1); ClipPolygonLine(1, b.max[0], pvP1, n1, pvP0, n0); ClipPolygonLine(2, b.min[1], pvP0, n0, pvP1, n1); ClipPolygonLine(3, b.max[1], pvP1, n1, pvP0, n0); ClipPolygonLine(4, b.min[2], pvP0, n0, pvP1, n1); ClipPolygonLine(5, b.max[2], pvP1, n1, vClipped, n); assert(n < 64); unsigned int firstV, lastV; if (n > 2) { if (vClipped[0] == vClipped[n - 1]) { n--; } const CoordType vU = vTriangle[1] - vTriangle[0]; const CoordType vV = vTriangle[2] - vTriangle[0]; const ScalarType tArea = (vU ^ vV).SquaredNorm(); if (tArea < eps) { continue; } unsigned int tvidx[3]; tvidx[0] = (*it).V(0) - &(*(m.vert.begin())); tvidx[1] = (*it).V(1) - &(*(m.vert.begin())); tvidx[2] = (*it).V(2) - &(*(m.vert.begin())); unsigned int refT = (unsigned int)(std::distance(m.face.begin(), it)); numTriangles += n - 2; size_t vBegin = vInfos.size(); VertexInfo vnfo; TriangleInfo tnfo; unsigned int vmin[3]; unsigned int vmax[3]; if (tvidx[0] < tvidx[1]) { vmin[0] = tvidx[0]; vmax[0] = tvidx[1]; } else { vmin[0] = tvidx[1]; vmax[0] = tvidx[0]; } if (tvidx[0] < tvidx[2]) { vmin[1] = tvidx[0]; vmax[1] = tvidx[2]; } else { vmin[1] = tvidx[2]; vmax[1] = tvidx[0]; } if (tvidx[1] < tvidx[2]) { vmin[2] = tvidx[1]; vmax[2] = tvidx[2]; } else { vmin[2] = tvidx[2]; vmax[2] = tvidx[1]; } for (unsigned int i=0; i hi = origVertsMap.insert(std::make_pair(tvidx[0], vIdx)); if (hi.second) { vnfo.idx = tvidx[0]; vInfos.push_back(vnfo); currVIdx = vIdx++; } else { currVIdx = (*(hi.first)).second; } } else if (vClipped[i] == vTriangle[1]) { std::pair hi = origVertsMap.insert(std::make_pair(tvidx[1], vIdx)); if (hi.second) { vnfo.idx = tvidx[1]; vInfos.push_back(vnfo); currVIdx = vIdx++; } else { currVIdx = (*(hi.first)).second; } } else if (vClipped[i] == vTriangle[2]) { std::pair hi = origVertsMap.insert(std::make_pair(tvidx[2], vIdx)); if (hi.second) { vnfo.idx = tvidx[2]; vInfos.push_back(vnfo); currVIdx = vIdx++; } else { currVIdx = (*(hi.first)).second; } } else if (vnfo.fV < eps) { std::pair mi = edges.insert(std::make_pair(vmin[1], emptyMap)); std::pair hi = (*(mi.first)).second.insert(std::make_pair(vmax[1], emptyIsects)); bool found = false; for (unsigned int s=0; s<(*(hi.first)).second.n; ++s) { if (vClipped[i] == (*(hi.first)).second.isects[s].p) { found = true; vnfo.idx = (unsigned int)(-1); currVIdx = (*(hi.first)).second.isects[s].idx; break; } } if (!found) { (*(hi.first)).second.isects[(*(hi.first)).second.n].p = vClipped[i]; (*(hi.first)).second.isects[(*(hi.first)).second.n].idx = vIdx; (*(hi.first)).second.n++; vnfo.idx = (unsigned int)(-1); numVertices++; vInfos.push_back(vnfo); currVIdx = vIdx++; } } else if (vnfo.fU < eps) { std::pair mi = edges.insert(std::make_pair(vmin[0], emptyMap)); std::pair hi = (*(mi.first)).second.insert(std::make_pair(vmax[0], emptyIsects)); bool found = false; for (unsigned int s=0; s<(*(hi.first)).second.n; ++s) { if (vClipped[i] == (*(hi.first)).second.isects[s].p) { found = true; vnfo.idx = (unsigned int)(-1); currVIdx = (*(hi.first)).second.isects[s].idx; break; } } if (!found) { (*(hi.first)).second.isects[(*(hi.first)).second.n].p = vClipped[i]; (*(hi.first)).second.isects[(*(hi.first)).second.n].idx = vIdx; (*(hi.first)).second.n++; vnfo.idx = (unsigned int)(-1); numVertices++; vInfos.push_back(vnfo); currVIdx = vIdx++; } } else if ((vnfo.fU + vnfo.fV) >= ((ScalarType)(1.0 - 1e-5))) { std::pair mi = edges.insert(std::make_pair(vmin[2], emptyMap)); std::pair hi = (*(mi.first)).second.insert(std::make_pair(vmax[2], emptyIsects)); bool found = false; for (unsigned int s=0; s<(*(hi.first)).second.n; ++s) { if (vClipped[i] == (*(hi.first)).second.isects[s].p) { found = true; vnfo.idx = (unsigned int)(-1); currVIdx = (*(hi.first)).second.isects[s].idx; break; } } if (!found) { (*(hi.first)).second.isects[(*(hi.first)).second.n].p = vClipped[i]; (*(hi.first)).second.isects[(*(hi.first)).second.n].idx = vIdx; (*(hi.first)).second.n++; vnfo.idx = (unsigned int)(-1); numVertices++; vInfos.push_back(vnfo); currVIdx = vIdx++; } } else { vnfo.idx = (unsigned int)(-1); numVertices++; vInfos.push_back(vnfo); currVIdx = vIdx++; } if (i == 0) { firstV = currVIdx; } if (i > 1) { tnfo.idx = tIdx++; tnfo.v[0] = firstV; tnfo.v[1] = lastV; tnfo.v[2] = currVIdx; tInfos.push_back(tnfo); } lastV = currVIdx; } } } if (tInfos.empty()) { return; } const unsigned int vSize = (unsigned int)(m.vn); const unsigned int tSize = (unsigned int)(m.fn); typedef Allocator TriMeshAllocatorType; TriMeshAllocatorType::AddVertices(r, (int)(vInfos.size())); TriMeshAllocatorType::AddFaces(r, (int)(tInfos.size())); for (size_t i=0; i value + eps; break; case 2: flag = p_in[1] + eps < value; break; case 3: flag = p_in[1] > value + eps; break; case 4: flag = p_in[2] + eps < value; break; case 5: flag = p_in[2] > value + eps; break; default: break; } return (flag); } static inline void CrossPoint(int mode, const ScalarType & value, const CoordType & SP, const CoordType & PP, CoordType & p_out) { switch(mode) { case 0: case 1: p_out[0] = value; if ((PP[0] - SP[0]) == ((ScalarType)(0))) { p_out[1] = PP[1]; p_out[2] = PP[2]; } else { p_out[1] = SP[1] + (value - SP[0]) * (PP[1] - SP[1]) / (PP[0] - SP[0]); p_out[2] = SP[2] + (value - SP[0]) * (PP[2] - SP[2]) / (PP[0] - SP[0]); } break; case 2: case 3: p_out[1] = value; if ((PP[1] - SP[1]) == ((ScalarType)(0))) { p_out[0] = PP[0]; p_out[2] = PP[2]; } else { p_out[0] = SP[0] + (value - SP[1]) * (PP[0] - SP[0]) / (PP[1] - SP[1]); p_out[2] = SP[2] + (value - SP[1]) * (PP[2] - SP[2]) / (PP[1] - SP[1]); } break; case 4: case 5: p_out[2] = value; if ((PP[2] - SP[2]) == ((ScalarType)(0))) { p_out[0] = PP[0]; p_out[1] = PP[1]; } else { p_out[0] = SP[0] + (value - SP[2]) * (PP[0] - SP[0]) / (PP[2] - SP[2]); p_out[1] = SP[1] + (value - SP[2]) * (PP[1] - SP[1]) / (PP[2] - SP[2]); } break; default: break; } } static inline void ClipPolygonLine(int mode, const ScalarType & value, CoordType * P_in, unsigned int n_in, CoordType * P_out, unsigned int & n_out) { unsigned int ps; CoordType * SP; CoordType * PP; n_out = 0; SP = &P_in[n_in-1]; if (ClassType::InRegion(mode, value, *SP)) { ps = 0; } else { ps = 2; } for(unsigned int i=0; i> 1) | ((ClassType::InRegion(mode, value, *PP)) ? (0) : (2)); switch(ps) { case 0: break; case 1: ClassType::CrossPoint(mode, value, *SP, *PP, P_out[n_out]); n_out++; break; case 2: ClassType::CrossPoint(mode, value, *SP, *PP, P_out[n_out]); n_out++; P_out[n_out] = *PP; n_out++; break; case 3: P_out[n_out] = *PP; n_out++; break; default: break; } SP = PP; } } }; } // end namespace tri } // end namespace vcg #endif // __VCGLIB_TRI_CLIP qutemol/vcg/vcg/complex/trimesh/edge_collapse.h0000444000175000017500000002145710705165375020263 0ustar mbamba/**************************************************************************** * VCGLib o o * * Visual and Computer Graphics Library o o * * _ O _ * * Copyright(C) 2004 \/)\/ * * Visual Computing Lab /\/| * * ISTI - Italian National Research Council | * * \ * * All rights reserved. * * * * 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. * * * * 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 (http://www.gnu.org/licenses/gpl.txt) * * for more details. * * * ****************************************************************************/ /**************************************************************************** History $Log: edge_collapse.h,v $ Revision 1.17 2007/10/16 16:46:53 cignoni Added Allocator::DeleteFace and Allocator::DeleteVertex; Now the use of SetD() should be deprecated. Revision 1.16 2006/10/07 15:04:25 cignoni removed a useless include Revision 1.15 2005/10/12 10:36:26 cignoni Removed unused local type Edge. Now it use the standard simplex edge. Revision 1.14 2004/12/10 01:04:42 cignoni better comments Revision 1.13 2004/11/23 10:34:45 cignoni passed parameters by reference in many funcs and gcc cleaning ****************************************************************************/ #ifndef __VCG_TETRA_TRI_COLLAPSE #define __VCG_TETRA_TRI_COLLAPSE #include #include #include namespace vcg{ namespace tri{ /** \addtogroup trimesh */ /*@{*/ /** This a static utility class for the edge collapse. It provides a common set of useful function for actually making an edge collapse over a trimesh. See also the corresponding class in the local optimization framework called TriEdgeCollapse **/ template class EdgeCollapse { public: /// The tetrahedral mesh type typedef TRI_MESH_TYPE TriMeshType; /// The tetrahedron type typedef typename TriMeshType::FaceType FaceType; /// The vertex type typedef typename FaceType::VertexType VertexType; /// The vertex iterator type typedef typename TriMeshType::VertexIterator VertexIterator; /// The tetra iterator type typedef typename TriMeshType::FaceIterator FaceIterator; /// The coordinate type typedef typename FaceType::VertexType::CoordType CoordType; /// The scalar type typedef typename TriMeshType::VertexType::ScalarType ScalarType; ///the container of tetrahedron type typedef typename TriMeshType::FaceContainer FaceContainer; ///the container of vertex type typedef typename TriMeshType::VertContainer VertContainer; ///half edge type typedef typename TriMeshType::FaceType::EdgeType EdgeType; /// vector of pos typedef typename std::vector EdgeVec; ///of VFIterator typedef typename vcg::face::VFIterator VFI; /// vector of VFIterator typedef typename std::vector > VFIVec; /// Default Constructor EdgeCollapse() { }; ~EdgeCollapse() { }; static VFIVec & AV0(){static VFIVec av0; return av0;} static VFIVec & AV1(){static VFIVec av1; return av1;} static VFIVec & AV01(){static VFIVec av01; return av01;} void FindSets(EdgeType &p) { VertexType * v0 = p.V(0); VertexType * v1 = p.V(1); AV0().clear(); // Facce incidenti in v0 AV1().clear(); // Facce incidenti in v1 AV01().clear(); // Facce incidenti in v0 e v1 VFI x; for( x.f = v0->VFp(), x.z = v0->VFi(); x.f!=0; ++x) { int zv1 = -1; for(int j=0;j<3;++j) if( x.f->V(j)==&*v1 ) { zv1 = j; break; } if(zv1==-1) AV0().push_back( x ); // la faccia x.f non ha il vertice v1 => e' incidente solo in v0 else AV01().push_back( x ); } for( x.f = v1->VFp(), x.z = v1->VFi(); x.f!=0; ++x ) { int zv0 = -1; for(int j=0;j<3;++j) if( x.f->V(j)==&*v0 ) { zv0 = j; break; } if(zv0==-1) AV1().push_back( x ); // la faccia x.f non ha il vertice v1 => e' incidente solo in v0 } } bool LinkConditions(EdgeType pos){ const int ADJ_1 = TriMeshType::VertexType::NewBitFlag(); const int ADJ_E = TriMeshType::VertexType::NewBitFlag(); //enum {ADJ_1= MeshType::VertexType::USER0, // ADJ_E= MeshType::VertexType::USER0<<1} ; // const int ALLADJ = ADJ_1|ADJ_E; const int NOTALLADJ = ~(ADJ_1 | ADJ_E | TriMeshType::VertexType::VISITED); const int NOTALLADJ1 = ~(ADJ_E | TriMeshType::VertexType::VISITED); //EdgePosB x; typename vcg::face::VFIterator x; // Clear visited and adj flag for all vertices adj to v0; for(x.f = pos.V(0)->VFp(), x.z = pos.V(0)->VFi(); x.f!=0; ++x ) { x.f->V1(x.z)->Flags() &= NOTALLADJ; x.f->V2(x.z)->Flags() &= NOTALLADJ; } // Clear visited flag for all vertices adj to v1 and set them adj1 to v1; for(x.f = pos.V(1)->VFp(), x.z = pos.V(1)->VFi(); x.f!=0; ++x ) { x.f->V1(x.z)->Flags() &= NOTALLADJ1; x.f->V2(x.z)->Flags() &= NOTALLADJ1; } // Mark vertices adj to v1 as ADJ_1 and adj1 to v1; for(x.f = pos.V(1)->VFp(), x.z = pos.V(1)->VFi(); x.f!=0; ++x ) { if(x.f->V1(x.z)==pos.V(0)) x.f->V2(x.z)->Flags() |= ADJ_E | ADJ_1; else x.f->V2(x.z)->Flags() |= ADJ_1; if(x.f->V2(x.z)==pos.V(0)) x.f->V1(x.z)->Flags() |= ADJ_E | ADJ_1; else x.f->V1(x.z)->Flags() |= ADJ_1; } // compute the number of: int adj01=0; // vertices adjacents to both v0 and v1 int adje=0; // vertices adjacents to an egde (usually 2) for(x.f = pos.V(0)->VFp(), x.z = pos.V(0)->VFi(); x.f!=0; ++x ) { if(!x.f->V1(x.z)->IsV()) { x.f->V1(x.z)->SetV(); if(x.f->V1(x.z)->Flags()&ADJ_1) ++adj01; if(x.f->V1(x.z)->Flags()&ADJ_E) ++adje; } if(!x.f->V2(x.z)->IsV()) { x.f->V2(x.z)->SetV(); if(x.f->V2(x.z)->Flags()&ADJ_1) ++adj01; if(x.f->V2(x.z)->Flags()&ADJ_E) ++adje; } } //bool val=TopoCheck2(); //if(val != (adj01==adje)) printf("Wrong topo %i %i\n",adj01,adje); TriMeshType::VertexType::DeleteBitFlag(ADJ_E); TriMeshType::VertexType::DeleteBitFlag(ADJ_1); return (adj01==adje); } int DoCollapse(TriMeshType &m, EdgeType & c, const Point3 &p) { FindSets(c); typename VFIVec::iterator i; int n_face_del =0 ; //set Face Face topology if (TriMeshType::HasFFTopology()) { //int e0=c.z; //int e1=c.f->FFi(c.z); //opposite edge //FaceType *f0=c.f; //FaceType *f1=f0->FFp(c.z); // ////take right indexes //FaceType *f00=f0->FFp((e0+1)%3); //FaceType *f01=f0->FFp((e0+2)%3); //int If00=f0->FFi((e0+1)%3); //int If01=f0->FFi((e0+2)%3); // ////then attach faces //f00->FFp(If00)=f01; //f00->FFi(If00)=If01; //f01->FFp(If01)=f00; //f01->FFi(If01)=If00; ////and the ones of face f1 //f00=f1->FFp((e1+1)%3); //f01=f1->FFp((e1+2)%3); //If00=f1->FFi((e1+1)%3); //If01=f1->FFi((e1+2)%3); // ////and attach faces //f00->FFp(If00)=f01; //f00->FFi(If00)=If01; //f01->FFp(If01)=f00; //f01->FFi(If01)=If00; } for(i=AV01().begin();i!=AV01().end();++i) { FaceType & f = *((*i).f); assert(f.V((*i).z) == c.V(0)); vcg::face::VFDetach(f,((*i).z+1)%3); vcg::face::VFDetach(f,((*i).z+2)%3); Allocator::DeleteFace(m,f); //n_face_del++; } //set Vertex Face topology for(i=AV0().begin();i!=AV0().end();++i) { (*i).f->V((*i).z) = c.V(1); // In tutte le facce incidenti in v0, si sostituisce v0 con v1 (*i).f->VFp((*i).z) = (*i).f->V((*i).z)->VFp(); // e appendo la lista di facce incidenti in v1 a questa faccia (*i).f->VFi((*i).z) = (*i).f->V((*i).z)->VFi(); (*i).f->V((*i).z)->VFp() = (*i).f; (*i).f->V((*i).z)->VFi() = (*i).z; } Allocator::DeleteVertex(m,*(c.V(0))); //c.V(0)->SetD(); c.V(1)->P()=p; return n_face_del; } }; } } #endif qutemol/vcg/vcg/complex/trimesh/clustering.h0000444000175000017500000002651410714111150017631 0ustar mbamba/**************************************************************************** * VCGLib o o * * Visual and Computer Graphics Library o o * * _ O _ * * Copyright(C) 2006 \/)\/ * * Visual Computing Lab /\/| * * ISTI - Italian National Research Council | * * \ * * All rights reserved. * * * * 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. * * * * 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 (http://www.gnu.org/licenses/gpl.txt) * * for more details. * * * ****************************************************************************/ /**************************************************************************** History $Log: clustering.h,v $ Revision 1.12 2007/11/06 16:12:24 ponchio Addded check for no color in mesh Revision 1.11 2006/06/08 13:55:16 cignoni Added ColorPreserving Cellbase template. Revision 1.10 2006/05/26 10:18:11 cignoni Re-adapted to ms compilers Revision 1.9 2006/05/25 09:37:14 cignoni Many changes for the different interpretation of hash_set between gcc and .net. Probably to be completed. Revision 1.8 2006/05/24 16:42:22 m_di_benedetto Corrected bbox inflation amount in case of _cellsize != 0 Revision 1.7 2006/05/24 15:16:01 cignoni better comment to the init parameters Revision 1.6 2006/05/24 08:54:04 cignoni Added missing std:: to swap Revision 1.5 2006/05/21 06:40:31 cignoni Added DoubleFace management Revision 1.4 2006/05/19 20:49:03 m_di_benedetto Added check for empty generated mesh (prevent call to mesh allocator with zero vertices or faces). Revision 1.3 2006/05/18 22:20:53 m_di_benedetto added check for deleted faces and modified/added std namespace qualifier. Revision 1.2 2006/05/18 13:59:20 cignoni Some minor optimizations Revision 1.1 2006/05/16 21:56:06 cignoni First working Version ****************************************************************************/ #ifndef __VCGLIB_CLUSTERING #define __VCGLIB_CLUSTERING #include #include #include #include #include #include #include #include // some stuff for portable hashes... #ifdef WIN32 #ifndef __MINGW32__ #include #include #define STDEXT stdext #else #include #include #define STDEXT __gnu_cxx #endif #else #include #include #define STDEXT __gnu_cxx #endif namespace vcg{ namespace tri{ #define HASH_P0 73856093 #define HASH_P1 19349663 #define HASH_P2 83492791 class HashedPoint3i : public Point3i { public: const size_t Hash() const { return (V(0)*HASH_P0 ^ V(1)*HASH_P1 ^ V(2)*HASH_P2); } operator size_t () const {return Hash();} }; // needed for gcc compilation #ifndef _MSC_VER }} namespace STDEXT { template <> struct hash{ inline size_t operator ()(const vcg::tri::HashedPoint3i &p) const {return size_t(p);} }; } namespace vcg{ namespace tri{ #endif // template class AverageCell { typedef typename MeshType::CoordType CoordType; typedef typename MeshType::FaceType FaceType; public: inline void Add(MeshType &m, FaceType &f, int i) { p+=f.cV(i)->cP(); // we prefer to use the un-normalized face normal so small faces facing away are dropped out // and the resulting average is weighed with the size of the faces falling here. n+=f.cN(); cnt++; } AverageCell(): p(0,0,0), n(0,0,0),cnt(0){} CoordType p; CoordType n; int cnt; int id; CoordType Pos() const { return p/cnt; } Color4b Col() const {return Color4b::White;} }; template class AverageColorCell { typedef typename MeshType::CoordType CoordType; typedef typename MeshType::FaceType FaceType; public: inline void Add(MeshType &m, FaceType &f, int i) { p+=f.cV(i)->cP(); c+=CoordType(f.cV(i)->C()[0],f.cV(i)->C()[1],f.cV(i)->C()[2]); // we prefer to use the un-normalized face normal so small faces facing away are dropped out // and the resulting average is weighed with the size of the faces falling here. n+=f.cN(); cnt++; } AverageColorCell(): p(0,0,0), n(0,0,0), c(0,0,0),cnt(0){} CoordType p; CoordType n; CoordType c; int cnt; int id; Color4b Col() const { return Color4b(c[0]/cnt,c[1]/cnt,c[2]/cnt,255); } CoordType Pos() const { return p/cnt; } }; /* Metodo di clustering */ template class Clustering { public: typedef typename MeshType::ScalarType ScalarType; typedef typename MeshType::CoordType CoordType; typedef typename MeshType::VertexType VertexType; typedef typename MeshType::FaceType FaceType; typedef typename MeshType::VertexPointer VertexPointer; typedef typename MeshType::VertexIterator VertexIterator; typedef typename MeshType::FaceIterator FaceIterator; // DuplicateFace == bool means that during the clustering doublesided surface (like a thin shell) that would be clustered to a single surface // will be merged into two identical but opposite faces. // So in practice: // DuplicateFace=true a model with looks ok if you enable backface culling // DuplicateFace=false a model with looks ok if you enable doublesided lighting and disable backfaceculling bool DuplicateFaceParam; class SimpleTri { public: CellType *v[3]; const int ii(int i) const {return *((int *)(&(v[i])));} bool operator < ( const SimpleTri &p) const { return (v[2]!=p.v[2])?(v[2] v[1] ) std::swap(v[0],v[1]); // now v0 < v1 if(v[0] > v[2] ) std::swap(v[0],v[2]); // now v0 is the minimum if(v[1] > v[2] ) std::swap(v[1],v[2]); // sorted! } // Hashing Function; operator size_t () const { return (ii(0)*HASH_P0 ^ ii(1)*HASH_P1 ^ ii(2)*HASH_P2); } }; // The init function Take two parameters // _size is the approximate total number of cells composing the grid surrounding the objects (usually a large number) // eg _size==1.000.000 means a 100x100x100 grid // _cellsize is the absolute lenght of the edge of the grid cell. // eg _cellsize==2.0 means that all the vertexes in a 2.0x2.0x2.0 cell are clustered togheter // Notes: // _size is used only if the cell edge IS zero. // _cellsize gives you an absolute measure of the maximum error introduced // during the simplification (e.g. half of the cell edge lenght) void Init(Box3 _mbb, int _size, ScalarType _cellsize=0) { Grid.bbox=_mbb; ///inflate the bb calculated ScalarType infl = (_cellsize == (ScalarType)0) ? (Grid.bbox.Diag() / _size) : (_cellsize); Grid.bbox.min-=CoordType(infl,infl,infl); Grid.bbox.max+=CoordType(infl,infl,infl); Grid.dim = Grid.bbox.max - Grid.bbox.min; if( _cellsize==0) BestDim( _size, Grid.dim, Grid.siz ); else Grid.siz = Point3i::Construct(Grid.dim / _cellsize); // find voxel size Grid.voxel[0] = Grid.dim[0]/Grid.siz[0]; Grid.voxel[1] = Grid.dim[1]/Grid.siz[1]; Grid.voxel[2] = Grid.dim[2]/Grid.siz[2]; } BasicGrid Grid; #ifdef _MSC_VER STDEXT::hash_set TriSet; typedef typename STDEXT::hash_set::iterator TriHashSetIterator; #else struct SimpleTriHashFunc{ inline size_t operator ()(const SimpleTri &p) const {return size_t(p);} }; STDEXT::hash_set TriSet; typedef typename STDEXT::hash_set::iterator TriHashSetIterator; #endif STDEXT::hash_map GridCell; void Add(MeshType &m) { FaceIterator fi; for(fi=m.face.begin();fi!=m.face.end();++fi) { if ((*fi).IsD()) { continue; } HashedPoint3i pi; SimpleTri st; for(int i=0;i<3;++i) { Grid.PToIP((*fi).cV(i)->cP(), pi ); st.v[i]=&(GridCell[pi]); st.v[i]->Add(m,*(fi),i); } if( (st.v[0]!=st.v[1]) && (st.v[0]!=st.v[2]) && (st.v[1]!=st.v[2]) ) { // if we allow the duplication of faces we sort the vertex only partially (to maintain the original face orientation) if(DuplicateFaceParam) st.sortOrient(); else st.sort(); TriSet.insert(st); } // printf("Inserted %8i triangles, clustered to %8i tri and %i cells\n",distance(m.face.begin(),fi),TriSet.size(),GridCell.size()); } } void Extract(MeshType &m) { m.Clear(); if (TriSet.empty() || GridCell.empty()) { return; } Allocator::AddVertices(m,GridCell.size()); typename STDEXT::hash_map::iterator gi; int i=0; for(gi=GridCell.begin();gi!=GridCell.end();++gi) { m.vert[i].P()=(*gi).second.Pos(); if(m.vert[i].HasColor()) m.vert[i].C()=(*gi).second.Col(); (*gi).second.id=i; ++i; } Allocator::AddFaces(m,TriSet.size()); TriHashSetIterator ti; i=0; for(ti=TriSet.begin();ti!=TriSet.end();++ti) { m.face[i].V(0)=&(m.vert[(*ti).v[0]->id]); m.face[i].V(1)=&(m.vert[(*ti).v[1]->id]); m.face[i].V(2)=&(m.vert[(*ti).v[2]->id]); // if we are merging faces even when opposite we choose // the best orientation according to the averaged normal if(!DuplicateFaceParam) { CoordType N=vcg::Normal(m.face[i]); int badOrient=0; if( N*(*ti).v[0]->n <0) ++badOrient; if( N*(*ti).v[1]->n <0) ++badOrient; if( N*(*ti).v[2]->n <0) ++badOrient; if(badOrient>2) std::swap(m.face[i].V(0),m.face[i].V(1)); } i++; } } }; //end class clustering } // namespace tri } // namespace vcg #endif qutemol/vcg/vcg/complex/trimesh/textcoord_optimization.h0000444000175000017500000003240611006576221022301 0ustar mbamba/**************************************************************************** * VCGLib o o * * Visual and Computer Graphics Library o o * * _ O _ * * Copyright(C) 2004 \/)\/ * * Visual Computing Lab /\/| * * ISTI - Italian National Research Council | * * \ * * All rights reserved. * * * * 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. * * * * 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 (http://www.gnu.org/licenses/gpl.txt) * * for more details. * * * ****************************************************************************/ /**************************************************************************** History $Log: textcoord_optimization.h,v $ Revision 1.7 2008/05/02 11:35:45 cignoni removed useless code (two functions were repeated) Revision 1.6 2007/02/02 04:11:00 tarini added parameter theta (from conformal to equiareal) to AreaPresTextureOptimizer. Improved feature lists (comments). Revision 1.5 2007/02/02 01:39:58 tarini added three general-utility global functions for texture coordinates: SmoothTextureCoords, IsFoldFree, MarkFolds (see descriptions) Revision 1.4 2007/02/02 01:23:47 tarini added a few general comments on AreaPreserving optimizer, recapping optimizer features. Revision 1.3 2007/02/02 01:18:15 tarini First version: general virtual class for texture optimizers. A subclass for area preservation. ****************************************************************************/ #ifndef __VCGLIB__TEXTCOOORD_OPTIMIZATION #define __VCGLIB__TEXTCOOORD_OPTIMIZATION #include /* SINGLE PATCH TEXTURE OPTIMIZATIONS A set of classes to perform optimizations of disk->disk parametrization. Requires texture coords to be defined per vertex (replicate seams). */ namespace vcg { namespace tri { /* Base class for all Texture Optimizers*/ template class TextureOptimizer{ protected: MESH_TYPE &m; SimpleTempData isFixed; public: /* Tpyes */ typedef MESH_TYPE MeshType; typedef typename MESH_TYPE::VertexIterator VertexIterator; typedef typename MESH_TYPE::FaceIterator FaceIterator; typedef typename MESH_TYPE::VertexType VertexType; typedef typename MESH_TYPE::FaceType FaceType; typedef typename MESH_TYPE::ScalarType ScalarType; /* Access functions */ const MeshType & Mesh() const {return m;} MeshType & Mesh() {return m;} /* Constructior */ TextureOptimizer(MeshType &_m):m(_m),isFixed(_m.vert){ assert(m.HasPerVertexTexture()); } // initializes on current geometry virtual void TargetCurrentGeometry()=0; // performs an interation. Returns largest movement. virtual ScalarType Iterate()=0; // performs an iteration (faster, but it does not tell how close it is to stopping) virtual void IterateBlind()=0; // performs iteration virtual ScalarType IterateN(int step){ for (int i=0; iIterateBlind(); } if (step>1) return this->Iterate(); else return 0; } // performs iterations until convergence. bool IterateUntilConvergence(ScalarType threshold=0.0001, int maxite=5000){ int i; while (Iterate()>threshold) { if (i++>maxite) return false; } return true; } // desctuctor: free temporary field ~TextureOptimizer(){ isFixed.Stop(); }; // set the current border as fixed (forced to stay in position during text optimization) void SetBorderAsFixed(){ isFixed.Start(); for (VertexIterator v=m.vert.begin(); v!=m.vert.end(); v++) { isFixed[v]=(v->IsB())?1:0; } } // everything moves, no vertex must fixed during texture optimization) void SetNothingAsFixed(){ isFixed.Start(); for (VertexIterator v=m.vert.begin(); v!=m.vert.end(); v++) { isFixed[v]=0; } } // fix a given vertex void FixVertex(const VertexType *v, bool fix=true){ isFixed[v]=(fix)?1:0; } }; /* AREA PRESERVING TEXTURE OPTIMIZATION as in: Degener, P., Meseth, J., Klein, R. "An adaptable surface parameterization method." Proc. of the 12th International Meshing oundtable, 201213 [2003]. Features: :) - Balances angle and area distortions (best results!). :) - Can choose how to balance area and angle preservation (see SetTheta) theta=0 -> pure conformal (use MIPS instead!) theta=3 -> good balance between area and angle preservation theta>3 -> care more about area than about angles :( - Slowest method. :( - Requires a fixed boundary, else expands forever in texture space (unless theta=0). :( - Diverges in presence of flipped faces (unless theta=0). :( - Requires a speed parameter to be set. Speed too large => when close, bounces back and forth around minimum, w/o getting any closer. Lower speed => longer convercence times */ template class AreaPreservingTextureOptimizer:public TextureOptimizer{ public: /* Types */ typedef MESH_TYPE MeshType; typedef typename MESH_TYPE::VertexIterator VertexIterator; typedef typename MESH_TYPE::FaceIterator FaceIterator; typedef typename MESH_TYPE::VertexType VertexType; typedef typename MESH_TYPE::FaceType FaceType; typedef typename MESH_TYPE::ScalarType ScalarType; private: typedef TextureOptimizer Super; // superclass (commodity) // extra data per face: [0..3] -> cotangents. [4] -> area*2 SimpleTempData > data; SimpleTempData > sum; ScalarType totArea; ScalarType speed; int theta; public: // constructor and destructor AreaPreservingTextureOptimizer(MeshType &_m):Super(_m),data(_m.face),sum(_m.vert){ speed=0.001; theta=3; } ~AreaPreservingTextureOptimizer(){ data.Stop(); sum.Stop(); Super::isFixed.Stop(); } void SetSpeed(ScalarType _speed){ speed=_speed; } ScalarType GetSpeed(){ return speed; } // sets the parameter theta: // good parameters are in 1..3 // 0 = converge to pure conformal, ignore area preservation // 3 = good balance between area and conformal // >3 = area more important, angle preservation less important void SetTheta(int _theta){ theta=_theta; } int GetTheta(){ return theta; } void IterateBlind(){ /* todo: do as iterate, but without */ Iterate(); } ScalarType Iterate(){ ScalarType max; // max displacement #define v0 (f->V0(i)->T().P()) #define v1 (f->V1(i)->T().P()) #define v2 (f->V2(i)->T().P()) for (VertexIterator v=Super::m.vert.begin(); v!=Super::m.vert.end(); v++) { sum[v].Zero(); } ScalarType tot_proj_area=0; for (FaceIterator f=Super::m.face.begin(); f!=Super::m.face.end(); f++) { int i=0; double area2 = ((v1-v0) ^ (v2-v0)); tot_proj_area+=area2; } double scale= 1.0; //tot_proj_area / tot_area ; for (FaceIterator f=Super::m.face.begin(); f!=Super::m.face.end(); f++) { int i=0; ScalarType area2 = ((v1-v0) ^ (v2-v0)); for (i=0; i<3; i++){ ScalarType a = (v1-v0).Norm(), b = ((v1-v0) * (v2-v0))/a, c = area2 / a, m0= data[f][i] / area2, m1= data[f][(i+1)%3] / area2, m2= data[f][(i+2)%3] / area2, mx= (b-a)/area2, my= c/area2, // 1.0/a mA= data[f][3]/area2 * scale, e = m0*((b-a)*(b-a)+c*c) + m1*(b*b+c*c) + m2*a*a, // as obvious M1= mA + 1.0/mA, M2= mA - 1.0/mA, px= e*my, py=-e*mx, qx= m1*b+ m2*a, qy= m1*c, /* linear weightings dx= (OMEGA) * (my * M2) + (1-OMEGA) * ( px - 2.0*qx), dy= (OMEGA) * (-mx * M2) + (1-OMEGA) * ( py - 2.0*qy),*/ // exponential weighting // 2d gradient dx=// M1 //*M1 // ^ theta-1 pow(M1,theta-1) *(px*(M1+ theta*M2) - 2.0*qx*M1), dy=// M1 //*M1 // ^ theta-1 pow(M1,theta-1) *(py*(M1+ theta*M2) - 2.0*qy*M1), gy= dy/c, gx= (dx - gy*b) / a; // 3d gradient sum[f->V(i)]+= ( (v1-v0) * gx + (v2-v0) * gy ) * data[f][3]; } } max=0; // max displacement speed=0.001; for (VertexIterator v=Super::m.vert.begin(); v!=Super::m.vert.end(); v++) if ( !Super::isFixed[v] ) //if (!v->IsB()) { ScalarType n=sum[v].Norm(); if ( n > 1 ) { sum[v]/=n; n=1.0;} if ( n*speed<=0.1 ); { v->T().P()-=(sum[v] * speed ) /** scale*/; if (maxV(1)->P() - f->V(0)->P() )^(f->V(2)->P() - f->V(0)->P() )).Norm(); totArea+=area2; //if ( Super::isFixed[f->V1(0)] ) for (int i=0; i<3; i++){ data[f][i]=( (f->V1(i)->P() - f->V0(i)->P() )*(f->V2(i)->P() - f->V0(i)->P() ) )/area2; data[f][3]=area2; } } } }; /* texture coords general utility functions */ /*++++++++++++++++++++++++++++++++++++++++++*/ // returns false if any fold is present (faster than MarkFolds) template bool IsFoldFree(MESH_TYPE &m){ assert(m.HasPerVertexTexture()); typedef typename MESH_TYPE::VertexType::TextureType::PointType PointType; typedef typename MESH_TYPE::VertexType::TextureType::PointType::ScalarType ScalarType; ScalarType lastsign=0; for (typename MESH_TYPE::FaceIterator f=m.face.begin(); f!=m.face.end(); f++){ ScalarType sign=((f->V(1)->T().P()-f->V(0)->T().P()) ^ (f->V(2)->T().P()-f->V(0)->T().P())); if (sign!=0) { if (sign*lastsign<0) return false; lastsign=sign; } } return true; } // detects and marks folded faces, by setting their quality to 0 (or 1 otherwise) // returns number of folded faces template int MarkFolds(MESH_TYPE &m){ assert(m.HasPerVertexTexture()); assert(m.HasPerFaceQuality()); typedef typename MESH_TYPE::VertexType::TextureType::PointType PointType; typedef typename MESH_TYPE::VertexType::TextureType::PointType::ScalarType ScalarType; SimpleTempData sign(m.face); sign.Start(0); // first pass, determine predominant sign int npos=0, nneg=0; ScalarType lastsign=0; for (typename MESH_TYPE::FaceIterator f=m.face.begin(); f!=m.face.end(); f++){ ScalarType fsign=((f->V(1)->T().P()-f->V(0)->T().P()) ^ (f->V(2)->T().P()-f->V(0)->T().P())); if (fsign<0) { sign[f]=-1; nneg++; } if (fsign>0) { sign[f]=+1; npos++; } } // second pass, detect folded faces int res=0; short gsign= (nneg>npos)?-1:+1; for (typename MESH_TYPE::FaceIterator f=m.face.begin(); f!=m.face.end(); f++){ if (sign[f]*gsign<0){ res++; f->Q()=0; } else f->Q()=1; } sign.Stop(); return res; } // Smooths texture coords. // (can be useful to remove folds, // e.g. these created when obtaining tecture coordinates after projections) template void SmoothTextureCoords(MESH_TYPE &m){ assert(m.HasPerVertexTexture()); typedef typename MESH_TYPE::VertexType::TextureType::PointType PointType; SimpleTempData div(m.vert); SimpleTempData sum(m.vert); div.Start(); sum.Start(); for (typename MESH_TYPE::VertexIterator v=m.vert.begin(); v!=m.vert.end(); v++) { sum[v].Zero(); div[v]=0; } for (typename MESH_TYPE::FaceIterator f=m.face.begin(); f!=m.face.end(); f++){ div[f->V(0)] +=2; sum[f->V(0)] += f->V(2)->T().P(); sum[f->V(0)] += f->V(1)->T().P(); div[f->V(1)] +=2; sum[f->V(1)] += f->V(0)->T().P(); sum[f->V(1)] += f->V(2)->T().P(); div[f->V(2)] +=2; sum[f->V(2)] += f->V(1)->T().P(); sum[f->V(2)] += f->V(0)->T().P(); } for (typename MESH_TYPE::VertexIterator v=m.vert.begin(); v!=m.vert.end(); v++) // if (!v->IsB()) { if (v->div>0) { v->T().P() = sum[v]/div[v]; } } div.Stop(); sum.Stop(); } } } // End namespace vcg::tri #endif // __VCGLIB__TEXTCOOORD_OPTIMIZATION qutemol/vcg/vcg/complex/trimesh/base.h0000444000175000017500000004032611013264245016370 0ustar mbamba/**************************************************************************** * VCGLib o o * * Visual and Computer Graphics Library o o * * _ O _ * * Copyright(C) 2004 \/)\/ * * Visual Computing Lab /\/| * * ISTI - Italian National Research Council | * * \ * * All rights reserved. * * * * 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. * * * * 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 (http://www.gnu.org/licenses/gpl.txt) * * for more details. * * * ****************************************************************************/ /**************************************************************************** History $Log: base.h,v $ Revision 1.35 2008/05/16 10:57:41 cignoni missing typename Revision 1.34 2008/05/16 10:07:36 ganovelli added Trimesh destructor to purge unremoved PerVertex[PerFace]Attribute Revision 1.33 2008/05/15 16:32:27 ganovelli PerVertexAttribute and PerFaceAttribute added to Trimesh Revision 1.32 2008/04/15 10:34:07 cignoni added HasPerVertexTexCoord ( mesh ) Revision 1.31 2008/02/21 17:27:06 cignoni Added HasPerVertexColor static function Revision 1.30 2008/01/28 14:46:03 cignoni added hasPerWedgeColor and HasPerWedgeNormal Revision 1.29 2008/01/28 08:42:07 cignoni added HasPerFaceNormal and HasPerVertexNormal Revision 1.28 2007/03/12 15:38:03 tarini Texture coord name change! "TCoord" and "Texture" are BAD. "TexCoord" is GOOD. Revision 1.27 2007/02/22 09:18:41 cignoni Added guards on msvc pragmas Revision 1.26 2007/02/14 15:31:41 ganovelli Added HasPerVertexFlag Revision 1.25 2006/11/28 22:35:29 cignoni Added Consistency check in the HasVFAdj static function Revision 1.24 2006/11/07 11:29:23 cignoni Corrected some errors in the reflections Has*** functions Revision 1.23 2006/10/27 11:08:18 ganovelli added override to HasFFAdjacency , HasVFAdjacency for the optional attributes (see also complex/trimesh/allocate.h) Revision 1.22 2006/07/10 14:26:22 cignoni Minor. Added a disambiguating this at the constructor of trimesh Revision 1.21 2006/05/25 04:40:57 cignoni Updated HasPerFaceColor/Quality to the new style with mesh param. Revision 1.20 2006/05/03 21:35:31 cignoni Added new style HasPerFaceColor(m) and HasPerFaceMark(m) Revision 1.19 2005/12/02 00:05:34 cignoni Added HasFlags and a couple of missing include files Revision 1.18 2005/11/26 00:16:03 cignoni added HasPerWedgeTexture taking mesh as input. (needed for optional components) Revision 1.17 2005/11/16 22:35:47 cignoni Added missing includes (color and assert) Added texture name members Revision 1.16 2005/11/15 12:09:17 rita_borgo Changed Volume Routine, before was returning negative values Revision 1.15 2005/10/03 16:00:08 rita_borgo Minor changes Revision 1.14 2005/03/18 16:37:46 fiorin Minor changes Revision 1.13 2005/01/28 17:56:57 pietroni changed HasVFTopology function... control if both vertex and face define the vf topology Revision 1.12 2004/10/28 00:54:34 cignoni Better Doxygen documentation Revision 1.11 2004/10/07 14:25:38 ganovelli added camera and shot Revision 1.10 2004/09/08 15:15:05 ganovelli changes for gcc Revision 1.9 2004/07/15 12:03:50 ganovelli access to imark added Revision 1.8 2004/07/15 11:39:24 ganovelli IsDeleted to IsD Revision 1.7 2004/07/09 10:18:19 ganovelli added access functions to vn and fn Revision 1.6 2004/05/04 02:29:54 ganovelli removed Const from ConstFacePointer and ConstVertexPointer in the arguement function Mark, which are meant to be changed Revision 1.5 2004/03/18 16:00:10 cignoni minor changes Revision 1.4 2004/03/10 00:57:44 cignoni minor changes Revision 1.3 2004/03/07 21:54:56 cignoni some more reflection functions Revision 1.2 2004/03/04 00:08:15 cignoni First working version! Revision 1.1 2004/02/19 13:11:06 cignoni Initial commit ****************************************************************************/ #if defined(_MSC_VER) #pragma warning( disable : 4804 ) #endif #include #include #include #include #include #include #include #include /* People should subclass his vertex class from these one... */ #ifndef __VCG_MESH #define __VCG_MESH namespace vcg { namespace tri { /** \addtogroup trimesh */ /*@{*/ /*@{*/ /** Class Mesh. This is class for definition of a mesh. @param VertContainerType (Template Parameter) Specifies the type of the vertices container any the vertex type. @param FaceContainerType (Template Parameter) Specifies the type of the faces container any the face type. */ template < class VertContainerType, class FaceContainerType > class TriMesh{ public: typedef TriMesh MeshType; typedef FaceContainerType FaceContainer; typedef VertContainerType VertContainer; typedef typename VertContainer::value_type VertexType; typedef typename FaceContainer::value_type FaceType; typedef typename VertexType::ScalarType ScalarType; typedef typename VertexType::CoordType CoordType; typedef typename VertContainer::iterator VertexIterator; typedef typename FaceContainer::iterator FaceIterator; typedef typename VertContainer::const_iterator ConstVertexIterator; typedef typename FaceContainer::const_iterator ConstFaceIterator; typedef VertexType * VertexPointer; typedef const VertexType * ConstVertexPointer; typedef FaceType * FacePointer; typedef const FaceType * ConstFacePointer; typedef Box3 BoxType; /// Set of vertices VertContainer vert; /// Real number of vertices int vn; /// Set of faces FaceContainer face; /// Real number of faces int fn; /// Bounding box of the mesh Box3 bbox; /// Nomi di textures // std::vector textures; // std::vector normalmaps; class HandlesWrapper{ public: void * _handle; std::string _name; void Resize(const int & sz){((SimpleTempDataBase*)_handle)->Resize(sz);} void Reorder(std::vector & newVertIndex){((SimpleTempDataBase*)_handle)->Reorder(newVertIndex);} const bool operator<(const HandlesWrapper b) const { return(_name.empty()&&b._name.empty())?(_handle < b._handle):( _name < b._name);} }; template class PerVertexAttributeHandle{ public: PerVertexAttributeHandle( void *ah):_handle ( (SimpleTempData *)ah ){} SimpleTempData * _handle; template ATTR_TYPE & operator [](const RefType & i){return (*_handle)[i];} }; template class PerFaceAttributeHandle{ public: PerFaceAttributeHandle(void *ah):_handle ( (SimpleTempData *)ah ){} SimpleTempData * _handle; template ATTR_TYPE & operator [](const RefType & i){return (*_handle)[i];} }; std::set< HandlesWrapper> vert_attr; std::set< HandlesWrapper> face_attr; /// La camera Camera camera; // intrinsic Shot shot; // extrinsic /// Il colore della mesh private: Color4b c; public: inline const Color4b & C() const { return c; } inline Color4b & C() { return c; } /// Default constructor TriMesh():shot(camera) { fn = vn = 0; imark = 0; } /// destructor ~TriMesh() { typename std::set< HandlesWrapper>::iterator i; for( i = vert_attr.begin(); i != vert_attr.end(); ++i) delete ((SimpleTempDataBase*)(*i)._handle); for( i = face_attr.begin(); i != face_attr.end(); ++i) delete ((SimpleTempDataBase*)(*i)._handle); } inline int MemUsed() const { return sizeof(MeshType)+sizeof(VertexType)*vert.size()+sizeof(FaceType)*face.size(); } inline int MemNeeded() const { return sizeof(MeshType)+sizeof(VertexType)*vn+sizeof(FaceType)*fn; } /// Function to destroy the mesh void Clear() { vert.clear(); face.clear(); // textures.clear(); // normalmaps.clear(); vn = 0; fn = 0; } /// Reflection functions that speak about vertex and face properties. static bool HasPerVertexNormal() { return VertexType::HasNormal() ; } static bool HasPerVertexColor() { return VertexType::HasColor() ; } static bool HasPerVertexMark() { return VertexType::HasMark() ; } static bool HasPerVertexQuality() { return VertexType::HasQuality(); } static bool HasPerVertexTexCoord(){ return VertexType::HasTexCoord(); } static bool HasPerVertexFlags() { return VertexType::HasFlags(); } static bool HasPerFaceColor() { return FaceType::HasFaceColor() ; } static bool HasPerFaceNormal() { return FaceType::HasFaceNormal() ; } static bool HasPerFaceMark() { return FaceType::HasFaceMark() ; } static bool HasPerFaceQuality() { return FaceType::HasFaceQuality(); } static bool HasPerFaceFlags() { return FaceType::HasFlags(); } static bool HasPerWedgeColor() { return FaceType::HasWedgeColor() ; } static bool HasPerWedgeNormal() { return FaceType::HasWedgeNormal() ; } static bool HasPerWedgeMark() { return FaceType::HasWedgeMark() ; } static bool HasPerWedgeQuality() { return FaceType::HasWedgeQuality(); } static bool HasPerWedgeTexCoord() { return FaceType::HasWedgeTexCoord(); } static bool HasFFTopology() { return FaceType::HasFFAdjacency(); } static bool HasVFTopology() { return ((FaceType::HasVFAdjacency())&&(VertexType::HasVFAdjacency())); } static bool HasTopology() { return HasFFTopology() || HasVFTopology(); } int & SimplexNumber(){ return fn;} int & VertexNumber(){ return vn;} /// Initialize the imark-system of the faces void InitFaceIMark() { FaceIterator f; for(f=face.begin();f!=face.end();++f) if( !(*f).IsD() && (*f).IsR() && (*f).IsW() ) (*f).InitIMark(); } /// Initialize the imark-system of the vertices void InitVertexIMark() { VertexIterator vi; for(vi=vert.begin();vi!=vert.end();++vi) if( !(*vi).IsD() && (*vi).IsRW() ) (*vi).InitIMark(); } /// The incremental mark int imark; /** Access function to the incremental mark. */ inline int & IMark(){return imark;} /** Check if the vertex incremental mark matches the one of the mesh. @param v Vertex pointer */ inline bool IsMarked( ConstVertexPointer v ) const { return v->IMark() == imark; } /** Check if the face incremental mark matches the one of the mesh. @param v Face pointer */ inline bool IsMarked( ConstFacePointer f ) const { return f->IMark() == imark; } /** Set the vertex incremental mark of the vertex to the one of the mesh. @param v Vertex pointer */ inline void Mark( VertexPointer v ) const { v->IMark() = imark; } /** Set the face incremental mark of the vertex to the one of the mesh. @param v Vertex pointer */ inline void Mark( FacePointer f ) const { f->IMark() = imark; } /// Unmark the mesh inline void UnMarkAll() { ++imark; } /// Calcolo del volume di una mesh chiusa ScalarType Volume() { FaceIterator fi; int j,k; ScalarType V = 0; CoordType T,N,B; for(fi = face.begin(); fi!=face.end(); ++fi) { for(j = 0; j < 3; ++j) { /*calcolo tangente, normale e binormale (6 volte)*/ k = (j+1)%3; T = (*fi).P(k) - (*fi).P(j); T.Normalize(); B = ( (*fi).P( k ) - (*fi).P(j) ) ^ ( (*fi).P((k+1)%3) - (*fi).P(j) ) ; B.Normalize(); N = T ^ B; CoordType pj = (*fi).P(j); CoordType pk = (*fi).P(k); V += (pk* T )*(pk*N)*(pk*B); V += (pj*(-T))*(pj*N)*(pj*B); } } return V/6.0; } }; // end class Mesh template < class VertContainerType, class FaceContainerType > bool HasPerVertexQuality (const TriMesh < VertContainerType , FaceContainerType> & /*m*/) {return VertContainerType::value_type::HasQuality();} template < class VertContainerType, class FaceContainerType > bool HasPerVertexColor (const TriMesh < VertContainerType , FaceContainerType> & /*m*/) {return VertContainerType::value_type::HasColor();} template < class VertContainerType, class FaceContainerType > bool HasPerVertexTexCoord (const TriMesh < VertContainerType , FaceContainerType> & /*m*/) {return VertContainerType::value_type::HasTexCoord();} template < class VertContainerType, class FaceContainerType > bool HasPerVertexFlags (const TriMesh < VertContainerType , FaceContainerType> & /*m*/) {return VertContainerType::value_type::HasFlags();} template < class VertContainerType, class FaceContainerType > bool HasPerVertexNormal (const TriMesh < VertContainerType , FaceContainerType> & /*m*/) {return VertContainerType::value_type::HasNormal();} template < class VertContainerType, class FaceContainerType > bool HasPerWedgeTexCoord (const TriMesh < VertContainerType , FaceContainerType> & /*m*/) {return FaceContainerType::value_type::HasWedgeTexCoord();} template < class VertContainerType, class FaceContainerType > bool HasPerWedgeNormal (const TriMesh < VertContainerType , FaceContainerType> & /*m*/) {return FaceContainerType::value_type::HasWedgeNormal();} template < class VertContainerType, class FaceContainerType > bool HasPerWedgeColor (const TriMesh < VertContainerType , FaceContainerType> & /*m*/) {return FaceContainerType::value_type::HasWedgeColor();} template < class VertContainerType, class FaceContainerType > bool HasPerFaceFlags (const TriMesh < VertContainerType , FaceContainerType> & /*m*/) {return FaceContainerType::value_type::HasFlags();} template < class VertContainerType, class FaceContainerType > bool HasPerFaceNormal (const TriMesh < VertContainerType , FaceContainerType> & /*m*/) {return FaceContainerType::value_type::HasFaceNormal();} template < class VertContainerType, class FaceContainerType > bool HasPerFaceColor (const TriMesh < VertContainerType , FaceContainerType> & /*m*/) {return FaceContainerType::value_type::HasFaceColor();} template < class VertContainerType, class FaceContainerType > bool HasPerFaceMark (const TriMesh < VertContainerType , FaceContainerType> & /*m*/) {return FaceContainerType::value_type::HasMark();} template < class VertContainerType, class FaceContainerType > bool HasPerFaceQuality (const TriMesh < VertContainerType , FaceContainerType> & /*m*/) {return FaceContainerType::value_type::HasFaceQuality();} template < class VertContainerType, class FaceContainerType > bool HasFFAdjacency (const TriMesh < VertContainerType , FaceContainerType> & /*m*/) {return FaceContainerType::value_type::HasFFAdjacency();} template < class VertContainerType, class FaceContainerType > bool HasVFAdjacency (const TriMesh < VertContainerType , FaceContainerType> & /*m*/) { assert(FaceContainerType::value_type::HasVFAdjacency() == VertContainerType::value_type::HasVFAdjacency()); return FaceContainerType::value_type::HasVFAdjacency(); } template bool HasPerVertexAttribute(const MESH_TYPE &m, std::string name){ typename std::set< typename MESH_TYPE::HandlesWrapper>::const_iterator ai; typename MESH_TYPE::HandlesWrapper h; h._name = name; ai = m.vert_attr.find(h); return (ai!= m.vert_attr.end() ) ; } template bool HasPerFaceAttribute(const MESH_TYPE &m, std::string name){ typename std::set< typename MESH_TYPE::HandlesWrapper>::const_iterator ai; typename MESH_TYPE::HandlesWrapper h; h._name = name; ai = m.face_attr.find(h); return (ai!= m.face_attr.end() ) ; } /*@}*/ /*@}*/ } // end namespace } // end namespace #endif qutemol/vcg/vcg/complex/trimesh/refine.h0000444000175000017500000007534110776415210016740 0ustar mbamba/***********F***************************************************************** * VCGLib o o * * Visual and Computer Graphics Library o o * * _ O _ * * Copyright(C) 2004 \/)\/ * * Visual Computing Lab /\/| * * ISTI - Italian National Research Council | * * \ * * All rights reserved. * * * * 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. * * * * 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 (http://www.gnu.org/licenses/gpl.txt) * * for more details. * * * ****************************************************************************/ /**************************************************************************** History $Log: refine.h,v $ Revision 1.19 2008/04/07 12:58:48 cignoni Changed the edge split predicate, now it takes a pos instead of two pnts Added quality interpolation Revision 1.18 2008/03/18 10:31:47 cignoni added color interpolation to butterfly Revision 1.17 2007/03/27 09:25:14 cignoni corrected managment of selected flag when refining the whole mesh flipmesh Revision 1.16 2007/03/12 15:37:18 tarini Texture coord name change! "TCoord" and "Texture" are BAD. "TexCoord" is GOOD. Revision 1.15 2007/01/18 18:15:14 cignoni added missing typenames Revision 1.14 2007/01/17 14:31:47 giec Added TrSplit function. Revision 1.13 2006/10/27 13:26:49 ganovelli changed &*vert.end() to !vert.empty() -> &vert.back() to comply vs2005 compiler Revision 1.12 2006/06/18 20:42:01 cignoni removed wrong fn setting Revision 1.11 2006/06/06 14:35:28 zifnab1974 Changes for compilation on linux AMD64. Some remarks: Linux filenames are case-sensitive. _fileno and _filelength do not exist on linux Revision 1.10 2006/05/03 21:42:10 cignoni HasPerWedgeTexture -> HasPerWedgeTexture(m) Revision 1.9 2005/12/22 11:24:09 cignoni removed div by zero bug in callback of refine (tnx to Mario Latronico) Revision 1.8 2005/12/13 11:01:01 cignoni Added Callback in refine Revision 1.7 2005/12/02 00:06:37 cignoni commented out an old TRACE Revision 1.6 2005/07/11 13:13:33 cignoni small gcc-related compiling issues (typenames,ending cr, initialization order) Revision 1.5 2005/06/29 15:25:41 callieri deleted a wrong declaration "typename typename" Revision 1.4 2005/06/17 00:48:27 cignoni Corrected the type name of wedge tex coords WedgeInterp in RefineE Revision 1.3 2005/02/25 10:28:04 pietroni added #include use of update topology in refineE Revision 1.2 2005/02/02 16:01:13 pietroni 1 warning corrected Revision 1.1 2004/10/12 15:42:29 ganovelli first working version ****************************************************************************/ #ifndef __VCGLIB_REFINE #define __VCGLIB_REFINE #include #include #include #include #include #include #include #include #include #include #include #include #include namespace vcg{ /* Tabella che codifica le modalita' di split a seconda di quali dei tre edge sono da splittare Il primo numero codifica il numero di triangoli, le successive 5 triple codificano i triangoli secondo la seguente convenzione: 0..2 vertici originali del triangolo 3..5 mp01, mp12, mp20 midpoints of the three edges Nel caso "due lati splittati" e' necessario fare la triangolazione del trapezio bene. Per cui in questo caso sono specificati 5 triangoli, il primo e' quello ovvio, se dei due lati splittati e' minore il primo va scelta la prima coppia altrimenti la seconda coppia il campo swap codificano le due diagonali da testare per scegliere quale triangolazione usare per il caso con tre triangoli: se diag1 struct MidPoint : public std::unary_function , typename MESH_TYPE::CoordType > { void operator()(typename MESH_TYPE::VertexType &nv, face::Pos ep){ nv.P()= (ep.f->V(ep.z)->P()+ep.f->V1(ep.z)->P())/2.0; if( MESH_TYPE::HasPerVertexNormal()) nv.N()= (ep.f->V(ep.z)->N()+ep.f->V1(ep.z)->N()).Normalize(); if( MESH_TYPE::HasPerVertexColor()) nv.C().lerp(ep.f->V(ep.z)->C(),ep.f->V1(ep.z)->C(),.5f); if( MESH_TYPE::HasPerVertexQuality()) nv.Q() = ((ep.f->V(ep.z)->Q()+ep.f->V1(ep.z)->Q())) / 2.0; } Color4 WedgeInterp(Color4 &c0, Color4 &c1) { Color4 cc; return cc.lerp(c0,c1,0.5f); } template TexCoord2 WedgeInterp(TexCoord2 &t0, TexCoord2 &t1) { TexCoord2 tmp; assert(t0.n()== t1.n()); tmp.n()=t0.n(); tmp.t()=(t0.t()+t1.t())/2.0; return tmp; } }; template struct MidPointArc : public std::unary_function , typename MESH_TYPE::CoordType> { void operator()(typename MESH_TYPE::VertexType &nv, face::Pos ep) { const typename MESH_TYPE::ScalarType EPS =1e-10; typename MESH_TYPE::CoordType vp = (ep.f->V(ep.z)->P()+ep.f->V1(ep.z)->P())/2.0; typename MESH_TYPE::CoordType n = (ep.f->V(ep.z)->N()+ep.f->V1(ep.z)->N())/2.0; typename MESH_TYPE::ScalarType w =n.Norm(); if(wV(ep.z)->P()+ep.f->V1(ep.z)->P())/2.0; return;} n/=w; typename MESH_TYPE::CoordType d0 = ep.f->V(ep.z)->P() - vp; typename MESH_TYPE::CoordType d1 = ep.f->V1(ep.z)->P()- vp; typename MESH_TYPE::ScalarType d=Distance(ep.f->V(ep.z)->P(),ep.f->V1(ep.z)->P())/2.0; typename MESH_TYPE::CoordType nn = ep.f->V1(ep.z)->N() ^ ep.f->V(ep.z)->N(); typename MESH_TYPE::CoordType np = n ^ d0; // vettore perp al piano edge, normale interpolata np.Normalize(); double sign=1; if(np*nn<0) sign=-1; // se le normali non divergono sposta il punto nella direzione opposta typename MESH_TYPE::CoordType n0=ep.f->V(ep.z)->N() -np*(ep.f->V(ep.z)->N()*np); n0.Normalize(); typename MESH_TYPE::CoordType n1=ep.f->V1(ep.z)->N()-np*(ep.f->V1(ep.z)->N()*np); assert(n1.Norm()>EPS); n1.Normalize(); typename MESH_TYPE::ScalarType cosa0=n0*n; typename MESH_TYPE::ScalarType cosa1=n1*n; if(2-cosa0-cosa1V(ep.z)->P()+ep.f->V1(ep.z)->P())/2.0;return;} typename MESH_TYPE::ScalarType cosb0=(d0*n)/d; typename MESH_TYPE::ScalarType cosb1=(d1*n)/d; assert(1+cosa0>EPS); assert(1+cosa1>EPS); typename MESH_TYPE::ScalarType delta0=d*(cosb0 +sqrt( ((1-cosb0*cosb0)*(1-cosa0))/(1+cosa0)) ); typename MESH_TYPE::ScalarType delta1=d*(cosb1 +sqrt( ((1-cosb1*cosb1)*(1-cosa1))/(1+cosa1)) ); assert(delta0+delta1<2*d); nv.P()=vp+n*sign*(delta0+delta1)/2.0; return ; } // Aggiunte in modo grezzo le due wedgeinterp Color4 WedgeInterp(Color4 &c0, Color4 &c1) { Color4 cc; return cc.lerp(c0,c1,0.5f); } template TexCoord2 WedgeInterp(TexCoord2 &t0, TexCoord2 &t1) { TexCoord2 tmp; assert(t0.n()== t1.n()); tmp.n()=t0.n(); tmp.t()=(t0.t()+t1.t())/2.0; return tmp; } }; /* Versione Della Midpoint basata sul paper: S. Karbacher, S. Seeger, G. Hausler A non linear subdivision scheme for triangle meshes Non funziona! Almeno due problemi: 1) il verso delle normali influenza il risultato (e.g. si funziona solo se le normali divergono) Risolvibile controllando se le normali divergono 2) gli archi vanno calcolati sul piano definito dalla normale interpolata e l'edge. funziona molto meglio nelle zone di sella e non semplici. */ template struct MidPointArcNaive : public std::unary_function< face::Pos , typename MESH_TYPE::CoordType> { typename MESH_TYPE::CoordType operator()(face::Pos ep) { typename MESH_TYPE::CoordType vp = (ep.f->V(ep.z)->P()+ep.f->V1(ep.z)->P())/2.0; typename MESH_TYPE::CoordType n = (ep.f->V(ep.z)->N()+ep.f->V1(ep.z)->N())/2.0; n.Normalize(); typename MESH_TYPE::CoordType d0 = ep.f->V(ep.z)->P() - vp; typename MESH_TYPE::CoordType d1 = ep.f->V1(ep.z)->P()- vp; typename MESH_TYPE::ScalarType d=Distance(ep.f->V(ep.z)->P(),ep.f->V1(ep.z)->P())/2.0; typename MESH_TYPE::ScalarType cosa0=ep.f->V(ep.z)->N()*n; typename MESH_TYPE::ScalarType cosa1=ep.f->V1(ep.z)->N()*n; typename MESH_TYPE::ScalarType cosb0=(d0*n)/d; typename MESH_TYPE::ScalarType cosb1=(d1*n)/d; typename MESH_TYPE::ScalarType delta0=d*(cosb0 +sqrt( ((1-cosb0*cosb0)*(1-cosa0))/(1+cosa0)) ); typename MESH_TYPE::ScalarType delta1=d*(cosb1 +sqrt( ((1-cosb1*cosb1)*(1-cosa1))/(1+cosa1)) ); return vp+n*(delta0+delta1)/2.0; } }; /* A partire da una mesh raffina una volta tutti i lati dei triangoli minore di thr Se RefineSelected == true allora raffina SOLO le facce selezionate i cui edge sono piu'corti di thr. I nuovi vertici e facce della mesh sono aggiunte in fondo Requirement: Topologia (in effetti se non si usa la il raffinamento per selezione non servirebbe) Restituisce false se non raffina nemmeno una faccia. Si assume che se la mesh ha dati per wedge la funzione di midpoint interpoli i nuovi wedge tutti uguali per tutti i wedge sulla stessa 'vecchia' faccia. */ // binary predicate che dice quando splittare un edge // la refine usa qt funzione di default: raffina se l'edge^2 e' piu lungo di thr2 template class EdgeLen { public: FLT thr2; bool operator()(face::Pos ep) const { return SquaredDistance(ep.f->V(ep.z)->P(), ep.f->V1(ep.z)->P())>thr2; } }; /* template bool Refine(MESH_TYPE &m, MIDPOINT mid, typename MESH_TYPE::ScalarType thr=0,bool RefineSelectedP=false) { volatile RefineW,true> RT; volatile RefineW,false> RF; bool retval; if(RefineSelectedP) retval=RT.RefineT(m,mid,thr); if(!RefineSelectedP) retval=RF.RefineT(m,mid,thr); return retval; } template bool RefineE(MESH_TYPE &m, MIDPOINT mid, EDGEPRED ep, bool RefineSelectedP=false) { RefineW RT; RefineW RF; bool retval; if(RefineSelectedP) retval=RT.RefineT(m,mid,ep); if(!RefineSelectedP) retval=RF.RefineT(m,mid,ep); return retval; } */ /*********************************************************/ /*********************************************************/ /*********************************************************/ template bool Refine(MESH_TYPE &m, MIDPOINT mid, typename MESH_TYPE::ScalarType thr=0,bool RefineSelected=false, CallBackPos *cb = 0) { EdgeLen ep; ep.thr2=thr*thr; return RefineE(m,mid,ep,RefineSelected,cb); } template bool RefineE(MESH_TYPE &m, MIDPOINT mid, EDGEPRED ep,bool RefineSelected=false, CallBackPos *cb = 0) { int j,NewVertNum=0,NewFaceNum=0; typedef std::pair vvpair; std::map Edge2Vert; // First Loop: We analyze the mesh to compute the number of the new faces and new vertices typename MESH_TYPE::FaceIterator fi; int step=0,PercStep=m.fn/33; if(PercStep==0) PercStep=1; for(fi=m.face.begin(),j=0;fi!=m.face.end();++fi) if(!(*fi).IsD()) { if(cb && (++step%PercStep)==0)(*cb)(step/PercStep,"Refining..."); for(j=0;j<3;j++){ if(ep(face::Pos (&*fi,j)) && (!RefineSelected || ((*fi).IsS() && (*fi).FFp(j)->IsS())) ){ ++NewFaceNum; if( ((*fi).V(j)<(*fi).V1(j)) || (*fi).IsB(j) ) ++NewVertNum; } } } // end face loop if(NewVertNum==0) return false; typename MESH_TYPE::VertexIterator lastv = tri::Allocator::AddVertices(m,NewVertNum); // typename MESH_TYPE::VertexIterator lastv=m.AddVertices(NewVertNum); // Secondo Ciclo si inizializza la mappa da edge a vertici // e la posizione dei nuovi vertici //j=0; for(fi=m.face.begin();fi!=m.face.end();++fi) if(!(*fi).IsD()) { if(cb && (++step%PercStep)==0)(*cb)(step/PercStep,"Refining..."); for(j=0;j<3;j++) if(ep(face::Pos (&*fi,j)) && (!RefineSelected || ((*fi).IsS() && (*fi).FFp(j)->IsS())) ) if((*fi).V(j)<(*fi).V1(j) || (*fi).IsB(j)){ mid( (*lastv), face::Pos (&*fi,j)); //(*lastv).P()=((*fi).V(j)->P()+(*fi).V1(j)->P())/2; Edge2Vert[ vvpair((*fi).V(j),(*fi).V1(j)) ] = &*lastv; ++lastv; } } assert(lastv==m.vert.end()); typename MESH_TYPE::FaceIterator lastf = tri::Allocator::AddFaces(m,NewFaceNum); // MESH_TYPE::FaceIterator lastf = m.AddFaces(NewFaceNum); // int ddd=0; distance(m.face.begin(),lastf,ddd); typename MESH_TYPE::FaceIterator oldendf=lastf; /* v0 f0 mp01 mp02 f3 f1 f2 v1 mp12 v2 */ typename MESH_TYPE::VertexPointer vv[6]; // i sei vertici in gioco // 0..2 vertici originali del triangolo // 3..5 mp01, mp12, mp20 midpoints of the three edges typename MESH_TYPE::FacePointer nf[4]; // le quattro facce in gioco. typename MESH_TYPE::FaceType::TexCoordType wtt[6]; // per ogni faccia sono al piu' tre i nuovi valori // di texture per wedge (uno per ogni edge) int fca=0,fcn =0; for(fi=m.face.begin();fi!=oldendf;++fi) if(!(*fi).IsD()) { if(cb && (++step%PercStep)==0)(*cb)(step/PercStep,"Refining..."); fcn++; vv[0]=(*fi).V(0); vv[1]=(*fi).V(1); vv[2]=(*fi).V(2); bool e0=ep(face::Pos (&*fi,0)); bool e1=ep(face::Pos (&*fi,1)); bool e2=ep(face::Pos (&*fi,2)); if(e0) if((*fi).V(0)<(*fi).V(1)|| (*fi).IsB(0)) vv[3]=Edge2Vert[ vvpair((*fi).V(0),(*fi).V(1)) ]; else vv[3]=Edge2Vert[ vvpair((*fi).V(1),(*fi).V(0)) ]; else vv[3]=0; if(e1) if((*fi).V(1)<(*fi).V(2)|| (*fi).IsB(1)) vv[4]=Edge2Vert[ vvpair((*fi).V(1),(*fi).V(2)) ]; else vv[4]=Edge2Vert[ vvpair((*fi).V(2),(*fi).V(1)) ]; else vv[4]=0; if(e2) if((*fi).V(2)<(*fi).V(0)|| (*fi).IsB(2)) vv[5]=Edge2Vert[ vvpair((*fi).V(2),(*fi).V(0)) ]; else vv[5]=Edge2Vert[ vvpair((*fi).V(0),(*fi).V(2)) ]; else vv[5]=0; int ind=((&*vv[3])?1:0)+((&*vv[4])?2:0)+((&*vv[5])?4:0); nf[0]=&*fi; int i; for(i=1;iP(),vv[SplitTab[ind].swap[0][1]]->P()) < SquaredDistance(vv[SplitTab[ind].swap[1][0]]->P(),vv[SplitTab[ind].swap[1][1]]->P()) ) { // swap the last two triangles (*nf[2]).V(1)=(*nf[1]).V(0); (*nf[1]).V(1)=(*nf[2]).V(0); if(tri::HasPerWedgeTexCoord(m)){ //analogo ai vertici... (*nf[2]).WT(1)=(*nf[1]).WT(0); (*nf[1]).WT(1)=(*nf[2]).WT(0); } if((*nf[1]).IsB(0)) (*nf[2]).SetB(1); else (*nf[2]).ClearB(1); if((*nf[2]).IsB(0)) (*nf[1]).SetB(1); else (*nf[1]).ClearB(1); (*nf[1]).ClearB(0); (*nf[2]).ClearB(0); } } // m.fn= m.face.size(); assert(lastf==m.face.end()); assert(!m.vert.empty()); for(fi=m.face.begin();fi!=m.face.end();++fi) if(!(*fi).IsD()){ assert((*fi).V(0)>=&*m.vert.begin() && (*fi).V(0)<=&m.vert.back() ); assert((*fi).V(1)>=&*m.vert.begin() && (*fi).V(1)<=&m.vert.back() ); assert((*fi).V(2)>=&*m.vert.begin() && (*fi).V(2)<=&m.vert.back() ); } vcg::tri::UpdateTopology::FaceFace(m); return true; } /*************************************************************************/ /* Modified Butterfly interpolation scheme, as presented in Zorin, Schroeder Subdivision for modeling and animation Siggraph 2000 Course Notes */ /* vul-------vu--------vur \ / \ / \ / \ / \ / fu \ / vl--------vr / \ fd / \ / \ / \ / \ / \ vdl-------vd--------vdr */ template struct MidPointButterfly : public std::unary_function , typename MESH_TYPE::CoordType> { void operator()(typename MESH_TYPE::VertexType &nv, face::Pos ep) { face::Pos he(ep.f,ep.z,ep.f->V(ep.z)); typename MESH_TYPE::CoordType *vl,*vr; typename MESH_TYPE::CoordType *vl0,*vr0; typename MESH_TYPE::CoordType *vu,*vd,*vul,*vur,*vdl,*vdr; vl=&he.v->P(); he.FlipV(); vr=&he.v->P(); if( MESH_TYPE::HasPerVertexColor()) nv.C().lerp(ep.f->V(ep.z)->C(),ep.f->V1(ep.z)->C(),.5f); if(he.IsBorder()) { he.NextB(); vr0=&he.v->P(); he.FlipV(); he.NextB(); assert(&he.v->P()==vl); he.NextB(); vl0=&he.v->P(); nv.P()=((*vl)+(*vr))*(9.0/16.0)-((*vl0)+(*vr0))/16.0 ; } else { he.FlipE();he.FlipV(); vu=&he.v->P(); he.FlipF();he.FlipE();he.FlipV(); vur=&he.v->P(); he.FlipV();he.FlipE();he.FlipF(); assert(&he.v->P()==vu); // back to vu (on the right) he.FlipE(); he.FlipF();he.FlipE();he.FlipV(); vul=&he.v->P(); he.FlipV();he.FlipE();he.FlipF(); assert(&he.v->P()==vu); // back to vu (on the left) he.FlipV();he.FlipE();he.FlipF(); assert(&he.v->P()==vl);// again on vl (but under the edge) he.FlipE();he.FlipV(); vd=&he.v->P(); he.FlipF();he.FlipE();he.FlipV(); vdl=&he.v->P(); he.FlipV();he.FlipE();he.FlipF(); assert(&he.v->P()==vd);// back to vd (on the right) he.FlipE(); he.FlipF();he.FlipE();he.FlipV(); vdr=&he.v->P(); nv.P()=((*vl)+(*vr))/2.0+((*vu)+(*vd))/8.0 - ((*vul)+(*vur)+(*vdl)+(*vdr))/16.0; } } /// Aggiunte in modo grezzo le due wedge interp Color4 WedgeInterp(Color4 &c0, Color4 &c1) { Color4 cc; return cc.lerp(c0,c1,0.5f); } template TexCoord2 WedgeInterp(TexCoord2 &t0, TexCoord2 &t1) { TexCoord2 tmp; assert(t0.n()== t1.n()); tmp.n()=t0.n(); tmp.t()=(t0.t()+t1.t())/2.0; return tmp; } }; #if 0 int rule=0; if(vr==vul) rule+=1; if(vl==vur) rule+=2; if(vl==vdr) rule+=4; if(vr==vdl) rule+=8; switch(rule){ /* */ /* */ case 0 : return ((*vl)+(*vr))/2.0+((*vu)+(*vd))/8.0 - ((*vul)+(*vur)+(*vdl)+(*vdr))/16.0; /* ul */ case 1 : return (*vl*6 + *vr*10 + *vu + *vd*3 - *vur - *vdl -*vdr*2 )/16.0; /* ur */ case 2 : return (*vr*6 + *vl*10 + *vu + *vd*3 - *vul - *vdr -*vdl*2 )/16.0; /* dr */ case 4 : return (*vr*6 + *vl*10 + *vd + *vu*3 - *vdl - *vur -*vul*2 )/16.0; /* dl */ case 8 : return (*vl*6 + *vr*10 + *vd + *vu*3 - *vdr - *vul -*vur*2 )/16.0; /* ul,ur */ case 3 : return (*vl*4 + *vr*4 + *vd*2 + - *vdr - *vdl )/8.0; /* dl,dr */ case 12 : return (*vl*4 + *vr*4 + *vu*2 + - *vur - *vul )/8.0; /* ul,dr */ case 5 : /* ur,dl */ case 10 : default: return (*vl+ *vr)/2.0; } #endif /* vul-------vu--------vur \ / \ / \ / \ / \ / fu \ / vl--------vr / \ fd / \ / \ / \ / \ / \ vdl-------vd--------vdr */ // Versione modificata per tenere di conto in meniara corretta dei vertici con valenza alta template struct MidPointButterfly2 : public std::unary_function , typename MESH_TYPE::CoordType> { typename MESH_TYPE::CoordType operator()(face::Pos ep) { double Rules[11][10] = { {.0}, // valenza 0 {.0}, // valenza 1 {.0}, // valenza 2 { .4166666667, -.08333333333 , -.08333333333 }, // valenza 3 { .375 , .0 , -0.125 , .0 }, // valenza 4 { .35 , .03090169945 , -.08090169945 , -.08090169945, .03090169945 }, // valenza 5 { .5 , .125 , -0.0625 , .0 , -0.0625 , 0.125 }, // valenza 6 { .25 , .1088899050 , -.06042933822 , -.04846056675, -.04846056675, -.06042933822, .1088899050 }, // valenza 7 { .21875 , .1196383476 , -.03125 , -.05713834763, -.03125 , -.05713834763, -.03125 ,.1196383476 }, // valenza 8 { .1944444444, .1225409480 , -.00513312590 , -.05555555556, -.03407448880, -.03407448880, -.05555555556, -.00513312590, .1225409480 }, // valenza 9 { .175 , .1213525492 , .01545084973 , -.04635254918, -.04045084973, -.025 , -.04045084973, -.04635254918, .01545084973, .1213525492 } // valenza 10 }; face::Pos he(ep.f,ep.z,ep.f->V(ep.z)); typename MESH_TYPE::CoordType *vl,*vr; vl=&he.v->P(); vr=&he.VFlip()->P(); if(he.IsBorder()) {he.FlipV(); typename MESH_TYPE::CoordType *vl0,*vr0; he.NextB(); vr0=&he.v->P(); he.FlipV(); he.NextB(); assert(&he.v->P()==vl); he.NextB(); vl0=&he.v->P(); return ((*vl)+(*vr))*(9.0/16.0)-((*vl0)+(*vr0))/16.0 ; } int kl=0,kr=0; // valence of left and right vertices bool bl=false,br=false; // if left and right vertices are of border face::Pos heStart=he;assert(he.v->P()==*vl); do { // compute valence of left vertex he.FlipE();he.FlipF(); if(he.IsBorder()) bl=true; ++kl; } while(he!=heStart); he.FlipV();heStart=he;assert(he.v->P()==*vr); do { // compute valence of right vertex he.FlipE();he.FlipF(); if(he.IsBorder()) br=true; ++kr; } while(he!=heStart); if(br||bl) return MidPointButterfly()( ep ); if(kr==6 && kl==6) return MidPointButterfly()( ep ); // TRACE("odd vertex among valences of %i %i\n",kl,kr); typename MESH_TYPE::CoordType newposl=*vl*.75, newposr=*vr*.75; he.FlipV();heStart=he; assert(he.v->P()==*vl); int i=0; if(kl!=6) do { // compute position of left vertex newposl+= he.VFlip()->P() * Rules[kl][i]; he.FlipE();he.FlipF(); ++i; } while(he!=heStart); i=0;he.FlipV();heStart=he;assert(he.v->P()==*vr); if(kr!=6) do { // compute position of right vertex newposr+=he.VFlip()->P()* Rules[kr][i]; he.FlipE();he.FlipF(); ++i; } while(he!=heStart); if(kr==6) return newposl; if(kl==6) return newposr; return newposl+newposr; } }; /* // Nuovi punti (e.g. midpoint) template struct OddPointLoop : public std::unary_function , typename MESH_TYPE::CoordType> { } // vecchi punti template struct EvenPointLoop : public std::unary_function , typename MESH_TYPE::CoordType> { } */ template struct MidPointPlane : public std::unary_function , typename MESH_TYPE::CoordType> { Plane3 pl; typedef Point3 Point3x; void operator()(typename MESH_TYPE::VertexType &nv, face::Pos ep){ Point3x &p0=ep.f->V0(ep.z)->P(); Point3x &p1=ep.f->V1(ep.z)->P(); double pp= Distance(p0,pl)/(Distance(p0,pl) - Distance(p1,pl)); nv.P()=p1*pp + p0*(1.0-pp); } Color4 WedgeInterp(Color4 &c0, Color4 &c1) { Color4 cc; return cc.lerp(c0,c1,0.5f); } template TexCoord2 WedgeInterp(TexCoord2 &t0, TexCoord2 &t1) { TexCoord2 tmp; assert(t0.n()== t1.n()); tmp.n()=t0.n(); tmp.t()=(t0.t()+t1.t())/2.0; return tmp; } }; template class EdgeSplPlane { public: Plane3 pl; bool operator()(const Point3 &p0, const Point3 &p1) const { if(Distance(pl,p0)>0) { if(Distance(pl,p1)>0) return false; else return true; } else if(Distance(pl,p1)<=0) return false; return true; } }; template struct MidPointSphere : public std::unary_function , typename MESH_TYPE::CoordType> { Sphere3 sph; typedef Point3 Point3x; void operator()(typename MESH_TYPE::VertexType &nv, face::Pos ep){ Point3x &p0=ep.f->V0(ep.z)->P(); Point3x &p1=ep.f->V1(ep.z)->P(); nv.P()= sph.c+((p0+p1)/2.0 - sph.c ).Normalize(); } Color4 WedgeInterp(Color4 &c0, Color4 &c1) { Color4 cc; return cc.lerp(c0,c1,0.5f); } template TexCoord2 WedgeInterp(TexCoord2 &t0, TexCoord2 &t1) { TexCoord2 tmp; assert(t0.n()== t1.n()); tmp.n()=t0.n(); tmp.t()=(t0.t()+t1.t())/2.0; return tmp; } }; template class EdgeSplSphere { public: Sphere3 sph; bool operator()(const Point3 &p0, const Point3 &p1) const { if(Distance(sph,p0)>0) { if(Distance(sph,p1)>0) return false; else return true; } else if(Distance(sph,p1)<=0) return false; return true; } }; /*! * Triangle split */ template struct CenterPoint : public std::unary_function { typename TRIMESH_TYPE::CoordType operator()(typename TRIMESH_TYPE::FacePointer f){ return vcg::Barycenter(*f); } }; template void TriSplit(typename TRIMESH_TYPE::FacePointer f, typename TRIMESH_TYPE::FacePointer f1,typename TRIMESH_TYPE::FacePointer f2, typename TRIMESH_TYPE::VertexPointer vB, CenterPoint Center) { vB->P() = Center(f); //i tre vertici della faccia da dividere typename TRIMESH_TYPE::VertexType* V0,*V1,*V2; V0 = f->V(0); V1 = f->V(1); V2 = f->V(2); //risistemo la faccia di partenza (*f).V(2) = &(*vB); //Faccia nuova #1 (*f1).V(0) = &(*vB); (*f1).V(1) = V1; (*f1).V(2) = V2; //Faccia nuova #2 (*f2).V(0) = V0; (*f2).V(1) = &(*vB); (*f2).V(2) = V2; if(f->HasFFAdjacency()) { //adiacenza delle facce adiacenti a quelle aggiunte f->FFp(1)->FFp(f->FFi(1)) = f1; f->FFp(2)->FFp(f->FFi(2)) = f2; //adiacenza ff typename TRIMESH_TYPE::FacePointer FF0,FF1,FF2; FF0 = f->FFp(0); FF1 = f->FFp(1); FF2 = f->FFp(2); //Indici di adiacenza ff char FFi0,FFi1,FFi2; FFi0 = f->FFi(0); FFi1 = f->FFi(1); FFi2 = f->FFi(2); //adiacenza della faccia di partenza (*f).FFp(1) = &(*f1); (*f).FFi(1) = 0; (*f).FFp(2) = &(*f2); (*f).FFi(2) = 0; //adiacenza della faccia #1 (*f1).FFp(0) = f; (*f1).FFi(0) = 1; (*f1).FFp(1) = FF1; (*f1).FFi(1) = FFi1; (*f1).FFp(2) = &(*f2); (*f1).FFi(2) = 1; //adiacenza della faccia #2 (*f2).FFp(0) = f; (*f2).FFi(0) = 2; (*f2).FFp(1) = &(*f1); (*f2).FFi(1) = 2; (*f2).FFp(2) = FF2; (*f2).FFi(2) = FFi2; } } } // namespace vcg #endif qutemol/vcg/vcg/complex/trimesh/closest.h0000444000175000017500000004110210616660226017132 0ustar mbamba/**************************************************************************** * VCGLib o o * * Visual and Computer Graphics Library o o * * _ O _ * * Copyright(C) 2004 \/)\/ * * Visual Computing Lab /\/| * * ISTI - Italian National Research Council | * * \ * * All rights reserved. * * * * 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. * * * * 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 (http://www.gnu.org/licenses/gpl.txt) * * for more details. * * * ****************************************************************************/ /**************************************************************************** History $Log: closest.h,v $ Revision 1.28 2007/05/04 16:34:30 ganovelli changes to comply "plus" types Revision 1.27 2006/12/06 12:59:13 pietroni added max distance to rayIterator Revision 1.26 2006/11/21 16:06:54 ponchio passing VDistFunct() to functions wanting a reference, not a value (why a reference btw?) Revision 1.25 2006/11/13 13:13:49 ponchio Added usual typename. Revision 1.24 2006/11/12 02:41:03 pietroni added normalization of normal in DoRay functions Revision 1.23 2006/11/10 11:41:49 pietroni added DoRayFuntion that return interpolated normal Revision 1.22 2006/09/20 17:18:26 ponchio VDistFunct() at line 292 was passed as a temporary. Invalid under g++. Fixed. Revision 1.21 2006/02/09 08:38:04 pietroni sintax error corrected Revision 1.20 2006/02/08 17:02:41 pietroni commented one GetClosestFace function ... the code is the same then getClosest that return barycentric coordinates Revision 1.19 2006/01/10 13:31:54 pietroni correct pass of variable closest_pt by reference in getclosestFace function Revision 1.18 2005/12/02 00:13:34 cignoni Added and removed typenames for gcc compiling. removed also some template arguments specifcation that gcc disliked... commented out GetInSphereFace and SetMesh that are probably never used and i didnt succeed in compile Revision 1.17 2005/10/05 17:02:52 pietroni corrected bugs on GEtKClosestVert and GetInSphereVert Revision 1.16 2005/10/03 16:19:07 spinelli fixed some bugs Revision 1.15 2005/10/03 13:59:39 pietroni added GetInSphere and GetInBox functions rensmed Functions respectively with Face suffix or Vertex suffix for query on vertex or faces Revision 1.14 2005/09/30 13:10:37 pietroni used functor defined in face/distance.h for distance point-face used functor defined in intersection3.h for ray-triangle intersection added GetKClosest and DoRay Functions Revision 1.13 2005/09/28 08:30:48 cignoni changed name of include, removed use of an undefined type (scalar instead of Scalar) removed unused code portions (the old closest code) Revision 1.12 2005/09/21 09:24:30 pietroni Added RayIterators. Added ClosestIterators on Triangles and Vertices. Added Closest Functions on triangles and Vertices. Revision 1.11 2005/09/19 13:36:24 pietroni added ray iterator of faces Revision 1.10 2005/09/16 11:53:51 cignoni Small gcc compliling issues Revision 1.9 2005/09/15 13:16:10 spinelli fixed bugs Revision 1.8 2005/09/15 11:15:00 pietroni minor changes Revision 1.7 2005/09/14 12:56:47 pietroni used closest function from grid Revision 1.6 2005/08/26 09:12:48 cignoni changed typedef A2UGridLink da 'GridStaticPtr::Link' a typedef 'GRID::Link' Revision 1.5 2005/02/08 17:49:38 pietroni added if (!l->Elem()->IsD()) test on each element Revision 1.4 2005/01/28 12:00:33 cignoni small gcc compiling issues for namespaces Revision 1.3 2005/01/24 11:47:23 cignoni Now used also by the official Metro Removed using namespace (NEVER IN HEADERS!) Made the computation of barycentric coords only when necessary Renamed Mindistpoint to Closest Revision 1.2 2005/01/21 17:13:09 pietroni included distance.h changed Dist to vcg::face::PointDistance Revision 1.1 2004/10/04 15:32:16 ganovelli moved from metro core Revision 1.6 2004/05/14 00:34:36 ganovelli header added ****************************************************************************/ #ifndef __VCG_TRIMESH_CLOSEST #define __VCG_TRIMESH_CLOSEST #include #include #include #include #include #include #include #include #include namespace vcg { namespace trimesh { //**MARKER CLASSES**// template class Tmark { MESH_TYPE *m; public: Tmark(){} void UnMarkAll(){m->UnMarkAll();} bool IsMarked(OBJ_TYPE* obj){return (m->IsMarked(obj));} void Mark(OBJ_TYPE* obj){m->Mark(obj);} void SetMesh(MESH_TYPE *_m) {m=_m;} }; template class FaceTmark:public Tmark {}; template class VertTmark:public Tmark {}; //**CLOSEST FUNCTION DEFINITION**// /* aka MetroCore data una mesh m e una ug sulle sue facce trova il punto di m piu' vicino ad un punto dato. */ // input: mesh, punto, griglia (gr), distanza limite (mdist) // output: normale (interpolata) alla faccia e punto piu' vicino su di essa, e coord baricentriche del punto trovato // Nota che il parametro template GRID non ci dovrebbe essere, visto che deve essere // UGrid, ma non sono riuscito a definirlo implicitamente template typename MESH::FaceType * GetClosestFace( MESH & mesh, GRID & gr, const typename GRID::CoordType & _p, const typename GRID::ScalarType & _maxDist, typename GRID::ScalarType & _minDist, typename GRID::CoordType &_closestPt, typename GRID::CoordType & _normf, typename GRID::CoordType & _ip) { typedef typename GRID::ScalarType ScalarType; typedef Point3 Point3x; typedef FaceTmark MarkerFace; MarkerFace mf; mf.SetMesh(&mesh); vcg::face::PointDistanceFunctor FDistFunct; _minDist=_maxDist; typename MESH::FaceType* bestf= gr.GetClosest(FDistFunct, mf, _p, _maxDist, _minDist, _closestPt); if(_maxDist> ScalarType(fabs(_minDist))) { // f=bestf; typename MESH::ScalarType alfa, beta, gamma; //calcolo normale con interpolazione trilineare InterpolationParameters(*bestf,_closestPt, alfa, beta, gamma); _normf = (bestf->V(0)->cN())*alfa+ (bestf->V(1)->cN())*beta+ (bestf->V(2)->cN())*gamma ; _ip=Point3x(alfa,beta,gamma); //normf.Normalize(); inutile si assume le normali ai vertici benfatte _minDist = fabs(_minDist); return(bestf); } return (0); } /*template typename MESH::FaceType * GetClosestFace( MESH & mesh,GRID & gr,const typename GRID::CoordType & _p, const typename GRID::ScalarType & _maxDist,typename GRID::ScalarType & _minDist, typename GRID::CoordType &_closestPt,typename GRID::CoordType & _normf) { Point3 _ip; typedef FaceTmark MarkerFace; MarkerFace mf; mf.SetMesh(&mesh); vcg::face::PointDistanceFunctor FDistFunct; typename MESH::FaceType* bestf= gr.GetClosest(FDistFunct,mf,_p,_maxDist,_minDist,_closestPt) ); }*/ template typename MESH::FaceType * GetClosestFace( MESH & mesh,GRID & gr,const typename GRID::CoordType & _p, const typename GRID::ScalarType & _maxDist,typename GRID::ScalarType & _minDist, typename GRID::CoordType &_closestPt) { typedef typename GRID::ScalarType ScalarType; typedef Point3 Point3x; typedef FaceTmark MarkerFace; MarkerFace mf; mf.SetMesh(&mesh); vcg::face::PointDistanceFunctor PDistFunct; _minDist=_maxDist; return (gr.GetClosest(PDistFunct,mf,_p,_maxDist,_minDist,_closestPt)); } template typename MESH::VertexType * GetClosestVertex( MESH & mesh,GRID & gr,const typename GRID::CoordType & _p, const typename GRID::ScalarType & _maxDist,typename GRID::ScalarType & _minDist ) { typedef typename GRID::ScalarType ScalarType; typedef Point3 Point3x; typedef VertTmark MarkerVert; MarkerVert mv; mv.SetMesh(&mesh); typedef vcg::vertex::PointDistanceFunctor VDistFunct; VDistFunct fn; _minDist=_maxDist; Point3x _closestPt; return (gr.GetClosest/**/(fn,mv,_p,_maxDist,_minDist,_closestPt)); } template unsigned int GetKClosestFace(MESH & mesh,GRID & gr, const unsigned int _k, const typename GRID::CoordType & _p, const typename GRID::ScalarType & _maxDist, OBJPTRCONTAINER & _objectPtrs,DISTCONTAINER & _distances, POINTCONTAINER & _points) { typedef FaceTmark MarkerFace; MarkerFace mf; mf.SetMesh(&mesh); vcg::face::PointDistanceFunctor FDistFunct; return (gr.GetKClosest /**/ (FDistFunct,mf,_k,_p,_maxDist,_objectPtrs,_distances,_points)); } template unsigned int GetKClosestVertex(MESH & mesh,GRID & gr, const unsigned int _k, const typename GRID::CoordType & _p, const typename GRID::ScalarType & _maxDist, OBJPTRCONTAINER & _objectPtrs,DISTCONTAINER & _distances, POINTCONTAINER & _points) { typedef VertTmark MarkerVert; MarkerVert mv; mv.SetMesh(&mesh); typedef vcg::vertex::PointDistanceFunctor VDistFunct; VDistFunct distFunct; return (gr.GetKClosest/* */ (distFunct,mv,_k,_p,_maxDist,_objectPtrs,_distances,_points)); } //template // unsigned int GetInSphereFace(MESH & mesh, // GRID & gr, // const typename GRID::CoordType & _p, // const typename GRID::ScalarType & _r, // OBJPTRCONTAINER & _objectPtrs, // DISTCONTAINER & _distances, // POINTCONTAINER & _points) //{ // typedef FaceTmark MarkerFace; // MarkerFace mf; // mf.SetMesh(&mesh); // typedef vcg::face::PointDistanceFunctor F DistFunct; // return (gr.GetInSphere/**/ // (FDistFunct(),mf,_p,_r,_maxDist,_objectPtrs,_distances,_points)); //} template unsigned int GetInSphereVertex(MESH & mesh, GRID & gr, const typename GRID::CoordType & _p, const typename GRID::ScalarType & _r, OBJPTRCONTAINER & _objectPtrs, DISTCONTAINER & _distances, POINTCONTAINER & _points) { typedef VertTmark MarkerVert; MarkerVert mv; mv.SetMesh(&mesh); typedef vcg::vertex::PointDistanceFunctor VDistFunct; VDistFunct fn; return (gr.GetInSphere/**/ (fn, mv,_p,_r,_objectPtrs,_distances,_points)); } template unsigned int GetInBoxFace(MESH & mesh, GRID & gr, const vcg::Box3 _bbox, OBJPTRCONTAINER & _objectPtrs) { typedef FaceTmark MarkerFace; MarkerFace mf; mf.SetMesh(&mesh); return(gr.GetInBox/**/(mf,_bbox,_objectPtrs)); } template unsigned int GetInBoxVertex(MESH & mesh, GRID & gr, const vcg::Box3 _bbox, OBJPTRCONTAINER & _objectPtrs) { typedef VertTmark MarkerVert; MarkerVert mv; mv.SetMesh(&mesh); return(gr.GetInBox/**/(mv,_bbox,_objectPtrs)); } template typename GRID::ObjPtr DoRay(MESH & mesh,GRID & gr, const Ray3 & _ray, const typename GRID::ScalarType & _maxDist, typename GRID::ScalarType & _t) { typedef typename MESH::FaceType FaceType; typedef typename MESH::ScalarType ScalarType; typedef FaceTmark MarkerFace; MarkerFace mf; mf.SetMesh(&mesh); Ray3 _ray1=_ray; _ray1.Normalize(); typedef vcg::RayTriangleIntersectionFunctor FintFunct; return(gr.DoRay(FintFunct(),mf,_ray1,_maxDist,_t)); } template typename GRID::ObjPtr DoRay(MESH & mesh,GRID & gr, const Ray3 & _ray, const typename GRID::ScalarType & _maxDist, typename GRID::ScalarType & _t, typename GRID::CoordType & _normf) { typedef typename MESH::FaceType FaceType; typedef typename MESH::ScalarType ScalarType; typedef FaceTmark MarkerFace; MarkerFace mf; mf.SetMesh(&mesh); typedef vcg::RayTriangleIntersectionFunctor FintFunct; Ray3 _ray1=_ray; _ray1.Normalize(); FaceType *f=gr.DoRay(FintFunct(),mf,_ray1,_maxDist,_t); typename GRID::CoordType dir=_ray.Direction(); dir.Normalize(); typename GRID::CoordType int_point=_ray.Origin()+_ray1.Direction()*_t; typename GRID::ScalarType alfa,beta,gamma; if (f!=NULL) { f->InterpolationParameters(int_point, alfa, beta, gamma); _normf = (f->V(0)->cN())*alfa+ (f->V(1)->cN())*beta+ (f->V(2)->cN())*gamma ; } return f; } //**ITERATORS DEFINITION**// template class ClosestFaceIterator:public vcg::ClosestIterator > { public: typedef GRID GridType; typedef MESH MeshType; typedef FaceTmark MarkerFace; typedef vcg::face::PointDistanceFunctor PDistFunct; typedef vcg::ClosestIterator > ClosestBaseType; typedef typename MESH::FaceType FaceType; typedef typename MESH::ScalarType ScalarType; //ClosestFaceIterator(GridType &_Si):ClosestBaseType(_Si,PDistFunct()){} ClosestFaceIterator(GridType &_Si):ClosestBaseType(_Si,PDistFunct()){} // Commented out: it seems unuseful and make gcc complain. p. void SetMesh(MeshType *m) {this->tm.SetMesh(m);} }; template class ClosestVertexIterator:public vcg::ClosestIterator > { public: typedef GRID GridType; typedef MESH MeshType; typedef VertTmark MarkerVert; typedef vcg::vertex::PointDistanceFunctor VDistFunct; typedef vcg::ClosestIterator > ClosestBaseType; VDistFunct fn; ClosestVertexIterator(GridType &_Si):ClosestBaseType(_Si,fn){} // Commented out: it seems unuseful and make gcc complain. p. void SetMesh(MeshType *m) {this->tm.SetMesh(m);} }; template class TriRayIterator:public vcg::RayIterator,FaceTmark > { public: typedef GRID GridType; typedef MESH MeshType; typedef FaceTmark MarkerFace; typedef vcg::RayTriangleIntersectionFunctor FintFunct; typedef vcg::RayIterator > RayBaseType; typedef typename MESH::FaceType FaceType; typedef typename MESH::ScalarType ScalarType; TriRayIterator(GridType &_Si,const ScalarType &max_d):RayBaseType(_Si,FintFunct(),max_d){} // Commented out: it seems unuseful and make gcc complain. p. void SetMesh(MeshType *m) {this->tm.SetMesh(m);} }; } // end namespace trimesh } // end namespace vcg #endif qutemol/vcg/vcg/complex/trimesh/create/0000755000175000017500000000000011633404241016545 5ustar mbambaqutemol/vcg/vcg/complex/trimesh/create/platonic.h0000444000175000017500000005650311004010100020511 0ustar mbamba/**************************************************************************** * VCGLib o o * * Visual and Computer Graphics Library o o * * _ O _ * * Copyright(C) 2004 \/)\/ * * Visual Computing Lab /\/| * * ISTI - Italian National Research Council | * * \ * * All rights reserved. * * * * 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. * * * * 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 (http://www.gnu.org/licenses/gpl.txt) * * for more details. * * * ****************************************************************************/ /**************************************************************************** History $Log: platonic.h,v $ Revision 1.14 2008/04/24 04:44:48 cignoni added facegrid method to build just the faces Revision 1.13 2008/02/15 14:38:32 ganovelli added Cylinder(..). the filename platonic.h is lesser and lesser significant... Revision 1.12 2007/10/19 22:29:36 cignoni Re-Wrote basic build function Revision 1.11 2007/02/01 06:38:27 cignoni Added small comment to grid function Revision 1.10 2007/01/27 13:14:34 marfr960 Removed unuseful CoordType test Revision 1.9 2006/08/23 15:29:44 marfr960 *** empty log message *** Revision 1.8 2006/03/27 04:18:35 cignoni Double->Scalar in dodecahedron Revision 1.7 2006/01/30 08:09:05 cignoni Corrected Grid Revision 1.6 2006/01/22 17:10:15 cignoni Added Grid function (to build range map meshes...) Revision 1.5 2005/07/11 13:16:34 cignoni small gcc-related compiling issues (typenames,ending cr, initialization order) Revision 1.4 2005/07/01 11:17:06 cignoni Added option of passing a base mesh to Sphere for spherifying it Revision 1.3 2005/06/17 00:49:29 cignoni Added missing Sphere function Revision 1.2 2005/02/25 11:41:08 pietroni Fixed bug in Square Revision 1.1 2005/01/19 15:43:15 fiorin Moved from vcg/complex/trimesh to vcg/complex/trimesh/create Revision 1.10 2004/10/28 00:54:34 cignoni Better Doxygen documentation Revision 1.9 2004/09/24 10:14:38 fiorin Corrected bug in cone Revision 1.8 2004/09/22 15:12:38 fiorin Corrected bug in hexahedron Revision 1.7 2004/07/09 15:34:29 tarini Dodecahedron added! (and doxigened a little bit) Revision 1.6 2004/05/13 21:08:00 cignoni Conformed C++ syntax to GCC requirements Revision 1.5 2004/03/18 15:29:07 cignoni Completed Octahedron and Icosahedron Revision 1.2 2004/03/03 16:11:46 cignoni First working version (tetrahedron!) ****************************************************************************/ #ifndef __VCGLIB_PLATONIC #define __VCGLIB_PLATONIC #include #include #include #include namespace vcg { namespace tri { /** \addtogroup trimesh */ //@{ /** A set of functions that builds meshes that represent surfaces of platonic solids, and other simple shapes. The 1st parameter is the mesh that will be filled with the solid. */ template void Tetrahedron(TetraMeshType &in) { typedef TetraMeshType MeshType; typedef typename TetraMeshType::CoordType CoordType; typedef typename TetraMeshType::VertexPointer VertexPointer; typedef typename TetraMeshType::VertexIterator VertexIterator; typedef typename TetraMeshType::FaceIterator FaceIterator; in.Clear(); Allocator::AddVertices(in,4); Allocator::AddFaces(in,4); VertexPointer ivp[4]; VertexIterator vi=in.vert.begin(); ivp[0]=&*vi;(*vi).P()=CoordType ( 1.0, 1.0, 1.0); ++vi; ivp[1]=&*vi;(*vi).P()=CoordType (-1.0, 1.0,-1.0); ++vi; ivp[2]=&*vi;(*vi).P()=CoordType (-1.0,-1.0, 1.0); ++vi; ivp[3]=&*vi;(*vi).P()=CoordType ( 1.0,-1.0,-1.0); FaceIterator fi=in.face.begin(); (*fi).V(0)=ivp[0]; (*fi).V(1)=ivp[1]; (*fi).V(2)=ivp[2]; ++fi; (*fi).V(0)=ivp[0]; (*fi).V(1)=ivp[2]; (*fi).V(2)=ivp[3]; ++fi; (*fi).V(0)=ivp[0]; (*fi).V(1)=ivp[3]; (*fi).V(2)=ivp[1]; ++fi; (*fi).V(0)=ivp[3]; (*fi).V(1)=ivp[2]; (*fi).V(2)=ivp[1]; } /// builds a Dodecahedron, /// (each pentagon is composed of 5 triangles) template void Dodecahedron(DodMeshType & in) { typedef DodMeshType MeshType; typedef typename MeshType::CoordType CoordType; typedef typename MeshType::VertexPointer VertexPointer; typedef typename MeshType::VertexIterator VertexIterator; typedef typename MeshType::FaceIterator FaceIterator; typedef typename MeshType::ScalarType ScalarType; const int N_penta=12; const int N_points=62; int penta[N_penta*3*3]= {20,11, 18, 18, 11, 8, 8, 11, 4, 13,23, 4, 4, 23, 8, 8, 23, 16, 13, 4, 30, 30, 4, 28, 28, 4, 11, 16,34, 8, 8, 34, 18, 18, 34, 36, 11,20, 28, 28, 20, 45, 45, 20, 38, 13,30, 23, 23, 30, 41, 41, 30, 47, 16,23, 34, 34, 23, 50, 50, 23, 41, 20,18, 38, 38, 18, 52, 52, 18, 36, 30,28, 47, 47, 28, 56, 56, 28, 45, 50,60, 34, 34, 60, 36, 36, 60, 52, 45,38, 56, 56, 38, 60, 60, 38, 52, 50,41, 60, 60, 41, 56, 56, 41, 47 }; //A B E D C const ScalarType p=(1.0 + math::Sqrt(5.0)) / 2.0; const ScalarType p2=p*p; const ScalarType p3=p*p*p; ScalarType vv[N_points*3]= { 0, 0, 2*p2, p2, 0, p3, p, p2, p3, 0, p, p3, -p, p2, p3, -p2, 0, p3, -p, -p2, p3, 0, -p, p3, p, -p2, p3, p3, p, p2, p2, p2, p2, 0, p3, p2, -p2, p2, p2, -p3, p, p2, -p3, -p, p2, -p2, -p2, p2, 0, -p3, p2, p2, -p2, p2, p3, -p, p2, p3, 0, p, p2, p3, p, -p2, p3, p, -p3, 0, p, -p2, -p3, p, p2, -p3, p, 2*p2, 0, 0, p3, p2, 0, p, p3, 0, 0, 2*p2, 0, -p, p3, 0, -p3, p2, 0, -2*p2, 0, 0, -p3, -p2, 0, -p, -p3, 0, 0, -2*p2, 0, p, -p3, 0, p3, -p2, 0, p3, 0, -p, p2, p3, -p, -p2, p3, -p, -p3, 0, -p, -p2, -p3, -p, p2, -p3, -p, p3, p, -p2, p2, p2, -p2, 0, p3, -p2, -p2, p2, -p2, -p3, p, -p2, -p3, -p, -p2, -p2, -p2, -p2, 0, -p3, -p2, p2, -p2, -p2, p3, -p, -p2, p2, 0, -p3, p, p2, -p3, 0, p, -p3, -p, p2, -p3, -p2, 0, -p3, -p, -p2, -p3, 0, -p, -p3, p, -p2, -p3, 0, 0, -2*p2 }; in.Clear(); //in.face.clear(); Allocator::AddVertices(in,20+12); Allocator::AddFaces(in, 5*12); // five pentagons, each made by 5 tri int h,i,j,k=0,m=0; bool used[N_points]; for (i=0; i index(in.vn); for(j=0,vi=in.vert.begin();j void Octahedron(OctMeshType &in) { typedef OctMeshType MeshType; typedef typename MeshType::CoordType CoordType; typedef typename MeshType::VertexPointer VertexPointer; typedef typename MeshType::VertexIterator VertexIterator; typedef typename MeshType::FaceIterator FaceIterator; in.Clear(); Allocator::AddVertices(in,6); Allocator::AddFaces(in,8); VertexPointer ivp[6]; VertexIterator vi=in.vert.begin(); ivp[0]=&*vi;(*vi).P()=CoordType ( 1, 0, 0); ++vi; ivp[1]=&*vi;(*vi).P()=CoordType ( 0, 1, 0); ++vi; ivp[2]=&*vi;(*vi).P()=CoordType ( 0, 0, 1); ++vi; ivp[3]=&*vi;(*vi).P()=CoordType (-1, 0, 0); ++vi; ivp[4]=&*vi;(*vi).P()=CoordType ( 0,-1, 0); ++vi; ivp[5]=&*vi;(*vi).P()=CoordType ( 0, 0,-1); FaceIterator fi=in.face.begin(); (*fi).V(0)=ivp[0]; (*fi).V(1)=ivp[1]; (*fi).V(2)=ivp[2]; ++fi; (*fi).V(0)=ivp[0]; (*fi).V(1)=ivp[2]; (*fi).V(2)=ivp[4]; ++fi; (*fi).V(0)=ivp[0]; (*fi).V(1)=ivp[4]; (*fi).V(2)=ivp[5]; ++fi; (*fi).V(0)=ivp[0]; (*fi).V(1)=ivp[5]; (*fi).V(2)=ivp[1]; ++fi; (*fi).V(0)=ivp[3]; (*fi).V(1)=ivp[1]; (*fi).V(2)=ivp[5]; ++fi; (*fi).V(0)=ivp[3]; (*fi).V(1)=ivp[5]; (*fi).V(2)=ivp[4]; ++fi; (*fi).V(0)=ivp[3]; (*fi).V(1)=ivp[4]; (*fi).V(2)=ivp[2]; ++fi; (*fi).V(0)=ivp[3]; (*fi).V(1)=ivp[2]; (*fi).V(2)=ivp[1]; } template void Icosahedron(IcoMeshType &in) { typedef IcoMeshType MeshType; typedef typename MeshType::ScalarType ScalarType; typedef typename MeshType::CoordType CoordType; typedef typename MeshType::VertexPointer VertexPointer; typedef typename MeshType::VertexIterator VertexIterator; typedef typename MeshType::FaceIterator FaceIterator; ScalarType L=ScalarType((math::Sqrt(5.0)+1.0)/2.0); CoordType vv[12]={ CoordType ( 0, L, 1), CoordType ( 0, L,-1), 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 ( 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} }; in.Clear(); Allocator::AddVertices(in,12); Allocator::AddFaces(in,20); VertexPointer ivp[12]; VertexIterator vi; int i; for(i=0,vi=in.vert.begin();vi!=in.vert.end();++i,++vi){ (*vi).P()=vv[i]; ivp[i]=&*vi; } FaceIterator fi; for(i=0,fi=in.face.begin();fi!=in.face.end();++i,++fi){ (*fi).V(0)=ivp[ff[i][0]]; (*fi).V(1)=ivp[ff[i][1]]; (*fi).V(2)=ivp[ff[i][2]]; } } template void Hexahedron(MeshType &in) { typedef typename MeshType::ScalarType ScalarType; typedef typename MeshType::CoordType CoordType; typedef typename MeshType::VertexPointer VertexPointer; typedef typename MeshType::VertexIterator VertexIterator; typedef typename MeshType::FaceIterator FaceIterator; in.Clear(); Allocator::AddVertices(in,8); Allocator::AddFaces(in,12); VertexPointer ivp[8]; VertexIterator vi=in.vert.begin(); ivp[7]=&*vi;(*vi).P()=CoordType (-1,-1,-1); ++vi; ivp[6]=&*vi;(*vi).P()=CoordType ( 1,-1,-1); ++vi; ivp[5]=&*vi;(*vi).P()=CoordType (-1, 1,-1); ++vi; ivp[4]=&*vi;(*vi).P()=CoordType ( 1, 1,-1); ++vi; ivp[3]=&*vi;(*vi).P()=CoordType (-1,-1, 1); ++vi; ivp[2]=&*vi;(*vi).P()=CoordType ( 1,-1, 1); ++vi; ivp[1]=&*vi;(*vi).P()=CoordType (-1, 1, 1); ++vi; ivp[0]=&*vi;(*vi).P()=CoordType ( 1, 1, 1); FaceIterator fi=in.face.begin(); (*fi).V(0)=ivp[0]; (*fi).V(1)=ivp[1]; (*fi).V(2)=ivp[2]; ++fi; (*fi).V(0)=ivp[3]; (*fi).V(1)=ivp[2]; (*fi).V(2)=ivp[1]; ++fi; (*fi).V(0)=ivp[0]; (*fi).V(1)=ivp[2]; (*fi).V(2)=ivp[4]; ++fi; (*fi).V(0)=ivp[6]; (*fi).V(1)=ivp[4]; (*fi).V(2)=ivp[2]; ++fi; (*fi).V(0)=ivp[0]; (*fi).V(1)=ivp[4]; (*fi).V(2)=ivp[1]; ++fi; (*fi).V(0)=ivp[5]; (*fi).V(1)=ivp[1]; (*fi).V(2)=ivp[4]; ++fi; (*fi).V(0)=ivp[7]; (*fi).V(1)=ivp[5]; (*fi).V(2)=ivp[6]; ++fi; (*fi).V(0)=ivp[4]; (*fi).V(1)=ivp[6]; (*fi).V(2)=ivp[5]; ++fi; (*fi).V(0)=ivp[7]; (*fi).V(1)=ivp[6]; (*fi).V(2)=ivp[3]; ++fi; (*fi).V(0)=ivp[2]; (*fi).V(1)=ivp[3]; (*fi).V(2)=ivp[6]; ++fi; (*fi).V(0)=ivp[7]; (*fi).V(1)=ivp[3]; (*fi).V(2)=ivp[5]; ++fi; (*fi).V(0)=ivp[1]; (*fi).V(1)=ivp[5]; (*fi).V(2)=ivp[3]; } template void Square(MeshType &in) { typedef typename MeshType::ScalarType ScalarType; typedef typename MeshType::CoordType CoordType; typedef typename MeshType::VertexPointer VertexPointer; typedef typename MeshType::VertexIterator VertexIterator; typedef typename MeshType::FaceIterator FaceIterator; in.Clear(); Allocator::AddVertices(in,4); Allocator::AddFaces(in,2); VertexPointer ivp[4]; VertexIterator vi=in.vert.begin(); ivp[0]=&*vi;(*vi).P()=CoordType ( 1, 0, 0); ++vi; ivp[1]=&*vi;(*vi).P()=CoordType ( 0, 1, 0); ++vi; ivp[2]=&*vi;(*vi).P()=CoordType (-1, 0, 0); ++vi; ivp[3]=&*vi;(*vi).P()=CoordType ( 0,-1, 0); FaceIterator fi=in.face.begin(); (*fi).V(0)=ivp[0]; (*fi).V(1)=ivp[1]; (*fi).V(2)=ivp[2]; ++fi; (*fi).V(0)=ivp[0]; (*fi).V(1)=ivp[2]; (*fi).V(2)=ivp[3]; } // this function build a sphere starting from a eventually not empty mesh. // If the mesh is not empty it is 'spherified' and used as base for the subdivision process. // otherwise an icosahedron is used. template void Sphere(MeshType &in, const int subdiv = 3 ) { typedef typename MeshType::ScalarType ScalarType; typedef typename MeshType::CoordType CoordType; typedef typename MeshType::VertexPointer VertexPointer; typedef typename MeshType::VertexIterator VertexIterator; 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(); tri::UpdateFlags::FaceBorderFromNone(in); size_t lastsize = 0; for(int i = 0 ; i < subdiv; ++i) { Refine< MeshType, MidPoint >(in, MidPoint(), 0); for(vi = in.vert.begin() + lastsize; vi != in.vert.end(); ++vi) vi->P().Normalize(); lastsize = in.vert.size(); } } /// 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 ) { typedef typename MeshType::ScalarType ScalarType; typedef typename MeshType::CoordType CoordType; typedef typename MeshType::VertexPointer VertexPointer; typedef typename MeshType::VertexIterator VertexIterator; typedef typename MeshType::FaceIterator FaceIterator; const int D = 24; int i,b1,b2; in.Clear(); int VN,FN; if(r1==0 || r2==0) { VN=D+2; FN=D*2; } else { VN=D*2+2; FN=D*4; } Allocator::AddVertices(in,VN); Allocator::AddFaces(in,FN); VertexPointer *ivp = new VertexPointer[VN]; VertexIterator vi=in.vert.begin(); ivp[0]=&*vi;(*vi).P()=CoordType ( 0,-h/2,0 ); ++vi; ivp[1]=&*vi;(*vi).P()=CoordType ( 0, h/2,0 ); ++vi; b1 = b2 = 2; int cnt=2; if(r1!=0) { for(i=0;i void Box(MeshType &in, const typename MeshType::BoxType & bb ) { typedef typename MeshType::ScalarType ScalarType; typedef typename MeshType::CoordType CoordType; typedef typename MeshType::VertexPointer VertexPointer; typedef typename MeshType::VertexIterator VertexIterator; typedef typename MeshType::FaceIterator FaceIterator; in.Clear(); Allocator::AddVertices(in,8); Allocator::AddFaces(in,12); VertexPointer ivp[8]; VertexIterator vi=in.vert.begin(); ivp[0]=&*vi;(*vi).P()=CoordType (bb.min[0],bb.min[1],bb.min[2]); ++vi; ivp[1]=&*vi;(*vi).P()=CoordType (bb.max[0],bb.min[1],bb.min[2]); ++vi; ivp[2]=&*vi;(*vi).P()=CoordType (bb.min[0],bb.max[1],bb.min[2]); ++vi; ivp[3]=&*vi;(*vi).P()=CoordType (bb.max[0],bb.max[1],bb.min[2]); ++vi; ivp[3]=&*vi;(*vi).P()=CoordType (bb.min[0],bb.min[1],bb.max[2]); ++vi; ivp[3]=&*vi;(*vi).P()=CoordType (bb.max[0],bb.min[1],bb.max[2]); ++vi; ivp[4]=&*vi;(*vi).P()=CoordType (bb.min[0],bb.max[1],bb.max[2]); ++vi; ivp[5]=&*vi;(*vi).P()=CoordType (bb.max[0],bb.max[1],bb.max[2]); FaceIterator fi=in.face.begin(); (*fi).V(0)=ivp[0]; (*fi).V(1)=ivp[1]; (*fi).V(2)=ivp[2]; ++fi; (*fi).V(0)=ivp[3]; (*fi).V(1)=ivp[2]; (*fi).V(2)=ivp[1]; ++fi; (*fi).V(0)=ivp[0]; (*fi).V(1)=ivp[2]; (*fi).V(2)=ivp[4]; ++fi; (*fi).V(0)=ivp[6]; (*fi).V(1)=ivp[4]; (*fi).V(2)=ivp[2]; ++fi; (*fi).V(0)=ivp[0]; (*fi).V(1)=ivp[4]; (*fi).V(2)=ivp[1]; ++fi; (*fi).V(0)=ivp[5]; (*fi).V(1)=ivp[1]; (*fi).V(2)=ivp[4]; ++fi; (*fi).V(0)=ivp[7]; (*fi).V(1)=ivp[5]; (*fi).V(2)=ivp[6]; ++fi; (*fi).V(0)=ivp[4]; (*fi).V(1)=ivp[6]; (*fi).V(2)=ivp[5]; ++fi; (*fi).V(0)=ivp[7]; (*fi).V(1)=ivp[6]; (*fi).V(2)=ivp[3]; ++fi; (*fi).V(0)=ivp[2]; (*fi).V(1)=ivp[3]; (*fi).V(2)=ivp[6]; ++fi; (*fi).V(0)=ivp[7]; (*fi).V(1)=ivp[3]; (*fi).V(2)=ivp[5]; ++fi; (*fi).V(0)=ivp[1]; (*fi).V(1)=ivp[5]; (*fi).V(2)=ivp[3]; } // this function build a mesh starting from a vector of generic coords (objects having a triple of float at their beginning) // and a vector of faces (objects having a triple of ints at theri beginning). template void Build( MeshType & in, const V & v, const F & f) { typedef typename MeshType::ScalarType ScalarType; typedef typename MeshType::CoordType CoordType; typedef typename MeshType::VertexPointer VertexPointer; typedef typename MeshType::VertexIterator VertexIterator; typedef typename MeshType::FaceIterator FaceIterator; Allocator::AddVertices(in,v.size()); Allocator::AddFaces(in,f.size()); typename V::const_iterator vi; typename MeshType::VertexType tv; // tv.Supervisor_Flags()=0; for(int i=0;i index(in.vn); VertexIterator j; int k; for(k=0,j=in.vert.begin();j!=in.vert.end();++j,++k) index[k] = &*j; typename F::const_iterator fi; typename MeshType::FaceType ft; for(int i=0;i=0 ); assert( ff[1]>=0 ); assert( ff[2]>=0 ); assert( ff[0] array // Once generated the vertex positions it uses the FaceGrid function to generate the faces; template void Grid(MeshType & in, int w, int h, float wl, float hl, float *data) { typedef typename MeshType::CoordType CoordType; typedef typename MeshType::VertexPointer VertexPointer; typedef typename MeshType::VertexIterator VertexIterator; typedef typename MeshType::FaceIterator FaceIterator; in.Clear(); Allocator::AddVertices(in,w*h); float wld=wl/float(w); float hld=hl/float(h); for(int i=0;i void FaceGrid(MeshType & in, int w, int h) { assert(in.vn == in.vert.size()); // require a compact vertex vector assert(in.vn <= w*h); // the number of vertices should be large enough Allocator::AddFaces(in,(w-1)*(h-1)*2); // i+0,j+0 -- i+0,j+1 // | \ | // | \ | // | \ | // | \ | // i+1,j+0 -- i+1,j+1 // for(int i=0;i void Cylinder(const int &slices, const int &stacks, MeshType & m){ float rad_step = M_PI / (float)stacks; float sli_step = 1.0 / (float)slices; float angle = 0,heigth = 0; float x,y,h; typename MeshType::VertexIterator vi = vcg::tri::Allocator::AddVertices(m,slices*stacks); for ( int j = 0; j < slices; ++j) for ( int i = 0; i < stacks; ++i){ x = cos( 2.0 * M_PI / stacks * i); y = sin( 2.0 * M_PI / stacks * i); h = j / (float)slices; (*vi).P() = MeshType::CoordType(x,y,h); ++vi; } typename MeshType::FaceIterator fi ; for ( int j = 0; j < slices-1; ++j) for ( int i = 0; i < stacks; ++i){ if(((i+j)%2) == 0){ fi = vcg::tri::Allocator::AddFaces(m,1); (*fi).V(0) = &m.vert[j *stacks+ i]; (*fi).V(1) = &m.vert[j *stacks+(i+1)%stacks]; (*fi).V(2) = &m.vert[(j+1)*stacks+(i+1)%stacks]; fi = vcg::tri::Allocator::AddFaces(m,1); (*fi).V(0) = &m.vert[j *stacks+i]; (*fi).V(1) = &m.vert[(j+1)*stacks+(i+1)%stacks]; (*fi).V(2) = &m.vert[(j+1)*stacks+i]; } else{ fi = vcg::tri::Allocator::AddFaces(m,1); (*fi).V(0) = &m.vert[(j+1) *stacks+i]; (*fi).V(1) = &m.vert[ j *stacks+i]; (*fi).V(2) = &m.vert[ j *stacks+(i+1)%stacks]; fi = vcg::tri::Allocator::AddFaces(m,1); (*fi).V(0) = &m.vert[(j+1) *stacks+i]; (*fi).V(1) = &m.vert[ j *stacks+(i+1)%stacks]; (*fi).V(2) = &m.vert[ (j+1) *stacks+(i+1)%stacks]; } } } //@} } // End Namespace TriMesh } // End Namespace vcg #endif qutemol/vcg/vcg/complex/trimesh/create/advancing_front.h0000444000175000017500000003517310776640023022076 0ustar mbamba#ifndef MLS_ADVANCE_H #define MLS_ADVANCE_H #include #include #include #include #include namespace vcg { namespace tri { class FrontEdge { public: int v0, v1, v2; //v0, v1 represent the FrontEdge, v2 the other vertex //in the face this FrontEdge belongs to int face; //index of the face bool active; //keep tracks of wether it is in front or in deads //the loops in the front are mantained as a double linked list std::list::iterator next; std::list::iterator previous; FrontEdge() {} FrontEdge(int _v0, int _v1, int _v2, int _face): v0(_v0), v1(_v1), v2(_v2), face(_face), active(true) { assert(v0 != v1 && v1 != v2 && v0 != v2); } }; template class AdvancingFront { public: typedef typename MESH::VertexType VertexType; typedef typename MESH::FaceType FaceType; typedef typename MESH::ScalarType ScalarType; typedef typename MESH::VertexType::CoordType Point3x; // protected: std::list front; std::list deads; std::vector nb; //number of fronts a vertex is into, //this is used for the Visited and Border flags //but adding topology may not be needed anymore public: MESH &mesh; //this structure will be filled by the algorithm AdvancingFront(MESH &_mesh): mesh(_mesh) { UpdateFlags::FaceBorderFromNone(mesh); UpdateFlags::VertexBorderFromFace(mesh); nb.clear(); nb.resize(mesh.vert.size(), 0); CreateLoops(); } virtual ~AdvancingFront() {} virtual ScalarType radi() { return 0; } void BuildMesh(CallBackPos call = NULL, int interval = 512) { while(1) { if(call) call(0, "Advancing front"); for(int i = 0; i < interval; i++) { if(!front.size() && !SeedFace()) return; AddFace(); } } } protected: //Implement these functions in your subclass virtual bool Seed(int &v0, int &v1, int &v2) = 0; virtual int Place(FrontEdge &e, std::list::iterator &touch) = 0; bool CheckFrontEdge(int v0, int v1) { int tot = 0; //HACK to speed up things until i can use a seach structure // int i = mesh.face.size() - 4*(front.size()); // if(front.size() < 100) i = mesh.face.size() - 100; int i = 0; if(i < 0) i = 0; for(; i < (int)mesh.face.size(); i++) { FaceType &f = mesh.face[i]; for(int k = 0; k < 3; k++) { if(v1== (int)f.V(k) && v0 == (int)f.V((k+1)%3)) ++tot; else if(v0 == (int)f.V(k) && v1 == (int)f.V((k+1)%3)) { //orientation non constistent return false; } } if(tot >= 2) { //non manifold return false; } } return true; } //create the FrontEdge loops from seed faces void CreateLoops() { VertexType *start = &*mesh.vert.begin(); for(int i = 0; i < (int)mesh.face.size(); i++) { FaceType &f = mesh.face[i]; if(f.IsD()) continue; for(int k = 0; k < 3; k++) { if(f.IsB(k)) { NewEdge(FrontEdge(f.V0(k) - start, f.V1(k) - start, f.V2(k) - start, i)); nb[f.V0(k)-start]++; } } } for(std::list::iterator s = front.begin(); s != front.end(); s++) { (*s).previous = front.end(); (*s).next = front.end(); } //now create loops: for(std::list::iterator s = front.begin(); s != front.end(); s++) { for(std::list::iterator j = front.begin(); j != front.end(); j++) { if(s == j) continue; if((*s).v1 != (*j).v0) continue; if((*j).previous != front.end()) continue; (*s).next = j; (*j).previous = s; break; } } for(std::list::iterator s = front.begin(); s != front.end(); s++) { assert((*s).next != front.end()); assert((*s).previous != front.end()); } } bool SeedFace() { int v[3]; bool success = Seed(v[0], v[1], v[2]); if(!success) return false; nb.resize(mesh.vert.size(), 0); //create the border of the first face std::list::iterator e = front.end(); std::list::iterator last = e; std::list::iterator first; for(int i = 0; i < 3; i++) { int v0 = v[i]; int v1 = v[((i+1)%3)]; int v2 = v[((i+2)%3)]; mesh.vert[v0].SetB(); nb[v[i]]++; e = front.insert(front.begin(), FrontEdge(v0, v1, v2, mesh.face.size())); if(i != 0) { (*last).next = e; (*e).previous = last; } else first = e; last = e; } //connect last and first (*last).next = first; (*first).previous = last; AddFace(v[0], v[1], v[2]); return true; } public: bool AddFace() { if(!front.size()) return false; std::list::iterator ei = front.begin(); FrontEdge ¤t = *ei; FrontEdge &previous = *current.previous; FrontEdge &next = *current.next; int v0 = current.v0, v1 = current.v1; assert(nb[v0] < 10 && nb[v1] < 10); std::list::iterator touch = front.end(); int v2 = Place(current, touch); if(v2 == -1) { KillEdge(ei); return false; } assert(v2 != v0 && v2 != v1); if(touch != front.end()) { //check for orientation and manifoldness //touch == current.previous? if(v2 == previous.v0) { if(!CheckEdge(v2, v1)) { KillEdge(ei); return false; } /*touching previous FrontEdge (we reuse previous) next ------->v2 -----> v1------> \ / \ / previous \ / current \ / v0 */ Detach(v0); std::list::iterator up = NewEdge(FrontEdge(v2, v1, v0, mesh.face.size())); MoveFront(up); (*up).previous = previous.previous; (*up).next = current.next; (*previous.previous).next = up; next.previous = up; Erase(current.previous); Erase(ei); Glue(up); //touch == (*current.next).next } else if(v2 == next.v1) { if(!CheckEdge(v0, v2)) { KillEdge(ei); return false; } /*touching next FrontEdge (we reuse next) previous ------->v0 -----> v2------> \ / \ / \ / next \ / v1 */ Detach(v1); std::list::iterator up = NewEdge(FrontEdge(v0, v2, v1, mesh.face.size())); MoveFront(up); (*up).previous = current.previous; (*up).next = (*current.next).next; previous.next = up; (*next.next).previous = up; Erase(current.next); Erase(ei); Glue(up); } else { if(!CheckEdge(v0, v2) || !CheckEdge(v2, v1)) { KillEdge(ei); return false; } //touching some loop: split (or merge it is local does not matter. //like this /* left right <--------v2-<------ /|\ / \ up / \ down / \ / V ----v0 - - - > v1--------- current */ std::list::iterator left = touch; std::list::iterator right = (*touch).previous; //this would be a really bad join if(v1 == (*right).v0 || v0 == (*left).v1) { KillEdge(ei); return false; } nb[v2]++; std::list::iterator down = NewEdge(FrontEdge(v2, v1, v0, mesh.face.size())); std::list::iterator up = NewEdge(FrontEdge(v0, v2, v1, mesh.face.size())); (*right).next = down; (*down).previous = right; (*down).next = current.next; next.previous = down; (*left).previous = up; (*up).next = left; (*up).previous = current.previous; previous.next = up; Erase(ei); } } else { // assert(CheckEdge(v0, v2)); // assert(CheckEdge(v2, v1)); /* adding a new vertex v2 /|\ / \ up / \ down / \ / V ----v0 - - - > v1--------- */ assert(!mesh.vert[v2].IsB()); //fatal error! a new point is already a border? nb[v2]++; mesh.vert[v2].SetB(); std::list::iterator down = NewEdge(FrontEdge(v2, v1, v0, mesh.face.size())); std::list::iterator up = NewEdge(FrontEdge(v0, v2, v1, mesh.face.size())); (*down).previous = up; (*up).next = down; (*down).next = current.next; next.previous = down; (*up).previous = current.previous; previous.next = up; Erase(ei); } AddFace(v0, v2, v1); return false; } protected: void AddFace(int v0, int v1, int v2) { assert(v0 < (int)mesh.vert.size() && v1 < (int)mesh.vert.size() && v2 < (int)mesh.vert.size()); FaceType face; face.V(0) = &mesh.vert[v0]; face.V(1) = &mesh.vert[v1]; face.V(2) = &mesh.vert[v2]; ComputeNormalizedNormal(face); mesh.face.push_back(face); mesh.fn++; } void AddVertex(VertexType &vertex) { VertexType *oldstart = NULL; if(mesh.vert.size()) oldstart = &*mesh.vert.begin(); mesh.vert.push_back(vertex); mesh.vn++; VertexType *newstart = &*mesh.vert.begin(); if(oldstart && oldstart != newstart) { for(int i = 0; i < mesh.face.size(); i++) { FaceType &face = mesh.face[i]; for(int k = 0; k < 3; k++) face.V(k) = newstart + (face.V(k) - oldstart); } } nb.push_back(0); } bool CheckEdge(int v0, int v1) { int tot = 0; //HACK to speed up things until i can use a seach structure /* int i = mesh.face.size() - 4*(front.size()); if(front.size() < 100) i = mesh.face.size() - 100; if(i < 0) i = 0;*/ VertexType *vv0 = &(mesh.vert[v0]); VertexType *vv1 = &(mesh.vert[v1]); for(int i = 0; i < (int)mesh.face.size(); i++) { FaceType &f = mesh.face[i]; for(int k = 0; k < 3; k++) { if(vv0 == f.V0(k) && vv1 == f.V1(k)) //orientation non constistent return false; else if(vv1 == f.V0(k) && vv0 == f.V1(k)) ++tot; } if(tot >= 2) { //non manifold return false; } } return true; } //front management: //Add a new FrontEdge to the back of the queue std::list::iterator NewEdge(FrontEdge e) { return front.insert(front.end(), e); } //move an Edge among the dead ones void KillEdge(std::list::iterator e) { (*e).active = false; deads.splice(deads.end(), front, e); } void Erase(std::list::iterator e) { if((*e).active) front.erase(e); else deads.erase(e); } //move an FrontEdge to the back of the queue void MoveBack(std::list::iterator e) { front.splice(front.end(), front, e); } void MoveFront(std::list::iterator e) { front.splice(front.begin(), front, e); } //check if e can be sewed with one of oits neighbours bool Glue(std::list::iterator e) { return Glue((*e).previous, e) || Glue(e, (*e).next); } //Glue toghether a and b (where a.next = b bool Glue(std::list::iterator a, std::list::iterator b) { if((*a).v0 != (*b).v1) return false; std::list::iterator previous = (*a).previous; std::list::iterator next = (*b).next; (*previous).next = next; (*next).previous = previous; Detach((*a).v1); Detach((*a).v0); Erase(a); Erase(b); return true; } void Detach(int v) { assert(nb[v] > 0); if(--nb[v] == 0) { mesh.vert[v].ClearB(); } } }; template class AdvancingTest: public AdvancingFront { public: typedef typename MESH::VertexType VertexType; typedef typename MESH::VertexIterator VertexIterator; typedef typename MESH::FaceType FaceType; typedef typename MESH::FaceIterator FaceIterator; typedef typename MESH::ScalarType ScalarType; typedef typename MESH::VertexType::CoordType Point3x; AdvancingTest(MESH &_mesh): AdvancingFront(_mesh) {} bool Seed(int &v0, int &v1, int &v2) { VertexType v[3]; v[0].P() = Point3x(0, 0, 0); v[1].P() = Point3x(1, 0, 0); v[2].P() = Point3x(0, 1, 0); v[0].ClearFlags(); v[1].ClearFlags(); v[2].ClearFlags(); v0 = this->mesh.vert.size(); AddVertex(v[0]); v1 = this->mesh.vert.size(); AddVertex(v[1]); v2 = this->mesh.vert.size(); AddVertex(v[2]); return true; } int Place(FrontEdge &e, std::list::iterator &touch) { Point3f p[3]; p[0] = this->mesh.vert[e.v0].P(); p[1] = this->mesh.vert[e.v1].P(); p[2] = this->mesh.vert[e.v2].P(); Point3f point = p[0] + p[1] - p[2]; int vn = this->mesh.vert.size(); for(int i = 0; i < this->mesh.vert.size(); i++) { if((this->mesh.vert[i].P() - point).Norm() < 0.1) { vn = i; //find the border assert(this->mesh.vert[i].IsB()); for(std::list::iterator k = this->front.begin(); k != this->front.end(); k++) if((*k).v0 == i) touch = k; for(std::list::iterator k = this->deads.begin(); k != this->deads.end(); k++) if((*k).v0 == i) touch = k; break; } } if(vn == this->mesh.vert.size()) { VertexType v; v.P() = point; v.ClearFlags(); AddVertex(v); } return vn; } }; }//namespace tri }//namespace vcg #endif qutemol/vcg/vcg/complex/trimesh/create/emc_lookup_table.h0000444000175000017500000011724610222557515022241 0ustar mbamba/*===========================================================================*\ * * * IsoEx * * Copyright (C) 2002 by Computer Graphics Group, RWTH Aachen * * www.rwth-graphics.de * * * *---------------------------------------------------------------------------* * * * License * * * * This library is free software; you can redistribute it and/or modify it * * under the terms of the GNU Library General Public License as published * * by the Free Software Foundation, version 2. * * * * This library 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 * * Library General Public License for more details. * * * * You should have received a copy of the GNU Library General Public * * License along with this library; if not, write to the Free Software * * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * * \*===========================================================================*/ //== TABLES ================================================================== #ifndef __VCG_EMC_LOOK_UP_TABLE #define __VCG_EMC_LOOK_UP_TABLE namespace vcg { namespace tri { class EMCLookUpTable { public: static const int EdgeTable(unsigned char cubetype) { static const int edgeTable[256]= { 0x0 , 0x109, 0x203, 0x30a, 0x406, 0x50f, 0x605, 0x70c, 0x80c, 0x905, 0xa0f, 0xb06, 0xc0a, 0xd03, 0xe09, 0xf00, 0x190, 0x99 , 0x393, 0x29a, 0x596, 0x49f, 0x795, 0x69c, 0x99c, 0x895, 0xb9f, 0xa96, 0xd9a, 0xc93, 0xf99, 0xe90, 0x230, 0x339, 0x33 , 0x13a, 0x636, 0x73f, 0x435, 0x53c, 0xa3c, 0xb35, 0x83f, 0x936, 0xe3a, 0xf33, 0xc39, 0xd30, 0x3a0, 0x2a9, 0x1a3, 0xaa , 0x7a6, 0x6af, 0x5a5, 0x4ac, 0xbac, 0xaa5, 0x9af, 0x8a6, 0xfaa, 0xea3, 0xda9, 0xca0, 0x460, 0x569, 0x663, 0x76a, 0x66 , 0x16f, 0x265, 0x36c, 0xc6c, 0xd65, 0xe6f, 0xf66, 0x86a, 0x963, 0xa69, 0xb60, 0x5f0, 0x4f9, 0x7f3, 0x6fa, 0x1f6, 0xff , 0x3f5, 0x2fc, 0xdfc, 0xcf5, 0xfff, 0xef6, 0x9fa, 0x8f3, 0xbf9, 0xaf0, 0x650, 0x759, 0x453, 0x55a, 0x256, 0x35f, 0x55 , 0x15c, 0xe5c, 0xf55, 0xc5f, 0xd56, 0xa5a, 0xb53, 0x859, 0x950, 0x7c0, 0x6c9, 0x5c3, 0x4ca, 0x3c6, 0x2cf, 0x1c5, 0xcc , 0xfcc, 0xec5, 0xdcf, 0xcc6, 0xbca, 0xac3, 0x9c9, 0x8c0, 0x8c0, 0x9c9, 0xac3, 0xbca, 0xcc6, 0xdcf, 0xec5, 0xfcc, 0xcc , 0x1c5, 0x2cf, 0x3c6, 0x4ca, 0x5c3, 0x6c9, 0x7c0, 0x950, 0x859, 0xb53, 0xa5a, 0xd56, 0xc5f, 0xf55, 0xe5c, 0x15c, 0x55 , 0x35f, 0x256, 0x55a, 0x453, 0x759, 0x650, 0xaf0, 0xbf9, 0x8f3, 0x9fa, 0xef6, 0xfff, 0xcf5, 0xdfc, 0x2fc, 0x3f5, 0xff , 0x1f6, 0x6fa, 0x7f3, 0x4f9, 0x5f0, 0xb60, 0xa69, 0x963, 0x86a, 0xf66, 0xe6f, 0xd65, 0xc6c, 0x36c, 0x265, 0x16f, 0x66 , 0x76a, 0x663, 0x569, 0x460, 0xca0, 0xda9, 0xea3, 0xfaa, 0x8a6, 0x9af, 0xaa5, 0xbac, 0x4ac, 0x5a5, 0x6af, 0x7a6, 0xaa , 0x1a3, 0x2a9, 0x3a0, 0xd30, 0xc39, 0xf33, 0xe3a, 0x936, 0x83f, 0xb35, 0xa3c, 0x53c, 0x435, 0x73f, 0x636, 0x13a, 0x33 , 0x339, 0x230, 0xe90, 0xf99, 0xc93, 0xd9a, 0xa96, 0xb9f, 0x895, 0x99c, 0x69c, 0x795, 0x49f, 0x596, 0x29a, 0x393, 0x99 , 0x190, 0xf00, 0xe09, 0xd03, 0xc0a, 0xb06, 0xa0f, 0x905, 0x80c, 0x70c, 0x605, 0x50f, 0x406, 0x30a, 0x203, 0x109, 0x0 }; return edgeTable[cubetype]; }; // end of EdgeTable //----------------------------------------------------------------------------- static int* TriTable(unsigned char cubetype, int u) { static int triTable[256][2][17] = {{{-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, { 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, {{0, 8, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {1, 3, 0, 8, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, {{0, 1, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {1, 3, 0, 1, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, {{1, 8, 3, 9, 8, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {1, 4, 1, 9, 8, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, {{1, 2, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {1, 3, 1, 2, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, {{0, 8, 3, 1, 2, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {2, 3, 3, 0, 8, 3, 1, 2, 10, -1, -1, -1, -1, -1, -1, -1, -1}}, {{9, 2, 10, 0, 2, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {1, 4, 2, 10, 9, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, {{2, 8, 3, 2, 10, 8, 10, 9, 8, -1, -1, -1, -1, -1, -1, -1, -1}, {1, 5, 10, 9, 8, 3, 2 , -1,-1, -1, -1, -1, -1, -1, -1, -1, -1}}, {{3, 11, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {1, 3, 3, 11, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, {{0, 11, 2, 8, 11, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {1, 4, 0, 8, 11, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, /* 10 */ {{1, 9, 0, 2, 3, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {2, 3, 3, 1, 9, 0, 2, 3,11, -1, -1, -1, -1, -1, -1, -1, -1}}, {{1, 11, 2, 1, 9, 11, 9, 8, 11, -1, -1, -1, -1, -1, -1, -1, -1}, {1, 5, 9, 8, 11, 2, 1,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, {{3, 10, 1, 11, 10, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {1, 4, 3, 11,10, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, {{0, 10, 1, 0, 8, 10, 8, 11, 10, -1, -1, -1, -1, -1, -1, -1, -1}, {1, 5, 8, 11, 10, 1, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, {{3, 9, 0, 3, 11, 9, 11, 10, 9, -1, -1, -1, -1, -1, -1, -1, -1}, {1, 5, 11,10, 9, 0, 3, -1,-1, -1, -1, -1, -1, -1, -1, -1, -1}}, /* 15 */ {{9, 8, 10, 10, 8, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {1, 4, 8, 11, 10, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, {{4, 7, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {1, 3, 4, 7, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, {{4, 3, 0, 7, 3, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {1, 4, 4, 7, 3, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, {{0, 1, 9, 8, 4, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {2, 3, 3, 0, 1, 9, 8, 4, 7, -1, -1, -1, -1, -1, -1, -1, -1}}, {{4, 1, 9, 4, 7, 1, 7, 3, 1, -1, -1, -1, -1, -1, -1, -1, -1}, {1, 5, 7, 3, 1, 9, 4, -1,-1, -1, -1, -1, -1, -1, -1, -1, -1}}, /* 20 */ {{1, 2, 10, 8, 4, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {2, 3, 3, 1, 2,10, 8, 4, 7, -1, -1, -1, -1, -1, -1, -1, -1}}, {{3, 4, 7, 3, 0, 4, 1, 2, 10, -1, -1, -1, -1, -1, -1, -1, -1}, {2, 4, 3, 3, 0, 4, 7, 1, 2, 10, -1, -1, -1, -1, -1, -1, -1}}, {{9, 2, 10, 9, 0, 2, 8, 4, 7, -1, -1, -1, -1, -1, -1, -1, -1}, {2, 4, 3, 2,10, 9, 0, 8, 4, 7, -1, -1, -1, -1, -1, -1, -1}}, {{2, 10, 9, 2, 9, 7, 2, 7, 3, 7, 9, 4, -1, -1, -1, -1, -1}, {1, 6, 7, 3, 2,10, 9, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, {{8, 4, 7, 3, 11, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {2, 3, 3, 8, 4, 7, 3, 11, 2, -1, -1, -1, -1, -1, -1, -1, -1}}, /* 25 */ {{11, 4, 7, 11, 2, 4, 2, 0, 4, -1, -1, -1, -1, -1, -1, -1, -1}, { 1, 5, 2, 0, 4, 7,11,-1,-1, -1, -1, -1, -1, -1, -1, -1, -1}}, {{9, 0, 1, 8, 4, 7, 2, 3, 11, -1, -1, -1, -1, -1, -1, -1, -1}, {3, 3, 3, 3, 9, 0, 1, 8, 4, 7, 2, 3, 11, -1, -1, -1, -1}}, {{4, 7, 11, 9, 4, 11, 9, 11, 2, 9, 2, 1, -1, -1, -1, -1, -1}, {2, 4, 4, 2, 1, 9, 11, 11,9,4,7, -1, -1, -1, -1, -1 ,-1}}, {{3, 10, 1, 3, 11, 10, 7, 8, 4, -1, -1, -1, -1, -1, -1, -1, -1}, {2, 4, 3, 3, 11,10, 1, 7, 8, 4, -1, -1, -1, -1, -1, -1, -1}}, {{1, 11, 10, 1, 4, 11, 1, 0, 4, 7, 11, 4, -1, -1, -1, -1, -1}, {1, 6, 1, 0, 4, 7,11,10, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, /* 30 */ {{4, 7, 8, 9, 0, 11, 9, 11, 10, 11, 0, 3, -1, -1, -1, -1, -1}, {2, 3, 5, 4, 7, 8, 0, 3, 11, 10, 9, -1, -1, -1, -1, -1, -1}}, {{4, 7, 11, 4, 11, 9, 9, 11, 10, -1, -1, -1, -1, -1, -1, -1, -1}, {1, 5, 4, 7,11,10, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, {{9, 5, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {1, 3, 9, 5, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, {{9, 5, 4, 0, 8, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {2, 3, 3, 9, 5, 4, 0, 8, 3, -1, -1, -1, -1, -1, -1, -1, -1}}, {{0, 5, 4, 1, 5, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {1, 4, 0, 1, 5, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, /* 35 */ {{8, 5, 4, 8, 3, 5, 3, 1, 5, -1, -1, -1, -1, -1, -1, -1, -1}, {1, 5, 3, 1, 5, 4, 8,-1,-1, -1, -1, -1, -1, -1, -1, -1, -1}}, {{1, 2, 10, 9, 5, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {2, 3, 3, 1, 2,10, 9, 5, 4, -1, -1, -1, -1, -1, -1, -1, -1}}, {{3, 0, 8, 1, 2, 10, 4, 9, 5, -1, -1, -1, -1, -1, -1, -1, -1}, {3, 3, 3, 3, 3, 0, 8, 1, 2, 10, 4, 9, 5, -1, -1, -1, -1}}, {{5, 2, 10, 5, 4, 2, 4, 0, 2, -1, -1, -1, -1, -1, -1, -1, -1}, {1, 5, 4, 0, 2,10, 5,-1,-1, -1, -1, -1, -1, -1, -1, -1, -1}}, {{2, 10, 5, 3, 2, 5, 3, 5, 4, 3, 4, 8, -1, -1, -1, -1, -1}, {2, 4, 4, 2, 10, 5, 3, 4, 8, 3, 5, -1, -1, -1, -1, -1, -1}}, /* 40 */ {{9, 5, 4, 2, 3, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {2, 3, 3, 9, 5, 4, 2, 3, 11, -1, -1, -1, -1, -1, -1, -1, -1}}, {{0, 11, 2, 0, 8, 11, 4, 9, 5, -1, -1, -1, -1, -1, -1, -1, -1}, {2, 4, 3, 0, 8, 11, 2, 4, 9, 5, -1, -1, -1, -1, -1, -1, -1}}, {{0, 5, 4, 0, 1, 5, 2, 3, 11, -1, -1, -1, -1, -1, -1, -1, -1}, {2, 4, 3, 0, 1, 5, 4, 2, 3, 11, -1, -1, -1, -1, -1, -1, -1}}, {{2, 1, 5, 2, 5, 8, 2, 8, 11, 4, 8, 5, -1, -1, -1, -1, -1}, {1, 6, 2, 1, 5, 4, 8,11, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, {{10, 3, 11, 10, 1, 3, 9, 5, 4, -1, -1, -1, -1, -1, -1, -1, -1}, { 2, 4, 3, 3,11,10, 1, 9, 5, 4, -1, -1, -1, -1, -1, -1, -1}}, /* 45 */ {{4, 9, 5, 0, 8, 1, 8, 10, 1, 8, 11, 10, -1, -1, -1, -1, -1}, {2, 3, 5, 4, 9, 5, 1, 0, 8,11, 10, -1, -1, -1, -1, -1, -1}}, {{5, 4, 0, 5, 0, 11, 5, 11, 10, 11, 0, 3, -1, -1, -1, -1, -1}, {1, 6, 5, 4, 0, 3,11, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, {{5, 4, 8, 5, 8, 10, 10, 8, 11, -1, -1, -1, -1, -1, -1, -1, -1}, {1, 5, 5, 4, 8, 11, 10,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, {{9, 7, 8, 5, 7, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {1, 4, 7, 8, 9, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, {{9, 3, 0, 9, 5, 3, 5, 7, 3, -1, -1, -1, -1, -1, -1, -1, -1}, {1, 5, 5, 7, 3, 0, 9,-1,-1, -1, -1, -1, -1, -1, -1, -1, -1}}, /* 50 */ {{0, 7, 8, 0, 1, 7, 1, 5, 7, -1, -1, -1, -1, -1, -1, -1, -1}, {1, 5, 1, 5, 7, 8, 0,-1,-1, -1, -1, -1, -1, -1, -1, -1, -1}}, {{1, 5, 3, 3, 5, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {1, 4, 3, 1, 5, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, {{9, 7, 8, 9, 5, 7, 10, 1, 2, -1, -1, -1, -1, -1, -1, -1, -1}, {2, 4, 3, 7, 8, 9, 5,10, 1, 2, -1, -1, -1, -1, -1, -1, -1}}, {{10, 1, 2, 9, 5, 0, 5, 3, 0, 5, 7, 3, -1, -1, -1, -1, -1}, { 2, 3, 5,10, 1, 2, 0, 9, 5, 7, 3,-1, -1, -1, -1, -1, -1}}, {{8, 0, 2, 8, 2, 5, 8, 5, 7, 10, 5, 2, -1, -1, -1, -1, -1}, {1, 6, 2,10, 5, 7, 8, 0,-1, -1, -1, -1, -1, -1, -1, -1, -1}}, /* 55 */ {{2, 10, 5, 2, 5, 3, 3, 5, 7, -1, -1, -1, -1, -1, -1, -1, -1}, {1, 5, 2,10, 5, 7, 3,-1,-1, -1, -1, -1, -1, -1, -1, -1, -1}}, {{7, 9, 5, 7, 8, 9, 3, 11, 2, -1, -1, -1, -1, -1, -1, -1, -1}, {2, 4, 3, 7, 8, 9, 5, 3,11, 2, -1, -1, -1, -1, -1, -1, -1}}, {{9, 5, 7, 9, 7, 2, 9, 2, 0, 2, 7, 11, -1, -1, -1, -1, -1}, {1, 6, 2, 0, 9, 5, 7,11, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, {{2, 3, 11, 0, 1, 8, 1, 7, 8, 1, 5, 7, -1, -1, -1, -1, -1}, {2, 3, 5, 2, 3,11, 8, 0, 1, 5, 7, -1, -1, -1, -1, -1, -1}}, {{11, 2, 1, 11, 1, 7, 7, 1, 5, -1, -1, -1, -1, -1, -1, -1, -1}, {1, 5,11, 2, 1, 5, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, /* 60 */ {{9, 5, 8, 8, 5, 7, 10, 1, 3, 10, 3, 11, -1, -1, -1, -1, -1}, {2, 4, 4, 3,11, 10, 1, 5, 7, 8, 9, -1, -1, -1, -1, -1, -1}}, {{5, 7, 0, 5, 0, 9, 7, 11, 0, 1, 0, 10, 11, 10, 0, -1, -1}, {1, 7, 5, 7, 11,10, 1, 0, 9, -1, -1, -1, -1, -1, -1, -1, -1}}, {{11, 10, 0, 11, 0, 3, 10, 5, 0, 8, 0, 7, 5, 7, 0, -1, -1}, {1, 7, 11,10,5, 7, 8, 0,3, -1, -1, -1, -1, -1, -1, -1, -1}}, {{11, 10, 5, 7, 11, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, { 1, 4, 5, 7, 11,10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, {{10, 6, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, { 1, 3,10, 6, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, /* 65 */ {{0, 8, 3, 5, 10, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {2, 3, 3, 0, 8, 3, 5, 10, 6, -1, -1, -1, -1, -1, -1, -1, -1}}, {{9, 0, 1, 5, 10, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {2, 3, 3, 9, 0, 1, 5, 10, 6, -1, -1, -1, -1, -1, -1, -1, -1}}, {{1, 8, 3, 1, 9, 8, 5, 10, 6, -1, -1, -1, -1, -1, -1, -1, -1}, {2, 4, 3, 1, 9, 8, 3, 5,10, 6, -1, -1, -1, -1, -1, -1, -1}}, {{1, 6, 5, 2, 6, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {1, 4, 1, 2, 6, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, {{1, 6, 5, 1, 2, 6, 3, 0, 8, -1, -1, -1, -1, -1, -1, -1, -1}, {2, 4, 3, 1, 2, 6, 5, 3, 0, 8, -1, -1, -1, -1, -1, -1, -1}}, /* 70 */ {{9, 6, 5, 9, 0, 6, 0, 2, 6, -1, -1, -1, -1, -1, -1, -1, -1}, {1, 5, 0, 2, 6, 5, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, {{5, 9, 8, 5, 8, 2, 5, 2, 6, 3, 2, 8, -1, -1, -1, -1, -1}, {1, 6, 2, 6, 5, 9, 8, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, {{2, 3, 11, 10, 6, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {2, 3, 3, 2, 3,11, 10, 6, 5, -1, -1, -1, -1, -1, -1, -1, -1}}, {{11, 0, 8, 11, 2, 0, 10, 6, 5, -1, -1, -1, -1, -1, -1, -1, -1}, { 2, 4, 3, 0, 8, 11, 2, 10, 6, 5, -1, -1, -1, -1, -1, -1, -1}}, {{0, 1, 9, 2, 3, 11, 5, 10, 6, -1, -1, -1, -1, -1, -1, -1, -1}, {3, 3, 3, 3, 0, 1, 9, 2, 3, 11, 5, 10, 6, -1, -1, -1, -1}}, /* 75 */ {{5, 10, 6, 1, 9, 2, 9, 11, 2, 9, 8, 11, -1, -1, -1, -1, -1}, {2, 3, 5, 5,10, 6, 2, 1, 9, 8,11, -1, -1, -1, -1, -1, -1}}, {{6, 3, 11, 6, 5, 3, 5, 1, 3, -1, -1, -1, -1, -1, -1, -1, -1}, {1, 5, 5, 1, 3, 11,6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, {{0, 8, 11, 0, 11, 5, 0, 5, 1, 5, 11, 6, -1, -1, -1, -1, -1}, {1, 6, 5, 1, 0, 8,11, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, {{3, 11, 6, 0, 3, 6, 0, 6, 5, 0, 5, 9, -1, -1, -1, -1, -1}, {2, 4, 4, 3, 11, 6, 0, 5, 9, 0, 6, -1, -1, -1, -1}}, {{6, 5, 9, 6, 9, 11, 11, 9, 8, -1, -1, -1, -1, -1, -1, -1, -1}, {1, 5, 6, 5, 9, 8, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, /* 80 */ {{5, 10, 6, 4, 7, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {2, 3, 3, 5,10, 6, 4, 7, 8, -1, -1, -1, -1, -1, -1, -1, -1}}, {{4, 3, 0, 4, 7, 3, 6, 5, 10, -1, -1, -1, -1, -1, -1, -1, -1}, {2, 4, 3, 4, 7, 3, 0, 6, 5, 10, -1, -1, -1, -1, -1, -1, -1}}, {{1, 9, 0, 5, 10, 6, 8, 4, 7, -1, -1, -1, -1, -1, -1, -1, -1}, {3, 3, 3, 3, 1, 9, 0, 5,10, 6, 8, 4, 7, -1, -1, -1, -1}}, {{10, 6, 5, 1, 9, 7, 1, 7, 3, 7, 9, 4, -1, -1, -1, -1, -1}, { 2, 3, 5,10, 6, 5, 9, 4, 7, 3, 1,-1, -1, -1, -1, -1, -1}}, {{6, 1, 2, 6, 5, 1, 4, 7, 8, -1, -1, -1, -1, -1, -1, -1, -1}, {2, 4, 3, 1, 2, 6, 5, 4, 7, 8, -1, -1, -1, -1, -1, -1, -1}}, /* 85 */ {{1, 2, 5, 5, 2, 6, 3, 0, 4, 3, 4, 7, -1, -1, -1, -1, -1}, {2, 4, 4, 2, 6, 5, 1, 3, 0, 4, 7, -1, -1, -1, -1, -1, -1}}, {{8, 4, 7, 9, 0, 5, 0, 6, 5, 0, 2, 6, -1, -1, -1, -1, -1}, {2, 3, 5, 8, 4, 7, 5, 9, 0, 2, 6, -1, -1, -1, -1, -1, -1}}, {{7, 3, 9, 7, 9, 4, 3, 2, 9, 5, 9, 6, 2, 6, 9, -1, -1}, {1, 7, 7, 3, 2, 6, 5, 9, 4,-1, -1, -1, -1, -1, -1, -1, -1}}, {{3, 11, 2, 7, 8, 4, 10, 6, 5, -1, -1, -1, -1, -1, -1, -1, -1}, {3, 3, 3, 3, 3,11, 2, 7, 8, 4, 10, 6, 5, -1, -1, -1, -1}}, {{5, 10, 6, 4, 7, 2, 4, 2, 0, 2, 7, 11, -1, -1, -1, -1, -1}, {2, 3, 5, 5,10, 6, 7,11, 2, 0, 4, -1, -1, -1, -1, -1, -1}}, /* 90 */ {{0, 1, 9, 4, 7, 8, 2, 3, 11, 5, 10, 6, -1, -1, -1, -1, -1}, {4, 3, 3, 3, 3, 0, 1, 9, 4, 7, 8, 2, 3, 11, 5, 10, 6}}, {{9, 2, 1, 9, 11, 2, 9, 4, 11, 7, 11, 4, 5, 10, 6, -1, -1}, {3, 4, 4, 3, 2, 1, 9,11, 4, 7, 11, 9, 5, 10, 6, -1, -1}}, {{8, 4, 7, 3, 11, 5, 3, 5, 1, 5, 11, 6, -1, -1, -1, -1, -1}, {2, 3, 5, 8, 4, 7, 11, 6, 5, 1, 3, -1, -1, -1, -1, -1, -1}}, {{5, 1, 11, 5, 11, 6, 1, 0, 11, 7, 11, 4, 0, 4, 11, -1, -1}, {1, 7, 5, 1, 0, 4, 7,11, 6, -1, -1, -1, -1, -1, -1, -1, -1}}, {{0, 5, 9, 0, 6, 5, 0, 3, 6, 11, 6, 3, 8, 4, 7, -1, -1}, {3, 4, 4, 3, 0, 6, 5, 9, 3, 11, 6, 0, 8, 4, 7, -1, -1}}, /* 95 */ {{6, 5, 9, 6, 9, 11, 4, 7, 9, 7, 11, 9, -1, -1, -1, -1, -1}, {2, 4, 4, 9, 4, 7, 11, 6, 5, 9, 11,-1, -1, -1, -1, -1, -1}}, {{10, 4, 9, 6, 4, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, { 1, 4, 4, 9, 10, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, {{4, 10, 6, 4, 9, 10, 0, 8, 3, -1, -1, -1, -1, -1, -1, -1, -1}, {2, 4, 3, 4, 9,10, 6, 0, 8, 3, -1, -1, -1, -1, -1, -1, -1}}, {{10, 0, 1, 10, 6, 0, 6, 4, 0, -1, -1, -1, -1, -1, -1, -1, -1}, { 1, 5, 6, 4, 0, 1, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, {{8, 3, 1, 8, 1, 6, 8, 6, 4, 6, 1, 10, -1, -1, -1, -1, -1}, {1, 6, 1,10, 6, 4, 8, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, /* 100 */ {{1, 4, 9, 1, 2, 4, 2, 6, 4, -1, -1, -1, -1, -1, -1, -1, -1}, {1, 5, 2, 6, 4, 9, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, {{3, 0, 8, 1, 2, 9, 2, 4, 9, 2, 6, 4, -1, -1, -1, -1, -1}, {2, 3, 5, 3, 0, 8, 9, 1, 2, 6, 4, -1, -1, -1, -1, -1, -1}}, {{0, 2, 4, 4, 2, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {1, 4, 2, 6, 4, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, {{8, 3, 2, 8, 2, 4, 4, 2, 6, -1, -1, -1, -1, -1, -1, -1, -1}, {1, 5, 8, 3, 2, 6, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, {{10, 4, 9, 10, 6, 4, 11, 2, 3, -1, -1, -1, -1, -1, -1, -1, -1}, { 2, 4, 3, 10, 6, 4, 9,11, 2, 3, -1, -1, -1, -1, -1, -1, -1}}, /* 105 */ {{0, 8, 2, 2, 8, 11, 4, 9, 10, 4, 10, 6, -1, -1, -1, -1, -1}, {2, 4, 4, 2, 11, 8, 0, 10, 6, 4, 9, -1, -1, -1, -1, -1, -1}}, {{3, 11, 2, 0, 1, 6, 0, 6, 4, 6, 1, 10, -1, -1, -1, -1, -1}, {2, 3, 5, 3,11, 2, 1, 10,6, 4, 0, -1, -1, -1, -1, -1, -1}}, {{6, 4, 1, 6, 1, 10, 4, 8, 1, 2, 1, 11, 8, 11, 1, -1, -1}, {1, 7, 6, 4, 8,11, 2, 1,10, -1, -1, -1, -1, -1, -1, -1, -1}}, {{9, 6, 4, 9, 3, 6, 9, 1, 3, 11, 6, 3, -1, -1, -1, -1, -1}, {1, 6, 3,11, 6, 4, 9, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, {{8, 11, 1, 8, 1, 0, 11, 6, 1, 9, 1, 4, 6, 4, 1, -1, -1}, {1, 7, 8,11, 6, 4, 9, 1, 0, -1, -1, -1, -1, -1, -1, -1, -1}}, /* 110 */ {{3, 11, 6, 3, 6, 0, 0, 6, 4, -1, -1, -1, -1, -1, -1, -1, -1}, {1, 5, 3,11, 6, 4, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, {{6, 4, 8, 11, 6, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {1, 4, 8, 11, 6, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, {{7, 10, 6, 7, 8, 10, 8, 9, 10, -1, -1, -1, -1, -1, -1, -1, -1}, {1, 5, 8, 9,10, 6, 7,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, {{0, 7, 3, 0, 10, 7, 0, 9, 10, 6, 7, 10, -1, -1, -1, -1, -1}, {1, 6, 0, 9, 10, 6, 7, 3, -1,-1,-1, -1, -1, -1, -1, -1, -1}}, {{10, 6, 7, 1, 10, 7, 1, 7, 8, 1, 8, 0, -1, -1, -1, -1, -1}, { 2, 4, 4, 8, 0, 1, 7, 10, 6, 7, 1,-1, -1, -1, -1, -1, -1}}, /* 115 */ {{10, 6, 7, 10, 7, 1, 1, 7, 3, -1, -1, -1, -1, -1, -1, -1, -1}, { 1, 5, 10, 6, 7, 3, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, {{1, 2, 6, 1, 6, 8, 1, 8, 9, 8, 6, 7, -1, -1, -1, -1, -1}, {1, 6, 1, 2, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, {{2, 6, 9, 2, 9, 1, 6, 7, 9, 0, 9, 3, 7, 3, 9, -1, -1}, {1, 7, 2, 6, 7, 3, 0, 9, 1, -1, -1, -1, -1, -1, -1, -1, -1}}, {{7, 8, 0, 7, 0, 6, 6, 0, 2, -1, -1, -1, -1, -1, -1, -1, -1}, {1, 5, 7, 8, 0, 2, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, {{7, 3, 2, 6, 7, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {1, 4, 7, 3, 2, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, /* 120 */ {{2, 3, 11, 10, 6, 8, 10, 8, 9, 8, 6, 7, -1, -1, -1, -1, -1}, {2, 3, 5, 2, 3,11, 6, 7, 8, 9,10, -1, -1, -1, -1, -1, -1}}, {{2, 0, 7, 2, 7, 11, 0, 9, 7, 6, 7, 10, 9, 10, 7, -1, -1}, {1, 7, 2, 0, 9,10,6, 7, 11, -1, -1, -1, -1, -1, -1, -1, -1}}, {{1, 8, 0, 1, 7, 8, 1, 10, 7, 6, 7, 10, 2, 3, 11, -1, -1}, {3, 4, 4, 3, 8, 0, 1, 7, 10, 6, 7, 1, 11, 2, 3, -1, -1}}, {{11, 2, 1, 11, 1, 7, 10, 6, 1, 6, 7, 1, -1, -1, -1, -1, -1}, { 2, 4, 4, 11, 2, 1,7, 1, 10, 6, 7,-1, -1, -1, -1, -1, -1}}, {{8, 9, 6, 8, 6, 7, 9, 1, 6, 11, 6, 3, 1, 3, 6, -1, -1}, {1, 7, 8, 9, 1, 3, 11, 6, 7,-1, -1, -1, -1, -1, -1, -1, -1}}, /* 125 */ {{0, 9, 1, 11, 6, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {2, 3, 3, 0, 9, 1, 11, 6, 7, -1, -1, -1, -1, -1, -1, -1, -1}}, {{7, 8, 0, 7, 0, 6, 3, 11, 0, 11, 6, 0, -1, -1, -1, -1, -1}, {2, 4, 4, 0, 3,11, 6, 7, 8, 0, 6, -1, -1, -1, -1, -1, -1}}, {{7, 11, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {1, 3, 7, 11, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, {{7, 6, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {1, 3, 7, 6, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, {{3, 0, 8, 11, 7, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {2, 3, 3, 3, 0, 8, 11, 7, 6, -1, -1, -1, -1, -1, -1, -1, -1}}, /* 130 */ {{0, 1, 9, 11, 7, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {2, 3, 3, 0, 1, 9, 11, 7, 6, -1, -1, -1, -1, -1, -1, -1, -1}}, {{8, 1, 9, 8, 3, 1, 11, 7, 6, -1, -1, -1, -1, -1, -1, -1, -1}, {2, 4, 3, 1, 9, 8, 3,11, 7, 6, -1, -1, -1, -1, -1, -1, -1}}, {{10, 1, 2, 6, 11, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, { 2, 3, 3,10, 1, 2, 6, 11, 7, -1, -1, -1, -1, -1, -1, -1, -1}}, {{1, 2, 10, 3, 0, 8, 6, 11, 7, -1, -1, -1, -1, -1, -1, -1, -1}, {3, 3, 3, 3, 1, 2,10, 3, 0, 8, 6, 11, 7, -1, -1, -1, -1}}, {{2, 9, 0, 2, 10, 9, 6, 11, 7, -1, -1, -1, -1, -1, -1, -1, -1}, {2, 4, 3, 2, 10, 9, 0, 6, 11, 7, -1, -1, -1, -1, -1, -1, -1}}, /* 135 */ {{6, 11, 7, 2, 10, 3, 10, 8, 3, 10, 9, 8, -1, -1, -1, -1, -1}, {2, 3, 5, 6, 11, 7, 3, 2,10, 9, 8, -1, -1, -1, -1, -1, -1}}, {{7, 2, 3, 6, 2, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {1, 4, 2, 3, 7, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, {{7, 0, 8, 7, 6, 0, 6, 2, 0, -1, -1, -1, -1, -1, -1, -1, -1}, {1, 5, 6, 2, 0, 8, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, {{2, 7, 6, 2, 3, 7, 0, 1, 9, -1, -1, -1, -1, -1, -1, -1, -1}, {2, 4, 3, 2, 3, 7, 6, 0, 1, 9, -1, -1, -1, -1, -1, -1, -1}}, {{1, 6, 2, 1, 8, 6, 1, 9, 8, 8, 7, 6, -1, -1, -1, -1, -1}, {1, 6, 6, 2, 1, 9, 8, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, /* 140 */ {{10, 7, 6, 10, 1, 7, 1, 3, 7, -1, -1, -1, -1, -1, -1, -1, -1}, { 1, 5, 1, 3, 7, 6,10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, {{10, 7, 6, 1, 7, 10, 1, 8, 7, 1, 0, 8, -1, -1, -1, -1, -1}, { 2, 4, 4, 10, 1, 7, 6, 8, 7, 1, 0,-1, -1, -1, -1, -1, -1}}, {{0, 3, 7, 0, 7, 10, 0, 10, 9, 6, 10, 7, -1, -1, -1, -1, -1}, {1, 6,10, 9, 0, 3, 7, 6,-1, -1, -1, -1, -1, -1, -1, -1, -1}}, {{7, 6, 10, 7, 10, 8, 8, 10, 9, -1, -1, -1, -1, -1, -1, -1, -1}, {1, 5, 7, 6, 10, 9, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, {{6, 8, 4, 11, 8, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {1, 4, 6, 11, 8, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, /* 145 */ {{3, 6, 11, 3, 0, 6, 0, 4, 6, -1, -1, -1, -1, -1, -1, -1, -1}, {1, 5, 0, 4, 6,11, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, {{8, 6, 11, 8, 4, 6, 9, 0, 1, -1, -1, -1, -1, -1, -1, -1, -1}, {2, 4, 3, 6,11, 8, 4, 9, 0, 1, -1, -1, -1, -1, -1, -1, -1}}, {{9, 4, 6, 9, 6, 3, 9, 3, 1, 11, 3, 6, -1, -1, -1, -1, -1}, {1, 6, 6,11, 3, 1, 9, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, {{6, 8, 4, 6, 11, 8, 2, 10, 1, -1, -1, -1, -1, -1, -1, -1, -1}, {2, 4, 3, 6, 11, 8, 4, 2, 10, 1, -1, -1, -1, -1, -1, -1, -1}}, {{1, 2, 10, 3, 0, 11, 0, 6, 11, 0, 4, 6, -1, -1, -1, -1, -1}, {2, 3, 5, 1, 2, 10,11, 3,0,4, 6, -1, -1, -1, -1, -1, -1}}, /* 150 */ {{4, 11, 8, 4, 6, 11, 0, 2, 9, 2, 10, 9, -1, -1, -1, -1, -1}, {2, 4, 4, 4, 6, 11, 8, 2,10, 9, 0, -1, -1, -1, -1, -1, -1}}, {{10, 9, 3, 10, 3, 2, 9, 4, 3, 11, 3, 6, 4, 6, 3, -1, -1}, {1, 7, 10,9, 4, 6, 11, 3, 2, -1, -1, -1, -1, -1, -1, -1, -1}}, {{8, 2, 3, 8, 4, 2, 4, 6, 2, -1, -1, -1, -1, -1, -1, -1, -1}, {1, 5, 4, 6, 2, 3, 8,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, {{0, 4, 2, 4, 6, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {1, 4, 4, 6, 2, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, {{1, 9, 0, 2, 3, 4, 2, 4, 6, 4, 3, 8, -1, -1, -1, -1, -1}, {2, 3, 5, 1, 9, 0, 3, 8, 4, 6, 2, -1, -1, -1, -1, -1, -1}}, /* 155 */ {{1, 9, 4, 1, 4, 2, 2, 4, 6, -1, -1, -1, -1, -1, -1, -1, -1}, {1, 5, 1, 9, 4, 6, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, {{8, 1, 3, 8, 6, 1, 8, 4, 6, 6, 10, 1, -1, -1, -1, -1, -1}, {1, 6, 1, 3, 8, 4, 6,10, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, {{10, 1, 0, 10, 0, 6, 6, 0, 4, -1, -1, -1, -1, -1, -1, -1, -1}, { 1, 5,10, 1,0,4,6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, {{4, 6, 3, 4, 3, 8, 6, 10, 3, 0, 3, 9, 10, 9, 3, -1, -1}, {1, 7, 4, 6, 10, 9, 0,3, 8, -1, -1, -1, -1, -1, -1, -1, -1}}, {{10, 9, 4, 6, 10, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, { 1, 4, 4, 6, 10, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, /* 160 */ {{4, 9, 5, 7, 6, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {2, 3, 3, 4, 9, 5, 7, 6, 11, -1, -1, -1, -1, -1, -1, -1, -1}}, {{0, 8, 3, 4, 9, 5, 11, 7, 6, -1, -1, -1, -1, -1, -1, -1, -1}, {3, 3, 3, 3, 0, 8, 3, 4, 9, 5, 11, 7, 6, -1, -1, -1, -1}}, {{5, 0, 1, 5, 4, 0, 7, 6, 11, -1, -1, -1, -1, -1, -1, -1, -1}, {2, 4, 3, 0, 1, 5, 4, 7, 6, 11, -1, -1, -1, -1, -1, -1, -1}}, {{11, 7, 6, 8, 3, 4, 3, 5, 4, 3, 1, 5, -1, -1, -1, -1, -1}, { 2, 3, 5,11, 7, 6, 4, 8, 3, 1, 5,-1, -1, -1, -1, -1, -1}}, {{9, 5, 4, 10, 1, 2, 7, 6, 11, -1, -1, -1, -1, -1, -1, -1, -1}, {3, 3, 3, 3, 9, 5, 4,10, 1, 2, 7, 6, 11, -1, -1, -1, -1}}, /* 165 */ {{6, 11, 7, 1, 2, 10, 0, 8, 3, 4, 9, 5, -1, -1, -1, -1, -1}, {4, 3, 3, 3, 3, 6,11, 7, 1, 2,10, 0, 8, 3, 4, 9, 5}}, {{7, 6, 11, 5, 4, 10, 4, 2, 10, 4, 0, 2, -1, -1, -1, -1, -1}, {2, 3, 5, 7, 6, 11, 10, 5, 4, 0, 2,-1, -1, -1, -1, -1, -1}}, {{3, 4, 8, 3, 5, 4, 3, 2, 5, 10, 5, 2, 11, 7, 6, -1, -1}, {3, 4, 4, 3, 5, 3, 2,10, 4, 8, 3, 5, 6, 11, 7, 6, -1}}, {{7, 2, 3, 7, 6, 2, 5, 4, 9, -1, -1, -1, -1, -1, -1, -1, -1}, {2, 4, 3, 2, 3, 7, 6, 5, 4, 9, -1, -1, -1, -1, -1, -1, -1}}, {{9, 5, 4, 0, 8, 6, 0, 6, 2, 6, 8, 7, -1, -1, -1, -1, -1}, {2, 3, 5, 9, 5, 4, 8, 7, 6, 2, 0, -1, -1, -1, -1, -1, -1}}, /* 170 */ {{3, 6, 2, 3, 7, 6, 1, 5, 0, 5, 4, 0, -1, -1, -1, -1, -1}, {2, 4, 4, 3, 7, 6, 2, 0, 1, 5, 4, -1, -1, -1, -1, -1, -1}}, {{6, 2, 8, 6, 8, 7, 2, 1, 8, 4, 8, 5, 1, 5, 8, -1, -1}, {1, 7, 6, 2, 1, 5, 4, 8, 7,-1, -1, -1, -1, -1, -1, -1, -1}}, {{9, 5, 4, 10, 1, 6, 1, 7, 6, 1, 3, 7, -1, -1, -1, -1, -1}, {2, 3, 5, 9, 5, 4, 6,10, 1, 3, 7,-1, -1, -1, -1, -1, -1}}, {{1, 6, 10, 1, 7, 6, 1, 0, 7, 8, 7, 0, 9, 5, 4, -1, -1}, {3, 4, 4, 3, 0, 8, 7, 1, 6, 10, 1, 7, 9, 5, 4, -1, -1}}, {{4, 0, 10, 4, 10, 5, 0, 3, 10, 6, 10, 7, 3, 7, 10, -1, -1}, {1, 7, 4, 0, 3, 7, 6, 10, 5, -1, -1, -1, -1, -1, -1, -1, -1}}, /* 175 */ {{7, 6, 10, 7, 10, 8, 5, 4, 10, 4, 8, 10, -1, -1, -1, -1, -1}, {2, 4, 4, 4, 8, 10, 5, 7, 6,10, 8, -1, -1, -1, -1, -1, -1}}, {{6, 9, 5, 6, 11, 9, 11, 8, 9, -1, -1, -1, -1, -1, -1, -1, -1}, {1, 5,11, 8, 9, 5, 6,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, {{3, 6, 11, 0, 6, 3, 0, 5, 6, 0, 9, 5, -1, -1, -1, -1, -1}, {2, 4, 4, 0, 9, 5, 6, 6,11, 3, 0, -1, -1, -1, -1, -1, -1}}, {{0, 11, 8, 0, 5, 11, 0, 1, 5, 5, 6, 11, -1, -1, -1, -1, -1}, {1, 6, 0, 1, 5, 6,11, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, {{6, 11, 3, 6, 3, 5, 5, 3, 1, -1, -1, -1, -1, -1, -1, -1, -1}, {1, 5, 6,11, 3, 1, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, /*180 */ {{1, 2, 10, 9, 5, 11, 9, 11, 8, 11, 5, 6, -1, -1, -1, -1, -1}, {2, 3, 5, 1, 2, 10, 5, 6,11, 8, 9, -1, -1, -1, -1, -1, -1}}, {{0, 11, 3, 0, 6, 11, 0, 9, 6, 5, 6, 9, 1, 2, 10, -1, -1}, {3, 4, 4, 3, 11, 3,0, 6, 9, 5, 6, 0, 2, 10, 1, 2, 10}}, {{11, 8, 5, 11, 5, 6, 8, 0, 5, 10, 5, 2, 0, 2, 5, -1, -1}, { 1, 7,11, 8, 0, 2,10, 5, 6,-1, -1, -1, -1, -1, -1, -1, -1}}, {{6, 11, 3, 6, 3, 5, 2, 10, 3, 10, 5, 3, -1, -1, -1, -1, -1}, {2, 4, 4, 6,11, 3, 5, 10, 5, 3, 2, -1, -1, -1, -1, -1, -1}}, {{5, 8, 9, 5, 2, 8, 5, 6, 2, 3, 8, 2, -1, -1, -1, -1, -1}, {1, 6, 2, 3, 8, 9, 5, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, /* 185 */ {{9, 5, 6, 9, 6, 0, 0, 6, 2, -1, -1, -1, -1, -1, -1, -1, -1}, {1, 5, 9, 5, 6, 2, 0,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, {{1, 5, 8, 1, 8, 0, 5, 6, 8, 3, 8, 2, 6, 2, 8, -1, -1}, {1, 7, 1, 5, 6, 2, 3, 8, 0, -1, -1, -1, -1, -1, -1, -1, -1}}, {{1, 5, 6, 2, 1, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {1, 4, 1, 5, 6, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, {{1, 3, 6, 1, 6, 10, 3, 8, 6, 5, 6, 9, 8, 9, 6, -1, -1}, {1, 7, 1, 3, 8, 9, 5, 6,10, -1, -1, -1, -1, -1, -1, -1, -1}}, {{10, 1, 0, 10, 0, 6, 9, 5, 0, 5, 6, 0, -1, -1, -1, -1, -1}, { 2, 4, 4, 5, 6, 0, 9, 10, 1, 0, 6, -1, -1, -1, -1, -1, -1}}, /* 190 */ {{0, 3, 8, 5, 6, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {2, 3, 3, 0, 3, 8, 5, 6, 10, -1, -1, -1, -1, -1, -1, -1, -1}}, {{10, 5, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, { 1, 3,10, 5, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, {{11, 5, 10, 7, 5, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, { 1, 4, 5,10, 11, 7,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, {{11, 5, 10, 11, 7, 5, 8, 3, 0, -1, -1, -1, -1, -1, -1, -1, -1}, { 2, 4, 3, 5,10,11, 7, 8, 3, 0, -1, -1, -1, -1, -1, -1, -1}}, {{5, 11, 7, 5, 10, 11, 1, 9, 0, -1, -1, -1, -1, -1, -1, -1, -1}, { 2, 4, 3, 5, 10, 11, 7, 1, 9, 0, -1, -1, -1, -1, -1, -1, -1}}, /* 195 */ {{10, 7, 5, 10, 11, 7, 9, 8, 1, 8, 3, 1, -1, -1, -1, -1, -1}, { 2, 4, 4, 10, 11, 7, 5, 1, 9, 8, 3, -1, -1, -1, -1, -1, -1}}, {{11, 1, 2, 11, 7, 1, 7, 5, 1, -1, -1, -1, -1, -1, -1, -1, -1}, { 1, 5, 7, 5, 1, 2,11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, {{0, 8, 3, 1, 2, 7, 1, 7, 5, 7, 2, 11, -1, -1, -1, -1, -1}, {2, 3, 5, 0, 8, 3, 2,11, 7, 5,1, -1, -1, -1, -1, -1, -1}}, {{9, 7, 5, 9, 2, 7, 9, 0, 2, 2, 11, 7, -1, -1, -1, -1, -1}, {1, 6, 2,11, 7, 5, 9, 0,-1, -1, -1, -1, -1, -1, -1, -1, -1}}, {{7, 5, 2, 7, 2, 11, 5, 9, 2, 3, 2, 8, 9, 8, 2, -1, -1}, {1, 7, 7, 5, 9, 8, 3, 2,11,-1, -1, -1, -1, -1, -1, -1, -1}}, /* 200 */ {{2, 5, 10, 2, 3, 5, 3, 7, 5, -1, -1, -1, -1, -1, -1, -1, -1}, {1, 5, 3, 7, 5,10, 2,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, {{8, 2, 0, 8, 5, 2, 8, 7, 5, 10, 2, 5, -1, -1, -1, -1, -1}, {1, 6, 5,10, 2, 0, 8, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, {{9, 0, 1, 5, 10, 3, 5, 3, 7, 3, 10, 2, -1, -1, -1, -1, -1}, {2, 3, 5, 9, 0, 1, 10, 2, 3, 7, 5, -1, -1, -1, -1, -1, -1}}, {{9, 8, 2, 9, 2, 1, 8, 7, 2, 10, 2, 5, 7, 5, 2, -1, -1}, {1, 7, 9, 8, 7, 5,10, 2, 1,-1, -1, -1, -1, -1, -1, -1, -1}}, {{1, 3, 5, 3, 7, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {1, 4, 3, 7, 5, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, /* 205 */ {{0, 8, 7, 0, 7, 1, 1, 7, 5, -1, -1, -1, -1, -1, -1, -1, -1}, {1, 5, 0, 8, 7, 5, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, {{9, 0, 3, 9, 3, 5, 5, 3, 7, -1, -1, -1, -1, -1, -1, -1, -1}, {1, 5, 9, 0, 3, 7, 5,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, {{9, 8, 7, 5, 9, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {1, 4, 7, 5, 9, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, {{5, 8, 4, 5, 10, 8, 10, 11, 8, -1, -1, -1, -1, -1, -1, -1, -1}, {1, 5, 10,11, 8, 4, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, {{5, 0, 4, 5, 11, 0, 5, 10, 11, 11, 3, 0, -1, -1, -1, -1, -1}, {1, 6, 0, 4, 5,10,11, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, /* 210 */ {{0, 1, 9, 8, 4, 10, 8, 10, 11, 10, 4, 5, -1, -1, -1, -1, -1}, {2, 3, 5, 0, 1, 9, 4, 5, 10, 11, 8, -1, -1, -1, -1, -1, -1}}, {{10, 11, 4, 10, 4, 5, 11, 3, 4, 9, 4, 1, 3, 1, 4, -1, -1}, { 1, 7,10, 11, 3, 1, 9,4, 5,-1, -1, -1, -1, -1, -1, -1}}, {{2, 5, 1, 2, 8, 5, 2, 11, 8, 4, 5, 8, -1, -1, -1, -1, -1}, {1, 6, 2,11, 8, 4, 5, 1,-1, -1, -1, -1, -1, -1, -1, -1, -1}}, {{0, 4, 11, 0, 11, 3, 4, 5, 11, 2, 11, 1, 5, 1, 11, -1, -1}, {1, 7, 0, 4, 5, 1, 2, 11, 3,-1, -1, -1, -1, -1, -1, -1, -1}}, {{0, 2, 5, 0, 5, 9, 2, 11, 5, 4, 5, 8, 11, 8, 5, -1, -1}, {1, 7, 0, 2,11, 8, 4, 5, 9, -1, -1, -1, -1, -1, -1, -1, -1}}, /* 215 */ {{9, 4, 5, 2, 11, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {2, 3, 3, 9, 4, 5, 2, 11, 3, -1, -1, -1, -1, -1, -1, -1, -1}}, {{2, 5, 10, 3, 5, 2, 3, 4, 5, 3, 8, 4, -1, -1, -1, -1, -1}, {2, 4, 4, 2, 3, 5, 10, 4, 5, 3, 8,-1, -1, -1, -1, -1, -1}}, {{5, 10, 2, 5, 2, 4, 4, 2, 0, -1, -1, -1, -1, -1, -1, -1, -1}, {1, 5, 5,10, 2, 0, 4,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, {{3, 10, 2, 3, 5, 10, 3, 8, 5, 4, 5, 8, 0, 1, 9, -1, -1}, {3, 4, 4, 3, 3, 5, 10, 2, 8, 4, 5, 3, 0, 1, 9, -1, -1}}, {{5, 10, 2, 5, 2, 4, 1, 9, 2, 9, 4, 2, -1, -1, -1, -1, -1}, {1, 6,10, 2, 1, 9, 4, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, /* 220 */ {{8, 4, 5, 8, 5, 3, 3, 5, 1, -1, -1, -1, -1, -1, -1, -1, -1}, {1, 5, 8, 4, 5, 1, 3,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, {{0, 4, 5, 1, 0, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {1, 4, 0, 4, 5, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, {{8, 4, 5, 8, 5, 3, 9, 0, 5, 0, 3, 5, -1, -1, -1, -1, -1}, {2, 4, 4, 0, 3, 5, 9, 8, 4, 5, 3, -1, -1, -1, -1, -1, -1}}, {{9, 4, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {1, 3, 9, 4, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, {{4, 11, 7, 4, 9, 11, 9, 10, 11, -1, -1, -1, -1, -1, -1, -1, -1}, {1, 5, 9,10, 11, 7, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, /* 225 */ {{0, 8, 3, 4, 9, 7, 9, 11, 7, 9, 10, 11, -1, -1, -1, -1, -1}, {2, 3, 5, 0, 8, 3, 7, 4, 9, 10, 11, -1, -1, -1, -1, -1, -1}}, {{1, 10, 11, 1, 11, 4, 1, 4, 0, 7, 4, 11, -1, -1, -1, -1, -1}, {1, 6, 1, 10,11, 7, 4, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, {{3, 1, 4, 3, 4, 8, 1, 10, 4, 7, 4, 11, 10, 11, 4, -1, -1}, {1, 7, 3, 1,10,11, 7, 4, 8, -1, -1, -1, -1, -1, -1, -1, -1}}, {{4, 11, 7, 9, 11, 4, 9, 2, 11, 9, 1, 2, -1, -1, -1, -1, -1}, {2, 4, 4, 2, 11, 9, 1, 4, 9, 11, 7, -1, -1, -1, -1, -1, -1}}, {{9, 7, 4, 9, 11, 7, 9, 1, 11, 2, 11, 1, 0, 8, 3, -1, -1}, {3, 4, 4, 3, 1, 2, 11, 9, 7, 4, 9,11, 8, 3, 0, 8, 3}}, /* 230 */ {{11, 7, 4, 11, 4, 2, 2, 4, 0, -1, -1, -1, -1, -1, -1, -1, -1}, { 1, 5, 11, 7, 4, 0, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, {{11, 7, 4, 11, 4, 2, 8, 3, 4, 3, 2, 4, -1, -1, -1, -1, -1}, { 2, 4, 4, 11, 7, 4, 2, 3, 2, 4, 8,-1, -1, -1, -1, -1, -1}}, {{2, 9, 10, 2, 7, 9, 2, 3, 7, 7, 4, 9, -1, -1, -1, -1, -1}, {1, 6, 2, 3, 7, 4, 9,10, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, {{9, 10, 7, 9, 7, 4, 10, 2, 7, 8, 7, 0, 2, 0, 7, -1, -1}, {1, 7, 9,10, 2, 0, 8, 7, 4,-1, -1, -1, -1, -1, -1, -1, -1}}, {{3, 7, 10, 3, 10, 2, 7, 4, 10, 1, 10, 0, 4, 0, 10, -1, -1}, {1, 7, 3, 7, 4, 0, 1,10, 2, -1, -1, -1, -1, -1, -1, -1, -1}}, /* 235 */ {{1, 10, 2, 8, 7, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {2, 3, 3, 1,10, 2, 8, 7, 4, -1, -1, -1, -1, -1, -1, -1, -1}}, {{4, 9, 1, 4, 1, 7, 7, 1, 3, -1, -1, -1, -1, -1, -1, -1, -1}, {1, 5, 4, 9, 1, 3, 7,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, {{4, 9, 1, 4, 1, 7, 0, 8, 1, 8, 7, 1, -1, -1, -1, -1, -1}, {2, 4, 4, 8, 7, 1, 0, 4, 9, 1, 7, -1, -1, -1, -1, -1, -1}}, {{4, 0, 3, 7, 4, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {1, 4, 3, 7, 4, 0,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, {{4, 8, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {1, 3, 4, 8, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, /* 240 */ {{9, 10, 8, 10, 11, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {1, 4, 8, 9, 10,11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, {{3, 0, 9, 3, 9, 11, 11, 9, 10, -1, -1, -1, -1, -1, -1, -1, -1}, {1, 5, 3, 0, 9, 10, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, {{0, 1, 10, 0, 10, 8, 8, 10, 11, -1, -1, -1, -1, -1, -1, -1, -1}, {1, 5, 0, 1, 10,11, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, {{3, 1, 10, 11, 3, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {1, 4, 3, 1,10, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, {{1, 2, 11, 1, 11, 9, 9, 11, 8, -1, -1, -1, -1, -1, -1, -1, -1}, {1, 5, 1, 2, 11, 8, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, /* 245 */ {{3, 0, 9, 3, 9, 11, 1, 2, 9, 2, 11, 9, -1, -1, -1, -1, -1}, {2, 4, 4, 2,11, 9, 1, 3, 0, 9, 11, -1, -1, -1, -1, -1,-1}}, {{0, 2, 11, 8, 0, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {1, 4, 0, 2,11, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, {{3, 2, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {1, 3, 3, 2, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, {{2, 3, 8, 2, 8, 10, 10, 8, 9, -1, -1, -1, -1, -1, -1, -1, -1}, {1, 5, 2, 3, 8, 9, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, {{9, 10, 2, 0, 9, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {1, 4, 2, 0, 9,10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, /* 250 */ {{2, 3, 8, 2, 8, 10, 0, 1, 8, 1, 10, 8, -1, -1, -1, -1, -1}, {2, 4, 4, 2, 3, 8, 10, 1, 10, 8, 0, -1, -1, -1, -1, -1, -1}}, {{1, 10, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {1, 3, 1, 10, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, {{1, 3, 8, 9, 1, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {1, 4, 1, 3, 8, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, {{0, 9, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {1, 3, 0, 9, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, {{0, 3, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {1, 3, 0, 3, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, {{-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, { 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}} }; return &triTable[cubetype][u][0]; }; // end of TriTable //----------------------------------------------------------------------------- static const int PolyTable(unsigned int cubetype, int u) { static const int polyTable[8][16] = { {-1}, {-1}, {-1}, {0, 1, 2, -1}, {0, 1, 2, 2, 3, 0, -1}, {0, 1, 2, 0, 2, 4, 4, 2, 3, -1}, {0, 1, 2, 2, 3, 4, 4, 5, 0, 0, 2, 4, -1}, {0, 1, 5, 0, 5, 6, 1, 2, 5, 4, 5, 3, 2, 3, 5, -1} }; return polyTable[cubetype][u]; }; // end of PolyTable //============================================================================= }; //end of class EMCLookUpTable }; // end of namespace tri }; // end of namespace vcg #endif // __VCG_EMC_LOOK_UP_TABLE qutemol/vcg/vcg/complex/trimesh/create/mc_lookup_table.h0000444000175000017500000052065010175475002022066 0ustar mbamba/** * @file LookUpTable.h * @author Thomas Lewiner * @author Math Dept, PUC-Rio * @version 0.2 * @date 12/08/2002 * * @brief LookUpTable for the MarchingCubes 33 Algorithm */ //________________________________________________ #ifndef __VCG_MC_LOOK_UP_TABLE #define __VCG_MC_LOOK_UP_TABLE namespace vcg { namespace tri { class MCLookUpTable { public: //_____________________________________________________________________________ /** * \brief case mapping * For each of the possible vertex states listed in this table there is a * specific triangulation of the edge intersection points. The table lists * all of them in the form of 0-5 edge triples with the list terminated by * the invalid value -1. For example: case[3] list the 2 triangles * formed when cube[0] and cube[1] are inside of the surface, but the rest of * the cube is not. * * Cube description: * 7 ________ 6 _____6__ ________ * /| /| 7/| /| /| /| * / | / | / | /5 | / 6 / | * 4 /_______ / | /__4____ / 10 /_______3/ | * | | |5 | | 11 | | | | | 2 | * | 3|__|_____|2 | |__|__2__| | 4 |__|_____| * | / | / 8 3/ 9 / | / | / * | / | / | / | /1 | / 5 / * |/_______|/ |/___0___|/ |/_1_____|/ * 0 1 0 1 */ //----------------------------------------------------------------------------- static const char Cases(unsigned char cubetype, unsigned char u) { static const char cases[256][2] = { /* 0: */ { 0, -1 }, /* 1: 0, */ { 1, 0 }, /* 2: 1, */ { 1, 1 }, /* 3: 0, 1, */ { 2, 0 }, /* 4: 2, */ { 1, 2 }, /* 5: 0, 2, */ { 3, 0 }, /* 6: 1, 2, */ { 2, 3 }, /* 7: 0, 1, 2, */ { 5, 0 }, /* 8: 3, */ { 1, 3 }, /* 9: 0, 3, */ { 2, 1 }, /* 10: 1, 3, */ { 3, 3 }, /* 11: 0, 1, 3, */ { 5, 1 }, /* 12: 2, 3, */ { 2, 5 }, /* 13: 0, 2, 3, */ { 5, 4 }, /* 14: 1, 2, 3, */ { 5, 9 }, /* 15: 0, 1, 2, 3, */ { 8, 0 }, /* 16: 4, */ { 1, 4 }, /* 17: 0, 4, */ { 2, 2 }, /* 18: 1, 4, */ { 3, 4 }, /* 19: 0, 1, 4, */ { 5, 2 }, /* 20: 2, 4, */ { 4, 2 }, /* 21: 0, 2, 4, */ { 6, 2 }, /* 22: 1, 2, 4, */ { 6, 9 }, /* 23: 0, 1, 2, 4, */ { 11, 0 }, /* 24: 3, 4, */ { 3, 8 }, /* 25: 0, 3, 4, */ { 5, 5 }, /* 26: 1, 3, 4, */ { 7, 3 }, /* 27: 0, 1, 3, 4, */ { 9, 1 }, /* 28: 2, 3, 4, */ { 6, 16 }, /* 29: 0, 2, 3, 4, */ { 14, 3 }, /* 30: 1, 2, 3, 4, */ { 12, 12 }, /* 31: 0, 1, 2, 3, 4, */ { 5, 24 }, /* 32: 5, */ { 1, 5 }, /* 33: 0, 5, */ { 3, 1 }, /* 34: 1, 5, */ { 2, 4 }, /* 35: 0, 1, 5, */ { 5, 3 }, /* 36: 2, 5, */ { 3, 6 }, /* 37: 0, 2, 5, */ { 7, 0 }, /* 38: 1, 2, 5, */ { 5, 10 }, /* 39: 0, 1, 2, 5, */ { 9, 0 }, /* 40: 3, 5, */ { 4, 3 }, /* 41: 0, 3, 5, */ { 6, 4 }, /* 42: 1, 3, 5, */ { 6, 11 }, /* 43: 0, 1, 3, 5, */ { 14, 1 }, /* 44: 2, 3, 5, */ { 6, 17 }, /* 45: 0, 2, 3, 5, */ { 12, 4 }, /* 46: 1, 2, 3, 5, */ { 11, 6 }, /* 47: 0, 1, 2, 3, 5, */ { 5, 25 }, /* 48: 4, 5, */ { 2, 8 }, /* 49: 0, 4, 5, */ { 5, 7 }, /* 50: 1, 4, 5, */ { 5, 12 }, /* 51: 0, 1, 4, 5, */ { 8, 1 }, /* 52: 2, 4, 5, */ { 6, 18 }, /* 53: 0, 2, 4, 5, */ { 12, 5 }, /* 54: 1, 2, 4, 5, */ { 14, 7 }, /* 55: 0, 1, 2, 4, 5, */ { 5, 28 }, /* 56: 3, 4, 5, */ { 6, 21 }, /* 57: 0, 3, 4, 5, */ { 11, 4 }, /* 58: 1, 3, 4, 5, */ { 12, 15 }, /* 59: 0, 1, 3, 4, 5, */ { 5, 30 }, /* 60: 2, 3, 4, 5, */ { 10, 5 }, /* 61: 0, 2, 3, 4, 5, */ { 6, 32 }, /* 62: 1, 2, 3, 4, 5, */ { 6, 39 }, /* 63: 0, 1, 2, 3, 4, 5, */ { 2, 12 }, /* 64: 6, */ { 1, 6 }, /* 65: 0, 6, */ { 4, 0 }, /* 66: 1, 6, */ { 3, 5 }, /* 67: 0, 1, 6, */ { 6, 0 }, /* 68: 2, 6, */ { 2, 6 }, /* 69: 0, 2, 6, */ { 6, 3 }, /* 70: 1, 2, 6, */ { 5, 11 }, /* 71: 0, 1, 2, 6, */ { 14, 0 }, /* 72: 3, 6, */ { 3, 9 }, /* 73: 0, 3, 6, */ { 6, 5 }, /* 74: 1, 3, 6, */ { 7, 4 }, /* 75: 0, 1, 3, 6, */ { 12, 1 }, /* 76: 2, 3, 6, */ { 5, 14 }, /* 77: 0, 2, 3, 6, */ { 11, 3 }, /* 78: 1, 2, 3, 6, */ { 9, 4 }, /* 79: 0, 1, 2, 3, 6, */ { 5, 26 }, /* 80: 4, 6, */ { 3, 10 }, /* 81: 0, 4, 6, */ { 6, 6 }, /* 82: 1, 4, 6, */ { 7, 5 }, /* 83: 0, 1, 4, 6, */ { 12, 2 }, /* 84: 2, 4, 6, */ { 6, 19 }, /* 85: 0, 2, 4, 6, */ { 10, 1 }, /* 86: 1, 2, 4, 6, */ { 12, 13 }, /* 87: 0, 1, 2, 4, 6, */ { 6, 24 }, /* 88: 3, 4, 6, */ { 7, 7 }, /* 89: 0, 3, 4, 6, */ { 12, 9 }, /* 90: 1, 3, 4, 6, */ { 13, 1 }, /* 91: 0, 1, 3, 4, 6, */ { 7, 9 }, /* 92: 2, 3, 4, 6, */ { 12, 20 }, /* 93: 0, 2, 3, 4, 6, */ { 6, 33 }, /* 94: 1, 2, 3, 4, 6, */ { 7, 13 }, /* 95: 0, 1, 2, 3, 4, 6, */ { 3, 12 }, /* 96: 5, 6, */ { 2, 10 }, /* 97: 0, 5, 6, */ { 6, 7 }, /* 98: 1, 5, 6, */ { 5, 13 }, /* 99: 0, 1, 5, 6, */ { 11, 2 }, /* 100: 2, 5, 6, */ { 5, 16 }, /* 101: 0, 2, 5, 6, */ { 12, 7 }, /* 102: 1, 2, 5, 6, */ { 8, 3 }, /* 103: 0, 1, 2, 5, 6, */ { 5, 29 }, /* 104: 3, 5, 6, */ { 6, 22 }, /* 105: 0, 3, 5, 6, */ { 10, 2 }, /* 106: 1, 3, 5, 6, */ { 12, 17 }, /* 107: 0, 1, 3, 5, 6, */ { 6, 27 }, /* 108: 2, 3, 5, 6, */ { 14, 9 }, /* 109: 0, 2, 3, 5, 6, */ { 6, 34 }, /* 110: 1, 2, 3, 5, 6, */ { 5, 39 }, /* 111: 0, 1, 2, 3, 5, 6, */ { 2, 14 }, /* 112: 4, 5, 6, */ { 5, 20 }, /* 113: 0, 4, 5, 6, */ { 14, 5 }, /* 114: 1, 4, 5, 6, */ { 9, 5 }, /* 115: 0, 1, 4, 5, 6, */ { 5, 32 }, /* 116: 2, 4, 5, 6, */ { 11, 10 }, /* 117: 0, 2, 4, 5, 6, */ { 6, 35 }, /* 118: 1, 2, 4, 5, 6, */ { 5, 41 }, /* 119: 0, 1, 2, 4, 5, 6, */ { 2, 16 }, /* 120: 3, 4, 5, 6, */ { 12, 23 }, /* 121: 0, 3, 4, 5, 6, */ { 6, 37 }, /* 122: 1, 3, 4, 5, 6, */ { 7, 14 }, /* 123: 0, 1, 3, 4, 5, 6, */ { 3, 16 }, /* 124: 2, 3, 4, 5, 6, */ { 6, 46 }, /* 125: 0, 2, 3, 4, 5, 6, */ { 4, 6 }, /* 126: 1, 2, 3, 4, 5, 6, */ { 3, 21 }, /* 127: 0, 1, 2, 3, 4, 5, 6, */ { 1, 8 }, /* 128: 7, */ { 1, 7 }, /* 129: 0, 7, */ { 3, 2 }, /* 130: 1, 7, */ { 4, 1 }, /* 131: 0, 1, 7, */ { 6, 1 }, /* 132: 2, 7, */ { 3, 7 }, /* 133: 0, 2, 7, */ { 7, 1 }, /* 134: 1, 2, 7, */ { 6, 10 }, /* 135: 0, 1, 2, 7, */ { 12, 0 }, /* 136: 3, 7, */ { 2, 7 }, /* 137: 0, 3, 7, */ { 5, 6 }, /* 138: 1, 3, 7, */ { 6, 12 }, /* 139: 0, 1, 3, 7, */ { 11, 1 }, /* 140: 2, 3, 7, */ { 5, 15 }, /* 141: 0, 2, 3, 7, */ { 9, 2 }, /* 142: 1, 2, 3, 7, */ { 14, 6 }, /* 143: 0, 1, 2, 3, 7, */ { 5, 27 }, /* 144: 4, 7, */ { 2, 9 }, /* 145: 0, 4, 7, */ { 5, 8 }, /* 146: 1, 4, 7, */ { 6, 13 }, /* 147: 0, 1, 4, 7, */ { 14, 2 }, /* 148: 2, 4, 7, */ { 6, 20 }, /* 149: 0, 2, 4, 7, */ { 12, 6 }, /* 150: 1, 2, 4, 7, */ { 10, 3 }, /* 151: 0, 1, 2, 4, 7, */ { 6, 25 }, /* 152: 3, 4, 7, */ { 5, 18 }, /* 153: 0, 3, 4, 7, */ { 8, 2 }, /* 154: 1, 3, 4, 7, */ { 12, 16 }, /* 155: 0, 1, 3, 4, 7, */ { 5, 31 }, /* 156: 2, 3, 4, 7, */ { 11, 9 }, /* 157: 0, 2, 3, 4, 7, */ { 5, 34 }, /* 158: 1, 2, 3, 4, 7, */ { 6, 40 }, /* 159: 0, 1, 2, 3, 4, 7, */ { 2, 13 }, /* 160: 5, 7, */ { 3, 11 }, /* 161: 0, 5, 7, */ { 7, 2 }, /* 162: 1, 5, 7, */ { 6, 14 }, /* 163: 0, 1, 5, 7, */ { 12, 3 }, /* 164: 2, 5, 7, */ { 7, 6 }, /* 165: 0, 2, 5, 7, */ { 13, 0 }, /* 166: 1, 2, 5, 7, */ { 12, 14 }, /* 167: 0, 1, 2, 5, 7, */ { 7, 8 }, /* 168: 3, 5, 7, */ { 6, 23 }, /* 169: 0, 3, 5, 7, */ { 12, 10 }, /* 170: 1, 3, 5, 7, */ { 10, 4 }, /* 171: 0, 1, 3, 5, 7, */ { 6, 28 }, /* 172: 2, 3, 5, 7, */ { 12, 21 }, /* 173: 0, 2, 3, 5, 7, */ { 7, 10 }, /* 174: 1, 2, 3, 5, 7, */ { 6, 41 }, /* 175: 0, 1, 2, 3, 5, 7, */ { 3, 13 }, /* 176: 4, 5, 7, */ { 5, 21 }, /* 177: 0, 4, 5, 7, */ { 9, 3 }, /* 178: 1, 4, 5, 7, */ { 11, 8 }, /* 179: 0, 1, 4, 5, 7, */ { 5, 33 }, /* 180: 2, 4, 5, 7, */ { 12, 22 }, /* 181: 0, 2, 4, 5, 7, */ { 7, 11 }, /* 182: 1, 2, 4, 5, 7, */ { 6, 42 }, /* 183: 0, 1, 2, 4, 5, 7, */ { 3, 14 }, /* 184: 3, 4, 5, 7, */ { 14, 11 }, /* 185: 0, 3, 4, 5, 7, */ { 5, 36 }, /* 186: 1, 3, 4, 5, 7, */ { 6, 44 }, /* 187: 0, 1, 3, 4, 5, 7, */ { 2, 17 }, /* 188: 2, 3, 4, 5, 7, */ { 6, 47 }, /* 189: 0, 2, 3, 4, 5, 7, */ { 3, 18 }, /* 190: 1, 2, 3, 4, 5, 7, */ { 4, 7 }, /* 191: 0, 1, 2, 3, 4, 5, 7, */ { 1, 9 }, /* 192: 6, 7, */ { 2, 11 }, /* 193: 0, 6, 7, */ { 6, 8 }, /* 194: 1, 6, 7, */ { 6, 15 }, /* 195: 0, 1, 6, 7, */ { 10, 0 }, /* 196: 2, 6, 7, */ { 5, 17 }, /* 197: 0, 2, 6, 7, */ { 12, 8 }, /* 198: 1, 2, 6, 7, */ { 11, 7 }, /* 199: 0, 1, 2, 6, 7, */ { 6, 26 }, /* 200: 3, 6, 7, */ { 5, 19 }, /* 201: 0, 3, 6, 7, */ { 14, 4 }, /* 202: 1, 3, 6, 7, */ { 12, 18 }, /* 203: 0, 1, 3, 6, 7, */ { 6, 29 }, /* 204: 2, 3, 6, 7, */ { 8, 4 }, /* 205: 0, 2, 3, 6, 7, */ { 5, 35 }, /* 206: 1, 2, 3, 6, 7, */ { 5, 40 }, /* 207: 0, 1, 2, 3, 6, 7, */ { 2, 15 }, /* 208: 4, 6, 7, */ { 5, 22 }, /* 209: 0, 4, 6, 7, */ { 11, 5 }, /* 210: 1, 4, 6, 7, */ { 12, 19 }, /* 211: 0, 1, 4, 6, 7, */ { 6, 30 }, /* 212: 2, 4, 6, 7, */ { 14, 10 }, /* 213: 0, 2, 4, 6, 7, */ { 6, 36 }, /* 214: 1, 2, 4, 6, 7, */ { 6, 43 }, /* 215: 0, 1, 2, 4, 6, 7, */ { 4, 4 }, /* 216: 3, 4, 6, 7, */ { 9, 7 }, /* 217: 0, 3, 4, 6, 7, */ { 5, 37 }, /* 218: 1, 3, 4, 6, 7, */ { 7, 15 }, /* 219: 0, 1, 3, 4, 6, 7, */ { 3, 17 }, /* 220: 2, 3, 4, 6, 7, */ { 5, 44 }, /* 221: 0, 2, 3, 4, 6, 7, */ { 2, 19 }, /* 222: 1, 2, 3, 4, 6, 7, */ { 3, 22 }, /* 223: 0, 1, 2, 3, 4, 6, 7, */ { 1, 10 }, /* 224: 5, 6, 7, */ { 5, 23 }, /* 225: 0, 5, 6, 7, */ { 12, 11 }, /* 226: 1, 5, 6, 7, */ { 14, 8 }, /* 227: 0, 1, 5, 6, 7, */ { 6, 31 }, /* 228: 2, 5, 6, 7, */ { 9, 6 }, /* 229: 0, 2, 5, 6, 7, */ { 7, 12 }, /* 230: 1, 2, 5, 6, 7, */ { 5, 42 }, /* 231: 0, 1, 2, 5, 6, 7, */ { 3, 15 }, /* 232: 3, 5, 6, 7, */ { 11, 11 }, /* 233: 0, 3, 5, 6, 7, */ { 6, 38 }, /* 234: 1, 3, 5, 6, 7, */ { 6, 45 }, /* 235: 0, 1, 3, 5, 6, 7, */ { 4, 5 }, /* 236: 2, 3, 5, 6, 7, */ { 5, 45 }, /* 237: 0, 2, 3, 5, 6, 7, */ { 3, 19 }, /* 238: 1, 2, 3, 5, 6, 7, */ { 2, 21 }, /* 239: 0, 1, 2, 3, 5, 6, 7, */ { 1, 11 }, /* 240: 4, 5, 6, 7, */ { 8, 5 }, /* 241: 0, 4, 5, 6, 7, */ { 5, 38 }, /* 242: 1, 4, 5, 6, 7, */ { 5, 43 }, /* 243: 0, 1, 4, 5, 6, 7, */ { 2, 18 }, /* 244: 2, 4, 5, 6, 7, */ { 5, 46 }, /* 245: 0, 2, 4, 5, 6, 7, */ { 3, 20 }, /* 246: 1, 2, 4, 5, 6, 7, */ { 2, 22 }, /* 247: 0, 1, 2, 4, 5, 6, 7, */ { 1, 12 }, /* 248: 3, 4, 5, 6, 7, */ { 5, 47 }, /* 249: 0, 3, 4, 5, 6, 7, */ { 2, 20 }, /* 250: 1, 3, 4, 5, 6, 7, */ { 3, 23 }, /* 251: 0, 1, 3, 4, 5, 6, 7, */ { 1, 13 }, /* 252: 2, 3, 4, 5, 6, 7, */ { 2, 23 }, /* 253: 0, 2, 3, 4, 5, 6, 7, */ { 1, 14 }, /* 254: 1, 2, 3, 4, 5, 6, 7, */ { 1, 15 }, /* 255: 0, 1, 2, 3, 4, 5, 6, 7, */ { 0, -1 } }; return cases[cubetype][u]; }; // end of Cases //_____________________________________________________________________________ //_____________________________________________________________________________ /** * \brief tiling table for case 1 * For each of the case above, the specific triangulation of the edge * intersection points is given. * When a case is ambiguous, there is an auxiliary table that contains * the face number to test and the tiling table contains the specific * triangulations depending on the results * A minus sign means to invert the result of the test. */ //----------------------------------------------------------------------------- static const char* Tiling1(unsigned char config) { static const char tiling1[16][3] = { /* 1: 0, */ { 0, 8, 3 }, /* 2: 1, */ { 0, 1, 9 }, /* 4: 2, */ { 1, 2, 10 }, /* 8: 3, */ { 3, 11, 2 }, /* 16: 4, */ { 4, 7, 8 }, /* 32: 5, */ { 9, 5, 4 }, /* 64: 6, */ { 10, 6, 5 }, /* 128: 7, */ { 7, 6, 11 }, /* 127: 0, 1, 2, 3, 4, 5, 6, */ { 7, 11, 6 }, /* 191: 0, 1, 2, 3, 4, 5, 7, */ { 10, 5, 6 }, /* 223: 0, 1, 2, 3, 4, 6, 7, */ { 9, 4, 5 }, /* 239: 0, 1, 2, 3, 5, 6, 7, */ { 4, 8, 7 }, /* 247: 0, 1, 2, 4, 5, 6, 7, */ { 3, 2, 11 }, /* 251: 0, 1, 3, 4, 5, 6, 7, */ { 1, 10, 2 }, /* 253: 0, 2, 3, 4, 5, 6, 7, */ { 0, 9, 1 }, /* 254: 1, 2, 3, 4, 5, 6, 7, */ { 0, 3, 8 } }; return &tiling1[config][0]; }; // end of Tiling1 //_____________________________________________________________________________ //_____________________________________________________________________________ /** * \brief tiling table for case 2 * For each of the case above, the specific triangulation of the edge * intersection points is given. * When a case is ambiguous, there is an auxiliary table that contains * the face number to test and the tiling table contains the specific * triangulations depending on the results * A minus sign means to invert the result of the test. */ //----------------------------------------------------------------------------- static const char* Tiling2(unsigned char config) { static const char tiling2[24][6] = { /* 3: 0, 1, */ { 1, 8, 3, 9, 8, 1 }, /* 9: 0, 3, */ { 0, 11, 2, 8, 11, 0 }, /* 17: 0, 4, */ { 4, 3, 0, 7, 3, 4 }, /* 6: 1, 2, */ { 9, 2, 10, 0, 2, 9 }, /* 34: 1, 5, */ { 0, 5, 4, 1, 5, 0 }, /* 12: 2, 3, */ { 3, 10, 1, 11, 10, 3 }, /* 68: 2, 6, */ { 1, 6, 5, 2, 6, 1 }, /* 136: 3, 7, */ { 7, 2, 3, 6, 2, 7 }, /* 48: 4, 5, */ { 9, 7, 8, 5, 7, 9 }, /* 144: 4, 7, */ { 6, 8, 4, 11, 8, 6 }, /* 96: 5, 6, */ { 10, 4, 9, 6, 4, 10 }, /* 192: 6, 7, */ { 11, 5, 10, 7, 5, 11 }, /* 63: 0, 1, 2, 3, 4, 5, */ { 11, 10, 5, 7, 11, 5 }, /* 159: 0, 1, 2, 3, 4, 7, */ { 10, 9, 4, 6, 10, 4 }, /* 111: 0, 1, 2, 3, 5, 6, */ { 6, 4, 8, 11, 6, 8 }, /* 207: 0, 1, 2, 3, 6, 7, */ { 9, 8, 7, 5, 9, 7 }, /* 119: 0, 1, 2, 4, 5, 6, */ { 7, 3, 2, 6, 7, 2 }, /* 187: 0, 1, 3, 4, 5, 7, */ { 1, 5, 6, 2, 1, 6 }, /* 243: 0, 1, 4, 5, 6, 7, */ { 3, 1, 10, 11, 3, 10 }, /* 221: 0, 2, 3, 4, 6, 7, */ { 0, 4, 5, 1, 0, 5 }, /* 249: 0, 3, 4, 5, 6, 7, */ { 9, 10, 2, 0, 9, 2 }, /* 238: 1, 2, 3, 5, 6, 7, */ { 4, 0, 3, 7, 4, 3 }, /* 246: 1, 2, 4, 5, 6, 7, */ { 0, 2, 11, 8, 0, 11 }, /* 252: 2, 3, 4, 5, 6, 7, */ { 1, 3, 8, 9, 1, 8 } }; return &tiling2[config][0]; }; // end of Tiling2 //_____________________________________________________________________________ //_____________________________________________________________________________ /** * \brief test table for case 3 * One face to test * When the test on the specified face is positive : 4 first triangles * When the test on the specified face is negative : 2 last triangles * * For each of the case above, the specific triangulation of the edge * intersection points is given. * When a case is ambiguous, there is an auxiliary table that contains * the face number to test and the tiling table contains the specific * triangulations depending on the results * A minus sign means to invert the result of the test. */ //----------------------------------------------------------------------------- static const char Test3(unsigned char config) { static const char test3[24] = { /* 5: 0, 2, */ 5, /* 33: 0, 5, */ 1, /* 129: 0, 7, */ 4, /* 10: 1, 3, */ 5, /* 18: 1, 4, */ 1, /* 66: 1, 6, */ 2, /* 36: 2, 5, */ 2, /* 132: 2, 7, */ 3, /* 24: 3, 4, */ 4, /* 72: 3, 6, */ 3, /* 80: 4, 6, */ 6, /* 160: 5, 7, */ 6, /* 95: 0, 1, 2, 3, 4, 6, */ -6, /* 175: 0, 1, 2, 3, 5, 7, */ -6, /* 183: 0, 1, 2, 4, 5, 7, */ -3, /* 231: 0, 1, 2, 5, 6, 7, */ -4, /* 123: 0, 1, 3, 4, 5, 6, */ -3, /* 219: 0, 1, 3, 4, 6, 7, */ -2, /* 189: 0, 2, 3, 4, 5, 7, */ -2, /* 237: 0, 2, 3, 5, 6, 7, */ -1, /* 245: 0, 2, 4, 5, 6, 7, */ -5, /* 126: 1, 2, 3, 4, 5, 6, */ -4, /* 222: 1, 2, 3, 4, 6, 7, */ -1, /* 250: 1, 3, 4, 5, 6, 7, */ -5 }; return test3[config]; }; // end of Test3 //_____________________________________________________________________________ /** * \brief tiling table for case 3.1 * For each of the case above, the specific triangulation of the edge * intersection points is given. * When a case is ambiguous, there is an auxiliary table that contains * the face number to test and the tiling table contains the specific * triangulations depending on the results * A minus sign means to invert the result of the test. */ //----------------------------------------------------------------------------- static const char* Tiling3_1(unsigned char config) { static const char tiling3_1[24][6] = { /* 5: 0, 2, */ { 0, 8, 3, 1, 2, 10 }, /* 33: 0, 5, */ { 9, 5, 4, 0, 8, 3 }, /* 129: 0, 7, */ { 3, 0, 8, 11, 7, 6 }, /* 10: 1, 3, */ { 1, 9, 0, 2, 3, 11 }, /* 18: 1, 4, */ { 0, 1, 9, 8, 4, 7 }, /* 66: 1, 6, */ { 9, 0, 1, 5, 10, 6 }, /* 36: 2, 5, */ { 1, 2, 10, 9, 5, 4 }, /* 132: 2, 7, */ { 10, 1, 2, 6, 11, 7 }, /* 24: 3, 4, */ { 8, 4, 7, 3, 11, 2 }, /* 72: 3, 6, */ { 2, 3, 11, 10, 6, 5 }, /* 80: 4, 6, */ { 5, 10, 6, 4, 7, 8 }, /* 160: 5, 7, */ { 4, 9, 5, 7, 6, 11 }, /* 95: 0, 1, 2, 3, 4, 6, */ { 5, 9, 4, 11, 6, 7 }, /* 175: 0, 1, 2, 3, 5, 7, */ { 6, 10, 5, 8, 7, 4 }, /* 183: 0, 1, 2, 4, 5, 7, */ { 11, 3, 2, 5, 6, 10 }, /* 231: 0, 1, 2, 5, 6, 7, */ { 7, 4, 8, 2, 11, 3 }, /* 123: 0, 1, 3, 4, 5, 6, */ { 2, 1, 10, 7, 11, 6 }, /* 219: 0, 1, 3, 4, 6, 7, */ { 10, 2, 1, 4, 5, 9 }, /* 189: 0, 2, 3, 4, 5, 7, */ { 1, 0, 9, 6, 10, 5 }, /* 237: 0, 2, 3, 5, 6, 7, */ { 9, 1, 0, 7, 4, 8 }, /* 245: 0, 2, 4, 5, 6, 7, */ { 0, 9, 1, 11, 3, 2 }, /* 126: 1, 2, 3, 4, 5, 6, */ { 8, 0, 3, 6, 7, 11 }, /* 222: 1, 2, 3, 4, 6, 7, */ { 4, 5, 9, 3, 8, 0 }, /* 250: 1, 3, 4, 5, 6, 7, */ { 3, 8, 0, 10, 2, 1 } }; return &tiling3_1[config][0]; }; // end of Tiling3_1 //_____________________________________________________________________________ /** * \brief tiling table for case 3.2 * For each of the case above, the specific triangulation of the edge * intersection points is given. * When a case is ambiguous, there is an auxiliary table that contains * the face number to test and the tiling table contains the specific * triangulations depending on the results * A minus sign means to invert the result of the test. */ //----------------------------------------------------------------------------- static const char* Tiling3_2(unsigned char config) { static const char tiling3_2[24][12] = { /* 5: 0, 2, */ { 10, 3, 2, 10, 8, 3, 10, 1, 0, 8, 10, 0 }, /* 33: 0, 5, */ { 3, 4, 8, 3, 5, 4, 3, 0, 9, 5, 3, 9 }, /* 129: 0, 7, */ { 6, 8, 7, 6, 0, 8, 6, 11, 3, 0, 6, 3 }, /* 10: 1, 3, */ { 11, 0, 3, 11, 9, 0, 11, 2, 1, 9, 11, 1 }, /* 18: 1, 4, */ { 7, 9, 4, 7, 1, 9, 7, 8, 0, 1, 7, 0 }, /* 66: 1, 6, */ { 6, 1, 10, 6, 0, 1, 9, 0, 6, 9, 6, 5 }, /* 36: 2, 5, */ { 4, 10, 5, 4, 2, 10, 4, 9, 1, 2, 4, 1 }, /* 132: 2, 7, */ { 7, 2, 11, 7, 1, 2, 7, 6, 10, 1, 7, 10 }, /* 24: 3, 4, */ { 2, 7, 11, 2, 4, 7, 2, 3, 8, 4, 2, 8 }, /* 72: 3, 6, */ { 5, 11, 6, 5, 3, 11, 5, 10, 2, 3, 5, 2 }, /* 80: 4, 6, */ { 8, 6, 7, 8, 10, 6, 8, 4, 5, 10, 8, 5 }, /* 160: 5, 7, */ { 11, 5, 6, 11, 9, 5, 11, 7, 4, 9, 11, 4 }, /* 95: 0, 1, 2, 3, 4, 6, */ { 6, 5, 11, 5, 9, 11, 4, 7, 11, 4, 11, 9 }, /* 175: 0, 1, 2, 3, 5, 7, */ { 7, 6, 8, 6, 10, 8, 5, 4, 8, 5, 8, 10 }, /* 183: 0, 1, 2, 4, 5, 7, */ { 6, 11, 5, 11, 3, 5, 2, 10, 5, 2, 5, 3 }, /* 231: 0, 1, 2, 5, 6, 7, */ { 11, 7, 2, 7, 4, 2, 8, 3, 2, 8, 2, 4 }, /* 123: 0, 1, 3, 4, 5, 6, */ { 11, 2, 7, 2, 1, 7, 10, 6, 7, 10, 7, 1 }, /* 219: 0, 1, 3, 4, 6, 7, */ { 5, 10, 4, 10, 2, 4, 1, 9, 4, 1, 4, 2 }, /* 189: 0, 2, 3, 4, 5, 7, */ { 10, 1, 6, 1, 0, 6, 6, 0, 9, 5, 6, 9 }, /* 237: 0, 2, 3, 5, 6, 7, */ { 4, 9, 7, 9, 1, 7, 0, 8, 7, 0, 7, 1 }, /* 245: 0, 2, 4, 5, 6, 7, */ { 3, 0, 11, 0, 9, 11, 1, 2, 11, 1, 11, 9 }, /* 126: 1, 2, 3, 4, 5, 6, */ { 7, 8, 6, 8, 0, 6, 3, 11, 6, 3, 6, 0 }, /* 222: 1, 2, 3, 4, 6, 7, */ { 8, 4, 3, 4, 5, 3, 9, 0, 3, 9, 3, 5 }, /* 250: 1, 3, 4, 5, 6, 7, */ { 2, 3, 10, 3, 8, 10, 0, 1, 10, 0, 10, 8 } }; return &tiling3_2[config][0]; }; // end of Tiling3_2 //_____________________________________________________________________________ //_____________________________________________________________________________ /** * \brief test table for case 4 * Interior to test * When the test on the interior is negative : 2 first triangles * When the test on the interior is positive : 6 last triangles * * For each of the case above, the specific triangulation of the edge * intersection points is given. * When a case is ambiguous, there is an auxiliary table that contains * the face number to test and the tiling table contains the specific * triangulations depending on the results * A minus sign means to invert the result of the test. */ //----------------------------------------------------------------------------- static const char Test4(unsigned char config) { static const char test4[8] = { /* 65: 0, 6, */ 7, /* 130: 1, 7, */ 7, /* 20: 2, 4, */ 7, /* 40: 3, 5, */ 7, /* 215: 0, 1, 2, 4, 6, 7, */ -7, /* 235: 0, 1, 3, 5, 6, 7, */ -7, /* 125: 0, 2, 3, 4, 5, 6, */ -7, /* 190: 1, 2, 3, 4, 5, 7, */ -7 }; return test4[config]; }; // end of Test4 //_____________________________________________________________________________ /** * \brief tiling table for case 4.1 * For each of the case above, the specific triangulation of the edge * intersection points is given. * When a case is ambiguous, there is an auxiliary table that contains * the face number to test and the tiling table contains the specific * triangulations depending on the results * A minus sign means to invert the result of the test. */ //----------------------------------------------------------------------------- static const char* Tiling4_1(unsigned char config) { static const char tiling4_1[8][6] = { /* 65: 0, 6, */ { 0, 8, 3, 5, 10, 6 }, /* 130: 1, 7, */ { 0, 1, 9, 11, 7, 6 }, /* 20: 2, 4, */ { 1, 2, 10, 8, 4, 7 }, /* 40: 3, 5, */ { 9, 5, 4, 2, 3, 11 }, /* 215: 0, 1, 2, 4, 6, 7, */ { 4, 5, 9, 11, 3, 2 }, /* 235: 0, 1, 3, 5, 6, 7, */ { 10, 2, 1, 7, 4, 8 }, /* 125: 0, 2, 3, 4, 5, 6, */ { 9, 1, 0, 6, 7, 11 }, /* 190: 1, 2, 3, 4, 5, 7, */ { 3, 8, 0, 6, 10, 5 } }; return &tiling4_1[config][0]; }; // end of Tiling4_1 //_____________________________________________________________________________ /** * \brief tiling table for case 4.2 * For each of the case above, the specific triangulation of the edge * intersection points is given. * When a case is ambiguous, there is an auxiliary table that contains * the face number to test and the tiling table contains the specific * triangulations depending on the results * A minus sign means to invert the result of the test. */ //----------------------------------------------------------------------------- static const char* Tiling4_2(unsigned char config) { static const char tiling4_2[8][18] = { /* 65: 0, 6, */ { 8, 5, 0, 5, 8, 6, 3, 6, 8, 6, 3, 10, 0, 10, 3, 10, 0, 5 }, /* 130: 1, 7, */ { 9, 6, 1, 6, 9, 7, 0, 7, 9, 7, 0, 11, 1, 11, 0, 11, 1, 6 }, /* 20: 2, 4, */ { 10, 7, 2, 7, 10, 4, 1, 4, 10, 4, 1, 8, 2, 8, 1, 8, 2, 7 }, /* 40: 3, 5, */ { 11, 4, 3, 4, 11, 5, 2, 5, 11, 5, 2, 9, 3, 9, 2, 9, 3, 4 }, /* 215: 0, 1, 2, 4, 6, 7, */ { 3, 4, 11, 5, 11, 4, 11, 5, 2, 9, 2, 5, 2, 9, 3, 4, 3, 9 }, /* 235: 0, 1, 3, 5, 6, 7, */ { 2, 7, 10, 4, 10, 7, 10, 4, 1, 8, 1, 4, 1, 8, 2, 7, 2, 8 }, /* 125: 0, 2, 3, 4, 5, 6, */ { 1, 6, 9, 7, 9, 6, 9, 7, 0, 11, 0, 7, 0, 11, 1, 6, 1, 11 }, /* 190: 1, 2, 3, 4, 5, 7, */ { 0, 5, 8, 6, 8, 5, 8, 6, 3, 10, 3, 6, 3, 10, 0, 5, 0, 10 } }; return &tiling4_2[config][0]; }; // end of Tiling4_2 //_____________________________________________________________________________ //_____________________________________________________________________________ /** * \brief tiling table for case 5 * For each of the case above, the specific triangulation of the edge * intersection points is given. * When a case is ambiguous, there is an auxiliary table that contains * the face number to test and the tiling table contains the specific * triangulations depending on the results * A minus sign means to invert the result of the test. */ //----------------------------------------------------------------------------- static const char* Tiling5(unsigned char config) { static const char tiling5[48][9] = { /* 7: 0, 1, 2, */ { 2, 8, 3, 2, 10, 8, 10, 9, 8 }, /* 11: 0, 1, 3, */ { 1, 11, 2, 1, 9, 11, 9, 8, 11 }, /* 19: 0, 1, 4, */ { 4, 1, 9, 4, 7, 1, 7, 3, 1 }, /* 35: 0, 1, 5, */ { 8, 5, 4, 8, 3, 5, 3, 1, 5 }, /* 13: 0, 2, 3, */ { 0, 10, 1, 0, 8, 10, 8, 11, 10 }, /* 25: 0, 3, 4, */ { 11, 4, 7, 11, 2, 4, 2, 0, 4 }, /* 137: 0, 3, 7, */ { 7, 0, 8, 7, 6, 0, 6, 2, 0 }, /* 49: 0, 4, 5, */ { 9, 3, 0, 9, 5, 3, 5, 7, 3 }, /* 145: 0, 4, 7, */ { 3, 6, 11, 3, 0, 6, 0, 4, 6 }, /* 14: 1, 2, 3, */ { 3, 9, 0, 3, 11, 9, 11, 10, 9 }, /* 38: 1, 2, 5, */ { 5, 2, 10, 5, 4, 2, 4, 0, 2 }, /* 70: 1, 2, 6, */ { 9, 6, 5, 9, 0, 6, 0, 2, 6 }, /* 50: 1, 4, 5, */ { 0, 7, 8, 0, 1, 7, 1, 5, 7 }, /* 98: 1, 5, 6, */ { 10, 0, 1, 10, 6, 0, 6, 4, 0 }, /* 76: 2, 3, 6, */ { 6, 3, 11, 6, 5, 3, 5, 1, 3 }, /* 140: 2, 3, 7, */ { 10, 7, 6, 10, 1, 7, 1, 3, 7 }, /* 100: 2, 5, 6, */ { 1, 4, 9, 1, 2, 4, 2, 6, 4 }, /* 196: 2, 6, 7, */ { 11, 1, 2, 11, 7, 1, 7, 5, 1 }, /* 152: 3, 4, 7, */ { 8, 2, 3, 8, 4, 2, 4, 6, 2 }, /* 200: 3, 6, 7, */ { 2, 5, 10, 2, 3, 5, 3, 7, 5 }, /* 112: 4, 5, 6, */ { 7, 10, 6, 7, 8, 10, 8, 9, 10 }, /* 176: 4, 5, 7, */ { 6, 9, 5, 6, 11, 9, 11, 8, 9 }, /* 208: 4, 6, 7, */ { 5, 8, 4, 5, 10, 8, 10, 11, 8 }, /* 224: 5, 6, 7, */ { 4, 11, 7, 4, 9, 11, 9, 10, 11 }, /* 31: 0, 1, 2, 3, 4, */ { 4, 7, 11, 4, 11, 9, 9, 11, 10 }, /* 47: 0, 1, 2, 3, 5, */ { 5, 4, 8, 5, 8, 10, 10, 8, 11 }, /* 79: 0, 1, 2, 3, 6, */ { 6, 5, 9, 6, 9, 11, 11, 9, 8 }, /* 143: 0, 1, 2, 3, 7, */ { 7, 6, 10, 7, 10, 8, 8, 10, 9 }, /* 55: 0, 1, 2, 4, 5, */ { 2, 10, 5, 2, 5, 3, 3, 5, 7 }, /* 103: 0, 1, 2, 5, 6, */ { 8, 3, 2, 8, 2, 4, 4, 2, 6 }, /* 59: 0, 1, 3, 4, 5, */ { 11, 2, 1, 11, 1, 7, 7, 1, 5 }, /* 155: 0, 1, 3, 4, 7, */ { 1, 9, 4, 1, 4, 2, 2, 4, 6 }, /* 115: 0, 1, 4, 5, 6, */ { 10, 6, 7, 10, 7, 1, 1, 7, 3 }, /* 179: 0, 1, 4, 5, 7, */ { 6, 11, 3, 6, 3, 5, 5, 3, 1 }, /* 157: 0, 2, 3, 4, 7, */ { 10, 1, 0, 10, 0, 6, 6, 0, 4 }, /* 205: 0, 2, 3, 6, 7, */ { 0, 8, 7, 0, 7, 1, 1, 7, 5 }, /* 185: 0, 3, 4, 5, 7, */ { 9, 5, 6, 9, 6, 0, 0, 6, 2 }, /* 217: 0, 3, 4, 6, 7, */ { 5, 10, 2, 5, 2, 4, 4, 2, 0 }, /* 241: 0, 4, 5, 6, 7, */ { 3, 0, 9, 3, 9, 11, 11, 9, 10 }, /* 110: 1, 2, 3, 5, 6, */ { 3, 11, 6, 3, 6, 0, 0, 6, 4 }, /* 206: 1, 2, 3, 6, 7, */ { 9, 0, 3, 9, 3, 5, 5, 3, 7 }, /* 118: 1, 2, 4, 5, 6, */ { 7, 8, 0, 7, 0, 6, 6, 0, 2 }, /* 230: 1, 2, 5, 6, 7, */ { 11, 7, 4, 11, 4, 2, 2, 4, 0 }, /* 242: 1, 4, 5, 6, 7, */ { 0, 1, 10, 0, 10, 8, 8, 10, 11 }, /* 220: 2, 3, 4, 6, 7, */ { 8, 4, 5, 8, 5, 3, 3, 5, 1 }, /* 236: 2, 3, 5, 6, 7, */ { 4, 9, 1, 4, 1, 7, 7, 1, 3 }, /* 244: 2, 4, 5, 6, 7, */ { 1, 2, 11, 1, 11, 9, 9, 11, 8 }, /* 248: 3, 4, 5, 6, 7, */ { 2, 3, 8, 2, 8, 10, 10, 8, 9 } }; return &tiling5[config][0]; }; // end of Tiling5 //_____________________________________________________________________________ //_____________________________________________________________________________ /** * \brief test table for case 6 * 1 face to test + eventually the interior * When the test on the specified face is positive : 5 first triangles * When the test on the specified face is negative : * - if the test on the interior is negative : 3 middle triangles * - if the test on the interior is positive : 8 last triangles * The support edge for the interior test is marked as the 3rd column. * * For each of the case above, the specific triangulation of the edge * intersection points is given. * When a case is ambiguous, there is an auxiliary table that contains * the face number to test and the tiling table contains the specific * triangulations depending on the results * A minus sign means to invert the result of the test. */ //----------------------------------------------------------------------------- static const char Test6(unsigned char config, int u) { static const char test6[48][3] = { /* 67: 0, 1, 6, */ { 2, 7, 10 }, /* 131: 0, 1, 7, */ { 4, 7, 11 }, /* 21: 0, 2, 4, */ { 5, 7, 1 }, /* 69: 0, 2, 6, */ { 5, 7, 3 }, /* 41: 0, 3, 5, */ { 1, 7, 9 }, /* 73: 0, 3, 6, */ { 3, 7, 10 }, /* 81: 0, 4, 6, */ { 6, 7, 5 }, /* 97: 0, 5, 6, */ { 1, 7, 8 }, /* 193: 0, 6, 7, */ { 4, 7, 8 }, /* 22: 1, 2, 4, */ { 1, 7, 8 }, /* 134: 1, 2, 7, */ { 3, 7, 11 }, /* 42: 1, 3, 5, */ { 5, 7, 2 }, /* 138: 1, 3, 7, */ { 5, 7, 0 }, /* 146: 1, 4, 7, */ { 1, 7, 9 }, /* 162: 1, 5, 7, */ { 6, 7, 6 }, /* 194: 1, 6, 7, */ { 2, 7, 9 }, /* 28: 2, 3, 4, */ { 4, 7, 8 }, /* 44: 2, 3, 5, */ { 2, 7, 9 }, /* 52: 2, 4, 5, */ { 2, 7, 10 }, /* 84: 2, 4, 6, */ { 6, 7, 7 }, /* 148: 2, 4, 7, */ { 3, 7, 10 }, /* 56: 3, 4, 5, */ { 4, 7, 11 }, /* 104: 3, 5, 6, */ { 3, 7, 11 }, /* 168: 3, 5, 7, */ { 6, 7, 4 }, /* 87: 0, 1, 2, 4, 6, */ { -6, -7, 4 }, /* 151: 0, 1, 2, 4, 7, */ { -3, -7, 11 }, /* 199: 0, 1, 2, 6, 7, */ { -4, -7, 11 }, /* 107: 0, 1, 3, 5, 6, */ { -3, -7, 10 }, /* 171: 0, 1, 3, 5, 7, */ { -6, -7, 7 }, /* 203: 0, 1, 3, 6, 7, */ { -2, -7, 10 }, /* 211: 0, 1, 4, 6, 7, */ { -2, -7, 9 }, /* 227: 0, 1, 5, 6, 7, */ { -4, -7, 8 }, /* 61: 0, 2, 3, 4, 5, */ { -2, -7, 9 }, /* 93: 0, 2, 3, 4, 6, */ { -6, -7, 6 }, /* 109: 0, 2, 3, 5, 6, */ { -1, -7, 9 }, /* 117: 0, 2, 4, 5, 6, */ { -5, -7, 0 }, /* 213: 0, 2, 4, 6, 7, */ { -5, -7, 2 }, /* 121: 0, 3, 4, 5, 6, */ { -3, -7, 11 }, /* 233: 0, 3, 5, 6, 7, */ { -1, -7, 8 }, /* 62: 1, 2, 3, 4, 5, */ { -4, -7, 8 }, /* 158: 1, 2, 3, 4, 7, */ { -1, -7, 8 }, /* 174: 1, 2, 3, 5, 7, */ { -6, -7, 5 }, /* 182: 1, 2, 4, 5, 7, */ { -3, -7, 10 }, /* 214: 1, 2, 4, 6, 7, */ { -1, -7, 9 }, /* 186: 1, 3, 4, 5, 7, */ { -5, -7, 3 }, /* 234: 1, 3, 5, 6, 7, */ { -5, -7, 1 }, /* 124: 2, 3, 4, 5, 6, */ { -4, -7, 11 }, /* 188: 2, 3, 4, 5, 7, */ { -2, -7, 10 } }; return test6[config][u]; }; // end of Test6 //_____________________________________________________________________________ /** * \brief tiling table for case 6.1.1 * For each of the case above, the specific triangulation of the edge * intersection points is given. * When a case is ambiguous, there is an auxiliary table that contains * the face number to test and the tiling table contains the specific * triangulations depending on the results * A minus sign means to invert the result of the test. */ //----------------------------------------------------------------------------- static const char* Tiling6_1_1(unsigned char config) { static const char tiling6_1_1[48][9] = { /* 67: 0, 1, 6, */ { 6, 5, 10, 3, 1, 8, 9, 8, 1 }, /* 131: 0, 1, 7, */ { 11, 7, 6, 9, 3, 1, 3, 9, 8 }, /* 21: 0, 2, 4, */ { 1, 2, 10, 7, 0, 4, 0, 7, 3 }, /* 69: 0, 2, 6, */ { 3, 0, 8, 5, 2, 6, 2, 5, 1 }, /* 41: 0, 3, 5, */ { 5, 4, 9, 2, 0, 11, 8, 11, 0 }, /* 73: 0, 3, 6, */ { 10, 6, 5, 8, 2, 0, 2, 8, 11 }, /* 81: 0, 4, 6, */ { 10, 6, 5, 0, 4, 3, 7, 3, 4 }, /* 97: 0, 5, 6, */ { 3, 0, 8, 6, 4, 10, 9, 10, 4 }, /* 193: 0, 6, 7, */ { 8, 3, 0, 10, 7, 5, 7, 10, 11 }, /* 22: 1, 2, 4, */ { 8, 4, 7, 10, 0, 2, 0, 10, 9 }, /* 134: 1, 2, 7, */ { 7, 6, 11, 0, 2, 9, 10, 9, 2 }, /* 42: 1, 3, 5, */ { 2, 3, 11, 4, 1, 5, 1, 4, 0 }, /* 138: 1, 3, 7, */ { 0, 1, 9, 6, 3, 7, 3, 6, 2 }, /* 146: 1, 4, 7, */ { 9, 0, 1, 11, 4, 6, 4, 11, 8 }, /* 162: 1, 5, 7, */ { 11, 7, 6, 1, 5, 0, 4, 0, 5 }, /* 194: 1, 6, 7, */ { 0, 1, 9, 7, 5, 11, 10, 11, 5 }, /* 28: 2, 3, 4, */ { 4, 7, 8, 1, 3, 10, 11, 10, 3 }, /* 44: 2, 3, 5, */ { 9, 5, 4, 11, 1, 3, 1, 11, 10 }, /* 52: 2, 4, 5, */ { 10, 1, 2, 8, 5, 7, 5, 8, 9 }, /* 84: 2, 4, 6, */ { 8, 4, 7, 2, 6, 1, 5, 1, 6 }, /* 148: 2, 4, 7, */ { 1, 2, 10, 4, 6, 8, 11, 8, 6 }, /* 56: 3, 4, 5, */ { 2, 3, 11, 5, 7, 9, 8, 9, 7 }, /* 104: 3, 5, 6, */ { 11, 2, 3, 9, 6, 4, 6, 9, 10 }, /* 168: 3, 5, 7, */ { 9, 5, 4, 3, 7, 2, 6, 2, 7 }, /* 87: 0, 1, 2, 4, 6, */ { 4, 5, 9, 2, 7, 3, 7, 2, 6 }, /* 151: 0, 1, 2, 4, 7, */ { 3, 2, 11, 4, 6, 9, 10, 9, 6 }, /* 199: 0, 1, 2, 6, 7, */ { 11, 3, 2, 9, 7, 5, 7, 9, 8 }, /* 107: 0, 1, 3, 5, 6, */ { 10, 2, 1, 8, 6, 4, 6, 8, 11 }, /* 171: 0, 1, 3, 5, 7, */ { 7, 4, 8, 1, 6, 2, 6, 1, 5 }, /* 203: 0, 1, 3, 6, 7, */ { 2, 1, 10, 7, 5, 8, 9, 8, 5 }, /* 211: 0, 1, 4, 6, 7, */ { 4, 5, 9, 3, 1, 11, 10, 11, 1 }, /* 227: 0, 1, 5, 6, 7, */ { 8, 7, 4, 10, 3, 1, 3, 10, 11 }, /* 61: 0, 2, 3, 4, 5, */ { 9, 1, 0, 11, 5, 7, 5, 11, 10 }, /* 93: 0, 2, 3, 4, 6, */ { 6, 7, 11, 0, 5, 1, 5, 0, 4 }, /* 109: 0, 2, 3, 5, 6, */ { 1, 0, 9, 6, 4, 11, 8, 11, 4 }, /* 117: 0, 2, 4, 5, 6, */ { 9, 1, 0, 7, 3, 6, 2, 6, 3 }, /* 213: 0, 2, 4, 6, 7, */ { 11, 3, 2, 5, 1, 4, 0, 4, 1 }, /* 121: 0, 3, 4, 5, 6, */ { 11, 6, 7, 9, 2, 0, 2, 9, 10 }, /* 233: 0, 3, 5, 6, 7, */ { 7, 4, 8, 2, 0, 10, 9, 10, 0 }, /* 62: 1, 2, 3, 4, 5, */ { 0, 3, 8, 5, 7, 10, 11, 10, 7 }, /* 158: 1, 2, 3, 4, 7, */ { 8, 0, 3, 10, 4, 6, 4, 10, 9 }, /* 174: 1, 2, 3, 5, 7, */ { 5, 6, 10, 3, 4, 0, 4, 3, 7 }, /* 182: 1, 2, 4, 5, 7, */ { 5, 6, 10, 0, 2, 8, 11, 8, 2 }, /* 214: 1, 2, 4, 6, 7, */ { 9, 4, 5, 11, 0, 2, 0, 11, 8 }, /* 186: 1, 3, 4, 5, 7, */ { 8, 0, 3, 6, 2, 5, 1, 5, 2 }, /* 234: 1, 3, 5, 6, 7, */ { 10, 2, 1, 4, 0, 7, 3, 7, 0 }, /* 124: 2, 3, 4, 5, 6, */ { 6, 7, 11, 1, 3, 9, 8, 9, 3 }, /* 188: 2, 3, 4, 5, 7, */ { 10, 5, 6, 8, 1, 3, 1, 8, 9 } }; return &tiling6_1_1[config][0]; }; // end of Tiling6_1_1 //_____________________________________________________________________________ /** * \brief tiling table for case 6.1.2 * For each of the case above, the specific triangulation of the edge * intersection points is given. * When a case is ambiguous, there is an auxiliary table that contains * the face number to test and the tiling table contains the specific * triangulations depending on the results * A minus sign means to invert the result of the test. */ //----------------------------------------------------------------------------- static const char* Tiling6_1_2(unsigned char config) { static const char tiling6_1_2[48][21] = { /* 67: 0, 1, 6, */ { 1, 10, 3, 6, 3, 10, 3, 6, 8, 5, 8, 6, 8, 5, 9, 1, 9, 5, 10, 1, 5 }, /* 131: 0, 1, 7, */ { 1, 11, 3, 11, 1, 6, 9, 6, 1, 6, 9, 7, 8, 7, 9, 7, 8, 3, 7, 3, 11 }, /* 21: 0, 2, 4, */ { 4, 1, 0, 1, 4, 10, 7, 10, 4, 10, 7, 2, 3, 2, 7, 2, 3, 0, 2, 0, 1 }, /* 69: 0, 2, 6, */ { 6, 3, 2, 3, 6, 8, 5, 8, 6, 8, 5, 0, 1, 0, 5, 0, 1, 2, 0, 2, 3 }, /* 41: 0, 3, 5, */ { 0, 9, 2, 5, 2, 9, 2, 5, 11, 4, 11, 5, 11, 4, 8, 0, 8, 4, 9, 0, 4 }, /* 73: 0, 3, 6, */ { 0, 10, 2, 10, 0, 5, 8, 5, 0, 5, 8, 6, 11, 6, 8, 6, 11, 2, 6, 2, 10 }, /* 81: 0, 4, 6, */ { 4, 5, 0, 10, 0, 5, 0, 10, 3, 6, 3, 10, 3, 6, 7, 4, 7, 6, 5, 4, 6 }, /* 97: 0, 5, 6, */ { 4, 8, 6, 3, 6, 8, 6, 3, 10, 0, 10, 3, 10, 0, 9, 4, 9, 0, 8, 4, 0 }, /* 193: 0, 6, 7, */ { 5, 8, 7, 8, 5, 0, 10, 0, 5, 0, 10, 3, 11, 3, 10, 3, 11, 7, 3, 7, 8 }, /* 22: 1, 2, 4, */ { 2, 8, 0, 8, 2, 7, 10, 7, 2, 7, 10, 4, 9, 4, 10, 4, 9, 0, 4, 0, 8 }, /* 134: 1, 2, 7, */ { 2, 11, 0, 7, 0, 11, 0, 7, 9, 6, 9, 7, 9, 6, 10, 2, 10, 6, 11, 2, 6 }, /* 42: 1, 3, 5, */ { 5, 2, 1, 2, 5, 11, 4, 11, 5, 11, 4, 3, 0, 3, 4, 3, 0, 1, 3, 1, 2 }, /* 138: 1, 3, 7, */ { 7, 0, 3, 0, 7, 9, 6, 9, 7, 9, 6, 1, 2, 1, 6, 1, 2, 3, 1, 3, 0 }, /* 146: 1, 4, 7, */ { 6, 9, 4, 9, 6, 1, 11, 1, 6, 1, 11, 0, 8, 0, 11, 0, 8, 4, 0, 4, 9 }, /* 162: 1, 5, 7, */ { 5, 6, 1, 11, 1, 6, 1, 11, 0, 7, 0, 11, 0, 7, 4, 5, 4, 7, 6, 5, 7 }, /* 194: 1, 6, 7, */ { 5, 9, 7, 0, 7, 9, 7, 0, 11, 1, 11, 0, 11, 1, 10, 5, 10, 1, 9, 5, 1 }, /* 28: 2, 3, 4, */ { 3, 8, 1, 4, 1, 8, 1, 4, 10, 7, 10, 4, 10, 7, 11, 3, 11, 7, 8, 3, 7 }, /* 44: 2, 3, 5, */ { 3, 9, 1, 9, 3, 4, 11, 4, 3, 4, 11, 5, 10, 5, 11, 5, 10, 1, 5, 1, 9 }, /* 52: 2, 4, 5, */ { 7, 10, 5, 10, 7, 2, 8, 2, 7, 2, 8, 1, 9, 1, 8, 1, 9, 5, 1, 5, 10 }, /* 84: 2, 4, 6, */ { 6, 7, 2, 8, 2, 7, 2, 8, 1, 4, 1, 8, 1, 4, 5, 6, 5, 4, 7, 6, 4 }, /* 148: 2, 4, 7, */ { 6, 10, 4, 1, 4, 10, 4, 1, 8, 2, 8, 1, 8, 2, 11, 6, 11, 2, 10, 6, 2 }, /* 56: 3, 4, 5, */ { 7, 11, 5, 2, 5, 11, 5, 2, 9, 3, 9, 2, 9, 3, 8, 7, 8, 3, 11, 7, 3 }, /* 104: 3, 5, 6, */ { 4, 11, 6, 11, 4, 3, 9, 3, 4, 3, 9, 2, 10, 2, 9, 2, 10, 6, 2, 6, 11 }, /* 168: 3, 5, 7, */ { 7, 4, 3, 9, 3, 4, 3, 9, 2, 5, 2, 9, 2, 5, 6, 7, 6, 5, 4, 7, 5 }, /* 87: 0, 1, 2, 4, 6, */ { 3, 4, 7, 4, 3, 9, 2, 9, 3, 9, 2, 5, 6, 5, 2, 5, 6, 7, 5, 7, 4 }, /* 151: 0, 1, 2, 4, 7, */ { 6, 11, 4, 3, 4, 11, 4, 3, 9, 2, 9, 3, 9, 2, 10, 6, 10, 2, 11, 6, 2 }, /* 199: 0, 1, 2, 6, 7, */ { 5, 11, 7, 11, 5, 2, 9, 2, 5, 2, 9, 3, 8, 3, 9, 3, 8, 7, 3, 7, 11 }, /* 107: 0, 1, 3, 5, 6, */ { 4, 10, 6, 10, 4, 1, 8, 1, 4, 1, 8, 2, 11, 2, 8, 2, 11, 6, 2, 6, 10 }, /* 171: 0, 1, 3, 5, 7, */ { 2, 7, 6, 7, 2, 8, 1, 8, 2, 8, 1, 4, 5, 4, 1, 4, 5, 6, 4, 6, 7 }, /* 203: 0, 1, 3, 6, 7, */ { 5, 10, 7, 2, 7, 10, 7, 2, 8, 1, 8, 2, 8, 1, 9, 5, 9, 1, 10, 5, 1 }, /* 211: 0, 1, 4, 6, 7, */ { 1, 9, 3, 4, 3, 9, 3, 4, 11, 5, 11, 4, 11, 5, 10, 1, 10, 5, 9, 1, 5 }, /* 227: 0, 1, 5, 6, 7, */ { 1, 8, 3, 8, 1, 4, 10, 4, 1, 4, 10, 7, 11, 7, 10, 7, 11, 3, 7, 3, 8 }, /* 61: 0, 2, 3, 4, 5, */ { 7, 9, 5, 9, 7, 0, 11, 0, 7, 0, 11, 1, 10, 1, 11, 1, 10, 5, 1, 5, 9 }, /* 93: 0, 2, 3, 4, 6, */ { 1, 6, 5, 6, 1, 11, 0, 11, 1, 11, 0, 7, 4, 7, 0, 7, 4, 5, 7, 5, 6 }, /* 109: 0, 2, 3, 5, 6, */ { 4, 9, 6, 1, 6, 9, 6, 1, 11, 0, 11, 1, 11, 0, 8, 4, 8, 0, 9, 4, 0 }, /* 117: 0, 2, 4, 5, 6, */ { 3, 0, 7, 9, 7, 0, 7, 9, 6, 1, 6, 9, 6, 1, 2, 3, 2, 1, 0, 3, 1 }, /* 213: 0, 2, 4, 6, 7, */ { 1, 2, 5, 11, 5, 2, 5, 11, 4, 3, 4, 11, 4, 3, 0, 1, 0, 3, 2, 1, 3 }, /* 121: 0, 3, 4, 5, 6, */ { 0, 11, 2, 11, 0, 7, 9, 7, 0, 7, 9, 6, 10, 6, 9, 6, 10, 2, 6, 2, 11 }, /* 233: 0, 3, 5, 6, 7, */ { 0, 8, 2, 7, 2, 8, 2, 7, 10, 4, 10, 7, 10, 4, 9, 0, 9, 4, 8, 0, 4 }, /* 62: 1, 2, 3, 4, 5, */ { 7, 8, 5, 0, 5, 8, 5, 0, 10, 3, 10, 0, 10, 3, 11, 7, 11, 3, 8, 7, 3 }, /* 158: 1, 2, 3, 4, 7, */ { 6, 8, 4, 8, 6, 3, 10, 3, 6, 3, 10, 0, 9, 0, 10, 0, 9, 4, 0, 4, 8 }, /* 174: 1, 2, 3, 5, 7, */ { 0, 5, 4, 5, 0, 10, 3, 10, 0, 10, 3, 6, 7, 6, 3, 6, 7, 4, 6, 4, 5 }, /* 182: 1, 2, 4, 5, 7, */ { 2, 10, 0, 5, 0, 10, 0, 5, 8, 6, 8, 5, 8, 6, 11, 2, 11, 6, 10, 2, 6 }, /* 214: 1, 2, 4, 6, 7, */ { 2, 9, 0, 9, 2, 5, 11, 5, 2, 5, 11, 4, 8, 4, 11, 4, 8, 0, 4, 0, 9 }, /* 186: 1, 3, 4, 5, 7, */ { 2, 3, 6, 8, 6, 3, 6, 8, 5, 0, 5, 8, 5, 0, 1, 2, 1, 0, 3, 2, 0 }, /* 234: 1, 3, 5, 6, 7, */ { 0, 1, 4, 10, 4, 1, 4, 10, 7, 2, 7, 10, 7, 2, 3, 0, 3, 2, 1, 0, 2 }, /* 124: 2, 3, 4, 5, 6, */ { 3, 11, 1, 6, 1, 11, 1, 6, 9, 7, 9, 6, 9, 7, 8, 3, 8, 7, 11, 3, 7 }, /* 188: 2, 3, 4, 5, 7, */ { 3, 10, 1, 10, 3, 6, 8, 6, 3, 6, 8, 5, 9, 5, 8, 5, 9, 1, 5, 1, 10 } }; return &tiling6_1_2[config][0]; }; // end of Tiling6_1_2 //_____________________________________________________________________________ /** * \brief tiling table for case 6.2 * For each of the case above, the specific triangulation of the edge * intersection points is given. * When a case is ambiguous, there is an auxiliary table that contains * the face number to test and the tiling table contains the specific * triangulations depending on the results * A minus sign means to invert the result of the test. */ //----------------------------------------------------------------------------- static const char* Tiling6_2(unsigned char config) { static const char tiling6_2[48][15] = { /* 67: 0, 1, 6, */ { 1, 10, 3, 6, 3, 10, 3, 6, 8, 5, 8, 6, 8, 5, 9 }, /* 131: 0, 1, 7, */ { 1, 11, 3, 11, 1, 6, 9, 6, 1, 6, 9, 7, 8, 7, 9 }, /* 21: 0, 2, 4, */ { 4, 1, 0, 1, 4, 10, 7, 10, 4, 10, 7, 2, 3, 2, 7 }, /* 69: 0, 2, 6, */ { 6, 3, 2, 3, 6, 8, 5, 8, 6, 8, 5, 0, 1, 0, 5 }, /* 41: 0, 3, 5, */ { 0, 9, 2, 5, 2, 9, 2, 5, 11, 4, 11, 5, 11, 4, 8 }, /* 73: 0, 3, 6, */ { 0, 10, 2, 10, 0, 5, 8, 5, 0, 5, 8, 6, 11, 6, 8 }, /* 81: 0, 4, 6, */ { 4, 5, 0, 10, 0, 5, 0, 10, 3, 6, 3, 10, 3, 6, 7 }, /* 97: 0, 5, 6, */ { 4, 8, 6, 3, 6, 8, 6, 3, 10, 0, 10, 3, 10, 0, 9 }, /* 193: 0, 6, 7, */ { 5, 8, 7, 8, 5, 0, 10, 0, 5, 0, 10, 3, 11, 3, 10 }, /* 22: 1, 2, 4, */ { 2, 8, 0, 8, 2, 7, 10, 7, 2, 7, 10, 4, 9, 4, 10 }, /* 134: 1, 2, 7, */ { 2, 11, 0, 7, 0, 11, 0, 7, 9, 6, 9, 7, 9, 6, 10 }, /* 42: 1, 3, 5, */ { 5, 2, 1, 2, 5, 11, 4, 11, 5, 11, 4, 3, 0, 3, 4 }, /* 138: 1, 3, 7, */ { 7, 0, 3, 0, 7, 9, 6, 9, 7, 9, 6, 1, 2, 1, 6 }, /* 146: 1, 4, 7, */ { 6, 9, 4, 9, 6, 1, 11, 1, 6, 1, 11, 0, 8, 0, 11 }, /* 162: 1, 5, 7, */ { 5, 6, 1, 11, 1, 6, 1, 11, 0, 7, 0, 11, 0, 7, 4 }, /* 194: 1, 6, 7, */ { 5, 9, 7, 0, 7, 9, 7, 0, 11, 1, 11, 0, 11, 1, 10 }, /* 28: 2, 3, 4, */ { 3, 8, 1, 4, 1, 8, 1, 4, 10, 7, 10, 4, 10, 7, 11 }, /* 44: 2, 3, 5, */ { 3, 9, 1, 9, 3, 4, 11, 4, 3, 4, 11, 5, 10, 5, 11 }, /* 52: 2, 4, 5, */ { 7, 10, 5, 10, 7, 2, 8, 2, 7, 2, 8, 1, 9, 1, 8 }, /* 84: 2, 4, 6, */ { 6, 7, 2, 8, 2, 7, 2, 8, 1, 4, 1, 8, 1, 4, 5 }, /* 148: 2, 4, 7, */ { 6, 10, 4, 1, 4, 10, 4, 1, 8, 2, 8, 1, 8, 2, 11 }, /* 56: 3, 4, 5, */ { 7, 11, 5, 2, 5, 11, 5, 2, 9, 3, 9, 2, 9, 3, 8 }, /* 104: 3, 5, 6, */ { 4, 11, 6, 11, 4, 3, 9, 3, 4, 3, 9, 2, 10, 2, 9 }, /* 168: 3, 5, 7, */ { 7, 4, 3, 9, 3, 4, 3, 9, 2, 5, 2, 9, 2, 5, 6 }, /* 87: 0, 1, 2, 4, 6, */ { 3, 4, 7, 4, 3, 9, 2, 9, 3, 9, 2, 5, 6, 5, 2 }, /* 151: 0, 1, 2, 4, 7, */ { 6, 11, 4, 3, 4, 11, 4, 3, 9, 2, 9, 3, 9, 2, 10 }, /* 199: 0, 1, 2, 6, 7, */ { 5, 11, 7, 11, 5, 2, 9, 2, 5, 2, 9, 3, 8, 3, 9 }, /* 107: 0, 1, 3, 5, 6, */ { 4, 10, 6, 10, 4, 1, 8, 1, 4, 1, 8, 2, 11, 2, 8 }, /* 171: 0, 1, 3, 5, 7, */ { 2, 7, 6, 7, 2, 8, 1, 8, 2, 8, 1, 4, 5, 4, 1 }, /* 203: 0, 1, 3, 6, 7, */ { 5, 10, 7, 2, 7, 10, 7, 2, 8, 1, 8, 2, 8, 1, 9 }, /* 211: 0, 1, 4, 6, 7, */ { 1, 9, 3, 4, 3, 9, 3, 4, 11, 5, 11, 4, 11, 5, 10 }, /* 227: 0, 1, 5, 6, 7, */ { 1, 8, 3, 8, 1, 4, 10, 4, 1, 4, 10, 7, 11, 7, 10 }, /* 61: 0, 2, 3, 4, 5, */ { 7, 9, 5, 9, 7, 0, 11, 0, 7, 0, 11, 1, 10, 1, 11 }, /* 93: 0, 2, 3, 4, 6, */ { 1, 6, 5, 6, 1, 11, 0, 11, 1, 11, 0, 7, 4, 7, 0 }, /* 109: 0, 2, 3, 5, 6, */ { 4, 9, 6, 1, 6, 9, 6, 1, 11, 0, 11, 1, 11, 0, 8 }, /* 117: 0, 2, 4, 5, 6, */ { 3, 0, 7, 9, 7, 0, 7, 9, 6, 1, 6, 9, 6, 1, 2 }, /* 213: 0, 2, 4, 6, 7, */ { 1, 2, 5, 11, 5, 2, 5, 11, 4, 3, 4, 11, 4, 3, 0 }, /* 121: 0, 3, 4, 5, 6, */ { 0, 11, 2, 11, 0, 7, 9, 7, 0, 7, 9, 6, 10, 6, 9 }, /* 233: 0, 3, 5, 6, 7, */ { 0, 8, 2, 7, 2, 8, 2, 7, 10, 4, 10, 7, 10, 4, 9 }, /* 62: 1, 2, 3, 4, 5, */ { 7, 8, 5, 0, 5, 8, 5, 0, 10, 3, 10, 0, 10, 3, 11 }, /* 158: 1, 2, 3, 4, 7, */ { 6, 8, 4, 8, 6, 3, 10, 3, 6, 3, 10, 0, 9, 0, 10 }, /* 174: 1, 2, 3, 5, 7, */ { 0, 5, 4, 5, 0, 10, 3, 10, 0, 10, 3, 6, 7, 6, 3 }, /* 182: 1, 2, 4, 5, 7, */ { 2, 10, 0, 5, 0, 10, 0, 5, 8, 6, 8, 5, 8, 6, 11 }, /* 214: 1, 2, 4, 6, 7, */ { 2, 9, 0, 9, 2, 5, 11, 5, 2, 5, 11, 4, 8, 4, 11 }, /* 186: 1, 3, 4, 5, 7, */ { 2, 3, 6, 8, 6, 3, 6, 8, 5, 0, 5, 8, 5, 0, 1 }, /* 234: 1, 3, 5, 6, 7, */ { 0, 1, 4, 10, 4, 1, 4, 10, 7, 2, 7, 10, 7, 2, 3 }, /* 124: 2, 3, 4, 5, 6, */ { 3, 11, 1, 6, 1, 11, 1, 6, 9, 7, 9, 6, 9, 7, 8 }, /* 188: 2, 3, 4, 5, 7, */ { 3, 10, 1, 10, 3, 6, 8, 6, 3, 6, 8, 5, 9, 5, 8 } }; return &tiling6_2[config][0]; }; // end of Tiling6_2 //_____________________________________________________________________________ //_____________________________________________________________________________ /** * \brief test table for case 7 * 3 faces to test + eventually the interior * When the tests on the 3 specified faces are positive : * - if the test on the interior is positive : 5 first triangles * - if the test on the interior is negative : 9 next triangles * When the tests on the first and the second specified faces are positive : 9 next triangles * When the tests on the first and the third specified faces are positive : 9 next triangles * When the tests on the second and the third specified faces are positive : 9 next triangles * When the test on the first specified face is positive : 5 next triangles * When the test on the second specified face is positive : 5 next triangles * When the test on the third specified face is positive : 5 next triangles * When the tests on the 3 specified faces are negative : 3 last triangles * The support edge for the interior test is marked as the 5th column. * * For each of the case above, the specific triangulation of the edge * intersection points is given. * When a case is ambiguous, there is an auxiliary table that contains * the face number to test and the tiling table contains the specific * triangulations depending on the results * A minus sign means to invert the result of the test. */ //----------------------------------------------------------------------------- static const char Test7(unsigned char config, int u) { static const char test7[16][5] = { /* 37: 0, 2, 5, */ { 1, 2, 5, 7, 1 }, /* 133: 0, 2, 7, */ { 3, 4, 5, 7, 3 }, /* 161: 0, 5, 7, */ { 4, 1, 6, 7, 4 }, /* 26: 1, 3, 4, */ { 4, 1, 5, 7, 0 }, /* 74: 1, 3, 6, */ { 2, 3, 5, 7, 2 }, /* 82: 1, 4, 6, */ { 1, 2, 6, 7, 5 }, /* 164: 2, 5, 7, */ { 2, 3, 6, 7, 6 }, /* 88: 3, 4, 6, */ { 3, 4, 6, 7, 7 }, /* 167: 0, 1, 2, 5, 7, */ { -3, -4, -6, -7, 7 }, /* 91: 0, 1, 3, 4, 6, */ { -2, -3, -6, -7, 6 }, /* 173: 0, 2, 3, 5, 7, */ { -1, -2, -6, -7, 5 }, /* 181: 0, 2, 4, 5, 7, */ { -2, -3, -5, -7, 2 }, /* 229: 0, 2, 5, 6, 7, */ { -4, -1, -5, -7, 0 }, /* 94: 1, 2, 3, 4, 6, */ { -4, -1, -6, -7, 4 }, /* 122: 1, 3, 4, 5, 6, */ { -3, -4, -5, -7, 3 }, /* 218: 1, 3, 4, 6, 7, */ { -1, -2, -5, -7, 1 } }; return test7[config][u]; }; // end of Test7 //_____________________________________________________________________________ /** * \brief tiling table for case 7.1 * For each of the case above, the specific triangulation of the edge * intersection points is given. * When a case is ambiguous, there is an auxiliary table that contains * the face number to test and the tiling table contains the specific * triangulations depending on the results * A minus sign means to invert the result of the test. */ //----------------------------------------------------------------------------- static const char* Tiling7_1(unsigned char config) { static const char tiling7_1[16][9] = { /* 37: 0, 2, 5, */ { 9, 5, 4, 10, 1, 2, 8, 3, 0 }, /* 133: 0, 2, 7, */ { 11, 7, 6, 8, 3, 0, 10, 1, 2 }, /* 161: 0, 5, 7, */ { 3, 0, 8, 5, 4, 9, 7, 6, 11 }, /* 26: 1, 3, 4, */ { 8, 4, 7, 9, 0, 1, 11, 2, 3 }, /* 74: 1, 3, 6, */ { 10, 6, 5, 11, 2, 3, 9, 0, 1 }, /* 82: 1, 4, 6, */ { 0, 1, 9, 6, 5, 10, 4, 7, 8 }, /* 164: 2, 5, 7, */ { 1, 2, 10, 7, 6, 11, 5, 4, 9 }, /* 88: 3, 4, 6, */ { 2, 3, 11, 4, 7, 8, 6, 5, 10 }, /* 167: 0, 1, 2, 5, 7, */ { 11, 3, 2, 8, 7, 4, 10, 5, 6 }, /* 91: 0, 1, 3, 4, 6, */ { 10, 2, 1, 11, 6, 7, 9, 4, 5 }, /* 173: 0, 2, 3, 5, 7, */ { 9, 1, 0, 10, 5, 6, 8, 7, 4 }, /* 181: 0, 2, 4, 5, 7, */ { 5, 6, 10, 3, 2, 11, 1, 0, 9 }, /* 229: 0, 2, 5, 6, 7, */ { 7, 4, 8, 1, 0, 9, 3, 2, 11 }, /* 94: 1, 2, 3, 4, 6, */ { 8, 0, 3, 9, 4, 5, 11, 6, 7 }, /* 122: 1, 3, 4, 5, 6, */ { 6, 7, 11, 0, 3, 8, 2, 1, 10 }, /* 218: 1, 3, 4, 6, 7, */ { 4, 5, 9, 2, 1, 10, 0, 3, 8 } }; return &tiling7_1[config][0]; }; // end of Tiling7_1 //_____________________________________________________________________________ /** * \brief tiling table for case 7.2 * For each of the case above, the specific triangulation of the edge * intersection points is given. * When a case is ambiguous, there is an auxiliary table that contains * the face number to test and the tiling table contains the specific * triangulations depending on the results * A minus sign means to invert the result of the test. */ //----------------------------------------------------------------------------- static const char* Tiling7_2(unsigned char config, int u) { static const char tiling7_2[16][3][15] = { /* 37: 0, 2, 5, */ { /* 1,0 */ { 1, 2, 10, 3, 4, 8, 4, 3, 5, 0, 5, 3, 5, 0, 9 }, /* 0,1 */ { 3, 0, 8, 9, 1, 4, 2, 4, 1, 4, 2, 5, 10, 5, 2 }, /* 1,1 */ { 9, 5, 4, 0, 10, 1, 10, 0, 8, 10, 8, 2, 3, 2, 8 } }, /* 133: 0, 2, 7, */ { /* 1,0 */ { 3, 0, 8, 1, 6, 10, 6, 1, 7, 2, 7, 1, 7, 2, 11 }, /* 0,1 */ { 1, 2, 10, 11, 3, 6, 0, 6, 3, 6, 0, 7, 8, 7, 0 }, /* 1,1 */ { 11, 7, 6, 2, 8, 3, 8, 2, 10, 8, 10, 0, 1, 0, 10 } }, /* 161: 0, 5, 7, */ { /* 1,0 */ { 9, 5, 4, 11, 3, 6, 0, 6, 3, 6, 0, 7, 8, 7, 0 }, /* 0,1 */ { 11, 7, 6, 3, 4, 8, 4, 3, 5, 0, 5, 3, 5, 0, 9 }, /* 1,1 */ { 3, 0, 8, 4, 9, 7, 11, 7, 9, 5, 11, 9, 11, 5, 6 } }, /* 26: 1, 3, 4, */ { /* 1,0 */ { 0, 1, 9, 2, 7, 11, 7, 2, 4, 3, 4, 2, 4, 3, 8 }, /* 0,1 */ { 2, 3, 11, 8, 0, 7, 1, 7, 0, 7, 1, 4, 9, 4, 1 }, /* 1,1 */ { 8, 4, 7, 3, 9, 0, 9, 3, 11, 9, 11, 1, 2, 1, 11 } }, /* 74: 1, 3, 6, */ { /* 1,0 */ { 2, 3, 11, 0, 5, 9, 5, 0, 6, 1, 6, 0, 6, 1, 10 }, /* 0,1 */ { 0, 1, 9, 10, 2, 5, 3, 5, 2, 5, 3, 6, 11, 6, 3 }, /* 1,1 */ { 6, 5, 10, 1, 11, 2, 11, 1, 9, 11, 9, 3, 0, 3, 9 } }, /* 82: 1, 4, 6, */ { /* 1,0 */ { 6, 5, 10, 8, 0, 7, 1, 7, 0, 7, 1, 4, 9, 4, 1 }, /* 0,1 */ { 8, 4, 7, 0, 5, 9, 5, 0, 6, 1, 6, 0, 6, 1, 10 }, /* 1,1 */ { 0, 1, 9, 5, 10, 4, 8, 4, 10, 6, 8, 10, 8, 6, 7 } }, /* 164: 2, 5, 7, */ { /* 1,0 */ { 11, 7, 6, 9, 1, 4, 2, 4, 1, 4, 2, 5, 10, 5, 2 }, /* 0,1 */ { 9, 5, 4, 1, 6, 10, 6, 1, 7, 2, 7, 1, 7, 2, 11 }, /* 1,1 */ { 1, 2, 10, 6, 11, 5, 9, 5, 11, 7, 9, 11, 9, 7, 4 } }, /* 88: 3, 4, 6, */ { /* 1,0 */ { 8, 4, 7, 10, 2, 5, 3, 5, 2, 5, 3, 6, 11, 6, 3 }, /* 0,1 */ { 6, 5, 10, 2, 7, 11, 7, 2, 4, 3, 4, 2, 4, 3, 8 }, /* 1,1 */ { 2, 3, 11, 7, 8, 6, 10, 6, 8, 4, 10, 8, 10, 4, 5 } }, /* 167: 0, 1, 2, 5, 7, */ { /* 1,0 */ { 7, 4, 8, 5, 2, 10, 2, 5, 3, 6, 3, 5, 3, 6, 11 }, /* 0,1 */ { 10, 5, 6, 11, 7, 2, 4, 2, 7, 2, 4, 3, 8, 3, 4 }, /* 1,1 */ { 11, 3, 2, 6, 8, 7, 8, 6, 10, 8, 10, 4, 5, 4, 10 } }, /* 91: 0, 1, 3, 4, 6, */ { /* 1,0 */ { 6, 7, 11, 4, 1, 9, 1, 4, 2, 5, 2, 4, 2, 5, 10 }, /* 0,1 */ { 4, 5, 9, 10, 6, 1, 7, 1, 6, 1, 7, 2, 11, 2, 7 }, /* 1,1 */ { 10, 2, 1, 5, 11, 6, 11, 5, 9, 11, 9, 7, 4, 7, 9 } }, /* 173: 0, 2, 3, 5, 7, */ { /* 1,0 */ { 10, 5, 6, 7, 0, 8, 0, 7, 1, 4, 1, 7, 1, 4, 9 }, /* 0,1 */ { 7, 4, 8, 9, 5, 0, 6, 0, 5, 0, 6, 1, 10, 1, 6 }, /* 1,1 */ { 9, 1, 0, 4, 10, 5, 10, 4, 8, 10, 8, 6, 7, 6, 8 } }, /* 181: 0, 2, 4, 5, 7, */ { /* 1,0 */ { 11, 3, 2, 9, 5, 0, 6, 0, 5, 0, 6, 1, 10, 1, 6 }, /* 0,1 */ { 9, 1, 0, 5, 2, 10, 2, 5, 3, 6, 3, 5, 3, 6, 11 }, /* 1,1 */ { 10, 5, 6, 2, 11, 1, 9, 1, 11, 3, 9, 11, 9, 3, 0 } }, /* 229: 0, 2, 5, 6, 7, */ { /* 1,0 */ { 9, 1, 0, 11, 7, 2, 4, 2, 7, 2, 4, 3, 8, 3, 4 }, /* 0,1 */ { 11, 3, 2, 7, 0, 8, 0, 7, 1, 4, 1, 7, 1, 4, 9 }, /* 1,1 */ { 7, 4, 8, 0, 9, 3, 11, 3, 9, 1, 11, 9, 11, 1, 2 } }, /* 94: 1, 2, 3, 4, 6, */ { /* 1,0 */ { 4, 5, 9, 6, 3, 11, 3, 6, 0, 7, 0, 6, 0, 7, 8 }, /* 0,1 */ { 6, 7, 11, 8, 4, 3, 5, 3, 4, 3, 5, 0, 9, 0, 5 }, /* 1,1 */ { 8, 0, 3, 7, 9, 4, 9, 7, 11, 9, 11, 5, 6, 5, 11 } }, /* 122: 1, 3, 4, 5, 6, */ { /* 1,0 */ { 8, 0, 3, 10, 6, 1, 7, 1, 6, 1, 7, 2, 11, 2, 7 }, /* 0,1 */ { 10, 2, 1, 6, 3, 11, 3, 6, 0, 7, 0, 6, 0, 7, 8 }, /* 1,1 */ { 6, 7, 11, 3, 8, 2, 10, 2, 8, 0, 10, 8, 10, 0, 1 } }, /* 218: 1, 3, 4, 6, 7, */ { /* 1,0 */ { 10, 2, 1, 8, 4, 3, 5, 3, 4, 3, 5, 0, 9, 0, 5 }, /* 0,1 */ { 8, 0, 3, 4, 1, 9, 1, 4, 2, 5, 2, 4, 2, 5, 10 }, /* 1,1 */ { 4, 5, 9, 1, 10, 0, 8, 0, 10, 2, 8, 10, 8, 2, 3 } } }; return &tiling7_2[config][u][0]; }; // end of Tiling7_2 //_____________________________________________________________________________ /** * \brief tiling table for case 7.3 * For each of the case above, the specific triangulation of the edge * intersection points is given. * When a case is ambiguous, there is an auxiliary table that contains * the face number to test and the tiling table contains the specific * triangulations depending on the results * A minus sign means to invert the result of the test. */ //----------------------------------------------------------------------------- static const char* Tiling7_3(unsigned char config, unsigned char u) { static const char tiling7_3[16][3][27] = { /* 37: 0, 2, 5, */ { /* 1,0 */ { 12, 2, 10, 12, 10, 5, 12, 5, 4, 12, 4, 8, 12, 8, 3, 12, 3, 0, 12, 0, 9, 12, 9, 1, 12, 1, 2 }, /* 0,1 */ { 12, 5, 4, 12, 4, 8, 12, 8, 3, 12, 3, 2, 12, 2, 10, 12, 10, 1, 12, 1, 0, 12, 0, 9, 12, 9, 5 }, /* 1,1 */ { 5, 4, 12, 10, 5, 12, 2, 10, 12, 3, 2, 12, 8, 3, 12, 0, 8, 12, 1, 0, 12, 9, 1, 12, 4, 9, 12 } }, /* 133: 0, 2, 7, */ { /* 1,0 */ { 12, 0, 8, 12, 8, 7, 12, 7, 6, 12, 6, 10, 12, 10, 1, 12, 1, 2, 12, 2, 11, 12, 11, 3, 12, 3, 0 }, /* 0,1 */ { 12, 7, 6, 12, 6, 10, 12, 10, 1, 12, 1, 0, 12, 0, 8, 12, 8, 3, 12, 3, 2, 12, 2, 11, 12, 11, 7 }, /* 1,1 */ { 7, 6, 12, 8, 7, 12, 0, 8, 12, 1, 0, 12, 10, 1, 12, 2, 10, 12, 3, 2, 12, 11, 3, 12, 6, 11, 12 } }, /* 161: 0, 5, 7, */ { /* 1,0 */ { 9, 5, 12, 0, 9, 12, 3, 0, 12, 11, 3, 12, 6, 11, 12, 7, 6, 12, 8, 7, 12, 4, 8, 12, 5, 4, 12 }, /* 0,1 */ { 3, 0, 12, 11, 3, 12, 6, 11, 12, 5, 6, 12, 9, 5, 12, 4, 9, 12, 7, 4, 12, 8, 7, 12, 0, 8, 12 }, /* 1,1 */ { 12, 3, 0, 12, 0, 9, 12, 9, 5, 12, 5, 6, 12, 6, 11, 12, 11, 7, 12, 7, 4, 12, 4, 8, 12, 8, 3 } }, /* 26: 1, 3, 4, */ { /* 1,0 */ { 12, 1, 9, 12, 9, 4, 12, 4, 7, 12, 7, 11, 12, 11, 2, 12, 2, 3, 12, 3, 8, 12, 8, 0, 12, 0, 1 }, /* 0,1 */ { 12, 4, 7, 12, 7, 11, 12, 11, 2, 12, 2, 1, 12, 1, 9, 12, 9, 0, 12, 0, 3, 12, 3, 8, 12, 8, 4 }, /* 1,1 */ { 4, 7, 12, 9, 4, 12, 1, 9, 12, 2, 1, 12, 11, 2, 12, 3, 11, 12, 0, 3, 12, 8, 0, 12, 7, 8, 12 } }, /* 74: 1, 3, 6, */ { /* 1,0 */ { 12, 3, 11, 12, 11, 6, 12, 6, 5, 12, 5, 9, 12, 9, 0, 12, 0, 1, 12, 1, 10, 12, 10, 2, 12, 2, 3 }, /* 0,1 */ { 12, 6, 5, 12, 5, 9, 12, 9, 0, 12, 0, 3, 12, 3, 11, 12, 11, 2, 12, 2, 1, 12, 1, 10, 12, 10, 6 }, /* 1,1 */ { 6, 5, 12, 11, 6, 12, 3, 11, 12, 0, 3, 12, 9, 0, 12, 1, 9, 12, 2, 1, 12, 10, 2, 12, 5, 10, 12 } }, /* 82: 1, 4, 6, */ { /* 1,0 */ { 10, 6, 12, 1, 10, 12, 0, 1, 12, 8, 0, 12, 7, 8, 12, 4, 7, 12, 9, 4, 12, 5, 9, 12, 6, 5, 12 }, /* 0,1 */ { 0, 1, 12, 8, 0, 12, 7, 8, 12, 6, 7, 12, 10, 6, 12, 5, 10, 12, 4, 5, 12, 9, 4, 12, 1, 9, 12 }, /* 1,1 */ { 12, 0, 1, 12, 1, 10, 12, 10, 6, 12, 6, 7, 12, 7, 8, 12, 8, 4, 12, 4, 5, 12, 5, 9, 12, 9, 0 } }, /* 164: 2, 5, 7, */ { /* 1,0 */ { 11, 7, 12, 2, 11, 12, 1, 2, 12, 9, 1, 12, 4, 9, 12, 5, 4, 12, 10, 5, 12, 6, 10, 12, 7, 6, 12 }, /* 0,1 */ { 1, 2, 12, 9, 1, 12, 4, 9, 12, 7, 4, 12, 11, 7, 12, 6, 11, 12, 5, 6, 12, 10, 5, 12, 2, 10, 12 }, /* 1,1 */ { 12, 1, 2, 12, 2, 11, 12, 11, 7, 12, 7, 4, 12, 4, 9, 12, 9, 5, 12, 5, 6, 12, 6, 10, 12, 10, 1 } }, /* 88: 3, 4, 6, */ { /* 1,0 */ { 8, 4, 12, 3, 8, 12, 2, 3, 12, 10, 2, 12, 5, 10, 12, 6, 5, 12, 11, 6, 12, 7, 11, 12, 4, 7, 12 }, /* 0,1 */ { 2, 3, 12, 10, 2, 12, 5, 10, 12, 4, 5, 12, 8, 4, 12, 7, 8, 12, 6, 7, 12, 11, 6, 12, 3, 11, 12 }, /* 1,1 */ { 12, 2, 3, 12, 3, 8, 12, 8, 4, 12, 4, 5, 12, 5, 10, 12, 10, 6, 12, 6, 7, 12, 7, 11, 12, 11, 2 } }, /* 167: 0, 1, 2, 5, 7, */ { /* 1,0 */ { 12, 4, 8, 12, 8, 3, 12, 3, 2, 12, 2, 10, 12, 10, 5, 12, 5, 6, 12, 6, 11, 12, 11, 7, 12, 7, 4 }, /* 0,1 */ { 12, 3, 2, 12, 2, 10, 12, 10, 5, 12, 5, 4, 12, 4, 8, 12, 8, 7, 12, 7, 6, 12, 6, 11, 12, 11, 3 }, /* 1,1 */ { 3, 2, 12, 8, 3, 12, 4, 8, 12, 5, 4, 12, 10, 5, 12, 6, 10, 12, 7, 6, 12, 11, 7, 12, 2, 11, 12 } }, /* 91: 0, 1, 3, 4, 6, */ { /* 1,0 */ { 12, 7, 11, 12, 11, 2, 12, 2, 1, 12, 1, 9, 12, 9, 4, 12, 4, 5, 12, 5, 10, 12, 10, 6, 12, 6, 7 }, /* 0,1 */ { 12, 2, 1, 12, 1, 9, 12, 9, 4, 12, 4, 7, 12, 7, 11, 12, 11, 6, 12, 6, 5, 12, 5, 10, 12, 10, 2 }, /* 1,1 */ { 2, 1, 12, 11, 2, 12, 7, 11, 12, 4, 7, 12, 9, 4, 12, 5, 9, 12, 6, 5, 12, 10, 6, 12, 1, 10, 12 } }, /* 173: 0, 2, 3, 5, 7, */ { /* 1,0 */ { 12, 6, 10, 12, 10, 1, 12, 1, 0, 12, 0, 8, 12, 8, 7, 12, 7, 4, 12, 4, 9, 12, 9, 5, 12, 5, 6 }, /* 0,1 */ { 12, 1, 0, 12, 0, 8, 12, 8, 7, 12, 7, 6, 12, 6, 10, 12, 10, 5, 12, 5, 4, 12, 4, 9, 12, 9, 1 }, /* 1,1 */ { 1, 0, 12, 10, 1, 12, 6, 10, 12, 7, 6, 12, 8, 7, 12, 4, 8, 12, 5, 4, 12, 9, 5, 12, 0, 9, 12 } }, /* 181: 0, 2, 4, 5, 7, */ { /* 1,0 */ { 11, 3, 12, 6, 11, 12, 5, 6, 12, 9, 5, 12, 0, 9, 12, 1, 0, 12, 10, 1, 12, 2, 10, 12, 3, 2, 12 }, /* 0,1 */ { 5, 6, 12, 9, 5, 12, 0, 9, 12, 3, 0, 12, 11, 3, 12, 2, 11, 12, 1, 2, 12, 10, 1, 12, 6, 10, 12 }, /* 1,1 */ { 12, 5, 6, 12, 6, 11, 12, 11, 3, 12, 3, 0, 12, 0, 9, 12, 9, 1, 12, 1, 2, 12, 2, 10, 12, 10, 5 } }, /* 229: 0, 2, 5, 6, 7, */ { /* 1,0 */ { 9, 1, 12, 4, 9, 12, 7, 4, 12, 11, 7, 12, 2, 11, 12, 3, 2, 12, 8, 3, 12, 0, 8, 12, 1, 0, 12 }, /* 0,1 */ { 7, 4, 12, 11, 7, 12, 2, 11, 12, 1, 2, 12, 9, 1, 12, 0, 9, 12, 3, 0, 12, 8, 3, 12, 4, 8, 12 }, /* 1,1 */ { 12, 7, 4, 12, 4, 9, 12, 9, 1, 12, 1, 2, 12, 2, 11, 12, 11, 3, 12, 3, 0, 12, 0, 8, 12, 8, 7 } }, /* 94: 1, 2, 3, 4, 6, */ { /* 1,0 */ { 12, 5, 9, 12, 9, 0, 12, 0, 3, 12, 3, 11, 12, 11, 6, 12, 6, 7, 12, 7, 8, 12, 8, 4, 12, 4, 5 }, /* 0,1 */ { 12, 0, 3, 12, 3, 11, 12, 11, 6, 12, 6, 5, 12, 5, 9, 12, 9, 4, 12, 4, 7, 12, 7, 8, 12, 8, 0 }, /* 1,1 */ { 0, 3, 12, 9, 0, 12, 5, 9, 12, 6, 5, 12, 11, 6, 12, 7, 11, 12, 4, 7, 12, 8, 4, 12, 3, 8, 12 } }, /* 122: 1, 3, 4, 5, 6, */ { /* 1,0 */ { 8, 0, 12, 7, 8, 12, 6, 7, 12, 10, 6, 12, 1, 10, 12, 2, 1, 12, 11, 2, 12, 3, 11, 12, 0, 3, 12 }, /* 0,1 */ { 6, 7, 12, 10, 6, 12, 1, 10, 12, 0, 1, 12, 8, 0, 12, 3, 8, 12, 2, 3, 12, 11, 2, 12, 7, 11, 12 }, /* 1,1 */ { 12, 6, 7, 12, 7, 8, 12, 8, 0, 12, 0, 1, 12, 1, 10, 12, 10, 2, 12, 2, 3, 12, 3, 11, 12, 11, 6 } }, /* 218: 1, 3, 4, 6, 7, */ { /* 1,0 */ { 10, 2, 12, 5, 10, 12, 4, 5, 12, 8, 4, 12, 3, 8, 12, 0, 3, 12, 9, 0, 12, 1, 9, 12, 2, 1, 12 }, /* 0,1 */ { 4, 5, 12, 8, 4, 12, 3, 8, 12, 2, 3, 12, 10, 2, 12, 1, 10, 12, 0, 1, 12, 9, 0, 12, 5, 9, 12 }, /* 1,1 */ { 12, 4, 5, 12, 5, 10, 12, 10, 2, 12, 2, 3, 12, 3, 8, 12, 8, 0, 12, 0, 1, 12, 1, 9, 12, 9, 4 } } }; return &tiling7_3[config][u][0]; }; // end of Tiling7_3 //_____________________________________________________________________________ /** * \brief tiling table for case 7.4.1 * For each of the case above, the specific triangulation of the edge * intersection points is given. * When a case is ambiguous, there is an auxiliary table that contains * the face number to test and the tiling table contains the specific * triangulations depending on the results * A minus sign means to invert the result of the test. */ //----------------------------------------------------------------------------- static const char* Tiling7_4_1(unsigned char config) { static const char tiling7_4_1[16][15] = { /* 37: 0, 2, 5, */ { 3, 4, 8, 4, 3, 10, 2, 10, 3, 4, 10, 5, 9, 1, 0 }, /* 133: 0, 2, 7, */ { 1, 6, 10, 6, 1, 8, 0, 8, 1, 6, 8, 7, 11, 3, 2 }, /* 161: 0, 5, 7, */ { 11, 3, 6, 9, 6, 3, 6, 9, 5, 0, 9, 3, 7, 4, 8 }, /* 26: 1, 3, 4, */ { 2, 7, 11, 7, 2, 9, 1, 9, 2, 7, 9, 4, 8, 0, 3 }, /* 74: 1, 3, 6, */ { 0, 5, 9, 5, 0, 11, 3, 11, 0, 5, 11, 6, 10, 2, 1 }, /* 82: 1, 4, 6, */ { 8, 0, 7, 10, 7, 0, 7, 10, 6, 1, 10, 0, 4, 5, 9 }, /* 164: 2, 5, 7, */ { 9, 1, 4, 11, 4, 1, 4, 11, 7, 2, 11, 1, 5, 6, 10 }, /* 88: 3, 4, 6, */ { 10, 2, 5, 8, 5, 2, 5, 8, 4, 3, 8, 2, 6, 7, 11 }, /* 167: 0, 1, 2, 5, 7, */ { 5, 2, 10, 2, 5, 8, 4, 8, 5, 2, 8, 3, 11, 7, 6 }, /* 91: 0, 1, 3, 4, 6, */ { 4, 1, 9, 1, 4, 11, 7, 11, 4, 1, 11, 2, 10, 6, 5 }, /* 173: 0, 2, 3, 5, 7, */ { 7, 0, 8, 0, 7, 10, 6, 10, 7, 0, 10, 1, 9, 5, 4 }, /* 181: 0, 2, 4, 5, 7, */ { 9, 5, 0, 11, 0, 5, 0, 11, 3, 6, 11, 5, 1, 2, 10 }, /* 229: 0, 2, 5, 6, 7, */ { 11, 7, 2, 9, 2, 7, 2, 9, 1, 4, 9, 7, 3, 0, 8 }, /* 94: 1, 2, 3, 4, 6, */ { 6, 3, 11, 3, 6, 9, 5, 9, 6, 3, 9, 0, 8, 4, 7 }, /* 122: 1, 3, 4, 5, 6, */ { 10, 6, 1, 8, 1, 6, 1, 8, 0, 7, 8, 6, 2, 3, 11 }, /* 218: 1, 3, 4, 6, 7, */ { 8, 4, 3, 10, 3, 4, 3, 10, 2, 5, 10, 4, 0, 1, 9 } }; return &tiling7_4_1[config][0]; }; // end of Tiling7_4_1 //_____________________________________________________________________________ /** * \brief tiling table for case 7.4.2 * For each of the case above, the specific triangulation of the edge * intersection points is given. * When a case is ambiguous, there is an auxiliary table that contains * the face number to test and the tiling table contains the specific * triangulations depending on the results * A minus sign means to invert the result of the test. */ //----------------------------------------------------------------------------- static const char* Tiling7_4_2(unsigned char config) { static const char tiling7_4_2[16][27] = { /* 37: 0, 2, 5, */ { 9, 4, 8, 4, 9, 5, 10, 5, 9, 1, 10, 9, 10, 1, 2, 0, 2, 1, 2, 0, 3, 8, 3, 0, 9, 8, 0 }, /* 133: 0, 2, 7, */ { 11, 6, 10, 6, 11, 7, 8, 7, 11, 3, 8, 11, 8, 3, 0, 2, 0, 3, 0, 2, 1, 10, 1, 2, 11, 10, 2 }, /* 161: 0, 5, 7, */ { 11, 3, 8, 0, 8, 3, 8, 0, 9, 8, 9, 4, 5, 4, 9, 4, 5, 7, 6, 7, 5, 7, 6, 11, 7, 11, 8 }, /* 26: 1, 3, 4, */ { 8, 7, 11, 7, 8, 4, 9, 4, 8, 0, 9, 8, 9, 0, 1, 3, 1, 0, 1, 3, 2, 11, 2, 3, 8, 11, 3 }, /* 74: 1, 3, 6, */ { 10, 5, 9, 5, 10, 6, 11, 6, 10, 2, 11, 10, 11, 2, 3, 1, 3, 2, 3, 1, 0, 9, 0, 1, 10, 9, 1 }, /* 82: 1, 4, 6, */ { 8, 0, 9, 1, 9, 0, 9, 1, 10, 9, 10, 5, 6, 5, 10, 5, 6, 4, 7, 4, 6, 4, 7, 8, 4, 8, 9 }, /* 164: 2, 5, 7, */ { 9, 1, 10, 2, 10, 1, 10, 2, 11, 10, 11, 6, 7, 6, 11, 6, 7, 5, 4, 5, 7, 5, 4, 9, 5, 9, 10 }, /* 88: 3, 4, 6, */ { 10, 2, 11, 3, 11, 2, 11, 3, 8, 11, 8, 7, 4, 7, 8, 7, 4, 6, 5, 6, 4, 6, 5, 10, 6, 10, 11 }, /* 167: 0, 1, 2, 5, 7, */ { 11, 2, 10, 2, 11, 3, 8, 3, 11, 7, 8, 11, 8, 7, 4, 6, 4, 7, 4, 6, 5, 10, 5, 6, 11, 10, 6 }, /* 91: 0, 1, 3, 4, 6, */ { 10, 1, 9, 1, 10, 2, 11, 2, 10, 6, 11, 10, 11, 6, 7, 5, 7, 6, 7, 5, 4, 9, 4, 5, 10, 9, 5 }, /* 173: 0, 2, 3, 5, 7, */ { 9, 0, 8, 0, 9, 1, 10, 1, 9, 5, 10, 9, 10, 5, 6, 4, 6, 5, 6, 4, 7, 8, 7, 4, 9, 8, 4 }, /* 181: 0, 2, 4, 5, 7, */ { 9, 5, 10, 6, 10, 5, 10, 6, 11, 10, 11, 2, 3, 2, 11, 2, 3, 1, 0, 1, 3, 1, 0, 9, 1, 9, 10 }, /* 229: 0, 2, 5, 6, 7, */ { 11, 7, 8, 4, 8, 7, 8, 4, 9, 8, 9, 0, 1, 0, 9, 0, 1, 3, 2, 3, 1, 3, 2, 11, 3, 11, 8 }, /* 94: 1, 2, 3, 4, 6, */ { 8, 3, 11, 3, 8, 0, 9, 0, 8, 4, 9, 8, 9, 4, 5, 7, 5, 4, 5, 7, 6, 11, 6, 7, 8, 11, 7 }, /* 122: 1, 3, 4, 5, 6, */ { 10, 6, 11, 7, 11, 6, 11, 7, 8, 11, 8, 3, 0, 3, 8, 3, 0, 2, 1, 2, 0, 2, 1, 10, 2, 10, 11 }, /* 218: 1, 3, 4, 6, 7, */ { 8, 4, 9, 5, 9, 4, 9, 5, 10, 9, 10, 1, 2, 1, 10, 1, 2, 0, 3, 0, 2, 0, 3, 8, 0, 8, 9 } }; return &tiling7_4_2[config][0]; }; // end of Tiling7_4_2 //_____________________________________________________________________________ //_____________________________________________________________________________ /** * \brief tiling table for case 8 * For each of the case above, the specific triangulation of the edge * intersection points is given. * When a case is ambiguous, there is an auxiliary table that contains * the face number to test and the tiling table contains the specific * triangulations depending on the results * A minus sign means to invert the result of the test. */ //----------------------------------------------------------------------------- static const char* Tiling8(unsigned char config) { static const char tiling8[6][6] = { /* 15: 0, 1, 2, 3, */ { 9, 8, 10, 10, 8, 11 }, /* 51: 0, 1, 4, 5, */ { 1, 5, 3, 3, 5, 7 }, /* 153: 0, 3, 4, 7, */ { 0, 4, 2, 4, 6, 2 }, /* 102: 1, 2, 5, 6, */ { 0, 2, 4, 4, 2, 6 }, /* 204: 2, 3, 6, 7, */ { 1, 3, 5, 3, 7, 5 }, /* 240: 4, 5, 6, 7, */ { 9, 10, 8, 10, 11, 8 } }; return &tiling8[config][0]; }; // end of Tiling8 //_____________________________________________________________________________ //_____________________________________________________________________________ /** * \brief tiling table for case 9 * For each of the case above, the specific triangulation of the edge * intersection points is given. * When a case is ambiguous, there is an auxiliary table that contains * the face number to test and the tiling table contains the specific * triangulations depending on the results * A minus sign means to invert the result of the test. */ //----------------------------------------------------------------------------- static const char* Tiling9(unsigned char config) { static const char tiling9[8][12] = { /* 39: 0, 1, 2, 5, */ { 2, 10, 5, 3, 2, 5, 3, 5, 4, 3, 4, 8 }, /* 27: 0, 1, 3, 4, */ { 4, 7, 11, 9, 4, 11, 9, 11, 2, 9, 2, 1 }, /* 141: 0, 2, 3, 7, */ { 10, 7, 6, 1, 7, 10, 1, 8, 7, 1, 0, 8 }, /* 177: 0, 4, 5, 7, */ { 3, 6, 11, 0, 6, 3, 0, 5, 6, 0, 9, 5 }, /* 78: 1, 2, 3, 6, */ { 3, 11, 6, 0, 3, 6, 0, 6, 5, 0, 5, 9 }, /* 114: 1, 4, 5, 6, */ { 10, 6, 7, 1, 10, 7, 1, 7, 8, 1, 8, 0 }, /* 228: 2, 5, 6, 7, */ { 4, 11, 7, 9, 11, 4, 9, 2, 11, 9, 1, 2 }, /* 216: 3, 4, 6, 7, */ { 2, 5, 10, 3, 5, 2, 3, 4, 5, 3, 8, 4 } }; return &tiling9[config][0]; }; //_____________________________________________________________________________ //_____________________________________________________________________________ /** * \brief test table for case 10 * 2 faces to test + eventually the interior * When the tests on both specified faces are positive : 4 middle triangles (1) * When the test on the first specified face is positive : 8 first triangles * When the test on the second specified face is positive : 8 next triangles * When the tests on both specified faces are negative : * - if the test on the interior is negative : 4 middle triangles * - if the test on the interior is positive : 8 last triangles * * For each of the case above, the specific triangulation of the edge * intersection points is given. * When a case is ambiguous, there is an auxiliary table that contains * the face number to test and the tiling table contains the specific * triangulations depending on the results * A minus sign means to invert the result of the test. */ //----------------------------------------------------------------------------- static const char Test10(unsigned char config, int u) { static const char test10[6][3] = { /* 195: 0, 1, 6, 7, */ { 2, 4, 7 }, /* 85: 0, 2, 4, 6, */ { 5, 6, 7 }, /* 105: 0, 3, 5, 6, */ { 1, 3, 7 }, /* 150: 1, 2, 4, 7, */ { 1, 3, 7 }, /* 170: 1, 3, 5, 7, */ { 5, 6, 7 }, /* 60: 2, 3, 4, 5, */ { 2, 4, 7 } }; return test10[config][u]; }; // end of Test10 //_____________________________________________________________________________ /** * \brief tiling table for case 10.1.1 * For each of the case above, the specific triangulation of the edge * intersection points is given. * When a case is ambiguous, there is an auxiliary table that contains * the face number to test and the tiling table contains the specific * triangulations depending on the results * A minus sign means to invert the result of the test. */ //----------------------------------------------------------------------------- static const char* Tiling10_1_1(unsigned char config) { static const char tiling10_1_1[6][12] = { /* 195: 0, 1, 6, 7, */ { 5, 10, 7, 11, 7, 10, 8, 1, 9, 1, 8, 3 }, /* 85: 0, 2, 4, 6, */ { 1, 2, 5, 6, 5, 2, 4, 3, 0, 3, 4, 7 }, /* 105: 0, 3, 5, 6, */ { 11, 0, 8, 0, 11, 2, 4, 9, 6, 10, 6, 9 }, /* 150: 1, 2, 4, 7, */ { 9, 0, 10, 2, 10, 0, 6, 8, 4, 8, 6, 11 }, /* 170: 1, 3, 5, 7, */ { 7, 2, 3, 2, 7, 6, 0, 1, 4, 5, 4, 1 }, /* 60: 2, 3, 4, 5, */ { 7, 9, 5, 9, 7, 8, 10, 1, 11, 3, 11, 1 } }; return &tiling10_1_1[config][0]; }; // end of Tiling10_1_1 //_____________________________________________________________________________ /** * \brief tiling table for case 10.1.1 inverted * For each of the case above, the specific triangulation of the edge * intersection points is given. * When a case is ambiguous, there is an auxiliary table that contains * the face number to test and the tiling table contains the specific * triangulations depending on the results * A minus sign means to invert the result of the test. */ //----------------------------------------------------------------------------- static const char* Tiling10_1_1_(unsigned char config) { static const char tiling10_1_1_[6][12] = { /* 195: 0, 1, 6, 7, */ { 5, 9, 7, 8, 7, 9, 11, 1, 10, 1, 11, 3 }, /* 85: 0, 2, 4, 6, */ { 3, 2, 7, 6, 7, 2, 4, 1, 0, 1, 4, 5 }, /* 105: 0, 3, 5, 6, */ { 10, 0, 9, 0, 10, 2, 4, 8, 6, 11, 6, 8 }, /* 150: 1, 2, 4, 7, */ { 8, 0, 11, 2, 11, 0, 6, 9, 4, 9, 6, 10 }, /* 170: 1, 3, 5, 7, */ { 5, 2, 1, 2, 5, 6, 0, 3, 4, 7, 4, 3 }, /* 60: 2, 3, 4, 5, */ { 7, 10, 5, 10, 7, 11, 9, 1, 8, 3, 8, 1 } }; return &tiling10_1_1_[config][0]; }; // end of Tiling10_1_1_ //_____________________________________________________________________________ /** * \brief tiling table for case 10.1.2 * For each of the case above, the specific triangulation of the edge * intersection points is given. * When a case is ambiguous, there is an auxiliary table that contains * the face number to test and the tiling table contains the specific * triangulations depending on the results * A minus sign means to invert the result of the test. */ //----------------------------------------------------------------------------- static const char* Tiling10_1_2(unsigned char config) { static const char tiling10_1_2[6][24] = { /* 195: 0, 1, 6, 7, */ { 3, 11, 7, 3, 7, 8, 9, 8, 7, 5, 9, 7, 9, 5, 10, 9, 10, 1, 3, 1, 10, 11, 3, 10 }, /* 85: 0, 2, 4, 6, */ { 7, 6, 5, 7, 5, 4, 0, 4, 5, 1, 0, 5, 0, 1, 2, 0, 2, 3, 7, 3, 2, 6, 7, 2 }, /* 105: 0, 3, 5, 6, */ { 11, 2, 10, 6, 11, 10, 11, 6, 4, 11, 4, 8, 0, 8, 4, 9, 0, 4, 0, 9, 10, 0, 10, 2 }, /* 150: 1, 2, 4, 7, */ { 11, 2, 10, 11, 10, 6, 4, 6, 10, 9, 4, 10, 4, 9, 0, 4, 0, 8, 11, 8, 0, 2, 11, 0 }, /* 170: 1, 3, 5, 7, */ { 7, 6, 5, 4, 7, 5, 7, 4, 0, 7, 0, 3, 2, 3, 0, 1, 2, 0, 2, 1, 5, 2, 5, 6 }, /* 60: 2, 3, 4, 5, */ { 7, 8, 3, 11, 7, 3, 7, 11, 10, 7, 10, 5, 9, 5, 10, 1, 9, 10, 9, 1, 3, 9, 3, 8 } }; return &tiling10_1_2[config][0]; }; // end of Tiling10_1_2 //_____________________________________________________________________________ /** * \brief tiling table for case 10.2 * For each of the case above, the specific triangulation of the edge * intersection points is given. * When a case is ambiguous, there is an auxiliary table that contains * the face number to test and the tiling table contains the specific * triangulations depending on the results * A minus sign means to invert the result of the test. */ //----------------------------------------------------------------------------- static const char* Tiling10_2(unsigned char config) { static const char tiling10_2[6][24] = { /* 195: 0, 1, 6, 7, */ { 12, 5, 9, 12, 9, 8, 12, 8, 3, 12, 3, 1, 12, 1, 10, 12, 10, 11, 12, 11, 7, 12, 7, 5 }, /* 85: 0, 2, 4, 6, */ { 12, 1, 0, 12, 0, 4, 12, 4, 7, 12, 7, 3, 12, 3, 2, 12, 2, 6, 12, 6, 5, 12, 5, 1 }, /* 105: 0, 3, 5, 6, */ { 4, 8, 12, 6, 4, 12, 10, 6, 12, 9, 10, 12, 0, 9, 12, 2, 0, 12, 11, 2, 12, 8, 11, 12 }, /* 150: 1, 2, 4, 7, */ { 12, 9, 4, 12, 4, 6, 12, 6, 11, 12, 11, 8, 12, 8, 0, 12, 0, 2, 12, 2, 10, 12, 10, 9 }, /* 170: 1, 3, 5, 7, */ { 0, 3, 12, 4, 0, 12, 5, 4, 12, 1, 5, 12, 2, 1, 12, 6, 2, 12, 7, 6, 12, 3, 7, 12 }, /* 60: 2, 3, 4, 5, */ { 10, 5, 12, 11, 10, 12, 3, 11, 12, 1, 3, 12, 9, 1, 12, 8, 9, 12, 7, 8, 12, 5, 7, 12 } }; return &tiling10_2[config][0]; }; // end of Tiling10_2 //_____________________________________________________________________________ /** * \brief tiling table for case 10.2 inverted * For each of the case above, the specific triangulation of the edge * intersection points is given. * When a case is ambiguous, there is an auxiliary table that contains * the face number to test and the tiling table contains the specific * triangulations depending on the results * A minus sign means to invert the result of the test. */ //----------------------------------------------------------------------------- static const char* Tiling10_2_(unsigned char config) { static const char tiling10_2_[6][24] = { /* 195: 0, 1, 6, 7, */ { 8, 7, 12, 9, 8, 12, 1, 9, 12, 3, 1, 12, 11, 3, 12, 10, 11, 12, 5, 10, 12, 7, 5, 12 }, /* 85: 0, 2, 4, 6, */ { 4, 5, 12, 0, 4, 12, 3, 0, 12, 7, 3, 12, 6, 7, 12, 2, 6, 12, 1, 2, 12, 5, 1, 12 }, /* 105: 0, 3, 5, 6, */ { 12, 11, 6, 12, 6, 4, 12, 4, 9, 12, 9, 10, 12, 10, 2, 12, 2, 0, 12, 0, 8, 12, 8, 11 }, /* 150: 1, 2, 4, 7, */ { 6, 10, 12, 4, 6, 12, 8, 4, 12, 11, 8, 12, 2, 11, 12, 0, 2, 12, 9, 0, 12, 10, 9, 12 }, /* 170: 1, 3, 5, 7, */ { 12, 7, 4, 12, 4, 0, 12, 0, 1, 12, 1, 5, 12, 5, 6, 12, 6, 2, 12, 2, 3, 12, 3, 7 }, /* 60: 2, 3, 4, 5, */ { 12, 7, 11, 12, 11, 10, 12, 10, 1, 12, 1, 3, 12, 3, 8, 12, 8, 9, 12, 9, 5, 12, 5, 7 } }; return &tiling10_2_[config][0]; }; // end of Tiling10_2_ //_____________________________________________________________________________ //_____________________________________________________________________________ /** * \brief tiling table for case 11 * For each of the case above, the specific triangulation of the edge * intersection points is given. * When a case is ambiguous, there is an auxiliary table that contains * the face number to test and the tiling table contains the specific * triangulations depending on the results * A minus sign means to invert the result of the test. */ //----------------------------------------------------------------------------- static const char* Tiling11(unsigned char config) { static const char tiling11[12][12] = { /* 23: 0, 1, 2, 4, */ { 2, 10, 9, 2, 9, 7, 2, 7, 3, 7, 9, 4 }, /* 139: 0, 1, 3, 7, */ { 1, 6, 2, 1, 8, 6, 1, 9, 8, 8, 7, 6 }, /* 99: 0, 1, 5, 6, */ { 8, 3, 1, 8, 1, 6, 8, 6, 4, 6, 1, 10 }, /* 77: 0, 2, 3, 6, */ { 0, 8, 11, 0, 11, 5, 0, 5, 1, 5, 11, 6 }, /* 57: 0, 3, 4, 5, */ { 9, 5, 7, 9, 7, 2, 9, 2, 0, 2, 7, 11 }, /* 209: 0, 4, 6, 7, */ { 5, 0, 4, 5, 11, 0, 5, 10, 11, 11, 3, 0 }, /* 46: 1, 2, 3, 5, */ { 5, 4, 0, 5, 0, 11, 5, 11, 10, 11, 0, 3 }, /* 198: 1, 2, 6, 7, */ { 9, 7, 5, 9, 2, 7, 9, 0, 2, 2, 11, 7 }, /* 178: 1, 4, 5, 7, */ { 0, 11, 8, 0, 5, 11, 0, 1, 5, 5, 6, 11 }, /* 156: 2, 3, 4, 7, */ { 8, 1, 3, 8, 6, 1, 8, 4, 6, 6, 10, 1 }, /* 116: 2, 4, 5, 6, */ { 1, 2, 6, 1, 6, 8, 1, 8, 9, 8, 6, 7 }, /* 232: 3, 5, 6, 7, */ { 2, 9, 10, 2, 7, 9, 2, 3, 7, 7, 4, 9 } }; return &tiling11[config][0]; }; // end of tiling11 //_____________________________________________________________________________ //_____________________________________________________________________________ /** * \brief test table for case 12 * 2 faces to test + eventually the interior * When the tests on both specified faces are positive : 4 middle triangles (1) * When the test on the first specified face is positive : 8 first triangles * When the test on the second specified face is positive : 8 next triangles * When the tests on both specified faces are negative : * - if the test on the interior is negative : 4 middle triangles * - if the test on the interior is positive : 8 last triangles * The support edge for the interior test is marked as the 4th column. * * For each of the case above, the specific triangulation of the edge * intersection points is given. * When a case is ambiguous, there is an auxiliary table that contains * the face number to test and the tiling table contains the specific * triangulations depending on the results * A minus sign means to invert the result of the test. */ //----------------------------------------------------------------------------- static const char Test12(unsigned char config, int u) { static const char test12[24][4] = { /* 135: 0, 1, 2, 7, */ { 4, 3, 7, 11 }, /* 75: 0, 1, 3, 6, */ { 3, 2, 7, 10 }, /* 83: 0, 1, 4, 6, */ { 2, 6, 7, 5 }, /* 163: 0, 1, 5, 7, */ { 6, 4, 7, 7 }, /* 45: 0, 2, 3, 5, */ { 2, 1, 7, 9 }, /* 53: 0, 2, 4, 5, */ { 5, 2, 7, 1 }, /* 149: 0, 2, 4, 7, */ { 5, 3, 7, 2 }, /* 101: 0, 2, 5, 6, */ { 5, 1, 7, 0 }, /* 197: 0, 2, 6, 7, */ { 5, 4, 7, 3 }, /* 89: 0, 3, 4, 6, */ { 6, 3, 7, 6 }, /* 169: 0, 3, 5, 7, */ { 1, 6, 7, 4 }, /* 225: 0, 5, 6, 7, */ { 1, 4, 7, 8 }, /* 30: 1, 2, 3, 4, */ { 4, 1, 7, 8 }, /* 86: 1, 2, 4, 6, */ { 6, 1, 7, 4 }, /* 166: 1, 2, 5, 7, */ { 3, 6, 7, 6 }, /* 58: 1, 3, 4, 5, */ { 4, 5, 7, 3 }, /* 154: 1, 3, 4, 7, */ { 1, 5, 7, 0 }, /* 106: 1, 3, 5, 6, */ { 3, 5, 7, 2 }, /* 202: 1, 3, 6, 7, */ { 2, 5, 7, 1 }, /* 210: 1, 4, 6, 7, */ { 1, 2, 7, 9 }, /* 92: 2, 3, 4, 6, */ { 4, 6, 7, 7 }, /* 172: 2, 3, 5, 7, */ { 6, 2, 7, 5 }, /* 180: 2, 4, 5, 7, */ { 2, 3, 7, 10 }, /* 120: 3, 4, 5, 6, */ { 3, 4, 7, 11 } }; return test12[config][u]; }; //_____________________________________________________________________________ /** * \brief tiling table for case 12.1.1 * For each of the case above, the specific triangulation of the edge * intersection points is given. * When a case is ambiguous, there is an auxiliary table that contains * the face number to test and the tiling table contains the specific * triangulations depending on the results * A minus sign means to invert the result of the test. */ //----------------------------------------------------------------------------- static const char* Tiling12_1_1(unsigned char config) { static const char tiling12_1_1[24][12] = { /* 135: 0, 1, 2, 7, */ { 7, 6, 11, 10, 3, 2, 3, 10, 8, 9, 8, 10 }, /* 75: 0, 1, 3, 6, */ { 6, 5, 10, 9, 2, 1, 2, 9, 11, 8, 11, 9 }, /* 83: 0, 1, 4, 6, */ { 10, 6, 5, 7, 9, 4, 9, 7, 1, 3, 1, 7 }, /* 163: 0, 1, 5, 7, */ { 7, 6, 11, 4, 8, 5, 3, 5, 8, 5, 3, 1 }, /* 45: 0, 2, 3, 5, */ { 5, 4, 9, 8, 1, 0, 1, 8, 10, 11, 10, 8 }, /* 53: 0, 2, 4, 5, */ { 1, 2, 10, 0, 9, 3, 5, 3, 9, 3, 5, 7 }, /* 149: 0, 2, 4, 7, */ { 10, 1, 2, 0, 11, 3, 11, 0, 6, 4, 6, 0 }, /* 101: 0, 2, 5, 6, */ { 8, 3, 0, 2, 9, 1, 9, 2, 4, 6, 4, 2 }, /* 197: 0, 2, 6, 7, */ { 3, 0, 8, 2, 11, 1, 7, 1, 11, 1, 7, 5 }, /* 89: 0, 3, 4, 6, */ { 6, 5, 10, 7, 11, 4, 2, 4, 11, 4, 2, 0 }, /* 169: 0, 3, 5, 7, */ { 9, 5, 4, 6, 8, 7, 8, 6, 0, 2, 0, 6 }, /* 225: 0, 5, 6, 7, */ { 8, 3, 0, 7, 4, 11, 9, 11, 4, 11, 9, 10 }, /* 30: 1, 2, 3, 4, */ { 4, 7, 8, 11, 0, 3, 0, 11, 9, 10, 9, 11 }, /* 86: 1, 2, 4, 6, */ { 4, 7, 8, 5, 9, 6, 0, 6, 9, 6, 0, 2 }, /* 166: 1, 2, 5, 7, */ { 11, 7, 6, 4, 10, 5, 10, 4, 2, 0, 2, 4 }, /* 58: 1, 3, 4, 5, */ { 11, 2, 3, 1, 8, 0, 8, 1, 7, 5, 7, 1 }, /* 154: 1, 3, 4, 7, */ { 0, 1, 9, 3, 8, 2, 4, 2, 8, 2, 4, 6 }, /* 106: 1, 3, 5, 6, */ { 2, 3, 11, 1, 10, 0, 6, 0, 10, 0, 6, 4 }, /* 202: 1, 3, 6, 7, */ { 9, 0, 1, 3, 10, 2, 10, 3, 5, 7, 5, 3 }, /* 210: 1, 4, 6, 7, */ { 9, 0, 1, 4, 5, 8, 10, 8, 5, 8, 10, 11 }, /* 92: 2, 3, 4, 6, */ { 8, 4, 7, 5, 11, 6, 11, 5, 3, 1, 3, 5 }, /* 172: 2, 3, 5, 7, */ { 5, 4, 9, 6, 10, 7, 1, 7, 10, 7, 1, 3 }, /* 180: 2, 4, 5, 7, */ { 10, 1, 2, 5, 6, 9, 11, 9, 6, 9, 11, 8 }, /* 120: 3, 4, 5, 6, */ { 11, 2, 3, 6, 7, 10, 8, 10, 7, 10, 8, 9 } }; return &tiling12_1_1[config][0]; }; // end of Tiling12_1_1 //_____________________________________________________________________________ /** * \brief tiling table for case 12.1.1 inverted * For each of the case above, the specific triangulation of the edge * intersection points is given. * When a case is ambiguous, there is an auxiliary table that contains * the face number to test and the tiling table contains the specific * triangulations depending on the results * A minus sign means to invert the result of the test. */ //----------------------------------------------------------------------------- static const char* Tiling12_1_1_(unsigned char config) { static const char tiling12_1_1_[24][12] = { /* 135: 0, 1, 2, 7, */ { 3, 2, 11, 10, 7, 6, 7, 10, 8, 9, 8, 10 }, /* 75: 0, 1, 3, 6, */ { 2, 1, 10, 9, 6, 5, 6, 9, 11, 8, 11, 9 }, /* 83: 0, 1, 4, 6, */ { 9, 4, 5, 7, 10, 6, 10, 7, 1, 3, 1, 7 }, /* 163: 0, 1, 5, 7, */ { 7, 4, 8, 6, 11, 5, 3, 5, 11, 5, 3, 1 }, /* 45: 0, 2, 3, 5, */ { 1, 0, 9, 8, 5, 4, 5, 8, 10, 11, 10, 8 }, /* 53: 0, 2, 4, 5, */ { 1, 0, 9, 2, 10, 3, 5, 3, 10, 3, 5, 7 }, /* 149: 0, 2, 4, 7, */ { 11, 3, 2, 0, 10, 1, 10, 0, 6, 4, 6, 0 }, /* 101: 0, 2, 5, 6, */ { 9, 1, 0, 2, 8, 3, 8, 2, 4, 6, 4, 2 }, /* 197: 0, 2, 6, 7, */ { 3, 2, 11, 0, 8, 1, 7, 1, 8, 1, 7, 5 }, /* 89: 0, 3, 4, 6, */ { 6, 7, 11, 5, 10, 4, 2, 4, 10, 4, 2, 0 }, /* 169: 0, 3, 5, 7, */ { 8, 7, 4, 6, 9, 5, 9, 6, 0, 2, 0, 6 }, /* 225: 0, 5, 6, 7, */ { 8, 7, 4, 3, 0, 11, 9, 11, 0, 11, 9, 10 }, /* 30: 1, 2, 3, 4, */ { 0, 3, 8, 11, 4, 7, 4, 11, 9, 10, 9, 11 }, /* 86: 1, 2, 4, 6, */ { 4, 5, 9, 7, 8, 6, 0, 6, 8, 6, 0, 2 }, /* 166: 1, 2, 5, 7, */ { 10, 5, 6, 4, 11, 7, 11, 4, 2, 0, 2, 4 }, /* 58: 1, 3, 4, 5, */ { 8, 0, 3, 1, 11, 2, 11, 1, 7, 5, 7, 1 }, /* 154: 1, 3, 4, 7, */ { 0, 3, 8, 1, 9, 2, 4, 2, 9, 2, 4, 6 }, /* 106: 1, 3, 5, 6, */ { 2, 1, 10, 3, 11, 0, 6, 0, 11, 0, 6, 4 }, /* 202: 1, 3, 6, 7, */ { 10, 2, 1, 3, 9, 0, 9, 3, 5, 7, 5, 3 }, /* 210: 1, 4, 6, 7, */ { 9, 4, 5, 0, 1, 8, 10, 8, 1, 8, 10, 11 }, /* 92: 2, 3, 4, 6, */ { 11, 6, 7, 5, 8, 4, 8, 5, 3, 1, 3, 5 }, /* 172: 2, 3, 5, 7, */ { 5, 6, 10, 4, 9, 7, 1, 7, 9, 7, 1, 3 }, /* 180: 2, 4, 5, 7, */ { 10, 5, 6, 1, 2, 9, 11, 9, 2, 9, 11, 8 }, /* 120: 3, 4, 5, 6, */ { 11, 6, 7, 2, 3, 10, 8, 10, 3, 10, 8, 9 } }; return &tiling12_1_1_[config][0]; }; // end of Tiling12_1_1_ //_____________________________________________________________________________ /** * \brief tiling table for case 12.1.2 * For each of the case above, the specific triangulation of the edge * intersection points is given. * When a case is ambiguous, there is an auxiliary table that contains * the face number to test and the tiling table contains the specific * triangulations depending on the results * A minus sign means to invert the result of the test. */ //----------------------------------------------------------------------------- static const char* Tiling12_1_2(unsigned char config) { static const char tiling12_1_2[24][24] = { /* 135: 0, 1, 2, 7, */ { 7, 3, 11, 3, 7, 8, 9, 8, 7, 6, 9, 7, 9, 6, 10, 2, 10, 6, 11, 2, 6, 2, 11, 3 }, /* 75: 0, 1, 3, 6, */ { 6, 2, 10, 2, 6, 11, 8, 11, 6, 5, 8, 6, 8, 5, 9, 1, 9, 5, 10, 1, 5, 1, 10, 2 }, /* 83: 0, 1, 4, 6, */ { 10, 9, 5, 9, 10, 1, 3, 1, 10, 6, 3, 10, 3, 6, 7, 4, 7, 6, 5, 4, 6, 4, 5, 9 }, /* 163: 0, 1, 5, 7, */ { 7, 8, 11, 3, 11, 8, 11, 3, 1, 11, 1, 6, 5, 6, 1, 6, 5, 4, 6, 4, 7, 8, 7, 4 }, /* 45: 0, 2, 3, 5, */ { 5, 1, 9, 1, 5, 10, 11, 10, 5, 4, 11, 5, 11, 4, 8, 0, 8, 4, 9, 0, 4, 0, 9, 1 }, /* 53: 0, 2, 4, 5, */ { 1, 9, 10, 5, 10, 9, 10, 5, 7, 10, 7, 2, 3, 2, 7, 2, 3, 0, 2, 0, 1, 9, 1, 0 }, /* 149: 0, 2, 4, 7, */ { 10, 11, 2, 11, 10, 6, 4, 6, 10, 1, 4, 10, 4, 1, 0, 3, 0, 1, 2, 3, 1, 3, 2, 11 }, /* 101: 0, 2, 5, 6, */ { 8, 9, 0, 9, 8, 4, 6, 4, 8, 3, 6, 8, 6, 3, 2, 1, 2, 3, 0, 1, 3, 1, 0, 9 }, /* 197: 0, 2, 6, 7, */ { 3, 11, 8, 7, 8, 11, 8, 7, 5, 8, 5, 0, 1, 0, 5, 0, 1, 2, 0, 2, 3, 11, 3, 2 }, /* 89: 0, 3, 4, 6, */ { 6, 11, 10, 2, 10, 11, 10, 2, 0, 10, 0, 5, 4, 5, 0, 5, 4, 7, 5, 7, 6, 11, 6, 7 }, /* 169: 0, 3, 5, 7, */ { 9, 8, 4, 8, 9, 0, 2, 0, 9, 5, 2, 9, 2, 5, 6, 7, 6, 5, 4, 7, 5, 7, 4, 8 }, /* 225: 0, 5, 6, 7, */ { 8, 4, 0, 9, 0, 4, 0, 9, 10, 0, 10, 3, 11, 3, 10, 3, 11, 7, 3, 7, 8, 4, 8, 7 }, /* 30: 1, 2, 3, 4, */ { 4, 0, 8, 0, 4, 9, 10, 9, 4, 7, 10, 4, 10, 7, 11, 3, 11, 7, 8, 3, 7, 3, 8, 0 }, /* 86: 1, 2, 4, 6, */ { 4, 9, 8, 0, 8, 9, 8, 0, 2, 8, 2, 7, 6, 7, 2, 7, 6, 5, 7, 5, 4, 9, 4, 5 }, /* 166: 1, 2, 5, 7, */ { 11, 10, 6, 10, 11, 2, 0, 2, 11, 7, 0, 11, 0, 7, 4, 5, 4, 7, 6, 5, 7, 5, 6, 10 }, /* 58: 1, 3, 4, 5, */ { 11, 8, 3, 8, 11, 7, 5, 7, 11, 2, 5, 11, 5, 2, 1, 0, 1, 2, 3, 0, 2, 0, 3, 8 }, /* 154: 1, 3, 4, 7, */ { 0, 8, 9, 4, 9, 8, 9, 4, 6, 9, 6, 1, 2, 1, 6, 1, 2, 3, 1, 3, 0, 8, 0, 3 }, /* 106: 1, 3, 5, 6, */ { 2, 10, 11, 6, 11, 10, 11, 6, 4, 11, 4, 3, 0, 3, 4, 3, 0, 1, 3, 1, 2, 10, 2, 1 }, /* 202: 1, 3, 6, 7, */ { 9, 10, 1, 10, 9, 5, 7, 5, 9, 0, 7, 9, 7, 0, 3, 2, 3, 0, 1, 2, 0, 2, 1, 10 }, /* 210: 1, 4, 6, 7, */ { 9, 5, 1, 10, 1, 5, 1, 10, 11, 1, 11, 0, 8, 0, 11, 0, 8, 4, 0, 4, 9, 5, 9, 4 }, /* 92: 2, 3, 4, 6, */ { 8, 11, 7, 11, 8, 3, 1, 3, 8, 4, 1, 8, 1, 4, 5, 6, 5, 4, 7, 6, 4, 6, 7, 11 }, /* 172: 2, 3, 5, 7, */ { 5, 10, 9, 1, 9, 10, 9, 1, 3, 9, 3, 4, 7, 4, 3, 4, 7, 6, 4, 6, 5, 10, 5, 6 }, /* 180: 2, 4, 5, 7, */ { 10, 6, 2, 11, 2, 6, 2, 11, 8, 2, 8, 1, 9, 1, 8, 1, 9, 5, 1, 5, 10, 6, 10, 5 }, /* 120: 3, 4, 5, 6, */ { 11, 7, 3, 8, 3, 7, 3, 8, 9, 3, 9, 2, 10, 2, 9, 2, 10, 6, 2, 6, 11, 7, 11, 6 } }; return &tiling12_1_2[config][0]; }; // end of Tiling12_1_2 //_____________________________________________________________________________ /** * \brief tiling table for case 12.2 * For each of the case above, the specific triangulation of the edge * intersection points is given. * When a case is ambiguous, there is an auxiliary table that contains * the face number to test and the tiling table contains the specific * triangulations depending on the results * A minus sign means to invert the result of the test. */ //----------------------------------------------------------------------------- static const char* Tiling12_2(unsigned char config) { static const char tiling12_2[24][24] = { /* 135: 0, 1, 2, 7, */ { 9, 8, 12, 10, 9, 12, 2, 10, 12, 3, 2, 12, 11, 3, 12, 6, 11, 12, 7, 6, 12, 8, 7, 12 }, /* 75: 0, 1, 3, 6, */ { 8, 11, 12, 9, 8, 12, 1, 9, 12, 2, 1, 12, 10, 2, 12, 5, 10, 12, 6, 5, 12, 11, 6, 12 }, /* 83: 0, 1, 4, 6, */ { 3, 1, 12, 7, 3, 12, 4, 7, 12, 9, 4, 12, 5, 9, 12, 6, 5, 12, 10, 6, 12, 1, 10, 12 }, /* 163: 0, 1, 5, 7, */ { 12, 3, 1, 12, 1, 5, 12, 5, 6, 12, 6, 11, 12, 11, 7, 12, 7, 4, 12, 4, 8, 12, 8, 3 }, /* 45: 0, 2, 3, 5, */ { 11, 10, 12, 8, 11, 12, 0, 8, 12, 1, 0, 12, 9, 1, 12, 4, 9, 12, 5, 4, 12, 10, 5, 12 }, /* 53: 0, 2, 4, 5, */ { 12, 5, 7, 12, 7, 3, 12, 3, 2, 12, 2, 10, 12, 10, 1, 12, 1, 0, 12, 0, 9, 12, 9, 5 }, /* 149: 0, 2, 4, 7, */ { 4, 6, 12, 0, 4, 12, 1, 0, 12, 10, 1, 12, 2, 10, 12, 3, 2, 12, 11, 3, 12, 6, 11, 12 }, /* 101: 0, 2, 5, 6, */ { 6, 4, 12, 2, 6, 12, 3, 2, 12, 8, 3, 12, 0, 8, 12, 1, 0, 12, 9, 1, 12, 4, 9, 12 }, /* 197: 0, 2, 6, 7, */ { 12, 7, 5, 12, 5, 1, 12, 1, 0, 12, 0, 8, 12, 8, 3, 12, 3, 2, 12, 2, 11, 12, 11, 7 }, /* 89: 0, 3, 4, 6, */ { 12, 2, 0, 12, 0, 4, 12, 4, 5, 12, 5, 10, 12, 10, 6, 12, 6, 7, 12, 7, 11, 12, 11, 2 }, /* 169: 0, 3, 5, 7, */ { 2, 0, 12, 6, 2, 12, 7, 6, 12, 8, 7, 12, 4, 8, 12, 5, 4, 12, 9, 5, 12, 0, 9, 12 }, /* 225: 0, 5, 6, 7, */ { 12, 9, 10, 12, 10, 11, 12, 11, 7, 12, 7, 4, 12, 4, 8, 12, 8, 3, 12, 3, 0, 12, 0, 9 }, /* 30: 1, 2, 3, 4, */ { 10, 9, 12, 11, 10, 12, 7, 11, 12, 4, 7, 12, 8, 4, 12, 3, 8, 12, 0, 3, 12, 9, 0, 12 }, /* 86: 1, 2, 4, 6, */ { 12, 0, 2, 12, 2, 6, 12, 6, 7, 12, 7, 8, 12, 8, 4, 12, 4, 5, 12, 5, 9, 12, 9, 0 }, /* 166: 1, 2, 5, 7, */ { 0, 2, 12, 4, 0, 12, 5, 4, 12, 10, 5, 12, 6, 10, 12, 7, 6, 12, 11, 7, 12, 2, 11, 12 }, /* 58: 1, 3, 4, 5, */ { 5, 7, 12, 1, 5, 12, 0, 1, 12, 8, 0, 12, 3, 8, 12, 2, 3, 12, 11, 2, 12, 7, 11, 12 }, /* 154: 1, 3, 4, 7, */ { 12, 4, 6, 12, 6, 2, 12, 2, 3, 12, 3, 8, 12, 8, 0, 12, 0, 1, 12, 1, 9, 12, 9, 4 }, /* 106: 1, 3, 5, 6, */ { 12, 6, 4, 12, 4, 0, 12, 0, 1, 12, 1, 10, 12, 10, 2, 12, 2, 3, 12, 3, 11, 12, 11, 6 }, /* 202: 1, 3, 6, 7, */ { 7, 5, 12, 3, 7, 12, 2, 3, 12, 10, 2, 12, 1, 10, 12, 0, 1, 12, 9, 0, 12, 5, 9, 12 }, /* 210: 1, 4, 6, 7, */ { 12, 10, 11, 12, 11, 8, 12, 8, 0, 12, 0, 1, 12, 1, 9, 12, 9, 4, 12, 4, 5, 12, 5, 10 }, /* 92: 2, 3, 4, 6, */ { 1, 3, 12, 5, 1, 12, 6, 5, 12, 11, 6, 12, 7, 11, 12, 4, 7, 12, 8, 4, 12, 3, 8, 12 }, /* 172: 2, 3, 5, 7, */ { 12, 1, 3, 12, 3, 7, 12, 7, 4, 12, 4, 9, 12, 9, 5, 12, 5, 6, 12, 6, 10, 12, 10, 1 }, /* 180: 2, 4, 5, 7, */ { 12, 11, 8, 12, 8, 9, 12, 9, 1, 12, 1, 2, 12, 2, 10, 12, 10, 5, 12, 5, 6, 12, 6, 11 }, /* 120: 3, 4, 5, 6, */ { 12, 8, 9, 12, 9, 10, 12, 10, 2, 12, 2, 3, 12, 3, 11, 12, 11, 6, 12, 6, 7, 12, 7, 8 } }; return &tiling12_2[config][0]; }; // end of Tiling12_2 //_____________________________________________________________________________ /** * \brief tiling table for case 12.2 inverted * For each of the case above, the specific triangulation of the edge * intersection points is given. * When a case is ambiguous, there is an auxiliary table that contains * the face number to test and the tiling table contains the specific * triangulations depending on the results * A minus sign means to invert the result of the test. */ //----------------------------------------------------------------------------- static const char* Tiling12_2_(unsigned char config) { static const char tiling12_2_[24][24] = { /* 135: 0, 1, 2, 7, */ { 12, 2, 11, 12, 11, 7, 12, 7, 6, 12, 6, 10, 12, 10, 9, 12, 9, 8, 12, 8, 3, 12, 3, 2 }, /* 75: 0, 1, 3, 6, */ { 12, 1, 10, 12, 10, 6, 12, 6, 5, 12, 5, 9, 12, 9, 8, 12, 8, 11, 12, 11, 2, 12, 2, 1 }, /* 83: 0, 1, 4, 6, */ { 12, 4, 5, 12, 5, 10, 12, 10, 6, 12, 6, 7, 12, 7, 3, 12, 3, 1, 12, 1, 9, 12, 9, 4 }, /* 163: 0, 1, 5, 7, */ { 7, 6, 12, 8, 7, 12, 4, 8, 12, 5, 4, 12, 1, 5, 12, 3, 1, 12, 11, 3, 12, 6, 11, 12 }, /* 45: 0, 2, 3, 5, */ { 12, 0, 9, 12, 9, 5, 12, 5, 4, 12, 4, 8, 12, 8, 11, 12, 11, 10, 12, 10, 1, 12, 1, 0 }, /* 53: 0, 2, 4, 5, */ { 1, 2, 12, 9, 1, 12, 0, 9, 12, 3, 0, 12, 7, 3, 12, 5, 7, 12, 10, 5, 12, 2, 10, 12 }, /* 149: 0, 2, 4, 7, */ { 12, 1, 2, 12, 2, 11, 12, 11, 3, 12, 3, 0, 12, 0, 4, 12, 4, 6, 12, 6, 10, 12, 10, 1 }, /* 101: 0, 2, 5, 6, */ { 12, 3, 0, 12, 0, 9, 12, 9, 1, 12, 1, 2, 12, 2, 6, 12, 6, 4, 12, 4, 8, 12, 8, 3 }, /* 197: 0, 2, 6, 7, */ { 3, 0, 12, 11, 3, 12, 2, 11, 12, 1, 2, 12, 5, 1, 12, 7, 5, 12, 8, 7, 12, 0, 8, 12 }, /* 89: 0, 3, 4, 6, */ { 6, 5, 12, 11, 6, 12, 7, 11, 12, 4, 7, 12, 0, 4, 12, 2, 0, 12, 10, 2, 12, 5, 10, 12 }, /* 169: 0, 3, 5, 7, */ { 12, 7, 4, 12, 4, 9, 12, 9, 5, 12, 5, 6, 12, 6, 2, 12, 2, 0, 12, 0, 8, 12, 8, 7 }, /* 225: 0, 5, 6, 7, */ { 8, 7, 12, 0, 8, 12, 3, 0, 12, 11, 3, 12, 10, 11, 12, 9, 10, 12, 4, 9, 12, 7, 4, 12 }, /* 30: 1, 2, 3, 4, */ { 12, 7, 8, 12, 8, 0, 12, 0, 3, 12, 3, 11, 12, 11, 10, 12, 10, 9, 12, 9, 4, 12, 4, 7 }, /* 86: 1, 2, 4, 6, */ { 4, 7, 12, 9, 4, 12, 5, 9, 12, 6, 5, 12, 2, 6, 12, 0, 2, 12, 8, 0, 12, 7, 8, 12 }, /* 166: 1, 2, 5, 7, */ { 12, 5, 6, 12, 6, 11, 12, 11, 7, 12, 7, 4, 12, 4, 0, 12, 0, 2, 12, 2, 10, 12, 10, 5 }, /* 58: 1, 3, 4, 5, */ { 12, 0, 3, 12, 3, 11, 12, 11, 2, 12, 2, 1, 12, 1, 5, 12, 5, 7, 12, 7, 8, 12, 8, 0 }, /* 154: 1, 3, 4, 7, */ { 0, 3, 12, 9, 0, 12, 1, 9, 12, 2, 1, 12, 6, 2, 12, 4, 6, 12, 8, 4, 12, 3, 8, 12 }, /* 106: 1, 3, 5, 6, */ { 2, 1, 12, 11, 2, 12, 3, 11, 12, 0, 3, 12, 4, 0, 12, 6, 4, 12, 10, 6, 12, 1, 10, 12 }, /* 202: 1, 3, 6, 7, */ { 12, 2, 1, 12, 1, 9, 12, 9, 0, 12, 0, 3, 12, 3, 7, 12, 7, 5, 12, 5, 10, 12, 10, 2 }, /* 210: 1, 4, 6, 7, */ { 9, 0, 12, 5, 9, 12, 4, 5, 12, 8, 4, 12, 11, 8, 12, 10, 11, 12, 1, 10, 12, 0, 1, 12 }, /* 92: 2, 3, 4, 6, */ { 12, 6, 7, 12, 7, 8, 12, 8, 4, 12, 4, 5, 12, 5, 1, 12, 1, 3, 12, 3, 11, 12, 11, 6 }, /* 172: 2, 3, 5, 7, */ { 5, 4, 12, 10, 5, 12, 6, 10, 12, 7, 6, 12, 3, 7, 12, 1, 3, 12, 9, 1, 12, 4, 9, 12 }, /* 180: 2, 4, 5, 7, */ { 10, 1, 12, 6, 10, 12, 5, 6, 12, 9, 5, 12, 8, 9, 12, 11, 8, 12, 2, 11, 12, 1, 2, 12 }, /* 120: 3, 4, 5, 6, */ { 11, 2, 12, 7, 11, 12, 6, 7, 12, 10, 6, 12, 9, 10, 12, 8, 9, 12, 3, 8, 12, 2, 3, 12 } }; return &tiling12_2_[config][0]; }; // end of Tiling12_2_ //_____________________________________________________________________________ //_____________________________________________________________________________ /** * \brief test table for case 13 * All faces are to be tested * * For each of the case above, the specific triangulation of the edge * intersection points is given. * When a case is ambiguous, there is an auxiliary table that contains * the face number to test and the tiling table contains the specific * triangulations depending on the results * A minus sign means to invert the result of the test. */ //----------------------------------------------------------------------------- /* 13: face test */ static const char Test13(unsigned char config, int u) { static const char test13[2][7] = { /* 165: 0, 2, 5, 7, */ { 1,2,3,4,5,6,7 }, /* 90: 1, 3, 4, 6, */ { 2,3,4,1,5,6,7 }, }; return test13[config][u]; }; // end of Test13 //_____________________________________________________________________________ /** * \brief subconfiguration table for case 13 * Hard-coded tests for the subconfiguration determination * * For each of the case above, the specific triangulation of the edge * intersection points is given. * When a case is ambiguous, there is an auxiliary table that contains * the face number to test and the tiling table contains the specific * triangulations depending on the results * A minus sign means to invert the result of the test. */ //----------------------------------------------------------------------------- /* 13: sub configs */ static const char Subconfig13(unsigned char config) { static const char subconfig13[64] = { /* 0: 0,0,0,0,0,0 */ 0, /* 1: 1,0,0,0,0,0 */ 1, /* 2: 0,1,0,0,0,0 */ 2, /* 3: 1,1,0,0,0,0 */ 7, /* 4: 0,0,1,0,0,0 */ 3, /* 5: 1,0,1,0,0,0 */ -1, /* 6: 0,1,1,0,0,0 */ 11, /* 7: 1,1,1,0,0,0 */ -1, /* 8: 0,0,0,1,0,0 */ 4, /* 9: 1,0,0,1,0,0 */ 8, /* 10: 0,1,0,1,0,0 */ -1, /* 11: 1,1,0,1,0,0 */ -1, /* 12: 0,0,1,1,0,0 */ 14, /* 13: 1,0,1,1,0,0 */ -1, /* 14: 0,1,1,1,0,0 */ -1, /* 15: 1,1,1,1,0,0 */ -1, /* 16: 0,0,0,0,1,0 */ 5, /* 17: 1,0,0,0,1,0 */ 9, /* 18: 0,1,0,0,1,0 */ 12, /* 19: 1,1,0,0,1,0 */ 23, /* 20: 0,0,1,0,1,0 */ 15, /* 21: 1,0,1,0,1,0 */ -1, /* 22: 0,1,1,0,1,0 */ 21, /* 23: 1,1,1,0,1,0 */ 38, /* 24: 0,0,0,1,1,0 */ 17, /* 25: 1,0,0,1,1,0 */ 20, /* 26: 0,1,0,1,1,0 */ -1, /* 27: 1,1,0,1,1,0 */ 36, /* 28: 0,0,1,1,1,0 */ 26, /* 29: 1,0,1,1,1,0 */ 33, /* 30: 0,1,1,1,1,0 */ 30, /* 31: 1,1,1,1,1,0 */ 44, /* 32: 0,0,0,0,0,1 */ 6, /* 33: 1,0,0,0,0,1 */ 10, /* 34: 0,1,0,0,0,1 */ 13, /* 35: 1,1,0,0,0,1 */ 19, /* 36: 0,0,1,0,0,1 */ 16, /* 37: 1,0,1,0,0,1 */ -1, /* 38: 0,1,1,0,0,1 */ 25, /* 39: 1,1,1,0,0,1 */ 37, /* 40: 0,0,0,1,0,1 */ 18, /* 41: 1,0,0,1,0,1 */ 24, /* 42: 0,1,0,1,0,1 */ -1, /* 43: 1,1,0,1,0,1 */ 35, /* 44: 0,0,1,1,0,1 */ 22, /* 45: 1,0,1,1,0,1 */ 32, /* 46: 0,1,1,1,0,1 */ 29, /* 47: 1,1,1,1,0,1 */ 43, /* 48: 0,0,0,0,1,1 */ -1, /* 49: 1,0,0,0,1,1 */ -1, /* 50: 0,1,0,0,1,1 */ -1, /* 51: 1,1,0,0,1,1 */ 34, /* 52: 0,0,1,0,1,1 */ -1, /* 53: 1,0,1,0,1,1 */ -1, /* 54: 0,1,1,0,1,1 */ 28, /* 55: 1,1,1,0,1,1 */ 42, /* 56: 0,0,0,1,1,1 */ -1, /* 57: 1,0,0,1,1,1 */ 31, /* 58: 0,1,0,1,1,1 */ -1, /* 59: 1,1,0,1,1,1 */ 41, /* 60: 0,0,1,1,1,1 */ 27, /* 61: 1,0,1,1,1,1 */ 40, /* 62: 0,1,1,1,1,1 */ 39, /* 63: 1,1,1,1,1,1 */ 45, }; return subconfig13[config]; }; // end of Subconfig13 //_____________________________________________________________________________ /** * \brief tiling table for case 13.1 * For each of the case above, the specific triangulation of the edge * intersection points is given. * When a case is ambiguous, there is an auxiliary table that contains * the face number to test and the tiling table contains the specific * triangulations depending on the results * A minus sign means to invert the result of the test. */ //----------------------------------------------------------------------------- /* 13.1 */ static const char* Tiling13_1(unsigned char config) { static const char tiling13_1[2][12] = { /* 165: 0, 2, 5, 7, */ { 11, 7, 6, 1, 2, 10, 8, 3, 0, 9, 5, 4 }, /* 90: 1, 3, 4, 6, */ { 8, 4, 7, 2, 3, 11, 9, 0, 1, 10, 6, 5 } }; return &tiling13_1[config][0]; }; // end of Tiling13_1 //_____________________________________________________________________________ /** * \brief tiling table for case 13.1 inverted * For each of the case above, the specific triangulation of the edge * intersection points is given. * When a case is ambiguous, there is an auxiliary table that contains * the face number to test and the tiling table contains the specific * triangulations depending on the results * A minus sign means to invert the result of the test. */ //----------------------------------------------------------------------------- /* 13.1 */ static const char* Tiling13_1_(unsigned char config) { static const char tiling13_1_[2][12] = { /* 165: 0, 2, 5, 7, */ { 7, 4, 8, 11, 3, 2, 1, 0, 9, 5, 6, 10 }, /* 90: 1, 3, 4, 6, */ { 6, 7, 11, 10, 2, 1, 0, 3, 8, 4, 5, 9 } }; return &tiling13_1_[config][0]; }; // end of Tiling13_1_ //_____________________________________________________________________________ /** * \brief tiling table for case 13.2 * For each of the case above, the specific triangulation of the edge * intersection points is given. * When a case is ambiguous, there is an auxiliary table that contains * the face number to test and the tiling table contains the specific * triangulations depending on the results * A minus sign means to invert the result of the test. */ //----------------------------------------------------------------------------- /* 13.2 */ static const char* Tiling13_2(unsigned char config, unsigned char u) { static const char tiling13_2[2][6][18] = { /* 165: 0, 2, 5, 7, */ { /* 1 */ { 1, 2, 10, 11, 7, 6, 3, 4, 8, 4, 3, 5, 0, 5, 3, 5, 0, 9 }, /* 2 */ { 8, 3, 0, 11, 7, 6, 9, 1, 4, 2, 4, 1, 4, 2, 5, 10, 5, 2 }, /* 3 */ { 9, 5, 4, 8, 3, 0, 1, 6, 10, 6, 1, 7, 2, 7, 1, 7, 2, 11 }, /* 4 */ { 9, 5, 4, 1, 2, 10, 11, 3, 6, 0, 6, 3, 6, 0, 7, 8, 7, 0 }, /* 5 */ { 9, 5, 4, 11, 7, 6, 0, 10, 1, 10, 0, 8, 10, 8, 2, 3, 2, 8 }, /* 6 */ { 1, 2, 10, 3, 0, 8, 4, 9, 7, 11, 7, 9, 5, 11, 9, 11, 5, 6 } }, /* 90: 1, 3, 4, 6, */ { /* 1 */ { 2, 3, 11, 8, 4, 7, 0, 5, 9, 5, 0, 6, 1, 6, 0, 6, 1, 10 }, /* 2 */ { 9, 0, 1, 8, 4, 7, 10, 2, 5, 3, 5, 2, 5, 3, 6, 11, 6, 3 }, /* 3 */ { 6, 5, 10, 9, 0, 1, 2, 7, 11, 7, 2, 4, 3, 4, 2, 4, 3, 8 }, /* 4 */ { 6, 5, 10, 2, 3, 11, 8, 0, 7, 1, 7, 0, 7, 1, 4, 9, 4, 1 }, /* 5 */ { 6, 5, 10, 8, 4, 7, 1, 11, 2, 11, 1, 9, 11, 9, 3, 0, 3, 9 }, /* 6 */ { 2, 3, 11, 0, 1, 9, 5, 10, 4, 8, 4, 10, 6, 8, 10, 8, 6, 7 } } }; return &tiling13_2[config][u][0]; }; // end of Tiling13_2 //_____________________________________________________________________________ /** * \brief tiling table for case 13.2 inverted * For each of the case above, the specific triangulation of the edge * intersection points is given. * When a case is ambiguous, there is an auxiliary table that contains * the face number to test and the tiling table contains the specific * triangulations depending on the results * A minus sign means to invert the result of the test. */ //----------------------------------------------------------------------------- /* 13.2 */ static const char* Tiling13_2_(unsigned char config, unsigned char u) { static const char tiling13_2_[2][6][18] = { /* 165: 0, 2, 5, 7, */ { /* 1 */ { 10, 5, 6, 11, 3, 2, 7, 0, 8, 0, 7, 1, 4, 1, 7, 1, 4, 9 }, /* 2 */ { 11, 3, 2, 7, 4, 8, 9, 5, 0, 6, 0, 5, 0, 6, 1, 10, 1, 6 }, /* 3 */ { 1, 0, 9, 7, 4, 8, 5, 2, 10, 2, 5, 3, 6, 3, 5, 3, 6, 11 }, /* 4 */ { 10, 5, 6, 1, 0, 9, 11, 7, 2, 4, 2, 7, 2, 4, 3, 8, 3, 4 }, /* 5 */ { 10, 5, 6, 7, 4, 8, 2, 11, 1, 9, 1, 11, 3, 9, 11, 9, 3, 0 }, /* 6 */ { 11, 3, 2, 9, 1, 0, 4, 10, 5, 10, 4, 8, 10, 8, 6, 7, 6, 8 } }, /* 90: 1, 3, 4, 6, */ { /* 1 */ { 6, 7, 11, 8, 0, 3, 4, 1, 9, 1, 4, 2, 5, 2, 4, 2, 5, 10 }, /* 2 */ { 8, 0, 3, 4, 5, 9, 10, 6, 1, 7, 1, 6, 1, 7, 2, 11, 2, 7 }, /* 3 */ { 2, 1, 10, 4, 5, 9, 6, 3, 11, 3, 6, 0, 7, 0, 6, 0, 7, 8 }, /* 4 */ { 6, 7, 11, 2, 1, 10, 8, 4, 3, 5, 3, 4, 3, 5, 0, 9, 0, 5 }, /* 5 */ { 6, 7, 11, 4, 5, 9, 3, 8, 2, 10, 2, 8, 0, 10, 8, 10, 0, 1 }, /* 6 */ { 8, 0, 3, 10, 2, 1, 5, 11, 6, 11, 5, 9, 11, 9, 7, 4, 7, 9 } } }; return &tiling13_2_[config][u][0]; }; // end of Tiling13_2_ //_____________________________________________________________________________ /** * \brief tiling table for case 13.3 * For each of the case above, the specific triangulation of the edge * intersection points is given. * When a case is ambiguous, there is an auxiliary table that contains * the face number to test and the tiling table contains the specific * triangulations depending on the results * A minus sign means to invert the result of the test. */ //----------------------------------------------------------------------------- /* 13.3 */ static const char* Tiling13_3(unsigned char config, unsigned int u) { static const char tiling13_3[2][12][30] = { /* 165: 0, 2, 5, 7, */ { /* 1,2 */ { 11, 7, 6, 12, 2, 10, 12, 10, 5, 12, 5, 4, 12, 4, 8, 12, 8, 3, 12, 3, 0, 12, 0, 9, 12, 9, 1, 12, 1, 2 }, /* 1,4 */ { 1, 2, 10, 9, 5, 12, 0, 9, 12, 3, 0, 12, 11, 3, 12, 6, 11, 12, 7, 6, 12, 8, 7, 12, 4, 8, 12, 5, 4, 12 }, /* 1,5 */ { 11, 7, 6, 12, 5, 4, 12, 4, 8, 12, 8, 3, 12, 3, 2, 12, 2, 10, 12, 10, 1, 12, 1, 0, 12, 0, 9, 12, 9, 5 }, /* 1,6 */ { 1, 2, 10, 12, 3, 0, 12, 0, 9, 12, 9, 5, 12, 5, 6, 12, 6, 11, 12, 11, 7, 12, 7, 4, 12, 4, 8, 12, 8, 3 }, /* 2,3 */ { 8, 3, 0, 11, 7, 12, 2, 11, 12, 1, 2, 12, 9, 1, 12, 4, 9, 12, 5, 4, 12, 10, 5, 12, 6, 10, 12, 7, 6, 12 }, /* 2,5 */ { 11, 7, 6, 5, 4, 12, 10, 5, 12, 2, 10, 12, 3, 2, 12, 8, 3, 12, 0, 8, 12, 1, 0, 12, 9, 1, 12, 4, 9, 12 }, /* 2,6 */ { 8, 3, 0, 1, 2, 12, 9, 1, 12, 4, 9, 12, 7, 4, 12, 11, 7, 12, 6, 11, 12, 5, 6, 12, 10, 5, 12, 2, 10, 12 }, /* 3,4 */ { 9, 5, 4, 12, 0, 8, 12, 8, 7, 12, 7, 6, 12, 6, 10, 12, 10, 1, 12, 1, 2, 12, 2, 11, 12, 11, 3, 12, 3, 0 }, /* 3,5 */ { 9, 5, 4, 12, 7, 6, 12, 6, 10, 12, 10, 1, 12, 1, 0, 12, 0, 8, 12, 8, 3, 12, 3, 2, 12, 2, 11, 12, 11, 7 }, /* 3,6 */ { 8, 3, 0, 12, 1, 2, 12, 2, 11, 12, 11, 7, 12, 7, 4, 12, 4, 9, 12, 9, 5, 12, 5, 6, 12, 6, 10, 12, 10, 1 }, /* 4,5 */ { 9, 5, 4, 7, 6, 12, 8, 7, 12, 0, 8, 12, 1, 0, 12, 10, 1, 12, 2, 10, 12, 3, 2, 12, 11, 3, 12, 6, 11, 12 }, /* 4,6 */ { 1, 2, 10, 3, 0, 12, 11, 3, 12, 6, 11, 12, 5, 6, 12, 9, 5, 12, 4, 9, 12, 7, 4, 12, 8, 7, 12, 0, 8, 12 } }, /* 90: 1, 3, 4, 6, */ { /* 1,2 */ { 8, 4, 7, 12, 3, 11, 12, 11, 6, 12, 6, 5, 12, 5, 9, 12, 9, 0, 12, 0, 1, 12, 1, 10, 12, 10, 2, 12, 2, 3 }, /* 1,4 */ { 2, 3, 11, 10, 6, 12, 1, 10, 12, 0, 1, 12, 8, 0, 12, 7, 8, 12, 4, 7, 12, 9, 4, 12, 5, 9, 12, 6, 5, 12 }, /* 1,5 */ { 8, 4, 7, 12, 6, 5, 12, 5, 9, 12, 9, 0, 12, 0, 3, 12, 3, 11, 12, 11, 2, 12, 2, 1, 12, 1, 10, 12, 10, 6 }, /* 1,6 */ { 2, 3, 11, 12, 0, 1, 12, 1, 10, 12, 10, 6, 12, 6, 7, 12, 7, 8, 12, 8, 4, 12, 4, 5, 12, 5, 9, 12, 9, 0 }, /* 2,3 */ { 0, 1, 9, 8, 4, 12, 3, 8, 12, 2, 3, 12, 10, 2, 12, 5, 10, 12, 6, 5, 12, 11, 6, 12, 7, 11, 12, 4, 7, 12 }, /* 2,5 */ { 8, 4, 7, 6, 5, 12, 11, 6, 12, 3, 11, 12, 0, 3, 12, 9, 0, 12, 1, 9, 12, 2, 1, 12, 10, 2, 12, 5, 10, 12 }, /* 2,6 */ { 9, 0, 1, 2, 3, 12, 10, 2, 12, 5, 10, 12, 4, 5, 12, 8, 4, 12, 7, 8, 12, 6, 7, 12, 11, 6, 12, 3, 11, 12 }, /* 3,4 */ { 6, 5, 10, 12, 1, 9, 12, 9, 4, 12, 4, 7, 12, 7, 11, 12, 11, 2, 12, 2, 3, 12, 3, 8, 12, 8, 0, 12, 0, 1 }, /* 3,5 */ { 6, 5, 10, 12, 4, 7, 12, 7, 11, 12, 11, 2, 12, 2, 1, 12, 1, 9, 12, 9, 0, 12, 0, 3, 12, 3, 8, 12, 8, 4 }, /* 3,6 */ { 9, 0, 1, 12, 2, 3, 12, 3, 8, 12, 8, 4, 12, 4, 5, 12, 5, 10, 12, 10, 6, 12, 6, 7, 12, 7, 11, 12, 11, 2 }, /* 4,5 */ { 6, 5, 10, 4, 7, 12, 9, 4, 12, 1, 9, 12, 2, 1, 12, 11, 2, 12, 3, 11, 12, 0, 3, 12, 8, 0, 12, 7, 8, 12 }, /* 4,6 */ { 2, 3, 11, 0, 1, 12, 8, 0, 12, 7, 8, 12, 6, 7, 12, 10, 6, 12, 5, 10, 12, 4, 5, 12, 9, 4, 12, 1, 9, 12 } } }; return &tiling13_3[config][u][0]; }; // end of Tiling13_3 //_____________________________________________________________________________ /** * \brief tiling table for case 13.3, inverted * For each of the case above, the specific triangulation of the edge * intersection points is given. * When a case is ambiguous, there is an auxiliary table that contains * the face number to test and the tiling table contains the specific * triangulations depending on the results * A minus sign means to invert the result of the test. */ //----------------------------------------------------------------------------- /* 13.3 */ static const char* Tiling13_3_(unsigned char config, unsigned char u) { static const char tiling13_3_[2][12][30] = { /* 165: 0, 2, 5, 7, */ { /* 1,2 */ { 3, 2, 11, 8, 7, 12, 0, 8, 12, 1, 0, 12, 10, 1, 12, 6, 10, 12, 5, 6, 12, 9, 5, 12, 4, 9, 12, 7, 4, 12 }, /* 1,4 */ { 5, 6, 10, 12, 2, 11, 12, 11, 7, 12, 7, 4, 12, 4, 9, 12, 9, 1, 12, 1, 0, 12, 0, 8, 12, 8, 3, 12, 3, 2 }, /* 1,5 */ { 10, 5, 6, 12, 7, 4, 12, 4, 9, 12, 9, 1, 12, 1, 2, 12, 2, 11, 12, 11, 3, 12, 3, 0, 12, 0, 8, 12, 8, 7 }, /* 1,6 */ { 11, 3, 2, 12, 1, 0, 12, 0, 8, 12, 8, 7, 12, 7, 6, 12, 6, 10, 12, 10, 5, 12, 5, 4, 12, 4, 9, 12, 9, 1 }, /* 2,3 */ { 7, 4, 8, 11, 3, 12, 6, 11, 12, 5, 6, 12, 9, 5, 12, 0, 9, 12, 1, 0, 12, 10, 1, 12, 2, 10, 12, 3, 2, 12 }, /* 2,5 */ { 7, 4, 8, 5, 6, 12, 9, 5, 12, 0, 9, 12, 3, 0, 12, 11, 3, 12, 2, 11, 12, 1, 2, 12, 10, 1, 12, 6, 10, 12 }, /* 2,6 */ { 11, 3, 2, 1, 0, 12, 10, 1, 12, 6, 10, 12, 7, 6, 12, 8, 7, 12, 4, 8, 12, 5, 4, 12, 9, 5, 12, 0, 9, 12 }, /* 3,4 */ { 1, 0, 9, 12, 4, 8, 12, 8, 3, 12, 3, 2, 12, 2, 10, 12, 10, 5, 12, 5, 6, 12, 6, 11, 12, 11, 7, 12, 7, 4 }, /* 3,5 */ { 7, 4, 8, 12, 5, 6, 12, 6, 11, 12, 11, 3, 12, 3, 0, 12, 0, 9, 12, 9, 1, 12, 1, 2, 12, 2, 10, 12, 10, 5 }, /* 3,6 */ { 1, 0, 9, 12, 3, 2, 12, 2, 10, 12, 10, 5, 12, 5, 4, 12, 4, 8, 12, 8, 7, 12, 7, 6, 12, 6, 11, 12, 11, 3 }, /* 4,5 */ { 10, 5, 6, 7, 4, 12, 11, 7, 12, 2, 11, 12, 1, 2, 12, 9, 1, 12, 0, 9, 12, 3, 0, 12, 8, 3, 12, 4, 8, 12 }, /* 4,6 */ { 9, 1, 0, 3, 2, 12, 8, 3, 12, 4, 8, 12, 5, 4, 12, 10, 5, 12, 6, 10, 12, 7, 6, 12, 11, 7, 12, 2, 11, 12 } }, /* 90: 1, 3, 4, 6, */ { /* 1,2 */ { 0, 3, 8, 9, 4, 12, 1, 9, 12, 2, 1, 12, 11, 2, 12, 7, 11, 12, 6, 7, 12, 10, 6, 12, 5, 10, 12, 4, 5, 12 }, /* 1,4 */ { 11, 6, 7, 12, 3, 8, 12, 8, 4, 12, 4, 5, 12, 5, 10, 12, 10, 2, 12, 2, 1, 12, 1, 9, 12, 9, 0, 12, 0, 3 }, /* 1,5 */ { 6, 7, 11, 12, 4, 5, 12, 5, 10, 12, 10, 2, 12, 2, 3, 12, 3, 8, 12, 8, 0, 12, 0, 1, 12, 1, 9, 12, 9, 4 }, /* 1,6 */ { 8, 0, 3, 12, 2, 1, 12, 1, 9, 12, 9, 4, 12, 4, 7, 12, 7, 11, 12, 11, 6, 12, 6, 5, 12, 5, 10, 12, 10, 2 }, /* 2,3 */ { 4, 5, 9, 8, 0, 12, 7, 8, 12, 6, 7, 12, 10, 6, 12, 1, 10, 12, 2, 1, 12, 11, 2, 12, 3, 11, 12, 0, 3, 12 }, /* 2,5 */ { 4, 5, 9, 6, 7, 12, 10, 6, 12, 1, 10, 12, 0, 1, 12, 8, 0, 12, 3, 8, 12, 2, 3, 12, 11, 2, 12, 7, 11, 12 }, /* 2,6 */ { 8, 0, 3, 2, 1, 12, 11, 2, 12, 7, 11, 12, 4, 7, 12, 9, 4, 12, 5, 9, 12, 6, 5, 12, 10, 6, 12, 1, 10, 12 }, /* 3,4 */ { 2, 1, 10, 12, 5, 9, 12, 9, 0, 12, 0, 3, 12, 3, 11, 12, 11, 6, 12, 6, 7, 12, 7, 8, 12, 8, 4, 12, 4, 5 }, /* 3,5 */ { 4, 5, 9, 12, 6, 7, 12, 7, 8, 12, 8, 0, 12, 0, 1, 12, 1, 10, 12, 10, 2, 12, 2, 3, 12, 3, 11, 12, 11, 6 }, /* 3,6 */ { 2, 1, 10, 12, 0, 3, 12, 3, 11, 12, 11, 6, 12, 6, 5, 12, 5, 9, 12, 9, 4, 12, 4, 7, 12, 7, 8, 12, 8, 0 }, /* 4,5 */ { 6, 7, 11, 4, 5, 12, 8, 4, 12, 3, 8, 12, 2, 3, 12, 10, 2, 12, 1, 10, 12, 0, 1, 12, 9, 0, 12, 5, 9, 12 }, /* 4,6 */ { 10, 2, 1, 0, 3, 12, 9, 0, 12, 5, 9, 12, 6, 5, 12, 11, 6, 12, 7, 11, 12, 4, 7, 12, 8, 4, 12, 3, 8, 12 } } }; return &tiling13_3_[config][u][0]; }; // end of Tiling13_3_ //_____________________________________________________________________________ /** * \brief tiling table for case 13.4 * For each of the case above, the specific triangulation of the edge * intersection points is given. * When a case is ambiguous, there is an auxiliary table that contains * the face number to test and the tiling table contains the specific * triangulations depending on the results * A minus sign means to invert the result of the test. */ //----------------------------------------------------------------------------- /* 13.4 */ static const char* Tiling13_4(unsigned char config, unsigned int u) { static const char tiling13_4[2][4][36] = { /* 165: 0, 2, 5, 7, */ { /* 1,2,6 */ { 12, 2, 10, 12, 10, 5, 12, 5, 6, 12, 6, 11, 12, 11, 7, 12, 7, 4, 12, 4, 8, 12, 8, 3, 12, 3, 0, 12, 0, 9, 12, 9, 1, 12, 1, 2 }, /* 1,4,5 */ { 11, 3, 12, 6, 11, 12, 7, 6, 12, 8, 7, 12, 4, 8, 12, 5, 4, 12, 9, 5, 12, 0, 9, 12, 1, 0, 12, 10, 1, 12, 2, 10, 12, 3, 2, 12 }, /* 2,3,5 */ { 9, 1, 12, 4, 9, 12, 5, 4, 12, 10, 5, 12, 6, 10, 12, 7, 6, 12, 11, 7, 12, 2, 11, 12, 3, 2, 12, 8, 3, 12, 0, 8, 12, 1, 0, 12 }, /* 3,4,6 */ { 12, 0, 8, 12, 8, 7, 12, 7, 4, 12, 4, 9, 12, 9, 5, 12, 5, 6, 12, 6, 10, 12, 10, 1, 12, 1, 2, 12, 2, 11, 12, 11, 3, 12, 3, 0 } }, /* 90: 1, 3, 4, 6, */ { /* 1,2,6 */ { 12, 3, 11, 12, 11, 6, 12, 6, 7, 12, 7, 8, 12, 8, 4, 12, 4, 5, 12, 5, 9, 12, 9, 0, 12, 0, 1, 12, 1, 10, 12, 10, 2, 12, 2, 3 }, /* 1,4,5 */ { 8, 0, 12, 7, 8, 12, 4, 7, 12, 9, 4, 12, 5, 9, 12, 6, 5, 12, 10, 6, 12, 1, 10, 12, 2, 1, 12, 11, 2, 12, 3, 11, 12, 0, 3, 12 }, /* 2,3,5 */ { 10, 2, 12, 5, 10, 12, 6, 5, 12, 11, 6, 12, 7, 11, 12, 4, 7, 12, 8, 4, 12, 3, 8, 12, 0, 3, 12, 9, 0, 12, 1, 9, 12, 2, 1, 12 }, /* 3,4,6 */ { 12, 1, 9, 12, 9, 4, 12, 4, 5, 12, 5, 10, 12, 10, 6, 12, 6, 7, 12, 7, 11, 12, 11, 2, 12, 2, 3, 12, 3, 8, 12, 8, 0, 12, 0, 1 } } }; return &tiling13_4[config][u][0]; }; // end of Tiling13_4 //_____________________________________________________________________________ /** * \brief tiling table for case 13.5.1 * The support edge for the interior test is marked as the 1st column. * For each of the case above, the specific triangulation of the edge * intersection points is given. * When a case is ambiguous, there is an auxiliary table that contains * the face number to test and the tiling table contains the specific * triangulations depending on the results * A minus sign means to invert the result of the test. */ //----------------------------------------------------------------------------- /* 13.5.1 */ static const char* Tiling13_5_1(unsigned char config, int u) { static const char tiling13_5_1[2][4][18] = { /* 165: 0, 2, 5, 7, */ { /* 1,2,5 */ { 7, 6, 11, 1, 0, 9, 10, 3, 2, 3, 10, 5, 3, 5, 8, 4, 8, 5 }, /* 1,4,6 */ { 1, 2, 10, 7, 4, 8, 3, 0, 11, 6, 11, 0, 9, 6, 0, 6, 9, 5 }, /* 2,3,6 */ { 3, 0, 8, 5, 6, 10, 1, 2, 9, 4, 9, 2, 11, 4, 2, 4, 11, 7 }, /* 3,4,5 */ { 5, 4, 9, 3, 2, 11, 8, 1, 0, 1, 8, 7, 1, 7, 10, 6, 10, 7 } }, /* 90: 1, 3, 4, 6, */ { /* 1,2,5 */ { 4, 7, 8, 2, 1, 10, 11, 0, 3, 0, 11, 6, 0, 6, 9, 5, 9, 6 }, /* 1,4,6 */ { 2, 3, 11, 4, 5, 9, 0, 1, 8, 7, 8, 1, 10, 7, 1, 7, 10, 6 }, /* 2,3,6 */ { 0, 1, 9, 6, 7, 11, 2, 3, 10, 5, 10, 3, 8, 5, 3, 5, 8, 4 }, /* 3,4,5 */ { 6, 5, 10, 0, 3, 8, 9, 2, 1, 2, 9, 4, 2, 4, 11, 7, 11, 4 } } }; return &tiling13_5_1[config][u][0]; }; // end of Tiling13_5_1 //_____________________________________________________________________________ /** * \brief tiling table for case 13.5.2 * For each of the case above, the specific triangulation of the edge * intersection points is given. * When a case is ambiguous, there is an auxiliary table that contains * the face number to test and the tiling table contains the specific * triangulations depending on the results * A minus sign means to invert the result of the test. */ //----------------------------------------------------------------------------- /* 13.5.2 */ static const char* Tiling13_5_2(unsigned char config, int u) { static const char tiling13_5_2[2][4][30] = { /* 165: 0, 2, 5, 7, */ { /* 1,2,5 */ { 1, 0, 9, 7, 4, 8, 7, 8, 3, 7, 3, 11, 2, 11, 3, 11, 2, 10, 11, 10, 6, 5, 6, 10, 6, 5, 7, 4, 7, 5 }, /* 1,4,6 */ { 7, 4, 8, 11, 3, 2, 6, 11, 2, 10, 6, 2, 6, 10, 5, 9, 5, 10, 1, 9, 10, 9, 1, 0, 2, 0, 1, 0, 2, 3 }, /* 2,3,6 */ { 5, 6, 10, 9, 1, 0, 4, 9, 0, 8, 4, 0, 4, 8, 7, 11, 7, 8, 3, 11, 8, 11, 3, 2, 0, 2, 3, 2, 0, 1 }, /* 3,4,5 */ { 3, 2, 11, 5, 6, 10, 5, 10, 1, 5, 1, 9, 0, 9, 1, 9, 0, 8, 9, 8, 4, 4, 8, 7, 4, 7, 5, 6, 5, 7 } }, /* 90: 1, 3, 4, 6, */ { /* 1,2,5 */ { 2, 1, 10, 4, 5, 9, 4, 9, 0, 4, 0, 8, 3, 8, 0, 8, 3, 11, 8, 11, 7, 6, 7, 11, 7, 6, 4, 5, 4, 6 }, /* 1,4,6 */ { 4, 5, 9, 8, 0, 3, 7, 8, 3, 11, 7, 3, 7, 11, 6, 10, 6, 11, 2, 10, 11, 10, 2, 1, 3, 1, 2, 1, 3, 0 }, /* 2,3,6 */ { 6, 7, 11, 10, 2, 1, 5, 10, 1, 9, 5, 1, 5, 9, 4, 8, 4, 9, 0, 8, 9, 8, 0, 3, 1, 3, 0, 3, 1, 2 }, /* 3,4,5 */ { 0, 3, 8, 6, 7, 11, 6, 11, 2, 6, 2, 10, 1, 10, 2, 10, 1, 9, 10, 9, 5, 5, 9, 4, 5, 4, 6, 7, 6, 4 } } }; return &tiling13_5_2[config][u][0]; }; // end of Tiling13_5_2 //_____________________________________________________________________________ //_____________________________________________________________________________ /** * \brief tiling table for case 14 * For each of the case above, the specific triangulation of the edge * intersection points is given. * When a case is ambiguous, there is an auxiliary table that contains * the face number to test and the tiling table contains the specific * triangulations depending on the results * A minus sign means to invert the result of the test. */ //----------------------------------------------------------------------------- static const char* Tiling14(unsigned char config) { static const char tiling14[12][12] = { /* 71: 0, 1, 2, 6, */ { 5, 9, 8, 5, 8, 2, 5, 2, 6, 3, 2, 8 }, /* 43: 0, 1, 3, 5, */ { 2, 1, 5, 2, 5, 8, 2, 8, 11, 4, 8, 5 }, /* 147: 0, 1, 4, 7, */ { 9, 4, 6, 9, 6, 3, 9, 3, 1, 11, 3, 6 }, /* 29: 0, 2, 3, 4, */ { 1, 11, 10, 1, 4, 11, 1, 0, 4, 7, 11, 4 }, /* 201: 0, 3, 6, 7, */ { 8, 2, 0, 8, 5, 2, 8, 7, 5, 10, 2, 5 }, /* 113: 0, 4, 5, 6, */ { 0, 7, 3, 0, 10, 7, 0, 9, 10, 6, 7, 10 }, /* 142: 1, 2, 3, 7, */ { 0, 3, 7, 0, 7, 10, 0, 10, 9, 6, 10, 7 }, /* 54: 1, 2, 4, 5, */ { 8, 0, 2, 8, 2, 5, 8, 5, 7, 10, 5, 2 }, /* 226: 1, 5, 6, 7, */ { 1, 10, 11, 1, 11, 4, 1, 4, 0, 7, 4, 11 }, /* 108: 2, 3, 5, 6, */ { 9, 6, 4, 9, 3, 6, 9, 1, 3, 11, 6, 3 }, /* 212: 2, 4, 6, 7, */ { 2, 5, 1, 2, 8, 5, 2, 11, 8, 4, 5, 8 }, /* 184: 3, 4, 5, 7, */ { 5, 8, 9, 5, 2, 8, 5, 6, 2, 3, 8, 2 } }; return &tiling14[config][0]; }; // end of Tiling14 //_____________________________________________________________________________ //_____________________________________________________________________________ /** * \brief original Marching Cubes implementation * For each of the possible vertex states listed in this table there is a * specific triangulation of the edge intersection points. The table lists * all of them in the form of 0-5 edge triples with the list terminated by * the invalid value -1. For example: casesClassic[3] list the 2 triangles * formed when cube[0] and cube[1] are inside of the surface, but the rest of * the cube is not. */ //----------------------------------------------------------------------------- static const char CasesClassic(unsigned char u, unsigned char w) { static const char casesClassic[256][16] = { /* 0: */ { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /* 1: 0, */ { 0, 8, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /* 2: 1, */ { 0, 1, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /* 3: 0, 1, */ { 1, 8, 3, 9, 8, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /* 4: 2, */ { 1, 2, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /* 5: 0, 2, */ { 0, 8, 3, 1, 2, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /* 6: 1, 2, */ { 9, 2, 10, 0, 2, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /* 7: 0, 1, 2, */ { 2, 8, 3, 2, 10, 8, 10, 9, 8, -1, -1, -1, -1, -1, -1, -1 }, /* 8: 3, */ { 3, 11, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /* 9: 0, 3, */ { 0, 11, 2, 8, 11, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /* 10: 1, 3, */ { 1, 9, 0, 2, 3, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /* 11: 0, 1, 3, */ { 1, 11, 2, 1, 9, 11, 9, 8, 11, -1, -1, -1, -1, -1, -1, -1 }, /* 12: 2, 3, */ { 3, 10, 1, 11, 10, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /* 13: 0, 2, 3, */ { 0, 10, 1, 0, 8, 10, 8, 11, 10, -1, -1, -1, -1, -1, -1, -1 }, /* 14: 1, 2, 3, */ { 3, 9, 0, 3, 11, 9, 11, 10, 9, -1, -1, -1, -1, -1, -1, -1 }, /* 15: 0, 1, 2, 3, */ { 9, 8, 10, 10, 8, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /* 16: 4, */ { 4, 7, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /* 17: 0, 4, */ { 4, 3, 0, 7, 3, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /* 18: 1, 4, */ { 0, 1, 9, 8, 4, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /* 19: 0, 1, 4, */ { 4, 1, 9, 4, 7, 1, 7, 3, 1, -1, -1, -1, -1, -1, -1, -1 }, /* 20: 2, 4, */ { 1, 2, 10, 8, 4, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /* 21: 0, 2, 4, */ { 3, 4, 7, 3, 0, 4, 1, 2, 10, -1, -1, -1, -1, -1, -1, -1 }, /* 22: 1, 2, 4, */ { 9, 2, 10, 9, 0, 2, 8, 4, 7, -1, -1, -1, -1, -1, -1, -1 }, /* 23: 0, 1, 2, 4, */ { 2, 10, 9, 2, 9, 7, 2, 7, 3, 7, 9, 4, -1, -1, -1, -1 }, /* 24: 3, 4, */ { 8, 4, 7, 3, 11, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /* 25: 0, 3, 4, */ { 11, 4, 7, 11, 2, 4, 2, 0, 4, -1, -1, -1, -1, -1, -1, -1 }, /* 26: 1, 3, 4, */ { 9, 0, 1, 8, 4, 7, 2, 3, 11, -1, -1, -1, -1, -1, -1, -1 }, /* 27: 0, 1, 3, 4, */ { 4, 7, 11, 9, 4, 11, 9, 11, 2, 9, 2, 1, -1, -1, -1, -1 }, /* 28: 2, 3, 4, */ { 3, 10, 1, 3, 11, 10, 7, 8, 4, -1, -1, -1, -1, -1, -1, -1 }, /* 29: 0, 2, 3, 4, */ { 1, 11, 10, 1, 4, 11, 1, 0, 4, 7, 11, 4, -1, -1, -1, -1 }, /* 30: 1, 2, 3, 4, */ { 4, 7, 8, 9, 0, 11, 9, 11, 10, 11, 0, 3, -1, -1, -1, -1 }, /* 31: 0, 1, 2, 3, 4, */ { 4, 7, 11, 4, 11, 9, 9, 11, 10, -1, -1, -1, -1, -1, -1, -1 }, /* 32: 5, */ { 9, 5, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /* 33: 0, 5, */ { 9, 5, 4, 0, 8, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /* 34: 1, 5, */ { 0, 5, 4, 1, 5, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /* 35: 0, 1, 5, */ { 8, 5, 4, 8, 3, 5, 3, 1, 5, -1, -1, -1, -1, -1, -1, -1 }, /* 36: 2, 5, */ { 1, 2, 10, 9, 5, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /* 37: 0, 2, 5, */ { 3, 0, 8, 1, 2, 10, 4, 9, 5, -1, -1, -1, -1, -1, -1, -1 }, /* 38: 1, 2, 5, */ { 5, 2, 10, 5, 4, 2, 4, 0, 2, -1, -1, -1, -1, -1, -1, -1 }, /* 39: 0, 1, 2, 5, */ { 2, 10, 5, 3, 2, 5, 3, 5, 4, 3, 4, 8, -1, -1, -1, -1 }, /* 40: 3, 5, */ { 9, 5, 4, 2, 3, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /* 41: 0, 3, 5, */ { 0, 11, 2, 0, 8, 11, 4, 9, 5, -1, -1, -1, -1, -1, -1, -1 }, /* 42: 1, 3, 5, */ { 0, 5, 4, 0, 1, 5, 2, 3, 11, -1, -1, -1, -1, -1, -1, -1 }, /* 43: 0, 1, 3, 5, */ { 2, 1, 5, 2, 5, 8, 2, 8, 11, 4, 8, 5, -1, -1, -1, -1 }, /* 44: 2, 3, 5, */ { 10, 3, 11, 10, 1, 3, 9, 5, 4, -1, -1, -1, -1, -1, -1, -1 }, /* 45: 0, 2, 3, 5, */ { 4, 9, 5, 0, 8, 1, 8, 10, 1, 8, 11, 10, -1, -1, -1, -1 }, /* 46: 1, 2, 3, 5, */ { 5, 4, 0, 5, 0, 11, 5, 11, 10, 11, 0, 3, -1, -1, -1, -1 }, /* 47: 0, 1, 2, 3, 5, */ { 5, 4, 8, 5, 8, 10, 10, 8, 11, -1, -1, -1, -1, -1, -1, -1 }, /* 48: 4, 5, */ { 9, 7, 8, 5, 7, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /* 49: 0, 4, 5, */ { 9, 3, 0, 9, 5, 3, 5, 7, 3, -1, -1, -1, -1, -1, -1, -1 }, /* 50: 1, 4, 5, */ { 0, 7, 8, 0, 1, 7, 1, 5, 7, -1, -1, -1, -1, -1, -1, -1 }, /* 51: 0, 1, 4, 5, */ { 1, 5, 3, 3, 5, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /* 52: 2, 4, 5, */ { 9, 7, 8, 9, 5, 7, 10, 1, 2, -1, -1, -1, -1, -1, -1, -1 }, /* 53: 0, 2, 4, 5, */ { 10, 1, 2, 9, 5, 0, 5, 3, 0, 5, 7, 3, -1, -1, -1, -1 }, /* 54: 1, 2, 4, 5, */ { 8, 0, 2, 8, 2, 5, 8, 5, 7, 10, 5, 2, -1, -1, -1, -1 }, /* 55: 0, 1, 2, 4, 5, */ { 2, 10, 5, 2, 5, 3, 3, 5, 7, -1, -1, -1, -1, -1, -1, -1 }, /* 56: 3, 4, 5, */ { 7, 9, 5, 7, 8, 9, 3, 11, 2, -1, -1, -1, -1, -1, -1, -1 }, /* 57: 0, 3, 4, 5, */ { 9, 5, 7, 9, 7, 2, 9, 2, 0, 2, 7, 11, -1, -1, -1, -1 }, /* 58: 1, 3, 4, 5, */ { 2, 3, 11, 0, 1, 8, 1, 7, 8, 1, 5, 7, -1, -1, -1, -1 }, /* 59: 0, 1, 3, 4, 5, */ { 11, 2, 1, 11, 1, 7, 7, 1, 5, -1, -1, -1, -1, -1, -1, -1 }, /* 60: 2, 3, 4, 5, */ { 9, 5, 8, 8, 5, 7, 10, 1, 3, 10, 3, 11, -1, -1, -1, -1 }, /* 61: 0, 2, 3, 4, 5, */ { 5, 7, 0, 5, 0, 9, 7, 11, 0, 1, 0, 10, 11, 10, 0, -1 }, /* 62: 1, 2, 3, 4, 5, */ { 11, 10, 0, 11, 0, 3, 10, 5, 0, 8, 0, 7, 5, 7, 0, -1 }, /* 63: 0, 1, 2, 3, 4, 5, */ { 11, 10, 5, 7, 11, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /* 64: 6, */ { 10, 6, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /* 65: 0, 6, */ { 0, 8, 3, 5, 10, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /* 66: 1, 6, */ { 9, 0, 1, 5, 10, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /* 67: 0, 1, 6, */ { 1, 8, 3, 1, 9, 8, 5, 10, 6, -1, -1, -1, -1, -1, -1, -1 }, /* 68: 2, 6, */ { 1, 6, 5, 2, 6, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /* 69: 0, 2, 6, */ { 1, 6, 5, 1, 2, 6, 3, 0, 8, -1, -1, -1, -1, -1, -1, -1 }, /* 70: 1, 2, 6, */ { 9, 6, 5, 9, 0, 6, 0, 2, 6, -1, -1, -1, -1, -1, -1, -1 }, /* 71: 0, 1, 2, 6, */ { 5, 9, 8, 5, 8, 2, 5, 2, 6, 3, 2, 8, -1, -1, -1, -1 }, /* 72: 3, 6, */ { 2, 3, 11, 10, 6, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /* 73: 0, 3, 6, */ { 11, 0, 8, 11, 2, 0, 10, 6, 5, -1, -1, -1, -1, -1, -1, -1 }, /* 74: 1, 3, 6, */ { 0, 1, 9, 2, 3, 11, 5, 10, 6, -1, -1, -1, -1, -1, -1, -1 }, /* 75: 0, 1, 3, 6, */ { 5, 10, 6, 1, 9, 2, 9, 11, 2, 9, 8, 11, -1, -1, -1, -1 }, /* 76: 2, 3, 6, */ { 6, 3, 11, 6, 5, 3, 5, 1, 3, -1, -1, -1, -1, -1, -1, -1 }, /* 77: 0, 2, 3, 6, */ { 0, 8, 11, 0, 11, 5, 0, 5, 1, 5, 11, 6, -1, -1, -1, -1 }, /* 78: 1, 2, 3, 6, */ { 3, 11, 6, 0, 3, 6, 0, 6, 5, 0, 5, 9, -1, -1, -1, -1 }, /* 79: 0, 1, 2, 3, 6, */ { 6, 5, 9, 6, 9, 11, 11, 9, 8, -1, -1, -1, -1, -1, -1, -1 }, /* 80: 4, 6, */ { 5, 10, 6, 4, 7, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /* 81: 0, 4, 6, */ { 4, 3, 0, 4, 7, 3, 6, 5, 10, -1, -1, -1, -1, -1, -1, -1 }, /* 82: 1, 4, 6, */ { 1, 9, 0, 5, 10, 6, 8, 4, 7, -1, -1, -1, -1, -1, -1, -1 }, /* 83: 0, 1, 4, 6, */ { 10, 6, 5, 1, 9, 7, 1, 7, 3, 7, 9, 4, -1, -1, -1, -1 }, /* 84: 2, 4, 6, */ { 6, 1, 2, 6, 5, 1, 4, 7, 8, -1, -1, -1, -1, -1, -1, -1 }, /* 85: 0, 2, 4, 6, */ { 1, 2, 5, 5, 2, 6, 3, 0, 4, 3, 4, 7, -1, -1, -1, -1 }, /* 86: 1, 2, 4, 6, */ { 8, 4, 7, 9, 0, 5, 0, 6, 5, 0, 2, 6, -1, -1, -1, -1 }, /* 87: 0, 1, 2, 4, 6, */ { 7, 3, 9, 7, 9, 4, 3, 2, 9, 5, 9, 6, 2, 6, 9, -1 }, /* 88: 3, 4, 6, */ { 3, 11, 2, 7, 8, 4, 10, 6, 5, -1, -1, -1, -1, -1, -1, -1 }, /* 89: 0, 3, 4, 6, */ { 5, 10, 6, 4, 7, 2, 4, 2, 0, 2, 7, 11, -1, -1, -1, -1 }, /* 90: 1, 3, 4, 6, */ { 0, 1, 9, 4, 7, 8, 2, 3, 11, 5, 10, 6, -1, -1, -1, -1 }, /* 91: 0, 1, 3, 4, 6, */ { 9, 2, 1, 9, 11, 2, 9, 4, 11, 7, 11, 4, 5, 10, 6, -1 }, /* 92: 2, 3, 4, 6, */ { 8, 4, 7, 3, 11, 5, 3, 5, 1, 5, 11, 6, -1, -1, -1, -1 }, /* 93: 0, 2, 3, 4, 6, */ { 5, 1, 11, 5, 11, 6, 1, 0, 11, 7, 11, 4, 0, 4, 11, -1 }, /* 94: 1, 2, 3, 4, 6, */ { 0, 5, 9, 0, 6, 5, 0, 3, 6, 11, 6, 3, 8, 4, 7, -1 }, /* 95: 0, 1, 2, 3, 4, 6, */ { 6, 5, 9, 6, 9, 11, 4, 7, 9, 7, 11, 9, -1, -1, -1, -1 }, /* 96: 5, 6, */ { 10, 4, 9, 6, 4, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /* 97: 0, 5, 6, */ { 4, 10, 6, 4, 9, 10, 0, 8, 3, -1, -1, -1, -1, -1, -1, -1 }, /* 98: 1, 5, 6, */ { 10, 0, 1, 10, 6, 0, 6, 4, 0, -1, -1, -1, -1, -1, -1, -1 }, /* 99: 0, 1, 5, 6, */ { 8, 3, 1, 8, 1, 6, 8, 6, 4, 6, 1, 10, -1, -1, -1, -1 }, /* 100: 2, 5, 6, */ { 1, 4, 9, 1, 2, 4, 2, 6, 4, -1, -1, -1, -1, -1, -1, -1 }, /* 101: 0, 2, 5, 6, */ { 3, 0, 8, 1, 2, 9, 2, 4, 9, 2, 6, 4, -1, -1, -1, -1 }, /* 102: 1, 2, 5, 6, */ { 0, 2, 4, 4, 2, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /* 103: 0, 1, 2, 5, 6, */ { 8, 3, 2, 8, 2, 4, 4, 2, 6, -1, -1, -1, -1, -1, -1, -1 }, /* 104: 3, 5, 6, */ { 10, 4, 9, 10, 6, 4, 11, 2, 3, -1, -1, -1, -1, -1, -1, -1 }, /* 105: 0, 3, 5, 6, */ { 0, 8, 2, 2, 8, 11, 4, 9, 10, 4, 10, 6, -1, -1, -1, -1 }, /* 106: 1, 3, 5, 6, */ { 3, 11, 2, 0, 1, 6, 0, 6, 4, 6, 1, 10, -1, -1, -1, -1 }, /* 107: 0, 1, 3, 5, 6, */ { 6, 4, 1, 6, 1, 10, 4, 8, 1, 2, 1, 11, 8, 11, 1, -1 }, /* 108: 2, 3, 5, 6, */ { 9, 6, 4, 9, 3, 6, 9, 1, 3, 11, 6, 3, -1, -1, -1, -1 }, /* 109: 0, 2, 3, 5, 6, */ { 8, 11, 1, 8, 1, 0, 11, 6, 1, 9, 1, 4, 6, 4, 1, -1 }, /* 110: 1, 2, 3, 5, 6, */ { 3, 11, 6, 3, 6, 0, 0, 6, 4, -1, -1, -1, -1, -1, -1, -1 }, /* 111: 0, 1, 2, 3, 5, 6, */ { 6, 4, 8, 11, 6, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /* 112: 4, 5, 6, */ { 7, 10, 6, 7, 8, 10, 8, 9, 10, -1, -1, -1, -1, -1, -1, -1 }, /* 113: 0, 4, 5, 6, */ { 0, 7, 3, 0, 10, 7, 0, 9, 10, 6, 7, 10, -1, -1, -1, -1 }, /* 114: 1, 4, 5, 6, */ { 10, 6, 7, 1, 10, 7, 1, 7, 8, 1, 8, 0, -1, -1, -1, -1 }, /* 115: 0, 1, 4, 5, 6, */ { 10, 6, 7, 10, 7, 1, 1, 7, 3, -1, -1, -1, -1, -1, -1, -1 }, /* 116: 2, 4, 5, 6, */ { 1, 2, 6, 1, 6, 8, 1, 8, 9, 8, 6, 7, -1, -1, -1, -1 }, /* 117: 0, 2, 4, 5, 6, */ { 2, 6, 9, 2, 9, 1, 6, 7, 9, 0, 9, 3, 7, 3, 9, -1 }, /* 118: 1, 2, 4, 5, 6, */ { 7, 8, 0, 7, 0, 6, 6, 0, 2, -1, -1, -1, -1, -1, -1, -1 }, /* 119: 0, 1, 2, 4, 5, 6, */ { 7, 3, 2, 6, 7, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /* 120: 3, 4, 5, 6, */ { 2, 3, 11, 10, 6, 8, 10, 8, 9, 8, 6, 7, -1, -1, -1, -1 }, /* 121: 0, 3, 4, 5, 6, */ { 2, 0, 7, 2, 7, 11, 0, 9, 7, 6, 7, 10, 9, 10, 7, -1 }, /* 122: 1, 3, 4, 5, 6, */ { 1, 8, 0, 1, 7, 8, 1, 10, 7, 6, 7, 10, 2, 3, 11, -1 }, /* 123: 0, 1, 3, 4, 5, 6, */ { 11, 2, 1, 11, 1, 7, 10, 6, 1, 6, 7, 1, -1, -1, -1, -1 }, /* 124: 2, 3, 4, 5, 6, */ { 8, 9, 6, 8, 6, 7, 9, 1, 6, 11, 6, 3, 1, 3, 6, -1 }, /* 125: 0, 2, 3, 4, 5, 6, */ { 0, 9, 1, 11, 6, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /* 126: 1, 2, 3, 4, 5, 6, */ { 7, 8, 0, 7, 0, 6, 3, 11, 0, 11, 6, 0, -1, -1, -1, -1 }, /* 127: 0, 1, 2, 3, 4, 5, 6, */ { 7, 11, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /* 128: 7, */ { 7, 6, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /* 129: 0, 7, */ { 3, 0, 8, 11, 7, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /* 130: 1, 7, */ { 0, 1, 9, 11, 7, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /* 131: 0, 1, 7, */ { 8, 1, 9, 8, 3, 1, 11, 7, 6, -1, -1, -1, -1, -1, -1, -1 }, /* 132: 2, 7, */ { 10, 1, 2, 6, 11, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /* 133: 0, 2, 7, */ { 1, 2, 10, 3, 0, 8, 6, 11, 7, -1, -1, -1, -1, -1, -1, -1 }, /* 134: 1, 2, 7, */ { 2, 9, 0, 2, 10, 9, 6, 11, 7, -1, -1, -1, -1, -1, -1, -1 }, /* 135: 0, 1, 2, 7, */ { 6, 11, 7, 2, 10, 3, 10, 8, 3, 10, 9, 8, -1, -1, -1, -1 }, /* 136: 3, 7, */ { 7, 2, 3, 6, 2, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /* 137: 0, 3, 7, */ { 7, 0, 8, 7, 6, 0, 6, 2, 0, -1, -1, -1, -1, -1, -1, -1 }, /* 138: 1, 3, 7, */ { 2, 7, 6, 2, 3, 7, 0, 1, 9, -1, -1, -1, -1, -1, -1, -1 }, /* 139: 0, 1, 3, 7, */ { 1, 6, 2, 1, 8, 6, 1, 9, 8, 8, 7, 6, -1, -1, -1, -1 }, /* 140: 2, 3, 7, */ { 10, 7, 6, 10, 1, 7, 1, 3, 7, -1, -1, -1, -1, -1, -1, -1 }, /* 141: 0, 2, 3, 7, */ { 10, 7, 6, 1, 7, 10, 1, 8, 7, 1, 0, 8, -1, -1, -1, -1 }, /* 142: 1, 2, 3, 7, */ { 0, 3, 7, 0, 7, 10, 0, 10, 9, 6, 10, 7, -1, -1, -1, -1 }, /* 143: 0, 1, 2, 3, 7, */ { 7, 6, 10, 7, 10, 8, 8, 10, 9, -1, -1, -1, -1, -1, -1, -1 }, /* 144: 4, 7, */ { 6, 8, 4, 11, 8, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /* 145: 0, 4, 7, */ { 3, 6, 11, 3, 0, 6, 0, 4, 6, -1, -1, -1, -1, -1, -1, -1 }, /* 146: 1, 4, 7, */ { 8, 6, 11, 8, 4, 6, 9, 0, 1, -1, -1, -1, -1, -1, -1, -1 }, /* 147: 0, 1, 4, 7, */ { 9, 4, 6, 9, 6, 3, 9, 3, 1, 11, 3, 6, -1, -1, -1, -1 }, /* 148: 2, 4, 7, */ { 6, 8, 4, 6, 11, 8, 2, 10, 1, -1, -1, -1, -1, -1, -1, -1 }, /* 149: 0, 2, 4, 7, */ { 1, 2, 10, 3, 0, 11, 0, 6, 11, 0, 4, 6, -1, -1, -1, -1 }, /* 150: 1, 2, 4, 7, */ { 4, 11, 8, 4, 6, 11, 0, 2, 9, 2, 10, 9, -1, -1, -1, -1 }, /* 151: 0, 1, 2, 4, 7, */ { 10, 9, 3, 10, 3, 2, 9, 4, 3, 11, 3, 6, 4, 6, 3, -1 }, /* 152: 3, 4, 7, */ { 8, 2, 3, 8, 4, 2, 4, 6, 2, -1, -1, -1, -1, -1, -1, -1 }, /* 153: 0, 3, 4, 7, */ { 0, 4, 2, 4, 6, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /* 154: 1, 3, 4, 7, */ { 1, 9, 0, 2, 3, 4, 2, 4, 6, 4, 3, 8, -1, -1, -1, -1 }, /* 155: 0, 1, 3, 4, 7, */ { 1, 9, 4, 1, 4, 2, 2, 4, 6, -1, -1, -1, -1, -1, -1, -1 }, /* 156: 2, 3, 4, 7, */ { 8, 1, 3, 8, 6, 1, 8, 4, 6, 6, 10, 1, -1, -1, -1, -1 }, /* 157: 0, 2, 3, 4, 7, */ { 10, 1, 0, 10, 0, 6, 6, 0, 4, -1, -1, -1, -1, -1, -1, -1 }, /* 158: 1, 2, 3, 4, 7, */ { 4, 6, 3, 4, 3, 8, 6, 10, 3, 0, 3, 9, 10, 9, 3, -1 }, /* 159: 0, 1, 2, 3, 4, 7, */ { 10, 9, 4, 6, 10, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /* 160: 5, 7, */ { 4, 9, 5, 7, 6, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /* 161: 0, 5, 7, */ { 0, 8, 3, 4, 9, 5, 11, 7, 6, -1, -1, -1, -1, -1, -1, -1 }, /* 162: 1, 5, 7, */ { 5, 0, 1, 5, 4, 0, 7, 6, 11, -1, -1, -1, -1, -1, -1, -1 }, /* 163: 0, 1, 5, 7, */ { 11, 7, 6, 8, 3, 4, 3, 5, 4, 3, 1, 5, -1, -1, -1, -1 }, /* 164: 2, 5, 7, */ { 9, 5, 4, 10, 1, 2, 7, 6, 11, -1, -1, -1, -1, -1, -1, -1 }, /* 165: 0, 2, 5, 7, */ { 6, 11, 7, 1, 2, 10, 0, 8, 3, 4, 9, 5, -1, -1, -1, -1 }, /* 166: 1, 2, 5, 7, */ { 7, 6, 11, 5, 4, 10, 4, 2, 10, 4, 0, 2, -1, -1, -1, -1 }, /* 167: 0, 1, 2, 5, 7, */ { 3, 4, 8, 3, 5, 4, 3, 2, 5, 10, 5, 2, 11, 7, 6, -1 }, /* 168: 3, 5, 7, */ { 7, 2, 3, 7, 6, 2, 5, 4, 9, -1, -1, -1, -1, -1, -1, -1 }, /* 169: 0, 3, 5, 7, */ { 9, 5, 4, 0, 8, 6, 0, 6, 2, 6, 8, 7, -1, -1, -1, -1 }, /* 170: 1, 3, 5, 7, */ { 3, 6, 2, 3, 7, 6, 1, 5, 0, 5, 4, 0, -1, -1, -1, -1 }, /* 171: 0, 1, 3, 5, 7, */ { 6, 2, 8, 6, 8, 7, 2, 1, 8, 4, 8, 5, 1, 5, 8, -1 }, /* 172: 2, 3, 5, 7, */ { 9, 5, 4, 10, 1, 6, 1, 7, 6, 1, 3, 7, -1, -1, -1, -1 }, /* 173: 0, 2, 3, 5, 7, */ { 1, 6, 10, 1, 7, 6, 1, 0, 7, 8, 7, 0, 9, 5, 4, -1 }, /* 174: 1, 2, 3, 5, 7, */ { 4, 0, 10, 4, 10, 5, 0, 3, 10, 6, 10, 7, 3, 7, 10, -1 }, /* 175: 0, 1, 2, 3, 5, 7, */ { 7, 6, 10, 7, 10, 8, 5, 4, 10, 4, 8, 10, -1, -1, -1, -1 }, /* 176: 4, 5, 7, */ { 6, 9, 5, 6, 11, 9, 11, 8, 9, -1, -1, -1, -1, -1, -1, -1 }, /* 177: 0, 4, 5, 7, */ { 3, 6, 11, 0, 6, 3, 0, 5, 6, 0, 9, 5, -1, -1, -1, -1 }, /* 178: 1, 4, 5, 7, */ { 0, 11, 8, 0, 5, 11, 0, 1, 5, 5, 6, 11, -1, -1, -1, -1 }, /* 179: 0, 1, 4, 5, 7, */ { 6, 11, 3, 6, 3, 5, 5, 3, 1, -1, -1, -1, -1, -1, -1, -1 }, /* 180: 2, 4, 5, 7, */ { 1, 2, 10, 9, 5, 11, 9, 11, 8, 11, 5, 6, -1, -1, -1, -1 }, /* 181: 0, 2, 4, 5, 7, */ { 0, 11, 3, 0, 6, 11, 0, 9, 6, 5, 6, 9, 1, 2, 10, -1 }, /* 182: 1, 2, 4, 5, 7, */ { 11, 8, 5, 11, 5, 6, 8, 0, 5, 10, 5, 2, 0, 2, 5, -1 }, /* 183: 0, 1, 2, 4, 5, 7, */ { 6, 11, 3, 6, 3, 5, 2, 10, 3, 10, 5, 3, -1, -1, -1, -1 }, /* 184: 3, 4, 5, 7, */ { 5, 8, 9, 5, 2, 8, 5, 6, 2, 3, 8, 2, -1, -1, -1, -1 }, /* 185: 0, 3, 4, 5, 7, */ { 9, 5, 6, 9, 6, 0, 0, 6, 2, -1, -1, -1, -1, -1, -1, -1 }, /* 186: 1, 3, 4, 5, 7, */ { 1, 5, 8, 1, 8, 0, 5, 6, 8, 3, 8, 2, 6, 2, 8, -1 }, /* 187: 0, 1, 3, 4, 5, 7, */ { 1, 5, 6, 2, 1, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /* 188: 2, 3, 4, 5, 7, */ { 1, 3, 6, 1, 6, 10, 3, 8, 6, 5, 6, 9, 8, 9, 6, -1 }, /* 189: 0, 2, 3, 4, 5, 7, */ { 10, 1, 0, 10, 0, 6, 9, 5, 0, 5, 6, 0, -1, -1, -1, -1 }, /* 190: 1, 2, 3, 4, 5, 7, */ { 0, 3, 8, 5, 6, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /* 191: 0, 1, 2, 3, 4, 5, 7, */ { 10, 5, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /* 192: 6, 7, */ { 11, 5, 10, 7, 5, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /* 193: 0, 6, 7, */ { 11, 5, 10, 11, 7, 5, 8, 3, 0, -1, -1, -1, -1, -1, -1, -1 }, /* 194: 1, 6, 7, */ { 5, 11, 7, 5, 10, 11, 1, 9, 0, -1, -1, -1, -1, -1, -1, -1 }, /* 195: 0, 1, 6, 7, */ { 10, 7, 5, 10, 11, 7, 9, 8, 1, 8, 3, 1, -1, -1, -1, -1 }, /* 196: 2, 6, 7, */ { 11, 1, 2, 11, 7, 1, 7, 5, 1, -1, -1, -1, -1, -1, -1, -1 }, /* 197: 0, 2, 6, 7, */ { 0, 8, 3, 1, 2, 7, 1, 7, 5, 7, 2, 11, -1, -1, -1, -1 }, /* 198: 1, 2, 6, 7, */ { 9, 7, 5, 9, 2, 7, 9, 0, 2, 2, 11, 7, -1, -1, -1, -1 }, /* 199: 0, 1, 2, 6, 7, */ { 7, 5, 2, 7, 2, 11, 5, 9, 2, 3, 2, 8, 9, 8, 2, -1 }, /* 200: 3, 6, 7, */ { 2, 5, 10, 2, 3, 5, 3, 7, 5, -1, -1, -1, -1, -1, -1, -1 }, /* 201: 0, 3, 6, 7, */ { 8, 2, 0, 8, 5, 2, 8, 7, 5, 10, 2, 5, -1, -1, -1, -1 }, /* 202: 1, 3, 6, 7, */ { 9, 0, 1, 5, 10, 3, 5, 3, 7, 3, 10, 2, -1, -1, -1, -1 }, /* 203: 0, 1, 3, 6, 7, */ { 9, 8, 2, 9, 2, 1, 8, 7, 2, 10, 2, 5, 7, 5, 2, -1 }, /* 204: 2, 3, 6, 7, */ { 1, 3, 5, 3, 7, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /* 205: 0, 2, 3, 6, 7, */ { 0, 8, 7, 0, 7, 1, 1, 7, 5, -1, -1, -1, -1, -1, -1, -1 }, /* 206: 1, 2, 3, 6, 7, */ { 9, 0, 3, 9, 3, 5, 5, 3, 7, -1, -1, -1, -1, -1, -1, -1 }, /* 207: 0, 1, 2, 3, 6, 7, */ { 9, 8, 7, 5, 9, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /* 208: 4, 6, 7, */ { 5, 8, 4, 5, 10, 8, 10, 11, 8, -1, -1, -1, -1, -1, -1, -1 }, /* 209: 0, 4, 6, 7, */ { 5, 0, 4, 5, 11, 0, 5, 10, 11, 11, 3, 0, -1, -1, -1, -1 }, /* 210: 1, 4, 6, 7, */ { 0, 1, 9, 8, 4, 10, 8, 10, 11, 10, 4, 5, -1, -1, -1, -1 }, /* 211: 0, 1, 4, 6, 7, */ { 10, 11, 4, 10, 4, 5, 11, 3, 4, 9, 4, 1, 3, 1, 4, -1 }, /* 212: 2, 4, 6, 7, */ { 2, 5, 1, 2, 8, 5, 2, 11, 8, 4, 5, 8, -1, -1, -1, -1 }, /* 213: 0, 2, 4, 6, 7, */ { 0, 4, 11, 0, 11, 3, 4, 5, 11, 2, 11, 1, 5, 1, 11, -1 }, /* 214: 1, 2, 4, 6, 7, */ { 0, 2, 5, 0, 5, 9, 2, 11, 5, 4, 5, 8, 11, 8, 5, -1 }, /* 215: 0, 1, 2, 4, 6, 7, */ { 9, 4, 5, 2, 11, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /* 216: 3, 4, 6, 7, */ { 2, 5, 10, 3, 5, 2, 3, 4, 5, 3, 8, 4, -1, -1, -1, -1 }, /* 217: 0, 3, 4, 6, 7, */ { 5, 10, 2, 5, 2, 4, 4, 2, 0, -1, -1, -1, -1, -1, -1, -1 }, /* 218: 1, 3, 4, 6, 7, */ { 3, 10, 2, 3, 5, 10, 3, 8, 5, 4, 5, 8, 0, 1, 9, -1 }, /* 219: 0, 1, 3, 4, 6, 7, */ { 5, 10, 2, 5, 2, 4, 1, 9, 2, 9, 4, 2, -1, -1, -1, -1 }, /* 220: 2, 3, 4, 6, 7, */ { 8, 4, 5, 8, 5, 3, 3, 5, 1, -1, -1, -1, -1, -1, -1, -1 }, /* 221: 0, 2, 3, 4, 6, 7, */ { 0, 4, 5, 1, 0, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /* 222: 1, 2, 3, 4, 6, 7, */ { 8, 4, 5, 8, 5, 3, 9, 0, 5, 0, 3, 5, -1, -1, -1, -1 }, /* 223: 0, 1, 2, 3, 4, 6, 7, */ { 9, 4, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /* 224: 5, 6, 7, */ { 4, 11, 7, 4, 9, 11, 9, 10, 11, -1, -1, -1, -1, -1, -1, -1 }, /* 225: 0, 5, 6, 7, */ { 0, 8, 3, 4, 9, 7, 9, 11, 7, 9, 10, 11, -1, -1, -1, -1 }, /* 226: 1, 5, 6, 7, */ { 1, 10, 11, 1, 11, 4, 1, 4, 0, 7, 4, 11, -1, -1, -1, -1 }, /* 227: 0, 1, 5, 6, 7, */ { 3, 1, 4, 3, 4, 8, 1, 10, 4, 7, 4, 11, 10, 11, 4, -1 }, /* 228: 2, 5, 6, 7, */ { 4, 11, 7, 9, 11, 4, 9, 2, 11, 9, 1, 2, -1, -1, -1, -1 }, /* 229: 0, 2, 5, 6, 7, */ { 9, 7, 4, 9, 11, 7, 9, 1, 11, 2, 11, 1, 0, 8, 3, -1 }, /* 230: 1, 2, 5, 6, 7, */ { 11, 7, 4, 11, 4, 2, 2, 4, 0, -1, -1, -1, -1, -1, -1, -1 }, /* 231: 0, 1, 2, 5, 6, 7, */ { 11, 7, 4, 11, 4, 2, 8, 3, 4, 3, 2, 4, -1, -1, -1, -1 }, /* 232: 3, 5, 6, 7, */ { 2, 9, 10, 2, 7, 9, 2, 3, 7, 7, 4, 9, -1, -1, -1, -1 }, /* 233: 0, 3, 5, 6, 7, */ { 9, 10, 7, 9, 7, 4, 10, 2, 7, 8, 7, 0, 2, 0, 7, -1 }, /* 234: 1, 3, 5, 6, 7, */ { 3, 7, 10, 3, 10, 2, 7, 4, 10, 1, 10, 0, 4, 0, 10, -1 }, /* 235: 0, 1, 3, 5, 6, 7, */ { 1, 10, 2, 8, 7, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /* 236: 2, 3, 5, 6, 7, */ { 4, 9, 1, 4, 1, 7, 7, 1, 3, -1, -1, -1, -1, -1, -1, -1 }, /* 237: 0, 2, 3, 5, 6, 7, */ { 4, 9, 1, 4, 1, 7, 0, 8, 1, 8, 7, 1, -1, -1, -1, -1 }, /* 238: 1, 2, 3, 5, 6, 7, */ { 4, 0, 3, 7, 4, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /* 239: 0, 1, 2, 3, 5, 6, 7, */ { 4, 8, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /* 240: 4, 5, 6, 7, */ { 9, 10, 8, 10, 11, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /* 241: 0, 4, 5, 6, 7, */ { 3, 0, 9, 3, 9, 11, 11, 9, 10, -1, -1, -1, -1, -1, -1, -1 }, /* 242: 1, 4, 5, 6, 7, */ { 0, 1, 10, 0, 10, 8, 8, 10, 11, -1, -1, -1, -1, -1, -1, -1 }, /* 243: 0, 1, 4, 5, 6, 7, */ { 3, 1, 10, 11, 3, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /* 244: 2, 4, 5, 6, 7, */ { 1, 2, 11, 1, 11, 9, 9, 11, 8, -1, -1, -1, -1, -1, -1, -1 }, /* 245: 0, 2, 4, 5, 6, 7, */ { 3, 0, 9, 3, 9, 11, 1, 2, 9, 2, 11, 9, -1, -1, -1, -1 }, /* 246: 1, 2, 4, 5, 6, 7, */ { 0, 2, 11, 8, 0, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /* 247: 0, 1, 2, 4, 5, 6, 7, */ { 3, 2, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /* 248: 3, 4, 5, 6, 7, */ { 2, 3, 8, 2, 8, 10, 10, 8, 9, -1, -1, -1, -1, -1, -1, -1 }, /* 249: 0, 3, 4, 5, 6, 7, */ { 9, 10, 2, 0, 9, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /* 250: 1, 3, 4, 5, 6, 7, */ { 2, 3, 8, 2, 8, 10, 0, 1, 8, 1, 10, 8, -1, -1, -1, -1 }, /* 251: 0, 1, 3, 4, 5, 6, 7, */ { 1, 10, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /* 252: 2, 3, 4, 5, 6, 7, */ { 1, 3, 8, 9, 1, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /* 253: 0, 2, 3, 4, 5, 6, 7, */ { 0, 9, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /* 254: 1, 2, 3, 4, 5, 6, 7, */ { 0, 3, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /* 255: 0, 1, 2, 3, 4, 5, 6, 7, */ { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }; return casesClassic[u][w]; }; // end of CasesClassic //_____________________________________________________________________________ }; // end of class EMCLookUpTable }; // end of namespace tri }; //end of namespace vcg #endif // __VCG_MC_LOOK_UP_TABLE qutemol/vcg/vcg/complex/trimesh/create/ball_pivoting.h0000444000175000017500000003166610776640023021570 0ustar mbamba#ifndef BALL_PIVOTING_H #define BALL_PIVOTING_H #include "advancing_front.h" #include #include /* Ball pivoting algorithm: 1) the vertices used in the new mesh are marked as visited 2) the border vertices of the new mesh are marked as border 3) the vector nb is used to keep track of the number of borders a vertex belongs to 4) usedBit flag is used to select the points in the mesh already processed */ namespace vcg { namespace tri { template class BallPivoting: public AdvancingFront { public: typedef typename MESH::VertexType VertexType; typedef typename MESH::FaceType FaceType; typedef typename MESH::ScalarType ScalarType; typedef typename MESH::VertexIterator VertexIterator; typedef typename MESH::VertexType::CoordType Point3x; typedef GridStaticPtr StaticGrid; float radius; //radius of the ball float min_edge; //min lenght of an edge float max_edge; //min lenght of an edge float max_angle; //max angle between 2 faces (cos(angle) actually) public: ScalarType radi() { return radius; } // if radius ==0 an autoguess for the ball pivoting radius is attempted // otherwise the passed value (in absolute mesh units) is used. BallPivoting(MESH &_mesh, float _radius = 0, float minr = 0.2, float angle = M_PI/2): AdvancingFront(_mesh), radius(_radius), min_edge(minr), max_edge(1.8), max_angle(cos(angle)), last_seed(-1) { //compute bbox baricenter = Point3x(0, 0, 0); UpdateBounding::Box(_mesh); for(VertexIterator vi=this->mesh.vert.begin();vi!=this->mesh.vert.end();++vi) if( !(*vi).IsD() ) baricenter += (*vi).P(); baricenter /= this->mesh.vn; assert(this->mesh.vn > 3); if(radius == 0) // radius ==0 means that an auto guess should be attempted. radius = sqrt((this->mesh.bbox.Diag()*this->mesh.bbox.Diag())/this->mesh.vn); min_edge *= radius; max_edge *= radius; //enlarging the bbox for out-of-box queries Box3 BPbbox=this->mesh.bbox; BPbbox.Offset(4*radius); grid.Set(this->mesh.vert.begin(), this->mesh.vert.end(), BPbbox); //mark visited points std::vector targets; std::vector points; std::vector dists; usedBit = VertexType::NewBitFlag(); for(int i = 0; i < (int)this->mesh.vert.size(); i++) this->mesh.vert[i].ClearUserBit(usedBit); UpdateFlags::VertexClearV(this->mesh); for(int i = 0; i < (int)this->mesh.face.size(); i++) { FaceType &f = this->mesh.face[i]; if(f.IsD()) continue; for(int k = 0; k < 3; k++) { f.V(k)->SetV(); int n = trimesh::GetInSphereVertex(this->mesh, grid, f.V(k)->P(), min_edge, targets, dists, points); for(int t = 0; t < n; t++) { targets[t]->SetUserBit(usedBit); assert(targets[t]->IsUserBit(usedBit)); } assert(f.V(k)->IsUserBit(usedBit)); } } } ~BallPivoting() { VertexType::DeleteBitFlag(usedBit); } bool Seed(int &v0, int &v1, int &v2) { bool use_normals = false; //get a sphere of neighbours std::vector targets; std::vector points; std::vector dists; while(last_seed++ < (int)(this->mesh.vert.size())) { VertexType &seed = this->mesh.vert[last_seed]; if(seed.IsD() || seed.IsUserBit(usedBit)) continue; seed.SetUserBit(usedBit); int n = trimesh::GetInSphereVertex(this->mesh, grid, seed.P(), 2*radius, targets, dists, points); if(n < 3) { continue; } bool success = true; //find the closest visited or boundary for(int i = 0; i < n; i++) { VertexType &v = *(targets[i]); if(v.IsV()) { success = false; break; } } if(!success) continue; VertexType *vv0, *vv1, *vv2; success = false; //find a triplet that does not contains any other point Point3x center; for(int i = 0; i < n; i++) { vv0 = targets[i]; if(vv0->IsD()) continue; Point3x &p0 = vv0->P(); for(int k = i+1; k < n; k++) { vv1 = targets[k]; if(vv1->IsD()) continue; Point3x &p1 = vv1->P(); float d2 = (p1 - p0).Norm(); if(d2 < min_edge || d2 > max_edge) continue; for(int j = k+1; j < n; j++) { vv2 = targets[j]; if(vv2->IsD()) continue; Point3x &p2 = vv2->P(); float d1 = (p2 - p0).Norm(); if(d1 < min_edge || d1 > max_edge) continue; float d0 = (p2 - p1).Norm(); if(d0 < min_edge || d0 > max_edge) continue; Point3x normal = (p1 - p0)^(p2 - p0); if(normal * (p0 - baricenter) < 0) continue; /* if(use_normals) { if(normal * vv0->N() < 0) continue; if(normal * vv1->N() < 0) continue; if(normal * vv2->N() < 0) continue; }*/ if(!FindSphere(p0, p1, p2, center)) { continue; } //check no other point inside int t; for(t = 0; t < n; t++) { if((center - targets[t]->P()).Norm() <= radius) break; } if(t < n) { continue; } //check on the other side there is not a surface Point3x opposite = center + normal*(((center - p0)*normal)*2/normal.SquaredNorm()); for(t = 0; t < n; t++) { VertexType &v = *(targets[t]); if((v.IsV()) && (opposite - v.P()).Norm() <= radius) break; } if(t < n) { continue; } success = true; i = k = j = n; } } } if(!success) { //see bad luck above continue; } Mark(vv0); Mark(vv1); Mark(vv2); v0 = vv0 - &*this->mesh.vert.begin(); v1 = vv1 - &*this->mesh.vert.begin(); v2 = vv2 - &*this->mesh.vert.begin(); return true; } return false; } //select a new vertex, mark as Visited and mark as usedBit all neighbours (less than min_edge) int Place(FrontEdge &edge, std::list::iterator &touch) { Point3x v0 = this->mesh.vert[edge.v0].P(); Point3x v1 = this->mesh.vert[edge.v1].P(); Point3x v2 = this->mesh.vert[edge.v2].P(); /* TODO why using the face normals everything goes wrong? should be exactly the same................................................ Point3x &normal = mesh.face[edge.face].N(); ? */ Point3x normal = ((v1 - v0)^(v2 - v0)).Normalize(); Point3x middle = (v0 + v1)/2; Point3x center; if(!FindSphere(v0, v1, v2, center)) { // assert(0); return -1; } Point3x start_pivot = center - middle; Point3x axis = (v1 - v0); ScalarType axis_len = axis.SquaredNorm(); if(axis_len > 4*radius*radius) { return -1; } axis.Normalize(); // r is the radius of the thorus of all possible spheres passing throug v0 and v1 ScalarType r = sqrt(radius*radius - axis_len/4); std::vector targets; std::vector dists; std::vector points; int n = trimesh::GetInSphereVertex(this->mesh, grid, middle, r + radius, targets, dists, points); if(targets.size() == 0) { return -1; //this really would be strange but one never knows. } VertexType *candidate = NULL; ScalarType min_angle = M_PI; for(int i = 0; i < static_cast(targets.size()); i++) { VertexType *v = targets[i]; int id = v - &*this->mesh.vert.begin(); if(v->IsD()) continue; // this should always be true IsB => IsV , IsV => IsU if(v->IsB()) assert(v->IsV()); if(v->IsV()) assert(v->IsUserBit(usedBit)); if(v->IsUserBit(usedBit) && !(v->IsB())) continue; if(id == edge.v0 || id == edge.v1 || id == edge.v2) continue; Point3x p = this->mesh.vert[id].P(); /* Find the sphere through v0, p, v1 (store center on end_pivot */ if(!FindSphere(v0, p, v1, center)) { continue; } /* Angle between old center and new center */ ScalarType alpha = Angle(start_pivot, center - middle, axis); /* adding a small bias to already chosen vertices. doesn't solve numerical problems, but helps. */ // if(this->mesh.vert[id].IsB()) alpha -= 0.001; /* Sometimes alpha might be little less then M_PI while it should be 0, by numerical errors: happens for example pivoting on the diagonal of a square. */ /* if(alpha > 2*M_PI - 0.8) { // Angle between old center and new *point* //TODO is this really overshooting? shouldbe enough to alpha -= 2*M_PI Point3x proj = p - axis * (axis * p - axis * middle); ScalarType beta = angle(start_pivot, proj - middle, axis); if(alpha > beta) alpha -= 2*M_PI; } */ if(candidate == NULL || alpha < min_angle) { candidate = v; min_angle = alpha; } } if(min_angle >= M_PI - 0.1) { return -1; } if(candidate == NULL) { return -1; } if(!candidate->IsB()) { assert((candidate->P() - v0).Norm() > min_edge); assert((candidate->P() - v1).Norm() > min_edge); } int id = candidate - &*this->mesh.vert.begin(); assert(id != edge.v0 && id != edge.v1); Point3x newnormal = ((candidate->P() - v0)^(v1 - v0)).Normalize(); if(normal * newnormal < max_angle || this->nb[id] >= 2) { return -1; } //test if id is in some border (to return touch for(std::list::iterator k = this->front.begin(); k != this->front.end(); k++) if((*k).v0 == id) touch = k; for(std::list::iterator k = this->deads.begin(); k != this->deads.end(); k++) if((*k).v0 == id) touch = k; //mark vertices close to candidate Mark(candidate); return id; } private: int last_seed; //used for new seeds when front is empty int usedBit; //use to detect if a vertex has been already processed. Point3x baricenter;//used for the first seed. StaticGrid grid; //lookup grid for points /* returns the sphere touching p0, p1, p2 of radius r such that the normal of the face points toward the center of the sphere */ bool FindSphere(Point3x &p0, Point3x &p1, Point3x &p2, Point3x ¢er) { //we want p0 to be always the smallest one. Point3x p[3]; if(p0 < p1 && p0 < p2) { p[0] = p0; p[1] = p1; p[2] = p2; } else if(p1 < p0 && p1 < p2) { p[0] = p1; p[1] = p2; p[2] = p0; } else { p[0] = p2; p[1] = p0; p[2] = p1; } Point3x q1 = p[1] - p[0]; Point3x q2 = p[2] - p[0]; Point3x up = q1^q2; ScalarType uplen = up.Norm(); //the three points are aligned if(uplen < 0.001*q1.Norm()*q2.Norm()) { return false; } up /= uplen; ScalarType a11 = q1*q1; ScalarType a12 = q1*q2; ScalarType a22 = q2*q2; ScalarType m = 4*(a11*a22 - a12*a12); ScalarType l1 = 2*(a11*a22 - a22*a12)/m; ScalarType l2 = 2*(a11*a22 - a12*a11)/m; center = q1*l1 + q2*l2; ScalarType circle_r = center.Norm(); if(circle_r > radius) { return false; //need too big a sphere } ScalarType height = sqrt(radius*radius - circle_r*circle_r); center += p[0] + up*height; return true; } /* compute angle from p to q, using axis for orientation */ ScalarType Angle(Point3x p, Point3x q, Point3x &axis) { p.Normalize(); q.Normalize(); Point3x vec = p^q; ScalarType angle = acos(p*q); if(vec*axis < 0) angle = -angle; if(angle < 0) angle += 2*M_PI; return angle; } void Mark(VertexType *v) { std::vector targets; std::vector points; std::vector dists; int n = trimesh::GetInSphereVertex(this->mesh, grid, v->P(), min_edge, targets, dists, points); for(int t = 0; t < n; t++) targets[t]->SetUserBit(usedBit); v->SetV(); } }; } //namespace tri } //namespace vcg #endif qutemol/vcg/vcg/complex/trimesh/create/readme.txt0000444000175000017500000001510510175142234020544 0ustar mbambaMARCHING CUBES & EXTENDED MARCHING CUBES =================================================================================== In breve le classi coinvolte sono 3 e sono: * MerchingCubes ed ExtendedMarchingCubes processano una cella alla volta, aggiungendo per ogni chiamata a ProcessCell l'insieme di triangoli approssimante la superficie che interseca la cella * Walker gestisce l'attraversamento del volume, servendo le chiamate effettuate dagli algoritmi di estrazione della superficie al volume e cachandone i risultato * Volume conosce come calcolare il campo scalare all'interno del volume da processare e come calcolare le intersezioni superficie/segmenti. DESCRIZIONE ==================================================================================== Le classi che implementano gli algoritmi MarchingCubes ed ExtendedMarchingCubes sono state implementate cos da risultare quanto pi generiche possibile: ogni chiamata al metodo ProcessCell(Point3i p1, Point3i p2) analizza la cella del volume individuata dai due punti p1 e p2 e l'analisi di questa cella si conclude esattamente al ritorno da questa chiamata: nel caso infatti la superficie da estrarre attraversi questa cella, all'interno di questa stessa chiamata la mesh viene aggiornata con un opportuno insieme di triangoli. L'assunzione alla base di questa astrazione l'esistenza di altri due entit, il Walker ed il Volume; sebbene sulla loro implementazione lasciata la pi completa libert, utile precisare in quale relazione essi stiano rispetto agli algoritmi di estrazione di superfici. Un esempio che riassume quanto qui esposto incluso nella libreria: vd. vcg/apps/test/extractors. VOLUME ==================================================================================== Gli algoritmi di estrazione di superfici risalgono alla superficie utilizzando i valori di un campo scalare definito sul volume da processare campionato sui vertici di una qualche griglia. Questo campo scalare sar generalmente diverso a seconda del tipo di applicazione. Il Volume appunto quella classe che racchiude il campo scalare e di cui ne conosce le propriet. In realt, all'interno dell'algoritmo di estrazione di superfici, non esiste alcun collegamento esplicito con il Volume: tutte le sue chiamate sono rivolte al Walker. Questo perch (per motivi che saranno esposti successivamente a proposito del Walker) il Walker potrebbe gi possedere il valore del campo calcolato in un dato punto, che evita cos di farselo ricalcolare nuovamente dal Volume: Similmente, quando viene chiesto di calcolare il punto di intersezione della superficie con un segmento, se il Walker dispone gi di questa informazione, la restituisce all'algoritmo di estrazione di superfici, altrimenti il calcolo verr effettuato dal Volume: il punto ottenuto verr restituito al Walker che potr quindi soddisfare la richiesta iniziale. Il motivo per cui si scelto di frapporre un Walker fra gli algoritmi di estrazione di superfici ed il Volume esclusivamente di ottimizzazione. L'idea di fondo che il Walker quell'oggetto attrverso cui avviene la visita del volume: per ogni cella del volume, esso effettua la chiamata ProcessCell. Conoscendo l'ordine di visita, il Walker anche la classe candidata ad implementare le politiche di caching, in quanto sa esattamente da che momento pu essere utile una certa informazione e per quanto a lungo pu essere conveniente mantenerla prima di liberarsene. WALKER ==================================================================================== Poich la politica di visita del volume realizzata all'interno del walker, opportuno che sempre all'interno del walker vengano realizzate le politiche di caching rivolte ad ottimizzare l'esecuzione degli algoritmi MC ed EMC. Durante il processing di ogni cella questi algoritmi possono chiamare le seguenti funzioni del Walker: MC EMC ------------------------------------------ V(i, j, k) X X GetXIntercept(p1, p2, v) X X GetYIntercept(p1, p2, v) X X GetZIntercept(p1, p2, v) X X Exist(p1, p2, v) X const float V(int i, int j, int k) const La superficie che attraversa ogni cella viene ricavata dall'algoritmo di estrazione analizzando il valore del campo sugli otto spigoli di ogni voxel del volume; per ogni voxel, il valore del campo sui suoi otto spigoli vengono richiesti dall'algoritmo di estrazione al walker: se questo valore gi stato calcolato e cachato, il walker restituisce direttamente tale valore; altrimenti il valore del campo in questo spigolo viene calcolato (eventualmente cachato) e restituito al walker. In questo modo il valoro del campo ad ogni punto viene calcolato una sola volta anzich 8, questo puo' essere molto utile nel caso si utilizzi dataset volumetrici mantenuti implicitamente. void GetXIntercept(Point3i p1, Point3i p2, VertexPointer v) void GetYIntercept(Point3i p1, Point3i p2, VertexPointer v) void GetZIntercept(Point3i p1, Point3i p2, VertexPointer v) Dall'analisi del valore del campo agli spigoli di un dato voxel, l'algoritmo di estrazione ha rilevato che la superficie interseca lo spigolo avente estremi p1 e p2(a seconda dell'orientazione di questo spigolo, viene chiamato uno dei tre metodi): al termine di una di queste chiamate, v deve puntare al vertice della mesh (di coordinate comprese fra p1 e p2) attraverso cui passa la superficie. Se questo vertice stato gi calcolato ed inserito nella mesh, il walker deve risalire a tale vertice e memorizzarne in v il suo puntatore. Altrimenti deve provvedere ad aggiugnere un nuovo vertice ed a calcolare la sua posizione; v deve puntare in questo caso al vertice appena inserito. Il motivo per cui questo calcolo non viene implementato direttamente negli algoritmi di estrazione (possibile per es. attraverso interpolazione lineare del valore del campo nei punti p1 e p2) che questo calcolo pu essere fatto in maniere molto pi precisa conoscendo come il campo viene calcolato, essendo infatti ci dipendente dall'applicazione. bool Exist(Point3i p1, Point3i p2, VertexPointer v) Questo metodo viene chiamato solamente all'interno dell'algoritmo MarchingCubes. A differenza dei tre motodi precedenti, in questo caso si vuole sapere solamente se esiste gi un vertice tra i punti p1 e p2: nel caso tale vertice esista, Exist deve resituire true ed v deve puntare a tale vertice; se invece tale vertice non esiste, Exist deve restituire false e v deve prendere il valore NULL. NB: nel caso in cui il vertice non esiste, alla mesh non deve essere aggiunto alcun nuovo vertice. qutemol/vcg/vcg/complex/trimesh/create/marching_cubes.h0000444000175000017500000007320610271351724021701 0ustar mbamba/**************************************************************************** * VCGLib o o * * Visual and Computer Graphics Library o o * * _ O _ * * Copyright(C) 2004 \/)\/ * * Visual Computing Lab /\/| * * ISTI - Italian National Research Council | * * \ * * All rights reserved. * * * * 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. * * * * 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 (http://www.gnu.org/licenses/gpl.txt) * * for more details. * * * ****************************************************************************/ /***************************************************************************/ #ifndef __VCG_MARCHING_CUBES #define __VCG_MARCHING_CUBES #include #include #include #include "mc_lookup_table.h" namespace vcg { 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 */ //! 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; #else #ifdef _WIN64 typedef unsigned __int64 size_t; #else 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; /*! * 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() /*! * * 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]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 ; // 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 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 ; 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 /*! * 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); 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 assert(vertices_idx[vert]>=0 && 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 }; // end of class MarchingCubes /*! @} */ //end of Doxygen documentation }; // end of namespace tri }; // end of namespace vcg #endif //__VCG_MARCHING_CUBES qutemol/vcg/vcg/complex/trimesh/create/resampler.h0000444000175000017500000004601710364210703020714 0ustar mbamba#ifndef __VCG_MESH_RESAMPLER #define __VCG_MESH_RESAMPLER #include #include #include //#include #include #include #include #include //#include //debugghe namespace vcg { namespace trimesh { /** \addtogroup trimesh */ /*@{*/ /*@{*/ /** Class Resampler. This is class reasmpling a mesh using marching cubes methods @param OLD_MESH_TYPE (Template Parameter) Specifies the type of mesh to be resampled @param NEW_MESH_TYPE (Template Parameter) Specifies the type of output mesh. */ template class Resampler { typedef typename OLD_MESH_TYPE Old_Mesh; typedef typename NEW_MESH_TYPE New_Mesh; template class Walker { private: typedef int VertexIndex; typedef typename OLD_MESH_TYPE Old_Mesh; typedef typename NEW_MESH_TYPE New_Mesh; typedef typename New_Mesh::CoordType NewCoordType; typedef typename New_Mesh::VertexType* VertexPointer; typedef typename Old_Mesh::FaceContainer FaceCont; typedef typename vcg::GridStaticPtr GridType; typedef typename vcg::Box3 BoundingBox; //typedef typename std::pair PointPair; typedef vcg::tri::Allocator< New_Mesh > Allocator; protected: BoundingBox _bbox; vcg::Point3i _resolution; vcg::Point3i _cell_size; float dim_diag; int _slice_dimension; int _current_slice; VertexIndex *_x_cs; // indici dell'intersezioni della superficie lungo gli Xedge della fetta corrente VertexIndex *_y_cs; // indici dell'intersezioni della superficie lungo gli Yedge della fetta corrente VertexIndex *_z_cs; // indici dell'intersezioni della superficie lungo gli Zedge della fetta corrente VertexIndex *_x_ns; // indici dell'intersezioni della superficie lungo gli Xedge della prossima fetta VertexIndex *_z_ns; // indici dell'intersezioni della superficie lungo gli Zedge della prossima fetta //float *_v_cs;///values of distance fields for each direction in current slice //float *_v_ns;///values of distance fields for each direction in next slice typedef typename std::pair field_value; field_value* _v_cs; field_value* _v_ns; New_Mesh *_newM; Old_Mesh *_oldM; GridType _g; public: float max_dim; /*Walker(Volume_Dataset *Vo,float in,const BoundingBox &bbox,vcg::Point3i &resolution) {*/ /* init=in; Vol=Vo;*/ void SetBBParameters() { _cell_size.X() =_bbox.DimX()/_resolution.X(); _cell_size.Y() =_bbox.DimY()/_resolution.Y(); _cell_size.Z() =_bbox.DimZ()/_resolution.Z(); ///extend bb until the box - resolution and cell matches while ((_bbox.DimX()%_cell_size.X())!=0) _bbox.max.X()++; while ((_bbox.DimY()%_cell_size.Y())!=0) _bbox.max.Y()++; while ((_bbox.DimZ()%_cell_size.Z())!=0) _bbox.max.Z()++; //exetend bb to 1 cell for each side _bbox.max+=_cell_size; _bbox.min-=_cell_size; ///resetting resolution values _resolution.X()=_bbox.DimX()/_cell_size.X(); _resolution.Y()=_bbox.DimY()/_cell_size.Y(); _resolution.Z()=_bbox.DimZ()/_cell_size.Z(); ///asserting values assert(_bbox.DimX()%_cell_size.X()==0); assert(_bbox.DimY()%_cell_size.Y()==0); assert(_bbox.DimZ()%_cell_size.Z()==0); assert(_cell_size.X()*_resolution.X()==_bbox.DimX()); assert(_cell_size.Y()*_resolution.Y()==_bbox.DimY()); assert(_cell_size.Z()*_resolution.Z()==_bbox.DimZ()); _slice_dimension = (_resolution.X()+1)*(_resolution.Z()+1); //Point3f diag=Point3f((float)_cell_size.V(0),(float)_cell_size.V(1),(float)_cell_size.V(2)); //max_dim=diag.Norm();///diagonal of a cell // _current_slice = _bbox.min.Y(); Point3f minD=Point3f((float)_bbox.min.V(0),(float)_bbox.min.V(1),(float)_bbox.min.V(2)); Point3f maxD=Point3f((float)_bbox.max.V(0),(float)_bbox.max.V(1),(float)_bbox.max.V(2)); /*Point3f d=(maxD-minD); dim_diag=d.Norm();*/ } Walker(const BoundingBox &bbox,vcg::Point3i &resolution) { assert (resolution.V(0)<=bbox.DimX()); assert (resolution.V(1)<=bbox.DimY()); assert (resolution.V(2)<=bbox.DimZ()); _bbox= bbox; _resolution = resolution; SetBBParameters(); _x_cs = new VertexIndex[ _slice_dimension ]; _y_cs = new VertexIndex[ _slice_dimension ]; _z_cs = new VertexIndex[ _slice_dimension ]; _x_ns = new VertexIndex[ _slice_dimension ]; _z_ns = new VertexIndex[ _slice_dimension ]; _v_cs= new field_value[(_resolution.X()+1)*(_resolution.Z()+1)]; _v_ns= new field_value[(_resolution.X()+1)*(_resolution.Z()+1)]; }; ~Walker() {} float V(Point3i p) { return (V(p.V(0),p.V(1),p.V(2))); } float V(int x,int y,int z) { assert ((y==_current_slice)||(y==(_current_slice+_cell_size.Y()))); //test if it is outside the bb of the mesh //vcg::Point3f test=vcg::Point3f((float)x,(float)y,(float)z); /*if (!_oldM->bbox.IsIn(test)) return (1.f);*/ int index=GetSliceIndex(x,z); if (y==_current_slice) { //assert(_v_cs[index]bbox.IsIn(test)) { dist=1.f; return true; }*/ vcg::Point3f Norm; vcg::Point3f Target; vcg::Point3f pip; //vcg::tri::get((*mesh),test,_g,dist,Norm,Target,f,pip); f= vcg::trimesh::GetClosestFace( *mesh,_g,test,max_dim,dist,Target,Norm,pip); if (f==NULL) return false; else { assert(!f->IsD()); Point3f dir=(test-Target); /* dist=dir.Norm();*/ dir.Normalize(); //direction of normal inside the mesh if ((dir*Norm)<0) dist=-dist; //the intersection exist return true; } } ///compute the values if an entire slice (per y) distances>dig of a cell are signed with double of /// the distance of the bb void CumputeSliceValues(int slice,field_value *slice_values) { float dist; for (int i=_bbox.min.X(); i<=_bbox.max.X(); i+=_cell_size.X()) { for (int k=_bbox.min.Z(); k<=_bbox.max.Z(); k+=_cell_size.Z()) { int index=GetSliceIndex(i,k); if (DistanceFromMesh(i,slice,k,_oldM,dist))///compute the distance,inside volume of the mesh is negative { //put computed values in the slice values matrix slice_values[index]=field_value(true,dist); //end putting values } else slice_values[index]=field_value(false,dist); } } } template void ProcessSlice(std::vector cells,EXTRACTOR_TYPE &extractor) { std::vector::iterator it; for (it=cells.begin();itface.begin(),_oldM->face.end()); } template void BuildMesh(Old_Mesh &old_mesh,New_Mesh &new_mesh,EXTRACTOR_TYPE &extractor) { _newM=&new_mesh; _oldM=&old_mesh; SetGrid(); _newM->Clear(); vcg::Point3i p1, p2; Begin(); extractor.Initialize(); for (int j=_bbox.min.Y(); j<=_bbox.max.Y()-_cell_size.Y(); j+=_cell_size.Y()) { ProcessSlice(FindCells(),extractor);//find cells where there is the isosurface and examine it NextSlice(); } extractor.Finalize(); /*_newM= NULL;*/ } //return the index of a vertex in slide as it was stored int GetSliceIndex(int x,int z) { int ii = (x - _bbox.min.X())/_cell_size.X(); int zz = (z - _bbox.min.Z())/_cell_size.Z(); VertexIndex index = ii+zz*(_resolution.X()+1); return (index); } ///return true if exist in the cell one value <0 and another one >0 bool FindMinMax(vcg::Point3i min,vcg::Point3i max) { assert((min.X() that bbox.diag this value is not valid //that is the mark if (_corners[i].Y()==_current_slice) value=_v_cs[GetSliceIndex(_corners[i].X(),_corners[i].Z())]; else value=_v_ns[GetSliceIndex(_corners[i].X(),_corners[i].Z())]; if (value.first==false) return false; //assign new values of min and max if (value.secondmax_value) max_value=value.second; } /////do not test with zero.. if ((min_value<=0.f)&&(max_value>=0.f)) return true; return false; } ///filter the cells from to_hexamine vector to the ones that /// min and max of the cell are <0 and >0 std::vector FindCells() { std::vector res; for (int i=_bbox.min.X(); i<=_bbox.max.X()-_cell_size.X(); i+=_cell_size.X()) { for (int k=_bbox.min.Z(); k<=_bbox.max.Z()-_cell_size.Z(); k+=_cell_size.Z()) { int x0=i; int y0=_current_slice; int z0=k; int x1=x0+_cell_size.X(); int y1=y0+_cell_size.Y(); int z1=z0+_cell_size.Z(); vcg::Point3i p0=Point3i(x0,y0,z0); vcg::Point3i p1=Point3i(x1,y1,z1); assert(p0<_bbox.max); if (FindMinMax(p0,p1)) res.push_back(p0); } } return res; } //swap slices , the initial value of distance fields ids set as double of bbox of space void NextSlice() { memset(_x_cs, -1, _slice_dimension*sizeof(VertexIndex)); memset(_y_cs, -1, _slice_dimension*sizeof(VertexIndex)); memset(_z_cs, -1, _slice_dimension*sizeof(VertexIndex)); std::swap(_x_cs, _x_ns); std::swap(_z_cs, _z_ns); std::swap(_v_cs, _v_ns); _current_slice += _cell_size.Y(); //memset(_v_ns, dim_diag*2.f, _slice_dimension*sizeof(float)); //memset(_v_ns, field_value(false,0.f), _slice_dimension*sizeof(field_value)); CumputeSliceValues(_current_slice+ _cell_size.Y(),_v_ns); } //initialize data strucures , the initial value of distance fields ids set as double of bbox of space void Begin() { _current_slice = _bbox.min.Y(); memset(_x_cs, -1, _slice_dimension*sizeof(VertexIndex)); memset(_y_cs, -1, _slice_dimension*sizeof(VertexIndex)); memset(_z_cs, -1, _slice_dimension*sizeof(VertexIndex)); memset(_x_ns, -1, _slice_dimension*sizeof(VertexIndex)); memset(_z_ns, -1, _slice_dimension*sizeof(VertexIndex)); /*memset(_v_cs, dim_diag*2.f, _slice_dimension*sizeof(float)); memset(_v_ns, dim_diag*2.f, _slice_dimension*sizeof(float));*/ /*memset(_v_cs, field_value(false,0.f), _slice_dimension*sizeof(field_value)); memset(_v_ns, field_value(false,0.f), _slice_dimension*sizeof(field_value));*/ CumputeSliceValues(_current_slice,_v_cs); CumputeSliceValues(_current_slice+_cell_size.Y(),_v_ns); } bool Exist(const vcg::Point3i &p1, const vcg::Point3i &p2, VertexPointer &v) { int i = (p1.X() - _bbox.min.X())/_cell_size.X(); int z = (p1.Z() - _bbox.min.Z())/_cell_size.Z(); VertexIndex index = i+z*_resolution.X(); //VertexIndex index =GetSliceIndex(// int v_ind = 0; if (p1.X()!=p2.X()) //intersezione della superficie con un Xedge { if (p1.Y()==_current_slice) { if (_x_cs[index]!=-1) { v_ind = _x_cs[index]; v = &_newM->vert[v_ind]; assert(!v->IsD()); return true; } } else { if (_x_ns[index]!=-1) { v_ind = _x_ns[index]; v = &_newM->vert[v_ind]; assert(!v->IsD()); return true; } } v = NULL; return false; } else if (p1.Y()!=p2.Y()) //intersezione della superficie con un Yedge { if (_y_cs[index]!=-1) { v_ind =_y_cs[index]; v = &_newM->vert[v_ind]; assert(!v->IsD()); return true; } else { v = NULL; return false; } } else if (p1.Z()!=p2.Z()) //intersezione della superficie con un Zedge { if (p1.Y()==_current_slice) { if ( _z_cs[index]!=-1) { v_ind = _z_cs[index]; v = &_newM->vert[v_ind]; assert(!v->IsD()); return true; } } else { if (_z_ns[index]!=-1) { v_ind = _z_ns[index]; v = &_newM->vert[v_ind]; assert(!v->IsD()); return true; } } v = NULL; return false; } assert (0); return false; } ///interpolate NewCoordType Interpolate(const vcg::Point3i &p1, const vcg::Point3i &p2,int dir) { float f1 = (float)V(p1); float f2 = (float)V(p2); float u = (float) f1/(f1-f2); NewCoordType ret=vcg::Point3f((float)p1.V(0),(float)p1.V(1),(float)p1.V(2)); ret.V(dir) = (float) p1.V(dir)*(1.f-u) + u*(float)p2.V(dir); return (ret); } ///if there is a vertex in z axis of a cell return the vertex or create it void GetXIntercept(const vcg::Point3i &p1, const vcg::Point3i &p2, VertexPointer &v) { assert ((p1.Y()==_current_slice)||(p1.Y()==(_current_slice+_cell_size.Y()))); int i = (p1.X() - _bbox.min.X())/_cell_size.X(); int z = (p1.Z() - _bbox.min.Z())/_cell_size.Z(); VertexIndex index = i+z*_resolution.X(); VertexIndex pos; if (p1.Y()==_current_slice) { if ((pos=_x_cs[index])==-1) { _x_cs[index] = (VertexIndex) _newM->vert.size(); pos = _x_cs[index]; Allocator::AddVertices( *_newM, 1 ); v = &_newM->vert[pos]; v->P()=Interpolate(p1,p2,0); return; } } if (p1.Y()==_current_slice+_cell_size.Y()) { if ((pos=_x_ns[index])==-1) { _x_ns[index] = (VertexIndex) _newM->vert.size(); pos = _x_ns[index]; Allocator::AddVertices( *_newM, 1 ); v = &_newM->vert[pos]; v->P()=Interpolate(p1,p2,0); return; } } v = &_newM->vert[pos]; } ///if there is a vertex in y axis of a cell return the vertex or create it void GetYIntercept(const vcg::Point3i &p1, const vcg::Point3i &p2, VertexPointer &v) { assert ((p1.Y()==_current_slice)||(p1.Y()==(_current_slice+_cell_size.Y()))); int i = (p1.X() - _bbox.min.X())/_cell_size.X(); int z = (p1.Z() - _bbox.min.Z())/_cell_size.Z(); VertexIndex index = i+z*_resolution.X(); VertexIndex pos; if ((pos=_y_cs[index])==-1) { _y_cs[index] = (VertexIndex) _newM->vert.size(); pos = _y_cs[index]; Allocator::AddVertices( *_newM, 1); v = &_newM->vert[ pos ]; v->P()=Interpolate(p1,p2,1); } v = &_newM->vert[pos]; } ///if there is a vertex in z axis of a cell return the vertex or create it void GetZIntercept(const vcg::Point3i &p1, const vcg::Point3i &p2, VertexPointer &v) { assert ((p1.Y()==_current_slice)||(p1.Y()==(_current_slice+_cell_size.Y()))); int i = (p1.X() - _bbox.min.X())/_cell_size.X(); int z = (p1.Z() - _bbox.min.Z())/_cell_size.Z(); VertexIndex index = i+z*_resolution.X(); VertexIndex pos; if (p1.Y()==_current_slice) { if ((pos=_z_cs[index])==-1) { _z_cs[index] = (VertexIndex) _newM->vert.size(); pos = _z_cs[index]; Allocator::AddVertices( *_newM, 1 ); v = &_newM->vert[pos]; v->P()=Interpolate(p1,p2,2); return; } } if (p1.Y()==_current_slice+_cell_size.Y()) { if ((pos=_z_ns[index])==-1) { _z_ns[index] = (VertexIndex) _newM->vert.size(); pos = _z_ns[index]; Allocator::AddVertices( *_newM, 1 ); v = &_newM->vert[pos]; v->P()=Interpolate(p1,p2,2); return; } } v = &_newM->vert[pos]; } };//end class walker public: typedef typename Walker< Old_Mesh,New_Mesh> MyWalker; typedef typename vcg::tri::MarchingCubes MarchingCubes; ///resample the mesh using marching cube algorithm ,the accuracy is the dimension of one cell the parameter static void Resample(Old_Mesh &old_mesh,New_Mesh &new_mesh,vcg::Point3 accuracy,float max_dist) { new_mesh.Clear(); if (Old_Mesh::HasPerFaceNormal()) vcg::tri::UpdateNormals::PerFaceNormalized(old_mesh); if (Old_Mesh::HasPerVertexNormal()) vcg::tri::UpdateNormals::PerVertexNormalized(old_mesh); ///the mesh must have plane for ugrid if (!Old_Mesh::FaceType::HasEdgePlane()) assert(0); else vcg::tri::UpdateEdges::Set(old_mesh); ///be sure that the bounding box is updated vcg::tri::UpdateBounding::Box(old_mesh); // MARCHING CUBES CALLS Point3i min=Point3i((int)ceil(old_mesh.bbox.min.V(0)),(int)ceil(old_mesh.bbox.min.V(1)),(int)ceil(old_mesh.bbox.min.V(2))); Point3i max=Point3i((int)ceil(old_mesh.bbox.max.V(0)),(int)ceil(old_mesh.bbox.max.V(1)),(int)ceil(old_mesh.bbox.max.V(2))); vcg::Box3 boxInt=Box3(min,max); float rx=((float)boxInt.DimX())/(float)accuracy.X(); float ry=((float)boxInt.DimY())/(float)accuracy.Y(); float rz=((float)boxInt.DimZ())/(float)accuracy.Z(); int rxi=(int)ceil(rx); int ryi=(int)ceil(ry); int rzi=(int)ceil(rz); Point3i res=Point3i(rxi,ryi,rzi); MyWalker walker(boxInt,res); walker.max_dim=max_dist; /*new_mesh.vert.reserve(old_mesh.vn*2); new_mesh.face.reserve(old_mesh.fn*2);*/ /*if (mm==MMarchingCubes) {*/ MarchingCubes mc(new_mesh, walker); walker.BuildMesh(old_mesh,new_mesh,mc); /*}*/ /*else if (mm==MExtendedMarchingCubes) { ExtendedMarchingCubes mc(new_mesh, walker,30); walker.BuildMesh(old_mesh,new_mesh,mc); }*/ if (New_Mesh::HasFFTopology()) vcg::tri::UpdateTopology::FaceFace(new_mesh); if (New_Mesh::HasVFTopology()) vcg::tri::UpdateTopology::VertexFace(new_mesh); if (New_Mesh::HasPerFaceNormal()) vcg::tri::UpdateNormals::PerFaceNormalized(new_mesh); if (New_Mesh::HasPerVertexNormal()) vcg::tri::UpdateNormals::PerVertexNormalized(new_mesh); } };//end class resampler };//end namespace trimesh };//end namespace vcg #endifqutemol/vcg/vcg/complex/trimesh/create/extended_marching_cubes.h0000444000175000017500000004301510461146633023556 0ustar mbamba/**************************************************************************** * VCGLib o o * * Visual and Computer Graphics Library o o * * _ O _ * * Copyright(C) 2004 \/)\/ * * Visual Computing Lab /\/| * * ISTI - Italian National Research Council | * * \ * * All rights reserved. * * * * 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. * * * * 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 (http://www.gnu.org/licenses/gpl.txt) * * for more details. * * * ****************************************************************************/ /***************************************************************************/ #ifndef __VCG_EXTENDED_MARCHING_CUBES #define __VCG_EXTENDED_MARCHING_CUBES #include #include #include #include #include #include #include #include #include #include #include #include #include "emc_lookup_table.h" namespace vcg { 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 */ //! 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; #else #ifdef _WIN64 typedef unsigned __int64 size_t; #else 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 struct { size_t face, edge; } LightEdge; /*! * 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; }; /*! * * 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; }; /*! * 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]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; 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); 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; } }; // 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]; /*! * 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 ]; for (i=0; ivert[ vertices_idx[i] ].P(); normals[i] = _mesh->vert[ vertices_idx[i] ].N(); } // 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 // 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 = vcg::math::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); double *b = new double[ vertices_num ]; for (i=0; i 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 if (rank == 2) { double smin = DBL_MAX; // the max value, as defined in unsigned int sminid = 0; unsigned int srank = vcg::math::Min< unsigned int >(vertices_num, 3u); for (i=0; i least squares, least norm solution x 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]); point += center; // insert the feature-point VertexPointer mean_point = &*AllocatorType::AddVertices( *_mesh, 1); mean_point->SetUserBit(_featureFlag); mean_point->P() = point; mean_point->N().Zero(); delete []x; 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() { size_t i; std::vector< LightEdge > edges; FaceIterator f_iter = _mesh->face.begin(); FaceIterator f_end = _mesh->face.end(); for (i=0; f_iter!=f_end; f_iter++, i++) { if (f_iter->V(1) > f_iter->V(0)) { LightEdge le; le.face = i; le.edge = 0; edges.push_back( le ); } if (f_iter->V(2) > f_iter->V(1)) { LightEdge le; le.face = i; le.edge = 1; edges.push_back( LightEdge(le)); } if (f_iter->V(0) > f_iter->V(2)) { LightEdge le; le.face = i; le.edge = 2; edges.push_back( le ); } } vcg::tri::UpdateTopology< TRIMESH_TYPE >::VertexFace( *_mesh ); vcg::tri::UpdateTopology< TRIMESH_TYPE >::FaceFace( *_mesh ); 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; if (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 of FlipEdges }; // end of class ExtendedMarchingCubes // /*! @} */ // end of Doxygen documentation } // end of namespace tri }; // end of namespace vcg #endif // __VCG_EXTENDED_MARCHING_CUBES qutemol/vcg/vcg/complex/trimesh/smooth.h0000444000175000017500000007637611013343746017011 0ustar mbamba/**************************************************************************** * VCGLib o o * * Visual and Computer Graphics Library o o * * _ O _ * * Copyright(C) 2004 \/)\/ * * Visual Computing Lab /\/| * * ISTI - Italian National Research Council | * * \ * * All rights reserved. * * * * 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. * * * * 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 (http://www.gnu.org/licenses/gpl.txt) * * for more details. * * * ****************************************************************************/ /**************************************************************************** History $Log: smooth.h,v $ Revision 1.20 2008/05/16 17:44:06 cignoni updated to the new temporary data structure and heavily restructured in a big class with uniform naming Revision 1.19 2008/05/08 23:50:44 cignoni renamed vertex quality smoothing added face normal smoothing FF (and added a VF to the previous face normal smoothing) Revision 1.18 2008/05/02 09:43:25 cignoni Added color smoothing, scale dependent laplacian changed a SD_old into SD fujumori, improved comments. Revision 1.17 2008/04/18 17:48:29 cignoni added facenormal smoothing Revision 1.16 2008/02/07 10:24:51 cignoni added a missing IsD() check Revision 1.15 2007/11/05 23:47:20 cignoni added selection to the pasodoble smoothing Revision 1.14 2007/03/27 09:40:47 cignoni Changed use of selected to visited flags. Improved variable namings and comments Revision 1.13 2006/11/07 15:13:56 zifnab1974 Necessary changes for compilation with gcc 3.4.6. Especially the hash function is a problem Revision 1.12 2006/11/07 11:28:02 cignoni Added Quality weighted laplacian smoothing Revision 1.11 2006/10/19 07:33:03 cignoni Corrected Laplacian, Added selection to HCSmooth Revision 1.10 2006/09/25 09:41:41 cignoni Added new version of pasodoble smoothing Revision 1.9 2006/02/06 10:45:47 cignoni Added missing typenames Revision 1.7 2006/01/24 13:23:22 pietroni used template types instead of point3f and float inside function calls Revision 1.6 2005/12/06 17:55:16 pietroni 1 bug corrected Revision 1.5 2005/12/02 16:24:56 pietroni corrected 1 bug in Cross Prod Gradient Revision 1.4 2005/11/23 16:24:44 pietroni corrected CrossProdGradient( ) Revision 1.3 2005/07/11 13:12:05 cignoni small gcc-related compiling issues (typenames,ending cr, initialization order) Revision 1.2 2005/03/16 16:14:12 spinelli aggiunta funzione PasoDobleSmooth e relative: - FitMesh - FaceErrorGrad - CrossProdGradient - TriAreaGradient - NormalSmooth e le classi: - PDVertInfo - PDFaceInfo necessarie per utilizzare SimpleTempData Revision 1.1 2004/12/11 14:53:19 ganovelli first partial porting: compiled gcc,intel and msvc ****************************************************************************/ #ifndef __VCGLIB__SMOOTH #define __VCGLIB__SMOOTH #include #include #include #include namespace vcg { namespace tri { /// /** \addtogroup trimesh */ /*@{*/ /// Class of static functions to smooth and fair meshes and their attributes. template class Smooth { public: typedef SmoothMeshType MeshType; typedef typename MeshType::VertexType VertexType; typedef typename MeshType::VertexType::CoordType CoordType; typedef typename MeshType::VertexPointer VertexPointer; typedef typename MeshType::VertexIterator VertexIterator; typedef typename MeshType::ScalarType ScalarType; typedef typename MeshType::FaceType FaceType; typedef typename MeshType::FacePointer FacePointer; typedef typename MeshType::FaceIterator FaceIterator; typedef typename MeshType::FaceContainer FaceContainer; typedef typename vcg::Box3 Box3Type; typedef typename vcg::face::VFIterator VFLocalIterator; class ScaleLaplacianInfo { public: CoordType PntSum; ScalarType LenSum; }; // This is precisely what curvature flow does. // Curvature flow smoothes the surface by moving along the surface // normal n with a speed equal to the mean curvature void VertexCoordLaplacianCurvatureFlow(MeshType &m, int step, ScalarType delta) { } // Another Laplacian smoothing variant, // here we sum the baricenter of the faces incidents on each vertex weighting them with the angle static void VertexCoordLaplacianAngleWeighted(MeshType &m, int step, ScalarType delta) { ScaleLaplacianInfo lpz; lpz.PntSum=CoordType(0,0,0); lpz.LenSum=0; SimpleTempData TD(m.vert,lpz); FaceIterator fi; for(int i=0;iP() + (*fi).V(1)->P() + (*fi).V(2)->P())/3.0; CoordType e0=((*fi).V(0)->P() - (*fi).V(1)->P()).Normalize(); CoordType e1=((*fi).V(1)->P() - (*fi).V(2)->P()).Normalize(); CoordType e2=((*fi).V(2)->P() - (*fi).V(0)->P()).Normalize(); a[0]=AngleN(-e0,e2); a[1]=AngleN(-e1,e0); a[2]=AngleN(-e2,e1); //assert(fabs(M_PI -a[0] -a[1] -a[2])<0.0000001); for(int j=0;j<3;++j){ CoordType dir= (mp-(*fi).V(j)->P()).Normalize(); TD[(*fi).V(j)].PntSum+=dir*a[j]; TD[(*fi).V(j)].LenSum+=a[j]; // well, it should be named angleSum } } for(vi=m.vert.begin();vi!=m.vert.end();++vi) if(!(*vi).IsD() && TD[*vi].LenSum>0 ) (*vi).P() = (*vi).P() + (TD[*vi].PntSum/TD[*vi].LenSum ) * delta; } }; // Scale dependent laplacian smoothing [Fujiwara 95] // as described in // Implicit Fairing of Irregular Meshes using Diffusion and Curvature Flow // Mathieu Desbrun, Mark Meyer, Peter Schroeder, Alan H. Barr // SIGGRAPH 99 // REQUIREMENTS: Border Flags. // // Note the delta parameter is in a absolute unit // it should be a small percentage of the shortest edge. static void VertexCoordScaleDependentLaplacian_Fujiwara(MeshType &m, int step, ScalarType delta) { SimpleTempData TD(m.vert); ScaleLaplacianInfo lpz; lpz.PntSum=CoordType(0,0,0); lpz.LenSum=0; TD.Start(lpz); FaceIterator fi; for(int i=0;iP() -(*fi).V(j)->P(); ScalarType len=Norm(edge); edge/=len; TD[(*fi).V(j)].PntSum+=edge; TD[(*fi).V1(j)].PntSum-=edge; TD[(*fi).V(j)].LenSum+=len; TD[(*fi).V1(j)].LenSum+=len; } for(fi=m.face.begin();fi!=m.face.end();++fi)if(!(*fi).IsD()) for(int j=0;j<3;++j) // se l'edge j e' di bordo si riazzera tutto e si riparte if((*fi).IsB(j)) { TD[(*fi).V(j)].PntSum=CoordType(0,0,0); TD[(*fi).V1(j)].PntSum=CoordType(0,0,0); TD[(*fi).V(j)].LenSum=0; TD[(*fi).V1(j)].LenSum=0; } for(fi=m.face.begin();fi!=m.face.end();++fi) if(!(*fi).IsD()) for(int j=0;j<3;++j) if((*fi).IsB(j)) { CoordType edge= (*fi).V1(j)->P() -(*fi).V(j)->P(); ScalarType len=Norm(edge); edge/=len; TD[(*fi).V(j)].PntSum+=edge; TD[(*fi).V1(j)].PntSum-=edge; TD[(*fi).V(j)].LenSum+=len; TD[(*fi).V1(j)].LenSum+=len; } // The fundamental part: // We move the new point of a quantity // // L(M) = 1/Sum(edgelen) * Sum(Normalized edges) // for(vi=m.vert.begin();vi!=m.vert.end();++vi) if(!(*vi).IsD() && TD[*vi].LenSum>0 ) (*vi).P() = (*vi).P() + (TD[*vi].PntSum/TD[*vi].LenSum)*delta; } TD.Stop(); }; class LaplacianInfo { public: CoordType sum; ScalarType cnt; }; // Classical Laplacian Smoothing. Each vertex can be moved onto the average of the adjacent vertices. // Can smooth only the selected vertices and weight the smoothing according to the quality // In the latter case 0 means that the vertex is not moved and 1 means that the vertex is moved onto the computed position. static void VertexCoordLaplacian(MeshType &m, int step, bool SmoothSelected=false, float QualityWeight=0) { LaplacianInfo lpz; lpz.sum=CoordType(0,0,0); lpz.cnt=1; SimpleTempData TD(m.vert,lpz); for(int i=0;iP(); TD[(*fi).V1(j)].sum+=(*fi).V(j)->P(); ++TD[(*fi).V(j)].cnt; ++TD[(*fi).V1(j)].cnt; } // si azzaera i dati per i vertici di bordo for(fi=m.face.begin();fi!=m.face.end();++fi) if(!(*fi).IsD()) for(int j=0;j<3;++j) if((*fi).IsB(j)) { //TD[(*fi).V(j)]=lpz; //TD[(*fi).V1(j)]=lpz; TD[(*fi).V0(j)].sum=(*fi).P0(j); TD[(*fi).V1(j)].sum=(*fi).P1(j); TD[(*fi).V0(j)].cnt=1; TD[(*fi).V1(j)].cnt=1; } // se l'edge j e' di bordo si deve mediare solo con gli adiacenti for(fi=m.face.begin();fi!=m.face.end();++fi) if(!(*fi).IsD()) for(int j=0;j<3;++j) if((*fi).IsB(j)) { TD[(*fi).V(j)].sum+=(*fi).V1(j)->P(); TD[(*fi).V1(j)].sum+=(*fi).V(j)->P(); ++TD[(*fi).V(j)].cnt; ++TD[(*fi).V1(j)].cnt; } if(QualityWeight>0) { // quality weighted smoothing // We assume that weights are in the 0..1 range. assert(tri::HasPerVertexQuality(m)); for(vi=m.vert.begin();vi!=m.vert.end();++vi) if(!(*vi).IsD() && TD[*vi].cnt>0 ) if(!SmoothSelected || (*vi).IsS()) { float q=(*vi).Q(); (*vi).P()=(*vi).P()*q + (TD[*vi].sum/TD[*vi].cnt)*(1.0-q); } } else { for(vi=m.vert.begin();vi!=m.vert.end();++vi) if(!(*vi).IsD() && TD[*vi].cnt>0 ) if(!SmoothSelected || (*vi).IsS()) (*vi).P()=TD[*vi].sum/TD[*vi].cnt; } } // end for }; /* Improved Laplacian Smoothing of Noisy Surface Meshes J. Vollmer, R. Mencl, and H. Mller EUROGRAPHICS Volume 18 (1999), Number 3 */ class HCSmoothInfo { public: CoordType dif; CoordType sum; int cnt; }; static void VertexCoordLaplacianHC(MeshType &m, int step, bool SmoothSelected=false ) { ScalarType beta=0.5; HCSmoothInfo lpz; lpz.sum=CoordType(0,0,0); lpz.dif=CoordType(0,0,0); lpz.cnt=0; SimpleTempData TD(m.vert,lpz); // First Loop compute the laplacian FaceIterator fi; for(fi=m.face.begin();fi!=m.face.end();++fi)if(!(*fi).IsD()) { for(int j=0;j<3;++j) { TD[(*fi).V(j)].sum+=(*fi).V1(j)->P(); TD[(*fi).V1(j)].sum+=(*fi).V(j)->P(); ++TD[(*fi).V(j)].cnt; ++TD[(*fi).V1(j)].cnt; // se l'edge j e' di bordo si deve sommare due volte if((*fi).IsB(j)) { TD[(*fi).V(j)].sum+=(*fi).V1(j)->P(); TD[(*fi).V1(j)].sum+=(*fi).V(j)->P(); ++TD[(*fi).V(j)].cnt; ++TD[(*fi).V1(j)].cnt; } } } VertexIterator vi; for(vi=m.vert.begin();vi!=m.vert.end();++vi) if(!(*vi).IsD()) TD[*vi].sum/=(float)TD[*vi].cnt; // Second Loop compute average difference for(fi=m.face.begin();fi!=m.face.end();++fi) if(!(*fi).IsD()) { for(int j=0;j<3;++j) { TD[(*fi).V(j)].dif +=TD[(*fi).V1(j)].sum-(*fi).V1(j)->P(); TD[(*fi).V1(j)].dif+=TD[(*fi).V(j)].sum-(*fi).V(j)->P(); // se l'edge j e' di bordo si deve sommare due volte if((*fi).IsB(j)) { TD[(*fi).V(j)].dif +=TD[(*fi).V1(j)].sum-(*fi).V1(j)->P(); TD[(*fi).V1(j)].dif+=TD[(*fi).V(j)].sum-(*fi).V(j)->P(); } } } for(vi=m.vert.begin();vi!=m.vert.end();++vi) { TD[*vi].dif/=(float)TD[*vi].cnt; if(!SmoothSelected || (*vi).IsS()) (*vi).P()= TD[*vi].sum - (TD[*vi].sum - (*vi).P())*beta + (TD[*vi].dif)*(1.f-beta); } }; // Laplacian smooth of the quality. class ColorSmoothInfo { public: unsigned int r; unsigned int g; unsigned int b; unsigned int a; int cnt; }; static void VertexColorLaplacian(MeshType &m, int step, bool SmoothSelected=false) { ColorSmoothInfo csi; csi.r=0; csi.g=0; csi.b=0; csi.cnt=0; SimpleTempData TD(m.vert,csi); for(int i=0;iC()[0]; TD[(*fi).V(j)].g+=(*fi).V1(j)->C()[1]; TD[(*fi).V(j)].b+=(*fi).V1(j)->C()[2]; TD[(*fi).V(j)].a+=(*fi).V1(j)->C()[3]; TD[(*fi).V1(j)].r+=(*fi).V(j)->C()[0]; TD[(*fi).V1(j)].g+=(*fi).V(j)->C()[1]; TD[(*fi).V1(j)].b+=(*fi).V(j)->C()[2]; TD[(*fi).V1(j)].a+=(*fi).V(j)->C()[3]; ++TD[(*fi).V(j)].cnt; ++TD[(*fi).V1(j)].cnt; } // si azzaera i dati per i vertici di bordo for(fi=m.face.begin();fi!=m.face.end();++fi) if(!(*fi).IsD()) for(int j=0;j<3;++j) if((*fi).IsB(j)) { TD[(*fi).V(j)]=csi; TD[(*fi).V1(j)]=csi; } // se l'edge j e' di bordo si deve mediare solo con gli adiacenti for(fi=m.face.begin();fi!=m.face.end();++fi) if(!(*fi).IsD()) for(int j=0;j<3;++j) if((*fi).IsB(j)) { TD[(*fi).V(j)].r+=(*fi).V1(j)->C()[0]; TD[(*fi).V(j)].g+=(*fi).V1(j)->C()[1]; TD[(*fi).V(j)].b+=(*fi).V1(j)->C()[2]; TD[(*fi).V(j)].a+=(*fi).V1(j)->C()[3]; TD[(*fi).V1(j)].r+=(*fi).V(j)->C()[0]; TD[(*fi).V1(j)].g+=(*fi).V(j)->C()[1]; TD[(*fi).V1(j)].b+=(*fi).V(j)->C()[2]; TD[(*fi).V1(j)].a+=(*fi).V(j)->C()[3]; ++TD[(*fi).V(j)].cnt; ++TD[(*fi).V1(j)].cnt; } for(vi=m.vert.begin();vi!=m.vert.end();++vi) if(!(*vi).IsD() && TD[*vi].cnt>0 ) if(!SmoothSelected || (*vi).IsS()) { (*vi).C()[0] = (unsigned int) ceil((double) (TD[*vi].r / TD[*vi].cnt)); (*vi).C()[1] = (unsigned int) ceil((double) (TD[*vi].g / TD[*vi].cnt)); (*vi).C()[2] = (unsigned int) ceil((double) (TD[*vi].b / TD[*vi].cnt)); (*vi).C()[3] = (unsigned int) ceil((double) (TD[*vi].a / TD[*vi].cnt)); } } }; // Laplacian smooth of the quality. class QualitySmoothInfo { public: ScalarType sum; int cnt; }; static void VertexQualityLaplacian(MeshType &m, int step=1, bool SmoothSelected=false) { QualitySmoothInfo lpz; lpz.sum=0; lpz.cnt=0; SimpleTempData TD(m.vert,lpz); //TD.Start(lpz); for(int i=0;iQ(); TD[(*fi).V1(j)].sum+=(*fi).V(j)->Q(); ++TD[(*fi).V(j)].cnt; ++TD[(*fi).V1(j)].cnt; } // si azzaera i dati per i vertici di bordo for(fi=m.face.begin();fi!=m.face.end();++fi) if(!(*fi).IsD()) for(int j=0;j<3;++j) if((*fi).IsB(j)) { TD[(*fi).V(j)]=lpz; TD[(*fi).V1(j)]=lpz; } // se l'edge j e' di bordo si deve mediare solo con gli adiacenti for(fi=m.face.begin();fi!=m.face.end();++fi) if(!(*fi).IsD()) for(int j=0;j<3;++j) if((*fi).IsB(j)) { TD[(*fi).V(j)].sum+=(*fi).V1(j)->Q(); TD[(*fi).V1(j)].sum+=(*fi).V(j)->Q(); ++TD[(*fi).V(j)].cnt; ++TD[(*fi).V1(j)].cnt; } //VertexIterator vi; for(vi=m.vert.begin();vi!=m.vert.end();++vi) if(!(*vi).IsD() && TD[*vi].cnt>0 ) if(!SmoothSelected || (*vi).IsS()) (*vi).Q()=TD[*vi].sum/TD[*vi].cnt; } //TD.Stop(); }; static void VertexNormalLaplacian(MeshType &m, int step,bool SmoothSelected=false) { SimpleTempData TD(m.vert); LaplacianInfo lpz; lpz.sum=CoordType(0,0,0); lpz.cnt=0; TD.Start(lpz); for(int i=0;iN(); TD[(*fi).V1(j)].sum+=(*fi).V(j)->N(); ++TD[(*fi).V(j)].cnt; ++TD[(*fi).V1(j)].cnt; } // si azzaera i dati per i vertici di bordo for(fi=m.face.begin();fi!=m.face.end();++fi) if(!(*fi).IsD()) for(int j=0;j<3;++j) if((*fi).IsB(j)) { TD[(*fi).V(j)]=lpz; TD[(*fi).V1(j)]=lpz; } // se l'edge j e' di bordo si deve mediare solo con gli adiacenti for(fi=m.face.begin();fi!=m.face.end();++fi) if(!(*fi).IsD()) for(int j=0;j<3;++j) if((*fi).IsB(j)) { TD[(*fi).V(j)].sum+=(*fi).V1(j)->N(); TD[(*fi).V1(j)].sum+=(*fi).V(j)->N(); ++TD[(*fi).V(j)].cnt; ++TD[(*fi).V1(j)].cnt; } //VertexIterator vi; for(vi=m.vert.begin();vi!=m.vert.end();++vi) if(!(*vi).IsD() && TD[*vi].cnt>0 ) if(!SmoothSelected || (*vi).IsS()) (*vi).N()=TD[*vi].sum/TD[*vi].cnt; } TD.Stop(); }; // Smooth solo lungo la direzione di vista // alpha e' compreso fra 0(no smoot) e 1 (tutto smoot) // Nota che se smootare il bordo puo far fare bandierine. static void VertexCoordViewDepth(MeshType &m, const CoordType & viewpoint, const ScalarType alpha, int step, bool SmoothBorder=false ) { SimpleTempData TD(m.vert); LaplacianInfo lpz; lpz.sum=CoordType(0,0,0); lpz.cnt=0; TD.Start(lpz); for(int i=0;iSupervisor_P(); TD[(*fi).V1(j)].sum+=(*fi).V(j)->Supervisor_P(); ++TD[(*fi).V(j)].cnt; ++TD[(*fi).V1(j)].cnt; } // si azzaera i dati per i vertici di bordo for(fi=m.face.begin();fi!=m.face.end();++fi) if(!(*fi).IsD()) for(int j=0;j<3;++j) if((*fi).IsB(j)) { TD[(*fi).V(j)]=lpz; TD[(*fi).V1(j)]=lpz; } // se l'edge j e' di bordo si deve mediare solo con gli adiacenti if(SmoothBorder) for(fi=m.face.begin();fi!=m.face.end();++fi) if(!(*fi).IsD()) for(int j=0;j<3;++j) if((*fi).IsB(j)) { TD[(*fi).V(j)].sum+=(*fi).V1(j)->Supervisor_P(); TD[(*fi).V1(j)].sum+=(*fi).V(j)->Supervisor_P(); ++TD[(*fi).V(j)].cnt; ++TD[(*fi).V1(j)].cnt; } for(vi=m.vert.begin();vi!=m.vert.end();++vi) if(!(*vi).IsD() && TD[*vi].cnt>0 ) { CoordType np = TD[*vi].sum/TD[*vi].cnt; CoordType d = (*vi).Supervisor_P() - viewpoint; d.Normalize(); ScalarType s = d * ( np - (*vi).Supervisor_P() ); (*vi).Supervisor_P() += d * (s*alpha); } } TD.Stop(); } /****************************************************************************************************************/ /****************************************************************************************************************/ // Paso Double Smoothing // The proposed // approach is a two step method where in the first step the face normals // are adjusted and then, in a second phase, the vertex positions are updated. /****************************************************************************************************************/ /****************************************************************************************************************/ // Classi di info class PDVertInfo { public: CoordType np; }; class PDFaceInfo { public: CoordType m; }; /***************************************************************************/ // Paso Doble Step 1 compute the smoothed normals /***************************************************************************/ // Requirements: // VF Topology // Normalized Face Normals // // This is the Normal Smoothing approach of Shen and Berner // Fuzzy Vector Median-Based Surface Smoothing TVCG 2004 void FaceNormalFuzzyVectorSB(MeshType &m, SimpleTempData &TD, ScalarType sigma) { int i; FaceIterator fi; for(fi=m.face.begin();fi!=m.face.end();++fi) { CoordType bc=(*fi).Barycenter(); // 1) Clear all the visited flag of faces that are vertex-adjacent to fi for(i=0;i<3;++i) { vcg::face::VFIterator ep(&*fi,i); while (!ep.End()) { ep.f->ClearV(); ++ep; } } // 1) Effectively average the normals weighting them with (*fi).SetV(); CoordType mm=CoordType(0,0,0); for(i=0;i<3;++i) { vcg::face::VFIterator ep(&*fi,i); while (!ep.End()) { if(! (*ep.f).IsV() ) { if(sigma>0) { ScalarType dd=SquaredDistance(ep.f->Barycenter(),bc); ScalarType ang=AngleN(ep.f->N(),(*fi).N()); mm+=ep.f->N()*exp((-sigma)*ang*ang/dd); } else mm+=ep.f->N(); (*ep.f).SetV(); } ++ep; } } mm.Normalize(); TD[*fi].m=mm; } } // Replace the normal of the face with the average of normals of the vertex adijacent faces. // Normals are weighted with face area. // It assumes that: // Normals are normalized: // VF adjacency is present. static void FaceNormalLaplacianVF(MeshType &m) { SimpleTempData TDF(m.face); PDFaceInfo lpzf; lpzf.m=CoordType(0,0,0); assert(tri::HasVFAdjacency(m)); TDF.Start(lpzf); int i; FaceIterator fi; tri::UpdateNormals::AreaNormalizeFace(m); for(fi=m.face.begin();fi!=m.face.end();++fi) if(!(*fi).IsD()) { CoordType bc=Barycenter(*fi); // 1) Clear all the visited flag of faces that are vertex-adjacent to fi for(i=0;i<3;++i) { VFLocalIterator ep(&*fi,i); for (;!ep.End();++ep) ep.f->ClearV(); } // 2) Effectively average the normals CoordType normalSum=(*fi).N(); for(i=0;i<3;++i) { VFLocalIterator ep(&*fi,i); for (;!ep.End();++ep) { if(! (*ep.f).IsV() ) { normalSum += ep.f->N(); (*ep.f).SetV(); } } } normalSum.Normalize(); TDF[*fi].m=normalSum; } for(fi=m.face.begin();fi!=m.face.end();++fi) (*fi).N()=TDF[*fi].m; tri::UpdateNormals::NormalizeFace(m); TDF.Stop(); } // Replace the normal of the face with the average of normals of the face adijacent faces. // Normals are weighted with face area. // It assumes that: // Normals are normalized: // FF adjacency is present. static void FaceNormalLaplacianFF(MeshType &m, int step=1, bool SmoothSelected=false ) { PDFaceInfo lpzf; lpzf.m=CoordType(0,0,0); SimpleTempData TDF(m.face,lpzf); assert(tri::HasFFAdjacency(m)); FaceIterator fi; tri::UpdateNormals::AreaNormalizeFace(m); for(int i=0;iN(); TDF[*fi].m=normalSum; } for(fi=m.face.begin();fi!=m.face.end();++fi) if(!SmoothSelected || (*fi).IsS()) (*fi).N()=TDF[*fi].m; tri::UpdateNormals::NormalizeFace(m); } } /***************************************************************************/ // Paso Doble Step 1 compute the smoothed normals /***************************************************************************/ // Requirements: // VF Topology // Normalized Face Normals // // This is the Normal Smoothing approach bsased on a angle thresholded weighting // sigma is in the 0 .. 1 range, it represent the cosine of a threshold angle. // sigma == 0 All the normals are averaged // sigma == 1 Nothing is averaged. // Only within the specified range are averaged toghether. The averagin is weighted with the static void FaceNormalAngleThreshold(MeshType &m, SimpleTempData &TD, ScalarType sigma) { int i; FaceIterator fi; for(fi=m.face.begin();fi!=m.face.end();++fi) if(!(*fi).IsD()) { CoordType bc=Barycenter(*fi); // 1) Clear all the visited flag of faces that are vertex-adjacent to fi for(i=0;i<3;++i) { VFLocalIterator ep(&*fi,i); for (;!ep.End();++ep) ep.f->ClearV(); } // 1) Effectively average the normals weighting them with the squared difference of the angle similarity // sigma is the cosine of a threshold angle. sigma \in 0..1 // sigma == 0 All the normals are averaged // sigma == 1 Nothing is averaged. // The averaging is weighted with the difference between normals. more similar the normal more important they are. CoordType normalSum=CoordType(0,0,0); for(i=0;i<3;++i) { VFLocalIterator ep(&*fi,i); for (;!ep.End();++ep) { if(! (*ep.f).IsV() ) { ScalarType cosang=ep.f->N()*(*fi).N(); if(cosang >= sigma) { ScalarType w = cosang-sigma; normalSum += ep.f->N()*(w*w); // similar normals have a cosang very close to 1 so cosang - sigma is maximized } (*ep.f).SetV(); } } } normalSum.Normalize(); TD[*fi].m=normalSum; } for(fi=m.face.begin();fi!=m.face.end();++fi) (*fi).N()=TD[*fi].m; } /****************************************************************************************************************/ // Restituisce il gradiente dell'area del triangolo nel punto p. // Nota che dovrebbe essere sempre un vettore che giace nel piano del triangolo e perpendicolare al lato opposto al vertice p. // Ottimizzato con Maple e poi pesantemente a mano. CoordType TriAreaGradient(CoordType &p,CoordType &p0,CoordType &p1) { CoordType dd = p1-p0; CoordType d0 = p-p0; CoordType d1 = p-p1; CoordType grad; ScalarType t16 = d0[1]* d1[2] - d0[2]* d1[1]; ScalarType t5 = -d0[2]* d1[0] + d0[0]* d1[2]; ScalarType t4 = -d0[0]* d1[1] + d0[1]* d1[0]; ScalarType delta= sqrtf(t4*t4 + t5*t5 +t16*t16); grad[0]= (t5 * (-dd[2]) + t4 * ( dd[1]))/delta; grad[1]= (t16 * (-dd[2]) + t4 * (-dd[0]))/delta; grad[2]= (t16 * ( dd[1]) + t5 * ( dd[0]))/delta; return grad; } template CoordType CrossProdGradient(CoordType &p, CoordType &p0, CoordType &p1, CoordType &m) { CoordType grad; CoordType p00=p0-p; CoordType p01=p1-p; grad[0] = (-p00[2] + p01[2])*m[1] + (-p01[1] + p00[1])*m[2]; grad[1] = (-p01[2] + p00[2])*m[0] + (-p00[0] + p01[0])*m[2]; grad[2] = (-p00[1] + p01[1])*m[0] + (-p01[0] + p00[0])*m[1]; return grad; } /* Deve Calcolare il gradiente di E(p) = A(p,p0,p1) (n - m)^2 = A(...) (2-2nm) = (p0-p)^(p1-p) 2A - 2A * ------------- m = 2A 2A - 2 (p0-p)^(p1-p) * m */ CoordType FaceErrorGrad(CoordType &p,CoordType &p0,CoordType &p1, CoordType &m) { return TriAreaGradient(p,p0,p1) *2.0f - CrossProdGradient(p,p0,p1,m) *2.0f ; } /***************************************************************************/ // Paso Doble Step 2 Fitta la mesh a un dato insieme di normali /***************************************************************************/ void FitMesh(MeshType &m, SimpleTempData &TDV, SimpleTempData &TDF, float lambda) { //vcg::face::Pos ep; vcg::face::VFIterator ep; VertexIterator vi; for(vi=m.vert.begin();vi!=m.vert.end();++vi) { CoordType ErrGrad=CoordType(0,0,0); ep.f=(*vi).VFp(); ep.z=(*vi).VFi(); while (!ep.End()) { ErrGrad+=FaceErrorGrad(ep.f->V(ep.z)->P(),ep.f->V1(ep.z)->P(),ep.f->V2(ep.z)->P(),TDF[ep.f].m); ++ep; } TDV[*vi].np=(*vi).P()-ErrGrad*(ScalarType)lambda; } for(vi=m.vert.begin();vi!=m.vert.end();++vi) (*vi).P()=TDV[*vi].np; } /****************************************************************************************************************/ static void FastFitMesh(MeshType &m, SimpleTempData &TDV, SimpleTempData &TDF, bool OnlySelected=false) { //vcg::face::Pos ep; vcg::face::VFIterator ep; VertexIterator vi; for(vi=m.vert.begin();vi!=m.vert.end();++vi) { CoordType Sum(0,0,0); ScalarType cnt=0; VFLocalIterator ep(&*vi); for (;!ep.End();++ep) { CoordType bc=Barycenter(*ep.F()); Sum += ep.F()->N()*(ep.F()->N()*(bc - (*vi).P())); ++cnt; } TDV[*vi].np=(*vi).P()+ Sum*(1.0/cnt); } if(OnlySelected) { for(vi=m.vert.begin();vi!=m.vert.end();++vi) if((*vi).IsS()) (*vi).P()=TDV[*vi].np; } else { for(vi=m.vert.begin();vi!=m.vert.end();++vi) (*vi).P()=TDV[*vi].np; } } static void VertexCoordPasoDoble(MeshType &m, int step, typename MeshType::ScalarType Sigma=0, int FitStep=10, typename MeshType::ScalarType FitLambda=0.05) { SimpleTempData< typename MeshType::VertContainer, PDVertInfo> TDV(m.vert); SimpleTempData< typename MeshType::FaceContainer, PDFaceInfo> TDF(m.face); PDVertInfo lpzv; lpzv.np=CoordType(0,0,0); PDFaceInfo lpzf; lpzf.m=CoordType(0,0,0); assert(m.HasVFTopology()); m.HasVFTopology(); TDV.Start(lpzv); TDF.Start(lpzf); for(int j=0;j::PerFace(m); FaceNormalAngleThreshold(m,TDF,Sigma); for(int k=0;k TDV(m.vert,lpzv); SimpleTempData< typename MeshType::FaceContainer, PDFaceInfo> TDF(m.face,lpzf); for(int j=0;j #include #include #include #include #include #include namespace vcg { namespace tri{ template class Stat { public: typedef StatMeshType MeshType; typedef typename MeshType::VertexType VertexType; typedef typename MeshType::VertexPointer VertexPointer; typedef typename MeshType::VertexIterator VertexIterator; typedef typename MeshType::ScalarType ScalarType; typedef typename MeshType::FaceType FaceType; typedef typename MeshType::FacePointer FacePointer; typedef typename MeshType::FaceIterator FaceIterator; typedef typename MeshType::FaceContainer FaceContainer; typedef typename vcg::Box3 Box3Type; static std::pair ComputePerVertexQualityMinMax( MeshType & m) // V1.0 { std::pair minmax = std::make_pair(std::numeric_limits::max(),-std::numeric_limits::max()); VertexIterator vi; for(vi = m.vert.begin(); vi != m.vert.end(); ++vi) if(!(*vi).IsD()) { if( (*vi).Q() < minmax.first) minmax.first=(*vi).Q(); if( (*vi).Q() > minmax.second) minmax.second=(*vi).Q(); } return minmax; } static void ComputePerVertexQualityHistogram( MeshType & m, Histogramf &h) // V1.0 { VertexIterator vi; int HistSize=10000; std::pair minmax = ComputePerVertexQualityMinMax(m); h.Clear(); h.SetRange( minmax.first,minmax.second, HistSize); for(vi = m.vert.begin(); vi != m.vert.end(); ++vi) if(!(*vi).IsD()) h.Add((*vi).Q()); // Sanity check; If some very wrong value has happened in the Q value, // the histogram is messed. If a significant percentage (20% )of the values are all in a single bin // we should try to solve the problem. No easy solution here. // We choose to compute the get the 1percentile and 99 percentile values as new mixmax ranges // and just to be sure enlarge the Histogram. if(h.MaxCount() > HistSize/5) { std::vector QV; QV.reserve(m.vn); for(vi = m.vert.begin(); vi != m.vert.end(); ++vi) if(!(*vi).IsD()) QV.push_back((*vi).Q()); std::nth_element(QV.begin(),QV.begin()+m.vn/100,QV.end()); float newmin=*(QV.begin()+m.vn/100); std::nth_element(QV.begin(),QV.begin()+m.vn-m.vn/100,QV.end()); float newmax=*(QV.begin()+m.vn-m.vn/100); h.Clear(); h.SetRange(newmin, newmax, HistSize*50); for(vi = m.vert.begin(); vi != m.vert.end(); ++vi) if(!(*vi).IsD()) h.Add((*vi).Q()); } } static int ComputeEdgeHistogram( MeshType & m, Histogramf &h) // V1.0 { ScalarType Diag = m.bbox.Diag(); h.Clear(); h.SetRange( 0, Diag, 10000); FaceIterator fi; for(fi = m.face.begin(); fi != m.face.end(); ++fi) { if(!(*fi).IsD()) { if( !(*fi).V(0)->IsS() && !(*fi).V(1)->IsS() ) { h.Add(Distance((*fi).V(0)->P(),(*fi).V(1)->P())); (*fi).V(0)->SetS(); (*fi).V(1)->SetS(); } if( !(*fi).V(1)->IsS() && !(*fi).V(2)->IsS()) { h.Add(Distance((*fi).V(1)->P(),(*fi).V(2)->P())); (*fi).V(2)->SetS(); (*fi).V(1)->SetS(); } if( !(*fi).V(2)->IsS() && !(*fi).V(0)->IsS()) { h.Add(Distance((*fi).V(2)->P(),(*fi).V(0)->P())); (*fi).V(0)->SetS(); (*fi).V(2)->SetS(); } } } VertexIterator vi; for(vi = m.cm.vert.begin(); vi != m.cm.vert.end(); ++vi) (*vi).ClearS(); return 0; } }; // end class } //End Namespace tri } // End Namespace vcg #endif qutemol/vcg/vcg/complex/trimesh/crease_cut.h0000444000175000017500000001757411002300000017556 0ustar mbamba/**************************************************************************** * VCGLib o o * * Visual and Computer Graphics Library o o * * _ O _ * * Copyright(C) 2008 \/)\/ * * Visual Computing Lab /\/| * * ISTI - Italian National Research Council | * * \ * * All rights reserved. * * * * 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. * * * * 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 (http://www.gnu.org/licenses/gpl.txt) * * for more details. * * * ****************************************************************************/ #ifndef __VCG_CREASE_CUT #define __VCG_CREASE_CUT #include #include #include namespace vcg { namespace tri { /* Crease Angle Assume che: la mesh abbia la topologia ff la mesh non abbia complex (o se li aveva fossero stati detached) Abbia le normali per faccia normalizzate!! Prende una mesh e duplica tutti gli edge le cui normali nelle facce incidenti formano un angolo maggiore di (espresso in rad). foreach face foreach unvisited vert vi scan the star of triangles around vi duplicating vi each time we encounter a crease angle. the new (and old) vertexes are put in a std::vector that is swapped with the original one at the end. Si tiene un vettore di interi 3 *fn che dice l'indice del vertice puntato da ogni faccia. quando si scandisce la stella intorno ad un vertici, per ogni wedge si scrive l'indice del vertice corrsipondente. */ template void CreaseCut(MESH_TYPE &m, float angleRad) { typedef typename MESH_TYPE::CoordType CoordType; typedef typename MESH_TYPE::ScalarType ScalarType; typedef typename MESH_TYPE::VertexType VertexType; typedef typename MESH_TYPE::VertexPointer VertexPointer; typedef typename MESH_TYPE::VertexIterator VertexIterator; typedef typename MESH_TYPE::FaceIterator FaceIterator; typedef typename MESH_TYPE::FaceType FaceType; typedef typename MESH_TYPE::FacePointer FacePointer; tri::Allocator::CompactVertexVector(m); tri::Allocator::CompactFaceVector(m); tri::UpdateNormals::NormalizeFace(m); assert(m.HasFFTopology()); typename MESH_TYPE::ScalarType cosangle=math::Cos(angleRad); tri::UpdateFlags::VertexClearV(m); std::vector indVec(m.fn*3,-1); int newVertexCounter=m.vn; int creaseCounter=0; int startVn=m.vn; FaceIterator fi; const FaceType * nextf; for(fi=m.face.begin();fi!=m.face.end();++fi) for(int j=0;j<3;++j) if(!(*fi).V(j)->IsV() ) // foreach unvisited vertex we loop around it searching for creases. { (*fi).V(j)->SetV(); face::JumpingPos iPos(&*fi,j,(*fi).V(j)); size_t vertInd = Index(m,iPos.v); // bool isBorderVertex = iPos.FindBorder(); // for border vertex we start from the border. face::JumpingPos startPos=iPos; if(!isBorderVertex) // for internal vertex we search the first crease and start from it { do { ScalarType dotProd = iPos.FFlip()->cN() * iPos.f->N(); iPos.NextFE(); if(dotProdcN() * iPos.f->N(); // test normal with the next face (fflip) size_t faceInd = Index(m,iPos.f); indVec[faceInd*3+ iPos.VInd()] = curVertexCounter; if(dotProd0 && (!isBorderVertex) ) newVertexCounter--; } // A questo punto ho un vettore che mi direbbe per ogni faccia quale vertice devo mettere. Dopo che ho aggiunto i vertici necessari, // rifaccio il giro delle facce qDebug("adding %i vert for %i crease edges ",newVertexCounter-m.vn, creaseCounter); tri::Allocator::AddVertices(m,newVertexCounter-m.vn); tri::UpdateFlags::VertexClearV(m); for(fi=m.face.begin();fi!=m.face.end();++fi) for(int j=0;j<3;++j) // foreach unvisited vertex { size_t faceInd = Index(m, *fi); size_t vertInd = Index(m, (*fi).V(j)); int curVertexInd = indVec[faceInd*3+ j]; assert(curVertexInd != -1); assert(curVertexInd < m.vn); if(curVertexInd < startVn) assert(curVertexInd == vertInd); if(curVertexInd >= startVn) { //m.vert[curVertexInd].ImportLocal(*((*fi).V(j))); tri::Append::ImportVertex(m.vert[curVertexInd],*((*fi).V(j))); (*fi).V(j) = & m.vert[curVertexInd]; } } tri::UpdateNormals::PerVertexFromCurrentFaceNormal(m); } } // end namespace tri } // end namespace vcg #endif /* face::Pos startPos=iPos; const FaceType * nextf; do{ size_t faceInd = Index(m,iPos.f); assert(iPos.f->V(iPos.VInd()) ==iPos.v); qDebug("Face %2i:%i - v%2i -- %2i",faceInd,iPos.VInd(),Index(m,iPos.v),curVertexCounter); indVec[faceInd*3+ iPos.VInd()] = curVertexCounter; nextf=iPos.FFlip(); ScalarType dotProd=nextf->cN() * iPos.f->N(); iPos.FlipF(); iPos.FlipE(); if(dotProd::AddVertices(m,newVertexCounter-m.vn); tri::UpdateFlags::VertexClearV(m); for(fi=m.face.begin();fi!=m.face.end();++fi) for(int j=0;j<3;++j) // foreach unvisited vertex { size_t faceInd = Index(m, *fi); size_t vertInd = Index(m, (*fi).V(j)); int curVertexInd = indVec[faceInd*3+ j]; qDebug("Setting Face %2i vert %2i : %2i -> %2i",faceInd,j,vertInd,curVertexInd); assert(curVertexInd != -1); assert(curVertexInd < m.vn); if(curVertexInd < startVn) assert(curVertexInd == vertInd); if(curVertexInd >= startVn) { //m.vert[curVertexInd].ImportLocal(*((*fi).V(j))); tri::Append::ImportVertex(m.vert[curVertexInd],*((*fi).V(j))); (*fi).V(j) = & m.vert[curVertexInd]; } } */ qutemol/vcg/vcg/complex/trimesh/allocate.h0000444000175000017500000005675411013062633017253 0ustar mbamba/**************************************************************************** * VCGLib o o * * Visual and Computer Graphics Library o o * * _ O _ * * Copyright(C) 2004 \/)\/ * * Visual Computing Lab /\/| * * ISTI - Italian National Research Council | * * \ * * All rights reserved. * * * * 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. * * * * 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 (http://www.gnu.org/licenses/gpl.txt) * * for more details. * * * ****************************************************************************/ /**************************************************************************** History $Log: allocate.h,v $ Revision 1.44 2008/05/15 16:32:27 ganovelli PerVertexAttribute and PerFaceAttribute added to Trimesh Revision 1.43 2008/04/18 17:45:23 cignoni fast return for compacting functions if no compacting is needed Revision 1.42 2008/04/10 09:18:57 cignoni moved Index function from append to the allocate Revision 1.41 2008/04/03 22:47:10 cignoni template the reorder functions on the vector types (for ocf) Revision 1.40 2008/03/11 09:22:07 cignoni Completed the garbage collecting functions CompactVertexVector and CompactFaceVector. Revision 1.39 2007/12/11 20:18:55 cignoni forgotten required std:: Revision 1.38 2007/12/11 11:35:50 cignoni Added the CompactVertexVector garbage collecting function. Revision 1.37 2007/10/16 16:46:53 cignoni Added Allocator::DeleteFace and Allocator::DeleteVertex; Now the use of SetD() should be deprecated. Revision 1.36 2007/01/11 10:24:25 cignoni Added test in AddVertices to do not update un-initalized vert references (for newly allocated faces) Revision 1.35 2006/11/29 15:58:50 cignoni Added check with the new end and avoided dangerous updating of already updated pointers Revision 1.34 2006/11/28 22:34:28 cignoni Added default constructor with null initialization to adjacency members. AddFaces and AddVertices NEED to know if the topology is correctly computed to update it. Revision 1.33 2006/11/13 13:12:27 ponchio Removed a couple of useless assert. Revision 1.32 2006/10/27 11:06:29 ganovelli the calls to HasFFAdjacency e HasVFAdjacency have been changed to override them for the optional attributes (see vcg/complex/trimesh/base.h) Revision 1.31 2006/10/17 06:54:14 fiorin Added #include Revision 1.30 2006/10/02 09:31:47 ponchio usual typename missing Revision 1.29 2006/09/29 15:11:41 giec Fixed a few bug. Revision 1.28 2006/09/29 14:40:22 cignoni Removed a useless, wrong version of AddFaces Revision 1.27 2006/02/28 12:22:48 spinelli fix bug end iterator++ Revision 1.26 2006/02/28 12:13:49 spinelli fix bug end iterator++ Revision 1.25 2005/11/10 15:37:58 cignoni Removed flags clearing (now it should be in the constructor of face and vertex) Revision 1.24 2005/10/13 09:32:11 cignoni Re-inserted the cFFp and cVFp access. If only the const version of the member function exists, the compiler will call it when a non-const object invokes that function Revision 1.23 2005/10/12 17:26:19 ponchio cFFp doesn not exist -> FFp (there is the const version...) same for cVFp. Revision 1.22 2005/10/12 10:47:21 cignoni Removed clearing of flags of added faces. Now the flag component has a constructor that clear it. FF and VF adjacency are updated only if they are present and consistent (e.g. only if VFp(k) != 0 or FFp(k)!=0) Revision 1.21 2005/07/01 11:22:00 cignoni Corrected for the fourth time line a cast to Facetype at line 341. Read the notes there before changing it again Revision 1.20 2005/06/09 14:14:29 ganovelli two warnings on type cast Revision 1.19 2005/04/27 16:08:39 callieri in addfaces, added casting for face* returned from vertex.VFp() [borland] Revision 1.18 2005/03/23 13:22:57 turini Wrong left parenthesis removed. Revision 1.17 2005/03/23 11:29:49 ganovelli cast int->iterator corrected Revision 1.16 2005/02/19 10:43:11 ponchio reverted tarini mod Revision 1.15 2005/02/08 17:14:28 tarini aggiunto un typecast a (FaceType*) per farlo compilare under Mingw comp Revision 1.14 2004/10/14 15:08:04 pietroni added #include Revision 1.13 2004/09/07 07:36:32 fasano Replaced some typename definitions Revision 1.12 2004/08/25 15:15:26 ganovelli minor changes to comply gcc compiler (typename's and stuff) Revision 1.11 2004/08/07 17:38:00 pietroni solved errors on AddFaces relative to VFp pointers of faces Revision 1.10 2004/08/07 16:16:32 pietroni corrected errors in AddFaces ( must be updated pointers to chain of faces of VFTopology) Revision 1.9 2004/08/05 16:44:06 pietroni added addafaces funtion with local values Revision 1.8 2004/07/15 11:40:34 ganovelli VFb to VFp Revision 1.7 2004/05/11 14:12:13 ganovelli general comment: minor modifications to compile with g++. Almost all insertions of "typename" keyword and new line at the end of file Revision 1.6 2004/05/10 13:24:21 cignoni Updated names of adj functions and added ending newline Revision 1.5 2004/04/21 14:06:10 ganovelli #ifndef added Revision 1.4 2004/03/31 14:43:56 cignoni bug in update of VF adj Revision 1.3 2004/03/12 15:25:29 cignoni Corrected bug on the return of a wrong iterator Revision 1.2 2004/03/03 15:35:52 cignoni Yet another cr lf mismatch Revision 1.1 2004/02/24 21:36:42 cignoni grouped documentation, changed typenames and reflection mechanism Revision 1.1 2004/02/19 13:11:06 cignoni Initial commit ****************************************************************************/ #ifndef __VCGLIB_TRIALLOCATOR #define __VCGLIB_TRIALLOCATOR #include #include #include namespace vcg { namespace tri { /** \addtogroup trimesh */ template size_t Index(MeshType &m, typename MeshType::VertexType &v) {return &v-&*m.vert.begin();} template size_t Index(MeshType &m, typename MeshType::FaceType &f) {return &f-&*m.face.begin();} template size_t Index(MeshType &m, const typename MeshType::VertexType *vp) {return vp-&*m.vert.begin();} template size_t Index(MeshType &m, const typename MeshType::FaceType * fp) {return fp-&*m.face.begin();} // Placeholder. // this one is called by the Compact and overridden by more specialized functions for OCF classes. // that manage also the additional types template void ReorderFace( std::vector &newVertIndex, std::vector &vert) {} template void ReorderVert( std::vector &newVertIndex, std::vector &vert) {} template void ReorderAttribute(ATTR_CONT &c,std::vector & newVertIndex, MeshType &m){ typename std::set::iterator ai; for(ai = c.begin(); ai != c.end(); ++ai) ((typename MeshType::HandlesWrapper)(*ai)).Reorder(newVertIndex); } template void ResizeAttribute(ATTR_CONT &c,const int & sz, MeshType &m){ typename std::set::iterator ai; for(ai =c.begin(); ai != c.end(); ++ai) ((typename MeshType::HandlesWrapper)(*ai)).Resize(m.vn); } /*@{*/ /// Class to safely add vertexes and faces to a mesh updating all the involved pointers. /// It provides static memeber to add either vertex or faces to a trimesh. template class Allocator { public: typedef AllocateMeshType MeshType; typedef typename MeshType::VertexType VertexType; typedef typename MeshType::VertexPointer VertexPointer; typedef typename MeshType::VertexIterator VertexIterator; typedef typename MeshType::VertContainer VertContainer; typedef typename MeshType::FaceType FaceType; typedef typename MeshType::FacePointer FacePointer; typedef typename MeshType::FaceIterator FaceIterator; typedef typename MeshType::FaceContainer FaceContainer; typedef typename MeshType::HandlesWrapper HandlesWrapper; typedef typename std::set::iterator HandlesIterator; typedef typename std::set::const_iterator HandlesConstIterator; typedef typename std::set::iterator HWIte; /** This class is used when allocating new vertexes and faces to update the pointers that can be changed when resizing the involved vectors of vertex or faces. It can also be used to prevent any update of the various mesh fields (e.g. in case you are building all the connections by hand as in a importer); */ template class PointerUpdater { public: void Clear(){newBase=oldBase=newEnd=oldEnd=0;preventUpdateFlag=false;}; void Update(SimplexPointerType &vp) { if(vp>=newBase && vp=oldBase); assert(vp &pu) { VertexIterator last; pu.Clear(); if(m.vert.empty()) pu.oldBase=0; // if the vector is empty we cannot find the last valid element else { pu.oldBase=&*m.vert.begin(); pu.oldEnd=&m.vert.back()+1; } m.vert.resize(m.vert.size()+n); m.vn+=n; typename std::set::iterator ai; for(ai = m.vert_attr.begin(); ai != m.vert_attr.end(); ++ai) ((typename MeshType::HandlesWrapper)(*ai)).Resize(m.vert.size()); pu.newBase = &*m.vert.begin(); pu.newEnd = &m.vert.back()+1; if(pu.NeedUpdate()) { FaceIterator fi; for (fi=m.face.begin(); fi!=m.face.end(); ++fi) if(!(*fi).IsD()) { if ((*fi).cV(0)!=0) pu.Update((*fi).V(0)); if ((*fi).cV(1)!=0) pu.Update((*fi).V(1)); if ((*fi).cV(2)!=0) pu.Update((*fi).V(2)); } // e poiche' lo spazio e' cambiato si ricalcola anche last da zero } unsigned int siz=(unsigned int)m.vert.size()-n; last = m.vert.begin(); advance(last,siz); return last;// deve restituire l'iteratore alla prima faccia aggiunta; } static VertexIterator AddVertices(MeshType &m, int n) { PointerUpdater pu; return AddVertices(m, n,pu); } /** Function to add n faces to the mesh. First wrapper, with no parameters */ static FaceIterator AddFaces(MeshType &m, int n) { PointerUpdater pu; return AddFaces(m,n,pu); } /** Function to add n faces to the mesh. Second Wrapper, with a vector of face pointer to be updated. */ static FaceIterator AddFaces(MeshType &m, int n,std::vector &local_vec) { PointerUpdater pu; FaceIterator f_ret= AddFaces(m,n,pu); typename std::vector::iterator fi; for(fi=local_vec.begin();fi!=local_vec.end();++fi) pu.Update(**fi); return f_ret; } /** Function to add n faces to the mesh. This is the only full featured function that is able to manage correctly all the internal pointers of the mesh (ff and vf relations). NOTE: THIS FUNCTION ALSO UPDATE FN */ static FaceIterator AddFaces(MeshType &m, int n, PointerUpdater &pu) { FaceIterator last; pu.Clear(); if(m.face.empty()) { pu.oldBase=0; // if the vector is empty we cannot find the last valid element } else { pu.oldBase=&*m.face.begin(); pu.oldEnd=&m.face.back()+1; last=m.face.end(); } m.face.resize(m.face.size()+n); m.fn+=n; typename std::set::iterator ai; for(ai = m.face_attr.begin(); ai != m.face_attr.end(); ++ai) ((typename MeshType::HandlesWrapper)(*ai)).Resize(m.face.size()); pu.newBase = &*m.face.begin(); pu.newEnd = &m.face.back()+1; if(pu.NeedUpdate()) { FaceIterator fi; for (fi=m.face.begin(); fi!=m.face.end(); ++fi) if(!(*fi).IsD()) { if(HasFFAdjacency(m)) { if ((*fi).cFFp(0)!=0) pu.Update((*fi).FFp(0)); if ((*fi).cFFp(1)!=0) pu.Update((*fi).FFp(1)); if ((*fi).cFFp(2)!=0) pu.Update((*fi).FFp(2)); } if(HasVFAdjacency(m)) { //update pointers to chain of face incident in a vertex //update them only if they are different from zero if ((*fi).cVFp(0)!=0) pu.Update((*fi).VFp(0)); if ((*fi).cVFp(1)!=0) pu.Update((*fi).VFp(1)); if ((*fi).cVFp(2)!=0) pu.Update((*fi).VFp(2)); } } VertexIterator vi; for (vi=m.vert.begin(); vi!=m.vert.end(); ++vi) if(!(*vi).IsD()) { if(HasVFAdjacency(m)) if ((*vi).cVFp()!=0) pu.Update((FaceType * &)(*vi).VFp()); // Note the above cast is probably not useful if you have correctly defined // your vertex type with the correct name of the facetype as a template argument; // pu.Update((FaceType*)(*vi).VFp()); compiles on old gcc and borland // pu.Update((*vi).VFp()); compiles on .net and newer gcc } // e poiche' lo spazio e' cambiato si ricalcola anche last da zero } unsigned int siz=(unsigned int)m.face.size()-n; last = m.face.begin(); advance(last,siz); return last; } /** Function to delete a face from the mesh. NOTE: THIS FUNCTION ALSO UPDATE FN */ static void DeleteFace(MeshType &m, FaceType &f) { assert(!f.IsD()); f.SetD(); --m.fn; } /** Function to delete a vertex from the mesh. NOTE: THIS FUNCTION ALSO UPDATE vn */ static void DeleteVertex(MeshType &m, VertexType &v) { assert(!v.IsD()); v.SetD(); --m.vn; } /* Function to compact all the vertices that have been deleted and put them to the end of the vector. after this pass the isD test in the scanning of vertex vector, is no more strongly necessary. It should not be called when TemporaryData is active; */ static void CompactVertexVector( MeshType &m ) { // If already compacted fast return please! if(m.vn==m.vert.size()) return; // newVertIndex [ ] gives you the new position of the vertex in the vector; std::vector newVertIndex(m.vert.size(),std::numeric_limits::max() ); size_t pos=0; size_t i=0; for(i=0;i(newVertIndex,m.vert); // reorder the optional atttributes in m.vert_attr to reflect the changes ReorderAttribute(m.vert_attr,newVertIndex,m); m.vert.resize(m.vn); // resize the optional atttributes in m.vert_attr to reflect the changes ResizeAttribute(m.vert_attr,m.vn,m); FaceIterator fi; VertexPointer vbase=&m.vert[0]; for(fi=m.face.begin();fi!=m.face.end();++fi) if(!(*fi).IsD()) for(i=0;i<3;++i) { size_t oldIndex = (*fi).V(i) - vbase; assert(oldIndex >=0 && oldIndex < newVertIndex.size()); (*fi).V(i) = vbase+newVertIndex[oldIndex]; } } /* Function to compact all the vertices that have been deleted and put them to the end of the vector. after this pass the isD test in the scanning of vertex vector, is no more strongly necessary. It should not be called when TemporaryData is active; */ static void CompactFaceVector( MeshType &m ) { // If already compacted fast return please! if(m.fn==m.face.size()) return; // newFaceIndex [ ] gives you the new position of the face in the vector; std::vector newFaceIndex(m.face.size(),std::numeric_limits::max() ); size_t pos=0; size_t i=0; for(i=0;i(newFaceIndex,m.face); // reorder the optional atttributes in m.face_attr to reflect the changes ReorderAttribute(m.face_attr,newFaceIndex,m); // Loop on the vertices to correct VF relation VertexIterator vi; FacePointer fbase=&m.face[0]; for (vi=m.vert.begin(); vi!=m.vert.end(); ++vi) if(!(*vi).IsD()) { if(HasVFAdjacency(m)) if ((*vi).cVFp()!=0) { size_t oldIndex = (*vi).cVFp() - fbase; assert(oldIndex >=0 && oldIndex < newFaceIndex.size()); (*vi).VFp() = fbase+newFaceIndex[oldIndex]; } } // Loop on the faces to correct VF and FF relations m.face.resize(m.fn); // resize the optional atttributes in m.face_attr to reflect the changes ResizeAttribute(m.face_attr,m.vn,m); FaceIterator fi; for(fi=m.face.begin();fi!=m.face.end();++fi) if(!(*fi).IsD()) { if(HasVFAdjacency(m)) for(i=0;i<3;++i) if ((*fi).cVFp(i)!=0) { size_t oldIndex = (*fi).VFp(i) - fbase; assert(oldIndex >=0 && oldIndex < newFaceIndex.size()); (*fi).VFp(i) = fbase+newFaceIndex[oldIndex]; } if(HasFFAdjacency(m)) for(i=0;i<3;++i) if ((*fi).cFFp(i)!=0) { size_t oldIndex = (*fi).FFp(i) - fbase; assert(oldIndex >=0 && oldIndex < newFaceIndex.size()); (*fi).FFp(i) = fbase+newFaceIndex[oldIndex]; } } } public: /// Per Vertex Attributes template static typename MeshType::template PerVertexAttributeHandle AddPerVertexAttribute( MeshType & m, std::string name){ HWIte i; HandlesWrapper h; h._name = name; if(!name.empty()){ i = m.vert_attr.find(h); assert(i ==m.vert_attr.end() );// an attribute with this name exists } h._handle = (void*) new SimpleTempData(m.vert); std::pair < HandlesIterator , bool> res = m.vert_attr.insert(h); return typename MeshType::template PerVertexAttributeHandle(res.first->_handle); } template static typename MeshType::template PerVertexAttributeHandle AddPerVertexAttribute( MeshType & m){ return AddPerVertexAttribute(m,std::string("")); } template static typename MeshType::template PerVertexAttributeHandle GetPerVertexAttribute( const MeshType & m, const std::string & name){ assert(!name.empty()); HandlesWrapper h1; h1._name = name; typename std::set ::const_iterator i; i =m.vert_attr.find(h1); if(i!=m.vert_attr.end()) return typename MeshType::template PerVertexAttributeHandle((*i)._handle); else return typename MeshType:: template PerVertexAttributeHandle(NULL); } template static void DeletePerVertexAttribute( MeshType & m,typename MeshType::template PerVertexAttributeHandle & h){ typename std::set ::iterator i; for( i = m.vert_attr.begin(); i != m.vert_attr.end(); ++i) if( (*i)._handle == h._handle ){ delete ((SimpleTempData*)(*i)._handle); m.vert_attr.erase(i); return;} assert(0); } template static void DeletePerVertexAttribute( MeshType & m, std::string name){ HandlesIterator i; HandlesWrapper h1; h1._name = name; i = m.vert_attr.find(h1); assert(i!=m.vert_attr.end()); delete ((SimpleTempData*)(*i)._handle); m.vert_attr.erase(i); } /// Per Face Attributes template static typename MeshType::template PerFaceAttributeHandle AddPerFaceAttribute( MeshType & m, std::string name){ HWIte i; HandlesWrapper h; h._name = name; if(!name.empty()){ i = m.face_attr.find(h); assert(i ==m.face_attr.end() );// an attribute with this name exists } h._handle = (void*) new SimpleTempData(m.face); std::pair < HandlesIterator , bool> res = m.face_attr.insert(h); return typename MeshType::template PerFaceAttributeHandle(res.first->_handle); } template static typename MeshType::template PerFaceAttributeHandle GetPerFaceAttribute( const MeshType & m, const std::string & name){ assert(!name.empty()); HandlesWrapper h1; h1._name = name; typename std::set ::const_iterator i; i =m.face_attr.find(h1); if(i!=m.face_attr.end()) return typename MeshType::template PerFaceAttributeHandle((*i)._handle); else return typename MeshType:: template PerFaceAttributeHandle(NULL); } template static void DeletePerFaceAttribute( MeshType & m,typename MeshType::template PerFaceAttributeHandle & h){ typename std::set ::iterator i; for( i = m.face_attr.begin(); i != m.face_attr.end(); ++i) if( (*i)._handle == h._handle ){ delete ((SimpleTempData*)(*i)._handle); m.face_attr.erase(i); return;} assert(0); } template static void DeletePerFaceAttribute( MeshType & m, std::string name){ HandlesIterator i; HandlesWrapper h1; h1._name = name; i = m.face_attr.find(h1); assert(i!=m.face_attr.end()); delete ((SimpleTempData*)(*i)._handle); m.face_attr.erase(i); } }; // end class /*@}*/ } // End Namespace TriMesh } // End Namespace vcg #endif qutemol/vcg/vcg/complex/trimesh/clean.h0000444000175000017500000010367011004012331016525 0ustar mbamba/**************************************************************************** * VCGLib o o * * Visual and Computer Graphics Library o o * * _ O _ * * Copyright(C) 2004 \/)\/ * * Visual Computing Lab /\/| * * ISTI - Italian National Research Council | * * \ * * All rights reserved. * * * * 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. * * * * 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 (http://www.gnu.org/licenses/gpl.txt) * * for more details. * * * ****************************************************************************/ /**************************************************************************** History $Log: clean.h,v $ Revision 1.59 2008/04/24 05:04:25 cignoni added a missing std:: Revision 1.58 2008/03/11 14:16:40 cignoni Added check on deleted faces in RemoveDegenerateFace Revision 1.57 2008/03/06 08:37:16 cignoni added HasConsistentPerWedgeTexCoord Revision 1.56 2008/01/24 11:52:05 cignoni corrected small bug in RemoveDuplicateVertex Revision 1.55 2007/10/29 11:32:46 cignoni Added a missing IsD() test Revision 1.54 2007/10/16 16:46:53 cignoni Added Allocator::DeleteFace and Allocator::DeleteVertex; Now the use of SetD() should be deprecated. Revision 1.53 2007/07/24 07:09:49 cignoni Added remove degenerate vertex to manage vertex with NAN coords Revision 1.52 2007/06/04 06:45:05 fiorin Replaced call to old StarSize method with NumberOfIncidentFaces Revision 1.51 2007/03/27 09:23:32 cignoni added honoring of selected flag for flipmesh Revision 1.50 2007/03/12 15:38:03 tarini Texture coord name change! "TCoord" and "Texture" are BAD. "TexCoord" is GOOD. Revision 1.49 2007/02/27 15:17:17 marfr960 std::numeric_limits::max() -> (std::numeric_limits::max)() to avoid annoying misunderstaindings on msvc8 Revision 1.48 2007/01/11 10:12:19 cignoni Removed useless and conflicting inclusion of face.h Revision 1.47 2006/12/01 21:26:14 cignoni Corrected bug in the IsFFAdjacencyConsistent the Topology checking function. Revision 1.46 2006/12/01 08:12:30 cignoni Added a function for FF topology consistency check Revision 1.45 2006/12/01 00:00:56 cignoni Corrected IsOrientedMesh. After the templating of the swapedge it did not worked any more.... Added Texture management to the FlipMesh Revision 1.44 2006/11/27 10:36:35 cignoni Added IsSizeConsistent Revision 1.43 2006/11/09 17:26:24 cignoni Corrected RemoveNonManifoldFace Revision 1.42 2006/10/15 07:31:22 cignoni typenames and qualifiers for gcc compliance Revision 1.41 2006/10/09 20:06:46 cignoni Added Remove NonManifoldFace Revision 1.40 2006/05/25 09:41:09 cignoni missing std and other gcc detected syntax errors Revision 1.39 2006/05/16 21:51:07 cignoni Redesigned the function for the removal of faces according to their area and edge lenght Revision 1.38 2006/05/03 21:40:27 cignoni Changed HasMark to HasPerFaceMark(m) and commented some unused internal vars of the class Revision 1.37 2006/04/18 07:01:22 zifnab1974 added a ; how could this ever compile? Revision 1.36 2006/04/12 15:08:51 cignoni Added ConnectedIterator (should be moved somewhere else) Cleaned ConnectedComponents Revision 1.35 2006/02/28 16:51:29 ponchio Added typename Revision 1.34 2006/02/01 15:27:00 cignoni Added IsD() test in SelfIntersection Revision 1.33 2006/01/27 09:55:25 corsini fix signed/unsigned mismatch Revision 1.32 2006/01/23 13:33:54 cignoni Added a missing vcg:: Revision 1.31 2006/01/22 17:06:27 cignoni vi/fi mismatch in ClipWithBox Revision 1.30 2006/01/22 10:07:42 cignoni Corrected use of Area with the unambiguous DoubleArea Added ClipWithBox function Revision 1.29 2006/01/11 15:40:14 cignoni Added RemoveDegenerateFace and added its automatic invocation at the end of RemoveDuplicateVertex Revision 1.28 2006/01/02 09:49:36 cignoni Added some missing std:: Revision 1.27 2005/12/29 12:27:37 cignoni Splitted IsComplexManifold in IsTwoManifoldFace and IsTwoManifoldVertex Revision 1.26 2005/12/21 14:15:03 corsini Remove printf Revision 1.25 2005/12/21 13:09:03 corsini Modify genus computation Revision 1.24 2005/12/19 15:13:06 corsini Fix IsOrientedMesh Revision 1.23 2005/12/16 13:13:44 cignoni Reimplemented SelfIntersection Revision 1.22 2005/12/16 10:54:59 corsini Reimplement isOrientedMesh Revision 1.21 2005/12/16 10:53:39 corsini Take account for deletion in isComplexManifold Revision 1.20 2005/12/16 10:51:43 corsini Take account for deletion in isRegularMesh Revision 1.19 2005/12/15 13:53:13 corsini Reimplement isComplexManifold Reimplement isRegular Revision 1.18 2005/12/14 14:04:35 corsini Fix genus computation Revision 1.17 2005/12/12 12:11:40 cignoni Removed unuseful detectunreferenced Revision 1.16 2005/12/04 00:25:00 cignoni Changed DegeneratedFaces -> RemoveZeroAreaFaces Revision 1.15 2005/12/03 22:34:25 cignoni Added missing include and sdt:: (tnx to Mario Latronico) Revision 1.14 2005/12/02 00:14:43 cignoni Removed some pointer vs iterator issues that prevented gcc compilation Revision 1.13 2005/11/22 14:04:10 rita_borgo Completed and tested self-intersection routine Revision 1.12 2005/11/17 00:41:07 cignoni Removed Initialize use updateflags::Clear() instead. Revision 1.11 2005/11/16 16:33:23 rita_borgo Changed ComputeSelfintersection Revision 1.10 2005/11/15 12:16:34 rita_borgo Changed DegeneratedFaces, sets the D flags for each faces that is found to be degenerated. CounEdges and ConnectedComponents check now if a face IsD() else for degenerated faces many asserts fail. Revision 1.9 2005/11/14 09:28:18 cignoni changed access to face functions (border, area) removed some typecast warnings Revision 1.8 2005/10/11 16:03:40 rita_borgo Added new functions belonging to triMeshInfo Started the Self-Intersection routine Revision 1.7 2005/10/03 15:57:53 rita_borgo Alligned with TriMeshInfo Code Revision 1.6 2005/01/28 11:59:35 cignoni Add std:: to stl containers Revision 1.5 2004/09/20 08:37:57 cignoni Better Doxygen docs Revision 1.4 2004/08/25 15:15:26 ganovelli minor changes to comply gcc compiler (typename's and stuff) Revision 1.3 2004/07/18 06:55:37 cignoni NewUserBit -> NewBitFlag Revision 1.2 2004/07/09 15:48:37 tarini Added an include () Revision 1.1 2004/06/24 08:03:59 cignoni Initial Release ****************************************************************************/ #ifndef __VCGLIB_CLEAN #define __VCGLIB_CLEAN // Standard headers #include #include #include // VCG headers #include #include #include #include #include #include namespace vcg { namespace tri{ template class ConnectedIterator { public: typedef ConnectedMeshType MeshType; typedef typename MeshType::VertexType VertexType; typedef typename MeshType::VertexPointer VertexPointer; typedef typename MeshType::VertexIterator VertexIterator; typedef typename MeshType::ScalarType ScalarType; typedef typename MeshType::FaceType FaceType; typedef typename MeshType::FacePointer FacePointer; typedef typename MeshType::FaceIterator FaceIterator; typedef typename MeshType::FaceContainer FaceContainer; typedef typename vcg::Box3 Box3Type; public: void operator ++() { FacePointer fpt=sf.top(); sf.pop(); for(int j=0;j<3;++j) if( !face::IsBorder(*fpt,j) ) { FacePointer l=fpt->FFp(j); if( !mp->IsMarked(l) ) { mp->Mark(l); sf.push(l); } } } void start(MeshType &m, FacePointer p) { mp=&m; while(!sf.empty()) sf.pop(); mp->UnMarkAll(); assert(p); assert(!p->IsD()); mp->Mark(p); sf.push(p); } bool completed() { return sf.empty(); } FacePointer operator *() { return sf.top(); } private: std::stack sf; MeshType *mp; }; /// /** \addtogroup trimesh */ /*@{*/ /// Class of static functions to clean/correct/restore meshs. template class Clean { public: typedef CleanMeshType MeshType; typedef typename MeshType::VertexType VertexType; typedef typename MeshType::VertexPointer VertexPointer; typedef typename MeshType::VertexIterator VertexIterator; typedef typename MeshType::ScalarType ScalarType; typedef typename MeshType::FaceType FaceType; typedef typename MeshType::FacePointer FacePointer; typedef typename MeshType::FaceIterator FaceIterator; typedef typename MeshType::FaceContainer FaceContainer; typedef typename vcg::Box3 Box3Type; typedef GridStaticPtr TriMeshGrid; typedef Point3 Point3x; //TriMeshGrid gM; //FaceIterator fi; //FaceIterator gi; //vcg::face::Pos he; //vcg::face::Pos hei; /* classe di confronto per l'algoritmo di eliminazione vertici duplicati*/ class RemoveDuplicateVert_Compare{ public: inline bool operator()(VertexPointer const &a, VertexPointer const &b) { return (*a).cP() < (*b).cP(); } }; /** This function removes all duplicate vertices of the mesh by looking only at their spatial positions. Note that it does not update any topology relation that could be affected by this like the VT or TT relation. the reason this function is usually performed BEFORE building any topology information. */ static int RemoveDuplicateVertex( MeshType & m, bool RemoveDegenerateFlag=true) // V1.0 { if(m.vert.size()==0 || m.vn==0) return 0; std::map mp; int i,j; VertexIterator vi; int deleted=0; int k=0; size_t num_vert = m.vert.size(); std::vector perm(num_vert); for(vi=m.vert.begin(); vi!=m.vert.end(); ++vi, ++k) perm[k] = &(*vi); RemoveDuplicateVert_Compare c_obj; std::sort(perm.begin(),perm.end(),c_obj); j = 0; i = j; mp[perm[i]] = perm[j]; ++i; for(;i!=num_vert;) { if( (! (*perm[i]).IsD()) && (! (*perm[j]).IsD()) && (*perm[i]).P() == (*perm[j]).cP() ) { VertexPointer t = perm[i]; mp[perm[i]] = perm[j]; ++i; Allocator::DeleteVertex(m,*t); deleted++; } else { j = i; ++i; } } FaceIterator fi; for(fi = m.face.begin(); fi!=m.face.end(); ++fi) if( !(*fi).IsD() ) for(k = 0; k < 3; ++k) if( mp.find( (typename MeshType::VertexPointer)(*fi).V(k) ) != mp.end() ) { (*fi).V(k) = &*mp[ (*fi).V(k) ]; } if(RemoveDegenerateFlag) RemoveDegenerateFace(m); return deleted; } /** This function removes that are not referenced by any face. The function updates the vn counter. @param m The mesh @return The number of removed vertices */ static int RemoveUnreferencedVertex( MeshType& m, bool DeleteVertexFlag=true) // V1.0 { FaceIterator fi; VertexIterator vi; int referredBit = VertexType::NewBitFlag(); int j; int deleted = 0; for(vi=m.vert.begin();vi!=m.vert.end();++vi) (*vi).ClearUserBit(referredBit); for(fi=m.face.begin();fi!=m.face.end();++fi) if( !(*fi).IsD() ) for(j=0;j<3;++j) (*fi).V(j)->SetUserBit(referredBit); for(vi=m.vert.begin();vi!=m.vert.end();++vi) if( (!(*vi).IsD()) && (!(*vi).IsUserBit(referredBit))) { if(DeleteVertexFlag) Allocator::DeleteVertex(m,*vi); ++deleted; } VertexType::DeleteBitFlag(referredBit); return deleted; } /** Degenerate vertices are vertices that have coords with invalid floating point values, All the faces incident on deleted vertices are also deleted */ static int RemoveDegenerateVertex(MeshType& m) { VertexIterator vi; int count_vd = 0; for(vi=m.vert.begin(); vi!=m.vert.end();++vi) if(math::IsNAN( (*vi).P()[0]) || math::IsNAN( (*vi).P()[1]) || math::IsNAN( (*vi).P()[2]) ) { count_vd++; Allocator::DeleteVertex(m,*vi); } FaceIterator fi; int count_fd = 0; for(fi=m.face.begin(); fi!=m.face.end();++fi) if(!(*fi).IsD()) if( (*fi).V(0)->IsD() || (*fi).V(1)->IsD() || (*fi).V(2)->IsD() ) { count_fd++; Allocator::DeleteFace(m,*fi); } return count_vd; } /** Degenerate faces are faces that are Topologically degenerate, i.e. have two or more vertex reference that link the same vertex (and not only two vertexes with the same coordinates). All Degenerate faces are zero area faces BUT not all zero area faces are degenerate. We do not take care of topology because when we have degenerate faces the topology calculation functions crash. */ static int RemoveDegenerateFace(MeshType& m) { FaceIterator fi; int count_fd = 0; for(fi=m.face.begin(); fi!=m.face.end();++fi) if(!(*fi).IsD()) { if((*fi).V(0) == (*fi).V(1) || (*fi).V(0) == (*fi).V(2) || (*fi).V(1) == (*fi).V(2) ) { count_fd++; Allocator::DeleteFace(m,*fi); } } return count_fd; } static int RemoveNonManifoldFace(MeshType& m) { FaceIterator fi; int count_fd = 0; std::vector ToDelVec; for(fi=m.face.begin(); fi!=m.face.end();++fi) if (!fi->IsD()) { if ((!IsManifold(*fi,0))|| (!IsManifold(*fi,1))|| (!IsManifold(*fi,2))) ToDelVec.push_back(&*fi); } for(int i=0;iIsD()) { FaceType &ff= *ToDelVec[i]; if ((!IsManifold(ff,0))|| (!IsManifold(ff,1))|| (!IsManifold(ff,2))) { for(int j=0;j<3;++j) if(!face::IsBorder(ff,j)) vcg::face::FFDetach(ff,j); Allocator::DeleteFace(m,ff); count_fd++; } } } return count_fd; } /* The following functions remove faces that are geometrically "bad" according to edges and area criteria. They remove the faces that are out of a given range of area or edges (e.g. faces too large or too small, or with edges too short or too long) but that could be topologically correct. These functions can optionally take into account only the selected faces. */ template static int RemoveFaceOutOfRangeAreaSel(MeshType& m, ScalarType MinAreaThr=0, ScalarType MaxAreaThr=(std::numeric_limits::max)()) { FaceIterator fi; int count_fd = 0; MinAreaThr*=2; MaxAreaThr*=2; for(fi=m.face.begin(); fi!=m.face.end();++fi) if(!(*fi).IsD()) if(!Selected || (*fi).IsS()) { const ScalarType doubleArea=DoubleArea(*fi); if((doubleArea<=MinAreaThr) || (doubleArea>=MaxAreaThr) ) { Allocator::DeleteFace(m,*fi); count_fd++; } } return count_fd; } template static int RemoveFaceOutOfRangeEdgeSel( MeshType& m, ScalarType MinEdgeThr=0, ScalarType MaxEdgeThr=(std::numeric_limits::max)()) { FaceIterator fi; int count_fd = 0; MinEdgeThr=MinEdgeThr*MinEdgeThr; MaxEdgeThr=MaxEdgeThr*MaxEdgeThr; for(fi=m.face.begin(); fi!=m.face.end();++fi) if(!(*fi).IsD()) if(!Selected || (*fi).IsS()) { for(unsigned int i=0;i<3;++i) { const ScalarType squaredEdge=SquaredDistance((*fi).V0(i)->cP(),(*fi).V1(i)->cP()); if((squaredEdge<=MinEdgeThr) || (squaredEdge>=MaxEdgeThr) ) { count_fd++; Allocator::DeleteFace(m,*fi); break; // skip the rest of the edges of the tri } } } return count_fd; } // alias for the old style. Kept for backward compatibility static int RemoveZeroAreaFace(MeshType& m) { return RemoveFaceOutOfRangeArea(m);} // Aliases for the functions that do not look at selection static int RemoveFaceOutOfRangeArea(MeshType& m, ScalarType MinAreaThr=0, ScalarType MaxAreaThr=(std::numeric_limits::max)()) { return RemoveFaceOutOfRangeAreaSel(m,MinAreaThr,MaxAreaThr); } static int RemoveFaceOutOfRangeEdge(MeshType& m, ScalarType MinEdgeThr=0, ScalarType MaxEdgeThr=(std::numeric_limits::max)()) { return RemoveFaceOutOfRangeEdgeSel(m,MinEdgeThr,MaxEdgeThr); } static int ClipWithBox( MeshType & m, Box3Type &bb) { FaceIterator fi; VertexIterator vi; for (vi = m.vert.begin(); vi != m.vert.end(); ++vi) if(!(*vi).IsD()) { if(!bb.IsIn((*vi).P()) ) Allocator::DeleteVertex(m,*vi); } for (fi = m.face.begin(); fi != m.face.end(); ++fi) if(!(*fi).IsD()) { if( (*fi).V(0)->IsD() || (*fi).V(1)->IsD() || (*fi).V(2)->IsD() ) Allocator::DeleteFace(m,*fi); } return m.vn; } /** * Check if the mesh is a manifold. * * First of all, for each face the FF condition is checked. * Then, a second test is performed: for each vertex the * number of face found have to be the same of the number of * face found with the VF walk trough. */ static bool IsTwoManifoldFace( MeshType & m ) { bool flagManifold = true; FaceIterator fi; // First Test assert(m.HasFFTopology()); for (fi = m.face.begin(); fi != m.face.end(); ++fi) { if (!fi->IsD()) { if ((!IsManifold(*fi,0))|| (!IsManifold(*fi,1))|| (!IsManifold(*fi,2))) { flagManifold = false; break; } } } return flagManifold; } static bool IsTwoManifoldVertex( MeshType & m ) { VertexIterator vi; bool flagManifold = true; assert(m.HasVFTopology()); face::VFIterator vfi; int starSizeFF; int starSizeVF; for (vi = m.vert.begin(); vi != m.vert.end(); ++vi) { if (!vi->IsD()) { face::VFIterator vfi(&*vi); face::Pos pos((*vi).VFp(), &*vi); starSizeFF = pos.NumberOfIncidentFaces(); starSizeVF = 0; while(!vfi.End()) { ++vfi; starSizeVF++; } if (starSizeFF != starSizeVF) { flagManifold = false; break; } } } return flagManifold; } static void CountEdges( MeshType & m, int &count_e, int &boundary_e ) { FaceIterator fi; vcg::face::Pos he; vcg::face::Pos hei; bool counted =false; for(fi=m.face.begin();fi!=m.face.end();fi++) { if(!((*fi).IsD())) { (*fi).SetS(); count_e +=3; //assume that we have to increase the number of edges with three for(int j=0; j<3; j++) { if (face::IsBorder(*fi,j)) //If this edge is a border edge boundary_e++; // then increase the number of boundary edges else if (IsManifold(*fi,j))//If this edge is manifold { if((*fi).FFp(j)->IsS()) //If the face on the other side of the edge is already selected count_e--; // we counted one edge twice } else//We have a non-manifold edge { hei.Set(&(*fi), j , fi->V(j)); he=hei; he.NextF(); while (he.f!=hei.f)// so we have to iterate all faces that are connected to this edge { if (he.f->IsS())// if one of the other faces was already visited than this edge was counted already. { counted=true; break; } else { he.NextF(); } } if (counted) { count_e--; counted=false; } } } } } } static int CountHoles( MeshType & m) { int numholes=0; int numholev=0; int BEdges=0; FaceIterator fi; FaceIterator gi; vcg::face::Pos he; vcg::face::Pos hei; std::vector< std::vector > holes; //indices of vertices for(fi=m.face.begin();fi!=m.face.end();++fi) (*fi).ClearS(); gi=m.face.begin(); fi=gi; for(fi=m.face.begin();fi!=m.face.end();fi++)//for all faces do { for(int j=0;j<3;j++)//for all edges { if(fi->V(j)->IsS()) continue; if(face::IsBorder(*fi,j))//found an unvisited border edge { he.Set(&(*fi),j,fi->V(j)); //set the face-face iterator to the current face, edge and vertex std::vector hole; //start of a new hole hole.push_back(fi->P(j)); // including the first vertex numholev++; he.v->SetS(); //set the current vertex as selected he.NextB(); //go to the next boundary edge while(fi->V(j) != he.v)//will we do not encounter the first boundary edge. { Point3x newpoint = he.v->P(); //select its vertex. if(he.v->IsS())//check if this vertex was selected already, because then we have an additional hole. { //cut and paste the additional hole. std::vector hole2; int index = static_cast(find(hole.begin(),hole.end(),newpoint) - hole.begin()); for(unsigned int i=index; iSetS(); //set the current vertex as selected he.NextB(); //go to the next boundary edge } holes.push_back(hole); } } } return static_cast(holes.size()); } static int BorderEdges( MeshType & m, int numholes) { int BEdges = 0; for(int i=0; i with, for each connecteed component its size and a represnant */ static int ConnectedComponents(MeshType &m) { std::vector< std::pair > CCV; return ConnectedComponents(m,CCV); } static int ConnectedComponents(MeshType &m, std::vector< std::pair > &CCV) { FaceIterator fi; FacePointer l; CCV.clear(); for(fi=m.face.begin();fi!=m.face.end();++fi) (*fi).ClearS(); int Compindex=0; std::stack sf; FacePointer fpt=&*(m.face.begin()); for(fi=m.face.begin();fi!=m.face.end();++fi) { if(!((*fi).IsD()) && !(*fi).IsS()) { (*fi).SetS(); CCV.push_back(make_pair(0,&*fi)); sf.push(&*fi); while (!sf.empty()) { fpt=sf.top(); ++CCV.back().first; sf.pop(); for(int j=0;j<3;++j) { if( !face::IsBorder(*fpt,j) ) { l=fpt->FFp(j); if( !(*l).IsS() ) { (*l).SetS(); sf.push(l); } } } } Compindex++; } } assert(CCV.size()==Compindex); return Compindex; } /** GENUS. A topologically invariant property of a surface defined as the largest number of non-intersecting simple closed curves that can be drawn on the surface without separating it. Roughly speaking, it is the number of holes in a surface. The genus g of a closed surface, also called the geometric genus, is related to the Euler characteristic by the relation $chi$ by $chi==2-2g$. The genus of a connected, orientable surface is an integer representing the maximum number of cuttings along closed simple curves without rendering the resultant manifold disconnected. It is equal to the number of handles on it. For general polyhedra the Euler Formula is: V + F - E = 2 - 2G - B where V is the number of vertices, F is the number of faces, E is the number of edges, G is the genus and B is the number of boundary polygons. The above formula is valid for a mesh with one single connected component. By considering multiple connected components the formula becomes: V + F - E = 2C - 2Gs - B where C is the number of connected components and Gs is the sum of the genus of all connected components. */ static int MeshGenus(MeshType &m, int numholes, int numcomponents, int count_e) { int V = m.vn; int F = m.fn; int E = count_e; return -((V + F - E + numholes - 2 * numcomponents) / 2); } /** * Check if the given mesh is regular, semi-regular or irregular. * * Each vertex of a \em regular mesh has valence 6 except for border vertices * which have valence 4. * * A \em semi-regular mesh is derived from an irregular one applying * 1-to-4 subdivision recursively. (not checked for now) * * All other meshes are \em irregular. */ static void IsRegularMesh(MeshType &m, bool &Regular, bool &Semiregular) { // This algorithm requires Vertex-Face topology assert(m.HasVFTopology()); Regular = true; VertexIterator vi; // for each vertex the number of edges are count for (vi = m.vert.begin(); vi != m.vert.end(); ++vi) { if (!vi->IsD()) { face::Pos he((*vi).VFp(), &*vi); face::Pos ht = he; int n=0; bool border=false; do { ++n; ht.NextE(); if (ht.IsBorder()) border=true; } while (ht != he); if (border) n = n/2; if ((n != 6)&&(!border && n != 4)) { Regular = false; break; } } } if (!Regular) Semiregular = false; else { // For now we do not account for semi-regularity Semiregular = false; } } static void IsOrientedMesh(MeshType &m, bool &Oriented, bool &Orientable) { assert(&Oriented != &Orientable); // This algorithms requires FF topology assert(m.HasFFTopology()); Orientable = true; Oriented = true; // Ensure that each face is deselected FaceIterator fi; for (fi = m.face.begin(); fi != m.face.end(); ++fi) fi->ClearS(); // initialize stack std::stack faces; // for each face of the mesh FacePointer fp,fpaux; int iaux; for (fi = m.face.begin(); fi != m.face.end(); ++fi) { if (!fi->IsD() && !fi->IsS()) { // each face put in the stack is selected (and oriented) fi->SetS(); faces.push(&(*fi)); // empty the stack while (!faces.empty()) { fp = faces.top(); faces.pop(); // make consistently oriented the adjacent faces for (int j = 0; j < 3; j++) { // get one of the adjacent face fpaux = fp->FFp(j); iaux = fp->FFi(j); if (!fpaux->IsD() && fpaux != fp && face::IsManifold(*fp, j)) { if (!CheckOrientation(*fpaux, iaux)) { Oriented = false; if (!fpaux->IsS()) { face::SwapEdge(*fpaux, iaux); assert(CheckOrientation(*fpaux, iaux)); } else { Orientable = false; break; } } // put the oriented face into the stack if (!fpaux->IsS()) { fpaux->SetS(); faces.push(fpaux); } } } } } if (!Orientable) break; } } /// Flip the orientation of the whole mesh flipping all the faces (by swapping the first two vertices) static void FlipMesh(MeshType &m, bool selected=false) { for (FaceIterator fi = m.face.begin(); fi != m.face.end(); ++fi) if(!(*fi).IsD()) if(!selected || (*fi).IsS()) { face::SwapEdge((*fi), 0); if (HasPerWedgeTexCoord(m)) std::swap((*fi).WT(0),(*fi).WT(1)); } } static bool SelfIntersections(MeshType &m, std::vector &ret) { //assert(FaceType::HasMark()); // Needed by the UG assert(HasPerFaceMark(m));// Needed by the UG Box3< ScalarType> bbox; TriMeshGrid gM; ret.clear(); FaceIterator fi; int referredBit = FaceType::NewBitFlag(); for(fi=m.face.begin();fi!=m.face.end();++fi) (*fi).ClearUserBit(referredBit); std::vector inBox; gM.Set(m.face.begin(),m.face.end()); for(fi=m.face.begin();fi!=m.face.end();++fi) if(!(*fi).IsD()) { (*fi).SetUserBit(referredBit); (*fi).GetBBox(bbox); vcg::trimesh::GetInBoxFace(m, gM, bbox,inBox); bool Intersected=false; typename std::vector::iterator fib; for(fib=inBox.begin();fib!=inBox.end();++fib) { if(!(*fib)->IsUserBit(referredBit) && (*fib != &*fi) ) if(TestIntersection(&*fi,*fib)){ ret.push_back(*fib); if(!Intersected) { ret.push_back(&*fi); Intersected=true; } } } inBox.clear(); } FaceType::DeleteBitFlag(referredBit); return (ret.size()>0); } /** This function simply test that the vn and fn counters be consistent with the size of the containers and the number of deleted simplexes. */ static bool IsSizeConsistent(MeshType &m) { int DeletedVertexNum=0; for (VertexIterator vi = m.vert.begin(); vi != m.vert.end(); ++vi) if((*vi).IsD()) DeletedVertexNum++; int DeletedFaceNum=0; for (FaceIterator fi = m.face.begin(); fi != m.face.end(); ++fi) if((*fi).IsD()) DeletedFaceNum++; if(m.vn+DeletedVertexNum != m.vert.size()) return false; if(m.fn+DeletedFaceNum != m.face.size()) return false; return true; } /** This function simply test that all the faces have a consistent face-face topology relation. useful for checking that a topology modifying algorithm does not mess something. */ static bool IsFFAdjacencyConsistent(MeshType &m) { if(!HasFFAdjacency(m)) return false; for (FaceIterator fi = m.face.begin(); fi != m.face.end(); ++fi) if(!(*fi).IsD()) { for(int i=0;i<3;++i) if(!FFCorrectness(*fi, i)) return false; } return true; } /** This function simply test that a mesh has some reasonable tex coord. */ static bool HasConsistentPerWedgeTexCoord(MeshType &m) { if(!HasPerWedgeTexCoord(m)) return false; for (FaceIterator fi = m.face.begin(); fi != m.face.end(); ++fi) if(!(*fi).IsD()) { FaceType &f=(*fi); if( ! ( (f.WT(0).N() == f.WT(1).N()) && (f.WT(0).N() == (*fi).WT(2).N()) ) ) return false; // all the vertices must have the same index. if((*fi).WT(0).N() <0) return false; // no undefined texture should be allowed } return true; } /** Simple check that there are no face with all collapsed tex coords. */ static bool HasZeroTexCoordFace(MeshType &m) { if(!HasPerWedgeTexCoord(m)) return false; for (FaceIterator fi = m.face.begin(); fi != m.face.end(); ++fi) if(!(*fi).IsD()) { if( (*fi).WT(0).P() == (*fi).WT(1).P() && (*fi).WT(0).P() == (*fi).WT(2).P() ) return false; } return true; } //test real intersection between faces static bool TestIntersection(FaceType *f0,FaceType *f1) { assert((!f0->IsD())&&(!f1->IsD())); //no adiacent faces if ( (f0!=f1) && (!ShareEdge(f0,f1)) && (!ShareVertex(f0,f1)) ) return (vcg::Intersection((*f0),(*f1))); return false; } //control if two faces share an edge static bool ShareEdge(FaceType *f0,FaceType *f1) { assert((!f0->IsD())&&(!f1->IsD())); for (int i=0;i<3;i++) if (f0->FFp(i)==f1) return (true); return(false); } //control if two faces share a vertex static bool ShareVertex(FaceType *f0,FaceType *f1) { assert((!f0->IsD())&&(!f1->IsD())); for (int i=0;i<3;i++) for (int j=0;j<3;j++) if (f0->V(i)==f1->V(j)) return (true); return(false); } }; // end class /*@}*/ } //End Namespace Tri } // End Namespace vcg #endif qutemol/vcg/vcg/complex/trimesh/inside.h0000444000175000017500000001107110632022563016725 0ustar mbamba /**************************************************************************** * IDOLib * * Interactive Deformable Objects Library * * http://idolib.sf.net * * * * Copyright(C) 2005 * * Visual Computing Lab * * ISTI - Italian National Research Council * * * * All rights reserved. * * * * 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. * * * * 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 (http://www.gnu.org/licenses/gpl.txt) * * for more details. * * * ****************************************************************************/ /**************************************************************************** History $Log: inside.h,v $ Revision 1.4 2007/06/07 15:34:11 turini Minor changes. Revision 1.3 2007/06/06 15:38:57 turini Use the barycenter function from triangle3.h instead of the one in face\base.h. Revision 1.2 2007/06/06 14:26:51 pietroni compiling error resolved ****************************************************************************/ #include #include #include #ifndef VCG_INSIDE #define VCG_INSIDE /// This static funtion is used to see if one point is inside a triangular mesh or not... /// First parameter is a spatial indexing structure (eg. a grid) used to perform research operation, initialized with faces of the triangular mesh of type TriMeshType namespace vcg { namespace trimesh { template class Inside { private: typedef typename FaceSpatialIndexing::CoordType CoordType; typedef typename FaceSpatialIndexing::ScalarType ScalarType; public: /// Return true if the point is inside the mesh. static bool Is_Inside( TriMeshType & m, FaceSpatialIndexing & _g_mesh, const CoordType & test ) { typedef typename TriMeshType::FaceType FaceType; typedef typename TriMeshType::ScalarType ScalarType; typedef typename TriMeshType::CoordType CoordType; const ScalarType EPSILON = 0.000001; /// First test if the element is inside the bounding box of the mesh. if( !( m.bbox.IsIn(test) ) ) return false; else { ScalarType dist; CoordType Norm, ip, nearest; FaceType *f = vcg::trimesh::GetClosestFace< TriMeshType, FaceSpatialIndexing >( m, _g_mesh, test, m.bbox.Diag(), dist, nearest, Norm, ip ); assert( f != NULL ); /// Check if there is any face in the mesh /// If the point is on the face is considered inside. if( ( test - nearest ).Norm() <= EPSILON ) return true; /// Check if the closest point is inside a face if( ( ip.V(0) > EPSILON ) && ( ip.V(1) > EPSILON ) && ( ip.V(2) > EPSILON ) ) { /// Check if the test point is inside the mesh using the normal direction vcg::Point3f debugn = f->N(); if( ( f->N() * ( test - nearest ) ) < 0 ) return true; else return false; } /// In this case we are not sure because hit an edge or a vertex. /// So we use a ray that go until the barycenter of found face, then see normal value again else { CoordType bary = vcg::Barycenter< FaceType >(*f); /// Set ray : origin and direction vcg::Ray3 r; r.Set( test, ( bary - test ) ); r.Normalize(); FaceType *f1 = vcg::trimesh::DoRay< TriMeshType, FaceSpatialIndexing >( m, _g_mesh, r, m.bbox.Diag(), dist ); assert( f1 != NULL ); /// In this case normal direction is enough. if( ( f1->N() * ( test - bary ) ) < 0 ) return true; else return false; } } } }; // end class } } #endifqutemol/vcg/vcg/complex/trimesh/inertia.h0000444000175000017500000002217110574111261017107 0ustar mbamba/**************************************************************************** * VCGLib o o * * Visual and Computer Graphics Library o o * * _ O _ * * Copyright(C) 2005 \/)\/ * * Visual Computing Lab /\/| * * ISTI - Italian National Research Council | * * \ * * All rights reserved. * * * * 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. * * * * 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 (http://www.gnu.org/licenses/gpl.txt) * * for more details. * * * ****************************************************************************/ /**************************************************************************** History $Log: inertia.h,v $ Revision 1.4 2007/03/08 22:48:17 cignoni Added missing include and changed the call to jacobi Revision 1.3 2006/03/29 10:12:08 corsini Add cast to avoid warning Revision 1.2 2005/12/12 12:08:30 cignoni First working version Revision 1.1 2005/11/21 15:58:12 cignoni First Release (not working!) Revision 1.13 2005/11/17 00:42:03 cignoni ****************************************************************************/ /* The algorithm is based on a three step reduction of the volume integrals to successively simpler integrals. The algorithm is designed to minimize the numerical errors that can result from poorly conditioned alignment of polyhedral faces. It is also designed for efficiency. All required volume integrals of a polyhedron are computed together during a single walk over the boundary of the polyhedron; exploiting common subexpressions reduces floating point operations. For more information, check out: Brian Mirtich, ``Fast and Accurate Computation of Polyhedral Mass Properties,'' journal of graphics tools, volume 1, number 2, 1996 */ #include #include #include namespace vcg { namespace tri { template class Inertia { typedef InertiaMeshType MeshType; typedef typename MeshType::VertexType VertexType; typedef typename MeshType::VertexPointer VertexPointer; typedef typename MeshType::VertexIterator VertexIterator; typedef typename MeshType::ScalarType ScalarType; typedef typename MeshType::FaceType FaceType; typedef typename MeshType::FacePointer FacePointer; typedef typename MeshType::FaceIterator FaceIterator; typedef typename MeshType::FaceContainer FaceContainer; private : enum {X=0,Y=1,Z=2}; inline ScalarType SQR(ScalarType &x) const { return x*x;} inline ScalarType CUBE(ScalarType &x) const { return x*x*x;} int A; /* alpha */ int B; /* beta */ int C; /* gamma */ /* projection integrals */ double P1, Pa, Pb, Paa, Pab, Pbb, Paaa, Paab, Pabb, Pbbb; /* face integrals */ double Fa, Fb, Fc, Faa, Fbb, Fcc, Faaa, Fbbb, Fccc, Faab, Fbbc, Fcca; /* volume integrals */ double T0, T1[3], T2[3], TP[3]; public: /* compute various integrations over projection of face */ void compProjectionIntegrals(FaceType &f) { double a0, a1, da; double b0, b1, db; double a0_2, a0_3, a0_4, b0_2, b0_3, b0_4; double a1_2, a1_3, b1_2, b1_3; double C1, Ca, Caa, Caaa, Cb, Cbb, Cbbb; double Cab, Kab, Caab, Kaab, Cabb, Kabb; int i; P1 = Pa = Pb = Paa = Pab = Pbb = Paaa = Paab = Pabb = Pbbb = 0.0; for (i = 0; i < 3; i++) { a0 = f.V(i)->P()[A]; b0 = f.V(i)->P()[B]; a1 = f.V1(i)->P()[A]; b1 = f.V1(i)->P()[B]; da = a1 - a0; db = b1 - b0; a0_2 = a0 * a0; a0_3 = a0_2 * a0; a0_4 = a0_3 * a0; b0_2 = b0 * b0; b0_3 = b0_2 * b0; b0_4 = b0_3 * b0; a1_2 = a1 * a1; a1_3 = a1_2 * a1; b1_2 = b1 * b1; b1_3 = b1_2 * b1; C1 = a1 + a0; Ca = a1*C1 + a0_2; Caa = a1*Ca + a0_3; Caaa = a1*Caa + a0_4; Cb = b1*(b1 + b0) + b0_2; Cbb = b1*Cb + b0_3; Cbbb = b1*Cbb + b0_4; Cab = 3*a1_2 + 2*a1*a0 + a0_2; Kab = a1_2 + 2*a1*a0 + 3*a0_2; Caab = a0*Cab + 4*a1_3; Kaab = a1*Kab + 4*a0_3; Cabb = 4*b1_3 + 3*b1_2*b0 + 2*b1*b0_2 + b0_3; Kabb = b1_3 + 2*b1_2*b0 + 3*b1*b0_2 + 4*b0_3; P1 += db*C1; Pa += db*Ca; Paa += db*Caa; Paaa += db*Caaa; Pb += da*Cb; Pbb += da*Cbb; Pbbb += da*Cbbb; Pab += db*(b1*Cab + b0*Kab); Paab += db*(b1*Caab + b0*Kaab); Pabb += da*(a1*Cabb + a0*Kabb); } P1 /= 2.0; Pa /= 6.0; Paa /= 12.0; Paaa /= 20.0; Pb /= -6.0; Pbb /= -12.0; Pbbb /= -20.0; Pab /= 24.0; Paab /= 60.0; Pabb /= -60.0; } void CompFaceIntegrals(FaceType &f) { Point3 n; ScalarType w; double k1, k2, k3, k4; compProjectionIntegrals(f); n = f.N(); w = -f.V(0)->P()*n; k1 = 1 / n[C]; k2 = k1 * k1; k3 = k2 * k1; k4 = k3 * k1; Fa = k1 * Pa; Fb = k1 * Pb; Fc = -k2 * (n[A]*Pa + n[B]*Pb + w*P1); Faa = k1 * Paa; Fbb = k1 * Pbb; Fcc = k3 * (SQR(n[A])*Paa + 2*n[A]*n[B]*Pab + SQR(n[B])*Pbb + w*(2*(n[A]*Pa + n[B]*Pb) + w*P1)); Faaa = k1 * Paaa; Fbbb = k1 * Pbbb; Fccc = -k4 * (CUBE(n[A])*Paaa + 3*SQR(n[A])*n[B]*Paab + 3*n[A]*SQR(n[B])*Pabb + CUBE(n[B])*Pbbb + 3*w*(SQR(n[A])*Paa + 2*n[A]*n[B]*Pab + SQR(n[B])*Pbb) + w*w*(3*(n[A]*Pa + n[B]*Pb) + w*P1)); Faab = k1 * Paab; Fbbc = -k2 * (n[A]*Pabb + n[B]*Pbbb + w*Pbb); Fcca = k3 * (SQR(n[A])*Paaa + 2*n[A]*n[B]*Paab + SQR(n[B])*Pabb + w*(2*(n[A]*Paa + n[B]*Pab) + w*Pa)); } void Compute(MeshType &m) { tri::UpdateNormals::PerFaceNormalized(m); double nx, ny, nz; T0 = T1[X] = T1[Y] = T1[Z] = T2[X] = T2[Y] = T2[Z] = TP[X] = TP[Y] = TP[Z] = 0; FaceIterator fi; for (fi=m.face.begin(); fi!=m.face.end();++fi) if(!(*fi).IsD()) { FaceType &f=(*fi); nx = fabs(f.N()[0]); ny = fabs(f.N()[1]); nz = fabs(f.N()[2]); if (nx > ny && nx > nz) C = X; else C = (ny > nz) ? Y : Z; A = (C + 1) % 3; B = (A + 1) % 3; CompFaceIntegrals(f); T0 += f.N()[X] * ((A == X) ? Fa : ((B == X) ? Fb : Fc)); T1[A] += f.N()[A] * Faa; T1[B] += f.N()[B] * Fbb; T1[C] += f.N()[C] * Fcc; T2[A] += f.N()[A] * Faaa; T2[B] += f.N()[B] * Fbbb; T2[C] += f.N()[C] * Fccc; TP[A] += f.N()[A] * Faab; TP[B] += f.N()[B] * Fbbc; TP[C] += f.N()[C] * Fcca; } T1[X] /= 2; T1[Y] /= 2; T1[Z] /= 2; T2[X] /= 3; T2[Y] /= 3; T2[Z] /= 3; TP[X] /= 2; TP[Y] /= 2; TP[Z] /= 2; } ScalarType Mass() { return static_cast(T0); } Point3 CenterOfMass() { Point3 r; r[X] = T1[X] / T0; r[Y] = T1[Y] / T0; r[Z] = T1[Z] / T0; return r; } void InertiaTensor(Matrix33 &J ){ Point3 r; r[X] = T1[X] / T0; r[Y] = T1[Y] / T0; r[Z] = T1[Z] / T0; /* compute inertia tensor */ J[X][X] = (T2[Y] + T2[Z]); J[Y][Y] = (T2[Z] + T2[X]); J[Z][Z] = (T2[X] + T2[Y]); J[X][Y] = J[Y][X] = - TP[X]; J[Y][Z] = J[Z][Y] = - TP[Y]; J[Z][X] = J[X][Z] = - TP[Z]; J[X][X] -= T0 * (r[Y]*r[Y] + r[Z]*r[Z]); J[Y][Y] -= T0 * (r[Z]*r[Z] + r[X]*r[X]); J[Z][Z] -= T0 * (r[X]*r[X] + r[Y]*r[Y]); J[X][Y] = J[Y][X] += T0 * r[X] * r[Y]; J[Y][Z] = J[Z][Y] += T0 * r[Y] * r[Z]; J[Z][X] = J[X][Z] += T0 * r[Z] * r[X]; } void InertiaTensor(Matrix44 &J ) { J.SetIdentity(); Point3 r; r[X] = T1[X] / T0; r[Y] = T1[Y] / T0; r[Z] = T1[Z] / T0; /* compute inertia tensor */ J[X][X] = (T2[Y] + T2[Z]); J[Y][Y] = (T2[Z] + T2[X]); J[Z][Z] = (T2[X] + T2[Y]); J[X][Y] = J[Y][X] = - TP[X]; J[Y][Z] = J[Z][Y] = - TP[Y]; J[Z][X] = J[X][Z] = - TP[Z]; J[X][X] -= T0 * (r[Y]*r[Y] + r[Z]*r[Z]); J[Y][Y] -= T0 * (r[Z]*r[Z] + r[X]*r[X]); J[Z][Z] -= T0 * (r[X]*r[X] + r[Y]*r[Y]); J[X][Y] = J[Y][X] += T0 * r[X] * r[Y]; J[Y][Z] = J[Z][Y] += T0 * r[Y] * r[Z]; J[Z][X] = J[X][Z] += T0 * r[Z] * r[X]; } // Calcola autovalori ed autovettori dell'inertia tensor. // Gli autovettori fanno una rotmatrix che se applicata mette l'oggetto secondo gli assi id minima/max inerzia. void InertiaTensorEigen(Matrix44 &EV, Point4 &ev ) { Matrix44 it; InertiaTensor(it); Matrix44d EVd,ITd;ITd.Import(it); Point4d evd; evd.Import(ev); int n; Jacobi(ITd,evd,EVd,n); EV.Import(EVd); ev.Import(evd); } }; // end class Inertia } // end namespace tri } // end namespace vcg qutemol/vcg/vcg/complex/trimesh/update/0000755000175000017500000000000011633404241016564 5ustar mbambaqutemol/vcg/vcg/complex/trimesh/update/curvature.h0000444000175000017500000003704511013343777020774 0ustar mbamba/**************************************************************************** * VCGLib o o * * Visual and Computer Graphics Library o o * * _ O _ * * Copyright(C) 2004 \/)\/ * * Visual Computing Lab /\/| * * ISTI - Italian National Research Council | * * \ * * All rights reserved. * * * * 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. * * * * 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 (http://www.gnu.org/licenses/gpl.txt) * * for more details. * * * ****************************************************************************/ /**************************************************************************** History $Log: curvature.h,v $ Revision 1.9 2008/05/16 17:44:31 cignoni updated to the new temporary data structure Revision 1.8 2008/05/14 10:03:29 ganovelli Point3f->Coordtype Revision 1.7 2008/04/23 16:37:15 onnis VertexCurvature method added. Revision 1.6 2008/04/04 10:26:12 cignoni Cleaned up names, now Kg() gives back Gaussian Curvature (k1*k2), while Kh() gives back Mean Curvature 1/2(k1+k2) Revision 1.5 2008/03/25 11:00:56 ganovelli fixed bugs sign of principal direction and mean curvature value Revision 1.4 2008/03/17 11:29:59 ganovelli taubin and desbrun estimates added (-> see vcg/simplex/vertexplus/component.h [component_ocf.h|component_occ.h ] Revision 1.3 2006/02/27 18:02:57 ponchio Area -> doublearea/2 added some typename Revision 1.2 2005/10/25 09:17:41 spinelli correct IsBorder Revision 1.1 2005/02/22 16:40:29 ganovelli created. This version writes the gaussian curvature on the Q() member of the vertex /****************************************************************************/ #ifndef VCGLIB_UPDATE_CURVATURE_ #define VCGLIB_UPDATE_CURVATURE_ #include #include #include #include #include #include #include namespace vcg { namespace tri { /** \addtogroup trimesh */ /*@{*/ /// Management, updating and computation of per-vertex and per-face normals. /// This class is used to compute or update the normals that can be stored in the vertex or face component of a mesh. template class UpdateCurvature { public: typedef typename MeshType::FaceType FaceType; typedef typename MeshType::FacePointer FacePointer; typedef typename MeshType::FaceIterator FaceIterator; typedef typename MeshType::VertexIterator VertexIterator; typedef typename MeshType::VertContainer VertContainer; typedef typename MeshType::VertexType VertexType; typedef typename MeshType::VertexPointer VertexPointer; typedef vcg::face::VFIterator VFIteratorType; typedef typename MeshType::CoordType CoordType; typedef typename CoordType::ScalarType ScalarType; private: typedef struct AdjVertex { VertexType * vert; float doubleArea; bool isBorder; }; public: /* Compute principal direction and magniuto of curvature as describe in the paper: @InProceedings{bb33922, author = "G. Taubin", title = "Estimating the Tensor of Curvature of a Surface from a Polyhedral Approximation", booktitle = "International Conference on Computer Vision", year = "1995", pages = "902--907", URL = "http://dx.doi.org/10.1109/ICCV.1995.466840", bibsource = "http://www.visionbib.com/bibliography/describe440.html#TT32253", */ static void PrincipalDirections(MeshType &m) { assert(m.HasVFTopology()); vcg::tri::UpdateNormals::PerVertexNormalized(m); VertexIterator vi; for (vi =m.vert.begin(); vi !=m.vert.end(); ++vi) { if ( ! (*vi).IsD() && (*vi).VFp() != NULL) { VertexType * central_vertex = &(*vi); std::vector weights; std::vector vertices; vcg::face::JumpingPos pos((*vi).VFp(), central_vertex); VertexType* firstV = pos.VFlip(); VertexType* tempV; float totalDoubleAreaSize = 0.0f; if (((firstV->cP()-central_vertex->cP())^(pos.VFlip()->cP()-central_vertex->cP()))*central_vertex->cN()<=0.0f) { pos.Set(central_vertex->VFp(), central_vertex); pos.FlipE(); firstV = pos.VFlip(); } else pos.Set(central_vertex->VFp(), central_vertex); do { pos.NextE(); tempV = pos.VFlip(); AdjVertex v; v.isBorder = pos.IsBorder(); v.vert = tempV; v.doubleArea = ((pos.F()->V(1)->cP() - pos.F()->V(0)->cP()) ^ (pos.F()->V(2)->cP()- pos.F()->V(0)->cP())).Norm();; totalDoubleAreaSize += v.doubleArea; vertices.push_back(v); } while(tempV != firstV); for (int i = 0; i < vertices.size(); ++i) { if (vertices[i].isBorder) { weights.push_back(vertices[i].doubleArea / totalDoubleAreaSize); } else { weights.push_back(0.5f * (vertices[i].doubleArea + vertices[(i-1)%vertices.size()].doubleArea) / totalDoubleAreaSize); } assert(weights.back() < 1.0f); } Matrix33 Tp; for (int i = 0; i < 3; ++i) Tp[i][i] = 1.0f - powf(central_vertex->cN()[i],2); Tp[0][1] = Tp[1][0] = -1.0f * (central_vertex->N()[0] * central_vertex->cN()[1]); Tp[1][2] = Tp[2][1] = -1.0f * (central_vertex->cN()[1] * central_vertex->cN()[2]); Tp[0][2] = Tp[2][0] = -1.0f * (central_vertex->cN()[0] * central_vertex->cN()[2]); Matrix33 tempMatrix; Matrix33 M; M.SetZero(); for (int i = 0; i < vertices.size(); ++i) { CoordType edge = (central_vertex->cP() - vertices[i].vert->cP()); float curvature = (2.0f * (central_vertex->cN() * edge) ) / edge.SquaredNorm(); CoordType T = (Tp*edge).Normalize(); tempMatrix.ExternalProduct(T,T); M += tempMatrix * weights[i] * curvature ; } CoordType W; CoordType e1(1.0f,0.0f,0.0f); if ((e1 - central_vertex->cN()).SquaredNorm() > (e1 + central_vertex->cN()).SquaredNorm()) W = e1 - central_vertex->cN(); else W = e1 + central_vertex->cN(); W.Normalize(); Matrix33 Q; Q.SetIdentity(); tempMatrix.ExternalProduct(W,W); Q -= tempMatrix * 2.0f; Matrix33 Qt(Q); Qt.Transpose(); Matrix33 QtMQ = (Qt * M * Q); CoordType bl = Q.GetColumn(0); CoordType T1 = Q.GetColumn(1); CoordType T2 = Q.GetColumn(2); float s,c; // Gabriel Taubin hint and Valentino Fiorin impementation float qt21 = QtMQ[2][1]; float qt12 = QtMQ[1][2]; float alpha = QtMQ[1][1]-QtMQ[2][2]; float beta = QtMQ[2][1]; float h[2]; float delta = sqrtf(4.0f*powf(alpha, 2) +16.0f*powf(beta, 2)); h[0] = (2.0f*alpha + delta) / (2.0f*beta); h[1] = (2.0f*alpha - delta) / (2.0f*beta); float t[2]; float best_c, best_s; float min_error = std::numeric_limits::infinity(); for (int i=0; i<2; i++) { delta = sqrtf(powf(h[1], 2) + 4.0f); t[0] = (h[i]+delta) / 2.0f; t[1] = (h[i]-delta) / 2.0f; for (int j=0; j<2; j++) { float squared_t = powf(t[j], 2); float denominator = 1.0f + squared_t; s = (2.0f*t[j]) / denominator; c = (1-squared_t) / denominator; float approximation = c*s*alpha + (powf(c, 2) - powf(s, 2))*beta; float angle_similarity = fabs(acosf(c)/asinf(s)); float error = fabs(1.0f-angle_similarity)+fabs(approximation); if (error TDAreaPtr(m.vert); //TDAreaPtr.Start(); SimpleTempData TDContr(m.vert); //TDContr.Start(); vcg::tri::UpdateNormals::PerVertexNormalized(m); //Compute AreaMix in H (vale anche per K) for(vi=m.vert.begin(); vi!=m.vert.end(); ++vi) if(!(*vi).IsD()) { (TDAreaPtr)[*vi].A = 0.0; (TDContr)[*vi] =typename MeshType::CoordType(0.0,0.0,0.0); (*vi).Kh() = 0.0; (*vi).Kg() = (float)(2.0 * M_PI); } for(fi=m.face.begin();fi!=m.face.end();++fi) if( !(*fi).IsD()) { // angles angle0 = math::Abs(Angle( (*fi).P(1)-(*fi).P(0),(*fi).P(2)-(*fi).P(0) )); angle1 = math::Abs(Angle( (*fi).P(0)-(*fi).P(1),(*fi).P(2)-(*fi).P(1) )); angle2 = M_PI-(angle0+angle1); if((angle0 < M_PI/2) && (angle1 < M_PI/2) && (angle2 < M_PI/2)) // triangolo non ottuso { float e01 = SquaredDistance( (*fi).V(1)->cP() , (*fi).V(0)->cP() ); float e12 = SquaredDistance( (*fi).V(2)->cP() , (*fi).V(1)->cP() ); float e20 = SquaredDistance( (*fi).V(0)->cP() , (*fi).V(2)->cP() ); area0 = ( e20*(1.0/tan(angle1)) + e01*(1.0/tan(angle2)) ) / 8.0; area1 = ( e01*(1.0/tan(angle2)) + e12*(1.0/tan(angle0)) ) / 8.0; area2 = ( e12*(1.0/tan(angle0)) + e20*(1.0/tan(angle1)) ) / 8.0; (TDAreaPtr)[(*fi).V(0)].A += area0; (TDAreaPtr)[(*fi).V(1)].A += area1; (TDAreaPtr)[(*fi).V(2)].A += area2; } else // obtuse { (TDAreaPtr)[(*fi).V(0)].A += vcg::DoubleArea((*fi)) / 6.0; (TDAreaPtr)[(*fi).V(1)].A += vcg::DoubleArea((*fi)) / 6.0; (TDAreaPtr)[(*fi).V(2)].A += vcg::DoubleArea((*fi)) / 6.0; } } for(fi=m.face.begin();fi!=m.face.end();++fi) if( !(*fi).IsD() ) { angle0 = math::Abs(Angle( (*fi).P(1)-(*fi).P(0),(*fi).P(2)-(*fi).P(0) )); angle1 = math::Abs(Angle( (*fi).P(0)-(*fi).P(1),(*fi).P(2)-(*fi).P(1) )); angle2 = M_PI-(angle0+angle1); e01v = ( (*fi).V(1)->cP() - (*fi).V(0)->cP() ) ; e12v = ( (*fi).V(2)->cP() - (*fi).V(1)->cP() ) ; e20v = ( (*fi).V(0)->cP() - (*fi).V(2)->cP() ) ; TDContr[(*fi).V(0)] += ( e20v * (1.0/tan(angle1)) - e01v * (1.0/tan(angle2)) ) / 4.0; TDContr[(*fi).V(1)] += ( e01v * (1.0/tan(angle2)) - e12v * (1.0/tan(angle0)) ) / 4.0; TDContr[(*fi).V(2)] += ( e12v * (1.0/tan(angle0)) - e20v * (1.0/tan(angle1)) ) / 4.0; (*fi).V(0)->Kg() -= angle0; (*fi).V(1)->Kg() -= angle1; (*fi).V(2)->Kg() -= angle2; for(int i=0;i<3;i++) { if(vcg::face::IsBorder((*fi), i)) { CoordType e1,e2; vcg::face::Pos hp(&*fi, i, (*fi).V(i)); vcg::face::Pos hp1=hp; hp1.FlipV(); e1=hp1.v->cP() - hp.v->cP(); hp1.FlipV(); hp1.NextB(); e2=hp1.v->cP() - hp.v->cP(); (*fi).V(i)->Kg() -= math::Abs(Angle(e1,e2)); } } } for(vi=m.vert.begin(); vi!=m.vert.end(); ++vi) if(!(*vi).IsD() /*&& !(*vi).IsB()*/) { if((TDAreaPtr)[*vi].A<=std::numeric_limits::epsilon()) { (*vi).Kh() = 0; (*vi).Kg() = 0; } else { (*vi).Kh() = (((TDContr)[*vi]* (*vi).cN()>0)?1.0:-1.0)*((TDContr)[*vi] / (TDAreaPtr) [*vi].A).Norm(); (*vi).Kg() /= (TDAreaPtr)[*vi].A; } } // TDAreaPtr.Stop(); // TDContr.Stop(); } /* Update the mean and the gaussian curvature of a vertex, using the * VF adiacency to walk around the vertex. Return the voronoi area * around the vertex. * if norm == true, the mean and the gaussian curvature are normalized * based on the paper * "optimizing 3d triangulations using discrete curvature analysis" * http://www2.in.tu-clausthal.de/~hormann/papers/Dyn.2001.OTU.pdf * */ static float VertexCurvature(VertexPointer v, bool norm = true) { // VFAdjacency required! assert(FaceType::HasVFAdjacency()); assert(VertexType::HasVFAdjacency()); VFIteratorType vfi(v); float A = 0; v->Kh() = 0; v->Kg() = 2 * M_PI; while (!vfi.End()) { if (!vfi.F()->IsD()) { FacePointer f = vfi.F(); int i = vfi.I(); VertexPointer v0 = f->V0(i), v1 = f->V1(i), v2 = f->V2(i); float ang0 = math::Abs(Angle(v1->P() - v0->P(), v2->P() - v0->P() )); float ang1 = math::Abs(Angle(v0->P() - v1->P(), v2->P() - v1->P() )); float ang2 = M_PI - ang0 - ang1; float s01 = SquaredDistance(v1->P(), v0->P()); float s02 = SquaredDistance(v2->P(), v0->P()); // voronoi cell of current vertex if (ang0 >= M_PI/2) A += (0.5f * DoubleArea(*f) - (s01 * tan(ang1) + s02 * tan(ang2)) / 8.0 ); else if (ang1 >= M_PI/2) A += (s01 * tan(ang0)) / 8.0; else if (ang2 >= M_PI/2) A += (s02 * tan(ang0)) / 8.0; else // non obctuse triangle A += ((s02 / tan(ang1)) + (s01 / tan(ang2))) / 8.0; // gaussian curvature update v->Kg() -= ang0; // mean curvature update ang1 = math::Abs(Angle(f->N(), v1->N())); ang2 = math::Abs(Angle(f->N(), v2->N())); v->Kh() += ( (math::Sqrt(s01) / 2.0) * ang1 + (math::Sqrt(s02) / 2.0) * ang2 ); } ++vfi; } v->Kh() /= 4.0f; if(norm) { if(A <= std::numeric_limits::epsilon()) { v->Kh() = 0; v->Kg() = 0; } else { v->Kh() /= A; v->Kg() /= A; } } return A; } }; } } #endif qutemol/vcg/vcg/complex/trimesh/update/topology.h0000444000175000017500000002732610776354512020635 0ustar mbamba/**************************************************************************** * VCGLib o o * * Visual and Computer Graphics Library o o * * _ O _ * * Copyright(C) 2004 \/)\/ * * Visual Computing Lab /\/| * * ISTI - Italian National Research Council | * * \ * * All rights reserved. * * * * 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. * * * * 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 (http://www.gnu.org/licenses/gpl.txt) * * for more details. * * * ****************************************************************************/ /**************************************************************************** History $Log: topology.h,v $ Revision 1.21 2008/04/07 08:20:26 cignoni Added texture topology computation Revision 1.20 2008/04/04 10:27:34 cignoni minor changes to the topology correctness checks Revision 1.19 2007/05/29 00:07:06 ponchio VFi++ -> ++VFi Revision 1.18 2006/02/27 19:26:14 spinelli minor bug in Face-Face topology loop fixed Revision 1.17 2006/02/27 11:56:48 spinelli minor bug in Face-Face topology loop fixed Revision 1.16 2005/11/10 15:36:42 cignoni Added clarifying comment in an assert Revision 1.15 2004/10/20 07:33:10 cignoni removed FaceBorderFlags (already present in update/flags.h) Revision 1.14 2004/10/18 17:10:22 ganovelli added ::FaceBorderFLags Revision 1.13 2004/10/01 15:58:00 ponchio Added include Revision 1.12 2004/09/09 13:02:12 ponchio Linux compatible path in #include Revision 1.11 2004/08/07 16:18:20 pietroni addet testFFTopology and testVFTopology functions used to test the rispective topology.... Revision 1.10 2004/07/15 11:35:08 ganovelli Vfb to VFp Revision 1.9 2004/07/15 00:13:39 cignoni Better doxigen documentation Revision 1.8 2004/06/02 16:42:44 ganovelli typename for gcc compilation Revision 1.7 2004/06/02 16:28:22 ganovelli minor changes (swap =>> math::Swap) Revision 1.6 2004/05/10 15:23:43 cignoni Changed a FV -> VF in VertexFace topology computation Revision 1.5 2004/05/06 15:24:38 pietroni changed names to topology functions Revision 1.4 2004/03/31 14:44:43 cignoni Added Vertex-Face Topology Revision 1.3 2004/03/12 15:22:19 cignoni Written some documentation and added to the trimes doxygen module Revision 1.2 2004/03/05 21:49:21 cignoni First working version for face face Revision 1.1 2004/03/04 00:53:24 cignoni Initial commit ****************************************************************************/ #ifndef __VCG_TRI_UPDATE_TOPOLOGY #define __VCG_TRI_UPDATE_TOPOLOGY #include #include #include namespace vcg { namespace tri { /** \addtogroup trimesh */ /*@{*/ /** Generation of per-vertex and per-face topological information. **/ template class UpdateTopology { public: typedef UpdateMeshType MeshType; typedef typename MeshType::VertexType VertexType; typedef typename MeshType::VertexPointer VertexPointer; typedef typename MeshType::VertexIterator VertexIterator; typedef typename MeshType::FaceType FaceType; typedef typename MeshType::FacePointer FacePointer; typedef typename MeshType::FaceIterator FaceIterator; /// Auxiliairy data structure for computing face face adjacency information. // It identifies and edge storing two vertex pointer and a face pointer where it belong. class PEdge { public: VertexPointer v[2]; // the two Vertex pointer are ordered! FacePointer f; // the face where this edge belong int z; // index in [0..2] of the edge of the face PEdge() {} void Set( FacePointer pf, const int nz ) { assert(pf!=0); assert(nz>=0); assert(nz<3); v[0] = pf->V(nz); v[1] = pf->V((nz+1)%3); assert(v[0] != v[1]); // The face pointed by 'f' is Degenerate (two coincident vertexes) if( v[0] > v[1] ) math::Swap(v[0],v[1]); f = pf; z = nz; } inline bool operator < ( const PEdge & pe ) const { if( v[0]pe.v[0] ) return false; else return v[1] < pe.v[1]; } inline bool operator <= ( const PEdge & pe ) const { if( v[0]pe.v[0] ) return false; else return v[1] <= pe.v[1]; } inline bool operator > ( const PEdge & pe ) const { if( v[0]>pe.v[0] ) return true; else if( v[0] pe.v[1]; } inline bool operator >= ( const PEdge & pe ) const { if( v[0]>pe.v[0] ) return true; else if( v[0]= pe.v[1]; } inline bool operator == ( const PEdge & pe ) const { return v[0]==pe.v[0] && v[1]==pe.v[1]; } inline bool operator != ( const PEdge & pe ) const { return v[0]!=pe.v[0] || v[1]!=pe.v[1]; } }; /** Update the Face-Face topological relation by allowing to retrieve for each face what other faces shares their edges. */ static void FaceFace(MeshType &m) { if(!m.HasFFTopology()) return; std::vector e; FaceIterator pf; typename std::vector::iterator p; if( m.fn == 0 ) return; e.resize(m.fn*3); // Alloco il vettore ausiliario p = e.begin(); for(pf=m.face.begin();pf!=m.face.end();++pf) // Lo riempio con i dati delle facce if( ! (*pf).IsD() ) for(int j=0;j<3;++j) { (*p).Set(&(*pf),j); ++p; } assert(p==e.end()); sort(e.begin(), e.end()); // Lo ordino per vertici int ne = 0; // Numero di edge reali typename std::vector::iterator pe,ps; ps = e.begin();pe=e.begin(); //for(ps = e.begin(),pe=e.begin();pe<=e.end();++pe) // Scansione vettore ausiliario do { if( pe==e.end() || *pe != *ps ) // Trovo blocco di edge uguali { typename std::vector::iterator q,q_next; for (q=ps;q=0); assert((*q).z< 3); q_next = q; ++q_next; assert((*q_next).z>=0); assert((*q_next).z< 3); (*q).f->FFp(q->z) = (*q_next).f; // Collegamento in lista delle facce (*q).f->FFi(q->z) = (*q_next).z; } assert((*q).z>=0); assert((*q).z< 3); (*q).f->FFp((*q).z) = ps->f; (*q).f->FFi((*q).z) = ps->z; ps = pe; ++ne; // Aggiorno il numero di edge } if(pe==e.end()) break; ++pe; } while(true); } /** Update the Vertex-Face topological relation by allowing to retrieve for each vertex the list of faces sharing this vertex.. */ static void VertexFace(MeshType &m) { if(!m.HasVFTopology()) return; VertexIterator vi; FaceIterator fi; for(vi=m.vert.begin();vi!=m.vert.end();++vi) { (*vi).VFp() = 0; (*vi).VFi() = 0; } for(fi=m.face.begin();fi!=m.face.end();++fi) if( ! (*fi).IsD() ) { for(int j=0;j<3;++j) { (*fi).VFp(j) = (*fi).V(j)->VFp(); (*fi).VFi(j) = (*fi).V(j)->VFi(); (*fi).V(j)->VFp() = &(*fi); (*fi).V(j)->VFi() = j; } } } /// Auxiliairy data structure for computing face face adjacency information. // It identifies and edge storing two vertex pointer and a face pointer where it belong. class PEdgeTex { public: typename FaceType::TexCoordType v[2]; // the two Vertex pointer are ordered! FacePointer f; // the face where this edge belong int z; // index in [0..2] of the edge of the face PEdgeTex() {} void Set( FacePointer pf, const int nz ) { assert(pf!=0); assert(nz>=0); assert(nz<3); v[0] = pf->WT(nz); v[1] = pf->WT((nz+1)%3); assert(v[0] != v[1]); // The face pointed by 'f' is Degenerate (two coincident vertexes) if( v[1] < v[0] ) swap(v[0],v[1]); f = pf; z = nz; } inline bool operator < ( const PEdgeTex & pe ) const { if( v[0] e; FaceIterator pf; typename std::vector::iterator p; if( m.fn == 0 ) return; e.resize(m.fn*3); // Alloco il vettore ausiliario p = e.begin(); for(pf=m.face.begin();pf!=m.face.end();++pf) // Lo riempio con i dati delle facce if( ! (*pf).IsD() ) for(int j=0;j<3;++j) { (*p).Set(&(*pf),j); ++p; } assert(p==e.end()); sort(e.begin(), e.end()); // Lo ordino per vertici int ne = 0; // Numero di edge reali typename std::vector::iterator pe,ps; ps = e.begin();pe=e.begin(); //for(ps = e.begin(),pe=e.begin();pe<=e.end();++pe) // Scansione vettore ausiliario do { if( pe==e.end() || (*pe) != (*ps) ) // Trovo blocco di edge uguali { typename std::vector::iterator q,q_next; for (q=ps;q=0); assert((*q).z< 3); q_next = q; ++q_next; assert((*q_next).z>=0); assert((*q_next).z< 3); (*q).f->FFp(q->z) = (*q_next).f; // Collegamento in lista delle facce (*q).f->FFi(q->z) = (*q_next).z; } assert((*q).z>=0); assert((*q).z< 3); (*q).f->FFp((*q).z) = ps->f; (*q).f->FFi((*q).z) = ps->z; ps = pe; ++ne; // Aggiorno il numero di edge } if(pe==e.end()) break; ++pe; } while(true); } ///test correctness of VFtopology static void TestVertexFace(MeshType &m) { if(!m.HasVFTopology()) return; VertexIterator vi; vcg::face::VFIterator VFi; for(vi=m.vert.begin();vi!=m.vert.end();++vi) { if (!vi->IsD()) if(vi->VFp()!=0) // unreferenced vertices MUST have VF == 0; { assert(vi->VFp() >= &*m.face.begin()); assert(vi->VFp() <= &m.face.back()); VFi.f=vi->VFp(); VFi.z=vi->VFi(); while (!VFi.End()) { assert(!VFi.F()->IsD()); assert((VFi.F()->V(VFi.I()))==&(*vi)); ++VFi; } } } } ///test correctness of FFtopology static void TestFaceFace(MeshType &m) { if(!m.HasFFTopology()) return; FaceIterator Fi; for(Fi=m.face.begin();Fi!=m.face.end();++Fi) { if (!Fi->IsD()) { for (int i=0;i<3;i++) { FaceType *f=Fi->FFp(i); int e=Fi->FFi(i); //invariant property of fftopology assert(f->FFp(e)=&(*Fi)); // Test that the two faces shares the same edge VertexPointer v0= Fi->V0(i); VertexPointer v1= Fi->V1(i); assert( (f->V0(e)==v0) || (f->V1(e)==v0) ); assert( (f->V0(e)==v1) || (f->V1(e)==v1) ); // Old unreadable test // assert(((f->V(e) == Fi->V(i))&&(f->V((e+1)%3)==Fi->V((i+1)%3)))|| // ((f->V(e)==Fi->V((i+1)%3))&&(f->V((e+1)%3)==Fi->V(i)))); } } } } }; // end class /*@}*/ } // End namespace } // End namespace #endif qutemol/vcg/vcg/complex/trimesh/update/normal.h0000444000175000017500000002512111010710460020214 0ustar mbamba/**************************************************************************** * VCGLib o o * * Visual and Computer Graphics Library o o * * _ O _ * * Copyright(C) 2004 \/)\/ * * Visual Computing Lab /\/| * * ISTI - Italian National Research Council | * * \ * * All rights reserved. * * * * 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. * * * * 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 (http://www.gnu.org/licenses/gpl.txt) * * for more details. * * * ****************************************************************************/ /**************************************************************************** History $Log: normal.h,v $ Revision 1.21 2008/05/08 23:48:00 cignoni added normalizevertex Revision 1.20 2008/04/18 17:52:08 cignoni added PerVertexFromCurrentFaceNormal AreaNormalizeFace NormalizeFace and shortened PerVertexNormalizedPerFaceNormalized Revision 1.19 2008/02/15 08:08:59 cignoni added missing include matrix33 Revision 1.18 2007/12/13 17:57:27 cignoni removed harmless gcc warnings Revision 1.17 2007/11/23 17:02:47 cignoni disambiguated pow call (again) Revision 1.16 2007/11/23 15:42:11 cignoni disambiguated pow call Revision 1.15 2007/11/14 11:56:23 ganovelli added updating of vertex and face normals Revision 1.14 2007/07/12 23:11:35 cignoni added the missing PerVertexNormalizedPerFaceNormalized Revision 1.13 2007/01/10 17:25:14 matteodelle *** empty log message *** Revision 1.12 2006/11/07 15:13:56 zifnab1974 Necessary changes for compilation with gcc 3.4.6. Especially the hash function is a problem Revision 1.11 2005/12/06 18:22:31 pietroni changed FaceType::ComputeNormal and FaceType::ComputeNormalizedNormal with face::ComputeNormal and face::ComputeNormalizedNormal Revision 1.10 2005/12/06 15:30:45 ponchio added #include triangle3.h for Normal(...) added a few FaceType:: instead of face:: Revision 1.9 2005/11/22 15:47:34 cignoni Moved ComputeNormal and ComputeNormalizedNormal out of the face class (no more a member function!) Revision 1.8 2005/11/21 21:44:43 cignoni Moved ComputeNormal and ComputeNormalizedNormal out of the face class (no more a member function!) Revision 1.7 2005/10/13 08:38:00 cignoni removed the access to the face member function normal and substituted with vcg::normal(*f); Revision 1.6 2005/06/17 00:46:09 cignoni Added a PerVertexNormalizedPerFace (vertex are face/area weighted AND normalized) Revision 1.5 2005/04/01 13:04:55 fiorin Minor changes Revision 1.4 2004/09/09 14:35:14 ponchio Typename changes for linux Revision 1.3 2004/08/31 15:18:54 pietroni minor changes to comply gcc compiler (typename's ) Revision 1.2 2004/03/12 15:22:19 cignoni Written some documentation and added to the trimes doxygen module Revision 1.1 2004/03/05 10:59:24 cignoni Changed name from plural to singular (normals->normal) Revision 1.1 2004/03/04 00:05:50 cignoni First working version! Revision 1.1 2004/02/19 13:11:06 cignoni Initial commit ****************************************************************************/ #ifndef __VCG_TRI_UPDATE_NORMALS #define __VCG_TRI_UPDATE_NORMALS #include #include namespace vcg { namespace tri { /** \addtogroup trimesh */ /*@{*/ /// Management, updating and computation of per-vertex and per-face normals. /// This class is used to compute or update the normals that can be stored in the vertex or face component of a mesh. template class UpdateNormals { public: typedef ComputeMeshType MeshType; typedef typename MeshType::VertexType VertexType; typedef typename VertexType::NormalType NormalType; typedef typename VertexType::ScalarType ScalarType; typedef typename MeshType::VertexPointer VertexPointer; typedef typename MeshType::VertexIterator VertexIterator; typedef typename MeshType::FaceType FaceType; typedef typename MeshType::FacePointer FacePointer; typedef typename MeshType::FaceIterator FaceIterator; /// Calculates the face normal (if stored in the current face type) static void PerFace(ComputeMeshType &m) { if( !m.HasPerFaceNormal()) return; FaceIterator f; for(f=m.face.begin();f!=m.face.end();++f) if( !(*f).IsD() ) face::ComputeNormal(*f); } /// Calculates the vertex normal. Exploiting or current face normals /// The normal of a vertex v is the weigthed average of the normals of the faces incident on v. static void PerVertexFromCurrentFaceNormal(ComputeMeshType &m) { if( !m.HasPerVertexNormal()) return; VertexIterator vi; for(vi=m.vert.begin();vi!=m.vert.end();++vi) if( !(*vi).IsD() && (*vi).IsRW() ) (*vi).N().Construct(0,0,0); FaceIterator fi; for(fi=m.face.begin();fi!=m.face.end();++fi) if( !(*fi).IsD()) { for(int j=0; j<3; ++j) if( !(*fi).V(j)->IsD()) (*fi).V(j)->N() += (*fi).cN(); } } /// Calculates the vertex normal. Without exploiting or touching face normals /// The normal of a vertex v is the weigthed average of the normals of the faces incident on v. static void PerVertex(ComputeMeshType &m) { if( !m.HasPerVertexNormal()) return; VertexIterator vi; for(vi=m.vert.begin();vi!=m.vert.end();++vi) if( !(*vi).IsD() && (*vi).IsRW() ) (*vi).N() = NormalType((ScalarType)0,(ScalarType)0,(ScalarType)0); FaceIterator f; for(f=m.face.begin();f!=m.face.end();++f) if( !(*f).IsD() && (*f).IsR() ) { //typename FaceType::NormalType t = (*f).Normal(); typename FaceType::NormalType t = vcg::Normal(*f); for(int j=0; j<3; ++j) if( !(*f).V(j)->IsD() && (*f).V(j)->IsRW() ) (*f).V(j)->N() += t; } } /// Calculates both vertex and face normals. /// The normal of a vertex v is the weigthed average of the normals of the faces incident on v. static void PerVertexPerFace(ComputeMeshType &m) { if( !m.HasPerVertexNormal() || !m.HasPerFaceNormal()) return; PerFace(m); VertexIterator vi; for(vi=m.vert.begin();vi!=m.vert.end();++vi) if( !(*vi).IsD() && (*vi).IsRW() ) (*vi).N() = NormalType((ScalarType)0,(ScalarType)0,(ScalarType)0); FaceIterator f; for(f=m.face.begin();f!=m.face.end();++f) if( !(*f).IsD() && (*f).IsR() ) { for(int j=0; j<3; ++j) if( !(*f).V(j)->IsD() && (*f).V(j)->IsRW() ) (*f).V(j)->N() += (*f).cN(); } } /// Calculates both vertex and face normals. /// The normal of a vertex v is the weigthed average of the normals of the faces incident on v. static void PerVertexNormalizedPerFace(ComputeMeshType &m) { PerVertexPerFace(m); NormalizeVertex(m); } /// Normalize the lenght of the face normals static void NormalizeVertex(ComputeMeshType &m) { VertexIterator vi; for(vi=m.vert.begin();vi!=m.vert.end();++vi) if( !(*vi).IsD() && (*vi).IsRW() ) (*vi).N().Normalize(); } /// Normalize the lenght of the face normals static void NormalizeFace(ComputeMeshType &m) { FaceIterator fi; for(fi=m.face.begin();fi!=m.face.end();++fi) if( !(*fi).IsD() ) (*fi).N().Normalize(); } static void AreaNormalizeFace(ComputeMeshType &m) { FaceIterator fi; for(fi=m.face.begin();fi!=m.face.end();++fi) if( !(*fi).IsD() ) { (*fi).N().Normalize(); (*fi).N() = (*fi).N() * DoubleArea(*fi); } } static void PerVertexNormalizedPerFaceNormalized(ComputeMeshType &m) { PerVertexNormalizedPerFace(m); NormalizeFace(m); } static void PerFaceRW(ComputeMeshType &m, bool normalize=false) { if( !m.HasPerFaceNormal()) return; FaceIterator f; bool cn = true; if(normalize) { for(f=m.m.face.begin();f!=m.m.face.end();++f) if( !(*f).IsD() && (*f).IsRW() ) { for(int j=0; j<3; ++j) if( !(*f).V(j)->IsR()) cn = false; if( cn ) face::ComputeNormalizedNormal(*f); cn = true; } } else { for(f=m.m.face.begin();f!=m.m.face.end();++f) if( !(*f).IsD() && (*f).IsRW() ) { for(int j=0; j<3; ++j) if( !(*f).V(j)->IsR()) cn = false; if( cn ) (*f).ComputeNormal(); cn = true; } } } static void PerFaceNormalized(ComputeMeshType &m) { if( !m.HasPerFaceNormal()) return; FaceIterator f; for(f=m.face.begin();f!=m.face.end();++f) if( !(*f).IsD() ) face::ComputeNormalizedNormal(*f); } /// Calculates the vertex normal static void PerVertexNormalized(ComputeMeshType &m) { if( !m.HasPerVertexNormal()) return; PerVertex(m); for(VertexIterator vi=m.vert.begin();vi!=m.vert.end();++vi) if( !(*vi).IsD() && (*vi).IsRW() ) (*vi).N().Normalize(); } /// multiply the vertex normals by the matrix passed. By default, the scale component is removed static void PerVertexMatrix(ComputeMeshType &m, const Matrix44 &mat, bool remove_scaling= true){ float scale; Matrix33 mat33(mat,3); if( !m.HasPerVertexNormal()) return; if(remove_scaling){ scale = pow(mat33.Determinant(),(ScalarType)(1.0/3.0)); mat33[0][0]/=scale; mat33[1][1]/=scale; mat33[2][2]/=scale; } for(VertexIterator vi=m.vert.begin();vi!=m.vert.end();++vi) if( !(*vi).IsD() && (*vi).IsRW() ) (*vi).N() = mat33*(*vi).N(); } /// multiply the face normals by the matrix passed. By default, the scale component is removed static void PerFaceMatrix(ComputeMeshType &m, const Matrix44 &mat, bool remove_scaling= true){ float scale; Matrix33 mat33(mat,3); if( !m.HasPerFaceNormal()) return; if(remove_scaling){ scale = pow(mat33.Determinant(),ScalarType(1.0/3.0)); mat33[0][0]/=scale; mat33[1][1]/=scale; mat33[2][2]/=scale; } for(FaceIterator fi=m.face.begin();fi!=m.face.end();++fi) if( !(*fi).IsD() && (*fi).IsRW() ) (*fi).N() = mat33* (*fi).N(); } }; // end class } // End namespace } // End namespace #endif qutemol/vcg/vcg/complex/trimesh/update/quality.h0000444000175000017500000002215410775424623020443 0ustar mbamba/**************************************************************************** * VCGLib o o * * Visual and Computer Graphics Library o o * * _ O _ * * Copyright(C) 2004 \/)\/ * * Visual Computing Lab /\/| * * ISTI - Italian National Research Council | * * \ * * All rights reserved. * * * * 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. * * * * 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 (http://www.gnu.org/licenses/gpl.txt) * * for more details. * * * ****************************************************************************/ /**************************************************************************** History $Log: quality.h,v $ Revision 1.8 2008/04/04 13:13:55 cignoni added methods for computing various kind of curvatures indicator from the HK values Revision 1.7 2005/03/17 16:16:08 cignoni removed small gcc compiling issues Revision 1.6 2005/03/15 11:48:50 cignoni Added missing include assert and improved comments and requirements of geodesic quality Revision 1.5 2004/07/15 00:13:39 cignoni Better doxigen documentation Revision 1.4 2004/07/06 06:29:53 cignoni removed assumption of a using namespace std and added a missing include Revision 1.3 2004/06/24 15:15:12 cignoni Better Doxygen documentation Revision 1.2 2004/05/10 13:43:00 cignoni Added use of VFIterator in VertexGeodesicFromBorder Revision 1.1 2004/03/31 14:59:14 cignoni First working version! Revision 1.2 2004/03/29 14:26:57 cignoni First working version! ****************************************************************************/ #ifndef __VCG_TRI_UPDATE_QUALITY #define __VCG_TRI_UPDATE_QUALITY #include #include #include #include namespace vcg { namespace tri { /** \addtogroup trimesh */ /*@{*/ /** Generation of per-vertex and per-face Qualities according to various strategy, like geodesic distance from the border (UpdateQuality::VertexGeodesicFromBorder) or curvature ecc. This class is templated over the mesh and (like all other Update* classes) has only static members; Typical usage: \code MyMeshType m; UpdateQuality::VertexGeodesicFromBorder(m); \endcode **/ template class UpdateQuality { public: typedef UpdateMeshType MeshType; typedef typename MeshType::ScalarType ScalarType; typedef typename MeshType::VertexType VertexType; typedef typename MeshType::VertexPointer VertexPointer; typedef typename MeshType::VertexIterator VertexIterator; typedef typename MeshType::FaceType FaceType; typedef typename MeshType::FacePointer FacePointer; typedef typename MeshType::FaceIterator FaceIterator; class VQualityHeap { public: float q; VertexPointer p; inline VQualityHeap( VertexPointer np ) { q = np->Q(); p = np; } // Attenzione il minore e' maggiore inline bool operator < ( const VQualityHeap & vq ) const { return q > vq.q; } inline bool operator == ( const VQualityHeap & vq ) const { return q == vq.q; } inline bool operator > ( const VQualityHeap & vq ) const { return q < vq.q; } inline bool operator != ( const VQualityHeap & vq ) const { return q != vq.q; } inline bool operator <= ( const VQualityHeap & vq ) const { return q >= vq.q; } inline bool operator >= ( const VQualityHeap & vq ) const { return q <= vq.q; } inline bool is_valid() const { return q==p->Q(); } }; // *** IMPORTANT REQUIREMENTS // VF topology // Border FLags // tri::UpdateTopology::VertexFace(sm); // tri::UpdateFlags::FaceBorderFromVF(sm); // // Calcola la qualita' come distanza geodesica dal bordo della mesh. // Robusta funziona anche per mesh non manifold. // La qualita' memorizzata indica la distanza assoluta dal bordo della mesh. // Nota prima del 13/11/03 in alcuni casi rari SPT andava in loop perche' poteva capitare // che per approx numeriche ben strane pw->Q() > pv->Q()+d ma durante la memorizzazione // della nuova distanza essa rimanesse uguale a prima. Patchato rimettendo i vertici nello // heap solo se migliorano la distanza di un epsilon == 1/100000 della mesh diag. /** Compute, for each vertex of the mesh the geodesic distance from the border of the mesh itself; Requirements: VF topology, Per Vertex Quality and border flags already computed (see UpdateFlags::FaceBorderFromVF and UpdateTopology::VertexFace); it uses the classical dijkstra Shortest Path Tree algorithm. The geodesic distance is approximated by allowing to walk only along edges of the mesh. */ static void VertexGeodesicFromBorder(MeshType &m) // R1 { //Requirements assert(m.HasVFTopology()); assert(m.HasPerVertexQuality()); std::vector< VQualityHeap > heap; VertexIterator v; FaceIterator f; int j; for(v=m.vert.begin();v!=m.vert.end();++v) (*v).Q() = -1; for(f=m.face.begin();f!=m.face.end();++f) // Inserisco nell'heap i v di bordo if(!(*f).IsD()) for(j=0;j<3;++j) if( (*f).IsB(j) ) { for(int k=0;k<2;++k) { VertexPointer pv = (*f).V((j+k)%3); if( pv->Q()==-1 ) { pv->Q() = 0; heap.push_back(VQualityHeap(pv)); } } } const ScalarType loc_eps=m.bbox.Diag()/ScalarType(100000); while( heap.size()!=0 ) // Shortest path tree { VertexPointer pv; std::pop_heap(heap.begin(),heap.end()); if( ! heap.back().is_valid() ) { heap.pop_back(); continue; } pv = heap.back().p; heap.pop_back(); for(face::VFIterator vfi(pv) ; !vfi.End(); ++vfi ) { for(int k=0;k<2;++k) { VertexPointer pw; float d; if(k==0) pw = vfi.f->V1(vfi.z); else pw = vfi.f->V2(vfi.z); d = Distance(pv->P(),pw->P()); if( pw->Q()==-1 || pw->Q() > pv->Q()+d + loc_eps) { pw->Q() = pv->Q()+d; heap.push_back(VQualityHeap(pw)); std::push_heap(heap.begin(),heap.end()); } } } } for(v=m.vert.begin();v!=m.vert.end();++v) if(v->Q()==-1) v->Q() = 0; } /** Assign to each vertex of the mesh a constant quality value. Useful for initialization. */ static void VertexConstant(MeshType &m, float q) { VertexIterator vi; for(vi=m.vert.begin();vi!=m.vert.end();++vi) if(!(*vi).IsD()) (*vi).Q()=q; } /** Assign to each face of the mesh a constant quality value. Useful for initialization. */ static void FaceConstant(MeshType &m, float q) { FaceIterator fi; for(fi=m.face.begin();fi!=m.face.end();++fi) (*fi).Q()=q; } static void VertexFromGaussianCurvature(MeshType &m) { VertexIterator vi; for(vi=m.vert.begin();vi!=m.vert.end();++vi) if(!(*vi).IsD()) (*vi).Q() = (*vi).Kg(); } static void VertexFromMeanCurvature(MeshType &m) { VertexIterator vi; for(vi=m.vert.begin();vi!=m.vert.end();++vi) if(!(*vi).IsD()) (*vi).Q() = (*vi).Kh(); } /* * Absolute Curvature * * 2|H| if K >= 0 * |k1| + |k2| = < * 2 * sqrt(|H|^2-K) otherwise * * defs and formulas taken from * * Improved curvature estimation for watershed segmentation of 3-dimensional meshes * S Pulla, A Razdan, G Farin - Arizona State University, Tech. Rep, 2001 * and from * Optimizing 3D triangulations using discrete curvature analysis * N Dyn, K Hormann, SJ Kim, D Levin - Mathematical Methods for Curves and Surfaces: Oslo, 2000 */ static void VertexFromAbsoluteCurvature(MeshType &m) { VertexIterator vi; for(vi=m.vert.begin();vi!=m.vert.end();++vi) if(!(*vi).IsD()) { if((*vi).Kg() >= 0) (*vi).Q() = math::Abs( 2*(*vi).Kh() ); else (*vi).Q() = 2*math::Sqrt(math::Abs( (*vi).Kh()*(*vi).Kh() - (*vi).Kg())); } } /* * RMS Curvature = sqrt(4H^2-2K) * def and formula taken from * * Improved curvature estimation for watershed segmentation of 3-dimensional meshes * S Pulla, A Razdan, G Farin - Arizona State University, Tech. Rep, 2001 */ static void VertexFromRMSCurvature(MeshType &m) { VertexIterator vi; for(vi=m.vert.begin();vi!=m.vert.end();++vi) if(!(*vi).IsD()) (*vi).Q() = math::Sqrt(math::Abs( 4*(*vi).Kh()*(*vi).Kh() - 2*(*vi).Kg())); } }; //end class } // end namespace } // end namespace #endif qutemol/vcg/vcg/complex/trimesh/update/bounding.h0000444000175000017500000000664610473072004020553 0ustar mbamba/**************************************************************************** * VCGLib o o * * Visual and Computer Graphics Library o o * * _ O _ * * Copyright(C) 2004 \/)\/ * * Visual Computing Lab /\/| * * ISTI - Italian National Research Council | * * \ * * All rights reserved. * * * * 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. * * * * 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 (http://www.gnu.org/licenses/gpl.txt) * * for more details. * * * ****************************************************************************/ // marco: removed types FaceType, FacePointer, FaceIterator to allow the use of this method from vertex meshes /**************************************************************************** History $Log: bounding.h,v $ Revision 1.3 2006/08/23 15:28:04 marfr960 removed types FaceType, FacePointer, FaceIterator Revision 1.2 2004/09/15 11:16:27 ganovelli changed P() to cP() Revision 1.1 2004/04/05 11:56:13 cignoni First working version! Revision 1.2 2004/03/12 15:22:19 cignoni Written some documentation and added to the trimes doxygen module Revision 1.1 2004/03/05 10:59:24 cignoni Changed name from plural to singular (normals->normal) Revision 1.1 2004/03/04 00:05:50 cignoni First working version! Revision 1.1 2004/02/19 13:11:06 cignoni Initial commit ****************************************************************************/ #ifndef __VCG_TRI_UPDATE_BOUNDING #define __VCG_TRI_UPDATE_BOUNDING namespace vcg { namespace tri { /** \addtogroup trimesh */ /*@{*/ /// Management, updating and computation of per-vertex and per-face normals. /// This class is used to compute or update the normals that can be stored in the vertex or face component of a mesh. template class UpdateBounding { public: typedef ComputeMeshType MeshType; typedef typename MeshType::VertexType VertexType; typedef typename MeshType::VertexPointer VertexPointer; typedef typename MeshType::VertexIterator VertexIterator; /// Calculates the bounding box of the m /// static void Box(ComputeMeshType &m) { m.bbox.SetNull(); VertexIterator vi; for(vi = m.vert.begin(); vi != m.vert.end(); ++vi) if( !(*vi).IsD() ) m.bbox.Add((*vi).cP()); } }; // end class } // End namespace } // End namespace #endif qutemol/vcg/vcg/complex/trimesh/update/color.h0000444000175000017500000002140210744433325020057 0ustar mbamba/**************************************************************************** * VCGLib o o * * Visual and Computer Graphics Library o o * * _ O _ * * Copyright(C) 2004 \/)\/ * * Visual Computing Lab /\/| * * ISTI - Italian National Research Council | * * \ * * All rights reserved. * * * * 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. * * * * 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 (http://www.gnu.org/licenses/gpl.txt) * * for more details. * * * ****************************************************************************/ /**************************************************************************** History $Log: color.h,v $ Revision 1.12 2008/01/19 17:43:49 ganovelli include added Revision 1.11 2007/05/04 16:34:31 ganovelli changes to comply "plus" types Revision 1.10 2006/05/21 07:00:01 cignoni Removed not working Equalized color (use funcs in stat.h) Revision 1.9 2006/03/01 10:29:55 ponchio HACK: MaxVal(0.0f) not defined in vcg/math/base.h as it should be, changing it to 1e36 (pretty close :P) Revision 1.8 2005/12/19 16:47:42 cignoni Better comment and a parameter more for UpdateColor::VertexBorderFlag Revision 1.7 2005/08/08 10:28:13 ganovelli added math:: namespace before min and max Revision 1.6 2004/08/25 15:15:26 ganovelli minor changes to comply gcc compiler (typename's and stuff) Revision 1.5 2004/07/15 00:13:39 cignoni Better doxigen documentation Revision 1.4 2004/06/24 07:56:54 cignoni now use std::numeric_limits instead of old max val() Revision 1.3 2004/03/12 15:22:19 cignoni Written some documentation and added to the trimes doxygen module Revision 1.2 2004/03/10 00:48:06 cignoni changed to the face::IsBorder() style Revision 1.1 2004/03/05 10:59:24 cignoni Changed name from plural to singular (normals->normal) ****************************************************************************/ #ifndef __VCG_TRI_UPDATE_COLOR #define __VCG_TRI_UPDATE_COLOR #include #include #include namespace vcg { namespace tri { /** \addtogroup trimesh */ /*@{*/ /// Generation of per-vertex and per-face colors according to various strategy. /// This class is used to compute per face or per vertex color with respect to for example Border (UpdateColor::VertexBorderFlag), Selection (UpdateColor::FaceSelected), Quality . template class UpdateColor { public: typedef UpdateMeshType MeshType; typedef typename UpdateMeshType::VertexType VertexType; typedef typename UpdateMeshType::VertexPointer VertexPointer; typedef typename UpdateMeshType::VertexIterator VertexIterator; typedef typename UpdateMeshType::FaceType FaceType; typedef typename UpdateMeshType::FacePointer FacePointer; typedef typename UpdateMeshType::FaceIterator FaceIterator; /** Color the vertexes of the mesh that are on the border It uses the information in the Vertex flags, and not any topology. So it just require that you have correctly computed the flags; vcg::tri::UpdateTopology::FaceFace(m.cm); vcg::tri::UpdateFlags::FaceBorderFromFF(m.cm); vcg::tri::UpdateFlags::VertexBorderFromFace (m.cm); vcg::tri::UpdateColor::VertexBorderFlag(m.cm); **/ static void VertexBorderFlag( UpdateMeshType &m, Color4b BorderColor=Color4b::Blue, Color4b InternalColor=Color4b::White) { typename UpdateMeshType::VertexIterator vi; for(vi=m.vert.begin();vi!=m.vert.end();++vi) if(!(*vi).IsD()) (*vi).C()=InternalColor; typename UpdateMeshType::FaceIterator fi; for(fi=m.face.begin();fi!=m.face.end();++fi) if(!(*fi).IsD()) for(int j=0;j<3;++j) if((*fi).IsB(j)){ (*fi).V(j)->C() = BorderColor; (*fi).V1(j)->C() = BorderColor; //(*fi).C() = BorderColor; } } static void FaceBF( UpdateMeshType &m, Color4b vn=Color4b::White, Color4b vb=Color4b::Blue, Color4b vc=Color4b::Red, Color4b vs=Color4b::LightBlue) { typename UpdateMeshType::FaceIterator fi; for(fi=m.face.begin();fi!=m.face.end();++fi) if(!(*fi).IsD()) (*fi).C() = vn; for(fi=m.face.begin();fi!=m.face.end();++fi) if(!(*fi).IsD()) { if((*fi).IsS()) (*fi).C() = vs; else { for(int j=0;j<3;++j) if(*fi.IsManifold(j)){ if((*fi).IsB(j)){ (*fi).C() = vb; (*fi).C() = vb; } } else { (*fi).C() = vc; (*fi).C() = vc; } } } } static int FaceSelected(UpdateMeshType &m, Color4b vs=Color4b::LightBlue) { int cnt=0; typename UpdateMeshType::FaceIterator fi; for(fi=m.face.begin();fi!=m.face.end();++fi) if(!(*fi).IsD()) if((*fi).IsS()) { (*fi).C() = vs; ++cnt; } else (*fi).C() = Color4b::White; return cnt; } static void FaceColorStrip(UpdateMeshType &m, std::vector &TStripF) { vcg::Color4b cc[7]={ vcg::Color4b::White , vcg::Color4b::Red , vcg::Color4b::Green , vcg::Color4b::Blue , vcg::Color4b::Cyan , vcg::Color4b::Yellow , vcg::Color4b::Magenta }; int cnt=0; typename std::vector::iterator fi; for(fi=TStripF.begin();fi!=TStripF.end();++fi) if(*fi) (**fi).C().ColorRamp(0,16,cnt); else cnt=(cnt+1)%16; // if(*fi) (**fi).C()=cc[cnt]; // else cnt=(cnt+1)%7; } static int VertexSelected(UpdateMeshType &m, Color4b vs=Color4b::LightBlue) { int cnt=0; typename UpdateMeshType::VertexIterator vi; for(vi=m.vert.begin();vi!=m.vert.end();++vi) if(!(*vi).IsD()) if((*vi).IsS()) {(*vi).C() = vs; ++cnt; } else (*vi).C() = Color4b::White; return cnt; } static void VertexConstant(UpdateMeshType &m, Color4b c=Color4b::White) { typename UpdateMeshType::VertexIterator vi; for(vi=m.vert.begin();vi!=m.vert.end();++vi) if(!(*vi).IsD()) (*vi).C()=c; } static void FaceConstant(UpdateMeshType &m, Color4b c=Color4b::White) { typename UpdateMeshType::FaceIterator fi; for(fi=m.face.begin();fi!=m.face.end();++fi) (*fi).C()=c; } static void VertexBorderManifoldFlag(UpdateMeshType &m, Color4b vn=Color4b::White, Color4b vb=Color4b::Blue, Color4b vc=Color4b::Red) { typename UpdateMeshType::VertexIterator vi; for(vi=m.vert.begin();vi!=m.vert.end();++vi) if(!(*vi).IsD()) (*vi).C()=vn; typename UpdateMeshType::FaceIterator fi; for(fi=m.face.begin();fi!=m.face.end();++fi) if(!(*fi).IsD()) for(int j=0;j<3;++j) if((*fi).IsManifold(j)){ if((*fi).IsB(j)){ (*fi).V(j)->C()=vb; (*fi).V1(j)->C()=vb; } } else { (*fi).V(j)->C()=vc; (*fi).V1(j)->C()=vc; } } static void FaceQuality(UpdateMeshType &m) { // step 1: find the range typename UpdateMeshType::FaceIterator fi; float minq=m.face[0].Q(), maxq=m.face[0].Q(); for(fi=m.face.begin();fi!=m.face.end();++fi) if(!(*fi).IsD()) if(!(*fi).IsD()) { minq=min(minq,(*fi).Q()); maxq=max(maxq,(*fi).Q()); } FaceQuality(m,minq,maxq); } static void FaceQuality(UpdateMeshType &m, float minq, float maxq) { typename UpdateMeshType::FaceIterator fi; for(fi=m.face.begin();fi!=m.face.end();++fi) if(!(*fi).IsD()) (*fi).C().ColorRamp(minq,maxq,(*fi).Q()); } static void VertexQuality(UpdateMeshType &m, float minq, float maxq) { typename UpdateMeshType::VertexIterator vi; for(vi=m.vert.begin();vi!=m.vert.end();++vi) if(!(*vi).IsD()) (*vi).C().ColorRamp(minq,maxq,(*vi).Q()); } static void VertexQuality(UpdateMeshType &m) { // step 1: find the range typename UpdateMeshType::VertexIterator vi; float minq=std::numeric_limits::max(), maxq=-std::numeric_limits::max(); for(vi=m.vert.begin();vi!=m.vert.end();++vi) if(!(*vi).IsD()) { minq=vcg::math::Min(minq,(*vi).Q()); maxq=vcg::math::Max(maxq,(*vi).Q()); } VertexQuality(m,minq,maxq); } }; /*@}*/ }// end namespace }// end namespace #endif qutemol/vcg/vcg/complex/trimesh/update/edges.h0000444000175000017500000001060010616660227020027 0ustar mbamba/**************************************************************************** * VCGLib o o * * Visual and Computer Graphics Library o o * * _ O _ * * Copyright(C) 2004 \/)\/ * * Visual Computing Lab /\/| * * ISTI - Italian National Research Council | * * \ * * All rights reserved. * * * * 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. * * * * 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 (http://www.gnu.org/licenses/gpl.txt) * * for more details. * * * ****************************************************************************/ /**************************************************************************** History $Log: edges.h,v $ Revision 1.5 2007/05/04 16:34:31 ganovelli changes to comply "plus" types Revision 1.4 2006/05/16 21:36:54 cignoni Removed unused box function and rewrote initial comment. Revision 1.3 2006/05/15 13:12:36 pietroni Updating of edge values id divided into 2 functions ( the first one update only a face...) added also resetting of edges flags.. (see first line of Set function) Revision 1.2 2004/05/12 18:52:35 ganovelli removed call to ComputeRT and put its body here Revision 1.1 2004/05/12 10:39:45 ganovelli created ****************************************************************************/ #ifndef __VCG_TRI_UPDATE_EDGES #define __VCG_TRI_UPDATE_EDGES #include namespace vcg { namespace tri { /** \addtogroup trimesh */ /*@{*/ /// This class is used to compute or update the precomputed data used to efficiently compute point-face distances.. template class UpdateEdges { public: typedef ComputeMeshType MeshType; typedef typename MeshType::VertexType VertexType; typedef typename MeshType::VertexPointer VertexPointer; typedef typename MeshType::VertexIterator VertexIterator; typedef typename MeshType::FaceType FaceType; typedef typename MeshType::FacePointer FacePointer; typedef typename MeshType::FaceIterator FaceIterator; typedef typename MeshType::FaceType::ScalarType ScalarType; static void Set(FaceType &f) { f.Flags() = f.Flags() & (~(FaceType::NORMX|FaceType::NORMY|FaceType::NORMZ)); // Primo calcolo degli edges f.Edge(0) = f.V(1)->P(); f.Edge(0) -= f.V(0)->P(); f.Edge(1) = f.V(2)->P(); f.Edge(1) -= f.V(1)->P(); f.Edge(2) = f.V(0)->P(); f.Edge(2) -= f.V(2)->P(); // Calcolo di plane f.Plane().SetDirection(f.Edge(0)^f.Edge(1)); f.Plane().SetOffset(f.Plane().Direction() * f.V(0)->P()); f.Plane().Normalize(); // Calcolo migliore proiezione ScalarType nx = math::Abs(f.Plane().Direction()[0]); ScalarType ny = math::Abs(f.Plane().Direction()[1]); ScalarType nz = math::Abs(f.Plane().Direction()[2]); ScalarType d; if(nx>ny && nx>nz) { f.Flags() |= FaceType::NORMX; d = 1/f.Plane().Direction()[0]; } else if(ny>nz) { f.Flags() |= FaceType::NORMY; d = 1/f.Plane().Direction()[1]; } else { f.Flags() |= FaceType::NORMZ; d = 1/f.Plane().Direction()[2]; } // Scalatura spigoli f.Edge(0)*=d; f.Edge(1)*=d; f.Edge(2)*=d; } static void Set(ComputeMeshType &m) { FaceIterator f; for(f = m.face.begin(); f!=m.face.end(); ++f) if(!(*f).IsD()) Set(*f); } }; // end class } // End namespace } // End namespace #endif qutemol/vcg/vcg/complex/trimesh/update/texture.h0000444000175000017500000000567011006071343020440 0ustar mbamba/**************************************************************************** * VCGLib o o * * Visual and Computer Graphics Library o o * * _ O _ * * Copyright(C) 2004 \/)\/ * * Visual Computing Lab /\/| * * ISTI - Italian National Research Council | * * \ * * All rights reserved. * * * * 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. * * * * 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 (http://www.gnu.org/licenses/gpl.txt) * * for more details. * * * ****************************************************************************/ /**************************************************************************** History $Log: position.h,v $ ****************************************************************************/ #ifndef __VCG_TRI_UPDATE_TEXTURE #define __VCG_TRI_UPDATE_TEXTURE #include namespace vcg { namespace tri { /** \addtogroup trimesh */ /*@{*/ /// This class is used to update vertex position according to a transformation matrix. template class UpdateTexture { public: typedef ComputeMeshType MeshType; typedef typename MeshType::ScalarType ScalarType; typedef typename MeshType::VertexType VertexType; typedef typename MeshType::VertexPointer VertexPointer; typedef typename MeshType::VertexIterator VertexIterator; typedef typename MeshType::FaceType FaceType; typedef typename MeshType::FacePointer FacePointer; typedef typename MeshType::FaceIterator FaceIterator; static void WedgeTexFromPlanar(ComputeMeshType &m, Plane3 &pl) { FaceIterator fi; for(fi=m.face.begin();vi!=m.face.end();++vi) if(!(*fi).IsD()) { } } static void WedgeTexFromCamera(ComputeMeshType &m, Plane3 &pl) { } }; // end class } // End namespace } // End namespace #endif qutemol/vcg/vcg/complex/trimesh/update/selection.h0000444000175000017500000001622111013206034020712 0ustar mbamba/**************************************************************************** * VCGLib o o * * Visual and Computer Graphics Library o o * * _ O _ * * Copyright(C) 2004 \/)\/ * * Visual Computing Lab /\/| * * ISTI - Italian National Research Council | * * \ * * All rights reserved. * * * * 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. * * * * 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 (http://www.gnu.org/licenses/gpl.txt) * * for more details. * * * ****************************************************************************/ /**************************************************************************** History $Log: selection.h,v $ Revision 1.4 2008/05/16 04:22:52 cignoni added VertexFromQualityRange selection Revision 1.3 2007/04/20 10:11:51 cignoni Corrected bug in selectionVertexFromFaceStrict Revision 1.2 2007/02/01 06:37:05 cignoni Added FaceFromBorder Revision 1.1 2006/10/16 08:50:58 cignoni First Working Version ****************************************************************************/ #ifndef __VCG_TRI_UPDATE_SELECTION #define __VCG_TRI_UPDATE_SELECTION namespace vcg { namespace tri { /** \addtogroup trimesh */ /*@{*/ /// Management, updating and computation of per-vertex and per-face normals. /// This class is used to compute or update the normals that can be stored in the vertex or face component of a mesh. template class UpdateSelection { public: typedef ComputeMeshType MeshType; typedef typename MeshType::VertexType VertexType; typedef typename MeshType::VertexPointer VertexPointer; typedef typename MeshType::VertexIterator VertexIterator; typedef typename MeshType::FaceType FaceType; typedef typename MeshType::FacePointer FacePointer; typedef typename MeshType::FaceIterator FaceIterator; /// static size_t AllVertex(MeshType &m) { VertexIterator vi; for(vi = m.vert.begin(); vi != m.vert.end(); ++vi) if( !(*vi).IsD() ) (*vi).SetS(); return m.vn; } static size_t AllFace(MeshType &m) { FaceIterator fi; for(fi = m.face.begin(); fi != m.face.end(); ++fi) if( !(*fi).IsD() ) (*fi).SetS(); return m.fn; } static size_t ClearVertex(MeshType &m) { VertexIterator vi; for(vi = m.vert.begin(); vi != m.vert.end(); ++vi) if( !(*vi).IsD() ) (*vi).ClearS(); return 0; } static size_t ClearFace(MeshType &m) { FaceIterator fi; for(fi = m.face.begin(); fi != m.face.end(); ++fi) if( !(*fi).IsD() ) (*fi).ClearS(); return 0; } static void Clear(MeshType &m) { ClearVertex(m); ClearFace(m); } static size_t CountFace(MeshType &m) { size_t selCnt=0; FaceIterator fi; for(fi=m.face.begin();fi!=m.face.end();++fi) if(!(*fi).IsD() && (*fi).IsS()) ++selCnt; return selCnt; } static size_t CountVertex(MeshType &m) { size_t selCnt=0; VertexIterator vi; for(vi=m.vert.begin();vi!=m.vert.end();++vi) if(!(*vi).IsD() && (*vi).IsS()) ++selCnt; return selCnt; } static size_t InvertFace(MeshType &m) { size_t selCnt=0; FaceIterator fi; for(fi=m.face.begin();fi!=m.face.end();++fi) if(!(*fi).IsD()) { if((*fi).IsS()) (*fi).ClearS(); else { (*fi).SetS(); ++selCnt; } } return selCnt; } static size_t InvertVertex(MeshType &m) { size_t selCnt=0; VertexIterator vi; for(vi=m.vert.begin();vi!=m.vert.end();++vi) if(!(*vi).IsD()) { if((*vi).IsS()) (*vi).ClearS(); else { (*vi).SetS(); ++selCnt; } } return selCnt; } // Select all the vertices that are touched by at least a single selected faces static size_t VertexFromFaceLoose(MeshType &m) { size_t selCnt=0; ClearVertex(m); FaceIterator fi; for(fi = m.face.begin(); fi != m.face.end(); ++fi) if( !(*fi).IsD() && (*fi).IsS()) { if( !(*fi).V(0)->IsS()) { (*fi).V(0)->SetS(); ++selCnt; } if( !(*fi).V(1)->IsS()) { (*fi).V(1)->SetS(); ++selCnt; } if( !(*fi).V(2)->IsS()) { (*fi).V(2)->SetS(); ++selCnt; } } return selCnt; } // Select ONLY the vertices that are touched ONLY by selected faces // or in other words all the vertices having all the faces incident on them selected. // Ambiguity in the def: isolated vertices should be selected? NO. // static size_t VertexFromFaceStrict(MeshType &m) { size_t selCnt=0; VertexFromFaceLoose(m); FaceIterator fi; for(fi = m.face.begin(); fi != m.face.end(); ++fi) if( !(*fi).IsD() && !(*fi).IsS()) { (*fi).V(0)->ClearS(); (*fi).V(1)->ClearS(); (*fi).V(2)->ClearS(); } return CountVertex(m); } // Select ONLY the faces with ALL the vertices selected static size_t FaceFromVertexStrict(MeshType &m) { size_t selCnt=0; ClearFace(m); FaceIterator fi; for(fi = m.face.begin(); fi != m.face.end(); ++fi) if( !(*fi).IsD()) { if((*fi).V(0)->IsS() && (*fi).V(1)->IsS() && (*fi).V(2)->IsS()) { (*fi).SetS(); ++selCnt; } } return selCnt; } static size_t FaceFromVertexLoose(MeshType &m) { size_t selCnt=0; ClearFace(m); FaceIterator fi; for(fi = m.face.begin(); fi != m.face.end(); ++fi) if( !(*fi).IsD() && !(*fi).IsS()) { if((*fi).V(0)->IsS() || (*fi).V(1)->IsS() || (*fi).V(2)->IsS()) { (*fi).SetS(); ++selCnt; } } return selCnt; } static size_t FaceFromBorder(MeshType &m) { size_t selCnt=0; ClearFace(m); FaceIterator fi; for(fi = m.face.begin(); fi != m.face.end(); ++fi) if( !(*fi).IsD() ) { if((*fi).IsB(0) || (*fi).IsB(1) || (*fi).IsB(2)) { (*fi).SetS(); ++selCnt; } } return selCnt; } // Select ONLY the vertices whose quality is in the specified closed interval. // static size_t VertexFromQualityRange(MeshType &m,float minq, float maxq) { size_t selCnt=0; ClearVertex(m); VertexIterator vi; assert(HasPerVertexQuality(m)); for(vi=m.vert.begin();vi!=m.vert.end();++vi) if(!(*vi).IsD()) { if( (*vi).Q()>=minq && (*vi).Q()<=maxq ) { (*vi).SetS(); ++selCnt; } } return selCnt; } }; // end class } // End namespace } // End namespace #endif qutemol/vcg/vcg/complex/trimesh/update/flag.h0000444000175000017500000002601710707134713017657 0ustar mbamba/**************************************************************************** * VCGLib o o * * Visual and Computer Graphics Library o o * * _ O _ * * Copyright(C) 2004 \/)\/ * * Visual Computing Lab /\/| * * ISTI - Italian National Research Council | * * \ * * All rights reserved. * * * * 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. * * * * 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 (http://www.gnu.org/licenses/gpl.txt) * * for more details. * * * ****************************************************************************/ /**************************************************************************** History $Log: flag.h,v $ Revision 1.21 2007/10/22 14:55:07 eraser85 bug in FaceBorderFromNone corrected (same as in Topology.h) Ganovelli Revision 1.20 2007/05/31 15:24:50 ponchio FIxed off-by-one error on FaceBorderFromNone. Revision 1.19 2007/05/22 15:19:42 cignoni Added VertexClear Revision 1.18 2007/01/30 18:49:23 tarini aggiunta la VertexBorderFromNone (flag bordo per vertici senza richiedere nulla) Revision 1.17 2006/08/31 13:11:12 marfr960 corrected bounds of a vector scan Revision 1.16 2006/08/30 12:59:49 marfr960 Added missing std:: to swap Revision 1.15 2006/08/30 06:50:07 cignoni Reverted to version 1.13. Version 1.14 was done on outdated version. Revision 1.13 2006/06/18 20:49:30 cignoni Added missing IsD tests Revision 1.12 2006/05/03 21:23:25 cignoni Corrected IsDeleted -> isD Revision 1.11 2005/12/02 00:09:12 cignoni Added assert(HasFlags) everywhere.. Revision 1.10 2005/07/06 08:16:34 ganovelli set VertexBorderFromFace as static Revision 1.9 2005/06/10 15:07:23 cignoni Completed FaceBorderFromNone (and added a missing helper class) Revision 1.8 2005/04/01 13:04:55 fiorin Minor changes Revision 1.7 2004/09/14 19:49:43 ganovelli first compilation version Revision 1.6 2004/07/15 00:13:39 cignoni Better doxigen documentation Revision 1.5 2004/07/06 06:27:02 cignoni Added FaceBorderFromVF Revision 1.4 2004/05/13 15:58:55 ganovelli function Clear added Revision 1.3 2004/03/12 15:22:19 cignoni Written some documentation and added to the trimes doxygen module Revision 1.2 2004/03/10 00:46:10 cignoni changed to the face::IsBorder() style Revision 1.1 2004/03/05 10:59:24 cignoni Changed name from plural to singular (normals->normal) Revision 1.1 2004/03/04 00:37:56 cignoni First working version! ****************************************************************************/ #ifndef __VCG_TRI_UPDATE_FLAGS #define __VCG_TRI_UPDATE_FLAGS #include namespace vcg { namespace tri { /** \addtogroup trimesh */ /*@{*/ /// Management, updating and computation of per-vertex and per-face flags (like border flags). /// This class is used to compute or update some of the flags that can be stored in the mesh components. For now just Border flags (e.g. the flag that tells if a given edge of a face belong to a border of the mesh or not). template class UpdateFlags { public: typedef UpdateMeshType MeshType; typedef vcg::face::Pos PosType; typedef typename MeshType::VertexType VertexType; typedef typename MeshType::VertexPointer VertexPointer; typedef typename MeshType::VertexIterator VertexIterator; typedef typename MeshType::FaceType FaceType; typedef typename MeshType::FacePointer FacePointer; typedef typename MeshType::FaceIterator FaceIterator; /** Reset all the mesh flags (both vertexes and faces) setting everithing to zero (the default value for flags) **/ static void Clear(MeshType &m) { assert(HasPerFaceFlags(m)); FaceIterator fi; VertexIterator vi; for(fi=m.face.begin(); fi!=m.face.end(); ++fi) (*fi).Flags() = 0; for(vi=m.vert.begin(); vi!=m.vert.end(); ++vi) (*vi).Flags() = 0; } static void VertexClear(MeshType &m, unsigned int FlagMask = 0xffffffff) { VertexIterator vi; int andMask = ~FlagMask; for(vi=m.vert.begin(); vi!=m.vert.end(); ++vi) if(!(*vi).IsD()) (*vi).Flags() &= andMask ; } static void VertexClearV(MeshType &m) { VertexClear(m,VertexType::VISITED);} static void VertexClearB(MeshType &m) { VertexClear(m,VertexType::BORDER);} /** Compute the border flags for the faces using the Face-Face Topology. Obviously it assumes that the topology has been correctly computed (see: UpdateTopology::FaceFace ) **/ static void FaceBorderFromFF(MeshType &m) { assert(HasPerFaceFlags(m)); // const int BORDERFLAG[3]={FaceType::BORDER0,FaceType::BORDER1,FaceType::BORDER2}; FaceIterator fi; for(fi=m.face.begin();fi!=m.face.end();++fi)if(!(*fi).IsD()) for(int j=0;j<3;++j) { //if(!(*fi).IsManifold(j)) (*fi).SetCF(j); //else if(face::IsBorder(*fi,j)) (*fi).SetB(j); else (*fi).ClearB(j); } } static void FaceBorderFromVF(MeshType &m) { assert(HasPerFaceFlags(m)); VertexIterator vi; assert(m.HasVFTopology()); int visitedBit=VertexType::NewBitFlag(); // Calcolo dei bordi // per ogni vertice vi si cercano i vertici adiacenti che sono toccati da una faccia sola // (o meglio da un numero dispari di facce) const int BORDERFLAG[3]={FaceType::BORDER0, FaceType::BORDER1, FaceType::BORDER2}; for(vi=m.vert.begin();vi!=m.vert.end();++vi) if(!(*vi).IsD()) { for(face::VFIterator vfi(&*vi) ; !vfi.End(); ++vfi ) { vfi.f->V1(vfi.z)->ClearUserBit(visitedBit); vfi.f->V2(vfi.z)->ClearUserBit(visitedBit); } for(face::VFIterator vfi(&*vi) ; !vfi.End(); ++vfi ) { if(vfi.f->V1(vfi.z)->IsUserBit(visitedBit)) vfi.f->V1(vfi.z)->ClearUserBit(visitedBit); else vfi.f->V1(vfi.z)->SetUserBit(visitedBit); if(vfi.f->V2(vfi.z)->IsUserBit(visitedBit)) vfi.f->V2(vfi.z)->ClearUserBit(visitedBit); else vfi.f->V2(vfi.z)->SetUserBit(visitedBit); } for(face::VFIterator vfi(&*vi) ; !vfi.End(); ++vfi ) { if(vfi.f->V(vfi.z)< vfi.f->V1(vfi.z) && vfi.f->V1(vfi.z)->IsUserBit(visitedBit)) vfi.f->Flags() |= BORDERFLAG[vfi.z]; if(vfi.f->V(vfi.z)< vfi.f->V2(vfi.z) && vfi.f->V2(vfi.z)->IsUserBit(visitedBit)) vfi.f->Flags() |= BORDERFLAG[(vfi.z+2)%3]; } } VertexType::DeleteBitFlag(VertexType::LastBitFlag()); } class EdgeSorter { public: VertexPointer v[2]; // Puntatore ai due vertici (Ordinati) FacePointer f; // Puntatore alla faccia generatrice int z; // Indice dell'edge nella faccia EdgeSorter() {} // Nothing to do void Set( const FacePointer pf, const int nz ) { assert(pf!=0); assert(nz>=0); assert(nz<3); v[0] = pf->V(nz); v[1] = pf->V((nz+1)%3); assert(v[0] != v[1]); if( v[0] > v[1] ) std::swap(v[0],v[1]); f = pf; z = nz; } inline bool operator < ( const EdgeSorter & pe ) const { if( v[0]pe.v[0] ) return false; else return v[1] < pe.v[1]; } inline bool operator == ( const EdgeSorter & pe ) const { return v[0]==pe.v[0] && v[1]==pe.v[1]; } inline bool operator != ( const EdgeSorter & pe ) const { return v[0]!=pe.v[0] || v[1]!=pe.v[1]; } }; // versione minimale che non calcola i complex flag. static void VertexBorderFromNone(MeshType &m) { assert(HasPerVertexFlags(m)); std::vector e; typename UpdateMeshType::FaceIterator pf; typename std::vector::iterator p; if( m.fn == 0 ) return; e.resize(m.fn*3); // Alloco il vettore ausiliario p = e.begin(); for(pf=m.face.begin();pf!=m.face.end();++pf) // Lo riempio con i dati delle facce if( ! (*pf).IsD() ) for(int j=0;j<3;++j) { (*p).Set(&(*pf),j); (*pf).ClearB(j); ++p; } assert(p==e.end()); sort(e.begin(), e.end()); // Lo ordino per vertici typename std::vector::iterator pe,ps; for(ps = e.begin(), pe = e.begin(); pe < e.end(); ++pe) // Scansione vettore ausiliario { if( pe==e.end() || *pe != *ps ) // Trovo blocco di edge uguali { if(pe-ps==1) { ps->v[0]->SetB(); ps->v[1]->SetB(); } else if(pe-ps!=2) { // not twomanyfold! for(;ps!=pe;++ps) { ps->v[0]->SetB(); // Si settano border anche i complex. ps->v[1]->SetB(); } } ps = pe; } } } // versione minimale che non calcola i complex flag. static void FaceBorderFromNone(MeshType &m) { assert(HasPerFaceFlags(m)); std::vector e; typename UpdateMeshType::FaceIterator pf; typename std::vector::iterator p; for(VertexIterator v=m.vert.begin();v!=m.vert.end();++v) (*v).ClearB(); if( m.fn == 0 ) return; e.resize(m.fn*3); // Alloco il vettore ausiliario p = e.begin(); for(pf=m.face.begin();pf!=m.face.end();++pf) // Lo riempio con i dati delle facce if( ! (*pf).IsD() ) for(int j=0;j<3;++j) { (*p).Set(&(*pf),j); (*pf).ClearB(j); ++p; } assert(p==e.end()); sort(e.begin(), e.end()); // Lo ordino per vertici typename std::vector::iterator pe,ps; ps = e.begin();pe=e.begin(); do { if( pe==e.end() || *pe != *ps ) // Trovo blocco di edge uguali { if(pe-ps==1) { ps->f->SetB(ps->z); } else if(pe-ps!=2) { // Caso complex!! for(;ps!=pe;++ps) ps->f->SetB(ps->z); // Si settano border anche i complex. } ps = pe; } if(pe==e.end()) break; ++pe; } while(true); // TRACE("found %i border (%i complex) on %i edges\n",nborder,ncomplex,ne); } /// Compute the PerVertex Border flag deriving it from the faces static void VertexBorderFromFace(MeshType &m) { assert(HasPerFaceFlags(m)); typename MeshType::VertexIterator v; typename MeshType::FaceIterator f; for(v=m.vert.begin();v!=m.vert.end();++v) (*v).ClearB(); for(f=m.face.begin();f!=m.face.end();++f) if(!(*f).IsD()) { for(int z=0;z<3;++z) if( (*f).IsB(z) ) { (*f).V0(z)->SetB(); (*f).V1(z)->SetB(); } } } }; // end class /*@}*/ } // End namespace tri } // End namespace vcg #endif qutemol/vcg/vcg/complex/trimesh/update/position.h0000444000175000017500000000634210716561147020616 0ustar mbamba/**************************************************************************** * VCGLib o o * * Visual and Computer Graphics Library o o * * _ O _ * * Copyright(C) 2004 \/)\/ * * Visual Computing Lab /\/| * * ISTI - Italian National Research Council | * * \ * * All rights reserved. * * * * 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. * * * * 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 (http://www.gnu.org/licenses/gpl.txt) * * for more details. * * * ****************************************************************************/ /**************************************************************************** History $Log: position.h,v $ Revision 1.2 2007/11/14 11:56:23 ganovelli added updating of vertex and face normals Revision 1.1 2005/07/06 08:02:27 cignoni Initial commit ****************************************************************************/ #ifndef __VCG_TRI_UPDATE_POSITION #define __VCG_TRI_UPDATE_POSITION #include "normal.h" namespace vcg { namespace tri { /** \addtogroup trimesh */ /*@{*/ /// This class is used to update vertex position according to a transformation matrix. template class UpdatePosition { public: typedef ComputeMeshType MeshType; typedef typename MeshType::ScalarType ScalarType; typedef typename MeshType::VertexType VertexType; typedef typename MeshType::VertexPointer VertexPointer; typedef typename MeshType::VertexIterator VertexIterator; typedef typename MeshType::FaceType FaceType; typedef typename MeshType::FacePointer FacePointer; typedef typename MeshType::FaceIterator FaceIterator; /// Multiply static void Matrix(ComputeMeshType &m, const Matrix44 &M, bool update_also_normals = true) { VertexIterator vi; for(vi=m.vert.begin();vi!=m.vert.end();++vi) if(!(*vi).IsD()) (*vi).P()=M*(*vi).cP(); if(update_also_normals){ if(m.HasPerVertexNormal()){ UpdateNormals::PerVertexMatrix(m,M); } if(m.HasPerFaceNormal()){ UpdateNormals::PerFaceMatrix(m,M); } } } }; // end class } // End namespace } // End namespace #endif qutemol/vcg/vcg/complex/trimesh/append.h0000444000175000017500000001601510777355601016740 0ustar mbamba/**************************************************************************** * VCGLib o o * * Visual and Computer Graphics Library o o * * _ O _ * * Copyright(C) 2004 \/)\/ * * Visual Computing Lab /\/| * * ISTI - Italian National Research Council | * * \ * * All rights reserved. * * * * 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. * * * * 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 (http://www.gnu.org/licenses/gpl.txt) * * for more details. * * * ****************************************************************************/ /**************************************************************************** History $Log: append.h,v $ Revision 1.8 2008/04/10 09:18:57 cignoni moved Index function from append to the allocate Revision 1.7 2008/01/28 08:39:56 cignoni added management of normals Revision 1.6 2007/03/12 15:38:03 tarini Texture coord name change! "TCoord" and "Texture" are BAD. "TexCoord" is GOOD. Revision 1.5 2006/05/25 04:40:57 cignoni Updated HasPerFaceColor/Quality to the new style with mesh param. Revision 1.4 2006/04/11 13:51:21 zifnab1974 commented out one function which does not compile on linux with gcc 3.4.5 Revision 1.3 2006/01/30 09:00:40 cignoni Corrected use of HasPerWedgeTexture Revision 1.2 2006/01/22 17:08:50 cignoni Bug due to wrong compuation of size of auxiliary vector (vn instead of vert.size() ) Revision 1.1 2006/01/11 15:45:21 cignoni Initial Release ****************************************************************************/ #ifndef __VCGLIB_APPEND #define __VCGLIB_APPEND #include #include namespace vcg { namespace tri { template class Append { public: typedef typename MeshLeft::ScalarType ScalarLeft; typedef typename MeshLeft::CoordType CoordLeft; typedef typename MeshLeft::VertexType VertexLeft; typedef typename MeshLeft::FaceType FaceLeft; typedef typename MeshLeft::VertexPointer VertexPointerLeft; typedef typename MeshLeft::VertexIterator VertexIteratorLeft; typedef typename MeshLeft::FaceIterator FaceIteratorLeft; typedef typename MeshRight::ScalarType ScalarRight; typedef typename MeshRight::CoordType CoordRight; typedef typename MeshRight::VertexType VertexRight; typedef typename MeshRight::FaceType FaceRight; typedef typename MeshRight::VertexPointer VertexPointerRight; typedef typename MeshRight::VertexIterator VertexIteratorRight; typedef typename MeshRight::FaceIterator FaceIteratorRight; typedef typename MeshRight::FacePointer FacePointerRight; static void ImportVertex(VertexLeft &vl, VertexRight &vr) { vl.P().Import(vr.P()); if(vl.HasNormal() && vr.HasNormal()) vl.N()=vr.N(); if(vl.HasColor() && vr.HasColor()) vl.C()=vr.C(); if(vl.HasQuality() && vr.HasQuality()) vl.Q()=vr.Q(); if(vl.HasTexCoord() && vr.HasTexCoord()) vl.T()=vr.T(); } static void ImportFace(MeshLeft &ml, MeshRight &mr, FaceLeft &fl, FaceRight &fr, std::vector &remap) { fl.V(0)=&ml.vert[remap[ Index(mr,fr.V(0))]]; fl.V(1)=&ml.vert[remap[ Index(mr,fr.V(1))]]; fl.V(2)=&ml.vert[remap[ Index(mr,fr.V(2))]]; if(HasPerFaceNormal(mr) && HasPerFaceNormal(ml)) fl.N()=fr.N(); if(HasPerFaceColor(mr) && HasPerFaceColor(ml)) fl.C()=fr.C(); if(HasPerFaceQuality(mr) && HasPerFaceQuality(ml)) fl.Q()=fr.Q(); if(HasPerWedgeTexCoord(mr) && HasPerWedgeTexCoord(ml)) { fl.WT(0)=fr.WT(0); fl.WT(1)=fr.WT(1); fl.WT(2)=fr.WT(2); }; } static void Mesh(MeshLeft& ml, MeshRight& mr, const bool selected = false) { // remap[i] keep where the position of where the i-th vertex of meshright has landed in meshleft std::vector remap(mr.vert.size(),-1); // first loop to find the referenced vertices and copy them preparing the remap vector FaceIteratorRight fi; int FaceToAdd=0; for(fi=mr.face.begin();fi!=mr.face.end();++fi) if((!(*fi).IsD()) && (!selected || (*fi).IsS() )) { ++FaceToAdd; for(int i=0;i<3;++i) { int vind=Index(mr, *(*fi).V(i)); if(remap[vind]==-1) { VertexIteratorLeft vp; vp=Allocator::AddVertices(ml,1); ImportVertex((*vp),*(*fi).V(i)); remap[vind]=Index(ml,*vp); } } } // second loop copy the faces updating the vertex references FaceIteratorLeft fp=Allocator::AddFaces(ml,FaceToAdd); for(fi=mr.face.begin();fi!=mr.face.end();++fi) if(!(*fi).IsD() && (!selected || (*fi).IsS() )) { ImportFace(ml,mr,(*fp),(*fi),remap); ++fp; } } // static void Subset(MeshLeft& ml, std::vector & vfpr) // { // // remap[i] keep where the position of where the i-th vertex of meshright has landed in meshleft // std::vector remap(mr.vert.size(),-1); // // first loop to find the referenced vertices and copy them preparing the remap vector // typename std::vector::iterator fi; // int FaceToAdd=0; // for(fi=vfpr.begin();fi!=vfpr.end();++fi) // if(!(*fi)->IsD()) // { // FaceToAdd++; // for(int i=0;i<3;++i) // { // int vind=Index(mr, *(**fi).V(i)); // if(remap[vind]==-1) // { // VertexIteratorLeft vp; // vp=Allocator::AddVertices(ml,1); // ImportVertex((*vp),*(**fi).V(i)); // remap[vind]=Index(ml,*vp); // } // } // } // // second loop copy the faces updating the vertex references // FaceIteratorLeft fp=Allocator::AddFaces(ml,FaceToAdd); // for(fi=vfpr.begin();fi!=vfpr.end();++fi) // if(!(*fi).IsD()) // { // ImportFace(ml,mr,(*fp),(*fi),remap); // ++fp; // } // } static void Selected(MeshLeft& ml, MeshRight& mr) { Mesh(mr,mr,true); } }; // end of class Append } // End Namespace TriMesh } // End Namespace vcg #endif qutemol/vcg/vcg/complex/trimesh/geodesic.h0000444000175000017500000002704610742213772017253 0ustar mbamba/**************************************************************************** * VCGLib o o * * Visual and Computer Graphics Library o o * * _ O _ * * Copyright(C) 2004 \/)\/ * * Visual Computing Lab /\/| * * ISTI - Italian National Research Council | * * \ * * All rights reserved. * * * * 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. * * * * 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 (http://www.gnu.org/licenses/gpl.txt) * * for more details. * * * ****************************************************************************/ /*#************************************************************************** History $Log: geodesic.h,v $ Revision 1.7 2008/01/12 19:41:46 ganovelli more appropriate function names, licence updated, comment added Revision 1.6 2008/01/12 19:07:05 ganovelli Recompiled from previous out of date version. Still to revise but working Revision 1.5 2005/12/13 17:17:19 ganovelli first importing from old version. NOT optimized! It works with VertexFace Adjacency even over non manifolds *#**************************************************************************/ #include #include #include #include #include #include #include #include /* class for computing approximated geodesic distances on a mesh. basic example: farthest vertex from a specified one MyMesh m; MyMesh::VertexPointer seed,far; MyMesh::ScalarType dist; vcg::Geo g; g.FarthestVertex(m,seed,far,d); */ namespace vcg{ template class Geo{ public: typedef typename MeshType::VertexPointer VertexPointer; typedef typename MeshType::ScalarType ScalarType; /* Auxiliary class for keeping the heap of vertices to visit and their estimated distance */ struct VertDist{ VertDist(){} VertDist(VertexPointer _v, ScalarType _d):v(_v),d(_d){} VertexPointer v; ScalarType d; }; /* Temporary data to associate to all the vertices: estimated distance and boolean flag */ template struct TempData{ TempData(){} TempData(const ScalarType & d_){d=d_;visited=false;} ScalarType d; bool visited; }; typedef SimpleTempData, TempData > TempDataType; TempDataType * TD; struct pred: public std::binary_function{ pred(){}; bool operator()(const VertDist& v0, const VertDist& v1) const {return (v0.d > v1.d);} }; /* starting from the seeds, it assign a distance value to each vertex. The distance of a vertex is its approximated geodesic distance to the closest seeds. This is function is not meant to be called (although is not prevented). Instead, it is invoked by wrapping function. */ typename MeshType::VertexPointer Visit( MeshType & m, std::vector & _frontier, ScalarType & max_distance, bool fartestOnBorder = false ) { bool isLeaf,toQueue; std::vector frontier; MeshType::VertexIterator ii; std::list children; typename MeshType::VertexPointer curr,farthest,pw1; std::list::iterator is; std::deque leaves; std::vector > expansion; std::vector ::iterator ifr; face::VFIterator x;int k; typename MeshType::VertexPointer pw; //Requirements assert(m.HasVFTopology()); assert(!_frontier.empty()); TD = new TempDataType(m.vert); TD->Start(TempData(-1.0)); for(ifr = _frontier.begin(); ifr != _frontier.end(); ++ifr){ (*TD)[(*ifr).v].visited= true; (*TD)[(*ifr).v].d = 0.0; (*ifr).d = 0.0; } for(ifr = _frontier.begin(); ifr != _frontier.end(); ++ifr) { // determina la distanza dei vertici della fan for( x.f = (*ifr).v->VFp(), x.z = (*ifr).v->VFi(); x.f!=0; ++x ) for(k=0;k<2;++k) { if(k==0) pw = x.f->V1(x.z); else pw = x.f->V2(x.z); if((*TD)[pw].d ==-1){ (*TD)[pw].d = Distance(pw->cP(),(*ifr).v->cP()); frontier.push_back(VertDist(pw,(*TD)[pw].d)); } } } // initialize Heap make_heap(frontier.begin(),frontier.end(),pred()); ScalarType curr_d,d_curr = 0.0; max_distance=0.0; std::vector:: iterator iv; while(!frontier.empty()) { //printf("size: %d\n", frontier.size()); expansion.clear(); pop_heap(frontier.begin(),frontier.end(),pred()); curr = (frontier.back()).v; frontier.pop_back(); d_curr = (*TD)[curr].d; (*TD)[curr].visited = true; isLeaf = (!fartestOnBorder || curr->IsB()); face::VFIterator x;int k; for( x.f = curr->VFp(), x.z = curr->VFi(); x.f!=0; ++x ) for(k=0;k<2;++k) { if(k==0) { pw = x.f->V1(x.z); pw1=x.f->V2(x.z); } else { pw = x.f->V2(x.z); pw1=x.f->V1(x.z); } const ScalarType & d_pw1 = (*TD)[pw1].d; if((! (*TD)[pw1].visited ) || d_curr == 0.0) { if( (*TD)[pw].d == -1){ curr_d = (*TD)[curr].d + (pw->P()-curr->P()).Norm(); expansion.push_back(std::pair(pw,curr_d)); } continue; } assert( (*TD)[pw1].d != -1); assert( (curr!=pw) && (pw!=pw1) && (pw1 != curr)); assert(d_pw1!=-1.0); //************** calcolo della distanza di pw in base alle distanze note di pw1 e curr //************** sapendo che (curr,pw,pw1) e'una faccia della mesh //************** (vedi figura in file distance.gif) Point3 w_c = pw->cP()- curr->cP(); Point3 w_w1 = pw->cP()- pw1->cP(); Point3 w1_c = pw1->cP()- curr->cP(); ScalarType ew_c = (w_c).Norm(); ScalarType ew_w1 = (w_w1).Norm(); ScalarType ec_w1 = (w1_c).Norm(); ScalarType alpha,alpha_, beta,beta_,theta,h,delta,s,a,b; alpha = acos((w_c*w1_c)/(ew_c*ec_w1)); s = (d_curr + d_pw1+ec_w1)/2; a = s/ec_w1; b = a*s; alpha_ = 2*acos ( math::Min(1.0,sqrt( (b- a* d_pw1)/d_curr))); if ( alpha+alpha_ > M_PI){ curr_d = d_curr + ew_c; }else { beta_ = 2*acos ( math::Min(1.0,sqrt( (b- a* d_curr)/d_pw1))); beta = acos((w_w1)*(-w1_c)/(ew_w1*ec_w1)); if ( beta+beta_ > M_PI) curr_d = d_pw1 + ew_w1; else { theta = ScalarType(M_PI)-alpha-alpha_; delta = cos(theta)* ew_c; h = sin(theta)* ew_c; curr_d = sqrt( pow(h,2)+ pow(d_curr + delta,2)); } } //************************************************************************************** toQueue = ( (*TD)[(pw)].d==-1); if(toQueue){// se non e'gia' in coda ce lo mette expansion.push_back(std::pair(pw,curr_d)); }else { if( (*TD)[(pw)].d > curr_d ) (*TD)[(pw)].d = curr_d; } if(isLeaf){ if(d_curr > max_distance){ max_distance = d_curr; farthest = curr; } } } std::vector > ::iterator i; for(i = expansion.begin(); i!= expansion.end(); ++i) { (*TD)[(*i).first].d = (*i).second; frontier.push_back(VertDist((*i).first,(*TD)[(*i).first].d)); push_heap(frontier.begin(),frontier.end(),pred()); } // end for }// end while // scrivi le distanze sul campo qualita' (nn: farlo parametrico) MeshType::VertexIterator vi; for(vi = m.vert.begin(); vi != m.vert.end(); ++vi) (*vi).Q() = (*TD)[&(*vi)].d; (*TD).Stop(); delete TD; return farthest; } public: /* Given a mesh and a vector of pointers to vertices (sources), assigns the approximated geodesic distance from the cloasest source to all the mesh vertices and returns the pointer to the farthest. Note: update the field Q() of the vertices */ void FartestVertex( MeshType & m, std::vector & fro, typename MeshType::VertexPointer & farthest, ScalarType & distance){ std::vector::iterator fi; std::vectorfr; for( fi = fro.begin(); fi != fro.end() ; ++fi) fr.push_back(VertDist(*fi,-1)); farthest = Visit(m,fr,distance,false); } /* Given a mesh and a pointers to a vertex-source (source), assigns the approximated geodesic distance from the vertex-source to all the mesh vertices and returns the pointer to the farthest Note: update the field Q() of the vertices */ void FartestVertex( MeshType & m, typename MeshType::VertexPointer seed, typename MeshType::VertexPointer & farthest, ScalarType & distance){ std::vector fro; fro.push_back( seed ); typename MeshType::VertexPointer v0; FartestVertex(m,fro,v0,distance); farthest = v0; } /* Same as FartestPoint but the returned pointer is to a border vertex Note: update the field Q() of the vertices */ void FartestBVertex(MeshType & m, std::vector & fro, typename MeshType::VertexPointer & farthest, ScalarType & distance){ std::vector::iterator fi; std::vectorfr; for( fi = fro.begin(); fi != fro.end() ; ++fi) fr.push_back(VertDist(*fi,-1)); farthest = Visit(m,fr,distance,true); } /* Same as FartestPoint but the returned pointer is to a border vertex Note: update the field Q() of the vertices */ void FartestBVertex( MeshType & m, typename MeshType::VertexPointer seed, typename MeshType::VertexPointer & farthest, ScalarType & distance){ std::vector fro; fro.push_back( seed ); typename MeshType::VertexPointer v0; FartestBVertex(m,fro,v0,distance); farthest = v0; } /* Assigns to each vertex of the mesh its distance to the closest vertex on the border Note: update the field Q() of the vertices */ void DistanceFromBorder( MeshType & m, typename MeshType::VertexPointer & v0, ScalarType & distance ){ std::vector fro; MeshType::VertexIterator vi; MeshType::VertexPointer farthest; for(vi = m.vert.begin(); vi != m.vert.end(); ++vi) if( (*vi).IsB()) fro.push_back(&(*vi)); FartestVertex(m,fro,farthest,distance); } }; };// end namespacequtemol/vcg/vcg/complex/local_optimization/0000755000175000017500000000000011633404241017527 5ustar mbambaqutemol/vcg/vcg/complex/local_optimization/tri_edge_collapse_quadric.h0000444000175000017500000005414710705165375025100 0ustar mbamba/**************************************************************************** * VCGLib o o * * Visual and Computer Graphics Library o o * * _ O _ * * Copyright(C) 2004 \/)\/ * * Visual Computing Lab /\/| * * ISTI - Italian National Research Council | * * \ * * All rights reserved. * * * * 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. * * * * 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 (http://www.gnu.org/licenses/gpl.txt) * * for more details. * * * ****************************************************************************/ /**************************************************************************** History $Log: tri_edge_collapse_quadric.h,v $ Revision 1.15 2007/10/16 16:46:53 cignoni Added Allocator::DeleteFace and Allocator::DeleteVertex; Now the use of SetD() should be deprecated. Revision 1.14 2007/03/22 11:07:16 cignoni Solved an issue related to different casting double-float between gcc 3 and gcc 4 Revision 1.13 2007/02/25 09:20:10 cignoni Added Rad to the NormalThr Option and removed a bug in multiple exectuion of non optimal simplification (missing an isD check) Revision 1.12 2007/01/19 09:13:14 cignoni Added Finalize() method to the interface, corrected minor bugs on border preserving and postsimplification cleanup Avoided double make_heap (it is done only in the local_optimization init) Revision 1.11 2006/10/15 07:31:21 cignoni typenames and qualifiers for gcc compliance Revision 1.10 2006/10/09 20:12:55 cignoni Heavyly restructured for meshlab inclusion. Now the access to the quadric elements are mediated by a static helper class. Revision 1.9 2006/10/07 17:20:25 cignoni Updated to the new style face->Normal() becomes Normal(face) Revision 1.8 2005/10/02 23:19:36 cignoni Changed the sign of the priority of a collapse. Now it is its the error as it should (and not -error) Revision 1.7 2005/04/14 11:35:07 ponchio *** empty log message *** Revision 1.6 2005/01/19 10:35:28 cignoni Better management of symmetric/asymmetric edge collapses Revision 1.5 2004/12/10 01:07:15 cignoni Moved param classes inside; added support for optimal placement and symmetric; added update heap also here (not only in the base class) Revision 1.4 2004/11/23 10:34:23 cignoni passed parameters by reference in many funcs and gcc cleaning Revision 1.3 2004/10/25 07:07:56 ganovelli A vcg.::Pos was used to implement the collapse type. CHanged to vcg::Edge Revision 1.2 2004/09/29 17:08:16 ganovelli corrected error in -error (see localoptimization) ****************************************************************************/ #ifndef __VCG_TRIMESHCOLLAPSE_QUADRIC__ #define __VCG_TRIMESHCOLLAPSE_QUADRIC__ #include #include #include #include #include #include namespace vcg{ namespace tri{ /** This class describe Quadric based collapse operation. Requirements: Vertex must have: incremental mark VF topology must have: members QuadricType Qd(); ScalarType W() const; A per-vertex Weight that can be used in simplification lower weight means that error is lowered, standard: return W==1.0 void Merge(MESH_TYPE::vertex_type const & v); Merges the attributes of the current vertex with the ones of v (e.g. its weight with the one of the given vertex, the color ect). Standard: void function; OtherWise the class should be templated with a static helper class that helps to retrieve these functions. If the vertex class exposes these functions a default static helper class is provided. */ //**Helper CLASSES**// template class QInfoStandard { public: QInfoStandard(){}; static void Init(){}; static math::Quadric &Qd(VERTEX_TYPE &v) {return v.Qd();} static math::Quadric &Qd(VERTEX_TYPE *v) {return v->Qd();} static typename VERTEX_TYPE::ScalarType W(VERTEX_TYPE *v) {return 1.0;}; static typename VERTEX_TYPE::ScalarType W(VERTEX_TYPE &v) {return 1.0;}; static void Merge(VERTEX_TYPE & v_dest, VERTEX_TYPE const & v_del){}; }; class TriEdgeCollapseQuadricParameter { public: double QualityThr; // all double BoundaryWeight; double NormalThrRad; double CosineThr; double QuadricEpsilon; double ScaleFactor; bool UseArea; bool UseVertexWeight; bool NormalCheck; bool QualityCheck; bool OptimalPlacement; bool MemoryLess; bool ComplexCheck; bool ScaleIndependent; //*********************** bool PreserveTopology; bool PreserveBoundary; bool MarkComplex; bool FastPreserveBoundary; bool SafeHeapUpdate; }; template > class TriEdgeCollapseQuadric: public TriEdgeCollapse< TriMeshType, MYTYPE> { public: typedef typename vcg::tri::TriEdgeCollapse< TriMeshType, MYTYPE > TEC; typedef typename TEC::EdgeType EdgeType; typedef typename TriEdgeCollapse::HeapType HeapType; typedef typename TriEdgeCollapse::HeapElem HeapElem; typedef typename TriMeshType::CoordType CoordType; typedef typename TriMeshType::ScalarType ScalarType; typedef math::Quadric< double > QuadricType; typedef typename TriMeshType::FaceType FaceType; typedef typename TriMeshType::VertexType VertexType; typedef TriEdgeCollapseQuadricParameter QParameter; typedef HelperType QH; static QParameter & Params(){ static QParameter p; return p; } enum Hint { HNHasFFTopology = 0x0001, // La mesh arriva con la topologia ff gia'fatta HNHasVFTopology = 0x0002, // La mesh arriva con la topologia bf gia'fatta HNHasBorderFlag = 0x0004 // La mesh arriva con i flag di bordo gia' settati }; static int & Hnt(){static int hnt; return hnt;} // the current hints static void SetHint(Hint hn) { Hnt() |= hn; } static void ClearHint(Hint hn) { Hnt()&=(~hn);} static bool IsSetHint(Hint hn) { return (Hnt()&hn)!=0; } // puntatori ai vertici che sono stati messi non-w per preservare il boundary static std::vector & WV(){ static std::vector _WV; return _WV; }; inline TriEdgeCollapseQuadric(const EdgeType &p, int i) //:TEC(p,i){} { this->localMark = i; this->pos=p; this->_priority = ComputePriority(); } inline bool IsFeasible(){ bool res = ( !Params().PreserveTopology || LinkConditions(this->pos) ); if(!res) ++( TriEdgeCollapse< TriMeshType,MYTYPE>::FailStat::LinkConditionEdge() ); return res; } void Execute(TriMeshType &m) { CoordType newPos; if(Params().OptimalPlacement) newPos= ComputeMinimal(); else newPos=this->pos.V(1)->P(); //this->pos.V(1)->Qd()+=this->pos.V(0)->Qd(); QH::Qd(this->pos.V(1))+=QH::Qd(this->pos.V(0)); //int FaceDel= DoCollapse(m, this->pos, newPos); // v0 is deleted and v1 take the new position //m.fn-=FaceDel; //--m.vn; } // Final Clean up after the end of the simplification process static void Finalize(TriMeshType &m,HeapType&h_ret) { // if the mesh was prepared with precomputed borderflags // correctly set them again. if(IsSetHint(HNHasBorderFlag) ) vcg::tri::UpdateFlags::FaceBorderFromVF(m); // If we had the boundary preservation we should clean up the writable flags if(Params().FastPreserveBoundary) { typename TriMeshType::VertexIterator vi; for(vi=m.vert.begin();vi!=m.vert.end();++vi) if(!(*vi).IsD()) (*vi).SetW(); } if(Params().FastPreserveBoundary) { typename std::vector::iterator wvi; for(wvi=WV().begin();wvi!=WV().end();++wvi) if(!(*wvi)->IsD()) (*wvi)->SetW(); } } static void Init(TriMeshType &m,HeapType&h_ret){ typename TriMeshType::VertexIterator vi; typename TriMeshType::FaceIterator pf; EdgeType av0,av1,av01; Params().CosineThr=cos(Params().NormalThrRad); if(!IsSetHint(HNHasVFTopology) ) vcg::tri::UpdateTopology::VertexFace(m); if(Params().MarkComplex) { vcg::tri::UpdateTopology::FaceFace(m); vcg::tri::UpdateFlags::FaceBorderFromFF(m); vcg::tri::UpdateTopology::VertexFace(m); } // e' un po' piu' lenta ma marca i vertici complex else if(!IsSetHint(HNHasBorderFlag) ) vcg::tri::UpdateFlags::FaceBorderFromVF(m); if(Params().FastPreserveBoundary) { for(pf=m.face.begin();pf!=m.face.end();++pf) if( !(*pf).IsD() && (*pf).IsW() ) for(int j=0;j<3;++j) if((*pf).IsB(j)) { (*pf).V(j)->ClearW(); (*pf).V1(j)->ClearW(); } } if(Params().PreserveBoundary) { WV().clear(); for(pf=m.face.begin();pf!=m.face.end();++pf) if( !(*pf).IsD() && (*pf).IsW() ) for(int j=0;j<3;++j) if((*pf).IsB(j)) { if((*pf).V(j)->IsW()) {(*pf).V(j)->ClearW(); WV().push_back((*pf).V(j));} if((*pf).V1(j)->IsW()) {(*pf).V1(j)->ClearW();WV().push_back((*pf).V1(j));} } } InitQuadric(m); // Initialize the heap with all the possible collapses if(IsSymmetric()) { // if the collapse is symmetric (e.g. u->v == v->u) for(vi=m.vert.begin();vi!=m.vert.end();++vi) if(!(*vi).IsD() && (*vi).IsRW()) { vcg::face::VFIterator x; for( x.F() = (*vi).VFp(), x.I() = (*vi).VFi(); x.F()!=0; ++ x){ x.V1()->ClearV(); x.V2()->ClearV(); } for( x.F() = (*vi).VFp(), x.I() = (*vi).VFi(); x.F()!=0; ++x ) { assert(x.F()->V(x.I())==&(*vi)); if((x.V0()IsRW() && !x.V1()->IsV()){ x.V1()->SetV(); h_ret.push_back(HeapElem(new MYTYPE(EdgeType(x.V0(),x.V1()),TriEdgeCollapse< TriMeshType,MYTYPE>::GlobalMark() ))); } if((x.V0()IsRW()&& !x.V2()->IsV()){ x.V2()->SetV(); h_ret.push_back(HeapElem(new MYTYPE(EdgeType(x.V0(),x.V2()),TriEdgeCollapse< TriMeshType,MYTYPE>::GlobalMark() ))); } } } } else { // if the collapse is A-symmetric (e.g. u->v != v->u) for(vi=m.vert.begin();vi!=m.vert.end();++vi) if(!(*vi).IsD() && (*vi).IsRW()) { vcg::face::VFIterator x; m.UnMarkAll(); for( x.F() = (*vi).VFp(), x.I() = (*vi).VFi(); x.F()!=0; ++ x) { assert(x.F()->V(x.I())==&(*vi)); if(x.V()->IsRW() && x.V1()->IsRW() && !m.IsMarked(x.F()->V1(x.I()))){ h_ret.push_back( HeapElem( new MYTYPE( EdgeType (x.V(),x.V1()),TriEdgeCollapse< TriMeshType,MYTYPE>::GlobalMark()))); } if(x.V()->IsRW() && x.V2()->IsRW() && !m.IsMarked(x.F()->V2(x.I()))){ h_ret.push_back( HeapElem( new MYTYPE( EdgeType (x.V(),x.V2()),TriEdgeCollapse< TriMeshType,MYTYPE>::GlobalMark()))); } } } } } static bool IsSymmetric() {return Params().OptimalPlacement;} static bool IsVertexStable() {return !Params().OptimalPlacement;} static void SetDefaultParams(){ Params().UseArea=true; Params().UseVertexWeight=false; Params().NormalCheck=false; Params().NormalThrRad=M_PI/2; Params().QualityCheck=true; Params().QualityThr=.1; Params().BoundaryWeight=.5; Params().OptimalPlacement=true; Params().ScaleIndependent=true; Params().ComplexCheck=false; Params().QuadricEpsilon =1e-15; Params().ScaleFactor=1.0; Params().PreserveTopology = false; } ///* // Funzione principale di valutazione dell'errore del collasso. // In pratica simula il collasso vero e proprio. // // Da ottimizzare il ciclo sulle normali (deve sparire on e si deve usare per face normals) //*/ ScalarType ComputePriority() { ScalarType error; typename vcg::face::VFIterator x; std::vector on; // original normals typename TriMeshType::VertexType * v[2]; v[0] = this->pos.V(0); v[1] = this->pos.V(1); if(Params().NormalCheck){ // Compute maximal normal variation // store the old normals for non-collapsed face in v0 for(x.F() = v[0]->VFp(), x.I() = v[0]->VFi(); x.F()!=0; ++x ) // for all faces in v0 if(x.F()->V(0)!=v[1] && x.F()->V(1)!=v[1] && x.F()->V(2)!=v[1] ) // skip faces with v1 on.push_back(NormalizedNormal(*x.F())); // store the old normals for non-collapsed face in v1 for(x.F() = v[1]->VFp(), x.I() = v[1]->VFi(); x.F()!=0; ++x ) // for all faces in v1 if(x.F()->V(0)!=v[0] && x.F()->V(1)!=v[0] && x.F()->V(2)!=v[0] ) // skip faces with v0 on.push_back(NormalizedNormal(*x.F())); } //// Move the two vertexe into new position (storing the old ones) CoordType OldPos0=v[0]->P(); CoordType OldPos1=v[1]->P(); if(Params().OptimalPlacement) { v[0]->P() = ComputeMinimal(); v[1]->P()=v[0]->P();} else v[0]->P() = v[1]->P(); //// Rescan faces and compute quality and difference between normals int i; double ndiff,MinCos = 1e100; // minimo coseno di variazione di una normale della faccia // (e.g. max angle) Mincos varia da 1 (normali coincidenti) a // -1 (normali opposte); double qt, MinQual = 1e100; CoordType nn; for(x.F() = v[0]->VFp(), x.I() = v[0]->VFi(),i=0; x.F()!=0; ++x ) // for all faces in v0 if(x.F()->V(0)!=v[1] && x.F()->V(1)!=v[1] && x.F()->V(2)!=v[1] ) // skip faces with v1 { if(Params().NormalCheck){ nn=NormalizedNormal(*x.F()); ndiff=nn*on[i++]; if(ndiffVFp(), x.I() = v[1]->VFi(),i=0; x.F()!=0; ++x ) // for all faces in v1 if(x.F()->V(0)!=v[0] && x.F()->V(1)!=v[0] && x.F()->V(2)!=v[0] ) // skip faces with v0 { if(Params().NormalCheck){ nn=NormalizedNormal(*x.F()); ndiff=nn*on[i++]; if(ndiffP()); double QuadErr = Params().ScaleFactor*qq.Apply(tpd); // All collapses involving triangles with quality larger than has no penalty; if(MinQual>Params().QualityThr) MinQual=Params().QualityThr; if(Params().NormalCheck){ // All collapses where the normal vary less than (e.g. more than CosineThr) // have no penalty if(MinCos>Params().CosineThr) MinCos=Params().CosineThr; MinCos=(MinCos+1)/2.0; // Now it is in the range 0..1 with 0 very dangerous! } if(QuadErrP()=OldPos0; v[1]->P()=OldPos1; this->_priority = error; return this->_priority; } // //static double MaxError() {return 1e100;} // inline void UpdateHeap(HeapType & h_ret) { this->GlobalMark()++; VertexType *v[2]; v[0]= this->pos.V(0); v[1]= this->pos.V(1); v[1]->IMark() = this->GlobalMark(); // First loop around the remaining vertex to unmark visited flags vcg::face::VFIterator vfi(v[1]); while (!vfi.End()){ vfi.V1()->ClearV(); vfi.V2()->ClearV(); ++vfi; } // Second Loop vfi = face::VFIterator(v[1]); while (!vfi.End()) { assert(!vfi.F()->IsD()); for (int j=0;j<3;j++) { if( !(vfi.V1()->IsV()) && vfi.V1()->IsRW()) { vfi.V1()->SetV(); h_ret.push_back(HeapElem(new MYTYPE(EdgeType(vfi.V0(),vfi.V1()), this->GlobalMark()))); std::push_heap(h_ret.begin(),h_ret.end()); if(!IsSymmetric()){ h_ret.push_back(HeapElem(new MYTYPE(EdgeType(vfi.V1(),vfi.V0()), this->GlobalMark()))); std::push_heap(h_ret.begin(),h_ret.end()); } } if( !(vfi.V2()->IsV()) && vfi.V2()->IsRW()) { vfi.V2()->SetV(); h_ret.push_back(HeapElem(new MYTYPE(EdgeType(vfi.V0(),vfi.V2()),this->GlobalMark()))); std::push_heap(h_ret.begin(),h_ret.end()); if(!IsSymmetric()){ h_ret.push_back(HeapElem(new MYTYPE(EdgeType(vfi.V2(),vfi.V0()), this->GlobalMark()))); std::push_heap(h_ret.begin(),h_ret.end()); } } if(Params().SafeHeapUpdate && vfi.V1()->IsRW() && vfi.V2()->IsRW() ) { h_ret.push_back(HeapElem(new MYTYPE(EdgeType(vfi.V1(),vfi.V2()),this->GlobalMark()))); std::push_heap(h_ret.begin(),h_ret.end()); if(!IsSymmetric()){ h_ret.push_back(HeapElem(new MYTYPE(EdgeType(vfi.V2(),vfi.V1()), this->GlobalMark()))); std::push_heap(h_ret.begin(),h_ret.end()); } } } ++vfi; } } static void InitQuadric(TriMeshType &m) { typename TriMeshType::FaceIterator pf; typename TriMeshType::VertexIterator pv; int j; QH::Init(); // m.ClearFlags(); for(pv=m.vert.begin();pv!=m.vert.end();++pv) // Azzero le quadriche if( ! (*pv).IsD() && (*pv).IsW()) QH::Qd(*pv).Zero(); for(pf=m.face.begin();pf!=m.face.end();++pf) if( !(*pf).IsD() && (*pf).IsR() ) if((*pf).V(0)->IsR() &&(*pf).V(1)->IsR() &&(*pf).V(2)->IsR()) { QuadricType q; Plane3 p; // Calcolo piano p.SetDirection( ( (*pf).V(1)->cP() - (*pf).V(0)->cP() ) ^ ( (*pf).V(2)->cP() - (*pf).V(0)->cP() )); // Se normalizzo non dipende dall'area if(!Params().UseArea) p.Normalize(); p.SetOffset( p.Direction() * (*pf).V(0)->cP()); // Calcolo quadrica delle facce q.ByPlane(p); for(j=0;j<3;++j) if( (*pf).V(j)->IsW() ) QH::Qd((*pf).V(j)) += q; // Sommo la quadrica ai vertici for(j=0;j<3;++j) if( (*pf).IsB(j)) // Bordo! { Plane3 pb; // Piano di bordo // Calcolo la normale al piano di bordo e la sua distanza // Nota che la lunghezza dell'edge DEVE essere Normalizzata // poiche' la pesatura in funzione dell'area e'gia fatta in p.Direction() // Senza la normalize il bordo e' pesato in funzione della grandezza della mesh (mesh grandi non decimano sul bordo) pb.SetDirection(p.Direction() ^ ( (*pf).V1(j)->cP() - (*pf).V(j)->cP() ).Normalize()); pb.SetDirection(pb.Direction()* (ScalarType)Params().BoundaryWeight); // amplify border planes pb.SetOffset(pb.Direction() * (*pf).V(j)->cP()); q.ByPlane(pb); if( (*pf).V (j)->IsW() ) QH::Qd((*pf).V (j)) += q; // Sommo le quadriche if( (*pf).V1(j)->IsW() ) QH::Qd((*pf).V1(j)) += q; } } if(Params().ScaleIndependent) { vcg::tri::UpdateBounding::Box(m); //Make all quadric independent from mesh size Params().ScaleFactor = 1e8*pow(1.0/m.bbox.Diag(),6); // scaling factor //Params().ScaleFactor *=Params().ScaleFactor ; //Params().ScaleFactor *=Params().ScaleFactor ; //printf("Scale factor =%f\n",Params().ScaleFactor ); //printf("bb (%5.2f %5.2f %5.2f)-(%5.2f %5.2f %5.2f) Diag %f\n",m.bbox.min[0],m.bbox.min[1],m.bbox.min[2],m.bbox.max[0],m.bbox.max[1],m.bbox.max[2],m.bbox.Diag()); } if(Params().ComplexCheck) { // secondo loop per diminuire quadriche complex (se non c'erano i complex si poteva fare in un giro solo) //for(pf=m.face.begin();pf!=m.face.end();++pf) //if( !(*pf).IsD() && (*pf).IsR() ) // if((*pf).V(0)->IsR() &&(*pf).V(1)->IsR() &&(*pf).V(2)->IsR()) // { // for(j=0;j<3;++j) // if((*pf).IsCF(j)) // Complex! // { // if( (*pf).V (j)->IsW() ) (*pf).V (j)->q *= 0.01; // Scalo le quadriche // if( (*pf).V1(j)->IsW() ) (*pf).V1(j)->q *= 0.01; // } // } } } // // // // // // //static void InitMesh(MESH_TYPE &m){ // Params().CosineThr=cos(Params().NormalThr); // InitQuadric(m); // //m.Topology(); // //OldInitQuadric(m,UseArea); // } // CoordType ComputeMinimal() { typename TriMeshType::VertexType * v[2]; v[0] = this->pos.V(0); v[1] = this->pos.V(1); QuadricType q=QH::Qd(v[0]); q+=QH::Qd(v[1]); Point3 x; bool rt=q.Minimum(x); if(!rt) { // if the computation of the minimum fails we choose between the two edge points and the middle one. Point3 x0=Point3d::Construct(v[0]->P()); Point3 x1=Point3d::Construct(v[1]->P()); x.Import((v[0]->P()+v[1]->P())/2); double qvx=q.Apply(x); double qv0=q.Apply(x0); double qv1=q.Apply(x1); if(qv0 #include #include #include struct FAIL{ static int VOL(){static int vol=0; return vol++;} static int LKF(){static int lkf=0; return lkf++;} static int LKE(){static int lke=0; return lke++;} static int LKV(){static int lkv=0; return lkv++;} static int OFD(){static int ofd=0; return ofd++;} static int BOR(){static int bor=0; return bor++;} }; namespace vcg{ namespace tetra{ /** \addtogroup tetramesh */ /*@{*/ /// This Class is specialization of LocalModification for the edge collapse /// It wraps the atomic operation EdgeCollapse to be used in a optimizatin routine. /// Note that it has knowledge of the heap of the class LocalOptimization because /// it is responsible of updating it after a collapse has been performed template class TetraEdgeCollapse: public LocalOptimization::LocModType { /// The tetrahedral mesh type //typedef typename TETRA_MESH_TYPE TETRA_MESH_TYPE; /// The tetrahedron type typedef typename TETRA_MESH_TYPE::TetraType TetraType; /// The vertex type typedef typename TetraType::VertexType VertexType; /// The coordinate type typedef typename TetraType::VertexType::CoordType CoordType; /// The scalar type typedef typename TETRA_MESH_TYPE::VertexType::ScalarType ScalarType; /////the base type class //typedef typename vcg::tri::LocalModification LocalMod; /// The HEdgePos type typedef Pos PosType; /// The HEdgePos Loop type typedef PosLoop PosLType; /// definition of the heap element typedef typename LocalOptimization::HeapElem HeapElem; private: ///the new point that substitute the edge Point3 _NewPoint; ///the pointer to edge collapser method vcg::tetra::EdgeCollapse _EC; ///mark for up_dating static int& _Imark(){ static int im=0; return im;} ///the pos of collapse PosType pos; ///pointer to vertex that remain VertexType *vrem; /// priority in the heap ScalarType _priority; public: /// Default Constructor TetraEdgeCollapse() {} ///Constructor with postype TetraEdgeCollapse(PosType p,int mark) { _Imark() = mark; pos=p; _priority = _AspectRatioMedia(p); } ~TetraEdgeCollapse() {} private: ///Return the aspect Ratio media of the tetrahedrons ///that share the adge to collapse ScalarType _AspectRatioMedia(PosType p) { PosLType posl=PosLType(p.T(),p.F(),p.E(),p.V()); posl.Reset(); int num=0; ScalarType ratio_media=0.f; while(!posl.LoopEnd()) { ratio_media+=posl.T()->AspectRatio(); posl.NextT(); num++; } ratio_media=ratio_media/num; return (ratio_media); } ///Modify pos and alfa to obtain the collapse that minimize the error ScalarType _VolumePreservingError(PosType &pos,CoordType &new_point,int nsteps) { VertexType *ve0=(pos.T()->V(Tetra::VofE(pos.E(),0))); VertexType *ve1=(pos.T()->V(Tetra::VofE(pos.E(),1))); bool ext_v0=ve0->IsB(); bool ext_v1=ve1->IsB(); ScalarType best_error=0.f; if ((ext_v0)&&(!ext_v1)) new_point=ve0->P(); else if ((!ext_v0)&&(ext_v1)) new_point=ve1->P(); else if ((!ext_v0)&&(!ext_v1)) {/*CoordType g; g.Zero(); g+=ve0->cP(); g+=ve1->cP(); g/=2;*/ new_point=(ve0->cP()+ve1->cP())/2.f; } else if ((ext_v0)&&(ext_v1))//both are external vertex { ScalarType step=1.f/(nsteps-1); ScalarType Vol_Original=_EC.VolumeOriginal(); for (int i=0;icP()*alfatemp; //g+=ve1->cP()*(1-alfatemp); //CoordType newPTemp=g; CoordType newPTemp=(ve0->cP()*alfatemp) +(ve1->cP()*(1.f-alfatemp)); //the error is the absolute value of difference of volumes ScalarType error=fabs(Vol_Original-_EC.VolumeSimulateCollapse(pos,newPTemp)); if(error %i %f\n", pos.()-&m.vert[0], pos.VFlip()-&m.vert[0],_priority); return buf; } ScalarType ComputePriority() { return (_priority = _AspectRatioMedia(this->pos)); } ScalarType ComputeError() { vrem=(pos.T()->V(Tetra::VofE(pos.E(),0))); return (_VolumePreservingError(pos,_NewPoint,5));// magic number....parametrize! } void Execute(TETRA_MESH_TYPE &tm) { // _EC.FindSets(pos); assert(!vrem->IsD()); int del=_EC.DoCollapse(pos,_NewPoint); tm.tn-=del; tm.vn-=1; } void UpdateHeap(typename LocalOptimization::HeapType & h_ret) { assert(!vrem->IsD()); _Imark()++; VTIterator VTi(vrem->VTb(),vrem->VTi()); while (!VTi.End()) { VTi.Vt()->ComputeVolume(); for (int j=0;j<6;j++) { vcg::tetra::Pos p=Pos(VTi.Vt(),Tetra::FofE(j,0),j,Tetra::VofE(j,0)); assert(!p.T()->V(p.V())->IsD()); assert(!p.T()->IsD()); h_ret.push_back(HeapElem(new TetraEdgeCollapse(p,_Imark()))); std::push_heap(h_ret.begin(),h_ret.end()); // update the mark of the vertices VTi.Vt()->V(Tetra::VofE(j,0))->IMark() = _Imark(); } ++VTi; } } /// return the type of operation ModifierType IsOfType(){ return TetraEdgeCollapseOp;} bool IsFeasible(){ vcg::tetra::EdgeCollapse::Reset(); _EC.FindSets(pos); ComputeError(); return(_EC.CheckPreconditions(pos,_NewPoint)); } bool IsUpToDate(){ if (!pos.T()->IsD()) { VertexType *v0=pos.T()->V(Tetra::VofE(pos.E(),0)); VertexType *v1=pos.T()->V(Tetra::VofE(pos.E(),1)); assert(!v0->IsD()); assert(!v1->IsD()); if(! (( (!v0->IsD()) && (!v1->IsD())) && _Imark()>=v0->IMark() && _Imark()>=v1->IMark())) { FAIL::OFD(); return false; } else return true; } else return false; } virtual ScalarType Priority() const { return _priority; } /// perform initialization static void Init(TETRA_MESH_TYPE &m,typename LocalOptimization::HeapType& h_ret){ h_ret.clear(); typename TETRA_MESH_TYPE::TetraIterator ti; for(ti = m.tetra.begin(); ti != m.tetra.end();++ti) if(!(*ti).IsD()){ (*ti).ComputeVolume(); for (int j=0;j<6;j++) { PosType p=PosType(&*ti,Tetra::FofE(j,0),j,Tetra::VofE(j,0)); assert(!p.T()->V(p.V())->IsD()); assert(!p.T()->IsD()); h_ret.push_back(HeapElem(new TetraEdgeCollapse(p,m.IMark))); } } } }; }//end namespace tetra }//end namespace vcg #endif qutemol/vcg/vcg/complex/local_optimization/tri_edge_collapse.h0000444000175000017500000002146510705165375023365 0ustar mbamba/**************************************************************************** * VCGLib o o * * Visual and Computer Graphics Library o o * * _ O _ * * Copyright(C) 2004 \/)\/ * * Visual Computing Lab /\/| * * ISTI - Italian National Research Council | * * \ * * All rights reserved. * * * * 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. * * * * 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 (http://www.gnu.org/licenses/gpl.txt) * * for more details. * * * ****************************************************************************/ /**************************************************************************** $Log: tri_edge_collapse.h,v $ Revision 1.20 2007/10/16 16:46:53 cignoni Added Allocator::DeleteFace and Allocator::DeleteVertex; Now the use of SetD() should be deprecated. Revision 1.19 2006/10/15 07:31:21 cignoni typenames and qualifiers for gcc compliance Revision 1.18 2006/10/09 20:09:40 cignoni Changed some access to VertexFaceIterator to reflect the shorter new operators. Revision 1.17 2005/10/12 10:44:01 cignoni Now creation of new edge use Ordered() constructor to comply the fact that the basic collapse is simmetric. Revision 1.16 2005/01/19 10:35:28 cignoni Better management of symmetric/asymmetric edge collapses Revision 1.15 2004/12/10 01:03:53 cignoni better comments and removed logging Revision 1.14 2004/11/23 10:34:23 cignoni passed parameters by reference in many funcs and gcc cleaning Revision 1.13 2004/10/25 16:28:32 ganovelli pos to edge Revision 1.12 2004/09/15 11:16:02 ganovelli changed P() to cP() Revision 1.11 2004/09/09 13:23:01 ponchio Header guards typo Revision 1.10 2004/09/09 13:01:12 ponchio Linux compatible path in #include Revision 1.9 2004/09/08 15:13:29 ganovelli changes for gc Revision 1.8 2004/09/08 14:33:31 ganovelli *** empty log message *** ****************************************************************************/ #ifndef __VCG_DECIMATION_TRICOLLAPSE #define __VCG_DECIMATION_TRICOLLAPSE #include #include #include namespace vcg{ namespace tri{ /** \addtogroup trimesh */ /*@{*/ /// This Class is specialization of LocalModification for the edge collapse. /// It wraps the atomic operation EdgeCollapse to be used in a optimizatin routine. /// Note that it has knowledge of the heap of the class LocalOptimization because /// it is responsible of updating it after a collapse has been performed; /// This is the base class of all the specialized collapse classes like for example Quadric Edge Collapse. /// Each derived class template class TriEdgeCollapse: public LocalOptimization::LocModType , public EdgeCollapse { public: /// static data to gather statistical information about the reasons of collapse failures class FailStat { public: static int &Volume() {static int vol=0; return vol;} static int &LinkConditionFace(){static int lkf=0; return lkf;} static int &LinkConditionEdge(){static int lke=0; return lke;} static int &LinkConditionVert(){static int lkv=0; return lkv;} static int &OutOfDate() {static int ofd=0; return ofd;} static int &Border() {static int bor=0; return bor;} static void Init() { Volume() =0; LinkConditionFace()=0; LinkConditionEdge()=0; LinkConditionVert()=0; OutOfDate() =0; Border() =0; } }; protected: typedef typename TriMeshType::FaceType FaceType; typedef typename TriMeshType::FaceType::VertexType VertexType; typedef typename VertexType::EdgeType EdgeType; typedef typename FaceType::VertexType::CoordType CoordType; typedef typename TriMeshType::VertexType::ScalarType ScalarType; typedef typename LocalOptimization::HeapElem HeapElem; typedef typename LocalOptimization::HeapType HeapType; TriMeshType *mt; ///the pair to collapse EdgeType pos; ///mark for up_dating static int& GlobalMark(){ static int im=0; return im;} ///mark for up_dating int localMark; /// priority in the heap ScalarType _priority; public: /// Default Constructor inline TriEdgeCollapse() {} ///Constructor with postype inline TriEdgeCollapse(const EdgeType &p, int mark) { localMark = mark; pos=p; _priority = ComputePriority(); } ~TriEdgeCollapse() {} private: public: inline ScalarType ComputePriority() { _priority = Distance(pos.V(0)->cP(),pos.V(1)->cP()); return _priority; } virtual const char *Info(TriMeshType &m) { mt = &m; static char buf[60]; sprintf(buf,"%i -> %i %g\n", pos.V(0)-&m.vert[0], pos.V(1)-&m.vert[0],-_priority); return buf; } inline void Execute(TriMeshType &m) { CoordType MidPoint=(pos.V(0)->P()+pos.V(1)->P())/2.0; int FaceDel=DoCollapse(m, pos, MidPoint); //m.fn-=FaceDel; //--m.vn; } static bool IsSymmetric() { return true;} inline void UpdateHeap(HeapType & h_ret) { GlobalMark()++; int nn=0; VertexType *v[2]; v[0]= pos.V(0);v[1]=pos.V(1); v[1]->IMark() = GlobalMark(); // First loop around the remaining vertex to unmark visited flags vcg::face::VFIterator vfi(v[1]->VFp(),v[1]->VFi()); while (!vfi.End()){ vfi.V1()->ClearV(); vfi.V2()->ClearV(); ++vfi; } // Second Loop vfi.F() = v[1]->VFp(); vfi.I() = v[1]->VFi(); while (!vfi.End()) { assert(!vfi.F()->IsD()); for (int j=0;j<3;j++) { if( !(vfi.V1()->IsV()) && (vfi.V1()->IsRW())) { vfi.F()->V1(vfi.I())->SetV(); h_ret.push_back(HeapElem(new MYTYPE(EdgeType::OrderedEdge( vfi.V(),vfi.V1() ),GlobalMark()))); std::push_heap(h_ret.begin(),h_ret.end()); if(this->IsSymmetric()){ h_ret.push_back(HeapElem(new MYTYPE(EdgeType::OrderedEdge( vfi.V1(),vfi.V()),GlobalMark()))); std::push_heap(h_ret.begin(),h_ret.end()); } } if( !(vfi.V2()->IsV()) && (vfi.V2()->IsRW())) { vfi.V2()->SetV(); h_ret.push_back(HeapElem(new MYTYPE(EdgeType::OrderedEdge(vfi.F()->V(vfi.I()),vfi.F()->V2(vfi.I())),GlobalMark()))); std::push_heap(h_ret.begin(),h_ret.end()); //if(false){ // h_ret.push_back(HeapElem(new MYTYPE(EdgeType (vfi.F()->V1(vfi.I()),vfi.F()->V(vfi.I())),GlobalMark()))); // std::push_heap(h_ret.begin(),h_ret.end()); // } } } ++vfi;nn++; } // printf("ADDED %d\n",nn); } ModifierType IsOfType(){ return TriEdgeCollapseOp;} inline bool IsFeasible(){ return LinkConditions(pos); } inline bool IsUpToDate(){ // if(pos.V(1)->IsD()) { // ++FailStat::OutOfDate(); // return false; //} // // if(pos.V(1)->IsD()) { // ++FailStat::OutOfDate(); // return false; //} VertexType *v0=pos.V(0); VertexType *v1=pos.V(1); //if(! (( (!v0->IsD()) && (!v1->IsD())) && // localMark>=v0->IMark() && // localMark>=v1->IMark())) if( v0->IsD() || v1->IsD() || localMark < v0->IMark() || localMark < v1->IMark() ) { ++FailStat::OutOfDate(); return false; } return true; } virtual ScalarType Priority() const { return _priority; } static void Init(TriMeshType&m,HeapType&h_ret){ h_ret.clear(); typename TriMeshType::FaceIterator fi; for(fi = m.face.begin(); fi != m.face.end();++fi) if(!(*fi).IsD()){ for (int j=0;j<3;j++) { EdgeType p=EdgeType::OrderedEdge(&*fi,j,(*fi).V(j)); h_ret.push_back(HeapElem(new MYTYPE(p,m.IMark()))); //printf("Inserting in heap coll %3i ->%3i %f\n",p.V()-&m.vert[0],p.VFlip()-&m.vert[0],h_ret.back().locModPtr->Priority()); } } } }; }//end namespace tri }//end namespace vcg #endif qutemol/vcg/vcg/complex/local_optimization/tri_edge_flip.h0000444000175000017500000003623011010044643022471 0ustar mbamba/**************************************************************************** * VCGLib o o * * Visual and Computer Graphics Library o o * * _ O _ * * Copyright(C) 2004 \/)\/ * * Visual Computing Lab /\/| * * ISTI - Italian National Research Council | * * \ * * All rights reserved. * * * * 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. * * * * 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 (http://www.gnu.org/licenses/gpl.txt) * * for more details. * * * ****************************************************************************/ #include #include #include namespace vcg { namespace tri { /** \addtogroup trimesh */ /* @{ */ /*! * This Class is specialization of LocalModification for the edge flip * It wraps the atomic operation EdgeFlip to be used in a optimization routine. * Note that it has knowledge of the heap of the class LocalOptimization because * it is responsible of updating it after a flip has been performed * This is the simplest edge flipping class. * It flips an edge only if two adjacent faces are coplanar and the * quality of the faces improves after the flip. */ template const & p0, Point3 const & p1, Point3 const & p2) = Quality> class PlanarEdgeFlip : public LocalOptimization< TRIMESH_TYPE>::LocModType { protected: typedef typename TRIMESH_TYPE::FaceType FaceType; typedef typename TRIMESH_TYPE::FacePointer FacePointer; typedef typename TRIMESH_TYPE::FaceIterator FaceIterator; typedef typename TRIMESH_TYPE::VertexType VertexType; typedef typename TRIMESH_TYPE::ScalarType ScalarType; typedef typename TRIMESH_TYPE::VertexPointer VertexPointer; typedef typename TRIMESH_TYPE::CoordType CoordType; typedef vcg::face::Pos PosType; typedef typename LocalOptimization::HeapElem HeapElem; typedef typename LocalOptimization::HeapType HeapType; /*! * the pos of the flipping */ PosType _pos; /*! * priority in the heap */ ScalarType _priority; /*! * Mark for updating */ int _localMark; /*! * mark for up_dating */ static int& GlobalMark() { static int im = 0; return im; } static void Insert(HeapType& heap, PosType& p, int mark) { if(!p.IsBorder() && p.F()->IsW() && p.FFlip()->IsW()) { MYTYPE* newflip = new MYTYPE(p, mark); heap.push_back(HeapElem(newflip)); std::push_heap(heap.begin(), heap.end()); } } public: /*! * Default constructor */ inline PlanarEdgeFlip() { } /*! * Constructor with pos type */ inline PlanarEdgeFlip(PosType pos, int mark) { _pos = pos; _localMark = mark; _priority = ComputePriority(); } /*! * Copy Constructor */ inline PlanarEdgeFlip(const PlanarEdgeFlip &par) { _pos = par.GetPos(); _localMark = par.GetMark(); _priority = par.Priority(); } /*! */ ~PlanarEdgeFlip() { } /*! * Parameter */ static ScalarType &CoplanarAngleThresholdDeg() { static ScalarType _CoplanarAngleThresholdDeg = 0.01f; return _CoplanarAngleThresholdDeg; } inline PosType GetPos() { return _pos; } inline int GetMark() { return _localMark; } /*! * Return the LocalOptimization type */ ModifierType IsOfType() { return TriEdgeFlipOp; } /*! * Check if the pos is updated */ bool IsUpToDate() { int lastMark = _pos.F()->V(0)->IMark(); lastMark = vcg::math::Max(lastMark, _pos.F()->V(1)->IMark()); lastMark = vcg::math::Max(lastMark, _pos.F()->V(2)->IMark()); return ( _localMark >= lastMark ); } /*! * Check if this flipping operation can be performed. It is a topological and geometrical check. */ virtual bool IsFeasible() { if(!vcg::face::CheckFlipEdge(*this->_pos.F(), this->_pos.E())) return false; if( math::ToDeg( Angle(_pos.FFlip()->cN(), _pos.F()->cN()) ) > CoplanarAngleThresholdDeg() ) return false; CoordType v0, v1, v2, v3; int i = _pos.E(); v0 = _pos.F()->P0(i); v1 = _pos.F()->P1(i); v2 = _pos.F()->P2(i); v3 = _pos.F()->FFp(i)->P2(_pos.F()->FFi(i)); // Take the parallelogram formed by the adjacent faces of edge // If a corner of the parallelogram on extreme of edge to flip is >= 180 // the flip produce two identical faces - avoid this if( (Angle(v2 - v0, v1 - v0) + Angle(v3 - v0, v1 - v0) >= M_PI) || (Angle(v2 - v1, v0 - v1) + Angle(v3 - v1, v0 - v1) >= M_PI)) return false; // if any of two faces adj to edge in non writable, the flip is unfeasible if(!_pos.F()->IsW() || !_pos.F()->FFp(i)->IsW()) return false; return true; } /*! * Compute the priority of this optimization */ /* 1 /|\ / | \ 2 | 3 \ | / \|/ 0 */ virtual ScalarType ComputePriority() { CoordType v0, v1, v2, v3; int i = _pos.E(); v0 = _pos.F()->P0(i); v1 = _pos.F()->P1(i); v2 = _pos.F()->P2(i); v3 = _pos.F()->FFp(i)->P2(_pos.F()->FFi(i)); ScalarType Qa = QualityFunc(v0, v1, v2); ScalarType Qb = QualityFunc(v0, v3, v1); ScalarType QaAfter = QualityFunc(v1, v2, v3); ScalarType QbAfter = QualityFunc(v0, v3, v2); // < 0 if the average quality of faces improves after flip _priority = (Qa + Qb - QaAfter - QbAfter) / 2.0; return _priority; } /*! * Return the priority of this optimization */ virtual ScalarType Priority() const { return _priority; } /*! * Execute the flipping of the edge */ void Execute(TRIMESH_TYPE &m) { int i = _pos.E(); int j = _pos.F()->FFi(i); FacePointer f1 = _pos.F(); FacePointer f2 = _pos.F()->FFp(i); vcg::face::FlipEdge(*_pos.F(), _pos.E()); // avoid texture coordinates swap after flip if(tri::HasPerWedgeTexCoord(m)) { f2->WT((j + 1) % 3) = f1->WT((i + 2) % 3); f1->WT((i + 1) % 3) = f2->WT((j + 2) % 3); } } /*! */ const char* Info(TRIMESH_TYPE &m) { static char dump[60]; sprintf(dump,"%ld -> %ld %g\n", _pos.F()->V(0)-&m.vert[0], _pos.F()->V(1)-&m.vert[0],-_priority); return dump; } /*! */ static void Init(TRIMESH_TYPE &mesh, HeapType &heap) { heap.clear(); FaceIterator fi; for(fi = mesh.face.begin(); fi != mesh.face.end(); ++fi) { if(!(*fi).IsD() && (*fi).IsW()) { for(unsigned int i = 0; i < 3; i++) { if( !(*fi).IsB(i) && !((*fi).FFp(i)->IsD()) && (*fi).FFp(i)->IsW() ) { if((*fi).V1(i) - (*fi).V0(i) > 0) { PosType p(&*fi, i); Insert(heap, p, mesh.IMark()); } //heap.push_back( HeapElem( new MYTYPE(PosType(&*fi, i), mesh.IMark() )) ); } //endif } //endfor } } //endfor } /*! */ virtual void UpdateHeap(HeapType &heap) { GlobalMark()++; // after flip, the new edge just created is the next edge int flipped = (_pos.E() + 1) % 3; PosType pos(_pos.F(), flipped); pos.F()->V(0)->IMark() = GlobalMark(); pos.F()->V(1)->IMark() = GlobalMark(); pos.F()->V(2)->IMark() = GlobalMark(); pos.F()->FFp(flipped)->V2(pos.F()->FFi(flipped))->IMark() = GlobalMark(); pos.FlipF(); pos.FlipE(); Insert(heap, pos, GlobalMark()); pos.FlipV(); pos.FlipE(); Insert(heap, pos, GlobalMark()); pos.FlipV(); pos.FlipE(); pos.FlipF(); pos.FlipE(); Insert(heap, pos, GlobalMark()); pos.FlipV(); pos.FlipE(); Insert(heap, pos, GlobalMark()); } }; // end of PlanarEdgeFlip class template class TriEdgeFlip : public PlanarEdgeFlip { protected: typedef typename TRIMESH_TYPE::FaceType FaceType; typedef typename TRIMESH_TYPE::ScalarType ScalarType; typedef typename TRIMESH_TYPE::CoordType CoordType; typedef vcg::face::Pos PosType; public: /*! * Default constructor */ inline TriEdgeFlip() {} /*! * Constructor with pos type */ inline TriEdgeFlip(const PosType pos, int mark) { this->_pos = pos; this->_localMark = mark; this->_priority = ComputePriority(); } /*! * Copy Constructor */ inline TriEdgeFlip(const TriEdgeFlip &par) { this->_pos = par.GetPos(); this->_localMark = par.GetMark(); this->_priority = par.Priority(); } ScalarType ComputePriority() { /* 1 /|\ / | \ 2 | 3 \ | / \|/ 0 */ CoordType v0, v1, v2, v3; int i = this->_pos.E(); v0 = this->_pos.F()->P0(i); v1 = this->_pos.F()->P1(i); v2 = this->_pos.F()->P2(i); v3 = this->_pos.F()->FFp(i)->P2(this->_pos.F()->FFi(i)); // if the sum of angles in v2 e v3 is > 180, then the triangle // pair is not a delaunay triangulation ScalarType alpha = math::Abs(Angle(v0 - v2, v1 - v2)); ScalarType beta = math::Abs(Angle(v0 - v3, v1 - v3)); this->_priority = 180 - math::ToDeg((alpha + beta)); return this->_priority; } }; // This kind of flip minimize the variance of number of incident faces // on the vertices of two faces involved in the flip template class TopoEdgeFlip : public PlanarEdgeFlip { protected: typedef typename TRIMESH_TYPE::VertexPointer VertexPointer; typedef typename TRIMESH_TYPE::FaceType FaceType; typedef typename TRIMESH_TYPE::FacePointer FacePointer; typedef typename TRIMESH_TYPE::ScalarType ScalarType; typedef typename TRIMESH_TYPE::CoordType CoordType; typedef vcg::face::Pos PosType; typedef typename LocalOptimization::HeapElem HeapElem; typedef typename LocalOptimization::HeapType HeapType; typedef typename TRIMESH_TYPE::FaceIterator FaceIterator; typedef typename TRIMESH_TYPE::VertexIterator VertexIterator; public: /*! * Default constructor */ inline TopoEdgeFlip() {} /*! * Constructor with pos type */ inline TopoEdgeFlip(const PosType pos, int mark) { this->_pos = pos; this->_localMark = mark; this->_priority = ComputePriority(); } /*! * Copy Constructor */ inline TopoEdgeFlip(const TopoEdgeFlip &par) { this->_pos = par.GetPos(); this->_localMark = par.GetMark(); this->_priority = par.Priority(); } ScalarType ComputePriority() { /* 1 /|\ / | \ 2 | 3 \ | / \|/ 0 */ VertexPointer v0, v1, v2, v3; int i = this->_pos.E(); v0 = this->_pos.F()->V0(i); v1 = this->_pos.F()->V1(i); v2 = this->_pos.F()->V2(i); v3 = this->_pos.F()->FFp(i)->V2(this->_pos.F()->FFi(i)); // This kind of flip minimize the variance of number of incident faces // on the vertices of two faces involved in the flip ScalarType avg = (v0->Q() + v1->Q() + v2->Q() + v3->Q()) / 4.0; ScalarType varbefore = (powf(v0->Q() - avg, 2.0) + powf(v1->Q() - avg, 2.0) + powf(v2->Q() - avg, 2.0) + powf(v3->Q() - avg, 2.0)) / 4.0; ScalarType varafter = (powf(v0->Q() - 1 - avg, 2.0) + powf(v1->Q() - 1 - avg, 2.0) + powf(v2->Q() + 1 - avg, 2.0) + powf(v3->Q() + 1 - avg, 2.0)) / 4.0; this->_priority = varafter - varbefore; return this->_priority; } /*! * Execute the flipping of the edge */ void Execute(TRIMESH_TYPE &m) { int i = this->_pos.E(); FacePointer f1 = this->_pos.F(); FacePointer f2 = f1->FFp(i); int j = f1->FFi(i); // update the number of faces adjacent to vertices f1->V0(i)->Q()--; f1->V1(i)->Q()--; f1->V2(i)->Q()++; f2->V2(j)->Q()++; // do the flip vcg::face::FlipEdge(*this->_pos.F(), this->_pos.E()); // avoid texture coordinates swap after flip if (tri::HasPerWedgeTexCoord(m)) { f2->WT((j + 1) % 3) = f1->WT((i + 2) % 3); f1->WT((i + 1) % 3) = f2->WT((j + 2) % 3); } } static void Init(TRIMESH_TYPE &m, HeapType &heap) { // reset quality field for each vertex VertexIterator vi; for(vi = m.vert.begin(); vi != m.vert.end(); ++vi) if(!(*vi).IsD()) (*vi).Q() = 0; // for each vertex, put the number of incident faces in quality field FaceIterator fi; for(fi = m.face.begin(); fi != m.face.end(); ++fi) if(!(*fi).IsD()) for(int i = 0; i < 3; i++) (*fi).V(i)->Q()++; TriEdgeFlip::Init(m, heap); } void UpdateHeap(HeapType &heap) { this->GlobalMark()++; VertexPointer v0, v1, v2, v3; int flipped = (this->_pos.E() + 1) % 3; FacePointer f1 = this->_pos.F(); FacePointer f2 = this->_pos.F()->FFp(flipped); v0 = f1->V0(flipped); v1 = f1->V1(flipped); v2 = f1->V2(flipped); v3 = f2->V2(f1->FFi(flipped)); v0->IMark() = this->GlobalMark(); v1->IMark() = this->GlobalMark(); v2->IMark() = this->GlobalMark(); v3->IMark() = this->GlobalMark(); // edges of the first face, except the flipped edge for(int i = 0; i < 3; i++) if(i != flipped) { PosType newpos(f1, i); Insert(heap, newpos, this->GlobalMark()); } // edges of the second face, except the flipped edge for(int i = 0; i < 3; i++) if(i != f1->FFi(flipped)) { PosType newpos(f2, i); Insert(heap, newpos, this->GlobalMark()); } // every edge with v0, v1 v3 of f1 for(int i = 0; i < 3; i++) { PosType startpos(f1, i); PosType pos(startpos); do { // go to the first border (if there is one) pos.NextE(); } while(pos != startpos && !pos.IsBorder()); // if a border is reached, set startpos here if(pos.IsBorder()) startpos = pos; do { VertexPointer v = pos.VFlip(); if(v != v0 && v != v1 && v != v2 && v != v3) Insert(heap, pos, this->GlobalMark()); pos.NextE(); } while(pos != startpos && !pos.IsBorder()); } PosType startpos(f2, (f1->FFi(flipped) + 2) % 3); PosType pos(startpos); do { // go to the first border (if there is one) pos.NextE(); } while(pos != startpos && !pos.IsBorder()); // if a border is reached, set startpos here if(pos.IsBorder()) startpos = pos; do { VertexPointer v = pos.VFlip(); if(v != v0 && v != v1 && v != v2 && v != v3) Insert(heap, pos, this->GlobalMark()); pos.NextE(); } while(pos != startpos && !pos.IsBorder()); } }; } // end of namespace tri } // end of namespace vcg qutemol/vcg/vcg/complex/local_optimization.h0000444000175000017500000003103210556471051017703 0ustar mbamba/**************************************************************************** * VCGLib o o * * Visual and Computer Graphics Library o o * * _ O _ * * Copyright(C) 2004 \/)\/ * * Visual Computing Lab /\/| * * ISTI - Italian National Research Council | * * \ * * All rights reserved. * * * * 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. * * * * 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 (http://www.gnu.org/licenses/gpl.txt) * * for more details. * * * ****************************************************************************/ /**************************************************************************** $Log: local_optimization.h,v $ Revision 1.21 2007/01/26 21:27:05 cignoni Corrected ClearHeap Bug (thanks to pirosu) Revision 1.20 2007/01/19 09:13:09 cignoni Added Finalize() method to the interface Revision 1.19 2007/01/11 11:48:33 ganovelli currMetric inizialied to heap.front() (it was heap.back()- wrong) Revision 1.18 2006/12/11 14:09:44 ganovelli added missing initialization of currMetric Revision 1.17 2006/06/09 07:28:43 m_di_benedetto Corrected ClearHeap(): iterator "hi" not decrementable if it was the first of the container. Revision 1.16 2005/11/10 15:38:46 cignoni Added casts to remove warnings Revision 1.15 2005/10/02 23:23:52 cignoni Changed the sense of the < operator for heap: it is reversed according to the stl where highest score elements must float in the heap Completed TimeBudget Termination condition. Parametrized the ClearHeap procedure now there is a HeapSimplexRatio param. Removed dirty printf. Revision 1.14 2005/04/14 11:34:33 ponchio *** empty log message *** Revision 1.13 2005/01/19 10:33:50 cignoni Improved ClearHeap management Revision 1.12 2004/12/10 01:02:48 cignoni added an inline and removed loggng Revision 1.11 2004/12/03 21:14:39 ponchio Fixed memory leak... Revision 1.10 2004/11/23 10:37:17 cignoni Added a member with a cached copy of the floating Priority() value inside the HeapElem to optimize operator< in heap updating operator Revision 1.9 2004/11/05 10:03:47 fiorin Added ModifierType::TriEdgeFlipOp Revision 1.8 2004/10/25 07:02:56 ganovelli some inline function, logs on file (precompiler directive) Revision 1.7 2004/09/29 17:08:39 ganovelli changed > to < in heapelem comparison Revision 1.6 2004/09/28 09:57:08 cignoni Better Doxygen docs Revision 1.5 2004/09/15 10:40:20 ponchio typedef LocalOptimization HeapType -> public: Revision 1.4 2004/09/08 15:10:59 ganovelli *** empty log message *** Revision 1.3 2004/07/27 09:46:15 cignoni First working version of the LocalOptimization/Simplification Framework Revision 1.1 2004/07/15 12:04:14 ganovelli minor changes Revision 1.2 2004/07/09 10:22:56 ganovelli working draft Revision 1.1 2004/07/08 08:25:15 ganovelli first draft ****************************************************************************/ #ifndef __VCGLIB_LOCALOPTIMIZATION #define __VCGLIB_LOCALOPTIMIZATION #include #include #include #include namespace vcg{ template class LocalOptimization; enum ModifierType{ TetraEdgeCollapseOp, TriEdgeSwapOp, TriVertexSplitOp, TriEdgeCollapseOp,TetraEdgeSpliOpt,TetraEdgeSwapOp, TriEdgeFlipOp}; /** \addtogroup tetramesh */ /*@{*/ /// This abstract class define which functions a local modification to be used in the LocalOptimization. template class LocalModification { public: typedef typename LocalOptimization::HeapType HeapType; typedef typename MeshType::ScalarType ScalarType; inline LocalModification(){}; virtual ~LocalModification(){}; /// return the type of operation virtual ModifierType IsOfType() = 0 ; /// return true if the data have not changed since it was created virtual bool IsUpToDate() = 0 ; /// return true if no constraint disallow this operation to be performed (ex: change of topology in edge collapses) virtual bool IsFeasible() = 0; /// Compute the priority to be used in the heap virtual ScalarType ComputePriority()=0; /// Return the priority to be used in the heap (implement static priority) virtual ScalarType Priority() const =0; /// Perform the operation and return the variation in the number of simplicies (>0 is refinement, <0 is simplification) virtual void Execute(MeshType &m)=0; /// perform initialization static void Init(MeshType &m, HeapType&); virtual const char *Info(MeshType &) {return 0;} /// Update the heap as a consequence of this operation virtual void UpdateHeap(HeapType&)=0; }; //end class local modification /// LocalOptimization: /// This class implements the algorihms running on 0-1-2-3-simplicial complex that are based on local modification /// The local modification can be and edge_collpase, or an edge_swap, a vertex plit...as far as they implement /// the interface defined in LocalModification. /// Implementation note: in order to keep the local modification itself indepented by its use in this class, they are not /// really derived by LocalModification. Instead, a wrapper is done to this purpose (see vcg/complex/tetramesh/decimation/collapse.h) template class LocalOptimization { public: LocalOptimization(MeshType &mm): m(mm){ ClearTermination();e=0.0;HeapSimplexRatio=5;} struct HeapElem; // scalar type typedef typename MeshType::ScalarType ScalarType; // type of the heap typedef typename std::vector HeapType; // modification type typedef LocalModification LocModType; // modification Pointer type typedef LocalModification * LocModPtrType; /// termination conditions enum LOTermination { LOnSimplices = 0x01, // test number of simplicies LOnVertices = 0x02, // test number of verticies LOnOps = 0x04, // test number of operations LOMetric = 0x08, // test Metric (error, quality...instance dependent) LOTime = 0x10 // test how much time is passed since the start } ; int tf; int nPerfmormedOps, nTargetOps, nTargetSimplices, nTargetVertices; float timeBudget; int start; ScalarType currMetric; ScalarType targetMetric; // The ratio between Heap size and the number of simplices in the current mesh // When this value is exceeded a ClearHeap Start; float HeapSimplexRatio; void SetTerminationFlag (int v){tf |= v;} void ClearTerminationFlag (int v){tf &= ~v;} bool IsTerminationFlag (int v){return ((tf & v)!=0);} void SetTargetSimplices (int ts ){nTargetSimplices = ts; SetTerminationFlag(LOnSimplices); } void SetTargetVertices (int tv ){nTargetVertices = tv; SetTerminationFlag(LOnVertices); } void SetTargetOperations(int to ){nTargetOps = to; SetTerminationFlag(LOnOps); } void SetTargetMetric (ScalarType tm ){targetMetric = tm; SetTerminationFlag(LOMetric); } void SetTimeBudget (float tb ){timeBudget = tb; SetTerminationFlag(LOTime); } void ClearTermination() { tf=0; nTargetSimplices=0; nTargetOps=0; targetMetric=0; timeBudget=0; nTargetVertices=0; } /// the mesh to optimize MeshType & m; ///the heap of operations HeapType h; ///the element of the heap // it is just a wrapper of the pointer to the localMod. // std heap does not work for // pointers and we want pointers to have heterogenous heaps. struct HeapElem { inline HeapElem(){locModPtr = NULL;} ~HeapElem(){} ///pointer to instance of local modifier LocModPtrType locModPtr; float pri; inline HeapElem( LocModPtrType _locModPtr) { locModPtr = _locModPtr; pri=float(locModPtr->Priority()); }; /// STL heap has the largest element as the first one. /// usually we mean priority as an error so we should invert the comparison inline const bool operator <(const HeapElem & h) const { return (pri > h.pri); //return (locModPtr->Priority() < h.locModPtr->Priority()); } bool IsUpToDate() { return locModPtr->IsUpToDate(); } }; /// Default distructor ~LocalOptimization(){ typename HeapType::iterator i; for(i = h.begin(); i != h.end(); i++) delete (*i).locModPtr; }; double e; /// main cycle of optimization bool DoOptimization() { start=clock(); nPerfmormedOps =0; while( !GoalReached() && !h.empty()) { if(h.size()> m.SimplexNumber()*HeapSimplexRatio ) ClearHeap(); std::pop_heap(h.begin(),h.end()); LocModPtrType locMod = h.back().locModPtr; currMetric=h.back().pri; h.pop_back(); if( locMod->IsUpToDate() ) { //printf("popped out: %s\n",locMod->Info(m)); // check if it is feasible if (locMod->IsFeasible()) { nPerfmormedOps++; locMod->Execute(m); locMod->UpdateHeap(h); } } //else printf("popped out unfeasible\n"); delete locMod; } return !(h.empty()); } // It removes from the heap all the operations that are no more 'uptodate' // (e.g. collapses that have some recently modified vertices) // This function is called from time to time by the doOptimization (e.g. when the heap is larger than fn*3) void ClearHeap() { typename HeapType::iterator hi; //int sz=h.size(); for(hi=h.begin();hi!=h.end();) { if(!(*hi).locModPtr->IsUpToDate()) { delete (*hi).locModPtr; *hi=h.back(); if(&*hi==&h.back()) { hi=h.end(); h.pop_back(); break; } h.pop_back(); continue; } ++hi; } //printf("\nReduced heap from %7i to %7i (fn %7i) ",sz,h.size(),m.fn); make_heap(h.begin(),h.end()); } ///initialize for all vertex the temporary mark must call only at the start of decimation ///by default it takes the first element in the heap and calls Init (static funcion) of that type ///of local modification. template void Init() { m.InitVertexIMark(); LocalModificationType::Init(m,h); std::make_heap(h.begin(),h.end()); if(!h.empty()) currMetric=h.front().pri; } template void Finalize() { LocalModificationType::Finalize(m,h); } /// say if the process is to end or not: the process ends when any of the termination conditions is verified /// override this function to implemetn other tests bool GoalReached(){ assert ( ( ( tf & LOnSimplices )==0) || ( nTargetSimplices!= -1)); assert ( ( ( tf & LOnVertices )==0) || ( nTargetVertices != -1)); assert ( ( ( tf & LOnOps )==0) || ( nTargetOps != -1)); assert ( ( ( tf & LOMetric )==0) || ( targetMetric != -1)); assert ( ( ( tf & LOTime )==0) || ( timeBudget != -1)); if ( IsTerminationFlag(LOnSimplices) && ( m.SimplexNumber()<= nTargetSimplices)) return true; if ( IsTerminationFlag(LOnVertices) && ( m.VertexNumber() <= nTargetVertices)) return true; if ( IsTerminationFlag(LOnOps) && (nPerfmormedOps == nTargetOps)) return true; if ( IsTerminationFlag(LOMetric) && ( currMetric > targetMetric)) return true; if ( IsTerminationFlag(LOTime) && ( (clock()-start)/(float)CLOCKS_PER_SEC > timeBudget)) return true; return false; } ///erase from the heap the operations that are out of date void ClearHeapOld() { typename HeapType::iterator hi; for(hi=h.begin();hi!=h.end();++hi) if(!(*hi).locModPtr->IsUpToDate()) { *hi=h.back(); h.pop_back(); if(hi==h.end()) break; } //printf("\nReduced heap from %i to %i",sz,h.size()); make_heap(h.begin(),h.end()); } };//end class decimation }//end namespace #endif qutemol/vcg/vcg/complex/vertexmesh/0000755000175000017500000000000011633404241016021 5ustar mbambaqutemol/vcg/vcg/complex/vertexmesh/base.h0000444000175000017500000001261310575271733017121 0ustar mbamba/**************************************************************************** * VCGLib o o * * Visual and Computer Graphics Library o o * * _ O _ * * Copyright(C) 2004 \/)\/ * * Visual Computing Lab /\/| * * ISTI - Italian National Research Council | * * \ * * All rights reserved. * * * * 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. * * * * 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 (http://www.gnu.org/licenses/gpl.txt) * * for more details. * * * ****************************************************************************/ /**************************************************************************** History $Log: base.h,v $ Revision 1.6 2007/03/12 15:38:03 tarini Texture coord name change! "TCoord" and "Texture" are BAD. "TexCoord" is GOOD. Revision 1.5 2006/08/23 16:49:25 marfr960 added typedef VertContainer VertexContainer to avoid inconsistency with pre-existing methods Revision 1.4 2006/08/23 15:32:24 marfr960 added bbox of the mesh vn int->size_t Revision 1.3 2005/09/20 13:58:55 pietroni Modified MArk function parameter form ConstVertexPointer to VertexPointer Revision 1.2 2005/08/02 11:37:29 pietroni renamed typedef VertexContainer into VertContainer (like trimesh) Revision 1.1 2005/03/09 13:22:55 ganovelli creation ****************************************************************************/ #pragma warning( disable : 4804 ) #include #include /* People should subclass his vertex class from these one... */ #ifndef __VCGLIB_VERTEXMESH #define __VCGLIB_VERTEXMESH namespace vcg { namespace vertex { /** \addtogroup vertexmesh */ /*@{*/ /** \class VertexMesh. This is class for definition of a mesh. @param VertContainerType (Template Parameter) Specifies the type of the vertices container any the vertex type. */ template < class VertContainerType > class VertexMesh{ public: typedef VertContainerType VertContainer; typedef VertContainer VertexContainer; typedef typename VertContainerType::value_type VertexType; typedef typename VertContainerType::value_type::ScalarType ScalarType; typedef typename VertContainerType::value_type::CoordType CoordType; typedef typename VertContainerType::iterator VertexIterator; typedef typename VertContainerType::const_iterator ConstVertexIterator; typedef VertexType * VertexPointer; typedef const VertexType * ConstVertexPointer; typedef Box3 BoxType; VertContainerType vert; /// Set of vertices size_t vn; /// Actual number of vertices Box3 bbox; /// Bounding box of the mesh private: Color4b c; /// Global color public: inline const Color4b & C() const { return c; } inline Color4b & C() { return c; } /// Default constructor VertexMesh() { vn = 0; imark = 0; } inline int MemUsed() const { return sizeof(VertexMesh)*vert.size(); } inline int MemNeeded() const { return sizeof(VertexMesh)*vn; } /// Function to destroy the mesh void Clear() { vert.clear(); vn = 0; } /// Reflection functions that speak about vertex and face properties. static bool HasPerVertexNormal() { return VertexType::HasNormal() ; } static bool HasPerVertexColor() { return VertexType::HasColor() ; } static bool HasPerVertexMark() { return VertexType::HasMark() ; } static bool HasPerVertexQuality() { return VertexType::HasQuality(); } static bool HasPerVertexTexCoord(){ return VertexType::HasTexCoord(); } /// Initialize the imark-system of the faces void InitPointIMark() { VertexIterator f; for(f=vert.begin();f!=vert.end();++f) if( !(*f).IsDeleted() && (*f).IsR() && (*f).IsW() ) (*f).InitIMark(); } /// Initialize the imark-system of the vertices void InitVertexIMark() { VertexIterator vi; for(vi=vert.begin();vi!=vert.end();++vi) if( !(*vi).IsDeleted() && (*vi).IsRW() ) (*vi).InitIMark(); } /// The incremental mark int imark; /** Check if the vertex incremental mark matches the one of the mesh. */ inline bool IsMarked( ConstVertexPointer v ) const { return v->IMark() == imark; } /** Set the vertex incremental mark of the vertex to the one of the mesh. */ inline void Mark( VertexPointer v ) const { v->IMark() = imark; } /// Unmark the mesh inline void UnMarkAll() { ++imark; } }; // end class VertexMesh /*@}*/ } // end namespace } // end namespace #endif qutemol/vcg/vcg/complex/vertexmesh/closest.h0000444000175000017500000001344410627517220017656 0ustar mbamba/**************************************************************************** * VCGLib o o * * Visual and Computer Graphics Library o o * * _ O _ * * Copyright(C) 2004 \/)\/ * * Visual Computing Lab /\/| * * ISTI - Italian National Research Council | * * \ * * All rights reserved. * * * * 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. * * * * 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 (http://www.gnu.org/licenses/gpl.txt) * * for more details. * * * ****************************************************************************/ #ifndef __VCG_VERTEXMESH_CLOSEST #define __VCG_VERTEXMESH_CLOSEST #include #include #include #include #include #include #include #include #include namespace vcg { namespace vertex { //**MARKER CLASSES**// template class Tmark { MESH_TYPE *m; public: Tmark(){} void UnMarkAll(){m->UnMarkAll();} bool IsMarked(OBJ_TYPE* obj){return (m->IsMarked(obj));} void Mark(OBJ_TYPE* obj){m->Mark(obj);} void SetMesh(MESH_TYPE *_m) {m=_m;} }; template class VertTmark:public Tmark {}; //**CLOSEST FUNCTION DEFINITION**// /* aka MetroCore data una mesh m e una ug sulle sue facce trova il punto di m piu' vicino ad un punto dato. */ // input: mesh, punto, griglia (gr), distanza limite (mdist) // output: normale (interpolata) alla faccia e punto piu' vicino su di essa, e coord baricentriche del punto trovato // Nota che il parametro template GRID non ci dovrebbe essere, visto che deve essere // UGrid, ma non sono riuscito a definirlo implicitamente template typename MESH::VertexType * GetClosestVertex( MESH & mesh,GRID & gr,const typename GRID::CoordType & _p, const typename GRID::ScalarType & _maxDist,typename GRID::ScalarType & _minDist ) { typedef typename GRID::ScalarType ScalarType; typedef Point3 Point3x; typedef VertTmark MarkerVert; MarkerVert mv; mv.SetMesh(&mesh); typedef PointDistanceFunctor VDistFunct; _minDist=_maxDist; Point3x _closestPt; return (gr.GetClosest(PointDistanceFunctor(),mv,_p,_maxDist,_minDist,_closestPt)); } template unsigned int GetKClosestVertex(MESH & mesh,GRID & gr, const unsigned int _k, const typename GRID::CoordType & _p, const typename GRID::ScalarType & _maxDist, OBJPTRCONTAINER & _objectPtrs,DISTCONTAINER & _distances, POINTCONTAINER & _points) { typedef VertTmark MarkerVert; MarkerVert mv; mv.SetMesh(&mesh); typedef vcg::vertex::PointDistanceFunctor VDistFunct; return (gr.GetKClosest/**/ (VDistFunct(),mv,_k,_p,_maxDist,_objectPtrs,_distances,_points)); } template unsigned int GetInSphereVertex(MESH & mesh, GRID & gr, const typename GRID::CoordType & _p, const typename GRID::ScalarType & _r, OBJPTRCONTAINER & _objectPtrs, DISTCONTAINER & _distances, POINTCONTAINER & _points) { typedef VertTmark MarkerVert; MarkerVert mv; mv.SetMesh(&mesh); typedef vcg::vertex::PointDistanceFunctor VDistFunct; return (gr.GetInSphere/**/ (VDistFunct(),mv,_p,_r,_objectPtrs,_distances,_points)); } template unsigned int GetInBoxVertex(MESH & mesh, GRID & gr, const vcg::Box3 _bbox, OBJPTRCONTAINER & _objectPtrs) { typedef VertTmark MarkerVert; MarkerVert mv; mv.SetMesh(&mesh); return(gr.GetInBox(mv,_bbox,_objectPtrs)); } //**ITERATORS DEFINITION**// template class ClosestVertexIterator:public vcg::ClosestIterator > { public: typedef GRID GridType; typedef MESH MeshType; typedef VertTmark MarkerVert; typedef vcg::vertex::PointDistanceFunctor VDistFunct; typedef vcg::ClosestIterator > ClosestBaseType; ClosestVertexIterator(GridType &_Si):ClosestBaseType(_Si,VDistFunct()){} void SetMesh(MeshType *m) {tm.SetMesh(m);} }; } // end namespace vertex } // end namespace vcg #endif qutemol/vcg/vcg/complex/vertexmesh/allocate.h0000444000175000017500000001024010213574257017761 0ustar mbamba/**************************************************************************** * VCGLib o o * * Visual and Computer Graphics Library o o * * _ O _ * * Copyright(C) 2004 \/)\/ * * Visual Computing Lab /\/| * * ISTI - Italian National Research Council | * * \ * * All rights reserved. * * * * 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. * * * * 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 (http://www.gnu.org/licenses/gpl.txt) * * for more details. * * * ****************************************************************************/ /**************************************************************************** History $Log: allocate.h,v $ Revision 1.1 2005/03/09 13:22:55 ganovelli creation ****************************************************************************/ #ifndef __VCGLIB_VERTEXALLOCATOR #define __VCGLIB_VERTEXALLOCATOR namespace vcg { namespace vertex { /** \addtogroup vertexmesh */ /*@{*/ /// Class to safely add vertexes and faces to a mesh updating all the involved pointers. /// It provides static memeber to add either vertex or faces to a edgemesh. template class Allocator { public: typedef AllocateMeshType MeshType; typedef typename MeshType::VertexType VertexType; typedef typename MeshType::VertexPointer VertexPointer; typedef typename MeshType::VertexIterator VertexIterator; /** This class is used when allocating new vertexes and faces to update the pointers that can be changed when resizing the involved vectors of vertex or faces. It can also be used to prevent any update of the various mesh fields (e.g. in case you are building all the connections by hand as in a importer); */ template class PointerUpdater { public: void Clear(){newBase=oldBase=newEnd=oldEnd=0;preventUpdateFlag=false;}; void Update(SimplexPointerType &vp) { vp=newBase+(vp-oldBase); } bool NeedUpdate() {if(newBase!=oldBase && !preventUpdateFlag) return true; else return false;} SimplexPointerType oldBase; SimplexPointerType newBase; SimplexPointerType newEnd; SimplexPointerType oldEnd; bool preventUpdateFlag; /// when true no update is considered necessary. }; /** Function to safely add n vertices to a mesh. @param m The mesh to be expanded @param n the number of vertexes to be added @param pu A PointerUpdater that stores the relocation that can be happened. */ static VertexIterator AddVertices(MeshType &m,int n, PointerUpdater &pu) { VertexIterator last=m.vert.end(); pu.Clear(); if(m.vert.empty()) pu.oldBase=0; // if the vector is empty we cannot find the last valid element else pu.oldBase=&*m.vert.begin(); for(int i=0; i pu; return AddVertices(m, n,pu); } }; // end class /*@}*/ } // End Namespace TriMesh } // End Namespace vcg #endif qutemol/vcg/vcg/complex/vertexmesh/update/0000755000175000017500000000000011633404241017303 5ustar mbambaqutemol/vcg/vcg/complex/vertexmesh/update/normal.h0000444000175000017500000000555410517130114020746 0ustar mbamba/**************************************************************************** * VCGLib o o * * Visual and Computer Graphics Library o o * * _ O _ * * Copyright(C) 2004 \/)\/ * * Visual Computing Lab /\/| * * ISTI - Italian National Research Council | * * \ * * All rights reserved. * * * * 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. * * * * 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 (http://www.gnu.org/licenses/gpl.txt) * * for more details. * * * ****************************************************************************/ /**************************************************************************** History $Log: normal.h,v $ Revision 1.2 2006/10/23 12:06:36 ganovelli added history in the file ****************************************************************************/ #ifndef __VCG_VERTEXMESH_UPDATE_NORMAL #define __VCG_VERTEXMESH_UPDATE_NORMAL #include namespace vcg { namespace vertex { /** \addtogroup vertexmesh */ /* @{ */ /*! * This class is used to update the normals of a Vertex mesh */ template < class VERTEX_CONTAINER > class UpdateNormal { public: typedef VERTEX_CONTAINER VertexContainer; typedef typename VERTEX_CONTAINER::value_type VertexType; typedef typename VertexType::ScalarType ScalarType; typedef typename VERTEX_CONTAINER::iterator VertexIterator; /*! */ static void UpdateNormals(const VertexIterator &begin, const VertexIterator &end, int k) { vcg::NormalExtrapolation< VertexContainer >::ExtrapolateNormlas(begin, end, k); }; }; //end of class UpdateNormal /*! @} */ }; //end of namespace vertex }; //end of namespace vcg #endif //__VCG_VERTEXMESH_UPDATE_NORMAL qutemol/vcg/vcg/complex/vertexmesh/update/bounding.h0000444000175000017500000000621310473103540021260 0ustar mbamba/**************************************************************************** * VCGLib o o * * Visual and Computer Graphics Library o o * * _ O _ * * Copyright(C) 2004 \/)\/ * * Visual Computing Lab /\/| * * ISTI - Italian National Research Council | * * \ * * All rights reserved. * * * * 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. * * * * 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 (http://www.gnu.org/licenses/gpl.txt) * * for more details. * * * ****************************************************************************/ /**************************************************************************** History $Log: bounding.h,v $ Revision 1.4 2006/08/23 16:50:40 marfr960 minor changes Revision 1.2 2006/06/29 13:02:38 ganovelli agiunta UpdateBoundingBase, superclasse di UpdateBounding, templated sul container di vertici. Revision 1.1 2005/03/09 13:22:55 ganovelli creation ****************************************************************************/ #ifndef __VCG_POINT_UPDATE_BOUNDING #define __VCG_POINT_UPDATE_BOUNDING #include namespace vcg { namespace vertex { /** \addtogroup vertexmesh */ /*@{*/ template class UpdateBoundingBase { public: typedef typename VERTEX_CONTAINER::value_type VertexType; typedef typename VERTEX_CONTAINER::value_type* VertexPointer; typedef typename VERTEX_CONTAINER::iterator VertexIterator; typedef typename VERTEX_CONTAINER::value_type::ScalarType ScalarType; static Box3 Box(VERTEX_CONTAINER &vert) { Box3 res; res.SetNull(); VertexIterator vi; for(vi= vert.begin();vi!= vert.end();++vi) if( !(*vi).IsD() ) res.Add((*vi).P()); return res; } }; // end class UpdateBoundingBase template class UpdateBounding: public UpdateBoundingBase { public: static void Box(VMType &vm) { vm.bbox = UpdateBoundingBase::Box(vm.vert); } }; } // End namespace vertex } // End namespace vcg #endif qutemol/vcg/vcg/complex/vertexmesh/update/position.h0000444000175000017500000000605210450747655021340 0ustar mbamba/**************************************************************************** * VCGLib o o * * Visual and Computer Graphics Library o o * * _ O _ * * Copyright(C) 2004 \/)\/ * * Visual Computing Lab /\/| * * ISTI - Italian National Research Council | * * \ * * All rights reserved. * * * * 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. * * * * 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 (http://www.gnu.org/licenses/gpl.txt) * * for more details. * * * ****************************************************************************/ /**************************************************************************** History $Log: position.h,v $ Revision 1.1 2006/06/29 13:03:41 ganovelli Initial commit Revision 1.1 2005/07/06 08:02:27 cignoni Initial commit ****************************************************************************/ #ifndef __VCG_VERTEX_UPDATE_POSITION #define __VCG_VERTEX_UPDATE_POSITION namespace vcg { namespace vertex { /** \addtogroup vertexmesh */ /*@{*/ /// This class is used to update vertex position according to a transformation matrix. template class UpdatePositionBase { public: typedef typename VERTEX_CONTAINER::value_type::ScalarType ScalarType; typedef typename VERTEX_CONTAINER::iterator VertexIterator; /// Multiply static void Matrix(VERTEX_CONTAINER &vert, const Matrix44 &mm) { VertexIterator vi; for(vi= vert.begin();vi!= vert.end();++vi) if(!(*vi).IsD()) (*vi).P()=mm*(*vi).cP(); } }; // end class template class UpdatePosition: public UpdatePositionBase { public: typedef typename VertexMeshType::VertexContainer VertexContainer; static void Matrix(VertexMeshType &vm, const Matrix44 &mm) { UpdatePositionBase::Matrix(vm.vert,mm); } }; } // End namespace } // End namespace #endif qutemol/vcg/vcg/complex/intersection.h0000444000175000017500000002225610674211437016522 0ustar mbamba/**************************************************************************** * VCGLib o o * * Visual and Computer Graphics Library o o * * _ O _ * * Copyright(C) 2004 \/)\/ * * Visual Computing Lab /\/| * * ISTI - Italian National Research Council | * * \ * * All rights reserved. * * * * 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. * * * * 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 (http://www.gnu.org/licenses/gpl.txt) * * for more details. * * * ****************************************************************************/ /**************************************************************************** History $Log: intersection.h,v $ Revision 1.12 2007/09/19 12:16:31 giec Overloaded Intersection function to compute trimesh-plane intersection,it return the set of faces that are contained into intersected cells. Revision 1.11 2007/05/02 13:25:45 zifnab1974 only use typename when necessary Revision 1.10 2007/04/10 22:46:57 pietroni - line 152 changed call intersection to IntersectionPlaneTriangle because changing in function's name Revision 1.9 2007/01/03 15:51:28 pietroni added initial define and included missing files Revision 1.8 2006/01/19 14:06:37 spinelli add std:: namespace... Revision 1.7 2005/10/03 16:18:15 spinelli add template parameter for spatialindexing struction Revision 1.6 2005/05/30 09:11:20 ganovelli header added, error in include Revision 1.3 2005/05/17 21:19:37 ganovelli some std::and typename missing (CRS4) Revision 1.2 2005/03/08 14:42:22 ganovelli added vcg header ****************************************************************************/ #include #include #include #include #include #include #include //#include #include #include #ifndef __VCGLIB_INTERSECTION_TRI_MESH #define __VCGLIB_INTERSECTION_TRI_MESH namespace vcg{ /** \addtogroup complex */ /*@{*/ /** Function computing the intersection between a grid and a plane. It returns all the cells intersected */ template < typename GridType,typename ScalarType> bool Intersect( GridType & grid,Plane3 plane, std::vector &cells){ Point3d p,_d; Plane3d pl; _d.Import(plane.Direction()); pl.SetDirection(_d); pl.SetOffset(plane.Offset()); for( int ax = 0; ax <3; ++ax) { int axis = ax; int axis0 = (axis+1)%3; int axis1 = (axis+2)%3; int i,j; Point3i pi; Segment3 seg; seg.P0().Import(grid.bbox.min); seg.P1().Import(grid.bbox.min); seg.P1()[axis] = grid.bbox.max[axis]; for(i = 0 ; i <= grid.siz[axis0]; ++i){ for(j = 0 ; j <= grid.siz[axis1]; ++j) { seg.P0()[axis0] = grid.bbox.min[axis0]+ (i+0.01) * grid.voxel[axis0] ; seg.P1()[axis0] = grid.bbox.min[axis0]+ (i+0.01) * grid.voxel[axis0]; seg.P0()[axis1] = grid.bbox.min[axis1]+ (j+0.01) * grid.voxel[axis1]; seg.P1()[axis1] = grid.bbox.min[axis1]+ (j+0.01) * grid.voxel[axis1]; if ( Intersection(pl,seg,p)) { pi[axis] = std::min(std::max(0,(int)floor((p[axis ]-grid.bbox.min[axis])/grid.voxel[axis])),grid.siz[axis]); pi[axis0] = i; pi[axis1] = j; grid.Grid(pi,axis,cells); } } } } sort(cells.begin(),cells.end()); cells.erase(unique(cells.begin(),cells.end()),cells.end()); return false; } /*@}*/ /** \addtogroup complex */ /*@{*/ /** Function computing the intersection between a trimesh and a plane. It returns an EdgeMesh. Note: This version always returns a segment for each triangle of the mesh which intersects with the plane. In other words there are 2*n vertices where n is the number of segments fo the mesh. You can run vcg::edge::Unify to unify the vertices closer that a given value epsilon. Note that, due to subtraction error during triangle plane intersection, it is not safe to put epsilon to 0. // TODO si dovrebbe considerare la topologia face-face della trimesh per derivare quella della edge mesh.. */ template < typename TriMeshType, typename EdgeMeshType, class ScalarType, class IndexingType > bool Intersection( /*TriMeshType & m, */ Plane3 pl, EdgeMeshType & em, double& ave_length, IndexingType *grid, typename std::vector< typename IndexingType::Cell* >& cells) { typedef typename TriMeshType::FaceContainer FaceContainer; typedef IndexingType GridType; typename EdgeMeshType::VertexIterator vi; typename TriMeshType::FaceIterator fi; std::vector v; v.clear(); Intersect(*grid,pl,cells); Segment3 seg; ave_length = 0.0; typename std::vector::iterator ic; typename GridType::Cell fs,ls; for(ic = cells.begin(); ic != cells.end();++ic) { grid->Grid(*ic,fs,ls); typename GridType::Link * lk = fs; while(lk != ls){ typename TriMeshType::FaceType & face = *(lk->Elem()); if(!face.IsS()) { face.SetS(); v.push_back(&face); if(vcg::IntersectionPlaneTriangle(pl,face,seg))// intersezione piano triangolo { face.SetS(); // add to em ave_length+=seg.Length(); vcg::edge::Allocator::AddEdges(em,1); vi = vcg::edge::Allocator::AddVertices(em,2); (*vi).P() = seg.P0(); em.edges.back().V(0) = &(*vi); vi++; (*vi).P() = seg.P1(); em.edges.back().V(1) = &(*vi); } }//endif lk++; }//end while } ave_length/=em.en; typename std::vector::iterator v_i; for(v_i=v.begin(); v_i!=v.end(); ++v_i) (*v_i)->ClearS(); return true; } /** \addtogroup complex */ /*@{*/ /** Compute the intersection between a trimesh and a plane. given a plane return the set of faces that are contained into intersected cells. */ template < typename TriMeshType, class ScalarType, class IndexingType > bool Intersection(Plane3 pl, IndexingType *grid, typename std::vector &v) { typedef typename TriMeshType::FaceContainer FaceContainer; typedef IndexingType GridType; typename TriMeshType::FaceIterator fi; v.clear(); typename std::vector< typename GridType::Cell* > cells; Intersect(*grid,pl,cells); typename std::vector::iterator ic; typename GridType::Cell fs,ls; for(ic = cells.begin(); ic != cells.end();++ic) { grid->Grid(*ic,fs,ls); typename GridType::Link * lk = fs; while(lk != ls){ typename TriMeshType::FaceType & face = *(lk->Elem()); v.push_back(&face); lk++; }//end while }//end for return true; } /*****************************************************************/ /*INTERSECTION RAY - MESH */ /* */ /* Intersection between a Ray and a Mesh. Returns a 3D Pointset! */ /*****************************************************************/ template < typename TriMeshType, class ScalarType> bool IntersectionRayMesh( /* Input Mesh */ TriMeshType * m, /* Ray */ const Line3 & ray, /* Intersect Point */ Point3 & hitPoint) { //typedef typename TriMeshType::FaceContainer FaceContainer; typename TriMeshType::FaceIterator fi; bool hit=false; if(m==0) return false; //TriMeshType::FaceIterator fi; //std::vector::iterator fi; ScalarType bar1,bar2,dist; Point3 p1; Point3 p2; Point3 p3; for(fi = m->face.begin(); fi != m->face.end(); ++fi) { p1=vcg::Point3( (*fi).P(0).X() ,(*fi).P(0).Y(),(*fi).P(0).Z() ); p2=vcg::Point3( (*fi).P(1).X() ,(*fi).P(1).Y(),(*fi).P(1).Z() ); p3=vcg::Point3( (*fi).P(2).X() ,(*fi).P(2).Y(),(*fi).P(2).Z() ); if(Intersection(ray,p1,p2,p3,bar1,bar2,dist)) { hitPoint= p1*(1-bar1-bar2) + p2*bar1 + p3*bar2; hit=true; } } return hit; } /*@}*/ } // end namespace vcg #endif qutemol/vcg/vcg/complex/boundary.h0000444000175000017500000001312510720526701015625 0ustar mbamba/**************************************************************************** * VCGLib o o * * Visual and Computer Graphics Library o o * * _ O _ * * Copyright(C) 2004 \/)\/ * * Visual Computing Lab /\/| * * ISTI - Italian National Research Council | * * \ * * All rights reserved. * * * * 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. * * * * 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 (http://www.gnu.org/licenses/gpl.txt) * * for more details. * * * ****************************************************************************/ /**************************************************************************** History $Log: boundary.h,v $ Revision 1.2 2007/11/20 09:49:53 ganovelli added missing newline at the end of file Revision 1.1 2007/07/31 12:31:34 ganovelli added ****************************************************************************/ #ifndef __VCG_TETRA_TRI_CONVERTER #define __VCG_TETRA_TRI_CONVERTER #include #include #include #include namespace vcg { /** Class Boundary. This is class for exporting the boundary of a d simplicial complex as a d-1 simplicial complex */ class Boundary{ public: ///this function build a triangle mesh using the same pointers to the tetrahedral mesh vertex template static void OfTetramesh(TetraContainer &tetra,TriangleMeshType &trim) { typedef typename TetraContainer::iterator TetraIterator; typedef typename TetraContainer::value_type TetraVertexType; typedef typename TriangleMeshType::FaceType FaceType; typedef typename TriangleMeshType::VertexType TriangleVertexType; TetraIterator ti; TetraVertexType *v0; TetraVertexType *v2; trim.Clear(); for (ti=tetra.begin();tiIsD())) { if ((ti->IsBorderF(0))||(ti->IsBorderF(1))||(ti->IsBorderF(2))||(ti->IsBorderF(3))) for (int i=0;i<4;i++) if (ti->IsBorderF(i)) { FaceType f=FaceType(); f.ClearFlags(); f.V(0)=(TriangleVertexType*)ti->V(Tetra::VofF(i,0)); f.V(1)=(TriangleVertexType*)ti->V(Tetra::VofF(i,1)); f.V(2)=(TriangleVertexType*)ti->V(Tetra::VofF(i,2)); trim.face.push_back(f); } } } } template struct InsertedV{ typedef typename TriVertexType::FaceType FaceType; InsertedV( TriVertexType *_v, FaceType* _f,int _z):v(_v),f(_f),z(_z){} TriVertexType *v; FaceType* f; int z; const bool operator <(const InsertedV & o){ return (v static void OfTetrameshCopy(TetraContainer &tetra,TriangleMeshType &trim) { typedef typename TetraContainer::iterator TetraIterator; typedef typename TetraContainer::value_type::VertexType TetraVertexType; typedef typename TriangleMeshType::FaceType FaceType; typedef typename TriangleMeshType::FaceIterator FaceIterator; typedef typename TriangleMeshType::VertexIterator TriVertexIterator; typedef typename TriangleMeshType::VertexType TriVertexType; vector > newVertices; typename vector >::iterator curr,next; TriVertexIterator vi; vector redirect; OfTetramesh(tetra,trim); FaceIterator fi; for(fi = trim.face.begin(); fi != trim.face.end(); ++fi){ newVertices.push_back(InsertedV( (*fi).V(0),&(*fi),0)); newVertices.push_back(InsertedV( (*fi).V(1),&(*fi),1)); newVertices.push_back(InsertedV( (*fi).V(2),&(*fi),2)); } sort(newVertices.begin(),newVertices.end()); int pos = 0; curr = next = newVertices.begin(); while( next != newVertices.end()){ if((*curr)!=(*next)) pos++; (*next).f->V( (*next).z) = (TriVertexType*)pos; curr = next; next++; } typename vector >::iterator newE = unique(newVertices.begin(),newVertices.end()); for(curr = newVertices.begin();curr!= newE;++curr) trim.vert.push_back(*((*curr).v)); for(vi = trim.vert.begin(); vi != trim.vert.end(); ++vi) redirect.push_back(&(*vi)); for(fi = trim.face.begin(); fi != trim.face.end(); ++fi){ (*fi).V(0) = redirect[(int)(*fi).V(0)]; (*fi).V(1) = redirect[(int)(*fi).V(1)]; (*fi).V(2) = redirect[(int)(*fi).V(2)]; } trim.vn = trim.vert.size(); trim.fn = trim.face.size(); } };// End class } // End namespace #endif qutemol/vcg/vcg/complex/edgemesh/0000755000175000017500000000000011633404241015410 5ustar mbambaqutemol/vcg/vcg/complex/edgemesh/base.h0000444000175000017500000001555010624316440016501 0ustar mbamba/**************************************************************************** * VCGLib o o * * Visual and Computer Graphics Library o o * * _ O _ * * Copyright(C) 2004 \/)\/ * * Visual Computing Lab /\/| * * ISTI - Italian National Research Council | * * \ * * All rights reserved. * * * * 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. * * * * 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 (http://www.gnu.org/licenses/gpl.txt) * * for more details. * * * ****************************************************************************/ /**************************************************************************** History $Log: base.h,v $ Revision 1.8 2007/05/21 13:22:40 cignoni Corrected gcc compiling issues Revision 1.7 2007/03/12 15:38:02 tarini Texture coord name change! "TCoord" and "Texture" are BAD. "TexCoord" is GOOD. Revision 1.6 2005/09/14 14:09:16 spinelli ConstVertexPointer --> VertexPointer ConstEdgePointer --> EdgePointer Revision 1.5 2005/05/17 21:19:37 ganovelli some std::and typename missing (CRS4) Revision 1.4 2004/10/28 00:47:42 cignoni Better Doxygen documentation Revision 1.3 2004/09/20 09:30:03 cignoni Better Doxygen docs Revision 1.2 2004/05/10 14:41:45 ganovelli name of adhacency function updated Revision 1.1 2004/04/26 19:10:04 ganovelli created ****************************************************************************/ #pragma warning( disable : 4804 ) /* People should subclass his vertex class from these one... */ #ifndef __VCGLIB_EDGEMESH #define __VCGLIB_EDGEMESH namespace vcg { namespace edge { /** \addtogroup edgemesh */ /*@{*/ /** \class EdgeMesh. This is class for definition of a mesh. @param VertContainerType (Template Parameter) Specifies the type of the vertices container any the vertex type. @param EdgeContainerType (Template Parameter) Specifies the type of the faces container any the face type. */ template < class VertContainerType, class EdgeContainerType > class EdgeMesh{ public: typedef EdgeContainerType EdgeContainer; typedef VertContainerType VertContainer; typedef typename VertContainer::value_type VertexType; typedef typename EdgeContainerType::value_type EdgeType; typedef typename VertexType::ScalarType ScalarType; typedef typename VertexType::CoordType CoordType; typedef typename VertContainer::iterator VertexIterator; typedef typename EdgeContainerType::iterator EdgeIterator; typedef typename VertContainer::const_iterator ConstVertexIterator; typedef typename EdgeContainerType::const_iterator ConstEdgeIterator; typedef VertexType * VertexPointer; typedef const VertexType * ConstVertexPointer; typedef EdgeType * EdgePointer; typedef const EdgeType * ConstEdgePointer; typedef Box3 BoxType; /// Set of vertices VertContainer vert; /// Real number of vertices int vn; /// Set of faces EdgeContainer edges; /// Real number of faces int en; /// Bounding box of the mesh Box3 bbox; /// Nomi di textures //std::vector textures; //std::vector normalmaps; /// La camera //Camera camera; /// Il colore della mesh private: Color4b c; public: inline const Color4b & C() const { return c; } inline Color4b & C() { return c; } /// Default constructor EdgeMesh() { en = vn = 0; imark = 0; } inline int MemUsed() const { return sizeof(EdgeMesh)+sizeof(VertexType)*vert.size()+sizeof(EdgeType)*edges.size(); } inline int MemNeeded() const { return sizeof(EdgeMesh)+sizeof(VertexType)*vn+sizeof(EdgeType)*en; } /// Function to destroy the mesh void Clear() { vert.clear(); edges.clear(); // textures.clear(); // normalmaps.clear(); vn = 0; en = 0; } /// Reflection functions that speak about vertex and face properties. static bool HasPerVertexNormal() { return VertexType::HasNormal() ; } static bool HasPerVertexColor() { return VertexType::HasColor() ; } static bool HasPerVertexMark() { return VertexType::HasMark() ; } static bool HasPerVertexQuality() { return VertexType::HasQuality(); } static bool HasPerVertexTexCoord(){ return VertexType::HasTexCoord(); } static bool HasPerEdgeColor() { return EdgeType::HasEdgeColor() ; } static bool HasPerEdgeNormal() { return EdgeType::HasEdgeNormal() ; } static bool HasPerEdgeMark() { return EdgeType::HasEdgeMark() ; } static bool HasPerEdgeQuality() { return EdgeType::HasEdgeQuality(); } static bool HasEETopology() { return EdgeType::HasEEAdjacency(); } static bool HasVETopology() { return EdgeType::HasVEAdjacency(); } static bool HasTopology() { return HasEETopology() || HasVETopology(); } /// Initialize the imark-system of the faces void InitEdgeIMark() { EdgeIterator f; for(f=edges.begin();f!=edges.end();++f) if( !(*f).IsDeleted() && (*f).IsR() && (*f).IsW() ) (*f).InitIMark(); } /// Initialize the imark-system of the vertices void InitVertexIMark() { VertexIterator vi; for(vi=vert.begin();vi!=vert.end();++vi) if( !(*vi).IsDeleted() && (*vi).IsRW() ) (*vi).InitIMark(); } /// The incremental mark int imark; /** Check if the vertex incremental mark matches the one of the mesh. */ inline bool IsMarked( ConstVertexPointer v ) const { return v->IMark() == imark; } /** Check if the face incremental mark matches the one of the mesh. */ inline bool IsMarked( ConstEdgePointer f ) const { return f->IMark() == imark; } /** Set the vertex incremental mark of the vertex to the one of the mesh. */ inline void Mark( VertexPointer v ) const { v->IMark() = imark; } /** Set the face incremental mark of the vertex to the one of the mesh. */ inline void Mark( EdgePointer f ) const { f->IMark() = imark; } /// Unmark the mesh inline void UnMarkAll() { ++imark; } }; // end class EdgeMesh /*@}*/ } // end namespace } // end namespace #endif qutemol/vcg/vcg/complex/edgemesh/closest.h0000444000175000017500000001527410461621372017250 0ustar mbamba/**************************************************************************** * VCGLib o o * * Visual and Computer Graphics Library o o * * _ O _ * * Copyright(C) 2004 \/)\/ * * Visual Computing Lab /\/| * * ISTI - Italian National Research Council | * * \ * * All rights reserved. * * * * 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. * * * * 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 (http://www.gnu.org/licenses/gpl.txt) * * for more details. * * * ****************************************************************************/ /**************************************************************************** History ****************************************************************************/ #ifndef __VCG_EDGEMESH_CLOSEST #define __VCG_EDGEMESH_CLOSEST #include #include #include #include #include #include #include #include #include namespace vcg { namespace edgemesh { //**MARKER CLASSES**// template class Tmark { MESH_TYPE *m; public: Tmark(){} void UnMarkAll(){m->UnMarkAll();} bool IsMarked(OBJ_TYPE* obj){return (m->IsMarked(obj));} void Mark(OBJ_TYPE* obj){m->Mark(obj);} void SetMesh(MESH_TYPE *_m) {m=_m;} }; template class EdgeTmark:public Tmark {}; template class VertTmark:public Tmark {}; //**CLOSEST FUNCTION DEFINITION**// template typename MESH::EdgeType * GetClosestEdge( MESH & mesh,GRID & gr,const typename GRID::CoordType & _p, const typename GRID::ScalarType & _maxDist,typename GRID::ScalarType & _minDist, typename GRID::CoordType &_closestPt) { typedef typename GRID::ScalarType ScalarType; typedef Point3 Point3x; typedef EdgeTmark MarkerEdge; MarkerEdge mf; mf.SetMesh(&mesh); vcg::edge::PointDistanceFunctor PDistFunct; _minDist=_maxDist; return (gr.GetClosest(PDistFunct,mf,_p,_maxDist,_minDist,_closestPt)); } template typename MESH::VertexType * GetClosestVertex( MESH & mesh,GRID & gr,const typename GRID::CoordType & _p, const typename GRID::ScalarType & _maxDist,typename GRID::ScalarType & _minDist ) { typedef typename GRID::ScalarType ScalarType; typedef Point3 Point3x; typedef VertTmark MarkerVert; MarkerVert mv; mv.SetMesh(&mesh); typedef vcg::vertex::PointDistanceFunctor VDistFunct; _minDist=_maxDist; Point3x _closestPt; return (gr.GetClosest/**/(VDistFunct(),mv,_p,_maxDist,_minDist,_closestPt)); } template unsigned int GetKClosestEdge(MESH & mesh,GRID & gr, const unsigned int _k, const typename GRID::CoordType & _p, const typename GRID::ScalarType & _maxDist, OBJPTRCONTAINER & _objectPtrs,DISTCONTAINER & _distances, POINTCONTAINER & _points) { typedef EdgeTmark MarkerEdge; MarkerEdge mf; mf.SetMesh(&mesh); vcg::face::PointDistanceFunctor FDistFunct; return (gr.GetKClosest /**/ (FDistFunct,mf,_k,_p,_maxDist,_objectPtrs,_distances,_points)); } template unsigned int GetKClosestVertex(MESH & mesh,GRID & gr, const unsigned int _k, const typename GRID::CoordType & _p, const typename GRID::ScalarType & _maxDist, OBJPTRCONTAINER & _objectPtrs,DISTCONTAINER & _distances, POINTCONTAINER & _points) { typedef VertTmark MarkerVert; MarkerVert mv; mv.SetMesh(&mesh); typedef vcg::vertex::PointDistanceFunctor VDistFunct; return (gr.GetKClosest/* */ (VDistFunct(),mv,_k,_p,_maxDist,_objectPtrs,_distances,_points)); } template unsigned int GetInSphereVertex(MESH & mesh, GRID & gr, const typename GRID::CoordType & _p, const typename GRID::ScalarType & _r, OBJPTRCONTAINER & _objectPtrs, DISTCONTAINER & _distances, POINTCONTAINER & _points) { typedef VertTmark MarkerVert; MarkerVert mv; mv.SetMesh(&mesh); typedef vcg::vertex::PointDistanceFunctor VDistFunct; return (gr.GetInSphere/**/ (VDistFunct(),mv,_p,_r,_objectPtrs,_distances,_points)); } template unsigned int GetInBoxEdge(MESH & mesh, GRID & gr, const vcg::Box3 _bbox, OBJPTRCONTAINER & _objectPtrs) { typedef EdgeTmark EdgeTmark; EdgeTmark mf; mf.SetMesh(&mesh); return(gr.GetInBox/**/(mf,_bbox,_objectPtrs)); } template unsigned int GetInBoxVertex(MESH & mesh, GRID & gr, const vcg::Box3 _bbox, OBJPTRCONTAINER & _objectPtrs) { typedef VertTmark MarkerVert; MarkerVert mv; mv.SetMesh(&mesh); return(gr.GetInBox/**/(mv,_bbox,_objectPtrs)); } } // end namespace edgemesh } // end namespace vcg #endif qutemol/vcg/vcg/complex/edgemesh/allocate.h0000444000175000017500000001613710627513746017370 0ustar mbamba/**************************************************************************** * VCGLib o o * * Visual and Computer Graphics Library o o * * _ O _ * * Copyright(C) 2004 \/)\/ * * Visual Computing Lab /\/| * * ISTI - Italian National Research Council | * * \ * * All rights reserved. * * * * 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. * * * * 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 (http://www.gnu.org/licenses/gpl.txt) * * for more details. * * * ****************************************************************************/ /**************************************************************************** History $Log: allocate.h,v $ Revision 1.9 2007/05/31 09:39:50 cignoni Small gcc compiling issues Revision 1.8 2007/05/21 11:12:10 cignoni Corrected gcc compiling issues Revision 1.7 2006/01/19 14:18:08 spinelli fix bug end iterator++ Revision 1.6 2005/05/30 09:43:41 spinelli vertexIterator sostituito con VertexIterator Revision 1.5 2005/05/17 21:14:56 ganovelli some typecast (crs4) Revision 1.4 2004/10/28 00:47:42 cignoni Better Doxygen documentation Revision 1.3 2004/09/20 08:37:47 cignoni Better Doxygen docs Revision 1.2 2004/05/10 14:41:25 ganovelli name of adhacency function updated ****************************************************************************/ #ifndef __VCGLIB_EDGEALLOCATOR #define __VCGLIB_EDGEALLOCATOR namespace vcg { namespace edge { /** \addtogroup edgemesh */ /*@{*/ /// Class to safely add vertexes and faces to a mesh updating all the involved pointers. /// It provides static memeber to add either vertex or faces to a edgemesh. template class Allocator { public: typedef AllocateMeshType MeshType; typedef typename MeshType::VertexType VertexType; typedef typename MeshType::VertexPointer VertexPointer; typedef typename MeshType::VertexIterator VertexIterator; typedef typename MeshType::EdgeType EdgeType; typedef typename MeshType::EdgePointer EdgePointer; typedef typename MeshType::EdgeIterator EdgeIterator; /** This class is used when allocating new vertexes and faces to update the pointers that can be changed when resizing the involved vectors of vertex or faces. It can also be used to prevent any update of the various mesh fields (e.g. in case you are building all the connections by hand as in a importer); */ template class PointerUpdater { public: void Clear(){newBase=oldBase=newEnd=oldEnd=0;preventUpdateFlag=false;}; void Update(SimplexPointerType &vp) { vp=newBase+(vp-oldBase); } bool NeedUpdate() {if(newBase!=oldBase && !preventUpdateFlag) return true; else return false;} SimplexPointerType oldBase; SimplexPointerType newBase; SimplexPointerType newEnd; SimplexPointerType oldEnd; bool preventUpdateFlag; /// when true no update is considered necessary. }; /** Function to safely add n vertices to a mesh. @param m The mesh to be expanded @param n the number of vertexes to be added @param pu A PointerUpdater that stores the relocation that can be happened. */ static VertexIterator AddVertices(MeshType &m,int n, PointerUpdater &pu) { VertexIterator last=m.vert.end(); pu.Clear(); if(m.vert.empty()) pu.oldBase=0; // if the vector is empty we cannot find the last valid element else pu.oldBase=&*m.vert.begin(); for(int i=0; i pu; return AddVertices(m, n,pu); } /** Function to add n faces to the mesh. @param n Il numero di facce che si vuole aggiungere alla mesh */ static EdgeIterator AddEdges(MeshType &m, int n) { PointerUpdater pu; return AddEdges(m,n,pu); } /** Function to add n faces to the mesh. NOTA: Aggiorna fn; */ static EdgeIterator AddEdges(MeshType &m, int n, PointerUpdater &pu) { EdgeIterator last=m.edges.end(); pu.Clear(); if(m.edges.empty()) { pu.oldBase=0; // if the vector is empty we cannot find the last valid element //last=0; } else { pu.oldBase=&*m.edges.begin(); last=m.edges.end(); } m.edges.resize(m.edges.size()+n); /*for(int i=0; i sostituito con std::vector Revision 1.4 2005/05/30 09:13:08 ganovelli error in include Revision 1.3 2005/05/17 21:19:37 ganovelli some std::and typename missing (CRS4) Revision 1.2 2005/03/08 14:42:22 ganovelli added vcg header ****************************************************************************/ #ifndef __VCGLIB__UNIFY #define __VCGLIB__UNIFY #include #include #include #include namespace vcg { /** \addtogroup edgemesh */ /*@{*/ /** Class for computing unification of the vertices or of the edges */ template struct Unify{ template class Tmark { MESH_TYPE m; public: Tmark(MESH_TYPE &_m):m(_m){} void UnMarkAll(){m.UnMarkAll();} bool IsMarked(OBJ_TYPE* obj){return (m.IsMarked(obj->v));} void Mark(OBJ_TYPE* obj){m.Mark(obj->v);} }; typedef typename EdgeMeshType::VertexPointer VertexPointer; typedef typename EdgeMeshType::EdgePointer EdgePointer; typedef typename EdgeMeshType::ScalarType ScalarType; typedef typename EdgeMeshType::CoordType CoordType; struct PVertex:EdgeMeshType::VertexType { typedef typename EdgeMeshType::ScalarType ScalarType; VertexPointer v; // the two Vertex pointer are ordered! EdgePointer e; // the edge where this vertex belong int z; // index in [0..2] of the edge of the face PVertex(EdgePointer pe, const int nz ):e(pe),z(nz),v(pe->V(nz)){} /*bool Dist(Point3 p,ScalarType & d,Point3& res) { res = p; ScalarType _d =vcg::Distance(p,v->P()); if(d > _d) { d = _d; return true; } return false; }*/ void GetBBox(vcg::Box3 & bb){ bb.Add(v->P()); } bool IsD(){ return v->IsD(); } }; typedef GridStaticPtr< PVertex > GridType; static void Join(PVertex pv0,PVertex & pv1){ pv1.e->V(pv1.z) = pv0.v; pv1.e = NULL; } class BackCompDist { public: inline bool operator () (const PVertex & obj, const CoordType & pt, ScalarType & mindist, CoordType & result) { result = pt; ScalarType _d =vcg::Distance(result,obj.v->P()); if(mindist < _d) { mindist = _d; return true; } return false; } }; static GridType & Grid(){static GridType grid; return grid; } static void Vertices(EdgeMeshType & em, ScalarType epsilon){ typename EdgeMeshType::EdgeIterator ei; typedef Tmark Marker; Marker tm=Marker(em); bool lastRound ; if(em.vn){ vcg::edge::UpdateBounding::Box(em); //Grid().SetBBox(em.bbox); std::vector pv; for(ei = em.edges.begin(); ei != em.edges.end();++ei){ pv.push_back(PVertex(&*ei,0)); pv.push_back(PVertex(&*ei,1)); } Grid().Set(pv.begin(), pv.end() ); typename std::vector::iterator pvi; Point3 p; PVertex * closest; do{ lastRound = true; for(pvi = pv.begin(); pvi != pv.end(); ++pvi) if((*pvi).e) { float eps = epsilon; Point3 vpos =(*pvi).v->P() ; (*pvi).v->SetD(); ScalarType max_dist=em.bbox.Diag(); ScalarType min_dist = 0; p = (vcg::trimesh::GetClosestVertex( em, Grid(), vpos, max_dist, min_dist))->P(); //closest = Grid().GetClosest(vpos, max_dist, BackCompDist(), eps, p,tm); //closest = Grid().GetClosest(vpos,eps,p); (*pvi).v->ClearD(); if(closest){ if(closest->e) { Join(*pvi,*closest); lastRound = false; } } } }while(!lastRound); } } // end Vertices }; // end class } // end namespace #endif qutemol/vcg/vcg/complex/edgemesh/update/0000755000175000017500000000000011633404241016672 5ustar mbambaqutemol/vcg/vcg/complex/edgemesh/update/topology.h0000444000175000017500000001262410627513752020734 0ustar mbamba/**************************************************************************** * VCGLib o o * * Visual and Computer Graphics Library o o * * _ O _ * * Copyright(C) 2004 \/)\/ * * Visual Computing Lab /\/| * * ISTI - Italian National Research Council | * * \ * * All rights reserved. * * * * 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. * * * * 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 (http://www.gnu.org/licenses/gpl.txt) * * for more details. * * * ****************************************************************************/ /**************************************************************************** History $Log: topology.h,v $ Revision 1.4 2007/05/31 09:39:54 cignoni Small gcc compiling issues Revision 1.3 2004/10/28 00:47:51 cignoni Better Doxygen documentation Revision 1.2 2004/05/10 14:42:17 ganovelli nimor changes ****************************************************************************/ #ifndef __VCG_EDGE_UPDATE_TOPOLOGY #define __VCG_EDGE_UPDATE_TOPOLOGY #include namespace vcg { namespace edge { /** \addtogroup edgemesh */ /*@{*/ template class UpdateTopology { public: typedef UpdateMeshType MeshType; typedef typename MeshType::VertexType VertexType; typedef typename MeshType::VertexPointer VertexPointer; typedef typename MeshType::VertexIterator VertexIterator; typedef typename MeshType::EdgeType EdgeType; typedef typename MeshType::EdgePointer EdgePointer; typedef typename MeshType::EdgeIterator EdgeIterator; /// Auxiliairy data structure for computing face face adjacency information. // It identifies and edge storing two vertex pointer and a face pointer where it belong. class PVertex { public: VertexPointer v; // the two Vertex pointer are ordered! EdgePointer e; // the edge where this vertex belong int z; // index in [0..2] of the edge of the face PVertex() {} void Set( EdgePointer pe, const int nz ) { assert(pe!=0); assert(nz>=0); assert(nz<2); v= pe->V(nz); e = pe; z = nz; } inline bool operator < ( const PVertex & pe ) const { return ( v ( const PVertex & pe ) const { return ( v>pe.v ); } inline bool operator >= ( const PVertex & pe ) const { return( v>pe.v ); } inline bool operator == ( const PVertex & pe ) const { return (v==pe.v); } inline bool operator != ( const PVertex & pe ) const { return (v!=pe.v || v!=pe.v); } }; static void EdgeEdge(MeshType &m) { if(!m.HasEETopology()) return; vector v; EdgeIterator pf; typename vector::iterator p; if( m.en == 0 ) return; v.resize(m.en*2); // Alloco il vettore ausiliario p = v.begin(); for(pf=m.edges.begin();pf!=m.edges.end();++pf) // Lo riempio con i dati delle facce if( ! (*pf).IsD() ) for(int j=0;j<2;++j) { (*p).Set(&(*pf),j); ++p; } assert(p==v.end()); sort(v.begin(), v.end()); // Lo ordino per vertici int ne = 0; // Numero di edge reali typename vector::iterator pe,ps; for(ps = v.begin(),pe=v.begin();pe<=v.end();++pe) // Scansione vettore ausiliario { if( pe==v.end() || *pe != *ps ) // Trovo blocco di edge uguali { typename vector::iterator q,q_next; for (q=ps;q=0); assert((*q).z< 2); q_next = q; ++q_next; assert((*q_next).z>=0); assert((*q_next).z< 2); (*q).e->EEp(q->z) = (*q_next).e; // Collegamento in lista delle facce (*q).e->EEi(q->z) = (*q_next).z; } assert((*q).z>=0); assert((*q).z< 3); (*q).e->EEp((*q).z) = ps->e; (*q).e->EEi((*q).z) = ps->z; ps = pe; ++ne; // Aggiorno il numero di edge } } } static void VertexEdge(MeshType &m) { if(!m.HasVETopology()) return; VertexIterator vi; EdgeIterator ei; for(vi=m.vert.begin();vi!=m.vert.end();++vi) { (*vi).Ep() = 0; (*vi).Ei() = 0; } for(ei=m.edges.begin();ei!=m.edges.end();++ei) if( ! (*ei).IsD() ) { for(int j=0;j<2;++j) { (*ei).Ev(j) = (*ei).V(j)->Ep(); (*ei).Zv(j) = (*ei).V(j)->Ei(); (*ei).V(j)->Ep() = &(*ei); (*ei).V(j)->Ei() = j; } } } }; // end class /*@}*/ } // End namespace } // End namespace #endif qutemol/vcg/vcg/complex/edgemesh/update/bounding.h0000444000175000017500000000574510047712271020664 0ustar mbamba/**************************************************************************** * VCGLib o o * * Visual and Computer Graphics Library o o * * _ O _ * * Copyright(C) 2004 \/)\/ * * Visual Computing Lab /\/| * * ISTI - Italian National Research Council | * * \ * * All rights reserved. * * * * 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. * * * * 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 (http://www.gnu.org/licenses/gpl.txt) * * for more details. * * * ****************************************************************************/ /**************************************************************************** History $Log: bounding.h,v $ Revision 1.2 2004/05/10 14:42:01 ganovelli mionr changes ****************************************************************************/ #ifndef __VCG_EDGE_UPDATE_BOUNDING #define __VCG_EDGE_UPDATE_BOUNDING namespace vcg { namespace edge { /** \addtogroup edgemesh */ /*@{*/ /// Management, updating and computation of per-vertex and per-face normals. /// This class is used to compute or update the normals that can be stored in the vertex or face component of a mesh. template class UpdateBounding { public: typedef ComputeMeshType MeshType; typedef typename MeshType::VertexType VertexType; typedef typename MeshType::VertexPointer VertexPointer; typedef typename MeshType::VertexIterator VertexIterator; typedef typename MeshType::EdgeType EdgeType; typedef typename MeshType::EdgePointer EdgePointer; typedef typename MeshType::EdgeIterator EdgeIterator; /// Calculates the vertex normal (if stored in the current face type) static void Box(ComputeMeshType &m) { m.bbox.SetNull(); VertexIterator vi; for(vi=m.vert.begin();vi!=m.vert.end();++vi) if( !(*vi).IsD() ) m.bbox.Add((*vi).P()); } }; // end class } // End namespace } // End namespace #endif qutemol/vcg/vcg/space/0000755000175000017500000000000011633404241013253 5ustar mbambaqutemol/vcg/vcg/space/normal_extrapolation.h0000444000175000017500000003352410636171322017675 0ustar mbamba/**************************************************************************** * VCGLib o o * * Visual and Computer Graphics Library o o * * _ O _ * * Copyright(C) 2004 \/)\/ * * Visual Computing Lab /\/| * * ISTI - Italian National Research Council | * * \ * * All rights reserved. * * * * 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. * * * * 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 (http://www.gnu.org/licenses/gpl.txt) * * for more details. * * * ****************************************************************************/ #ifndef VCG_SPACE_NORMAL_EXTRAPOLATION_H #define VCG_SPACE_NORMAL_EXTRAPOLATION_H #include #include #include #include #include #include #include #include #include #include #include #include #include namespace vcg { /*! */ template < class VERTEX_CONTAINER > class NormalExtrapolation { public: typedef typename VERTEX_CONTAINER::value_type VertexType; typedef VertexType * VertexPointer; typedef typename VERTEX_CONTAINER::iterator VertexIterator; typedef typename VertexType::CoordType CoordType; typedef typename VertexType::NormalType NormalType; typedef typename VertexType::ScalarType ScalarType; typedef typename vcg::Box3< ScalarType > BoundingBoxType; typedef typename vcg::Matrix33 MatrixType; enum NormalOrientation {IsCorrect=0, MustBeFlipped=1}; private: /************************************************* * Inner class definitions **************************************************/ // Dummy class: no object marker is needed class DummyObjectMarker {}; // Object functor: compute the distance between a vertex and a point struct VertPointDistanceFunctor { inline bool operator()(const VertexType &v, const CoordType &p, ScalarType &d, CoordType &q) const { ScalarType distance = vcg::Distance(p, v.P()); if (distance>d) return false; d = distance; q = v.P(); return true; } }; // Plane structure: identify a plain as a pair struct Plane { Plane() { center.Zero(); normal.Zero();}; // Object functor: return the bounding-box enclosing a given plane inline void GetBBox(BoundingBoxType &bb) { bb.Set(center); }; CoordType center; NormalType normal; int index; }; // Object functor: compute the distance between a point and the plane struct PlanePointDistanceFunctor { inline bool operator()(const Plane &plane, const CoordType &p, ScalarType &d, CoordType &q) const { ScalarType distance = vcg::Distance(p, plane.center); if (distance>d) return false; d = distance; q = plane.center; return true; } }; // Represent an edge in the Riemannian graph struct RiemannianEdge { RiemannianEdge(Plane *p=NULL, ScalarType w=std::numeric_limits::max()) {plane=p; weight=w; } Plane *plane; ScalarType weight; }; // Represent an edge in the MST tree struct MSTEdge { MSTEdge(Plane *p0=NULL, Plane *p1=NULL, ScalarType w=std::numeric_limits::max()) {u=p0; v=p1; weight=w;}; inline bool operator<(const MSTEdge &e) const {return weight sons; }; typedef std::vector< Plane > PlaneContainer; typedef typename PlaneContainer::iterator PlaneIterator; public: /*! */ static void ExtrapolateNormals(const VertexIterator &begin, const VertexIterator &end, const unsigned int k, const int root_index=-1, NormalOrientation orientation=IsCorrect, CallBackPos *callback=NULL) { BoundingBoxType dataset_bb; for (VertexIterator iter=begin; iter!=end; iter++) dataset_bb.Add(iter->P()); ScalarType max_distance = dataset_bb.Diag(); // Step 1: identify the tangent planes used to locally approximate the surface int vertex_count = int( std::distance(begin, end) ); int step = int(vertex_count/100)-1; int progress = 0; int percentage; char message[128]; sprintf(message, "Locating tangent planes..."); std::vector< Plane > tangent_planes(vertex_count); vcg::Octree< VertexType, ScalarType > octree_for_planes; octree_for_planes.Set( begin, end ); std::vector< VertexPointer > nearest_vertices; std::vector< CoordType > nearest_points; std::vector< ScalarType > distances; for (VertexIterator iter=begin; iter!=end; iter++) { if (callback!=NULL && (++progress%step)==0 && (percentage=int((progress*100)/vertex_count))<100) (callback)(percentage, message); VertPointDistanceFunctor vpdf; DummyObjectMarker dom; octree_for_planes.GetKClosest(vpdf, dom, k, iter->P(), max_distance, nearest_vertices, distances, nearest_points); // for each vertex *iter, compute the centroid as avarege of the k-nearest vertices of *iter Plane *plane = &tangent_planes[ std::distance(begin, iter) ]; for (unsigned int n=0; ncenter += nearest_points[n]; plane->center /= ScalarType(k); // then, identity the normal associated to the centroid MatrixType covariance_matrix; CoordType diff; covariance_matrix.SetZero(); for (unsigned int n=0; ncenter; for (int i=0; i<3; i++) for (int j=0; j<3; j++) covariance_matrix[i][j]+=diff[i]*diff[j]; } CoordType eigenvalues; MatrixType eigenvectors; int required_rotations; vcg::Jacobi< MatrixType, CoordType >(covariance_matrix, eigenvalues, eigenvectors, required_rotations); vcg::SortEigenvaluesAndEigenvectors< MatrixType, CoordType >(eigenvalues, eigenvectors); for (int d=0; d<3; d++) plane->normal[d] = eigenvectors[d][2]; plane->normal.Normalize(); iter->N() = plane->normal; plane->index = int( std::distance(begin, iter) ); } // Step 2: build the Riemannian graph, i.e. the graph where each point is connected to the k-nearest neigbours. dataset_bb.SetNull(); PlaneIterator ePlane = tangent_planes.end(); for (PlaneIterator iPlane=tangent_planes.begin(); iPlane!=ePlane; iPlane++) dataset_bb.Add(iPlane->center); max_distance = dataset_bb.Diag(); vcg::Octree< Plane, ScalarType > octree_for_plane; octree_for_plane.Set( tangent_planes.begin(), tangent_planes.end()); std::vector< Plane* > nearest_planes(distances.size()); std::vector< std::vector< RiemannianEdge > > riemannian_graph(vertex_count); //it's probably that we are wasting the last position... progress = 0; sprintf(message, "Building Riemannian graph..."); for (PlaneIterator iPlane=tangent_planes.begin(); iPlane!=ePlane; iPlane++) { if (callback!=NULL && (++progress%step)==0 && (percentage=int((progress*100)/vertex_count))<100) (callback)(percentage, message); unsigned int kk = k; PlanePointDistanceFunctor ppdf; DummyObjectMarker dom; octree_for_plane.GetKClosest (ppdf, dom, kk, iPlane->center, max_distance, nearest_planes, distances, nearest_points, true, false); for (int n=0; nindexindex) riemannian_graph[iPlane->index].push_back( RiemannianEdge( nearest_planes[n], 1.0f - fabs(iPlane->normal * nearest_planes[n]->normal)) ); } // Step 3: compute the minimum spanning tree (MST) over the Riemannian graph (we use the Kruskal algorithm) std::vector< MSTEdge > E; typename std::vector< std::vector< RiemannianEdge > >::iterator iRiemannian = riemannian_graph.begin(); typename std::vector< RiemannianEdge >::iterator iRiemannianEdge, eRiemannianEdge; for (int i=0; ibegin(), eRiemannianEdge=iRiemannian->end(); iRiemannianEdge!=eRiemannianEdge; iRiemannianEdge++) E.push_back(MSTEdge(&tangent_planes[i], iRiemannianEdge->plane, iRiemannianEdge->weight)); std::sort( E.begin(), E.end() ); vcg::DisjointSet planeset; for (typename std::vector< Plane >::iterator iPlane=tangent_planes.begin(); iPlane!=ePlane; iPlane++) planeset.MakeSet( &*iPlane ); typename std::vector< MSTEdge >::iterator iMSTEdge = E.begin(); typename std::vector< MSTEdge >::iterator eMSTEdge = E.end(); std::vector< MSTEdge > unoriented_tree; Plane *u, *v; for ( ; iMSTEdge!=eMSTEdge; iMSTEdge++) if ((u=planeset.FindSet(iMSTEdge->u))!=(v=planeset.FindSet(iMSTEdge->v))) unoriented_tree.push_back( *iMSTEdge ), planeset.Union(u, v); E.clear(); // compute for each plane the list of sorting edges std::vector< std::vector< int > > incident_edges(vertex_count); iMSTEdge = unoriented_tree.begin(); eMSTEdge = unoriented_tree.end(); progress = 0; int mst_size = int(unoriented_tree.size()); sprintf(message, "Building orieted graph..."); for ( ; iMSTEdge!=eMSTEdge; iMSTEdge++) { if (callback!=NULL && (++progress%step)==0 && (percentage=int((progress*100)/mst_size))<100) (callback)(percentage, message); int u_index = int(iMSTEdge->u->index); int v_index = int(iMSTEdge->v->index); incident_edges[ u_index ].push_back( v_index ), incident_edges[ v_index ].push_back( u_index ); } // Traverse the incident_edges vector and build the MST VertexIterator iCurrentVertex, iSonVertex; std::vector< MSTNode > MST(vertex_count); typename std::vector< Plane >::iterator iFirstPlane = tangent_planes.begin(); typename std::vector< Plane >::iterator iCurrentPlane, iSonPlane; MSTNode *mst_root; int r_index = (root_index!=-1)? root_index : rand()*vertex_count/RAND_MAX; mst_root = &MST[ r_index ]; mst_root->parent = mst_root; //the parent of the root is the root itself if (orientation==MustBeFlipped) { iCurrentVertex = begin; std::advance(iCurrentVertex, r_index); iCurrentVertex->N() = iCurrentVertex->N()*ScalarType(-1.0f); } { // just to limit the scope of the variable border std::queue< int > border; border.push(r_index); int maxSize = 0; int queueSize = 0; progress = 0; sprintf(message, "Extracting the tree..."); while ((queueSize=int(border.size()))>0) { if (callback!=NULL && ((++progress%step)==0) && (percentage=int((maxSize-queueSize)*100/maxSize))<100) (callback)(percentage, message); int current_node_index = border.front(); border.pop(); MSTNode *current_node = &MST[current_node_index]; //retrieve the pointer to the current MST node std::advance((iCurrentVertex=begin), current_node_index); //retrieve the pointer to the correspective vertex current_node->vertex = &*iCurrentVertex; //and associate it to the MST node std::vector< int >::iterator iSon = incident_edges[ current_node_index ].begin(); std::vector< int >::iterator eSon = incident_edges[ current_node_index ].end(); for ( ; iSon!=eSon; iSon++) { MSTNode *son = &MST[ *iSon ]; if (son->parent==NULL) // the node hasn't been visited { son->parent = current_node; // Update the MST nodes current_node->sons.push_back(son); //std::advance((iSonVertex=begin), *iSon);//retrieve the pointer to the Vertex associated to son border.push( *iSon ); } maxSize = vcg::math::Max(maxSize, queueSize); } } } // and finally visit the MST tree in order to propagate the normals { std::queue< MSTNode* > border; border.push(mst_root); sprintf(message, "Orienting normals..."); progress = 0; int maxSize = 0; int queueSize = 0; while ((queueSize=int(border.size()))>0) { MSTNode *current_node = border.front(); border.pop(); //std::vector< MSTNode* >::iterator iMSTSon = current_node->sons.begin(); //std::vector< MSTNode* >::iterator eMSTSon = current_node->sons.end(); for (int s=0; ssons.size()); s++) { if (callback!=NULL && ((++progress%step)==0) && (percentage=int((maxSize-queueSize)*100/maxSize))<100) (callback)(percentage, message); if (current_node->vertex->N()*current_node->sons[s]->vertex->N()sons[s]->vertex->N() *= ScalarType(-1.0f); border.push( current_node->sons[s] ); maxSize = vcg::math::Max(maxSize, queueSize); } } } if (callback!=NULL) (callback)(100, message); }; }; };//end of namespace vcg #endif //end of VCG_SPACE_NORMAL_EXTRAPOLATION_H qutemol/vcg/vcg/space/space.h0000444000175000017500000000626210416662135014531 0ustar mbamba/**************************************************************************** * VCGLib o o * * Visual and Computer Graphics Library o o * * _ O _ * * Copyright(C) 2004 \/)\/ * * Visual Computing Lab /\/| * * ISTI - Italian National Research Council | * * \ * * All rights reserved. * * * * 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. * * * * 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 (http://www.gnu.org/licenses/gpl.txt) * * for more details. * * * ****************************************************************************/ /**************************************************************************** History $Log: space.h,v $ Revision 1.3 2006/04/11 08:10:05 zifnab1974 changes necessary for gcc 3.4.5 on linux 64bit. Revision 1.2 2006/01/03 12:44:58 spinelli fix some bugs. Revision 1.1 2004/03/16 03:08:02 tarini first commit ****************************************************************************/ #ifndef __VCGLIB_SPACE #define __VCGLIB_SPACE #include namespace vcg { /*@{*/ /** This class represents the interface for any spatial objects. (points, lines, rays, segments, planes, triangles, axis aligned box). It consists in (the declaration of) a set of functions and types that each such object mush have. */ template class Point; template class Box; class ParamType; template class Space { public: /// Dimension is a constant determines the dimension of the space. enum {Dimension=N}; /// the type used as scalar. Typically, float or double, but char or int are possible too. typedef S ScalarType; /// type used as point Type typedef Point PointType; /// the ... //typedef ParamType; /// returns the bounding box of the object Box const BBox() const; /// given a point, return the closest point PointType ClosestPoint(PointType const &p) const; PointType LocalToGlobal(ParamType); ParamType GlobalToLocal(ParamType); }; // end class definition /*@}*/ } // end namespace #endif qutemol/vcg/vcg/space/index/0000755000175000017500000000000011633404241014362 5ustar mbambaqutemol/vcg/vcg/space/index/grid_static_obj.h0000444000175000017500000001113610642077074017672 0ustar mbamba/**************************************************************************** * VCGLib o o * * Visual and Computer Graphics Library o o * * _ O _ * * Copyright(C) 2004 \/)\/ * * Visual Computing Lab /\/| * * ISTI - Italian National Research Council | * * \ * * All rights reserved. * * * * 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. * * * * 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 (http://www.gnu.org/licenses/gpl.txt) * * for more details. * * * ****************************************************************************/ /**************************************************************************** History $Log: grid_static_obj.h,v $ Revision 1.5 2007/07/02 04:25:32 cignoni Corrected gcc compiling issues Revision 1.4 2006/09/27 08:49:32 spinelli bug fix, add return type to Init Revision 1.3 2006/08/23 15:20:14 marfr960 corrected minor bugs Revision 1.2 2005/12/02 00:29:00 cignoni updated the templates of BasicGrid Revision 1.1 2005/07/28 08:41:00 cignoni First working version Revision 1.13 2005/04/14 17:23:08 ponchio *** empty log message *** ****************************************************************************/ #ifndef __VCGLIB_UGRID_OBJ #define __VCGLIB_UGRID_OBJ #include #include #include #include #include #include namespace vcg { /** Static Uniform Grid A simple Spatial grid of object. Kept in the most trivial way. Every cell is allocated and contains one istance of the template class. */ template < class ObjType, class FLT=float > class GridStaticObj : public BasicGrid { public: /// La matriciona della griglia ObjType *grid; int size() const { return this->siz[0]*this->siz[1]*this->siz[2];} inline GridStaticObj() { grid = 0; } inline ~GridStaticObj() { if(grid) delete[] grid; } inline void Init(const ObjType &val) { fill(grid,grid+size(),val); } /// Date le coordinate ritorna la cella inline ObjType & Grid( const int x, const int y, const int z ) {return grid[GridInd(Point3i(x,y,z))]; } // Dato un punto ritorna la cella inline ObjType & Grid( const Point3 & p ) { return grid[GridInd(p)]; } inline int GridInd( const Point3i & pi ) const { #ifndef NDEBUG if ( pi[0]<0 || pi[0]>=this->siz[0] || pi[1]<0 || pi[1]>=this->siz[1] || pi[2]<0 || pi[2]>=this->siz[2] ) { assert(0); return 0; } #endif return pi[0]+this->siz[0]*(pi[1]+this->siz[1]*pi[2]); } // Dato un punto ritorna l'indice della cella inline int GridInd( const Point3 & p ) const { return GridInd(GridP(p)); } void Create( Point3i &_siz, const ObjType & init ) { this->siz=_siz; this->voxel[0] = this->dim[0]/this->siz[0]; this->voxel[1] = this->dim[1]/this->siz[1]; this->voxel[2] = this->dim[2]/this->siz[2]; if(grid) delete[] grid; int n = this->siz[0]*this->siz[1]*this->siz[2]; grid = new ObjType[n]; fill(grid,grid+n,init); } /// Crea una griglia di un dato bbox e con un certo numero di elem. /// il bbox viene gonfiato appositamente. template void Create(const Box3 & b, int ncell, const ObjType & init, bool Inflate = true ) { this->bbox.Import(b); if(Inflate) this->bbox.Offset(0.01*this->bbox.Diag()); this->dim = this->bbox.max - this->bbox.min; // Calcola la dimensione della griglia Point3i _siz; BestDim( ncell, this->dim, _siz ); Create(_siz, init ); } }; //end class SGrid } #endif qutemol/vcg/vcg/space/index/perfect_spatial_hashing.h0000444000175000017500000016612610566153176021427 0ustar mbamba/**************************************************************************** * VCGLib o o * * Visual and Computer Graphics Library o o * * _ O _ * * Copyright(C) 2004 \/)\/ * * Visual Computing Lab /\/| * * ISTI - Italian National Research Council | * * \ * * All rights reserved. * * * * 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. * * * * 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 (http://www.gnu.org/licenses/gpl.txt) * * for more details. * * * ****************************************************************************/ #ifndef VCG_SPACE_INDEX_PERFECT_SPATIAL_HASHING_H #define VCG_SPACE_INDEX_PERFECT_SPATIAL_HASHING_H #pragma warning(disable : 4996) #define _USE_GRID_UTIL_PARTIONING_ 1 #define _USE_OCTREE_PARTITIONING_ (1-_USE_GRID_UTIL_PARTIONING_) #include #include #include #include #include #include #include #include namespace vcg { // Compute the greatest common divisor between two integers a and b int GreatestCommonDivisor(const int a, const int b) { int m = a; int n = b; do { if (m class PerfectSpatialHashing : public vcg::SpatialIndex< OBJECT_TYPE, SCALAR_TYPE > { // Given an object or a pointer to an object, return the reference to the object template < typename TYPE > struct Dereferencer { static TYPE& Reference(TYPE &t) { return t; } static TYPE& Reference(TYPE* &t) { return *t; } static const TYPE& Reference(const TYPE &t) { return t; } static const TYPE& Reference(const TYPE* &t) { return *t; } }; // Given a type, holds this type in Type template < typename TYPE > struct ReferenceType { typedef TYPE Type; }; // Given as type a "pointer to type", holds the type in Type template < typename TYPE > struct ReferenceType< TYPE * > { typedef typename ReferenceType::Type Type; }; public: typedef SCALAR_TYPE ScalarType; typedef OBJECT_TYPE ObjectType; typedef typename ReferenceType< ObjectType >::Type * ObjectPointer; typedef typename vcg::Box3< ScalarType > BoundingBoxType; typedef typename vcg::Point3< ScalarType > CoordinateType; protected: /*! \struct NeighboringEntryIterator * This class provides a convenient way to iterate over the six neighboring cells of a given cell. */ struct NeighboringEntryIterator { /*! * Default constructor. * @param[in] entry The index of the cell in the UniformGrid around which iterate. * @param[in] table_size The number of cells in the UniformGrid for each side. */ NeighboringEntryIterator(const vcg::Point3i &entry, const int table_size) { m_Center = entry; m_TableSize = table_size; m_CurrentNeighbor.X() = (m_Center.X()+m_TableSize-1)%m_TableSize; m_CurrentNeighbor.Y() = m_Center.Y(); m_CurrentNeighbor.Z() = m_Center.Z(); m_CurrentIteration = 0; } /*! * Increment the iterator to point to the next neighboring entry in the UniformGrid */ void operator++(int) { switch(++m_CurrentIteration) { case 1: m_CurrentNeighbor.X()=(m_Center.X()+1)%m_TableSize; break; case 2: m_CurrentNeighbor.X()=m_Center.X(); m_CurrentNeighbor.Y()=(m_Center.Y()+m_TableSize-1)%m_TableSize; break; case 3: m_CurrentNeighbor.Y()=(m_Center.Y()+1)%m_TableSize; break; case 4: m_CurrentNeighbor.Y()=m_Center.Y(); m_CurrentNeighbor.Z()=(m_Center.Z()+m_TableSize-1)%m_TableSize; break; case 5: m_CurrentNeighbor.Z()=(m_Center.Z()+1)%m_TableSize; break; default: m_CurrentNeighbor = vcg::Point3i(-1, -1, -1); break; } } /*! * Dereferencing operator * \return The neighbor of the given cell at the current iteration */ vcg::Point3i operator*() { return m_CurrentNeighbor; } /*! * Assignment operator * @param[in] The source neighboring iterator * \return The reference to this iterator */ NeighboringEntryIterator& operator =(const NeighboringEntryIterator &it) { m_Center = it.m_Center ; m_CurrentNeighbor = it.m_CurrentNeighbor ; m_CurrentIteration = it.m_CurrentIteration ; m_TableSize = it.m_TableSize ; return *this; } /*! * Less than operator. Since each entry in the UniformGrid has only 6 neighbors, * the iterator over the neighboring entries can be compared with an integer. */ inline bool operator <(const int value) { return m_CurrentIterationGetResolution()) { m_CurrentPosition.Z() = 0; if (++m_CurrentPosition.Y()==m_UniformGrid->GetResolution()) { m_CurrentPosition.Y() = 0; if (++m_CurrentPosition.X()==m_UniformGrid->GetResolution()) m_CurrentPosition = CellCoordinate(-1, -1, -1); } } } /*! * Copy operator. * @param[in] it The iterator whose value has to be copied. */ void operator =(const EntryIterator &it) { m_UniformGrid = it.m_UniformGrid; m_CurrentPosition = it.m_CurrentPosition; } /*! * Equivalence operator */ bool operator==(const EntryIterator &it) const { return m_CurrentPosition==it.m_CurrentPosition; } /*! * Diversity operator */ bool operator!=(const EntryIterator &it) const { return m_CurrentPosition!=it.m_CurrentPosition; } /*! * Dereferencing operator. * \return The pointer to the vector of the objects contained in the cell pointed to by the iterator. */ std::vector< ObjectPointer >* operator*() { return m_UniformGrid->GetObjects(m_CurrentPosition); } /*! * Return the index of the cell pointed to by the iterator. */ CellCoordinate GetPosition() const { return m_CurrentPosition; } protected: UniformGrid * m_UniformGrid; CellCoordinate m_CurrentPosition; }; // end of struct EntryIterator /*! * Default constructor */ UniformGrid() {} /*! * Default destructor */ ~UniformGrid() {} /*! * These functions return an iterator pointing to the first and the last cell of the grid respectively. */ EntryIterator Begin() { return EntryIterator(this, CellCoordinate( 0, 0, 0)); } EntryIterator End() { return EntryIterator(this, CellCoordinate(-1, -1, -1)); } /*! * Return an iterator that iterates over the six adjacent cells of a given cell. * @param[in] at The cell around which this iterator takes values. * \return The iterator over the neighboring cells of at. */ NeighboringEntryIterator GetNeighboringEntryIterator(const CellCoordinate &at) { return NeighboringEntryIterator(at, m_CellPerSide); } /*! * Allocate the necessary space for the uniform grid. * @param[in] bounding_box The bounding box enclosing the whole dataset. * @param[in] cell_per_side The resolution of the grid. */ void Allocate(const BoundingBoxType &bounding_box, const int cell_per_side) { m_CellPerSide = cell_per_side; m_BoundingBox = bounding_box; m_CellSize = (m_BoundingBox.max - m_BoundingBox.min)/ScalarType(cell_per_side); m_Grid.resize(m_CellPerSide); for (int i=0; i void InsertElements(const OBJECT_ITERATOR &begin, const OBJECT_ITERATOR &end) { typedef OBJECT_ITERATOR ObjectIterator; typedef Dereferencer< typename ReferenceType< typename OBJECT_ITERATOR::value_type >::Type > ObjectDereferencer; std::vector< CellCoordinate > cells_occupied; for (ObjectIterator iObject=begin; iObject!=end; iObject++) { ObjectPointer pObject = &ObjectDereferencer::Reference( *iObject ); GetCellsIndex( pObject, cells_occupied); for (std::vector< CellCoordinate >::iterator iCell=cells_occupied.begin(), eCell=cells_occupied.end(); iCell!=eCell; iCell++) GetObjects( *iCell )->push_back( pObject ); cells_occupied.clear(); } } /*! * Given a point contained in the UniformGrid, returns the index of the cell where it's contained. * @param[in] query The 3D point. * \return The index of the UniformGrid entry where this point is contained. */ inline CellCoordinate Interize(const CoordinateType &query) const { CellCoordinate result; result.X() = (int) floorf( (query.X()-m_BoundingBox.min.X())/m_CellSize.X() ); result.Y() = (int) floorf( (query.Y()-m_BoundingBox.min.Y())/m_CellSize.Y() ); result.Z() = (int) floorf( (query.Z()-m_BoundingBox.min.Z())/m_CellSize.Z() ); return result; } /*! * Given a bounding box contained in the UniformGrid, returns its integer-equivalent bounding box. * @param[in] bounding_box The bounding box in the 3D space. * \return The integer representation of the bounding box. */ inline vcg::Box3i Interize(const BoundingBoxType &bounding_box) const { vcg::Box3i result; result.min = Interize(bounding_box.min); result.max = Interize(bounding_box.max); return result; } /*! * Given the pointer to an object, returns the set of cells in the uniform grid containing the object. * @param[in] pObject The pointer to the object * @param[out] cells_occuppied The set of cell index containing the object */ void GetCellsIndex(const ObjectPointer pObject, std::vector< CellCoordinate > & cells_occupied) { BoundingBoxType object_bb; (*pObject).GetBBox(object_bb); CoordinateType corner = object_bb.min; while (object_bb.IsIn(corner)) { CellCoordinate cell_index; cell_index.X() = (int) floorf( (corner.X()-m_BoundingBox.min.X())/m_CellSize.X() ); cell_index.Y() = (int) floorf( (corner.Y()-m_BoundingBox.min.Y())/m_CellSize.Y() ); cell_index.Z() = (int) floorf( (corner.Z()-m_BoundingBox.min.Z())/m_CellSize.Z() ); cells_occupied.push_back( cell_index ); if ((corner.X()+=m_CellSize.X())>object_bb.max.X()) { corner.X() = object_bb.min.X(); if ( (corner.Z()+=m_CellSize.Z())>object_bb.max.Z() ) { corner.Z() = object_bb.min.Z(); corner.Y() += m_CellSize.Y(); } } } } /*! * Return the number of cells of the uniform grid where there are no item of the input dataset. * \return The number of cells occupied by at least one item. */ int GetNumberOfNotEmptyCells() { int number_of_not_empty_cell = 0; for (int i=0; isize()>0) number_of_not_empty_cell++; return number_of_not_empty_cell; } /*! * Returns the number of entries for each side of the grid. * \return The resolution of the UniformGrid in each dimension. */ inline int GetResolution() const { return m_CellPerSide; } /*! * Return the pointer to a vector containing pointers to the objects falling in a given domain cell. * @param[in] at The index of the cell of the uniform grid where looking for * \return A pointer to a vector of pointers to the objects falling in the cell having index at. */ std::vector< ObjectPointer >* GetObjects(const int i, const int j, const int k) { return &m_Grid[i][j][k]; } std::vector< ObjectPointer >* GetObjects(const CellCoordinate &at) { return &m_Grid[at.X()][at.Y()][at.Z()];} std::vector< ObjectPointer >* operator[](const CellCoordinate &at) { return &m_Grid[at.X()][at.Y()][at.Z()];} protected: std::vector< std::vector< std::vector< std::vector< ObjectPointer > > > > m_Grid; /*!< The uniform grid */ BoundingBoxType m_BoundingBox; /*!< The bounding box of the uniform grid. */ int m_CellPerSide; /*!< The number of cell per side. */ CoordinateType m_CellSize; /*!< The dimension of each cell. */ }; //end of class UniformGrid /************************************************************************/ /*! \class HashTable * This class substitutes the uniform grid. */ /************************************************************************/ class HashTable { public: typedef vcg::Point3i EntryCoordinate; // We preferred using the Data structure instead of a pointer // to the vector of the domain elements just for extensibility struct Data { /*! * Default constructor */ Data(std::vector< ObjectPointer > *data) { domain_data = data; } std::vector< ObjectPointer > *domain_data; }; /*! * Default constructor */ HashTable() {} /*! * Default destructor */ ~HashTable() { Clear(true); } /*! * */ NeighboringEntryIterator GetNeighborintEntryIterator(const EntryCoordinate &at) { return NeighboringEntryIterator(at, m_EntryPerSide); } /*! * Allocates the space for the hash table; the number of entries created is entry_per_side^3. * @param[in] entry_per_side The number of entries for each size */ void Allocate(const int entry_per_side) { m_EntryPerSide = entry_per_side; m_Table.resize(m_EntryPerSide); for (int i=0; i *domain_data = pData->domain_data; pData->domain_data = new std::vector< ObjectPointer>( *domain_data ); } m_FreeEntries.clear(); } /*! * Inserts each entry in the hash table in the free entry list. * When this function is called, each entry in the hash table must be free. */ void BuildFreeEntryList() { m_FreeEntries.clear(); for (int i=0; idomain_data; delete m_Table[i][j][k]; m_Table[i][j][k] = NULL; } m_FreeEntries.clear(); } /*! * Returns the reference to the free entry list * \return The reference to the free entry list */ std::list< EntryCoordinate >* GetFreeEntryList() { return &m_FreeEntries; } /*! * Maps a given domain entry index into a hash table index. * It corresponds to the \f$f_0\f$ function in the original article. */ EntryCoordinate DomainToHashTable(const typename UniformGrid::CellCoordinate &p) { EntryCoordinate result; result.X() = p.X()%m_EntryPerSide; result.Y() = p.Y()%m_EntryPerSide; result.Z() = p.Z()%m_EntryPerSide; return result; } /*! * Inserts a new element in the hash table at the given position. * @param[in] at The position in the hash table where the new element will be created * @param[in] data The set of the domain elements contained in this entry */ void SetEntry(const EntryCoordinate &at, std::vector< ObjectPointer > *data) { assert(IsFree(at)); m_Table[at.X()][at.Y()][at.Z()] = new Data(data); m_FreeEntries.remove(at); } /*! * Given a hash table entry, this function modifies its coordinates in order to guarantee that * they are in the valid range. Call this function before accessing the hash table. * @param[in, out] entry The entry whose coordinates have to be checked. */ void ValidateEntry(EntryCoordinate &entry) { while (entry.X()<0) entry.X()+=m_EntryPerSide; while (entry.Y()<0) entry.Y()+=m_EntryPerSide; while (entry.Z()<0) entry.Z()+=m_EntryPerSide; } /*! * Check if a given position in the hash table is free. * @param[in] at The position of the hash table to check. * \return True if and only if the hash table is free at the given position. */ inline bool IsFree(const EntryCoordinate &at) const { return (GetData(at)==NULL); } /*! */ inline int GetSize() { return m_EntryPerSide; } /*! * Returns the number of free entries. */ inline int GetNumberOfFreeEntries() { return int(m_FreeEntries.size()); } /*! * Return the number of entries where there is some domain data. */ inline int GetNumberOfNotEmptyEntries() { return (int(powf(float(m_EntryPerSide), 3.0f))-int(m_FreeEntries.size())); } /*! * Return the pointer to the data stored in the hash table at the given position. * @param[in] at The position of the hash table where looks for the data. * \return A pointer to a valid data only if a valid pointer is stored in the hash * table at the given position; otherwise return NULL. */ inline Data* GetData (const int i, const int j, const int k) const { return m_Table[i][j][k]; } inline Data* GetData (const EntryCoordinate &at) const { return m_Table[at.X()][at.Y()][at.Z()]; } inline Data* operator[](const EntryCoordinate &at) const { return m_Table[at.X()][at.Y()][at.Z()]; } protected: int m_EntryPerSide; /*!< The number of entries for each side of the hash-table. */ std::vector< std::vector< std::vector < Data* > > > m_Table; /*!< The table. */ std::list< EntryCoordinate > m_FreeEntries; /*!< The list containing the free entries. */ }; //end of class HashTable /************************************************************************/ /*! \class OffsetTable * This class containts the offsets used for shifting the access to the hash table. */ /************************************************************************/ class OffsetTable { public: typedef unsigned char OffsetType; typedef vcg::Point3 Offset; typedef Offset * OffsetPointer; typedef vcg::Point3i EntryCoordinate; /*! \struct PreImage * This class represents the pre-image for a given entry in the offset table, that is the set * \f$h_1^{-1}(q)={p \in S s.t. h_1(p)=q}\f$ */ struct PreImage { /*! * Default constructor. * @param[in] at The entry in the offset table where the cells in the preimage are mapped into. * @param[in] preimage The set of UniformGrid cells mapping to this entry. */ PreImage(EntryCoordinate &at, std::vector< typename UniformGrid::CellCoordinate > *preimage) { entry_index = at; pre_image = preimage; cardinality = int(pre_image->size()); } /*! * less-than operator: needed for sorting the preimage slots based on their cardinality. * @param second * \return true if and only if the cardinality of this preimage slot is greater than that of second. */ inline bool operator<(const PreImage &second) const { return (cardinality>second.cardinality); } std::vector< typename UniformGrid::CellCoordinate > * pre_image; /*!< The set of entries in the uniform grid whose image through \f$h_1\f$ is this entry.*/ EntryCoordinate entry_index; /*!< The index of the entry inside the offset table. */ int cardinality; /*!< The cardinality of the pre-image. */ }; // end of struct PreImage /*! * Default constructor */ OffsetTable() { m_EntryPerSide=-1; m_NumberOfOccupiedEntries=0;} /*! * Destructor */ ~OffsetTable() { Clear(); } /*! * Clear the entries in the offset table and in the preimage table. */ void Clear() { for (int i=0; im_H1PreImage grid contains, for each * cell (i, j, k) a list of the domain grid (the UniformGrid) that are mapped through \f$h_1\f$ into that cell. */ void BuildH1PreImage(const typename UniformGrid::EntryIterator &begin, const typename UniformGrid::EntryIterator &end) { for (typename UniformGrid::EntryIterator iter=begin; iter!=end; iter++) { if ((*iter)->size()==0) continue; typename UniformGrid::CellCoordinate cell_index = iter.GetPosition(); EntryCoordinate at = DomainToOffsetTable(cell_index); m_H1PreImage[at.X()][at.Y()][at.Z()].push_back(cell_index); } } /*! * Sorts the entries of the PreImage table based on their cardinality. * @param[out] preimage The list containing the entries of the preimage sorted by cardinality */ void GetPreImageSortedPerCardinality(std::list< PreImage > &pre_image) { pre_image.clear(); for (int i=0; i *preimage = &m_H1PreImage[i][j][k]; if (preimage->size()>0) pre_image.push_back( PreImage(typename UniformGrid::CellCoordinate(i, j, k), preimage) ); } pre_image.sort(); } /*! * Check if the entries in the offset table near the given entry contain a valid offset. * @param[in] at The entry of the offset table whose neighboring entries will be checked. * @param[out] offsets The set of consistent offset found by inspecting the neighboring entries. * \return a vector containing possible offsets for the given entry */ void SuggestConsistentOffsets(const EntryCoordinate &at, std::vector< Offset > &offsets) { offsets.clear(); for (int i=-1; i<2; i++) for (int j=-1; j<2; j++) for (int k=-1; k<2; k++) { if (i==0 && j==0 && k==0) continue; int x = (at.X()+i+m_EntryPerSide)%m_EntryPerSide; int y = (at.Y()+j+m_EntryPerSide)%m_EntryPerSide; int z = (at.Z()+k+m_EntryPerSide)%m_EntryPerSide; EntryCoordinate neighboring_entry(x, y, z); if (!IsFree(neighboring_entry)) offsets.push_back( *GetOffset(neighboring_entry) ); } } /*! * Assures that the given entry can be used to access the offset table without throwing an out-of-bound exception. * @param[in,out] entry The entry to be checked. */ void ValidateEntryCoordinate(EntryCoordinate &entry) { while (entry.X()<0) entry.X()+=m_EntryPerSide; while (entry.Y()<0) entry.Y()+=m_EntryPerSide; while (entry.Z()<0) entry.Z()+=m_EntryPerSide; } /*! * Converts the coordinate of a given cell in the UniformGrid to a valid entry in the offset table. * This function corresponds to the \f$h_1\f$ function of the article. * @param[in] coord The index of a domain cell in the UniformGrid. * \return The coordinate of the entry corresponding to coord through this mapping. */ EntryCoordinate DomainToOffsetTable(const typename UniformGrid::CellCoordinate &coord) { EntryCoordinate result; result.X() = coord.X()%m_EntryPerSide; result.Y() = coord.Y()%m_EntryPerSide; result.Z() = coord.Z()%m_EntryPerSide; return result; } /*! * Adds a new element to the offset table. * @param[in] coord The index of the UniformGrid cell whose offset has to be stored. * @param[in] offset The offset to associate to the given UniformGrid cell. */ void SetOffset(const typename UniformGrid::CellCoordinate &coord, const Offset &offset) { EntryCoordinate entry = DomainToOffsetTable(coord); assert(IsFree(entry)); m_Table[entry.X()][entry.Y()][entry.Z()] = new Offset(offset); m_NumberOfOccupiedEntries++; } /*! * Return a random offset: this function is used during the first steps of the creation process, * when the offsets are computed at random. * @param[out] A random offset */ void GetRandomOffset( Offset &offset ) { offset.X() = OffsetType(rand()%m_MAX_VERSOR_LENGTH); offset.Y() = OffsetType(rand()%m_MAX_VERSOR_LENGTH); offset.Z() = OffsetType(rand()%m_MAX_VERSOR_LENGTH); } /*! * Return the number of entries of the offset table for each dimension. * \return The number of entries for each side */ inline int GetSize() const {return m_EntryPerSide;} /*! * Checks if the given entry in the offset table is free * @param[in] at The coordinate of the entry to be checked. * \return true if and only if the entry with coordinate at is free. */ inline bool IsFree(const EntryCoordinate &at) const { return GetOffset(at)==NULL; } //{ return m_Table[at.X()][at.Y()][at.Z()]==NULL; } /*! * Return the number of entries containing a valid offset. * \return The number of not empty entries. */ inline int GetNumberOfOccupiedCells() const { return m_NumberOfOccupiedEntries; } /*! * Return the pointer to the offset stored at the given entry. NULL if that entry doesn't contain a offset */ inline OffsetPointer& GetOffset (const int i, const int j, const int k) { return m_Table[i][j][k]; } inline OffsetPointer GetOffset (const int i, const int j, const int k) const { return m_Table[i][j][k]; } inline OffsetPointer& GetOffset (const EntryCoordinate &at) { return m_Table[at.X()][at.Y()][at.Z()]; } inline OffsetPointer GetOffset (const EntryCoordinate &at) const { return m_Table[at.X()][at.Y()][at.Z()]; } inline OffsetPointer& operator[](const EntryCoordinate &at) { return m_Table[at.X()][at.Y()][at.Z()]; } inline OffsetPointer operator[](const EntryCoordinate &at) const { return m_Table[at.X()][at.Y()][at.Z()]; } protected: const static int m_MAX_VERSOR_LENGTH = 256; /*!< The maximal length of the single component of each offset. */ int m_EntryPerSide; /*!< The resolution of the offset table. */ int m_NumberOfOccupiedEntries; /*!< The number of entries containing a valid offset. */ std::vector< std::vector< std::vector< OffsetPointer > > > m_Table; /*!< The offset table. */ std::vector< std::vector< std::vector< std::vector< typename UniformGrid::CellCoordinate > > > > m_H1PreImage; /*!< The \f$f1\f$ pre-image. */ }; //end of class OffsetTable /*******************************************************************************************************************************/ /*! \class BinaryImage * This class is used to encode the sparsity of the dataset. Since the hash table stores data associated with a sparse * subset of the domain, it may be necessary to determine if an arbitrary query point lies in this defined domain. */ /*******************************************************************************************************************************/ class BinaryImage { public: /*! * Default constructor */ BinaryImage() { m_Resolution = -1; } /*! * Destructor */ ~BinaryImage() {} /*! * Allocate the space necessary to encode the distribution of the dataset over the domain. * @param[in] size The resolution on each dimension of the bitmap. */ void Allocate(const int size) { m_Resolution = size; m_Mask.resize(m_Resolution); for (int i=0; iat. * @param[in] at The index of the UniformGrid cell to check. * \return true if and only if a portion of the dataset in included in this UniformGrid cell. */ inline bool ContainsData(const typename UniformGrid::CellCoordinate &at) const { return GetFlag(at)==true;} /*! * Returns the number of entries in each dimension. * \return The resolution of the BinaryImage. */ inline int GetResolution() const { return m_Resolution; } /*! * Return the value stored in the d-dimensional bitmap at the given position. * @param[in] i * @param[in] j * @param[in] k * \return */ inline bool operator()(const int i, const int j, const int k) { return m_Mask[i][j][k]; } /*! * Return the value stored at the given position in the d-dimensional bitmap. * @param[in] at * \return */ inline bool operator[](const typename UniformGrid::CellCoordinate &at) { return m_Mask[at.X()][at.Y()][at.Z()]; } inline bool& GetFlag(const int i, const int j, const int k)const { return m_Mask[i][j][k]; } inline void SetFlat(const int i, const int j, const int k) { m_Mask[i][j][k] = true; } inline bool GetFlag(const typename UniformGrid::CellCoordinate &at) const { return m_Mask[at.X()][at.Y()][at.Z()]; } inline void SetFlag(const typename UniformGrid::CellCoordinate &at) { m_Mask[at.X()][at.Y()][at.Z()] = true; } protected: std::vector< std::vector< std::vector< bool > > > m_Mask; /*!< The bitmap image. */ int m_Resolution; /*!< The resolution of the bitmap. */ }; // end of class BinaryImage /*******************************************************************************************************************************/ /*! \struct Neighbor * This class is used to retrieve the neighboring objects in the spatial queries and to sort them. */ /*******************************************************************************************************************************/ struct Neighbor { /*! * Default constructor */ Neighbor() { object = NULL; distance = ScalarType(-1.0); nearest_point.Zero(); } /*! * Constructor * @param[in] pObject The pointer to the object. * @param[in] dist The distance between the object and the query point. * @param[in] point The point on the object having minimal distance from the query point. */ Neighbor(ObjectPointer pObject, ScalarType dist, CoordinateType point) { object = pObject; distance = dist; nearest_point(point); } /*! * Less than operator. Needed for sorting a range of neighbor based on their distance from the query object. */ inline bool operator<(const Neighbor &second) { return distance void Set(const OBJECT_ITERATOR & bObj, const OBJECT_ITERATOR & eObj) { Set(bObj, eObj, FastConstructionApproach, NULL); } template < class OBJECT_ITERATOR > void Set(const OBJECT_ITERATOR & bObj, const OBJECT_ITERATOR & eObj, vcg::CallBackPos *callback) { Set(bObj, eObj, FastConstructionApproach, callback); } template < class OBJECT_ITERATOR > void Set(const OBJECT_ITERATOR & bObj, const OBJECT_ITERATOR & eObj, const ConstructionApproach approach) { Set(bObj, eObj, approach, NULL); } /*! * Add the elements to the PerfectSpatialHashing data structure. Since this structure can handle only * static dataset, the elements mustn't be changed while using this structure. * @param[in] bObj The iterator addressing the first element to be included in the hashing. * @param[in] eObj The iterator addressing the position after the last element to be included in the hashing. * @param[in] approach Either FastConstructionApproach or CompactConstructionApproach. * @param[in] callback The callback to call to provide information about the progress of the computation. */ template < class OBJECT_ITERATOR > void Set(const OBJECT_ITERATOR & bObj, const OBJECT_ITERATOR & eObj, const ConstructionApproach approach, vcg::CallBackPos *callback) { BoundingBoxType bounding_box; BoundingBoxType object_bb; bounding_box.SetNull(); for (OBJECT_ITERATOR iObj=bObj; iObj!=eObj; iObj++) { (*iObj).GetBBox(object_bb); bounding_box.Add(object_bb); } //...and expand it a bit more BoundingBoxType resulting_bb(bounding_box); CoordinateType offset = bounding_box.Dim()*float(m_BOUNDING_BOX_EXPANSION_FACTOR); CoordinateType center = bounding_box.Center(); resulting_bb.Offset(offset); float longest_side = vcg::math::Max( resulting_bb.DimX(), vcg::math::Max(resulting_bb.DimY(), resulting_bb.DimZ()) )/2.0f; resulting_bb.Set(center); resulting_bb.Offset(longest_side); int number_of_objects = int(std::distance(bObj, eObj)); // Try to find a reasonable space partition #ifdef _USE_GRID_UTIL_PARTIONING_ vcg::Point3i resolution; vcg::BestDim(number_of_objects, resulting_bb.Dim(), resolution); int cells_per_side = resolution.X(); #else ifdef _USE_OCTREE_PARTITIONING_ // Alternative to find the resolution of the uniform grid: int primitives_per_voxel; int depth = 4; do { int number_of_voxel = 1<<(3*depth); // i.e. 8^depth float density = float(number_of_voxel)/float(depth); primitives_per_voxel = int(float(number_of_objects)/density); depth++; } while (primitives_per_voxel>16 && depth<15); int cells_per_side = int(powf(2.0f, float(depth))); #endif m_UniformGrid.Allocate(resulting_bb, cells_per_side); m_UniformGrid.InsertElements(bObj, eObj); m_Bitmap.Allocate(cells_per_side); int number_of_cells_occupied = m_UniformGrid.GetNumberOfNotEmptyCells(); int hash_table_size = (int) ceilf(powf(float(number_of_cells_occupied), 1.0f/float(m_DIMENSION))); if (hash_table_size>256) hash_table_size = (int) ceilf(powf(1.01f*float(number_of_cells_occupied), 1.0f/float(m_DIMENSION))); m_HashTable.Allocate(hash_table_size); switch (approach) { case FastConstructionApproach : PerformFastConstruction(number_of_cells_occupied, callback) ; break; case CompactConstructionApproach: PerformCompactConstruction(number_of_cells_occupied, callback); break; default: assert(false); } Finalize(); } // end of method Set /*! * Returns all the objects contained inside a specified sphere * @param[in] distance_functor * @param[in] marker * @param[in] sphere_center * @param[in] sphere_radius * @param[out] objects * @param[out] distances * @param[out] points * \return */ template unsigned int GetInSphere ( OBJECT_POINT_DISTANCE_FUNCTOR & distance_functor, OBJECT_MARKER & marker, const CoordType & sphere_center, const ScalarType & sphere_radius, OBJECT_POINTER_CONTAINER & objects, DISTANCE_CONTAINER & distances, POINT_CONTAINER & points, bool sort_per_distance = true, bool allow_zero_distance = true ) { BoundingBoxType query_bb(sphere_center, sphere_radius); vcg::Box3i integer_bb = m_UniformGrid.Interize(query_bb); vcg::Point3i index; std::vector< std::vector< ObjectPointer >* > contained_objects; std::vector< ObjectPointer >* tmp; for (index.X()=integer_bb.min.X(); index.X()<=integer_bb.max.X(); index.X()++) for (index.Y()=integer_bb.min.Y(); index.Y()<=integer_bb.max.Y(); index.Y()++) for (index.Z()=integer_bb.min.Z(); index.Z()<=integer_bb.max.Z(); index.Z()++) if ((tmp=(*this)[index])!=NULL) contained_objects.push_back(tmp); std::vector< Neighbor > results; for (std::vector< std::vector< ObjectPointer >* >::iterator iVec=contained_objects.begin(), eVec=contained_objects.end(); iVec!=eVec; iVec++) for (std::vector< ObjectPointer >::iterator iObj=(*iVec)->begin(), eObj=(*iVec)->end(); iObj!=eObj; iObj++ ) { int r = int(results.size()); results.push_back(Neighbor()); results[r].object = *iObj; results[r].distance = sphere_radius; if (!distance_functor(*results[r].object, sphere_center, results[r].distance, results[r].nearest_point) || (results[r].distance==ScalarType(0.0) && !allow_zero_distance) ) results.pop_back(); } if (sort_per_distance) std::sort( results.begin(), results.end() ); int number_of_objects = int(results.size()); distances.resize(number_of_objects); points.resize(number_of_objects); objects.resize(number_of_objects); for (int i=0, size=int(results.size()); i* operator[](const CoordinateType &query) { typename UniformGrid::CellCoordinate ug_index = m_UniformGrid.Interize(query); if (!m_Bitmap[ug_index]) return NULL; HashTable::EntryCoordinate ht_index = PerfectHashFunction(ug_index); std::vector< ObjectPointer >* result = m_HashTable[ht_index]; return result; } std::vector< ObjectPointer >* operator[](const typename UniformGrid::CellCoordinate &query) { if(!m_Bitmap[query]) return NULL; HashTable::EntryCoordinate ht_index = PerfectHashFunction(query); std::vector< ObjectPointer >* result = m_HashTable[ht_index]->domain_data; return result; } protected: /*! * The injective mapping from the set of occupied cells to a slot in the hash-table * @param[in] query The index of a domain cell whose mapping has to be calculated. * @param[out] result The index of a entry in the hash-table where query is mapped into. */ typename HashTable::EntryCoordinate PerfectHashFunction(const typename UniformGrid::CellCoordinate &query) { typename HashTable::EntryCoordinate result; OffsetTable::OffsetPointer offset = m_OffsetTable[ m_OffsetTable.DomainToOffsetTable(query) ]; result = m_HashTable.DomainToHashTable( Shift(query, *offset) ); return result; } /*! * Performs the addition between a entry coordinate and an offset. * @param[in] entry The index of a given cell. * @param[in] offset The offset that must be applied to the entry. * \return The entry resulting by the addition of entry and offset. */ typename HashTable::EntryCoordinate Shift(const vcg::Point3i &entry, const typename OffsetTable::Offset &offset) { HashTable::EntryCoordinate result; result.X() = entry.X() + int(offset.X()); result.Y() = entry.Y() + int(offset.Y()); result.Z() = entry.Z() + int(offset.Z()); return result; } /*! * Finalizes the data structures at the end of the offset-table construction. * This function eliminates all unnecessary data, and encodes sparsity. * TODO At the moment, the sparsity encoding is implemented thought a bitmap, i.e. a boolean grid * where each slot tells if the relative UniformGrid has a valid entry in the HashTable. */ void Finalize() { #ifdef _DEBUG for (UniformGrid::EntryIterator iUGEntry=m_UniformGrid.Begin(), eUGEntry=m_UniformGrid.End(); iUGEntry!=eUGEntry; iUGEntry++) assert(m_Bitmap.ContainsData(iUGEntry.GetPosition())==((*iUGEntry)->size()>0)); #endif m_HashTable.Finalize(); m_UniformGrid.Finalize(); m_OffsetTable.Finalize(); } /*! * Check if the given offset is valid for a set of domain cell. * @param[in] pre_image * @param[in] offset * \return */ bool IsAValidOffset(const std::vector< typename UniformGrid::CellCoordinate > *pre_image, const typename OffsetTable::Offset &offset) { int ht_size = m_HashTable.GetSize(); int sqr_ht_size = ht_size*ht_size; std::vector< int > involved_entries; for (int i=0, pre_image_size=int((*pre_image).size()); i::max(); int hash_table_size = m_HashTable.GetSize(); int half_hash_table_size = int(float(hash_table_size)/2.0f); // According to the original article, a maximum number of trials are to be made in order to select the optimal (i.e. minimal) offset table size for (int t=0; ttrue if and only if the construction of the offset table succeeds. */ bool OffsetTableConstructionSucceded(const int offset_table_size, vcg::CallBackPos *callback) { m_OffsetTable.Allocate(offset_table_size); // Create the Offset table m_OffsetTable.BuildH1PreImage(m_UniformGrid.Begin(), m_UniformGrid.End()); // Build the f0 pre-image std::list< OffsetTable::PreImage > preimage_slots; m_OffsetTable.GetPreImageSortedPerCardinality(preimage_slots); char msg[128]; sprintf(msg, "Building offset table of resolution %d", m_OffsetTable.GetSize()); int step = int(preimage_slots.size())/100; int number_of_slots = int(preimage_slots.size()); int perc = 0; int iter = 0; for (std::list< OffsetTable::PreImage >::iterator iPreImage=preimage_slots.begin(), ePreImage=preimage_slots.end(); iPreImage!=ePreImage; iPreImage++, iter++) { if (callback!=NULL && iter%step==0 && (perc=iter*100/number_of_slots)<100) (*callback)(perc, msg); bool found_valid_offset = false; typename OffsetTable::Offset candidate_offset; // Heuristic #1: try to set the offset value to one stored in a neighboring entry of the offset table std::vector< typename OffsetTable::Offset > consistent_offsets; m_OffsetTable.SuggestConsistentOffsets( (*iPreImage).entry_index, consistent_offsets); for (std::vector< typename OffsetTable::Offset >::iterator iOffset=consistent_offsets.begin(), eOffset=consistent_offsets.end(); iOffset!=eOffset && !found_valid_offset; iOffset++) if (IsAValidOffset(iPreImage->pre_image, *iOffset)) { found_valid_offset = true; candidate_offset = *iOffset; } // Heuristic #2: if (!found_valid_offset) { std::vector< typename UniformGrid::CellCoordinate > *pre_image = (*iPreImage).pre_image; for (std::vector< typename UniformGrid::CellCoordinate >::iterator iPreImage=pre_image->begin(), ePreImage=pre_image->end(); iPreImage!=ePreImage && !found_valid_offset; iPreImage++) for (NeighboringEntryIterator iUGNeighbourhood=m_UniformGrid.GetNeighboringEntryIterator(*iPreImage); iUGNeighbourhood<6 && !found_valid_offset; iUGNeighbourhood++ ) if (!m_OffsetTable.IsFree( m_OffsetTable.DomainToOffsetTable( *iUGNeighbourhood ) )) { HashTable::EntryCoordinate ht_entry = PerfectHashFunction(*iUGNeighbourhood); for (NeighboringEntryIterator iHTNeighbourhood=m_HashTable.GetNeighborintEntryIterator(ht_entry); iHTNeighbourhood<6 && !found_valid_offset; iHTNeighbourhood++) if (m_HashTable.IsFree(*iHTNeighbourhood)) { candidate_offset.Import( *iHTNeighbourhood-m_HashTable.DomainToHashTable(*iPreImage) ) ; // m_OffsetTable.ValidateEntry( candidate_offset ); Is'n necessary, becouse the offset type is unsigned char. if (IsAValidOffset(pre_image, candidate_offset)) found_valid_offset = true; } } } if (!found_valid_offset) { // At the beginning, the offset can be found via random searches for (int i=0; iat(0); do m_OffsetTable.GetRandomOffset(candidate_offset); while (!m_HashTable.IsFree( m_HashTable.DomainToHashTable( Shift(base_entry, candidate_offset) ) )); if (IsAValidOffset( (*iPreImage).pre_image, candidate_offset)) found_valid_offset = true; } // The chance to find a valid offset table via random searches decreases toward the end of the offset table construction: // So a exhaustive search over all the free hash table entries is performed. for (std::list< HashTable::EntryCoordinate >::const_iterator iFreeCell=m_HashTable.GetFreeEntryList()->begin(), eFreeCell=m_HashTable.GetFreeEntryList()->end(); iFreeCell!=eFreeCell && !found_valid_offset; iFreeCell++) { UniformGrid::CellCoordinate domain_entry = (*iPreImage).pre_image->at(0); OffsetTable::EntryCoordinate offset_entry = m_OffsetTable.DomainToOffsetTable(domain_entry); HashTable::EntryCoordinate hashtable_entry = m_HashTable.DomainToHashTable(domain_entry); candidate_offset.Import(*iFreeCell - hashtable_entry); if ( IsAValidOffset(iPreImage->pre_image, candidate_offset) ) found_valid_offset = true; } } // If a valid offset has been found, the construction of the offset table continues, // otherwise the offset table must be enlarged and the construction repeated if (found_valid_offset) { m_OffsetTable.SetOffset( (*iPreImage->pre_image).at(0), candidate_offset); for (int c=0, pre_image_cardinality = iPreImage->cardinality; cpre_image).at(c)); std::vector< ObjectPointer > *domain_data = m_UniformGrid[ (*iPreImage->pre_image).at(c) ]; m_HashTable.SetEntry(ht_entry, domain_data /*, (*iPreImage->pre_image).at(c)*/); // might be useful for encoding sparsity m_Bitmap.SetFlag((*iPreImage->pre_image).at(c)); } } else { m_OffsetTable.Clear(); m_HashTable.Clear(); m_HashTable.BuildFreeEntryList(); m_Bitmap.Clear(); return false; } } if (callback!=NULL) (*callback)(100, msg); return true; } // end of OffsetTableConstructionSucceded /************************************************************************/ /* Data Members */ /************************************************************************/ protected: UniformGrid m_UniformGrid; /*!< The uniform grid used for partitioning the volume. */ OffsetTable m_OffsetTable; /*!< The offset table corresponding to \f$\Phi\f$ in the article. */ HashTable m_HashTable; /*!< The hash table that will substitute the uniform grid. */ BinaryImage m_Bitmap; const static float m_BOUNDING_BOX_EXPANSION_FACTOR; const static float m_SIGMA; const static int m_MAX_TRIALS_IN_COMPACT_CONSTRUCTION; const static int m_MAX_NUM_OF_RANDOM_GENERATED_OFFSET; const static int m_DIMENSION; }; //end of class PerfectSpatialHashing /*! @} */ //end of Doxygen documentation }//end of namespace vcg template < class OBJECT_TYPE, class SCALAR_TYPE > const int vcg::PerfectSpatialHashing< OBJECT_TYPE, SCALAR_TYPE >::m_MAX_NUM_OF_RANDOM_GENERATED_OFFSET = 32; template < class OBJECT_TYPE, class SCALAR_TYPE > const int vcg::PerfectSpatialHashing< OBJECT_TYPE, SCALAR_TYPE >::m_MAX_TRIALS_IN_COMPACT_CONSTRUCTION = 5; template < class OBJECT_TYPE, class SCALAR_TYPE > const int vcg::PerfectSpatialHashing< OBJECT_TYPE, SCALAR_TYPE >::m_DIMENSION = 3; template < class OBJECT_TYPE, class SCALAR_TYPE > const SCALAR_TYPE vcg::PerfectSpatialHashing< OBJECT_TYPE, SCALAR_TYPE >::m_BOUNDING_BOX_EXPANSION_FACTOR = SCALAR_TYPE(0.035); template < class OBJECT_TYPE, class SCALAR_TYPE > const SCALAR_TYPE vcg::PerfectSpatialHashing< OBJECT_TYPE, SCALAR_TYPE >::m_SIGMA = SCALAR_TYPE(1.0f/(2.0f*SCALAR_TYPE(m_DIMENSION))); #endif //VCG_SPACE_INDEX_PERFECT_SPATIAL_HASHING_Hqutemol/vcg/vcg/space/index/base.h0000444000175000017500000003167210320234254015451 0ustar mbamba/**************************************************************************** * VCGLib o o * * Visual and Computer Graphics Library o o * * _ O _ * * Copyright(C) 2004 \/)\/ * * Visual Computing Lab /\/| * * ISTI - Italian National Research Council | * * \ * * All rights reserved. * * * * 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. * * * * 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 (http://www.gnu.org/licenses/gpl.txt) * * for more details. * * * ****************************************************************************/ /**************************************************************************** History $Log: base.h,v $ Revision 1.2 2005/10/03 13:57:00 pietroni added GetInSphere and GetInBox functions Revision 1.1 2005/09/28 17:19:28 m_di_benedetto First Commit. ****************************************************************************/ #ifndef __VCGLIB_SPATIALINDEX_H #define __VCGLIB_SPATIALINDEX_H // standard headers #include // vcg headers #include #include #include namespace vcg { /**************************************************************************** Class SpatialIndex Description: This class exposes the base interface for all spatial indexing data structures, i.e. grids, bounding volume trees. Template Parameters: OBJTYPE: Type of the indexed objects. SCALARTYPE: Scalars type for structure's internal data (may differ from object's scalar type). ****************************************************************************/ template class SpatialIndex { public: /************************************************************************** Commonly used typedefs. **************************************************************************/ typedef SpatialIndex ClassType; typedef OBJTYPE ObjType; typedef SCALARTYPE ScalarType; typedef ObjType * ObjPtr; typedef Point3 CoordType; typedef vcg::Box3 BoxType; /************************************************************************** Method Set. Description: The Set method initializes the spatial structure. Template Parameters: OBJITER: Objects Container's iterator type. Method Parameters: _oBegin : [IN] begin objects container's iterator _oEnd : [IN] end objects container's iterator Return Value: None. **************************************************************************/ template void Set(const OBJITER & _oBegin, const OBJITER & _oEnd) { assert(0); // this is a base interface. (void)_oBegin; // avoid "unreferenced parameter" compiler warning. (void)_oEnd; } /************************************************************************** Method GetClosest. Description: The GetClosest method finds the closest object given a point. It also finds the closest point and minimum distance. Template Parameters: OBJPOINTDISTFUNCTOR : Object-Point distance functor type; this type must implement an operator () with signature bool operator () (const ObjType & obj, const CoordType & p, ScalarType & d, CoordType & q) where: obj [IN] is a reference to the current object being tested, p [IN] is the query point, d [IN/OUT] is in input the reject distance and in output the closest distance, q [OUT] is the closest point. The operator returns true if the closest distance is less than input reject distance. OBJMARKER : The type of a marker functor. Method Parameters: _getPointDistance : [IN] Functor for point-distance calculation. _marker : [IN] Functor for marking objects already tested. _p : [IN] The query point. _maxDist : [IN] Maximum reject distance. _minDist : [OUT] Closest distance. _closestPt : [OUT] Closest point. Return Value: A pointer to the closest object (if any). **************************************************************************/ template ObjPtr GetClosest( OBJPOINTDISTFUNCTOR & _getPointDistance, OBJMARKER & _marker, const CoordType & _p, const ScalarType & _maxDist, ScalarType & _minDist, CoordType & _closestPt) { assert(0); (void)_getPointDistance; (void)_marker; (void)_p; (void)_maxDist; (void)_minDist; (void)_closestPt; return ((ObjPtr)0); } /************************************************************************** Method GetKClosest. Description: The GetKClosest method finds the K closest object given a point. It also finds the closest points and minimum distances. Template Parameters: OBJPOINTDISTFUNCTOR : Object-Point distance functor type; this type must implement an operator () with signature bool operator () (const ObjType & obj, const CoordType & p, ScalarType & d, CoordType & q) where: obj [IN] is a reference to the current object being tested, p [IN] is the query point, d [IN/OUT] is in input the reject distance and in output the closest distance, q [OUT] is the closest point. The operator returns true if the closest distance is less than input reject distance. OBJMARKER : The type of a marker functor. OBJPTRCONTAINER : The type of a object pointers container. DISTCONTAINER : The type of a container which, in return, will contain the closest distances. POINTCONTAINER : The type of a container which, in return, will contain the closest points. Method Parameters: _getPointDistance : [IN] Functor for point-distance calculation. _marker : [IN] Functor for marking objects already tested. _k : [IN] The number of closest objects to search for. _p : [IN] The query point. _maxDist : [IN] Maximum reject distance. _objectPtrs : [OUT] Container which, in return, will contain pointers to the closest objects. _distances : [OUT] Container which, in return, will contain the closest distances. _objectPtrs : [OUT] Container which, in return, will contain the closest points. Return Value: The number of closest objects found. **************************************************************************/ template unsigned int GetKClosest( OBJPOINTDISTFUNCTOR & _getPointDistance, OBJMARKER & _marker, const unsigned int _k, const CoordType & _p, const ScalarType & _maxDist, OBJPTRCONTAINER & _objectPtrs, DISTCONTAINER & _distances, POINTCONTAINER & _points) { assert(0); (void)_getPointDistance; (void)_marker; (void)_k; (void)_p; (void)_maxDist; (void)_objectPtrs; (void)_distances; (void)_points; return (0); } /************************************************************************** Method GetInSphere. Description: The GetInSphere method finds all the objects in the specified sphere Template Parameters: OBJPOINTDISTFUNCTOR : Object-Point distance functor type; this type must implement an operator () with signature bool operator () (const ObjType & obj, const CoordType & p, ScalarType & d, CoordType & q) where: obj [IN] is a reference to the current object being tested, p [IN] is the query point, d [IN/OUT] is in input the reject distance and in output the closest distance, q [OUT] is the closest point. The operator returns true if the closest distance is less than input reject distance. OBJMARKER : The type of a marker functor. OBJPTRCONTAINER : The type of a object pointers container. DISTCONTAINER : The type of a container which, in return, will contain the closest distances. POINTCONTAINER : The type of a container which, in return, will contain the closest points. Method Parameters: _getPointDistance : [IN] Functor for point-distance calculation. _marker : [IN] Functor for marking objects already tested. _p : [IN] The query point. _r : [IN] The radius of the specified sphere. _objectPtrs : [OUT] Container which, in return, will contain pointers to the in-sphere objects. _distances : [OUT] Container which, in return, will contain the in-sphere distances. _objectPtrs : [OUT] Container which, in return, will contain the in-sphere nearests points for each object. Return Value: The number of in-sphere objects found. **************************************************************************/ template unsigned int GetInSphere( OBJPOINTDISTFUNCTOR & _getPointDistance, OBJMARKER & _marker,const CoordType & _p, const ScalarType & _r,OBJPTRCONTAINER & _objectPtrs, DISTCONTAINER & _distances, POINTCONTAINER & _points) { assert(0); (void)_getPointDistance; (void)_marker; (void)_p; (void)_r; (void)_objectPtrs; (void)_distances; (void)_points; return (0); } /************************************************************************** Method GetInBox. Description: The GetInBox returns all the object in the specified bbox Template Parameters: OBJMARKER : The type of a marker functor. OBJPTRCONTAINER : The type of a object pointers container. Method Parameters: _marker : [IN] Functor for marking objects already tested. _bbox : [IN] The bounding box of spatial query. _objectPtrs : [OUT] Container which, in return, will contain pointers to the closest objects. Return Value: The number of in-box objects found. **************************************************************************/ template unsigned int GetInBox(OBJMARKER & _marker, const BoxType _bbox,OBJPTRCONTAINER & _objectPtrs) { assert(0); (void)_marker; (void)_bbox; (void)_objectPtrs; return (0); } /************************************************************************** Method DoRay. Description: The DoRay method finds the first object in the structure hit by a ray. Template Parameters: OBJRAYISECTFUNCTOR : Object-Ray intersection functor type; this type must implement an operator () with signature bool operator () (const ObjType & obj, const Ray3 ray, ScalarType & t) where: obj [IN] is a reference to the current object being tested, ray [IN] is the query ray, t [OUT] is the parameter of the ray equation at which intersection occurs. The operator returns true if the the object has been hit by the ray (i.e. they intersect). OBJMARKER : The type of a marker functor. Method Parameters: _rayIntersector : [IN] Functor for object-ray intersection. _marker : [IN] Functor for marking objects already tested. _ray : [IN] The query ray. _maxDist : [IN] Maximum reject distance. _t : [OUT] the parameter of the ray equation at which intersection occurs. Return Value: A pointer to the first object hit by the ray (if any). **************************************************************************/ template ObjPtr DoRay(OBJRAYISECTFUNCTOR & _rayIntersector, OBJMARKER & _marker, const Ray3 & _ray, const ScalarType & _maxDist, ScalarType & _t) { assert(0); (void)_rayIntersector; (void)_marker; (void)_ray; (void)_maxDist; (void)_t; return ((ObjPtr)0); } }; } // end namespace vcg #endif // #ifndef __VCGLIB_SPATIALINDEX_H qutemol/vcg/vcg/space/index/octree_template.h0000444000175000017500000005420010515363203017706 0ustar mbamba/**************************************************************************** * VCGLib o o * * Visual and Computer Graphics Library o o * * _ O _ * * Copyright(C) 2004 \/)\/ * * Visual Computing Lab /\/| * * ISTI - Italian National Research Council | * * \ * * All rights reserved. * * * * 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. * * * * 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 (http://www.gnu.org/licenses/gpl.txt) * * for more details. * * * ****************************************************************************/ #ifndef VCG_SPACE_INDEX_OCTREETEMPLATE_H #define VCG_SPACE_INDEX_OCTREETEMPLATE_H #include #include #include namespace vcg { /* Octree Template Tiene un dataset volumetrico come un octree Assunzione che la grandezza sia una potenza di due La prof max e' fissa. E' un octree in cui il dato e' nella cella dell'octree. Anche i nodi non foglia hanno il dato Voxel Assunzioni sul tipo voxel: che abbia definiti gli operatori per poterci fare sopra pushpull. Si tiene int invece di puntatori per garantirsi reallocazione dinamica. I dati veri e propri stanno in un vettore di nodi */ template class OctreeTemplate { protected: struct Node; public: // Octree Type Definitions typedef unsigned long long ZOrderType; typedef SCALAR_TYPE ScalarType; typedef VOXEL_TYPE VoxelType; typedef VoxelType * VoxelPointer; typedef vcg::Point3i CenterType; static const ScalarType EXPANSION_FACTOR; typedef Node NodeType; typedef int NodeIndex; typedef NodeType * NodePointer; typedef vcg::Box3 BoundingBoxType; typedef vcg::Point3 CoordinateType; protected: /* * Inner structures: * Contains the information related to the octree node */ struct Node { // Default constructor: fill the data members with non-meaningful values Node() { parent = NULL; level = -1; } // Constructor: create a new Node Node(NodePointer parent, int level) { this->parent = parent; this->level = (char) level; } inline virtual NodePointer &Son(int sonIndex) = 0; inline virtual bool IsLeaf() = 0; // The position of the center of the node in integer coords in the 0..2^(2*sz) -1 range // The root has position (lsz/2,lsz/2,lsz/2) CenterType center; char level; NodePointer parent; VoxelType voxel; }; /* * Inner struct: Node */ struct InnerNode : public Node { InnerNode() : Node() {}; InnerNode(NodePointer parent, int level) : Node(parent, level) { memset(&sons[0], 0, 8*sizeof(Node*)); } inline NodePointer &Son(int sonIndex) { assert(0<=sonIndex && sonIndex<=8); return sons[sonIndex]; } inline bool IsLeaf() { return false; } NodePointer sons[8]; }; /* * Inner struct: Leaf */ struct Leaf : public Node { Leaf() : Node() {}; Leaf(NodePointer parent, int level) : Node(parent, level) {} inline NodePointer &Son(int /*sonIndex*/) { assert(false); NodePointer p = NULL; return p; } inline bool IsLeaf() { return true; } }; public: // Inizializza l'octree void Initialize(int maximumDepth) { this->maximumDepth = maximumDepth; size = 1<< maximumDepth; // e.g. 1*2^maxDepth lSize = 1<<(maximumDepth+1); // e.g. 1*2^(maxDepth+1) InnerNode *root = new InnerNode(NULL,0); nodes.clear(); nodes.push_back( root ); root->center = CenterType(size, size, size); ScalarType szf = (ScalarType) size; leafDimension = boundingBox.Dim(); leafDimension /= szf; leafDiagonal = leafDimension.Norm(); }; // Return the octree bounding-box inline BoundingBoxType BoundingBox() { return boundingBox; } // Return the Voxel of the n-th node inline VoxelPointer Voxel(const NodePointer n) { return &(n->voxel); } // Return the octree node count inline int NodeCount() const { return int(nodes.size()); } // Return the root index inline const NodePointer Root() const { return nodes[0]; } // Return the level of the n-th node inline char Level(const NodePointer n) const { return n->level; } // Return the referente to the i-th son of the n-th node inline NodePointer& Son(NodePointer n, int i) const { return n->Son(i); } // Return the parent index of the n-th node inline NodePointer Parent(const NodePointer n) const { return n->parent; } // Return the index of the current node in its father int WhatSon(NodePointer n) const { if(n==Root()) assert(false); NodePointer parent = Parent(n); for(int i=0;i<8;++i) if(parent->Son(i)==n) return i; return -1; } // Return the center of the n-th node inline CenterType CenterInOctreeCoordinates(const NodePointer n) const { return n->center;} /*! * Return the center of the n-th node expressed in world-coordinate * \param NodePointer the pointer to the node whose center in world coordinate has to be computed */ inline void CenterInWorldCoordinates(const NodePointer n, CoordinateType &wc_Center) const { assert(0<=n && n>shift))); wc_Center.Y() = boundingBox.min.Y() + (nodeSize.Y()*(0.5f+(ocCenter.Y()>>shift))); wc_Center.Z() = boundingBox.min.Z() + (nodeSize.Z()*(0.5f+(ocCenter.Z()>>shift))); }; // Given a node (even not leaf) it returns the center of the box it represent. // the center is expressed not in world-coordinates. // e.g. the root is (sz/2,sz/2,sz/2); // and the finest element in the grid in lower left corner has center (.5, .5, .5) /* 4---------------- 4---------------- 4---------------- | | | | | | | | | | 3---+---+---+---| 3 | | 3 | | | | | | | | | | | 2---+---+---+---| 2---+---+---+---| 2 c | | | | | | | | | | | 1---+---+---+---| 1 b + | 1 | | a | | | | | | | | | 0---1---2---3---4 0---1---2---3---4 0---1---2---3---4 This is a tree with maxdepth==2, so sz is 2^2=4 a) a leaf at the deepest level 2 has position (.5,.5) b) a mid node (lev 1) has position (1,1) c) root has level 0 and position (sz/2,sz/2) = (2,2) The center of a node has integer coords in the 2^(MaxDepth+1) range. The other approach is to use position as a bit string codifying the tree path, but in this case you have to supply also the level (e.g. the string lenght) you desire. The lower left corner node is always 0 ( (,) for the root (0,0) level 1, and (00,00) for level 2) | ~~~ | | 0~~ | 1~~ | | 00~ | 01~ | 10~ | 11~ | |000|001|010|011|100|101|110|111| The interesting properties is that if your octree represent a space [minv,maxv] and you want to find the octree cell containing a point p in [minv,maxv] you just have to convert p in the range [0,sz) truncate it to an integer and use it as a path. For example, consider an octree of depth 3, representing a range [0..100) sz=8 (each cell contains form 0 to 12.5 the point 5 -> 0.4 -> path is 000 45 -> 3.6 -> path is 011 50 -> 4.0 -> path is 100 100 -> 8 -> ERROR the interval is right open!!! Note how each cell is meant to contains a right open interval (e.g. the first cell contains [0,12.5) and the second [12.5,25) and so on) The center of each cell can simply be obtained by adding .5 to the path of the leaves. */ CoordinateType Center(NodePointer n) const { CoordinateType center; center.Import(GetPath(n)); center+=Point3f(.5f,.5f,.5f); //TODO verify the assert assert(center==nodes[n]->center); return center; } // Return the bounding-box of the n-th node expressed in world-coordinate BoundingBoxType BoundingBoxInWorldCoordinates(const NodePointer n) { char level = Level(n); int shift = maximumDepth-level+1; CoordinateType nodeDim = boundingBox.Dim()/float(1<>shift)); nodeBB.min.Y() = boundingBox.min.Y() + (nodeDim.Y()*(center.Y()>>shift)); nodeBB.min.Z() = boundingBox.min.Z() + (nodeDim.Z()*(center.Z()>>shift)); nodeBB.max = nodeBB.min+nodeDim; return nodeBB; }; /*! * Return the bounding-box of a node expressed in world-coordinate * \param NodePointer the node whose bounding-box has to be computed * \param wc_BB the bounding-box of the node in world coordinta */ inline void BoundingBoxInWorldCoordinates(const NodePointer n, BoundingBoxType &wc_bb) const { char level = Level(n); int shift = maximumDepth - level + 1; CoordinateType node_dimension = boundingBox.Dim()/ScalarType(1<center.X()>>shift)); wc_bb.min.Y() = boundingBox.min.Y()+(node_dimension.Y()*(n->center.Y()>>shift)); wc_bb.min.Z() = boundingBox.min.Z()+(node_dimension.Z()*(n->center.Z()>>shift)); wc_bb.max = wc_bb.min+node_dimension; }; // Return one of the 8 subb box of a given box. BoundingBoxType SubBox(BoundingBoxType &lbb, int i) { BoundingBoxType bs; if (i&1) bs.min.X()=(lbb.min.X()+(bs.max.X()=lbb.max.X()))/2.0f; else bs.max.X()=((bs.min.X()=lbb.min.X())+lbb.max.X())/2.0f; if (i&2) bs.min.Y()=(lbb.min.Y()+(bs.max.Y()=lbb.max.Y()))/2.0f; else bs.max.Y()=((bs.min.Y()=lbb.min.Y())+lbb.max.Y())/2.0f; if (i&4) bs.min.Z()=(lbb.min.Z()+(bs.max.Z()=lbb.max.Z()))/2.0f; else bs.max.Z()=((bs.min.Z()=lbb.min.Z())+lbb.max.Z())/2.0f; return bs; } // Given the bounding-box and the center (both in world-coordinates) // of a node, return the bounding-box (in world-coordinats) of the i-th son BoundingBoxType SubBoxAndCenterInWorldCoordinates(BoundingBoxType &lbb, CoordinateType ¢er, int i) { BoundingBoxType bs; if (i&1) { bs.min[0]=center[0]; bs.max[0]=lbb.max[0]; } else { bs.min[0]=lbb.min[0]; bs.max[0]=center[0]; } if (i&2) { bs.min[1]=center[1]; bs.max[1]=lbb.max[1]; } else { bs.max[1]=center[1]; bs.min[1]=lbb.min[1]; } if (i&4) { bs.min[2]=center[2]; bs.max[2]=lbb.max[2]; } else { bs.max[2]=center[2]; bs.min[2]=lbb.min[2]; } return bs; }; /* * Add a new Node to the octree. * The created node is the i-th son of the node pointed to by parent. * Return the pointer to the new node */ NodePointer NewNode(NodePointer parent, int i) { assert(0<=i && i<8); assert(Son(parent, i)==NULL); //int index = NodeCount(); char level = Level(parent)+1; Node *node = (levelcenter); int displacement = 1<<(maximumDepth-level); node->center.X() = parentCenter->X() + ((i&1)? displacement : -displacement); node->center.Y() = parentCenter->Y() + ((i&2)? displacement : -displacement); node->center.Z() = parentCenter->Z() + ((i&4)? displacement : -displacement); return node; } // Aggiunge un nodo all'octree nella posizione specificata e al livello specificato. // Vengono inoltre inseriti tutti gli antenati mancanti per andare dalla radice // al nodo ed al livello specificato seguendo path. NodePointer AddNode(CenterType path) { //the input coordinates must be in the range 0..2^maxdepth assert(path[0]>=0 && path[0]=0 && path[1]=0 && path[2]= rootLevel) { int nextSon=0; if((path[0]>>shiftLevel)%2) nextSon +=1; if((path[1]>>shiftLevel)%2) nextSon +=2; if((path[2]>>shiftLevel)%2) nextSon +=4; NodePointer nextNode = Son(curNode, nextSon); if(nextNode!=NULL) // nessun nodo pu aver Root() per figlio curNode = nextNode; else { NodePointer newNode = NewNode(curNode, nextSon); assert(Son(curNode, nextSon)==newNode); // TODO delete an assignment curNode=newNode; } --shiftLevel; } return curNode; } /*! * Given a query point, compute the z_order of the leaf where this point would be contained. * This leaf not necessarily must be exist! */ // Convert the point p coordinates to the integer based representation // in the range 0..size, where size is 2^maxdepth CenterType Interize(const CoordinateType &pf) const { CenterType pi; assert(pf.X()>=boundingBox.min.X() && pf.X()<=boundingBox.max.X()); assert(pf.Y()>=boundingBox.min.Y() && pf.Y()<=boundingBox.max.Y()); assert(pf.Z()>=boundingBox.min.Z() && pf.Z()<=boundingBox.max.Z()); pi.X() = int((pf.X() - boundingBox.min.X()) * size / (boundingBox.max.X() - boundingBox.min.X())); pi.Y() = int((pf.Y() - boundingBox.min.Y()) * size / (boundingBox.max.Y() - boundingBox.min.Y())); pi.Z() = int((pf.Z() - boundingBox.min.Z()) * size / (boundingBox.max.Z() - boundingBox.min.Z())); return pi; } // Inverse function of Interize; // Return to the original coords space (not to the original values!!) CoordinateType DeInterize(const CenterType &pi ) const { CoordinateType pf; assert(pi.X()>=0 && pi.X()=0 && pi.Y()=0 && pi.Z()=0 && path[0]=0 && path[1]=0 && path[2]>shift)%2) son +=1; if((path[1]>>shift)%2) son +=2; if((path[2]>>shift)%2) son +=4; NodePointer nextNode = Son(curNode, son); if(nextNode!=NULL) curNode=nextNode; else break; --shift; } return curNode; } // Return the 'path' from root to the specified node; // the path is coded as a point3s; each bit of each component code the direction in one level // only the last 'level' bits of the returned value are meaningful // for example for the root no bit are meaningfull (path is 0) // for the first level only one bit of each one of the three components are maninguful; CenterType GetPath(NodePointer n) const { if(n==Root()) return CenterType(0,0,0); CenterType path(0,0,0); int shift, mask, son; int startingLevel = int(Level(n)); while (n!=Root()) { shift = startingLevel-Level(n); //nodes[n].level mask = 1 << shift; // e.g. 1*2^shift son = WhatSon(n); if(son&1) path[0] |= mask; if(son&2) path[1] |= mask; if(son&4) path[2] |= mask; n = Parent(n); // nodes[n].parent } return path; } // Dato un punto 3D nello spazio restituisce un array contenente // i puntatori ai nodi che lo contengono, dalla radice fino alle foglie. // I nodi mancanti dalla radice fino a profondit maxDepth vengono aggiunti. // In posizione i ci sar il nodo di livello i. // Restituisce lo z-order del punto p ZOrderType BuildRoute(const CoordinateType &p, NodePointer *&route) { assert( boundingBox.min.X()<=p.X() && p.X()<=boundingBox.max.X() ); assert( boundingBox.min.Y()<=p.Y() && p.Y()<=boundingBox.max.Y() ); assert( boundingBox.min.Z()<=p.Z() && p.Z()<=boundingBox.max.Z() ); route[0] = Root(); NodePointer curNode = Root(); int shift = maximumDepth-1; CenterType path = CenterType::Construct(Interize(p)); while(shift >= 0) { int son = 0; if((path[0]>>shift)%2) son +=1; if((path[1]>>shift)%2) son +=2; if((path[2]>>shift)%2) son +=4; NodePointer nextNode = Son(curNode, son); if(nextNode!=NULL) { route[maximumDepth-shift] = nextNode; curNode = nextNode; } else { NodePointer newNode = NewNode(curNode, son); route[maximumDepth-shift] = newNode; curNode = newNode; } --shift; } return ZOrder(route[maximumDepth]); }; //end of BuildRoute // Restituisce il percorso dalla radice fino al nodo di profondit // massima presente nell'octree contenente il nodo p. Nessun nuovo nodo aggiunto // all'octree. In route sono inseriti gli indici dei nodi contenti p, dalla radice // fino al nodo di profontid massima presente; nelle eventuali posizioni rimaste // libere inserito il valore -1. Restituisce true se il punto p cade in una foglia // dell'otree, false altrimenti bool GetRoute(const CoordinateType &p, NodePointer *&route) { assert( boundingBox.min.X()<=p.X() && p.X()<=boundingBox.max.X() ); assert( boundingBox.min.Y()<=p.Y() && p.Y()<=boundingBox.max.Y() ); assert( boundingBox.min.Z()<=p.Z() && p.Z()<=boundingBox.max.Z() ); memset(route, NULL, maximumDepth*sizeof(NodePointer)); CenterType path = CenterType::Construct(Interize(p)); int shift = maximumDepth-1; NodePointer finalLevel = Root(); NodePointer curNode = Root(); while(shift >= finalLevel) { int son=0; if((path[0]>>shift)%2) son +=1; if((path[1]>>shift)%2) son +=2; if((path[2]>>shift)%2) son +=4; NodePointer nextNode = Son(curNode, son); if(nextNode!=NULL) { route[maximumDepth-shift] = nextNode; curNode = nextNode; } else return false; --shift; } return true; }; //end of GetReoute // Data una bounding-box bb_query, calcola l'insieme dei nodi di // profondit depth il cui bounding-box ha intersezione non nulla con // bb (la bounding-box dell'octree); i puntatori a tali nodi sono // inseriti progressivamente in contained_nodes. // The vector nodes must be cleared before calling this method. void ContainedNodes ( BoundingBoxType &query, std::vector< NodePointer > &nodes, int depth, NodePointer n, BoundingBoxType &nodeBB) { if (!query.Collide(nodeBB)) return; if (Level(n)==depth) nodes.push_back(n); else { NodePointer son; BoundingBoxType sonBB; CoordinateType nodeCenter = nodeBB.Center(); for (int s=0; s<8; s++) { son = Son(n, s); if (son!=NULL) { sonBB = SubBoxAndCenterInWorldCoordinates(nodeBB, nodeCenter, s); ContainedNodes(query, nodes, depth, son, sonBB); } } } }; //end of ContainedNodes // Data una bounding-box bb, calcola l'insieme delle foglie il cui // bounding-box ha intersezione non nulla con bb; i loro indici // sono inseriti all'interno di leaves. void ContainedLeaves( BoundingBoxType &query, std::vector< NodePointer > &leaves, NodePointer node, BoundingBoxType &nodeBB ) { NodePointer son; BoundingBoxType sonBB; CoordinateType nodeCenter = nodeBB.Center(); for (int s=0; s<8; s++) { son = Son(node, s); //nodes[nodeIndex].sonIndex[s] if (son!=NULL) { sonBB = SubBoxAndCenterInWorldCoordinates(nodeBB, nodeCenter, s); if ( query.Collide(sonBB) ) { if ( son->IsLeaf() ) leaves.push_back(son); else ContainedLeaves(query, leaves, son, sonBB); } } } }; //end of ContainedLeaves /* * Octree Data Members */ public: // the size of the finest grid available (2^maxDepth) int size; // double the size(2^maxDepth) int lSize; // The allowed maximum depth int maximumDepth; // The dimension of a leaf CoordinateType leafDimension; // The diagonal of a leaf ScalarType leafDiagonal; // The Octree nodes std::vector< Node* > nodes; // The bounding box containing the octree (in world coordinate) BoundingBoxType boundingBox; }; //end of class OctreeTemplate template const SCALAR_TYPE OctreeTemplate::EXPANSION_FACTOR = SCALAR_TYPE(0.035); } #endif //VCG_SPACE_INDEX_OCTREETEMPLATE_H qutemol/vcg/vcg/space/index/grid_util.h0000444000175000017500000001736210757007601016531 0ustar mbamba/**************************************************************************** * VCGLib o o * * Visual and Computer Graphics Library o o * * _ O _ * * Copyright(C) 2005 \/)\/ * * Visual Computing Lab /\/| * * ISTI - Italian National Research Council | * * \ * * All rights reserved. * * * * 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. * * * * 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 (http://www.gnu.org/licenses/gpl.txt) * * for more details. * * * ****************************************************************************/ /**************************************************************************** History $Log: grid_util.h,v $ Revision 1.13 2008/02/20 11:31:13 cignoni __int64 is a MS only type. Added portability defines at the beginning. Revision 1.12 2008/02/19 12:43:01 callieri in BestDim(...) changed int -> _int64 to cope with programs with a very large cell number (like plyMC) Revision 1.11 2008/02/04 19:18:44 ganovelli typo corrected Revision 1.10 2006/08/23 15:21:35 marfr960 added some comments Revision 1.9 2005/12/02 00:27:22 cignoni removed excess typenames Revision 1.8 2005/10/03 16:21:10 spinelli erase wrong assert on boxToIbox function Revision 1.7 2005/10/02 23:16:26 cignoni English comment and moved typedef to public scope Revision 1.6 2005/09/30 13:12:46 pietroni basic grid class is derived from Indexing base class defined in base,h Revision 1.5 2005/09/16 11:56:38 cignoni removed wrong typename and added ending \n Revision 1.4 2005/08/02 11:01:05 pietroni added IPToP and IBoxToBox functions, modified BoxToIBox function in order to use PToIP function Revision 1.3 2005/07/28 06:11:12 cignoni corrected error in GridP (did not compile) Revision 1.2 2005/07/01 11:33:36 cignoni Added a class BasicGrid with some utility function that are scattered among similar classes Revision 1.1 2005/03/15 11:43:18 cignoni Removed BestDim function from the grid_static_ptr class and moved to a indipendent file (grid_util.h) for sake of generality. ****************************************************************************/ #ifndef __VCGLIB_GRID_UTIL #define __VCGLIB_GRID_UTIL #include #include #include #ifndef WIN32 #define __int64 long long #define __cdecl #endif namespace vcg { /** BasicGrid Basic Class abstracting a gridded structure in a 3d space; Usueful for having coherent float to integer conversion in a unique place: Some Notes: - bbox is the real occupation of the box in the space; - siz is the number of cells for each side OBJTYPE: Type of the indexed objects. SCALARTYPE: Scalars type for structure's internal data (may differ from object's scalar type). */ template class BasicGrid:public SpatialIndex { public: typedef SCALARTYPE ScalarType; typedef Box3 Box3x; typedef Point3 CoordType; typedef OBJTYPE ObjType; typedef OBJTYPE* ObjPtr; typedef BasicGrid GridType; Box3x bbox; CoordType dim; /// Spatial Dimention (edge legth) of the bounding box Point3i siz; /// Number of cells forming the grid CoordType voxel; /// Dimensions of a single cell /* Given a 3D point, returns the coordinates of the cell where the point is * @param p is a 3D point * @return integer coordinates of the cell */ inline Point3i GridP( const Point3 & p ) const { Point3i pi; PToIP(p, pi); return pi; } /* Given a 3D point p, returns the index of the corresponding cell * @param p is a 3D point in the space * @return integer coordinates pi of the cell */ inline void PToIP(const CoordType & p, Point3i &pi ) const { CoordType t = p - bbox.min; pi[0] = int( t[0] / voxel[0] ); pi[1] = int( t[1] / voxel[1] ); pi[2] = int( t[2] / voxel[2] ); } /* Given a cell index return the lower corner of the cell * @param integer coordinates pi of the cell * @return p is a 3D point representing the lower corner of the cell */ inline void IPToP(const Point3i & pi, CoordType &p ) const { p[0] = ((ScalarType)pi[0])*voxel[0]; p[1] = ((ScalarType)pi[1])*voxel[1]; p[2] = ((ScalarType)pi[2])*voxel[2]; p += bbox.min; } /* Given a cell in coordinates, compute the corresponding cell in integer coordinates * @param b is the cell in coordinates * @return ib is the correspondent box in integer coordinates */ void BoxToIBox( const Box3x & b, Box3i & ib ) const { PToIP(b.min, ib.min); PToIP(b.max, ib.max); //assert(ib.max[0]>=0 && ib.max[1]>=0 && ib.max[2]>=0); } /* Given a cell in integer coordinates, compute the corresponding cell in coordinates * @param ib is the cell in integer coordinates * @return b is the correspondent box in coordinates */ /// Dato un box in voxel ritorna gli estremi del box reale void IBoxToBox( const Box3i & ib, Box3x & b ) const { IPToP(ib.min,b.min); IPToP(ib.max,b.max); } }; /** Calcolo dimensioni griglia. Calcola la dimensione della griglia in funzione della ratio del bounding box e del numero di elementi */ template void BestDim( const __int64 elems, const Point3 & size, Point3i & dim ) { const __int64 mincells = 1; // Numero minimo di celle const double GFactor = 1; // GridEntry = NumElem*GFactor double diag = size.Norm(); // Diagonale del box double eps = diag*1e-4; // Fattore di tolleranza assert(elems>0); assert(size[0]>=0.0); assert(size[1]>=0.0); assert(size[2]>=0.0); __int64 ncell = (__int64)(elems*GFactor); // Calcolo numero di voxel if(ncelleps) { if(size[1]>eps) { if(size[2]>eps) { double k = pow((double)(ncell/(size[0]*size[1]*size[2])),double(1.0/3.f)); dim[0] = int(size[0] * k); dim[1] = int(size[1] * k); dim[2] = int(size[2] * k); } else { dim[0] = int(::sqrt(ncell*size[0]/size[1])); dim[1] = int(::sqrt(ncell*size[1]/size[0])); } } else { if(size[2]>eps) { dim[0] = int(::sqrt(ncell*size[0]/size[2])); dim[2] = int(::sqrt(ncell*size[2]/size[0])); } else dim[0] = int(ncell); } } else { if(size[1]>eps) { if(size[2]>eps) { dim[1] = int(::sqrt(ncell*size[1]/size[2])); dim[2] = int(::sqrt(ncell*size[2]/size[1])); } else dim[1] = int(ncell); } else if(size[2]>eps) dim[2] = int(ncell); } dim[0] = math::Max(dim[0],1); dim[1] = math::Max(dim[1],1); dim[2] = math::Max(dim[2],1); } } #endif qutemol/vcg/vcg/space/index/spatial_hashing.h0000444000175000017500000003632010631506600017672 0ustar mbamba/**************************************************************************** * VCGLib o o * * Visual and Computer Graphics Library o o * * _ O _ * * Copyright(C) 2004 \/)\/ * * Visual Computing Lab /\/| * * ISTI - Italian National Research Council | * * \ * * All rights reserved. * * * * 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. * * * * 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 (http://www.gnu.org/licenses/gpl.txt) * * for more details. * * * ****************************************************************************/ /**************************************************************************** History $Log: spatial_hashing.h,v $ Revision 1.25 2007/06/06 10:33:36 marfr960 casting (size_t) to (int) to avoid annoying warning Revision 1.24 2006/12/06 17:47:50 marfr960 end() replaced by pointer lastPlusOne Revision 1.23 2006/10/02 09:25:49 ganovelli reverted to version 1.20 for critical bug Revision 1.20 2006/07/26 08:12:56 pietroni added InitEmpty Function Revision 1.19 2006/07/10 12:43:13 turini explicit cast in _IsInHtable() to resolve a warning Revision 1.18 2006/04/20 08:30:27 cignoni small GCC compiling issues Revision 1.17 2006/01/23 21:26:57 ponchio gcc compatibility (templates mostly) bbox -> this->bbox More consistent use of Box3x and such. Revision 1.16 2006/01/23 15:26:31 ponchio P1 --> HASH_P1 Old definition was conflicting with functions in segment.h Revision 1.15 2005/11/23 15:55:35 pietroni 1 warning corrected Revision 1.14 2005/11/07 14:15:36 pietroni added dynamic spatial hashing class for dynamic updating of entries (and relative functions) Revision 1.13 2005/10/05 17:04:18 pietroni corrected bug on Set Function .... bbox must be exetended in order to have'nt any object on his borde Revision 1.12 2005/10/03 13:58:21 pietroni added GetInSphere and GetInBox functions Revision 1.11 2005/10/03 10:05:26 pietroni changed Set functions, added possibility to pass the bbox as parameter Revision 1.10 2005/09/30 13:14:59 pietroni added wrapping to functions defined in GridClosest: - GetClosest - GetKClosest - DoRay Revision 1.9 2005/09/21 14:22:49 pietroni Added DynamicSpatialHAshTable class Revision 1.8 2005/09/19 13:35:45 pietroni use of standard grid interface use of vector instead of map inside the cell removed closest iterator Revision 1.7 2005/06/15 11:44:47 pietroni minor changes Revision 1.6 2005/06/01 13:47:59 pietroni resolved hash code conflicts Revision 1.5 2005/03/15 09:50:44 ganovelli there was a debug line, now removed Revision 1.4 2005/03/14 15:11:18 ganovelli ClosestK added and other minor changes Revision 1.3 2005/03/11 15:25:29 ganovelli added ClosersIterator and other minor changes. Not compatible with the previous version. Still other modifications to do (temporary commit) Revision 1.2 2005/02/21 12:13:25 ganovelli added vcg header ****************************************************************************/ #ifndef VCGLIB_SPATIAL_HASHING #define VCGLIB_SPATIAL_HASHING #define HASH_P0 73856093 #define HASH_P1 19349663 #define HASH_P2 83492791 #include #include //#include #include #include #ifdef WIN32 #ifndef __MINGW32__ #include #define STDEXT stdext #else #include #define STDEXT __gnu_cxx #endif #else #include #define STDEXT __gnu_cxx #endif namespace vcg{ /** Spatial Hash Table Spatial Hashing as described in "Optimized Spatial Hashing for Coll ision Detection of Deformable Objects", Matthias Teschner and Bruno Heidelberger and Matthias Muller and Danat Pomeranets and Markus Gross */ template < typename OBJTYPE,class FLT=double> class SpatialHashTable:public BasicGrid { public: typedef OBJTYPE ObjType; typedef ObjType* ObjPtr; typedef typename ObjType::ScalarType ScalarType; typedef Point3 CoordType; typedef typename BasicGrid::Box3x Box3x; // typedef typename SpatialHashTable SpatialHashType; typedef SpatialHashTable SpatialHashType; //typedef typename SpatialHashTable GridType; //type of container of pointer to object in a Cell //typedef typename std::pair EntryType ; class EntryType : public std::pair { public: EntryType(ObjType* sim,const int &_tempMark) { this->first=sim; this->second=_tempMark; } ObjType& operator *(){return (*this->first);} }; typedef typename std::vector CellContainerType; typedef typename CellContainerType::iterator IteMap; typedef EntryType* CellIterator; //This Class Identify the cell struct Cell { protected: Point3i cell_n;//cell number public: //elements CellContainerType _entries; Cell() {} Cell(ObjType* sim,Point3i _cell,const int &_tempMark) { _entries.push_back(EntryType(sim,_tempMark)); cell_n=_cell; } ///return the number of elements stored in the cell int Size() {return (int)(_entries.size());} ///find the simplex into the cell bool Find(ObjType* sim,IteMap &I) { for (I=_entries.begin();I<_entries.end();I++) if ((*I).first==sim) return true; return false; } ///update or insert an element into a cell void Update(ObjType* sim, const int & _tempMark) { IteMap I; if (Find(sim,I)) (*I).second=_tempMark; else _entries.push_back(EntryType(sim,_tempMark)); } Point3i CellN() {return cell_n;} bool operator ==(const Cell &h) {return (cell_n==h.CellN());} bool operator !=(const Cell &h) {return ((cell_n!=h.CellN()));} }; // end struct Cell //hash table definition typedef typename STDEXT::hash_multimap Htable; //record of the hash table typedef typename std::pair HRecord; //iterator to the hash table typedef typename Htable::iterator IteHtable; SpatialHashTable(){HashSpace=1000;};//default value for hash_space ~SpatialHashTable(){}; int tempMark; protected: Htable hash_table; ///number of possible hash code [0...HashSpace] int HashSpace; ///number of conflicts created int conflicts; ///insert a new cell void _InsertNewHentry(ObjType* s,Point3i cell) { int h=Hash(cell); hash_table.insert(HRecord(h,Cell(s,cell,tempMark))); } ///return true and return the iterator to the cell if exist bool _IsInHtable(Point3i cell,IteHtable &result) { int h=Hash(cell); int count = (int) hash_table.count(h); if (count==0)///in this case there is no entry for that key return false; else { std::pair p =hash_table.equal_range(h); IteHtable i = p.first; while((i != p.second)&&((*i).second.CellN()!=cell))++i; if (i==p.second)///the scan is terminated and we have not found the right cell { conflicts++; return false; } else ///we have found the right cell { result=i; return true; } } } virtual void _UpdateHMark(ObjType* s){(void)s;} ///insert an element in a specified cell if the cell doesn't exist than ///create it. void _InsertInCell(ObjType* s,Point3i cell) { IteHtable I; if (!_IsInHtable(cell,I)) _InsertNewHentry(s,cell); else///there is the entry specified by the iterator I so update only the temporary mark (*I).second.Update(s,tempMark); } // hashing const int Hash(Point3i p) const { return ((p.V(0)*HASH_P0 ^ p.V(1)*HASH_P1 ^ p.V(2)*HASH_P2)%HashSpace); } public: /////We need some extra space for numerical precision. //template // void SetBBox( const Box3Type & b ) //{ // bbox.Import( b ); // ScalarType t = bbox.Diag()/100.0; // if(t == 0) t = ScalarType(1e20); // <--- Some doubts on this (Cigno 5/1/04) // bbox.Offset(t); // dim = bbox.max - bbox.min; //} vcg::Box3i Add( ObjType* s) { Box3 b; s->GetBBox(b); vcg::Box3i bb; BoxToIBox(b,bb); //then insert all the cell of bb for (int i=bb.min.X();i<=bb.max.X();i++) for (int j=bb.min.Y();j<=bb.max.Y();j++) for (int k=bb.min.Z();k<=bb.max.Z();k++) _InsertInCell(s,vcg::Point3i(i,j,k)); _UpdateHMark(s); return bb; } /// set an empty spatial hash table void InitEmpty(const Box3x &_bbox, vcg::Point3i grid_size) { Box3x b; Box3x &bbox = this->bbox; CoordType &dim = this->dim; Point3i &siz = this->siz; CoordType &voxel = this->voxel; assert(!_bbox.IsNull()); bbox=_bbox; dim = bbox.max - bbox.min; assert((grid_size.V(0)>0)&&(grid_size.V(1)>0)&&(grid_size.V(2)>0)); siz=grid_size; voxel[0] = dim[0]/siz[0]; voxel[1] = dim[1]/siz[1]; voxel[2] = dim[2]/siz[2]; } /// Insert a mesh in the grid. template void Set(const OBJITER & _oBegin, const OBJITER & _oEnd,const Box3x &_bbox=Box3x() ) { OBJITER i; Box3x b; Box3x &bbox = this->bbox; CoordType &dim = this->dim; Point3i &siz = this->siz; CoordType &voxel = this->voxel; int _size=(int)std::distance(_oBegin,_oEnd); if(!_bbox.IsNull()) this->bbox=_bbox; else { for(i = _oBegin; i!= _oEnd; ++i) { (*i).GetBBox(b); this->bbox.Add(b); } ///inflate the bb calculated ScalarType infl=bbox.Diag()/_size; bbox.min -= CoordType(infl,infl,infl); bbox.max += CoordType(infl,infl,infl); } dim = bbox.max - bbox.min; BestDim( _size, dim, siz ); // find voxel size voxel[0] = dim[0]/siz[0]; voxel[1] = dim[1]/siz[1]; voxel[2] = dim[2]/siz[2]; for(i = _oBegin; i!= _oEnd; ++i) Add(&(*i)); } ///return the simplexes of the cell that contain p void Grid( const Point3d & p, CellIterator & first, CellIterator & last ) { IteHtable I; vcg::Point3i _c; this->PToIP(p,_c); Grid(_c,first,last); } ///return the simplexes on a specified cell void Grid( int x,int y,int z, CellIterator & first, CellIterator & last ) { Grid(vcg::Point3i(x,y,z),first,last); } ///return the simplexes on a specified cell void Grid( const Point3i & _c, CellIterator & first, CellIterator & end ) { IteHtable I; if (_IsInHtable(_c,I))//if there is the cell then { ///return pointers to first and last element cell elems first = &*(*I).second._entries.begin(); end = &((*I).second._entries.back()) + 1; } else { ///return 2 equals pointers first = 0; end = 0; } } ///return the number of elemnts in the cell and the iterator to the cell ///if the cell exist int numElemCell(Point3i _c,IteHtable &I) { if (_IsInHtable(_c,I)) return ((*I).second.Size()); else return 0; } ///return the number of cell created int CellNumber() {return (hash_table.size());} int Conflicts() {return conflicts;} void Clear() {hash_table.clear();} void SetHashKeySpace(int n) {HashSpace=n;} void UpdateTmark() {tempMark++;} template ObjPtr GetClosest(OBJPOINTDISTFUNCTOR & _getPointDistance, OBJMARKER & _marker, const CoordType & _p, const ScalarType & _maxDist,ScalarType & _minDist, CoordType & _closestPt) { return (vcg::GridClosest(*this,_getPointDistance,_marker, _p,_maxDist,_minDist,_closestPt)); } template unsigned int GetKClosest(OBJPOINTDISTFUNCTOR & _getPointDistance,OBJMARKER & _marker, const unsigned int _k, const CoordType & _p, const ScalarType & _maxDist,OBJPTRCONTAINER & _objectPtrs, DISTCONTAINER & _distances, POINTCONTAINER & _points) { return (vcg::GridGetKClosest (*this,_getPointDistance,_marker,_k,_p,_maxDist,_objectPtrs,_distances,_points)); } template unsigned int GetInSphere(OBJPOINTDISTFUNCTOR & _getPointDistance, OBJMARKER & _marker, const CoordType & _p, const ScalarType & _r, OBJPTRCONTAINER & _objectPtrs, DISTCONTAINER & _distances, POINTCONTAINER & _points) { return(vcg::GridGetInSphere (*this,_getPointDistance,_marker,_p,_r,_objectPtrs,_distances,_points)); } template unsigned int GetInBox(OBJMARKER & _marker, const Box3x _bbox, OBJPTRCONTAINER & _objectPtrs) { return(vcg::GridGetInBox (*this,_marker,_bbox,_objectPtrs)); } template ObjPtr DoRay(OBJRAYISECTFUNCTOR & _rayIntersector, OBJMARKER & _marker, const Ray3 & _ray, const ScalarType & _maxDist, ScalarType & _t) { return(vcg::GridDoRay (*this,_rayIntersector,_marker,_ray,_maxDist,_t)); } }; // end class /** Spatial Hash Table Dynamic Update the Hmark value on the simplex for dynamic updating of contents of the cell. The simplex must have the HMark() function. */ template < typename ContainerType,class FLT=double> class DynamicSpatialHashTable: public SpatialHashTable { public: typedef typename SpatialHashTable::CoordType CoordType; typedef typename SpatialHashTable::ObjType ObjType; typedef typename SpatialHashTable::ObjPtr ObjPtr; typedef typename SpatialHashTable::Box3x Box3x; typedef typename SpatialHashTable::CellIterator CellIterator; void _UpdateHMark(ObjType* s){ s->HMark() = this->tempMark;} void getInCellUpdated(vcg::Point3i cell,std::vector &elems) { CellIterator first,last,l; Grid(cell,first,last); for (l=first;l!=last;l++) { if ((l->second)>=(**l).HMark()) elems.push_back(&(**l)); } } }; }// end namespace #undef HASH_P0 #undef HASH_P1 #undef HASH_P2 #endif qutemol/vcg/vcg/space/index/grid_static_ptr.h0000444000175000017500000005115210646721756017736 0ustar mbamba/**************************************************************************** * VCGLib o o * * Visual and Computer Graphics Library o o * * _ O _ * * Copyright(C) 2004 \/)\/ * * Visual Computing Lab /\/| * * ISTI - Italian National Research Council | * * \ * * All rights reserved. * * * * 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. * * * * 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 (http://www.gnu.org/licenses/gpl.txt) * * for more details. * * * ****************************************************************************/ /**************************************************************************** History $Log: grid_static_ptr.h,v $ Revision 1.38 2007/07/16 16:59:26 ponchio Added method Gather: Using a cubic voxel of side (see Set with radius) allows you to process all pairs of objects within radius distance. Usefull to compute normals, weighted means etc. Speedup is about 7x. Revision 1.37 2007/07/16 15:13:39 cignoni Splitted initialiazation functions of grid to add flexibility in the creation Revision 1.36 2005/12/02 00:43:31 cignoni Forgotten a base deferencing like the previous one Note also the different possible sintax with this-> instead of the base class name Revision 1.35 2005/12/02 00:25:13 cignoni Added and removed typenames for gcc compiling. Added base class qualifier for referencing the elemntes of the templated base class (BasicGrid) it seems to be needed by the standard Revision 1.34 2005/11/30 16:01:25 m_di_benedetto Added std:: namespace for max() and min(). Revision 1.33 2005/11/30 10:32:44 m_di_benedetto Added (int) cast to std::distance to prevent compiler warning message. Revision 1.32 2005/11/10 15:44:17 cignoni Added casts to remove warnings Revision 1.31 2005/10/07 13:27:22 turini Minor changes in Set method: added use of template scalar type computing BBox. Revision 1.30 2005/10/05 17:05:08 pietroni corrected bug on Set Function .... bbox must be exetended in order to have'nt any object on his borde Revision 1.29 2005/10/03 13:57:56 pietroni added GetInSphere and GetInBox functions Revision 1.28 2005/10/02 23:15:26 cignoni Inveted the boolean sign of an assert in Grid() Revision 1.27 2005/09/30 15:07:28 cignoni Reordered grid access functions Added possibility of setting BBox explicitly in Set(...) Revision 1.26 2005/09/30 13:15:21 pietroni added wrapping to functions defined in GridClosest: - GetClosest - GetKClosest - DoRay Revision 1.25 2005/09/21 09:22:51 pietroni removed closest functions. Closest function is now on index\\Closest.h Users must use trimesh\\closest.h to perform spatial query. Revision 1.24 2005/09/16 11:57:15 cignoni Removed two wrong typenames Revision 1.23 2005/09/15 13:16:42 spinelli fixed bugs Revision 1.22 2005/09/15 11:14:39 pietroni minor changes Revision 1.21 2005/09/14 13:27:38 spinelli minor changes Revision 1.20 2005/09/14 12:57:52 pietroni canged template parameters for Closest Function (use of TempMark class) Revision 1.19 2005/09/14 09:05:32 pietroni added * operator to Link modified getClosest in order to use Temporary mark corrected bug on functor calling compilation Revision 1.18 2005/09/09 11:29:21 m_di_benedetto Modified old GetClosest() to respect old min_dist semantic (in/out) and removed #included Revision 1.17 2005/09/09 11:11:15 m_di_benedetto #included for std::numeric_limits::max() and corrected parameters bug in old GetClosest(); Revision 1.16 2005/09/09 11:01:02 m_di_benedetto Modified GetClosest(): now it uses a functor for distance calculation. Added comments and a GetClosest() method with backward compatibility. Revision 1.15 2005/08/26 09:27:58 cignoni Added a templated version of SetBBox Revision 1.14 2005/08/02 11:18:36 pietroni exetended form BasicGrid, changed type of t in class Link (from Iterator to Pointer to the object) Revision 1.13 2005/04/14 17:23:08 ponchio *** empty log message *** Revision 1.12 2005/03/15 11:43:18 cignoni Removed BestDim function from the grid_static_ptr class and moved to a indipendent file (grid_util.h) for sake of generality. Revision 1.11 2005/01/03 11:21:26 cignoni Added some casts Revision 1.10 2004/09/28 10:25:05 ponchio SetBox minimal change. Revision 1.9 2004/09/23 14:29:42 ponchio Small bugs fixed. Revision 1.8 2004/09/23 13:44:25 ponchio Removed SetSafeBBox. SetBBox is now safe enough. Revision 1.7 2004/09/09 12:44:39 fasano included stdio.h Revision 1.6 2004/09/09 08:39:29 ganovelli minor changes for gcc Revision 1.5 2004/06/25 18:34:23 ganovelli added Grid to return all the cells sharing a specified edge Revision 1.4 2004/06/23 15:49:03 ponchio Added some help and inndentation Revision 1.3 2004/05/12 18:50:58 ganovelli changed calls to Dist Revision 1.2 2004/05/11 14:33:46 ganovelli changed to grid_static_obj to grid_static_ptr Revision 1.1 2004/05/10 14:44:13 ganovelli created Revision 1.1 2004/03/08 09:21:31 cignoni Initial commit ****************************************************************************/ #ifndef __VCGLIB_UGRID #define __VCGLIB_UGRID #include #include #include #include #include #include #include #include namespace vcg { /** Static Uniform Grid A spatial search structure for a accessing a container of objects. It is based on a uniform grid overlayed over a protion of space. The grid partion the space into cells. Cells contains just pointers to the object that are stored elsewhere. The set of objects is meant to be static and pointer stable. Useful for situation were many space related query are issued over the same dataset (ray tracing, measuring distances between meshes, re-detailing ecc.). Works well for distribution that ar reasonably uniform. How to use it: ContainerType must have a 'value_type' typedef inside. (stl containers already have it) Objects pointed by cells (of kind 'value_type') must have a 'ScalarType' typedef (float or double usually) and a member function: void GetBBox(Box3 &b) which return the bounding box of the object When using the GetClosest() method, the user must supply a functor object (whose type is a method template argument) which expose the following operator (): bool operator () (const ObjType & obj, const Point3f & point, ScalarType & mindist, Point3f & result); which return true if the distance from point to the object 'obj' is < mindist and set mindist to said distance, and result must be set as the closest point of the object to point) */ template < class OBJTYPE, class FLT=float > class GridStaticPtr: public BasicGrid { public: typedef OBJTYPE ObjType; typedef ObjType* ObjPtr; typedef typename ObjType::ScalarType ScalarType; typedef Point3 CoordType; typedef Box3 Box3x; typedef Line3 Line3x; typedef GridStaticPtr GridPtrType; typedef BasicGrid BT; /** Internal class for keeping the first pointer of object. Definizione Link dentro la griglia. Classe di supporto per GridStaticObj. */ class Link { public: /// Costruttore di default inline Link(){}; /// Costruttore con inizializzatori inline Link(ObjPtr nt, const int ni ){ assert(ni>=0); t = nt; i = ni; }; inline bool operator < ( const Link & l ) const{ return i < l.i; } inline bool operator <= ( const Link & l ) const{ return i <= l.i; } inline bool operator > ( const Link & l ) const{ return i > l.i; } inline bool operator >= ( const Link & l ) const{ return i >= l.i; } inline bool operator == ( const Link & l ) const{ return i == l.i; } inline bool operator != ( const Link & l ) const{ return i != l.i; } inline ObjPtr & Elem() { return t; } ObjType &operator *(){return *(t);} inline int & Index() { return i; } private: /// Puntatore all'elemento T ObjPtr t; /// Indirizzo del voxel dentro la griglia int i; };//end class Link typedef Link* Cell; typedef Cell CellIterator; std::vector links; /// Insieme di tutti i links std::vector grid; /// Griglia vera e propria /// Date le coordinate di un grid point (corner minx,miy,minz) ritorna le celle che condividono /// l'edge cell che parte dal grid point in direzione axis inline void Grid( Point3i p, const int axis, std::vector & cl) { #ifndef NDEBUG if ( p[0]<0 || p[0] > BT::siz[0] || p[1]<0 || p[1]> BT::siz[1] || p[2]<0 || p[2]> BT::siz[2] ) assert(0); //return NULL; else #endif assert(((unsigned int) p[0]+BT::siz[0]*p[1]+BT::siz[1]*p[2])siz[axis1]-1);++j){ p[axis0]=i; p[axis1]=j; cl.push_back(Grid(p[0]+BT::siz[0]*(p[1]+BT::siz[1]*p[2]))); } } //////////////// // Official access functions //////////////// /// BY CELL Cell* Grid(const int i) { return &grid[i]; } void Grid( const Cell* g, Cell & first, Cell & last ) { first = *g; last = *(g+1); } /// BY INTEGER COORDS inline Cell* Grid( const int x, const int y, const int z ) { assert(!( x<0 || x>=BT::siz[0] || y<0 || y>=BT::siz[1] || z<0 || z>=BT::siz[2] )); assert(grid.size()>0); return &*grid.begin() + ( x+BT::siz[0]*(y+BT::siz[1]*z) ); } inline Cell* Grid( const Point3i &pi) { return Grid(pi[0],pi[1],pi[2]); } void Grid( const int x, const int y, const int z, Cell & first, Cell & last ) { Cell* g = Grid(x,y,z); first = *g; last = *(g+1); } void Grid( const Point3 & p, Cell & first, Cell & last ) { Cell* g = Grid(GridP(p)); first = *g; last = *(g+1); } /// Set the bounding box of the grid ///We need some extra space for numerical precision. template void SetBBox( const Box3Type & b ) { this->bbox.Import( b ); ScalarType t = this->bbox.Diag()/100.0; if(t == 0) t = ScalarType(1e-20); // <--- Some doubts on this (Cigno 5/1/04) this->bbox.Offset(t); this->dim = this->bbox.max - this->bbox.min; } void ShowStats(FILE *fp) { // Conto le entry //int nentry = 0; //Hist H; //H.SetRange(0,1000,1000); //int pg; //for(pg=0;pg inline void Set(const OBJITER & _oBegin, const OBJITER & _oEnd) { Box3 _bbox; Box3 b; OBJITER i; for(i = _oBegin; i!= _oEnd; ++i) { (*i).GetBBox(b); _bbox.Add(b); } ///inflate the bb calculated int _size=(int)std::distance(_oBegin,_oEnd); ScalarType infl=_bbox.Diag()/_size; _bbox.min-=vcg::Point3(infl,infl,infl); _bbox.max+=vcg::Point3(infl,infl,infl); Set(_oBegin,_oEnd,_bbox); } // This function automatically compute a reasonable size for the uniform grid providing the side (radius) of the cell // // Note that the bbox must be already 'inflated' so to be sure that no object will fall on the border of the grid. template inline void Set(const OBJITER & _oBegin, const OBJITER & _oEnd, const Box3x &_bbox, FLT radius) { Point3i _siz; Point3 _dim = _bbox.max - _bbox.min; _dim/=radius; assert(_dim[0]>0 && _dim[1]>0 && _dim[2]>0 ); _siz[0] = (int)ceil(_dim[0]); _siz[1] = (int)ceil(_dim[1]); _siz[2] = (int)ceil(_dim[2]); Point3 offset=Point3::Construct(_siz); offset*=radius; offset -= (_bbox.max - _bbox.min); offset /=2; assert( offset[0]>=0 && offset[1]>=0 && offset[2]>=0 ); Box3x bb = _bbox; bb.min -= offset; bb.max += offset; Set(_oBegin,_oEnd, bb,_siz); } // This function automatically compute a reasonable size for the uniform grid such that the number of cells is // the same of the nubmer of elements to be inserted in the grid. // // Note that the bbox must be already 'inflated' so to be sure that no object will fall on the border of the grid. template inline void Set(const OBJITER & _oBegin, const OBJITER & _oEnd, const Box3x &_bbox) { int _size=(int)std::distance(_oBegin,_oEnd); Point3 _dim = _bbox.max - _bbox.min; Point3i _siz; BestDim( _size, _dim, _siz ); Set(_oBegin,_oEnd,_bbox,_siz); } template inline void Set(const OBJITER & _oBegin, const OBJITER & _oEnd, const Box3x &_bbox, Point3i _siz) { OBJITER i; this->bbox=_bbox; this->siz=_siz; // find voxel size starting from the provided bbox and grid size. this->dim = this->bbox.max - this->bbox.min; this->voxel[0] = this->dim[0]/this->siz[0]; this->voxel[1] = this->dim[1]/this->siz[1]; this->voxel[2] = this->dim[2]/this->siz[2]; // "Alloca" la griglia: +1 per la sentinella grid.resize( this->siz[0]*this->siz[1]*this->siz[2]+1 ); // Ciclo inserimento dei tetraedri: creazione link links.clear(); for(i=_oBegin; i!=_oEnd; ++i) { Box3x bb; // Boundig box del tetraedro corrente (*i).GetBBox(bb); bb.Intersect(this->bbox); if(! bb.IsNull() ) { Box3i ib; // Boundig box in voxels BoxToIBox( bb,ib ); int x,y,z; for(z=ib.min[2];z<=ib.max[2];++z) { int bz = z*this->siz[1]; for(y=ib.min[1];y<=ib.max[1];++y) { int by = (y+bz)*this->siz[0]; for(x=ib.min[0];x<=ib.max[0];++x) // Inserire calcolo cella corrente // if( pt->Intersect( ... ) links.push_back( Link(&(*i),by+x) ); } } } } // Push della sentinella /*links.push_back( Link((typename ContainerType::iterator)NULL, (grid.size()-1)));*/ links.push_back( Link( NULL, int(grid.size())-1) ); // Ordinamento dei links sort( links.begin(), links.end() ); // Creazione puntatori ai links typename std::vector::iterator pl; unsigned int pg; pl = links.begin(); for(pg=0;pgIndex() ) // Trovato inizio { ++pl; // Ricerca prossimo blocco if(pl==links.end()) break; } } } int MemUsed() { return sizeof(GridStaticPtr)+ sizeof(Link)*links.size() + sizeof(Cell) * grid.size(); } template ObjPtr GetClosest(OBJPOINTDISTFUNCTOR & _getPointDistance, OBJMARKER & _marker, const CoordType & _p, const ScalarType & _maxDist,ScalarType & _minDist, CoordType & _closestPt) { return (vcg::GridClosest(*this,_getPointDistance,_marker, _p,_maxDist,_minDist,_closestPt)); } template unsigned int GetKClosest(OBJPOINTDISTFUNCTOR & _getPointDistance,OBJMARKER & _marker, const unsigned int _k, const CoordType & _p, const ScalarType & _maxDist,OBJPTRCONTAINER & _objectPtrs, DISTCONTAINER & _distances, POINTCONTAINER & _points) { return (vcg::GridGetKClosest(*this,_getPointDistance,_marker,_k,_p,_maxDist,_objectPtrs,_distances,_points)); } template unsigned int GetInSphere(OBJPOINTDISTFUNCTOR & _getPointDistance, OBJMARKER & _marker, const CoordType & _p, const ScalarType & _r, OBJPTRCONTAINER & _objectPtrs, DISTCONTAINER & _distances, POINTCONTAINER & _points) { return(vcg::GridGetInSphere (*this,_getPointDistance,_marker,_p,_r,_objectPtrs,_distances,_points)); } template unsigned int GetInBox(OBJMARKER & _marker, const vcg::Box3 _bbox, OBJPTRCONTAINER & _objectPtrs) { return(vcg::GridGetInBox (*this,_marker,_bbox,_objectPtrs)); } template ObjPtr DoRay(OBJRAYISECTFUNCTOR & _rayIntersector, OBJMARKER & _marker, const Ray3 & _ray, const ScalarType & _maxDist, ScalarType & _t) { return(vcg::GridDoRay(*this,_rayIntersector,_marker,_ray,_maxDist,_t)); } /* If the grid has a cubic voxel of side this function process all couple of elementes in neighbouring cells. GATHERFUNCTOR needs to expose this method: bool operator()(OBJTYPE *v1, OBJTYPE *v2); which is then called ONCE per unordered pair v1,v2. example: struct GFunctor { double radius2, iradius2; GFunctor(double radius) { radius2 = radius*radius; iradius2 = 1/radius2; } bool operator()(CVertex *v1, CVertex *v2) { Point3d &p = v1->P(); Point3d &q = v2->P(); double dist2 = (p-q).SquaredNorm(); if(dist2 < radius2) { double w = exp(dist2*iradius2); //do something } } }; */ template void Gather(GATHERFUNCTOR gfunctor) { static int corner[8*3] = { 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1 }; static int diagonals[14*2] = { 0, 0, 0, 1, 0, 2, 0, 3, 0, 4, 0, 5, 0, 6, 0, 7, 2, 3, 1, 3, 1, 2, 1, 4, 2, 5, 3, 6 }; Cell ostart, oend, dstart, dend; for(int z = 0; z < this->siz[2]; z++) { for(int y = 0; y < this->siz[1]; y++) { for(int x = 0; x < this->siz[0]; x++) { Grid(x, y, z, ostart, oend); for(Cell c = ostart; c != oend; c++) for(Cell s = c+1; s != oend; s++) gfunctor(c->Elem(), s->Elem()); for(int d = 2; d < 28; d += 2) { //skipping self int *cs = corner + 3*diagonals[d]; int *ce = corner + 3*diagonals[d+1]; if((x + cs[0] < this->siz[0]) && (y + cs[1] < this->siz[1]) && (z + cs[2] < this->siz[2]) && (x + ce[0] < this->siz[0]) && (y + ce[1] < this->siz[1]) && (z + ce[2] < this->siz[2])) { Grid(x+cs[0], y+cs[1], z+cs[2], ostart, oend); Grid(x+ce[0], y+ce[1], z+ce[2], dstart, dend); for(Cell c = ostart; c != oend; c++) for(Cell s = dstart; s != dend; s++) gfunctor(c->Elem(), s->Elem()); } } } } } } }; //end class GridStaticPtr } // end namespace #endif qutemol/vcg/vcg/space/index/aabb_binary_tree/0000755000175000017500000000000011633404241017632 5ustar mbambaqutemol/vcg/vcg/space/index/aabb_binary_tree/kclosest.h0000444000175000017500000001265510316571671021652 0ustar mbamba/**************************************************************************** * VCGLib o o * * Visual and Computer Graphics Library o o * * _ O _ * * Copyright(C) 2004 \/)\/ * * Visual Computing Lab /\/| * * ISTI - Italian National Research Council | * * \ * * All rights reserved. * * * * 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. * * * * 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 (http://www.gnu.org/licenses/gpl.txt) * * for more details. * * * ****************************************************************************/ /**************************************************************************** History $Log: kclosest.h,v $ Revision 1.2 2005/09/28 19:49:13 m_di_benedetto #included aabbtree base. Revision 1.1 2005/09/26 18:33:16 m_di_benedetto First Commit. ****************************************************************************/ #ifndef __VCGLIB_AABBBINARYTREE_KCLOSEST_H #define __VCGLIB_AABBBINARYTREE_KCLOSEST_H // stl headers #include #include // vcg headers #include #include /***************************************************************************/ namespace vcg { template class AABBBinaryTreeKClosest { public: typedef AABBBinaryTreeKClosest ClassType; typedef TREETYPE TreeType; typedef typename TreeType::ScalarType ScalarType; typedef typename TreeType::CoordType CoordType; typedef typename TreeType::NodeType NodeType; typedef typename TreeType::ObjPtr ObjPtr; protected: class ClosestObjType { public: ObjPtr pObj; ScalarType minDist; CoordType closestPt; }; class CompareClosest { public: bool operator () (const ClosestObjType & a, const ClosestObjType & b) { return (a.minDist < b.minDist); } }; typedef std::priority_queue, CompareClosest> PQueueType; public: template static inline unsigned int KClosest(TreeType & tree, OBJPOINTDISTANCEFUNCT & getPointDistance, const unsigned int k, const CoordType & p, const ScalarType & maxDist, OBJPTRCONTAINERTYPE & objects, DISTCONTAINERTYPE & distances, POINTCONTAINERTYPE & points) { typedef std::vector NodePtrVector; typedef typename NodePtrVector::const_iterator NodePtrVector_ci; if (k == 0) { return (0); } NodeType * pRoot = tree.pRoot; if (pRoot == 0) { return (0); } PQueueType pq; ScalarType mindmax = maxDist; ClassType::DepthFirstCollect(pRoot, getPointDistance, k, p, mindmax, pq); const unsigned int sz = (unsigned int)(pq.size()); while (!pq.empty()) { ClosestObjType cobj = pq.top(); pq.pop(); objects.push_back(cobj.pObj); distances.push_back(cobj.minDist); points.push_back(cobj.closestPt); } return (sz); } protected: template static void DepthFirstCollect(NodeType * node, OBJPOINTDISTANCEFUNCT & getPointDistance, const unsigned int k, const CoordType & p, ScalarType & mindmax, PQueueType & pq) { const CoordType dc = Abs(p - node->boxCenter); if (pq.size() >= k) { const ScalarType dmin = LowClampToZero(dc - node->boxHalfDims).SquaredNorm(); if (dmin >= mindmax) { return; } } if (node->IsLeaf()) { bool someInserted = true; for (typename TreeType::ObjPtrVectorConstIterator si=node->oBegin; si!=node->oEnd; ++si) { ScalarType minDst = (pq.size() >= k) ? (pq.top().minDist) : (mindmax); ClosestObjType cobj; if (getPointDistance(*(*si), p, minDst, cobj.closestPt)) { someInserted = true; cobj.pObj = (*si); cobj.minDist = minDst; if (pq.size() >= k) { pq.pop(); } pq.push(cobj); } } if (someInserted) { if (pq.size() >= k) { const ScalarType dmax = pq.top().minDist; const ScalarType sqdmax = dmax * dmax; if (sqdmax < mindmax) { mindmax = sqdmax; } } } } else { if (node->children[0] != 0) { ClassType::DepthFirstCollect(node->children[0], getPointDistance, k, p, mindmax, pq); } if (node->children[1] != 0) { ClassType::DepthFirstCollect(node->children[1], getPointDistance, k, p, mindmax, pq); } } } }; } // end namespace vcg #endif // #ifndef __VCGLIB_AABBBINARYTREE_KCLOSEST_H qutemol/vcg/vcg/space/index/aabb_binary_tree/base.h0000444000175000017500000003426510323157214020725 0ustar mbamba/**************************************************************************** * VCGLib o o * * Visual and Computer Graphics Library o o * * _ O _ * * Copyright(C) 2004 \/)\/ * * Visual Computing Lab /\/| * * ISTI - Italian National Research Council | * * \ * * All rights reserved. * * * * 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. * * * * 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 (http://www.gnu.org/licenses/gpl.txt) * * for more details. * * * ****************************************************************************/ /**************************************************************************** History $Log: base.h,v $ Revision 1.3 2005/10/12 09:59:40 cignoni Removed the supposedly wrong first parameter in the three invocation of ClassType::BoundObjects. Revision 1.2 2005/10/05 01:43:28 m_di_benedetto Removed "parent" pointer class member in Node class. Revision 1.1 2005/09/28 19:44:49 m_di_benedetto First Commit. ****************************************************************************/ #ifndef __VCGLIB_AABBBINARYTREEBASE_H #define __VCGLIB_AABBBINARYTREEBASE_H // standard headers #include // stl headers #include // vcg headers #include #include /***************************************************************************/ namespace vcg { template class AABBBinaryTree { public: typedef AABBBinaryTree ClassType; typedef OBJTYPE ObjType; typedef ObjType * ObjPtr; typedef SCALARTYPE ScalarType; typedef NODEAUXDATATYPE NodeAuxDataType; typedef Point3 CoordType; typedef std::vector ObjPtrVector; typedef typename ObjPtrVector::iterator ObjPtrVectorIterator; typedef typename ObjPtrVector::const_iterator ObjPtrVectorConstIterator; public: class AABBBinaryTreeNode { public: CoordType boxCenter; CoordType boxHalfDims; ObjPtrVectorIterator oBegin; ObjPtrVectorIterator oEnd; AABBBinaryTreeNode * children[2]; unsigned char splitAxis; NodeAuxDataType auxData; inline AABBBinaryTreeNode(void); inline ~AABBBinaryTreeNode(void); inline void Clear(void); inline bool IsLeaf(void) const; inline unsigned int ObjectsCount(void) const; inline unsigned int & Flags(void); inline const unsigned int & Flags(void) const; inline ScalarType & ScalarValue(void); inline const ScalarType & ScalarValue(void) const; inline int & IntValue(void); inline const int & IntValue(void) const; inline unsigned int & UIntValue(void); inline const unsigned int & UIntValue(void) const; inline void * & PtrValue(void); inline const void * & PtrValue(void) const; protected: union SharedDataUnion { unsigned int flags; int intValue; unsigned int uintValue; ScalarType scalarValue; void * ptrValue; }; SharedDataUnion sharedData; }; typedef AABBBinaryTreeNode NodeType; ObjPtrVector pObjects; NodeType * pRoot; inline AABBBinaryTree(void); inline ~AABBBinaryTree(void); inline void Clear(void); template inline bool Set(const OBJITERATOR & oBegin, const OBJITERATOR & oEnd, OBJITERATORPTRFUNCT & objPtr, OBJBOXFUNCT & objBox, OBJBARYCENTERFUNCT & objBarycenter, const unsigned int maxElemsPerLeaf = 1, const ScalarType & leafBoxMaxVolume = ((ScalarType)0), const bool useVariance = true); protected: template inline static NodeType * BoundObjects(const ObjPtrVectorIterator & oBegin, const ObjPtrVectorIterator & oEnd, const unsigned int size, const unsigned int maxElemsPerLeaf, const ScalarType & leafBoxMaxVolume, const bool useVariance, OBJBOXFUNCT & getBox, OBJBARYCENTERFUNCT & getBarycenter); template inline static int BalanceMedian(const ObjPtrVectorIterator & oBegin, const ObjPtrVectorIterator & oEnd, const int size, const int splitAxis, OBJBARYCENTERFUNCT & getBarycenter, ObjPtrVectorIterator & medianIter); }; template AABBBinaryTree::AABBBinaryTree(void) { this->pObjects.clear(); this->pRoot = 0; } template AABBBinaryTree::~AABBBinaryTree(void) { this->pObjects.clear(); delete this->pRoot; } template void AABBBinaryTree::Clear(void) { this->pObjects.clear(); delete this->pRoot; this->pRoot = 0; } template template bool AABBBinaryTree::Set(const OBJITERATOR & oBegin, const OBJITERATOR & oEnd, OBJITERATORPTRFUNCT & objPtr, OBJBOXFUNCT & objBox, OBJBARYCENTERFUNCT & objBarycenter, const unsigned int maxElemsPerLeaf, const ScalarType & leafBoxMaxVolume, const bool useVariance) { this->Clear(); if ((maxElemsPerLeaf == 0) && (leafBoxMaxVolume <= ((ScalarType)0))) { return (false); } const unsigned int size = (unsigned int)std::distance(oBegin, oEnd); this->pObjects.reserve(size); for (OBJITERATOR oi=oBegin; oi!=oEnd; ++oi) { this->pObjects.push_back(objPtr(*oi)); } this->pRoot = ClassType::BoundObjects(this->pObjects.begin(), this->pObjects.end(), size, maxElemsPerLeaf, leafBoxMaxVolume, useVariance, objBox, objBarycenter); return (this->pRoot != 0); } template template typename AABBBinaryTree::NodeType * AABBBinaryTree::BoundObjects(const ObjPtrVectorIterator & oBegin, const ObjPtrVectorIterator & oEnd, const unsigned int size, const unsigned int maxElemsPerLeaf, const ScalarType & leafBoxMaxVolume, const bool useVariance, OBJBOXFUNCT & getBox, OBJBARYCENTERFUNCT & getBarycenter) { if (size <= 0) { return (0); } NodeType * pNode = new NodeType(); if (pNode == 0) { return (0); } pNode->children[0] = 0; pNode->children[1] = 0; pNode->oBegin = oBegin; pNode->oEnd = oEnd; Box3 bbox; bbox.SetNull(); for (ObjPtrVectorConstIterator oi=pNode->oBegin; oi!=pNode->oEnd; ++oi) { Box3 tbox; getBox(*(*oi), tbox); bbox.Add(tbox); } pNode->boxCenter = bbox.Center(); pNode->boxHalfDims = bbox.Dim() / ((ScalarType)2); const bool bMaxObjectsReached = (((maxElemsPerLeaf > 0) && (size <= maxElemsPerLeaf)) || (size == 1)); const bool bMaxVolumeReached = ((leafBoxMaxVolume > ((ScalarType)0)) && (bbox.Volume() <= leafBoxMaxVolume)); const bool isLeaf = bMaxObjectsReached || bMaxVolumeReached; if (isLeaf) { pNode->splitAxis = 0; return (pNode); } CoordType pSplit; if (useVariance) { CoordType mean((ScalarType)0, (ScalarType)0, (ScalarType)0); CoordType variance((ScalarType)0, (ScalarType)0, (ScalarType)0); for (ObjPtrVectorIterator oi=oBegin; oi!=oEnd; ++oi) { CoordType bc; getBarycenter(*(*oi), bc); mean += bc; variance[0] += bc[0] * bc[0]; variance[1] += bc[1] * bc[1]; variance[2] += bc[2] * bc[2]; } variance[0] -= (mean[0] * mean[0]) / ((ScalarType)size); variance[1] -= (mean[1] * mean[1]) / ((ScalarType)size); variance[2] -= (mean[2] * mean[2]) / ((ScalarType)size); pSplit = variance; } else { pSplit = pNode->boxHalfDims; } ScalarType maxDim = pSplit[0]; unsigned char splitAxis = 0; if (maxDim < pSplit[1]) { maxDim = pSplit[1]; splitAxis = 1; } if (maxDim < pSplit[2]) { maxDim = pSplit[2]; splitAxis = 2; } pNode->splitAxis = splitAxis; ObjPtrVectorIterator median; const int lSize = ClassType::BalanceMedian(pNode->oBegin, pNode->oEnd, size, splitAxis, getBarycenter, median); const int rSize = size - lSize; if (lSize > 0) { pNode->children[0] = ClassType::BoundObjects(pNode->oBegin, median, lSize, maxElemsPerLeaf, leafBoxMaxVolume, useVariance, getBox, getBarycenter); if (pNode->children[0] == 0) { delete pNode; return (0); } } if (rSize > 0) { pNode->children[1] = ClassType::BoundObjects(median, pNode->oEnd, rSize, maxElemsPerLeaf, leafBoxMaxVolume, useVariance, getBox, getBarycenter); if (pNode->children[1] == 0) { delete pNode; return (0); } } return (pNode); } template template int AABBBinaryTree::BalanceMedian(const ObjPtrVectorIterator & oBegin, const ObjPtrVectorIterator & oEnd, const int size, const int splitAxis, OBJBARYCENTERFUNCT & getBarycenter, ObjPtrVectorIterator & medianIter) { const int iMedian = (size + 1) / 2; ObjPtrVectorIterator l, r, i, j; ObjPtr iTmp; ScalarType pos; ObjPtrVectorIterator median = oBegin + iMedian; CoordType bc; l = oBegin; r = oEnd - 1; while (l < r) { getBarycenter(*(*r), bc); pos = bc[splitAxis]; i = l; j = r - 1; while (true) { getBarycenter(*(*i), bc); while ((bc[splitAxis] <= pos) && (i < r)) { i++; getBarycenter(*(*i), bc); } getBarycenter(*(*j), bc); while ((bc[splitAxis] > pos) && (j > l)) { j--; getBarycenter(*(*j), bc); } if (i >= j) { break; } iTmp = (*i); (*i) = (*j); (*j) = iTmp; } iTmp = (*i); (*i) = (*r); (*r) = iTmp; if (i >= (median)) { r = i - 1; } if (i <= (median)) { l = i + 1; } } medianIter = median; return (iMedian); } template AABBBinaryTree::AABBBinaryTreeNode::AABBBinaryTreeNode(void) { this->children[0] = 0; this->children[1] = 0; } template AABBBinaryTree::AABBBinaryTreeNode::~AABBBinaryTreeNode(void) { delete this->children[0]; delete this->children[1]; } template void AABBBinaryTree::AABBBinaryTreeNode::Clear(void) { delete this->children[0]; this->children[0] = 0; delete this->children[1]; this->children[1] = 0; } template bool AABBBinaryTree::AABBBinaryTreeNode::IsLeaf(void) const { return ((this->children[0] == 0) && (this->children[1] == 0)); } template unsigned int AABBBinaryTree::AABBBinaryTreeNode::ObjectsCount(void) const { return ((unsigned int)(std::distance(this->oBegin, this->oEnd))); } template unsigned int & AABBBinaryTree::AABBBinaryTreeNode::Flags(void) { return (this->sharedData.flags); } template const unsigned int & AABBBinaryTree::AABBBinaryTreeNode::Flags(void) const { return (this->sharedData.flags); } template int & AABBBinaryTree::AABBBinaryTreeNode::IntValue(void) { return (this->sharedData.intValue); } template const int & AABBBinaryTree::AABBBinaryTreeNode::IntValue(void) const { return (this->sharedData.intValue); } template unsigned int & AABBBinaryTree::AABBBinaryTreeNode::UIntValue(void) { return (this->sharedData.uintValue); } template const unsigned int & AABBBinaryTree::AABBBinaryTreeNode::UIntValue(void) const { return (this->sharedData.uintValue); } template typename AABBBinaryTree::ScalarType & AABBBinaryTree::AABBBinaryTreeNode::ScalarValue(void) { return (this->sharedData.scalarValue); } template const typename AABBBinaryTree::ScalarType & AABBBinaryTree::AABBBinaryTreeNode::ScalarValue(void) const { return (this->sharedData.scalarValue); } template void * & AABBBinaryTree::AABBBinaryTreeNode::PtrValue(void) { return (this->sharedData.ptrValue); } template const void * & AABBBinaryTree::AABBBinaryTreeNode::PtrValue(void) const { return (this->sharedData.ptrValue); } } // end namespace vcg #endif // #ifndef __VCGLIB_AABBBINARYTREEBASE_H qutemol/vcg/vcg/space/index/aabb_binary_tree/closest.h0000444000175000017500000001234710316571671021475 0ustar mbamba/**************************************************************************** * VCGLib o o * * Visual and Computer Graphics Library o o * * _ O _ * * Copyright(C) 2004 \/)\/ * * Visual Computing Lab /\/| * * ISTI - Italian National Research Council | * * \ * * All rights reserved. * * * * 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. * * * * 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 (http://www.gnu.org/licenses/gpl.txt) * * for more details. * * * ****************************************************************************/ /**************************************************************************** History $Log: closest.h,v $ Revision 1.2 2005/09/28 19:49:13 m_di_benedetto #included aabbtree base. Revision 1.1 2005/09/26 18:33:16 m_di_benedetto First Commit. ****************************************************************************/ #ifndef __VCGLIB_AABBBINARYTREE_CLOSEST_H #define __VCGLIB_AABBBINARYTREE_CLOSEST_H // stl headers #include #include // vcg headers #include #include #include /***************************************************************************/ namespace vcg { template class AABBBinaryTreeClosest { public: typedef AABBBinaryTreeClosest ClassType; typedef TREETYPE TreeType; typedef typename TreeType::ScalarType ScalarType; typedef typename TreeType::CoordType CoordType; typedef typename TreeType::NodeType NodeType; typedef typename TreeType::ObjPtr ObjPtr; template static inline ObjPtr Closest(TreeType & tree, OBJPOINTDISTANCEFUNCT & getPointDistance, const CoordType & p, const ScalarType & maxDist, ScalarType & minDist, CoordType & q) { typedef OBJPOINTDISTANCEFUNCT ObjPointDistanceFunct; typedef std::vector NodePtrVector; typedef typename NodePtrVector::const_iterator NodePtrVector_ci; NodeType * pRoot = tree.pRoot; if (pRoot == 0) { return (0); } NodePtrVector clist1; NodePtrVector clist2; NodePtrVector leaves; NodePtrVector * candidates = &clist1; NodePtrVector * newCandidates = &clist2; clist1.reserve(tree.pObjects.size()); clist2.reserve(tree.pObjects.size()); leaves.reserve(tree.pObjects.size()); clist1.resize(0); clist2.resize(0); leaves.resize(0); ScalarType minMaxDist = maxDist * maxDist; candidates->push_back(pRoot); while (!candidates->empty()) { newCandidates->resize(0); for (NodePtrVector_ci bv=candidates->begin(); bv!=candidates->end(); ++bv) { const CoordType dc = Abs(p - (*bv)->boxCenter); const ScalarType maxDist = (dc + (*bv)->boxHalfDims).SquaredNorm(); (*bv)->ScalarValue() = LowClampToZero(dc - (*bv)->boxHalfDims).SquaredNorm(); if (maxDist < minMaxDist) { minMaxDist = maxDist; } } for (NodePtrVector_ci ci=candidates->begin(); ci!=candidates->end(); ++ci) { if ((*ci)->ScalarValue() < minMaxDist) { if ((*ci)->IsLeaf()) { leaves.push_back(*ci); } else { if ((*ci)->children[0] != 0) { newCandidates->push_back((*ci)->children[0]); } if ((*ci)->children[1] != 0) { newCandidates->push_back((*ci)->children[1]); } } } } NodePtrVector * cSwap = candidates; candidates = newCandidates; newCandidates = cSwap; } clist1.clear(); clist2.clear(); ObjPtr closestObject = 0; CoordType closestPoint; ScalarType closestDist = math::Sqrt(minMaxDist) + std::numeric_limits::epsilon(); ScalarType closestDistSq = closestDist * closestDist; for (NodePtrVector_ci ci=leaves.begin(); ci!=leaves.end(); ++ci) { if ((*ci)->ScalarValue() < closestDistSq) { for (typename TreeType::ObjPtrVectorConstIterator si=(*ci)->oBegin; si!=(*ci)->oEnd; ++si) { if (getPointDistance(*(*si), p, closestDist, closestPoint)) { closestDistSq = closestDist * closestDist; closestObject = (*si); } } } } leaves.clear(); q = closestPoint; minDist = closestDist; return (closestObject); } }; } // end namespace vcg #endif // #ifndef __VCGLIB_AABBBINARYTREE_CLOSEST_H qutemol/vcg/vcg/space/index/aabb_binary_tree/aabb_binary_tree.h0000444000175000017500000001443310320064632023254 0ustar mbamba/**************************************************************************** * VCGLib o o * * Visual and Computer Graphics Library o o * * _ O _ * * Copyright(C) 2004 \/)\/ * * Visual Computing Lab /\/| * * ISTI - Italian National Research Council | * * \ * * All rights reserved. * * * * 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. * * * * 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 (http://www.gnu.org/licenses/gpl.txt) * * for more details. * * * ****************************************************************************/ /**************************************************************************** History $Log: aabb_binary_tree.h,v $ Revision 1.6 2005/10/02 23:13:30 cignoni Changed the default strategy for building a AABB tree. Now the max num of elem per leaf is a constant (10) Revision 1.5 2005/09/29 22:18:16 m_di_benedetto Added frustum culling methods, renamed some parameters. Revision 1.4 2005/09/28 21:23:03 m_di_benedetto Added Import() to box and barycenter functors to handle tree and objects with different ScalarType. Revision 1.3 2005/09/28 20:10:41 m_di_benedetto First Commit. ****************************************************************************/ #ifndef __VCGLIB_AABBBINARYTREEINDEX_H #define __VCGLIB_AABBBINARYTREEINDEX_H // vcg headers #include #include #include #include #include #include #include /***************************************************************************/ namespace vcg { template class AABBBinaryTreeIndex : public SpatialIndex { public: typedef AABBBinaryTreeIndex ClassType; typedef OBJTYPE ObjType; typedef SCALARTYPE ScalarType; typedef NODEAUXDATA NodeAuxData; typedef ObjType * ObjPtr; typedef Point3 CoordType; typedef AABBBinaryTree TreeType; inline TreeType & Tree(void) { return (this->tree); } inline const TreeType & Tree(void) const { return (this->tree); } template inline void Set(const OBJITER & _oBegin, const OBJITER & _oEnd) { GetPointerFunctor getPtr; GetBox3Functor getBox; GetBarycenter3Functor getBarycenter; //const unsigned int divs = 100; //const unsigned int size = (unsigned int)(std::distance(_oBegin, _oEnd)); //const unsigned int maxObjectsPerLeaf = (size < divs) ? (size) : ((unsigned int)((float)(std::distance(_oBegin, _oEnd)) / (float)divs)); const unsigned int maxObjectsPerLeaf = 10; const ScalarType leafBoxMaxVolume = ((ScalarType)0); const bool useVariance = true; (void)(this->tree.Set(_oBegin, _oEnd, getPtr, getBox, getBarycenter, maxObjectsPerLeaf, leafBoxMaxVolume, useVariance)); } template inline bool Set(const OBJITERATOR & _oBegin, const OBJITERATOR & _oEnd, OBJITERATORPTRFUNCT & _objPtr, OBJBOXFUNCT & _objBox, OBJBARYCENTERFUNCT & _objBarycenter, const unsigned int _maxElemsPerLeaf = 1, const ScalarType & _leafBoxMaxVolume = ((ScalarType)0), const bool _useVariance = true) { return (this->tree.Set(_oBegin, _oEnd, _objPtr, _objBox, _objBarycenter, _maxElemsPerLeaf, _leafBoxMaxVolume, _useVariance)); } template inline ObjPtr GetClosest( OBJPOINTDISTFUNCTOR & _getPointDistance, OBJMARKER & _marker, const CoordType & _p, const ScalarType & _maxDist, ScalarType & _minDist, CoordType & _closestPt) { (void)_marker; return (AABBBinaryTreeClosest::Closest(this->tree, _getPointDistance, _p, _maxDist, _minDist, _closestPt)); } template inline unsigned int GetKClosest( OBJPOINTDISTFUNCTOR & _getPointDistance, OBJMARKER & _marker, const unsigned int _k, const CoordType & _p, const ScalarType & _maxDist, OBJPTRCONTAINER & _objectPtrs, DISTCONTAINER & _distances, POINTCONTAINER & _points) { (void)_marker; return (AABBBinaryTreeKClosest::KClosest(this->tree, _getPointDistance, _k, _p, _maxDist, _objectPtrs, _distances, _points)); } template inline ObjPtr DoRay(OBJRAYISECTFUNCTOR & _rayIntersector, OBJMARKER & _marker, const Ray3 & _ray, const ScalarType & _maxDist, ScalarType & _t) { (void)_marker; return (AABBBinaryTreeRay::Ray(this->tree, _rayIntersector, _ray, _maxDist, _t)); } inline void InitializeFrustumCull(void) { (void)(AABBBinaryTreeFrustumCull::Initialize(this->tree)); } inline void FrustumCull(const Plane3 _frustumPlanes[6], const unsigned int _minNodeObjectsCount) { (void)(AABBBinaryTreeFrustumCull::FrustumCull(this->tree, _frustumPlanes, _minNodeObjectsCount)); } protected: TreeType tree; }; } // end namespace vcg #endif // #ifndef __VCGLIB_AABBBINARYTREEINDEX_H qutemol/vcg/vcg/space/index/aabb_binary_tree/ray.h0000444000175000017500000001363010327665523020612 0ustar mbamba/**************************************************************************** * VCGLib o o * * Visual and Computer Graphics Library o o * * _ O _ * * Copyright(C) 2004 \/)\/ * * Visual Computing Lab /\/| * * ISTI - Italian National Research Council | * * \ * * All rights reserved. * * * * 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. * * * * 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 (http://www.gnu.org/licenses/gpl.txt) * * for more details. * * * ****************************************************************************/ /**************************************************************************** History $Log: ray.h,v $ Revision 1.4 2005/10/26 11:41:07 m_di_benedetto Removed child ordered traversal. Revision 1.3 2005/10/05 01:40:56 m_di_benedetto Node children are now tested in ascending ray-T order. Revision 1.2 2005/09/28 19:48:31 m_di_benedetto Removed hit point parameter, #included aabbtree base. Revision 1.1 2005/09/26 18:33:16 m_di_benedetto First Commit. ****************************************************************************/ #ifndef __VCGLIB_AABBBINARYTREE_RAY_H #define __VCGLIB_AABBBINARYTREE_RAY_H // vcg headers #include #include /***************************************************************************/ namespace vcg { template class AABBBinaryTreeRay { public: typedef AABBBinaryTreeRay ClassType; typedef TREETYPE TreeType; typedef typename TreeType::ScalarType ScalarType; typedef typename TreeType::CoordType CoordType; typedef typename TreeType::NodeType NodeType; typedef typename TreeType::ObjPtr ObjPtr; template static inline ObjPtr Ray(TreeType & tree, OBJRAYISECTFUNCT & rayIntersection, const Ray3 & ray, const ScalarType & maxDist, ScalarType & t) { typedef std::vector NodePtrVector; typedef typename NodePtrVector::const_iterator NodePtrVector_ci; NodeType * pRoot = tree.pRoot; if (pRoot == 0) { return (0); } const CoordType & rayDirection = ray.Direction(); t = maxDist / rayDirection.Norm(); Ray3Ex rayex; rayex.r = ray; rayex.invDirection[0] = ((ScalarType)1) / rayDirection[0]; rayex.invDirection[1] = ((ScalarType)1) / rayDirection[1]; rayex.invDirection[2] = ((ScalarType)1) / rayDirection[2]; rayex.sign[0] = (rayex.invDirection[0] < ((ScalarType)0)) ? (1) : (0); rayex.sign[1] = (rayex.invDirection[1] < ((ScalarType)0)) ? (1) : (0); rayex.sign[2] = (rayex.invDirection[2] < ((ScalarType)0)) ? (1) : (0); ObjPtr closestObj = 0; ClassType::DepthFirstRayIsect(pRoot, rayIntersection, rayex, t, closestObj); return (closestObj); } protected: class Ray3Ex { public: Ray3 r; CoordType invDirection; unsigned char sign[3]; }; static inline bool IntersectionBoxRay(const CoordType & boxCenter, const CoordType & boxHalfDims, const Ray3Ex & ray, ScalarType & t0) { const CoordType bounds[2] = { boxCenter - boxHalfDims, boxCenter + boxHalfDims }; ScalarType tmin, tmax; ScalarType tcmin, tcmax; const CoordType & origin = ray.r.Origin(); tmin = (bounds[ray.sign[0]][0] - origin[0]) * ray.invDirection[0]; tmax = (bounds[1 - ray.sign[0]][0] - origin[0]) * ray.invDirection[0]; tcmin = (bounds[ray.sign[1]][1] - origin[1]) * ray.invDirection[1]; tcmax = (bounds[1 - ray.sign[1]][1] - origin[1]) * ray.invDirection[1]; if ((tmin > tcmax) || (tcmin > tmax)) { return (false); } if (tcmin > tmin) { tmin = tcmin; } if (tcmax < tmax) { tmax = tcmax; } tcmin = (bounds[ray.sign[2]][2] - origin[2]) * ray.invDirection[2]; tcmax = (bounds[1-ray.sign[2]][2] - origin[2]) * ray.invDirection[2]; if ((tmin > tcmax) || (tcmin > tmax)) { return (false); } if (tcmin > tmin) { tmin = tcmin; } //if (tcmax < tmax) { tmax = tcmax; } t0 = (tmin >= ((ScalarType)0)) ? (tmin) :((ScalarType)0); return (true); } template static inline void DepthFirstRayIsect(const NodeType * node, OBJRAYISECTFUNCT & rayIntersection, const Ray3Ex & ray, ScalarType & rayT, ObjPtr & closestObj) { if (node == 0) { return; } ScalarType rt; if (!ClassType::IntersectionBoxRay(node->boxCenter, node->boxHalfDims, ray, rt)) { return; } if (rt >= rayT) { return; } if (node->IsLeaf()) { for (typename TreeType::ObjPtrVectorConstIterator si=node->oBegin; si!=node->oEnd; ++si) { if (rayIntersection(*(*si), ray.r, rt)) { if (rt < rayT) { rayT = rt; closestObj = (*si); } } } return; } ClassType::DepthFirstRayIsect(node->children[0], rayIntersection, ray, rayT, closestObj); ClassType::DepthFirstRayIsect(node->children[1], rayIntersection, ray, rayT, closestObj); } }; } // end namespace vcg #endif // #ifndef __VCGLIB_AABBBINARYTREE_RAY_H qutemol/vcg/vcg/space/index/aabb_binary_tree/frustum_cull.h0000444000175000017500000002262310363715051022535 0ustar mbamba/**************************************************************************** * VCGLib o o * * Visual and Computer Graphics Library o o * * _ O _ * * Copyright(C) 2004 \/)\/ * * Visual Computing Lab /\/| * * ISTI - Italian National Research Council | * * \ * * All rights reserved. * * * * 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. * * * * 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 (http://www.gnu.org/licenses/gpl.txt) * * for more details. * * * ****************************************************************************/ /**************************************************************************** History $Log: frustum_cull.h,v $ Revision 1.9 2006/01/19 13:54:49 m_di_benedetto Corrected Pass-Through bits and added visit flag. Revision 1.8 2005/11/30 09:57:13 m_di_benedetto Added methods to flag visibility. Revision 1.7 2005/10/26 11:42:03 m_di_benedetto Added PASS_THROUGH flags. Revision 1.6 2005/10/15 19:14:35 m_di_benedetto Modified objapplyfunctor to nodeapplyfunctor. Revision 1.5 2005/10/05 01:59:56 m_di_benedetto First Commit, new version. Revision 1.3 2005/09/29 22:20:49 m_di_benedetto Removed '&' in FrustumCull() method. Revision 1.2 2005/09/28 19:57:18 m_di_benedetto #included aabb tree base. Revision 1.1 2005/09/26 18:33:16 m_di_benedetto First Commit. ****************************************************************************/ #ifndef __VCGLIB_AABBBINARYTREE_FRUSTUMCULL_H #define __VCGLIB_AABBBINARYTREE_FRUSTUMCULL_H // std headers /* EMPTY */ // vcg headers #include #include #include /***************************************************************************/ namespace vcg { template class AABBBinaryTreeFrustumCull { public: typedef AABBBinaryTreeFrustumCull ClassType; typedef TREETYPE TreeType; typedef typename TreeType::ScalarType ScalarType; typedef typename TreeType::CoordType CoordType; typedef typename TreeType::NodeType NodeType; typedef typename TreeType::ObjPtr ObjPtr; protected: class VFrustumPlane { public: CoordType normal; ScalarType offset; unsigned int pVertexIndex[3]; }; class VFrustum { public: VFrustumPlane planes[6]; }; public: enum { FC_FIRST_PLANE_BIT = 0, FC_PARTIALLY_VISIBLE_BIT = (1 << (FC_FIRST_PLANE_BIT + 3)), FC_FULLY_VISIBLE_BIT = (1 << (FC_FIRST_PLANE_BIT + 4)), FC_PASS_THROUGH_FIRST_BIT = (FC_FIRST_PLANE_BIT + 5) }; static inline bool IsPartiallyVisible(const NodeType * node) { return ((node->Flags() & FC_PARTIALLY_VISIBLE_BIT) != 0); } static inline bool IsFullyVisible(const NodeType * node) { return ((node->Flags() & FC_FULLY_VISIBLE_BIT) != 0); } static inline void SetFullyVisible(NodeType * node) { node->Flags() |= FC_FULLY_VISIBLE_BIT; } static inline void SetInvisible(NodeType * node) { node->Flags() &= ~(FC_FULLY_VISIBLE_BIT | FC_PARTIALLY_VISIBLE_BIT); } static inline bool IsVisible(const NodeType * node) { return ((node->Flags() & (FC_PARTIALLY_VISIBLE_BIT | FC_FULLY_VISIBLE_BIT)) != 0); } static inline unsigned int PassThrough(const NodeType * node) { return ((node->Flags() >> FC_PASS_THROUGH_FIRST_BIT) & 0x03); } static inline void Initialize(TreeType & tree) { NodeType * pRoot = tree.pRoot; if (pRoot == 0) { return; } ClassType::InitializeNodeFlagsRec(pRoot); } template static inline void FrustumCull(TreeType & tree, const Point3 & viewerPosition, const Plane3 frustumPlanes[6], const unsigned int minNodeObjectsCount, NODEAPPLYFUNCTOR & nodeApply) { NodeType * pRoot = tree.pRoot; if (pRoot == 0) { return; } VFrustum frustum; for (int i=0; i<6; ++i) { frustum.planes[i].normal = frustumPlanes[i].Direction(); frustum.planes[i].offset = frustumPlanes[i].Offset(); frustum.planes[i].pVertexIndex[0] = (frustum.planes[i].normal[0] >= ((ScalarType)0)) ? (1) : (0); frustum.planes[i].pVertexIndex[1] = (frustum.planes[i].normal[1] >= ((ScalarType)0)) ? (1) : (0); frustum.planes[i].pVertexIndex[2] = (frustum.planes[i].normal[2] >= ((ScalarType)0)) ? (1) : (0); } const unsigned char inMask = 0x3F; ClassType::NodeVsFrustum(tree.pRoot, viewerPosition, frustum, inMask, minNodeObjectsCount, nodeApply); } protected: static inline void InitializeNodeFlagsRec(NodeType * node) { //node->Flags() &= ~(0x7F); node->Flags() = 0; if (node->children[0] != 0) { ClassType::InitializeNodeFlagsRec(node->children[0]); } if (node->children[1] != 0) { ClassType::InitializeNodeFlagsRec(node->children[1]); } } template static inline void NodeVsFrustum(NodeType * node, const Point3 & viewerPosition, const VFrustum & f, unsigned char inMask, unsigned int minNodeObjectsCount, NODEAPPLYFUNCTOR & nodeApply) { if (node == 0) { return; } const CoordType bminmax[2] = { node->boxCenter - node->boxHalfDims, node->boxCenter + node->boxHalfDims, }; const unsigned int firstFail = (unsigned int)((node->Flags() >> FC_FIRST_PLANE_BIT) & 0x7); const VFrustumPlane * fp = f.planes + firstFail; unsigned char k = 1 << firstFail; unsigned char newMask = 0x0; bool fullInside = true; node->Flags() &= ~(1 << 25); node->Flags() &= ~(FC_PARTIALLY_VISIBLE_BIT | FC_FULLY_VISIBLE_BIT | (0x03 << FC_PASS_THROUGH_FIRST_BIT)); if ((k & inMask) != 0) { if ( ((fp->normal[0] * bminmax[fp->pVertexIndex[0]][0]) + (fp->normal[1] * bminmax[fp->pVertexIndex[1]][1]) + (fp->normal[2] * bminmax[fp->pVertexIndex[2]][2]) + (fp->offset)) < ((ScalarType)0) ) { return; } if ( ((fp->normal[0] * bminmax[1 - fp->pVertexIndex[0]][0]) + (fp->normal[1] * bminmax[1 - fp->pVertexIndex[1]][1]) + (fp->normal[2] * bminmax[1 - fp->pVertexIndex[2]][2]) + (fp->offset)) < ((ScalarType)0) ) { newMask |= k; fullInside = false; } } k = 1; for (unsigned int i=0; k<=inMask; ++i, k<<=1) { if ((i != firstFail) && ((k & inMask) != 0)) { fp = f.planes + i; if ( ((fp->normal[0] * bminmax[fp->pVertexIndex[0]][0]) + (fp->normal[1] * bminmax[fp->pVertexIndex[1]][1]) + (fp->normal[2] * bminmax[fp->pVertexIndex[2]][2]) + (fp->offset)) < ((ScalarType)0) ) { node->Flags() = (node->Flags() & ((~0x0) & (0x7 << ClassType::FC_FIRST_PLANE_BIT))) | (i << ClassType::FC_FIRST_PLANE_BIT); return; } if ( ((fp->normal[0] * bminmax[1 - fp->pVertexIndex[0]][0]) + (fp->normal[1] * bminmax[1 - fp->pVertexIndex[1]][1]) + (fp->normal[2] * bminmax[1 - fp->pVertexIndex[2]][2]) + (fp->offset)) < ((ScalarType)0) ) { newMask |= k; fullInside = false; } } } if (fullInside || (node->IsLeaf()) || (node->ObjectsCount() <= minNodeObjectsCount)) { node->Flags() |= FC_FULLY_VISIBLE_BIT; nodeApply(*node); return; } node->Flags() |= FC_PARTIALLY_VISIBLE_BIT; //ClassType::NodeVsFrustum(node->children[0], viewerPosition, f, newMask, minNodeObjectsCount, nodeApply); //ClassType::NodeVsFrustum(node->children[1], viewerPosition, f, newMask, minNodeObjectsCount, nodeApply); ScalarType dt; if (node->splitAxis == 0) { dt = viewerPosition[0] - node->boxCenter[0]; } else if (node->splitAxis == 1) { dt = viewerPosition[1] - node->boxCenter[1]; } else { dt = viewerPosition[2] - node->boxCenter[2]; } if (dt <= (ScalarType)0) { ClassType::NodeVsFrustum(node->children[0], viewerPosition, f, newMask, minNodeObjectsCount, nodeApply); ClassType::NodeVsFrustum(node->children[1], viewerPosition, f, newMask, minNodeObjectsCount, nodeApply); } else { ClassType::NodeVsFrustum(node->children[1], viewerPosition, f, newMask, minNodeObjectsCount, nodeApply); ClassType::NodeVsFrustum(node->children[0], viewerPosition, f, newMask, minNodeObjectsCount, nodeApply); } const bool c0 = (node->children[0] != 0) && ClassType::IsVisible(node->children[0]); const bool c1 = (node->children[1] != 0) && ClassType::IsVisible(node->children[1]); if (c0 != c1) { node->Flags() &= ~(0x03 << FC_PASS_THROUGH_FIRST_BIT); if (c0) { node->Flags() |= (0x01 << FC_PASS_THROUGH_FIRST_BIT); } else { node->Flags() |= (0x02 << FC_PASS_THROUGH_FIRST_BIT); } } } }; } // end namespace vcg #endif // #ifndef __VCGLIB_AABBBINARYTREE_FRUSTUMCULL_H qutemol/vcg/vcg/space/index/octree.h0000444000175000017500000006077710620574221016034 0ustar mbamba/**************************************************************************** * VCGLib o o * * Visual and Computer Graphics Library o o * * _ O _ * * Copyright(C) 2004 \/)\/ * * Visual Computing Lab /\/| * * ISTI - Italian National Research Council | * * \ * * All rights reserved. * * * * 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. * * * * 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 (http://www.gnu.org/licenses/gpl.txt) * * for more details. * * * ****************************************************************************/ #ifndef VCG_SPACE_INDEX_OCTREE_H #define VCG_SPACE_INDEX_OCTREE_H #include #include #include #include #ifdef __glut_h__ #include #include #endif #include #include #include #include namespace vcg { /*! * Given an object or an object pointer, return the reference to the object */ template struct Dereferencer { static TYPE& Ref(TYPE &t) { return ( t); } static TYPE& Ref(TYPE* &t) { return (*t); } static const TYPE& Ref(const TYPE &t) { return ( t); } static const TYPE& Ref(const TYPE* &t) { return (*t); } }; /*! * Given a type, return the type */ template class ReferenceType { public: typedef T Type; }; /*! * Given as type a pointer to type, return the type */ template class ReferenceType { public: typedef typename ReferenceType::Type Type; }; /*! * The type of the octree voxels */ struct Voxel { Voxel() { count = begin = end = -1; } void SetRange(const int begin, const int end) { this->begin = begin; this->end = end; count = end-begin; }; void AddRange(const Voxel *voxel) { assert(voxel->end>end); count += voxel->count; end = voxel->end; }; int begin; int end; int count; }; template < class OBJECT_TYPE, class SCALAR_TYPE> class Octree : public vcg::OctreeTemplate< Voxel, SCALAR_TYPE >, public vcg::SpatialIndex< OBJECT_TYPE, SCALAR_TYPE > { protected: struct Neighbour; public: typedef SCALAR_TYPE ScalarType; typedef OBJECT_TYPE ObjectType; typedef typename Octree::Leaf * LeafPointer; typedef typename Octree::InnerNode * InnerNodePointer; typedef typename ReferenceType::Type * ObjectPointer; typedef vcg::Voxel VoxelType; typedef VoxelType * VoxelPointer; typedef vcg::OctreeTemplate< VoxelType, SCALAR_TYPE > TemplatedOctree; typedef typename TemplatedOctree::ZOrderType ZOrderType; typedef typename TemplatedOctree::BoundingBoxType BoundingBoxType; typedef typename TemplatedOctree::CenterType CenterType; typedef typename TemplatedOctree::CoordinateType CoordType; typedef typename TemplatedOctree::NodeType NodeType; typedef typename TemplatedOctree::NodePointer NodePointer; typedef typename TemplatedOctree::NodeIndex NodeIndex; typedef typename std::vector< Neighbour >::iterator NeighbourIterator; protected: /*********************************************** * INNER DATA STRUCTURES AND PREDICATES * ***********************************************/ /*! * Structure used during the sorting of the dataset */ template < typename LEAF_TYPE > struct ObjectPlaceholder { typedef LEAF_TYPE* LeafPointer; ObjectPlaceholder() { z_order = object_index = -1, leaf_pointer = NULL;} ObjectPlaceholder(ZOrderType zOrder, void* leafPointer, unsigned int objectIndex) { z_order = zOrder; leaf_pointer = leafPointer; object_index = objectIndex; } ZOrderType z_order; LeafPointer leaf_pointer; unsigned int object_index; }; /*! * Predicate used during the sorting of the dataset */ template struct ObjectSorter { inline bool operator()(const ObjectPlaceholder< LEAF_TYPE > &first, const ObjectPlaceholder< LEAF_TYPE > &second) { return (first.z_orderobject = NULL; this->distance = -1.0f; }; Neighbour(ObjectPointer &object, CoordType &point, ScalarType distance) { this->object = object; this->point = point; this->distance = distance; } inline bool operator<(const Neighbour &n) const { return distance void Set(const OBJECT_ITERATOR & bObj, const OBJECT_ITERATOR & eObj /*, vcg::CallBackPos *callback=NULL*/) { // Compute the bounding-box enclosing the whole dataset typedef Dereferencer::Type > DereferencerType; BoundingBoxType bounding_box, obj_bb; bounding_box.SetNull(); for (OBJECT_ITERATOR iObj=bObj; iObj!=eObj; iObj++) { (*iObj).GetBBox(obj_bb); bounding_box.Add(obj_bb); } //...and expand it a bit more BoundingBoxType resulting_bb(bounding_box); CoordType offset = bounding_box.Dim()*Octree::EXPANSION_FACTOR; CoordType center = bounding_box.Center(); resulting_bb.Offset(offset); ScalarType longest_side = vcg::math::Max( resulting_bb.DimX(), vcg::math::Max(resulting_bb.DimY(), resulting_bb.DimZ()) )/2.0f; resulting_bb.Set(center); resulting_bb.Offset(longest_side); TemplatedOctree::boundingBox = resulting_bb; // Try to find a reasonable octree depth int dataset_dimension = int(std::distance(bObj, eObj)); int primitives_per_voxel; int depth = 4; do { int number_of_voxel = 1<<(3*depth); // i.e. 8^depth float density = float(number_of_voxel)/float(depth); primitives_per_voxel = int(float(dataset_dimension)/density); depth++; } while (primitives_per_voxel>25 && depth<15); TemplatedOctree::Initialize(++depth); // Sort the dataset (using the lebesgue space filling curve...) std::string message("Indexing dataset..."); NodePointer *route = new NodePointer[depth+1]; OBJECT_ITERATOR iObj = bObj; //if (callback!=NULL) callback(int((i+1)*100/dataset_dimension), message.c_str()); std::vector< ObjectPlaceholder< NodeType > > placeholders/*(dataset_dimension)*/; vcg::Box3 object_bb; vcg::Point3 hit_leaf; for (int i=0; i() ); placeholders[placeholder_index].z_order = BuildRoute(hit_leaf, route); placeholders[placeholder_index].leaf_pointer = route[depth]; placeholders[placeholder_index].object_index = i; hit_leaf.X() += TemplatedOctree::leafDimension.X(); if (hit_leaf.X()>object_bb.max.X()) { hit_leaf.X() = object_bb.min.X(); hit_leaf.Z()+= TemplatedOctree::leafDimension.Z(); if (hit_leaf.Z()>object_bb.max.Z()) { hit_leaf.Z() = object_bb.min.Z(); hit_leaf.Y()+= TemplatedOctree::leafDimension.Y(); } } } } delete []route; int placeholder_count = int(placeholders.size()); // Allocate the mark array global_mark = 1; marks = new unsigned char[placeholder_count]; memset(&marks[0], 0, sizeof(unsigned char)*placeholder_count); std::sort(placeholders.begin(), placeholders.end(), ObjectSorter< NodeType >()); std::vector< NodePointer > filled_leaves(placeholder_count); sorted_dataset.resize( placeholder_count ); for (int i=0; iSetRange(begin, end); } // The octree is built, the dataset is sorted but only the leaves are indexed: // we propagate the indexing information bottom-up to the root IndexInnerNodes( TemplatedOctree::Root() ); } //end of Set /*! * Finds the closest object to a given point. */ template ObjectPointer GetClosest ( OBJECT_POINT_DISTANCE_FUNCTOR & distance_functor, OBJECT_MARKER & /*marker*/, const CoordType & query_point, const ScalarType & max_distance, ScalarType & distance, CoordType & point, bool allow_zero_distance = true ) { BoundingBoxType query_bb; ScalarType sphere_radius; if (!GuessInitialBoundingBox(query_point, max_distance, sphere_radius, query_bb)) return NULL; std::vector< NodePointer > leaves; //unsigned int object_count; //int leaves_count; IncrementMark(); AdjustBoundingBox(query_bb, sphere_radius, max_distance, leaves, 1); if (sphere_radius>max_distance) return NULL; std::vector< Neighbour > neighbors; RetrieveContainedObjects(query_point, distance_functor, max_distance, allow_zero_distance, leaves, neighbors); typename std::vector< Neighbour >::iterator first = neighbors.begin(); typename std::vector< Neighbour >::iterator last = neighbors.end(); std::partial_sort(first, first+1, last); distance = neighbors[0].distance; point = neighbors[0].point; return neighbors[0].object; }; //end of GetClosest /*! * Retrieve the k closest element to the query point */ template unsigned int GetKClosest ( OBJECT_POINT_DISTANCE_FUNCTOR & distance_functor, OBJECT_MARKER & /*marker*/, unsigned int k, const CoordType & query_point, const ScalarType & max_distance, OBJECT_POINTER_CONTAINER & objects, DISTANCE_CONTAINER & distances, POINT_CONTAINER & points, bool sort_per_distance = true, bool allow_zero_distance = true ) { BoundingBoxType query_bb; ScalarType sphere_radius; if (!GuessInitialBoundingBox(query_point, max_distance, sphere_radius, query_bb)) return 0; std::vector< NodePointer > leaves; std::vector< Neighbour > neighbors; unsigned int object_count; float k_distance; OBJECT_RETRIEVER: IncrementMark(); AdjustBoundingBox(query_bb, sphere_radius, max_distance, leaves, k); object_count = RetrieveContainedObjects(query_point, distance_functor, max_distance, allow_zero_distance, leaves, neighbors); if (sphere_radius(first, first+object_count, last ); else std::nth_element < NeighbourIterator >(first, first+object_count, last ); k_distance = neighbors[object_count-1].distance; if (k_distance>sphere_radius && sphere_radius(neighbors, object_count, objects, distances, points); }; //end of GetKClosest /*! * Returns all the objects contained inside a specified sphere */ template unsigned int GetInSphere ( OBJECT_POINT_DISTANCE_FUNCTOR &distance_functor, OBJECT_MARKER &/*marker*/, const CoordType &sphere_center, const ScalarType &sphere_radius, OBJECT_POINTER_CONTAINER &objects, DISTANCE_CONTAINER &distances, POINT_CONTAINER &points, bool sort_per_distance = false, bool allow_zero_distance = false ) { // Define the minimum bounding-box containing the sphere BoundingBoxType query_bb(sphere_center, sphere_radius); // If that bounding-box don't collide with the octree bounding-box, simply return 0 if (!TemplatedOctree::boundingBox.Collide(query_bb)) return 0; std::vector< NodePointer > leaves; std::vector< Neighbour > neighbors; IncrementMark(); ContainedLeaves(query_bb, leaves, TemplatedOctree::Root(), TemplatedOctree::boundingBox); int leaves_count = int(leaves.size()); if (leaves_count==0) return 0; int object_count = RetrieveContainedObjects(sphere_center, distance_functor, sphere_radius, allow_zero_distance, leaves, neighbors); NeighbourIterator first = neighbors.begin(); NeighbourIterator last = neighbors.end(); if (sort_per_distance) std::partial_sort< NeighbourIterator >(first, first+object_count, last ); else std::nth_element < NeighbourIterator >(first, first+object_count, last ); return CopyQueryResults(neighbors, object_count, objects, distances, points); };//end of GetInSphere /*! * Returns all the objects lying inside the specified bbox */ template unsigned int GetInBox ( OBJECT_MARKER &/*marker*/, const BoundingBoxType &query_bounding_box, OBJECT_POINTER_CONTAINER &objects ) { //if the query bounding-box don't collide with the octree bounding-box, simply return 0 if (!query_bounding_box.Collide()) { objects.clear(); return 0; } //otherwise, retrieve the leaves and fill the container with the objects contained std::vector< NodePointer > leaves; unsigned int object_count; int leaves_count; TemplatedOctree::ContainedLeaves(query_bounding_box, leaves, TemplatedOctree::Root(), TemplatedOctree::boundingBox); leaves_count = int(leaves.size()); if (leaves_count==0) return 0; IncrementMark(); for (int i=0; ibegin; int end = voxel->end; for ( ; beginpObject); } //end of for ( ; begin sorted_dataset; /*! * Markers used to avoid duplication of the same result during a query */ unsigned char *marks; unsigned char global_mark; /*! * The expansion factor used to solve the spatial queries * The current expansion factor is computed on the basis of the last expansion factor * and on the history of these values, through the following heuristic: * current_expansion_factor = alpha*last_expansion_factor + (1.0f-alpha)*mean_expansion_factor * where alpha = 1.0/3.0; */ //float last_expansion_factor; //float mean_expansion_factor; //float ALPHA; //float ONE_MINUS_ALPHA; protected: /*! */ inline void IncrementMark() { // update the marks global_mark = (global_mark+1)%255; if (global_mark == 0) { memset(&marks[0], 0, sizeof(unsigned char)*int(sorted_dataset.size())); global_mark++; } };//end of IncrementMark /* */ inline bool IsMarked(const ObjectReference *ref) const { return *ref->pMark == global_mark; }; /* */ inline void Mark(const ObjectReference *ref) { *ref->pMark = global_mark;}; /*! * Guess an initial bounding-box from which starting the research of the closest point(s). * \return true iff it's possibile to find a sphere, centered in query_point and having radius max_distance at most, which collide the octree bounding-box. */ inline bool GuessInitialBoundingBox(const CoordType &query_point, const ScalarType max_distance, ScalarType &sphere_radius, BoundingBoxType &query_bb) { // costruisco una bounging box centrata in query di dimensione pari a quella di una foglia. // e controllo se in tale bounging box sono contenute un numero di elementi >= a k. // Altrimenti espando il bounding box. query_bb.Set(query_point); // the radius of the sphere centered in query sphere_radius = 0.0f; // if the bounding-box doesn't intersect the bounding-box of the octree, then it must be immediately expanded if (!query_bb.IsIn(query_point)) { do { query_bb.Offset(TemplatedOctree::leafDiagonal); sphere_radius += TemplatedOctree::leafDiagonal; } while ( !TemplatedOctree::boundingBox.Collide(query_bb) || sphere_radius>max_distance); } return (sphere_radius<=max_distance); }; /*! * Modify the bounding-box used during the query until either at least k points * are contained inside the box or the box radius became greater than the threshold distance * Return the number of leaves contained inside the bounding-box */ inline int AdjustBoundingBox ( BoundingBoxType & query_bb, ScalarType & sphere_radius, const ScalarType max_allowed_distance, std::vector< NodePointer > & leaves, const int required_object_count ) { int leaves_count; int object_count; do { leaves.clear(); query_bb.Offset(TemplatedOctree::leafDiagonal); sphere_radius+= TemplatedOctree::leafDiagonal; ContainedLeaves(query_bb, leaves, TemplatedOctree::Root(), TemplatedOctree::boundingBox); leaves_count = int(leaves.size()); object_count = 0; for (int i=0; icount; } while (object_count inline int RetrieveContainedObjects ( const CoordType query_point, OBJECT_POINT_DISTANCE_FUNCTOR & distance_functor, const ScalarType max_allowed_distance, bool allow_zero_distance, std::vector< NodePointer > & leaves, std::vector< Neighbour > & neighbors ) { CoordType closest_point; neighbors.clear(); for (int i=0, leaves_count=int(leaves.size()); ibegin; int end = voxel->end; for ( ; beginpObject, query_point, distance, closest_point)) continue; Mark(ref); if ((distance!=ScalarType(0.0) || allow_zero_distance)) neighbors.push_back( Neighbour(ref->pObject, closest_point, distance) ); } //end of for ( ; begin inline int CopyQueryResults ( std::vector< Neighbour > &neighbors, const unsigned int object_count, OBJECT_POINTER_CONTAINER &objects, DISTANCE_CONTAINER &distances, POINT_CONTAINER &points ) { // copy the nearest object into points.resize( object_count ); distances.resize( object_count ); objects.resize( object_count ); typename POINT_CONTAINER::iterator iPoint = points.begin(); typename DISTANCE_CONTAINER::iterator iDistance = distances.begin(); typename OBJECT_POINTER_CONTAINER::iterator iObject = objects.begin(); for (unsigned int n=0; nAddRange( son_voxel ); } } }; // end of IndexInnerNodes }; #ifdef __glut_h__ /************************************************************************/ /* Rendering */ /************************************************************************/ protected: /*! * Structure which holds the rendering settings */ struct OcreeRenderingSetting { OcreeRenderingSetting() { color = vcg::Color4b(155, 155, 155, 255); isVisible = false; minVisibleDepth = 1; maxVisibleDepth = 4; }; int isVisible; int minVisibleDepth; int maxVisibleDepth; vcg::Color4b color; }; public: /* * Draw the octree in a valid OpenGL context according to the rendering settings */ void DrawOctree(vcg::Box3f &boundingBox, NodePointer n) { char level = TemplatedOctree::Level(n); NodePointer son; if (rendering_settings.minVisibleDepth>level) { for (int s=0; s<8; s++) if ((son=Son(n, s))!=0) DrawOctree(TemplatedOctree::SubBox(boundingBox, s), son); } else { vcg::glBoxWire(boundingBox); if (level #include #include #include //#include #include #include #include #include #include namespace vcg{ template class RayIterator { public: typedef typename Spatial_Idexing::ScalarType ScalarType; typedef typename vcg::Ray3 RayType; typedef typename Spatial_Idexing::Box3x IndexingBoxType; protected: typedef typename Spatial_Idexing::ObjType ObjType; typedef typename vcg::Point3 CoordType; typedef typename Spatial_Idexing::CellIterator CellIterator; ScalarType max_dist; ///control right bonding current cell index (only on initialization) void _ControlLimits() { for (int i=0;i<3;i++) { vcg::Point3i dim=Si.siz; if (CurrentCell.V(i)<0) CurrentCell.V(i) = 0; else if (CurrentCell.V(i)>=dim.V(i)) CurrentCell.V(i)=dim.V(i)-1; } } ///find initial line parameters void _FindLinePar() { /* Punti goal */ ///da verificare se vanno oltre ai limiti vcg::Point3i ip; Si.PToIP(start,ip); Si.IPToP(ip,goal); for (int i=0;i<3;i++) if(r.Direction().V(i)>0.0) goal.V(i)+=Si.voxel.V(i); ScalarType gx=goal.X(); ScalarType gy=goal.Y(); ScalarType gz=goal.Z(); dist=(r.Origin()-goal).Norm(); const float LocalMaxScalar = (std::numeric_limits::max)(); const float EPSILON = 1e-50f; /* Parametri della linea */ ScalarType tx,ty,tz; if( fabs(r.Direction().X())>EPSILON ) tx = (gx-r.Origin().X())/r.Direction().X(); else tx =LocalMaxScalar; if( fabs(r.Direction().Y())>EPSILON ) ty = (gy-r.Origin().Y())/r.Direction().Y(); else ty =LocalMaxScalar; if( fabs(r.Direction().Z())>EPSILON ) tz = (gz-r.Origin().Z())/r.Direction().Z(); else tz =LocalMaxScalar; t=CoordType(tx,ty,tz); } bool _controlEnd() { return (((CurrentCell.X()<0)||(CurrentCell.Y()<0)||(CurrentCell.Z()<0))|| ((CurrentCell.X()>=Si.siz.X())||(CurrentCell.Y()>=Si.siz.Y())||(CurrentCell.Z()>=Si.siz.Z()))); } void _NextCell() { assert(!end); vcg::Box3 bb_current; Si.IPToP(CurrentCell,bb_current.min); Si.IPToP(CurrentCell+vcg::Point3i(1,1,1),bb_current.max); CoordType inters; Intersection_Ray_Box(bb_current,r,inters); ScalarType testmax_dist=(inters-r.Origin()).Norm(); if (testmax_dist>max_dist) end=true; else { if( t.X()(Si.bbox,r,start))){ end=true; return; } Si.PToIP(start,CurrentCell); _ControlLimits(); _FindLinePar(); //go to first intersection while ((!End())&& Refresh()) _NextCell(); } bool End() {return end;} ///refresh current cell intersection , return false if there are ///at lest 1 intersection bool Refresh() { //Elems.clear(); typename Spatial_Idexing::CellIterator first,last,l; ///take first, last iterators to elements in the cell Si.Grid(CurrentCell.X(),CurrentCell.Y(),CurrentCell.Z(),first,last); for(l=first;l!=last;++l) { ObjType* elem=&(*(*l)); ScalarType t; CoordType Int; if((!elem->IsD())&&(!tm.IsMarked(elem))&&(int_funct((**l),r,t))&&(t<=max_dist)) { Int=r.Origin()+r.Direction()*t; Elems.push_back(Entry_Type(elem,t,Int)); tm.Mark(elem); } } ////then control if there are more than 1 element if (Elems.size()>1) std::sort(Elems.begin(),Elems.end()); CurrentElem=Elems.end(); if (Elems.size() > 0) { CurrentElem--; } return((Elems.size()==0)||(Dist()>dist)); } void operator ++() { //if (CurrentElem!=Elems.end()) if (Elems.size()>0) { CurrentElem--; //std::pop_heap(Elems.begin(),Elems.end()); Elems.pop_back(); } /*if (CurrentElem==Elems.end()) {*/ if (Dist()>dist) { if (!End()) { _NextCell(); while ((!End())&&Refresh()) _NextCell(); } } } ObjType &operator *(){return *((*CurrentElem).elem);} CoordType IntPoint() {return ((*CurrentElem).intersection);} ScalarType Dist() { if (Elems.size()>0) return ((*CurrentElem).dist); else return ((ScalarType)FLT_MAX); } //{return ((*CurrentElem).dist);} ///set the current spatial indexing structure used void SetIndexStructure(Spatial_Idexing &_Si) {Si=_Si;} protected: ///structure that mantain for the current cell pre-calculated data typedef struct Entry_Type { public: Entry_Type(ObjType* _elem,ScalarType _dist,CoordType _intersection) { elem=_elem; dist=_dist; intersection=_intersection; } inline bool operator < ( const Entry_Type & l ) const{return (dist > l.dist); } ObjType* elem; ScalarType dist; CoordType intersection; }; RayType r; //ray to find intersections Spatial_Idexing &Si; //reference to spatial index algorithm bool end; //true if the scan is terminated INTFUNCTOR &int_funct; TMARKER tm; std::vector Elems; //element loaded from curren cell typedef typename std::vector::iterator ElemIterator; ElemIterator CurrentElem; //iterator to current element vcg::Point3i CurrentCell; //current cell //used for raterization CoordType start; CoordType goal; ScalarType dist; CoordType t; }; template class ClosestIterator { typedef typename Spatial_Idexing::ObjType ObjType; typedef typename Spatial_Idexing::ScalarType ScalarType; typedef typename vcg::Point3 CoordType; typedef typename Spatial_Idexing::CellIterator CellIterator; ///control the end of scanning bool _EndGrid() { if ((explored.min==vcg::Point3i(0,0,0))&&(explored.max==Si.siz)) end =true; return end; } void _UpdateRadius() { if (radius>=max_dist) end=true; radius+=step_size; //control bounds if (radius>max_dist) radius=max_dist; } ///add cell to the curren set of explored cells bool _NextShell() { //then expand the box explored=to_explore; _UpdateRadius(); Box3 b3d(p,radius); Si.BoxToIBox(b3d,to_explore); Box3i ibox(Point3i(0,0,0),Si.siz-Point3i(1,1,1)); to_explore.Intersect(ibox); if (!to_explore.IsNull()) { assert(!( to_explore.min.X()<0 || to_explore.max.X()>=Si.siz[0] || to_explore.min.Y()<0 || to_explore.max.Y()>=Si.siz[1] || to_explore.min.Z()<0 || to_explore.max.Z()>=Si.siz[2] )); return true; } return false; } public: ///contructor ClosestIterator(Spatial_Idexing &_Si,DISTFUNCTOR _dist_funct):Si(_Si),dist_funct(_dist_funct){} ///set the current spatial indexing structure used void SetIndexStructure(Spatial_Idexing &_Si) {Si=_Si;} void SetMarker(TMARKER _tm) { tm=_tm; } ///initialize the Iterator void Init(CoordType _p,const ScalarType &_max_dist) { explored.SetNull(); to_explore.SetNull(); p=_p; max_dist=_max_dist; Elems.clear(); end=false; tm.UnMarkAll(); //step_size=Si.voxel.X(); step_size=Si.voxel.Norm(); radius=0; ///inflate the bbox until find a valid bbox while ((!_NextShell())&&(!End())); while ((!End())&& Refresh()&&(!_EndGrid())) _NextShell(); /////until don't find an element /////that is inside the radius //while ((!End())&&(Dist()>radius)) //{ // if ((_NextShell())&&(!_EndGrid())) // Refresh(); //} ////set to the last element ..the nearest //CurrentElem=Elems.end(); //CurrentElem--; } //return true if the scan is complete bool End() {return end;} ///refresh Object found also considering current shere radius, //and object comes from previos that are already in the stack //return false if no elements find bool Refresh() { int ix,iy,iz; for( iz = to_explore.min.Z();iz <= to_explore.max.Z(); ++iz) for(iy =to_explore.min.Y(); iy <=to_explore.max.Y(); ++iy) for(ix =to_explore.min.X(); ix <= to_explore.max.X();++ix) { // this test is to avoid to re-process already analyzed cells. if((explored.IsNull())|| (ixexplored.max[0] || iyexplored.max[1] || izexplored.max[2] )) { typename Spatial_Idexing::CellIterator first,last,l; Si.Grid(ix,iy,iz,first,last); for(l=first;l!=last;++l) { ObjType *elem=&(**l); if (!tm.IsMarked(elem)) { CoordType nearest; ScalarType dist=max_dist; if (dist_funct((**l),p,dist,nearest)) Elems.push_back(Entry_Type(elem,fabs(dist),nearest)); tm.Mark(elem); } } } } ////sort the elements in Elems and take a iterator to the last one std::sort(Elems.begin(),Elems.end()); CurrentElem=Elems.rbegin(); return((Elems.size()==0)||(Dist()>radius)); } bool ToUpdate() {return ((Elems.size()==0)||(Dist()>radius));} void operator ++() { if (!Elems.empty()) Elems.pop_back(); CurrentElem = Elems.rbegin(); if ((!End())&& ToUpdate()) while ((!End())&& Refresh()&&(!_EndGrid())) _NextShell(); } ObjType &operator *(){return *((*CurrentElem).elem);} //return distance of the element form the point if no element //are in the vector then return max dinstance ScalarType Dist() { if (Elems.size()>0) return ((*CurrentElem).dist); else return ((ScalarType)FLT_MAX); } CoordType NearestPoint() {return ((*CurrentElem).intersection);} protected: ///structure that mantain for the current cell pre-calculated data typedef struct Entry_Type { public: Entry_Type(ObjType* _elem,ScalarType _dist,CoordType _intersection) { elem=_elem; dist=_dist; intersection=_intersection; } inline bool operator < ( const Entry_Type & l ) const{return (dist > l.dist); } inline bool operator == ( const Entry_Type & l ) const{return (elem == l.elem); } ObjType* elem; ScalarType dist; CoordType intersection; }; CoordType p; //initial point Spatial_Idexing &Si; //reference to spatial index algorithm bool end; //true if the scan is terminated ScalarType max_dist; //max distance when the scan terminate vcg::Box3i explored; //current bounding box explored vcg::Box3i to_explore; //current bounding box explored ScalarType radius; //curret radius for sphere expansion ScalarType step_size; //radius step std::vector Elems; //element loaded from the current sphere DISTFUNCTOR &dist_funct; TMARKER tm; typedef typename std::vector::reverse_iterator ElemIterator; ElemIterator CurrentElem; //iterator to current element }; } #endif qutemol/vcg/vcg/space/index/grid_closest.h0000444000175000017500000002536010616656224017232 0ustar mbamba/**************************************************************************** * VCGLib o o * * Visual and Computer Graphics Library o o * * _ O _ * * Copyright(C) 2005 \/)\/ * * Visual Computing Lab /\/| * * ISTI - Italian National Research Council | * * \ * * All rights reserved. * * * * 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. * * * * 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 (http://www.gnu.org/licenses/gpl.txt) * * for more details. * * * ****************************************************************************/ /**************************************************************************** History $Log: grid_closest.h,v $ Revision 1.17 2007/05/04 16:17:24 ganovelli added cast to avoid warning Revision 1.16 2006/10/02 09:34:03 cignoni Re-added diff 1.12 by Pietroni (cancelled by previous rollback): in GridDoRay function the RayIterator must be initialized with maximum distance Revision 1.15 2006/10/02 09:28:45 cignoni Reverted to version 1.10 to nullify dangerous marfr960's changes Revision 1.10 2006/05/17 12:48:52 pietroni corrected bug in GridGetInBox function Revision 1.9 2006/01/27 09:58:47 corsini fix signed/unsigned mismatch Revision 1.8 2005/12/06 18:00:39 pietroni added deleted objects control for GridClosest() function call Revision 1.7 2005/12/02 00:30:27 cignoni Corrected typename usage and removed excess ';' from end of template functions, for gcc compiling Revision 1.6 2005/10/03 13:57:32 pietroni added GridGetInSphere and GridGetInBox functions Revision 1.5 2005/10/02 23:18:06 cignoni Small bug in the computation of the intersection between the todo box and the grid bbox that failed for extrema points. Revision 1.4 2005/09/30 15:12:16 cignoni Completely rewrote the GridClosest, now it: - works for point out of the grid - expands the box in a distance coherent way - does not re-visit already visited cells - shorter code!! ( still to be tested :) ) Revision 1.3 2005/09/30 13:15:48 pietroni added functions: - GetKClosest - DoRay Revision 1.2 2005/09/28 08:27:11 cignoni Added a control to avoid multiple check of the same cells during radial expansion Still miss some code to properly initialize when point is out of the BBox of the grid. Revision 1.1 2005/09/27 15:09:38 cignoni First Version ****************************************************************************/ ///** Returns the closest posistion of a point _p and its distance //@param _p a 3d point //@param _maxDist maximum distance not to search beyond. //@param _getPointDistance (templated type) a functor object used to calculate distance from a grid object to the point _p. //@param _minDist the returned closest distance //@param _closestPt the returned closest point //@return The closest element //*/ ///* // A DISTFUNCT object must implement an operator () with signature: // bool operator () (const ObjType& obj, const CoordType & _p, ScalarType & min_dist, CoordType & _closestPt); //*/ #ifndef __VCGLIB_GRID_CLOSEST #define __VCGLIB_GRID_CLOSEST #include namespace vcg{ template typename SPATIAL_INDEX::ObjPtr GridClosest(SPATIAL_INDEX &Si, OBJPOINTDISTFUNCTOR _getPointDistance, OBJMARKER & _marker, const typename SPATIAL_INDEX::CoordType & _p, const typename SPATIAL_INDEX::ScalarType & _maxDist, typename SPATIAL_INDEX::ScalarType & _minDist, typename SPATIAL_INDEX:: CoordType &_closestPt) { typedef typename SPATIAL_INDEX::ObjPtr ObjPtr; typedef SPATIAL_INDEX SpatialIndex; typedef typename SPATIAL_INDEX::CoordType CoordType; typedef typename SPATIAL_INDEX::ScalarType ScalarType; typedef typename SPATIAL_INDEX::Box3x Box3x; // Initialize min_dist with _maxDist to exploit early rejection test. _minDist = _maxDist; ObjPtr winner=NULL; _marker.UnMarkAll(); ScalarType newradius = Si.voxel.Norm(); ScalarType radius; Box3i iboxdone,iboxtodo; CoordType t_res; typename SPATIAL_INDEX::CellIterator first,last,l; if(Si.bbox.IsInEx(_p)) { Point3i _ip; Si.PToIP(_p,_ip); Si.Grid( _ip[0],_ip[1],_ip[2], first, last ); for(l=first;l!=last;++l) { ObjPtr elem=&(**l); if (!elem->IsD()) { if (_getPointDistance((**l), _p,_minDist, t_res)) // <-- NEW: use of distance functor { winner=elem; _closestPt=t_res; newradius=_minDist; // } _marker.Mark(elem); } } iboxdone=Box3i(_ip,_ip); } int ix,iy,iz; Box3i ibox(Point3i(0,0,0),Si.siz-Point3i(1,1,1)); do { radius=newradius; Box3x boxtodo=Box3x(_p,radius); //boxtodo.Intersect(Si.bbox); Si.BoxToIBox(boxtodo, iboxtodo); iboxtodo.Intersect(ibox); if(!boxtodo.IsNull()) { for (ix=iboxtodo.min[0]; ix<=iboxtodo.max[0]; ix++) for (iy=iboxtodo.min[1]; iy<=iboxtodo.max[1]; iy++) for (iz=iboxtodo.min[2]; iz<=iboxtodo.max[2]; iz++) if(ixiboxdone.max[0] || // this test is to avoid to re-process already analyzed cells. iyiboxdone.max[1] || iziboxdone.max[2] ) { Si.Grid( ix, iy, iz, first, last ); for(l=first;l!=last;++l) if (!(**l).IsD()) { ObjPtr elem=&(**l); if (!elem->IsD()) { if( ! _marker.IsMarked(elem)) { if (_getPointDistance((**l), _p, _minDist, t_res)) { winner=elem; _closestPt=t_res; }; _marker.Mark(elem); } } } } } if(!winner) newradius=radius+Si.voxel.Norm(); else newradius = _minDist; } while (_minDist>radius); return winner; } template unsigned int GridGetKClosest(SPATIALINDEXING &_Si, OBJPOINTDISTFUNCTOR & _getPointDistance, OBJMARKER & _marker, const unsigned int _k, const typename SPATIALINDEXING::CoordType & _p, const typename SPATIALINDEXING::ScalarType & _maxDist, OBJPTRCONTAINER & _objectPtrs, DISTCONTAINER & _distances, POINTCONTAINER & _points) { typedef vcg::ClosestIterator ClosestIteratorType; ClosestIteratorType Cli=ClosestIteratorType(_Si,_getPointDistance); Cli.SetMarker(_marker); Cli.Init(_p,_maxDist); unsigned int i=0; _objectPtrs.clear(); _distances.clear(); _points.clear(); while ((!Cli.End())&&(i<_k)) { _objectPtrs.push_back(&(*Cli)); _distances.push_back(Cli.Dist()); _points.push_back(Cli.NearestPoint()); ++Cli; i++; } return (i); } template typename SPATIALINDEXING::ObjPtr GridDoRay(SPATIALINDEXING &_Si, OBJRAYISECTFUNCTOR &_rayIntersector, OBJMARKER &_marker, const Ray3 & _ray, const typename SPATIALINDEXING::ScalarType & _maxDist, typename SPATIALINDEXING::ScalarType & _t) { typedef vcg::RayIterator RayIteratorType; RayIteratorType RayIte=RayIteratorType(_Si,_rayIntersector,_maxDist); RayIte.SetMarker(_marker); RayIte.Init(_ray); if (!RayIte.End()) { _t=RayIte.Dist(); return(&(*RayIte)); } return 0; } template unsigned int GridGetInSphere(SPATIALINDEXING &_Si, OBJPOINTDISTFUNCTOR & _getPointDistance, OBJMARKER & _marker, const typename SPATIALINDEXING::CoordType & _p, const typename SPATIALINDEXING::ScalarType & _r, OBJPTRCONTAINER & _objectPtrs, DISTCONTAINER & _distances, POINTCONTAINER & _points) { typedef vcg::ClosestIterator ClosestIteratorType; ClosestIteratorType Cli=ClosestIteratorType(_Si,_getPointDistance); Cli.SetMarker(_marker); Cli.Init(_p,_r); _objectPtrs.clear(); _distances.clear(); _points.clear(); while (!Cli.End()) { _objectPtrs.push_back(&(*Cli)); _distances.push_back(Cli.Dist()); _points.push_back(Cli.NearestPoint()); ++Cli; } return ((int)_objectPtrs.size()); } template unsigned int GridGetInBox(SPATIALINDEXING &_Si, OBJMARKER & _marker, const vcg::Box3 _bbox, OBJPTRCONTAINER & _objectPtrs) { typename SPATIALINDEXING::CellIterator first,last,l; _objectPtrs.clear(); vcg::Box3i ibbox; Box3i Si_ibox(Point3i(0,0,0),_Si.siz-Point3i(1,1,1)); _Si.BoxToIBox(_bbox, ibbox); ibbox.Intersect(Si_ibox); _marker.UnMarkAll(); if (ibbox.IsNull()) return 0; else { int ix,iy,iz; for (ix=ibbox.min[0]; ix<=ibbox.max[0]; ix++) for (iy=ibbox.min[1]; iy<=ibbox.max[1]; iy++) for (iz=ibbox.min[2]; iz<=ibbox.max[2]; iz++) { _Si.Grid( ix, iy, iz, first, last ); for(l=first;l!=last;++l) if (!(**l).IsD()) { typename SPATIALINDEXING::ObjPtr elem=&(**l); vcg::Box3 box_elem; elem->GetBBox(box_elem); if(( ! _marker.IsMarked(elem))&&(box_elem.Collide(_bbox))){ _objectPtrs.push_back(elem); _marker.Mark(elem); } } } return (static_cast(_objectPtrs.size())); } } }//end namespace vcg #endif qutemol/vcg/vcg/space/ray3.h0000444000175000017500000001651410323244006014303 0ustar mbamba/**************************************************************************** * VCGLib o o * * Visual and Computer Graphics Library o o * * _ O _ * * Copyright(C) 2004 \/)\/ * * Visual Computing Lab /\/| * * ISTI - Italian National Research Council | * * \ * * All rights reserved. * * * * 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. * * * * 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 (http://www.gnu.org/licenses/gpl.txt) * * for more details. * * * ****************************************************************************/ /**************************************************************************** History $Log: ray3.h,v $ Revision 1.5 2005/10/12 17:29:42 ponchio RayType ->Ray3 in a couple of location (not really sure is correct though...) Revision 1.4 2004/03/11 11:47:20 tarini minor updates, corrections, added documentations, etc. Revision 1.3 2004/03/10 15:27:18 tarini first version ****************************************************************************/ #ifndef __VCGLIB_RAY3 #define __VCGLIB_RAY3 #include namespace vcg { /** \addtogroup space */ /*@{*/ /** Templated class for 3D rays. This is the class for infinite rays in 3D space. A Ray is stored just as two Point3: an origin and a direction (not necessarily normalized). @param RayScalarType (template parameter) Specifies the type of scalar used to represent coords. @param NORM: if on, the direction is always Normalized */ template class Ray3 { public: /// The scalar type typedef RayScalarType ScalarType; /// The point type typedef Point3 PointType; /// The ray type typedef Ray3 RayType; private: /// Origin PointType _ori; /// Direction (not necessarily normalized, unless so specified by NORM) PointType _dir; public: //@{ /** @name Members to access the origin or direction Direction() cannot be assigned directly. Use SetDirection() or Set() instead. **/ /// inline const PointType &Origin() const { return _ori; } inline PointType &Origin() { return _ori; } inline const PointType &Direction() const { return _dir; } /// sets the origin inline void SetOrigin( const PointType & ori ) { _ori=ori; } /// sets the direction inline void SetDirection( const PointType & dir) { _dir=dir; if (NORM) _dir.Normalize(); } /// sets origin and direction. inline void Set( const PointType & ori, const PointType & dir ) { SetOrigin(ori); SetDirection(dir); } //@} //@{ /** @name Constructors **/ /// The empty constructor Ray3() {}; /// The (origin, direction) constructor Ray3(const PointType &ori, const PointType &dir) {SetOrigin(ori); SetDirection(dir);}; //@} /// Operator to compare two rays inline bool operator == ( RayType const & p ) const { return _ori==p._ori && _dir==p._dir; } /// Operator to dispare two rays inline bool operator != ( RayType const & p ) const { return _ori!=p._ori || _dir!=p._dir; } /// Projects a point on the ray inline ScalarType Projection( const PointType &p ) const { if (NORM) return ScalarType((p-_ori)*_dir); else return ScalarType((p-_ori)*_dir/_dir.SquaredNorm()); } /// returns wheter this type is normalized or not static bool IsNormalized() {return NORM;}; /// calculates the point of parameter t on the ray. inline PointType P( const ScalarType t ) const { return _ori + _dir * t; } /// normalizes direction field (returns a Normalized Ray) inline Ray3 &Normalize() { if (!NORM) _dir.Normalize(); return *((Ray3*)this);} /// normalizes direction field (returns a Normalized Ray) - static version static Ray3 &Normalize(RayType &p) { p.Normalize(); return *((Ray3*)(&p));} /// importer for different ray types (with any scalar type or normalization beaviour) template inline void Import( const Ray3 & b ) { _ori.Import( b.Origin() ); _dir.Import( b.Direction() ); if ((NORM) && (!K)) _dir.Normalize(); //printf("(=)%c->%c ",(!NORM)?'N':'n', NORM?'N':'n'); } /// constructs a new ray importing it from an existing one template static RayType Construct( const Ray3 & b ) { RayType res; res.Import(b); return res; } PointType ClosestPoint(const PointType & p) const{ return P(Projection(p)); } /// flips the ray inline void Flip(){ _dir=-_dir; }; //@{ /** @name Linearity for 3d rays (operators +, -, *, /) so a ray can be set as a linear combination of several rays. Note that the result of any operation returns a non-normalized ray; however, the command r0 = r1*a + r2*b is licit even if r0,r1,r2 are normalized rays, as the normalization will take place within the final assignement operation. **/ inline Ray3 operator + ( RayType const & p) const {return Ray3 ( _ori+p.Origin(), _dir+p.Direction() );} inline Ray3 operator - ( RayType const & p) const {return Ray3 ( _ori-p.Origin(), _dir-p.Direction() );} inline Ray3 operator * ( const ScalarType s ) const {return Ray3 ( _ori*s, _dir*s );} inline Ray3 operator / ( const ScalarType s ) const {ScalarType s0=((ScalarType)1.0)/s; return RayType( _ori*s0, _dir*s0 );} //@} //@{ /** @name Automatic normalized to non-normalized "Ray3dN r0 = r1" is equivalent to "Ray3dN r0 = r1.Normalize()" if r1 is a Ray3d **/ /// copy constructor that takes opposite beaviour Ray3(const Ray3 &r) { Import(r); }; /// assignment inline RayType & operator = ( Ray3 const &r) { Import(r); return *this; }; //@} }; // end class definition typedef Ray3 Ray3s; typedef Ray3 Ray3i; typedef Ray3 Ray3f; typedef Ray3 Ray3d; typedef Ray3 Ray3sN; typedef Ray3 Ray3iN; typedef Ray3 Ray3fN; typedef Ray3 Ray3dN; /// returns closest point template Point3 ClosestPoint( Ray3 r, const Point3 & p) { ScalarType t = r.Projection(p); if (t<0) return r.Origin(); return r.P(t); } /*@}*/ } // end namespace #endif qutemol/vcg/vcg/space/ray2.h0000444000175000017500000001617210556001656014314 0ustar mbamba/**************************************************************************** * VCGLib o o * * Visual and Computer Graphics Library o o * * _ O _ * * Copyright(C) 2004 \/)\/ * * Visual Computing Lab /\/| * * ISTI - Italian National Research Council | * * \ * * All rights reserved. * * * * 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. * * * * 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 (http://www.gnu.org/licenses/gpl.txt) * * for more details. * * * ****************************************************************************/ /**************************************************************************** History $Log: ray2.h,v $ Revision 1.1 2007/01/25 01:11:10 pietroni first working version ****************************************************************************/ #ifndef __VCGLIB_RAY2 #define __VCGLIB_RAY2 #include namespace vcg { /** \addtogroup space */ /*@{*/ /** Templated class for 3D rays. This is the class for infinite rays in 3D space. A Ray is stored just as two Point3: an origin and a direction (not necessarily normalized). @param RayScalarType (template parameter) Specifies the type of scalar used to represent coords. @param NORM: if on, the direction is always Normalized */ template class Ray2 { public: /// The scalar type typedef RayScalarType ScalarType; /// The point type typedef Point2 PointType; /// The ray type typedef Ray2 RayType; private: /// Origin PointType _ori; /// Direction (not necessarily normalized, unless so specified by NORM) PointType _dir; public: //@{ /** @name Members to access the origin or direction Direction() cannot be assigned directly. Use SetDirection() or Set() instead. **/ /// inline const PointType &Origin() const { return _ori; } inline PointType &Origin() { return _ori; } inline const PointType &Direction() const { return _dir; } /// sets the origin inline void SetOrigin( const PointType & ori ) { _ori=ori; } /// sets the direction inline void SetDirection( const PointType & dir) { _dir=dir; if (NORM) _dir.Normalize(); } /// sets origin and direction. inline void Set( const PointType & ori, const PointType & dir ) { SetOrigin(ori); SetDirection(dir); } //@} //@{ /** @name Constructors **/ /// The empty constructor Ray2() {}; /// The (origin, direction) constructor Ray2(const PointType &ori, const PointType &dir) {SetOrigin(ori); SetDirection(dir);}; //@} /// Operator to compare two rays inline bool operator == ( RayType const & p ) const { return _ori==p._ori && _dir==p._dir; } /// Operator to dispare two rays inline bool operator != ( RayType const & p ) const { return _ori!=p._ori || _dir!=p._dir; } /// Projects a point on the ray inline ScalarType Projection( const PointType &p ) const { if (NORM) return ScalarType((p-_ori)*_dir); else return ScalarType((p-_ori)*_dir/_dir.SquaredNorm()); } /// returns wheter this type is normalized or not static bool IsNormalized() {return NORM;}; /// calculates the point of parameter t on the ray. inline PointType P( const ScalarType t ) const { return _ori + _dir * t; } /// normalizes direction field (returns a Normalized Ray) inline Ray2 &Normalize() { if (!NORM) _dir.Normalize(); return *((Ray2*)this);} /// normalizes direction field (returns a Normalized Ray) - static version static Ray2 &Normalize(RayType &p) { p.Normalize(); return *((Ray2*)(&p));} /// importer for different ray types (with any scalar type or normalization beaviour) template inline void Import( const Ray2 & b ) { _ori.Import( b.Origin() ); _dir.Import( b.Direction() ); if ((NORM) && (!K)) _dir.Normalize(); //printf("(=)%c->%c ",(!NORM)?'N':'n', NORM?'N':'n'); } /// constructs a new ray importing it from an existing one template static RayType Construct( const Ray2 & b ) { RayType res; res.Import(b); return res; } PointType ClosestPoint(const PointType & p) const{ return P(Projection(p)); } /// flips the ray inline void Flip(){ _dir=-_dir; }; //@{ /** @name Linearity for 3d rays (operators +, -, *, /) so a ray can be set as a linear combination of several rays. Note that the result of any operation returns a non-normalized ray; however, the command r0 = r1*a + r2*b is licit even if r0,r1,r2 are normalized rays, as the normalization will take place within the final assignement operation. **/ inline Ray2 operator + ( RayType const & p) const {return Ray2 ( _ori+p.Origin(), _dir+p.Direction() );} inline Ray2 operator - ( RayType const & p) const {return Ray2 ( _ori-p.Origin(), _dir-p.Direction() );} inline Ray2 operator * ( const ScalarType s ) const {return Ray2 ( _ori*s, _dir*s );} inline Ray2 operator / ( const ScalarType s ) const {ScalarType s0=((ScalarType)1.0)/s; return RayType( _ori*s0, _dir*s0 );} //@} //@{ /** @name Automatic normalized to non-normalized "Ray2dN r0 = r1" is equivalent to "Ray2dN r0 = r1.Normalize()" if r1 is a Ray2d **/ /// copy constructor that takes opposite beaviour Ray2(const Ray2 &r) { Import(r); }; /// assignment inline RayType & operator = ( Ray2 const &r) { Import(r); return *this; }; //@} }; // end class definition typedef Ray2 Ray2s; typedef Ray2 Ray2i; typedef Ray2 Ray2f; typedef Ray2 Ray2d; typedef Ray2 Ray2sN; typedef Ray2 Ray2iN; typedef Ray2 Ray2fN; typedef Ray2 Ray2dN; /// returns closest point template Point3 ClosestPoint( Ray2 r, const Point3 & p) { ScalarType t = r.Projection(p); if (t<0) return r.Origin(); return r.P(t); } /*@}*/ } // end namespace #endif qutemol/vcg/vcg/space/colorspace.h0000444000175000017500000013651410527075120015567 0ustar mbamba/**************************************************************************** * VCGLib o o * * Visual and Computer Graphics Library o o * * _ O _ * * Copyright(C) 2006 \/)\/ * * Visual Computing Lab /\/| * * ISTI - Italian National Research Council | * * \ * * All rights reserved. * * * * 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. * * * * 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 (http://www.gnu.org/licenses/gpl.txt) * * for more details. * * * ****************************************************************************/ #ifndef __VCGLIB_COLORSPACE #define __VCGLIB_COLORSPACE #include /** * EVERYTHING YOU ALWAYS WANTED TO KNOW ABOUT COLORS BUT WERE AFRAID TO ASK *************************************************************************** UNDERSTANDING ILLUMINANTS ------------------------- ILLUMINANT A - INCANDESCENT The CIE standard illuminant A was first recommended in 1931 to represent incandescent light sources with an approximate color temperature of 2856 degrees Kelvin. ILLUMINANT C - SUNLIGHT CIE standard illuminant C was recommended in 1931 to represent average daylight with a color temperature of 6774 degrees Kelvin. ILLUMINANT D50 - DAYLIGHT AT 5000K - (DAYLIGHT - RED SHADE) CIE standard illuminant D50 is correlated color temperature D illuminant which is calculated from the standard illuminant D65. This standard illuminant represents Daylight at 5000 degrees Kelvin and is the ANSI standard illuminant used in the graphic arts industry. ILLUMINANT D65 - DAYLIGHT AT 6500K (DAYLIGHT - NEUTRAL) The CIE standard illuminant D65 represents daylight at approximately 6500 degrees Kelvin. This standard and the method for calculating different correlating color temperatures was introduced in 1964. ILLUMINANT D75 - DAYLIGHT - BLUE SHADE ... ILLUMINANT F2 - COOL WHITE (COOL WHITE FLUORESCENT) The CIE standard illuminant F2 represents the typical cool white fluorescent source. The spikes which protrude above the continuous graph in the fluorescent illuminants represent the power measurements at the principle mercury emission lines. ILLUMINANT F7 - BROAD BAND DAYLIGHT (BROAD BAND WHITE FLUORESCENT) The CIE standard Illuminant F7 represents a broad band daylight fluorescent source. Examples of this type of source are the GE and Philips Daylight fluorescent sources. ILLUMINANT F11 - NARROW BAND WHITE (TL84 FLUORESCENT) The CIE standard illuminant F11 represents a narrow band white fluorescent source. Sources similar to this illuminant are the Philips F40AX41 and TL841, as well as the GE SPX41. ILLUMINANT F12 - ULTRALUME 3000 FLUORESCENT ... References ---------- * Danny Pascale, "RGB coordinates of the Macbeth ColorChecker". * X-Rite Incorporated, "Understanding Illuminants", Whitepaper, http://www.xrite.com/documents/apps/public/whitepapers/Ca00002a.pdf * http://www.brucelindbloom.com - a web site with a huge amount of information about color theory. */ namespace vcg { /** \addtogroup space */ /*@{*/ /** This (empty) class is used to convert colors between different color space. \note All computations are in double precision independently of color data type. \note All color components are assumed in the range [0.0, 1.0]. */ template class ColorSpace { // definitions public: enum ConeResponse { BRADFORD = 0, VON_KRIES = 1, XYZ_SCALING = 2}; enum Illuminant { ILLUMINANT_A = 0, ILLUMINANT_B = 1, ILLUMINANT_C = 2, ILLUMINANT_D50 = 3, ILLUMINANT_D55 = 4, ILLUMINANT_D65 = 5, ILLUMINANT_D75 = 6, ILLUMINANT_E = 7, ILLUMINANT_INVALID = 8 }; enum RGBSpaces { ADOBE_RGB = 0, APPLE_RGB = 1, BEST_RGB = 2, BETA_RGB = 3, BRUCE_RGB = 4, CIE_RGB = 5, COLOR_MATCH = 6, DON_RGB4 = 7, ECI_RGB = 8, EKTA_SPACE = 9, NTSC_RGB = 10, PAL_RGB = 11, PROPHOTO = 12, SMPTE_C = 13, SRGB = 14, WIDE_GAMUT = 15 }; // private methods private: static double CIE_EPSILON() { return 0.008856; // Intent of the CIE Standard --> 216/24389 } static double CIE_KI() { return 903.3; // Intent of the CIE Standard --> 24389/27 } static double RGB2XYZ(int index) { // RGB WORKING SPACE DATA (RGB TO XYZ CONVERSION MATRIX) // // 144 elements (16 RGB spaces x matrices of 3 x 3) // static double RGB_TO_XYZ[]= { // Adobe RGB (1998) (ref. D65) 0.576700, 0.297361, 0.0270328, 0.185556, 0.627355, 0.0706879, 0.188212, 0.0752847, 0.991248, // Apple RGB (ref. D65) 0.449695, 0.244634, 0.0251829, 0.316251, 0.672034, 0.141184, 0.18452, 0.0833318, 0.922602, // BestRGB (ref. D50) 0.632670, 0.228457, 0.000000, 0.204556, 0.737352, 0.00951424, 0.126995, 0.0341908, 0.815696, // Beta RGB (ref. D50) 0.671254, 0.303273, 0.000000, 0.174583, 0.663786, 0.040701, 0.118383, 0.0329413, 0.784509, // BruceRGB (ref. D65) 0.467384, 0.240995, 0.0219086, 0.294454, 0.683554, 0.0736135, 0.188629, 0.0754517, 0.993447, // CIE (ref. E) 0.488718, 0.176204, 0.000000, 0.310680, 0.812985, 0.0102048, 0.200602, 0.0108109, 0.989795, // ColorMatch (ref. D50) 0.509344, 0.274884, 0.0242545, 0.320907, 0.658132, 0.108782, 0.133969, 0.0669845, 0.692174, // DonRGB4 (ref. D50) 0.645771, 0.278350, 0.00371134, 0.193351, 0.687970, 0.0179862, 0.125098, 0.0336802, 0.803513, // ECI (ref. D50) 0.650204, 0.320250, 0.000000, 0.178077, 0.602071, 0.0678390, 0.135938, 0.0776791, 0.757371, // Ekta Space PS5 (ref. D50) 0.593891, 0.260629, 0.000000, 0.272980, 0.734946, 0.0419970, 0.0973486, 0.00442493, 0.783213, // NTSC (ref. C) 0.606734, 0.298839, 0.000000, 0.173564, 0.586811, 0.0661196, 0.200112, 0.114350, 1.11491, // PAL / SECAM (ref. D65) 0.430587, 0.222021, 0.0201837, 0.341545, 0.706645, 0.129551, 0.178336, 0.0713342, 0.939234, // ProPhoto (ref. D50) 0.797675, 0.288040, 0.000000, 0.135192, 0.711874, 0.000000, 0.0313534, 0.000086, 0.825210, // SMPTE-C (ref. D65) 0.393555, 0.212395, 0.0187407, 0.365253, 0.701049, 0.111932, 0.191659, 0.0865558, 0.958297, // sRGB (ref. D65) 0.412424, 0.212656, 0.0193324, 0.357579, 0.715158, 0.119193, 0.180464, 0.0721856, 0.950444, // WideGamut (ref. D50) 0.716105, 0.258187, 0.000000, 0.100930, 0.724938, 0.0517813, 0.147186, 0.0168748, 0.773429 }; return RGB_TO_XYZ[index]; } static double XYZ2RGB(int index) { // RGB WORKING SPACE DATA (XYZ TO RGB CONVERSION MATRIX) // // 144 elements (16 RGB spaces x matrices of 3 x 3) // static double XYZ_TO_RGB[]= { // Adobe RGB (1998) (ref. D65) 2.04148, -0.969258, 0.0134455, -0.564977, 1.87599, -0.118373, -0.344713, 0.0415557, 1.01527, // Apple RGB (ref. D65) 2.95176, -1.0851, 0.0854804, -1.28951, 1.99084, -0.269456, -0.47388, 0.0372023, 1.09113, // BestRGB (ref. D50) 1.75526, -0.544134, 0.00634681, -0.483679, 1.50688, -0.0175762, -0.253000, 0.0215528, 1.22570, // Beta RGB (ref. D50) 1.68323, -0.771023, 0.0400012, -0.428236, 1.70656, -0.0885376, -0.236018, 0.0446899, 1.27236, // BruceRGB (ref. D65) 2.74566, -0.969257, 0.0112707, -1.13589, 1.87599, -0.113959, -0.435057, 0.0415557, 1.01311, // CIE (ref. E) 2.37067, -0.513885, 0.00529818, -0.900040, 1.42530, -0.0146949, -0.470634, 0.0885814, 1.00940, // ColorMatch (ref. D50) 2.64229, -1.11198, 0.0821698, -1.22343, 2.05902, -0.280725, -0.393014, 0.0159614, 1.45599, // DonRGB4 (ref. D50) 1.76039, -0.712629, 0.00782072, -0.488120, 1.65274, -0.0347411, -0.253613, 0.0416715, 1.24477, // ECI (ref. D50) 1.78276, -0.959362, 0.0859318, -0.496985, 1.94780, -0.174467, -0.269010, -0.0275807, 1.32283, // Ekta Space PS5 (ref. D50) 2.00438, -0.711029, 0.0381263, -0.730484, 1.62021, -0.0868780, -0.245005, 0.0792227, 1.27254, // NTSC (ref. C) 1.91049, -0.984310, 0.0583744, -0.532592, 1.99845, -0.118518, -0.288284, -0.0282980, 0.898611, // PAL / SECAM (ref. D65) 3.06313, -0.969258, 0.0678674, -1.39328, 1.87599, -0.228821, -0.475788, 0.0415557, 1.06919, // ProPhoto (ref. D50) 1.34594, -0.544599, 0.000000, -0.255608, 1.50817, 0.000000, -0.0511118, 0.0205351, 1.21181, // SMPTE-C (ref. D65) 3.50570, -1.06906, 0.0563117, -1.73964, 1.97781, -0.196994, -0.544011, 0.0351720, 1.05005, // sRGB (ref. D65) 3.24071, -0.969258, 0.0556352, -1.53726, 1.87599, -0.203996, -0.498571, 0.0415557, 1.05707, // WideGamut (ref. D50) 1.46281, -0.521793, 0.0349342, -0.184062, 1.44724, -0.0968931, -0.274361, 0.0677228, 1.28841 }; return XYZ_TO_RGB[index]; } static double CA(int index) { // CHROMATIC ADAPTATION MATRIX // // 196 (8 x 8 illuminants x 3 cone response) matrices of 3 x 3 elements // static double CAmatrix[]= { // A -> A 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, // A -> B (Bradford) 0.890600, -0.097037, 0.054012, -0.082873, 1.075262, -0.091063, 0.268563, 0.088084, 2.486772, // A -> B (Von Kries) 0.957515, -0.018042, 0.000000, -0.164247, 1.018522, 0.000000, 0.290746, 0.003635, 2.397466, // A -> B (XYZ scaling) 0.902065, 0.000000, 0.000000, 0.000000, 1.000000, 0.000000, 0.000000, 0.000000, 2.397474, // A -> C (Bradford) 0.853036, -0.123884, 0.091195, -0.113032, 1.085373, -0.155374, 0.440458, 0.142587, 3.477780, // A -> C (Von Kries) 0.941839, -0.024699, 0.000000, -0.224854, 1.025358, 0.000000, 0.480676, 0.004974, 3.322435, // A -> C (XYZ scaling) 0.892678, 0.000000, 0.000000, 0.000000, 1.000000, 0.000000, 0.000000, 0.000000, 3.322447, // A -> D50 (Bradford) 0.878034, -0.111621, 0.050313, -0.091487, 1.092265, -0.083964, 0.257070, 0.085312, 2.402220, // A -> D50 (Von Kries) 0.953214, -0.019868, 0.000000, -0.180875, 1.020397, 0.000000, 0.276267, 0.004004, 2.321454, // A -> D50 (XYZ scaling) 0.877936, 0.000000, 0.000000, 0.000000, 1.000000, 0.000000, 0.000000, 0.000000, 2.321462, // A -> D55 (Bradford) 0.864256, -0.122489, 0.061011, -0.102279, 1.098455, -0.102340, 0.307550, 0.101476, 2.689914, // A -> D55 (Von Kries) 0.947636, -0.022237, 0.000000, -0.202440, 1.022829, 0.000000, 0.331718, 0.004481, 2.590505, // A -> D55 (XYZ Scaling) 0.870670, 0.000000, 0.000000, 0.000000, 1.000000, 0.000000, 0.000000, 0.000000, 2.590514, // A -> D65 (Bradford) 0.844763, -0.136524, 0.080011, -0.117903, 1.103952, -0.135190, 0.395490, 0.129376, 3.196569, // A -> D65 (Von Kries) 0.939518, -0.025685, 0.000000, -0.233826, 1.026369, 0.000000, 0.428852, 0.005174, 3.063452, // A -> D65 (XYZ Scaling) 0.865414, 0.000000, 0.000000, 0.000000, 1.000000, 0.000000, 0.000000, 0.000000, 3.063462, // A -> D75 (Bradford) 0.830991, -0.145710, 0.095536, -0.129133, 1.106062, -0.162123, 0.466601, 0.151821, 3.608682, // A -> D75 (Von Kries) 0.933660, -0.028172, 0.000000, -0.256474, 1.028923, 0.000000, 0.507632, 0.005674, 3.447762, // A -> D75 (XYZ Scaling) 0.864434, 0.000000, 0.000000, 0.000000, 1.000000, 0.000000, 0.000000, 0.000000, 3.447773, // A -> E (Bradford) 0.881682, -0.100560, 0.071051, -0.090783, 1.070733, -0.120888, 0.344476, 0.111711, 2.933736, // A -> E (Von Kries) 0.953314, -0.019826, 0.000000, -0.180491, 1.020355, 0.000000, 0.375531, 0.003993, 2.813168, // A -> E (XYZ Scaling) 0.910515, 0.000000, 0.000000, 0.000000, 1.000000, 0.000000, 0.000000, 0.000000, 2.813177, // B -> A (Bradford) 1.138867, 0.104490, -0.020910, 0.077128, 0.934300, 0.032538, -0.125725, -0.044379, 0.403234, // B -> A (Von Kries) 1.047555, 0.018556, 0.000000, 0.168937, 0.984806, 0.000000, -0.127296, -0.003743, 0.417104, // B -> A (XYZ Scaling) 1.108567, 0.000000, 0.000000, 0.000000, 1.000000, 0.000000, 0.000000, 0.000000, 0.417106, // B -> B 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, // B -> C (Bradford) 0.950475, -0.030658, 0.014905, -0.025481, 1.009149, -0.024973, 0.075375, 0.024904, 1.397787, // B -> C (Von Kries) 0.982455, -0.006847, 0.000000, -0.062331, 1.005606, 0.000000, 0.081442, 0.001380, 1.385807, // B -> C (XYZ Scaling) 0.989593, 0.000000, 0.000000, 0.000000, 1.000000, 0.000000, 0.000000, 0.000000, 1.385811, // B -> D50 (Bradford) 0.985029, -0.014775, -0.001704, -0.009391, 1.014671, 0.003596, -0.002672, -0.000039, 0.966056, // B -> D50 (Von Kries) 0.995186, -0.001879, 0.000000, -0.017098, 1.001537, 0.000000, -0.005430, 0.000380, 0.968292, // B -> D50 (XYZ Scaling) 0.973252, 0.000000, 0.000000, 0.000000, 1.000000, 0.000000, 0.000000, 0.000000, 0.968295, // B -> D55 (Bradford) 0.967155, -0.026843, 0.002545, -0.018894, 1.020141, -0.003387, 0.019895, 0.007571, 1.081535, // B -> D55 (Von Kries) 0.988943, -0.004315, 0.000000, -0.039278, 1.003532, 0.000000, 0.018490, 0.000871, 1.080514, // B -> D55 (XYZ Scaling) 0.965197, 0.000000, 0.000000, 0.000000, 1.000000, 0.000000, 0.000000, 0.000000, 1.080518, // B -> D65 (Bradford) 0.941484, -0.042836, 0.010157, -0.032134, 1.025102, -0.016128, 0.058499, 0.020341, 1.284904, // B -> D65 (Von Kries) 0.979857, -0.007861, 0.000000, -0.071558, 1.006436, 0.000000, 0.060156, 0.001586, 1.277783, // B -> D65 (XYZ Scaling) 0.959370, 0.000000, 0.000000, 0.000000, 1.000000, 0.000000, 0.000000, 0.000000, 1.277788, // B -> D75 (Bradford) 0.923139, -0.053546, 0.016407, -0.041374, 1.027096, -0.026684, 0.089403, 0.030453, 1.450325, // B -> D75 (Von Kries) 0.973300, -0.010419, 0.000000, -0.094851, 1.008531, 0.000000, 0.093846, 0.002101, 1.438081, // B -> D75 (XYZ Scaling) 0.958283, 0.000000, 0.000000, 0.000000, 1.000000, 0.000000, 0.000000, 0.000000, 1.438086, // B -> E (Bradford) 0.987430, -0.004980, 0.006942, -0.005608, 0.996265, -0.012009, 0.032084, 0.010171, 1.179413, // B -> E (Von kries) 0.995299, -0.001835, 0.000000, -0.016702, 1.001503, 0.000000, 0.035959, 0.000370, 1.173388, // B -> E (XYZ Scaling) 1.009367, 0.000000, 0.000000, 0.000000, 1.000000, 0.000000, 0.000000, 0.000000, 1.173392, // C -> A (Bradford) 1.203987, 0.140744, -0.025283, 0.102952, 0.928000, 0.038760, -0.156705, -0.055873, 0.289153, // C -> A (Von Kries) 1.067896, 0.025724, 0.000000, 0.234191, 0.980909, 0.000000, -0.154849, -0.005190, 0.300982, // C -> A (XYZ Scaling) 1.120225, 0.000000, 0.000000, 0.000000, 1.000000, 0.000000, 0.000000, 0.000000, 0.300983, // C -> B (Bradford) 1.053816, 0.032278, -0.010661, 0.025192, 0.991268, 0.017441, -0.057275, -0.019402, 0.715681, // C -> B (Von Kries) 1.018301, 0.006933, 0.000000, 0.063126, 0.994853, 0.000000, -0.059908, -0.001398, 0.721597, // C -> B (XYZ Scaling) 1.010516, 0.000000, 0.000000, 0.000000, 1.000000, 0.000000, 0.000000, 0.000000, 0.721599, // C -> C 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, // C -> D50 (Bradford) 1.037765, 0.017182, -0.011978, 0.015460, 1.005438, 0.020371, -0.058148, -0.018868, 0.691416, // C -> D50 (Von Kries) 1.013279, 0.005031, 0.000000, 0.045808, 0.996264, 0.000000, -0.063514, -0.001014, 0.698718, // C -> D50 (XYZ Scaling) 0.983487, 0.000000, 0.000000, 0.000000, 1.000000, 0.000000, 0.000000, 0.000000, 0.698721, // C -> D55 (Bradford) 1.018382, 0.004560, -0.008957, 0.005982, 1.010689, 0.015570, -0.040789, -0.012837, 0.773954, // C -> D55 (Von Kries) 1.006768, 0.002564, 0.000000, 0.023348, 0.998095, 0.000000, -0.045848, -0.000516, 0.779698, // C -> D55 (XYZ Scaling) 0.975347, 0.000000, 0.000000, 0.000000, 1.000000, 0.000000, 0.000000, 0.000000, 0.779701, // C -> D65 (Bradford) 0.990490, -0.012269, -0.003515, -0.007115, 1.015427, 0.006679, -0.011434, -0.002878, 0.919313, // C -> D65 (Von Kries) 0.997291, -0.001026, 0.000000, -0.009340, 1.000760, 0.000000, -0.015193, 0.000208, 0.922047, // C -> D65 (XYZ Scaling) 0.969459, 0.000000, 0.000000, 0.000000, 1.000000, 0.000000, 0.000000, 0.000000, 0.922050, // C -> D75 (Bradford) 0.970531, -0.023599, 0.000967, -0.016198, 1.017309, -0.000743, 0.011914, 0.004934, 1.037548, // C -> D75 (Von Kries) 0.990453, -0.003617, 0.000000, -0.032927, 1.002683, 0.000000, 0.009543, 0.000730, 1.037718, // C -> D75 (XYZ Scaling) 0.968360, 0.000000, 0.000000, 0.000000, 1.000000, 0.000000, 0.000000, 0.000000, 1.037721, // C -> E (Bradford) 1.040046, 0.026802, -0.005645, 0.019876, 0.987617, 0.008842, -0.033485, -0.011765, 0.843919, // C -> E (Von Kries) 1.013396, 0.005075, 0.000000, 0.046208, 0.996233, 0.000000, -0.033655, -0.001024, 0.846716, // C -> E (XYZ Scaling) 1.019981, 0.000000, 0.000000, 0.000000, 1.000000, 0.000000, 0.000000, 0.000000, 0.846719, // D50 -> A (Bradford) 1.157264, 0.119830, -0.020050, 0.087174, 0.922061, 0.030403, -0.126938, -0.045569, 0.417348, // D50 -> A (Von Kries) 1.052976, 0.020503, 0.000000, 0.186659, 0.983644, 0.000000, -0.125633, -0.004137, 0.430762, // D50 -> A (XYZ Scaling) 1.139034, 0.000000, 0.000000, 0.000000, 1.000000, 0.000000, 0.000000, 0.000000, 0.430763, // D50 -> B (Bradford) 1.015344, 0.014785, 0.001735, 0.009388, 0.985677, -0.003652, 0.002809, 0.000081, 1.035142, // D50 -> B (Von Kries) 1.004871, 0.001885, 0.000000, 0.017164, 0.998496, 0.000000, 0.005627, -0.000381, 1.032740, // D50 -> B (XYZ Scaling) 1.027483, 0.000000, 0.000000, 0.000000, 1.000000, 0.000000, 0.000000, 0.000000, 1.032743, // D50 -> C (Bradford) 0.964813, -0.016165, 0.017191, -0.016469, 0.994317, -0.029580, 0.080692, 0.025774, 1.446947, // D50 -> C (Von Kries) 0.987122, -0.004985, 0.000000, -0.045378, 1.003977, 0.000000, 0.089662, 0.001004, 1.431183, // D50 -> C (XYZ Scaling) 1.016791, 0.000000, 0.000000, 0.000000, 1.000000, 0.000000, 0.000000, 0.000000, 1.431187, // D50 -> D50 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, // D50 -> D55 (Bradford) 0.981751, -0.012159, 0.004411, -0.009617, 1.005251, -0.007265, 0.023309, 0.007844, 1.119548, // D50 -> D55 (Von Kries) 0.993685, -0.002444, 0.000000, -0.022249, 1.001949, 0.000000, 0.024676, 0.000493, 1.115894, // D50 -> D55 (XYZ Scaling) 0.991724, 0.000000, 0.000000, 0.000000, 1.000000, 0.000000, 0.000000, 0.000000, 1.115898, // D50 -> D65 (Bradford) 0.955556, -0.028302, 0.012305, -0.023049, 1.009944, -0.020494, 0.063197, 0.021018, 1.330084, // D50 -> D65 (Von Kries) 0.984494, -0.006002, 0.000000, -0.054637, 1.004788, 0.000000, 0.067667, 0.001210, 1.319622, // D50 -> D65 (XYZ Scaling) 0.985737, 0.000000, 0.000000, 0.000000, 1.000000, 0.000000, 0.000000, 0.000000, 1.319627, // D50 -> D75 (Bradford) 0.936847, -0.039129, 0.018781, -0.032442, 1.011771, -0.031445, 0.095135, 0.031456, 1.501335, // D50 -> D75 (Von Kries) 0.977862, -0.008569, 0.000000, -0.078007, 1.006836, 0.000000, 0.102432, 0.001727, 1.485168, // D50 -> D75 (XYZ Scaling) 0.984620, 0.000000, 0.000000, 0.000000, 1.000000, 0.000000, 0.000000, 0.000000, 1.485174, // D50 -> E (Bradford) 1.002553, 0.009691, 0.008918, 0.003624, 0.981912, -0.016079, 0.035984, 0.010595, 1.220878, // D50 -> E (Von Kries) 1.000115, 0.000044, 0.000000, 0.000401, 0.999965, 0.000000, 0.042744, -0.000010, 1.211809, // D50 -> E (XYZ Scaling) 1.037108, 0.000000, 0.000000, 0.000000, 1.000000, 0.000000, 0.000000, 0.000000, 1.211813, // D55 -> A (Bradford) 1.180601, 0.133653, -0.021693, 0.097012, 0.918163, 0.032732, -0.138643, -0.049919, 0.373005, // D55 -> A (Von Kries) 1.060184, 0.023049, 0.000000, 0.209842, 0.982241, 0.000000, -0.136121, -0.004650, 0.386023, // D55 -> A (XYZ Scaling) 1.148540, 0.000000, 0.000000, 0.000000, 1.000000, 0.000000, 0.000000, 0.000000, 0.386024, // D55 -> B (Bradford) 1.034540, 0.027239, -0.002349, 0.019098, 0.980736, 0.003026, -0.019163, -0.007366, 0.924635, // D55 -> B (Von Kries) 1.011356, 0.004348, 0.000000, 0.039593, 0.996649, 0.000000, -0.017339, -0.000878, 0.925479, // D55 -> B (XYZ Scaling) 1.036058, 0.000000, 0.000000, 0.000000, 1.000000, 0.000000, 0.000000, 0.000000, 0.925482, // D55 -> C (Bradford) 0.982433, -0.004287, 0.011457, -0.006610, 0.989199, -0.019977, 0.051668, 0.016181, 1.292341, // D55 -> C (Von Kries) 0.993339, -0.002552, 0.000000, -0.023228, 1.001966, 0.000000, 0.058394, 0.000514, 1.282539, // D55 -> C (XYZ Scaling) 1.025276, 0.000000, 0.000000, 0.000000, 1.000000, 0.000000, 0.000000, 0.000000, 1.282543, // D55 -> D50 (Bradford) 1.018803, 0.012353, -0.003934, 0.009594, 0.994842, 0.006418, -0.021278, -0.007227, 0.893255, // D55 -> D50 (Von Kries) 1.006412, 0.002455, 0.000000, 0.022357, 0.998107, 0.000000, -0.022266, -0.000495, 0.896136, // D55 -> D50 (XYZ Scaling) 1.008345, 0.000000, 0.000000, 0.000000, 1.000000, 0.000000, 0.000000, 0.000000, 0.896140, // D55 -> D55 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, // D55 -> D65 (Bradford) 0.972990, -0.016440, 0.007051, -0.013357, 1.004598, -0.011734, 0.036285, 0.012078, 1.187991, // D55 -> D65 (Von Kries) 0.990671, -0.003573, 0.000000, -0.032527, 1.002753, 0.000000, 0.038746, 0.000720, 1.182565, // D55 -> D65 (XYZ Scaling) 0.993963, 0.000000, 0.000000, 0.000000, 1.000000, 0.000000, 0.000000, 0.000000, 1.182570, // D55 -> D75 (Bradford) 0.953688, -0.027490, 0.012840, -0.022677, 1.006379, -0.021468, 0.065280, 0.021618, 1.340903, // D55 -> D75 (Von Kries) 0.983939, -0.006152, 0.000000, -0.056002, 1.004740, 0.000000, 0.070060, 0.001240, 1.330918, // D55 -> D75 (XYZ Scaling) 0.992836, 0.000000, 0.000000, 0.000000, 1.000000, 0.000000, 0.000000, 0.000000, 1.330923, // D55 -> E (Bradford) 1.021308, 0.021962, 0.004085, 0.013455, 0.977009, -0.008075, 0.010784, 0.002161, 1.090481, // D55 -> E (Von Kries) 1.006527, 0.002499, 0.000000, 0.022756, 0.998075, 0.000000, 0.016037, -0.000505, 1.085950, // D55 -> E (XYZ Scaling) 1.045763, 0.000000, 0.000000, 0.000000, 1.000000, 0.000000, 0.000000, 0.000000, 1.085953, // D65 -> A (Bradford) 1.216371, 0.153235, -0.023966, 0.110931, 0.915343, 0.035935, -0.154983, -0.056006, 0.314346, // D65 -> A (Von kries) 1.071049, 0.026803, 0.000000, 0.244014, 0.980413, 0.000000, -0.150348, -0.005408, 0.326427, // D65 -> A (XYZ Scaling) 1.155516, 0.000000, 0.000000, 0.000000, 1.000000, 0.000000, 0.000000, 0.000000, 0.326428, // D65 -> B (Bradford) 1.064164, 0.044624, -0.007852, 0.032589, 0.976635, 0.012001, -0.048965, -0.017493, 0.778436, // D65 -> B (Von Kries) 1.021142, 0.007975, 0.000000, 0.072613, 0.994171, 0.000000, -0.048164, -0.001609, 0.782600, // D65 -> B (XYZ Scaling) 1.042351, 0.000000, 0.000000, 0.000000, 1.000000, 0.000000, 0.000000, 0.000000, 0.782603, // D65 -> C (Bradford) 1.009732, 0.012211, 0.003772, 0.006993, 0.984871, -0.007129, 0.012581, 0.003235, 1.087795, // D65 -> C (Von Kries) 1.002728, 0.001028, 0.000000, 0.009367, 0.999248, 0.000000, 0.016519, -0.000208, 1.084536, // D65 -> C (XYZ Scaling) 1.031503, 0.000000, 0.000000, 0.000000, 1.000000, 0.000000, 0.000000, 0.000000, 1.084540, // D65 -> D50 (Bradford) 1.047835, 0.029556, -0.009238, 0.022897, 0.990481, 0.015050, -0.050147, -0.017056, 0.752034, // D65 -> D50 (Von Kries) 1.016089, 0.006069, 0.000000, 0.055260, 0.995564, 0.000000, -0.052154, -0.001224, 0.757788, // D65 -> D50 (XYZ Scaling) 1.014470, 0.000000, 0.000000, 0.000000, 1.000000, 0.000000, 0.000000, 0.000000, 0.757790, // D65 -> D55 (Bradford) 1.028213, 0.016898, -0.005936, 0.013304, 0.995522, 0.009754, -0.031540, -0.010637, 0.841840, // D65 -> D55 (Von Kries) 1.009537, 0.003597, 0.000000, 0.032756, 0.997370, 0.000000, -0.033098, -0.000726, 0.845614, // D65 -> D55 (XYZ Scaling) 1.006074, 0.000000, 0.000000, 0.000000, 1.000000, 0.000000, 0.000000, 0.000000, 0.845616, // D65 -> D65 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, // D65 -> D75 (Bradford) 0.979823, -0.011388, 0.004880, -0.009251, 1.001719, -0.008121, 0.025117, 0.008361, 1.128649, // D65 -> D75 (Von Kries) 0.993120, -0.002596, 0.000000, -0.023629, 1.001897, 0.000000, 0.026719, 0.000523, 1.125446, // D65 -> D75 (XYZ Scaling) 0.998867, 0.000000, 0.000000, 0.000000, 1.000000, 0.000000, 0.000000, 0.000000, 1.125450, // D65 -> E (Bradford) 1.050285, 0.039078, -0.002409, 0.027087, 0.972947, 0.002652, -0.023276, -0.009266, 0.917968, // D65 -> E (Von kries) 1.016207, 0.006113, 0.000000, 0.055662, 0.995532, 0.000000, -0.019769, -0.001234, 0.918297, // D65 -> E (XYZ Scaling) 1.052114, 0.000000, 0.000000, 0.000000, 1.000000, 0.000000, 0.000000, 0.000000, 0.918300, // D75 -> A (Bradford) 1.243649, 0.167322, -0.025407, 0.120882, 0.914830, 0.037899, -0.165889, -0.060122, 0.278800, // D75 -> A (Von Kries) 1.079173, 0.029548, 0.000000, 0.269008, 0.979254, 0.000000, -0.159335, -0.005962, 0.290041, // D75 -> A (XYZ Scaling) 1.156827, 0.000000, 0.000000, 0.000000, 1.000000, 0.000000, 0.000000, 0.000000, 0.290042, // D75 -> B (Bradford) 1.086904, 0.056997, -0.011247, 0.042021, 0.975291, 0.017469, -0.067883, -0.023992, 0.689828, // D75 -> B (Von Kries) 1.028470, 0.010625, 0.000000, 0.096735, 0.992539, 0.000000, -0.067258, -0.002144, 0.695366, // D75 -> B (XYZ Scaling) 1.043533, 0.000000, 0.000000, 0.000000, 1.000000, 0.000000, 0.000000, 0.000000, 0.695369, // D75 -> C (Bradford) 1.030774, 0.023916, -0.000943, 0.016405, 0.983362, 0.000688, -0.011913, -0.004951, 0.963819, // D75 -> C (Von Kries) 1.009762, 0.003643, 0.000000, 0.033168, 0.997442, 0.000000, -0.009311, -0.000735, 0.963647, // D75 -> C (XYZ Scaling) 1.032673, 0.000000, 0.000000, 0.000000, 1.000000, 0.000000, 0.000000, 0.000000, 0.963650, // D75 -> D50 (Bradford) 1.070127, 0.041775, -0.012512, 0.032186, 0.988978, 0.020311, -0.068484, -0.023368, 0.666442, // D75 -> D50 (Von Kries) 1.023337, 0.008709, 0.000000, 0.079295, 0.993884, 0.000000, -0.070673, -0.001757, 0.673320, // D75 -> D50 (XYZ Scaling) 1.015620, 0.000000, 0.000000, 0.000000, 1.000000, 0.000000, 0.000000, 0.000000, 0.673322, // D75 -> D55 (Bradford) 1.049904, 0.028885, -0.009591, 0.022560, 0.993940, 0.015697, -0.051476, -0.017431, 0.745981, // D75 -> D55 (Von Kries) 1.016680, 0.006225, 0.000000, 0.056676, 0.995628, 0.000000, -0.053572, -0.001255, 0.751356, // D75 -> D55 (XYZ Scaling) 1.007215, 0.000000, 0.000000, 0.000000, 1.000000, 0.000000, 0.000000, 0.000000, 0.751359, // D75 -> D65 (Bradford) 1.020813, 0.011641, -0.004330, 0.009243, 0.998329, 0.007144, -0.022785, -0.007655, 0.886059, // D75 -> D65 (Von Kries) 1.006992, 0.002609, 0.000000, 0.023758, 0.998167, 0.000000, -0.023919, -0.000526, 0.888531, // D75 -> D65 (XYZ Scaling) 1.001134, 0.000000, 0.000000, 0.000000, 1.000000, 0.000000, 0.000000, 0.000000, 0.888534, // D75 -> D75 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, // D75 -> E (Bradford) 1.072560, 0.051258, -0.006403, 0.036583, 0.971617, 0.009183, -0.044763, -0.016548, 0.813408, // D75 -> E (Von Kries) 1.023456, 0.008754, 0.000000, 0.079698, 0.993854, 0.000000, -0.041900, -0.001766, 0.815937, // D75 -> E (XYZ Scaling) 1.053308, 0.000000, 0.000000, 0.000000, 1.000000, 0.000000, 0.000000, 0.000000, 0.815940, // E -> A (Bradford) 1.154755, 0.110892, -0.023397, 0.082246, 0.937839, 0.036653, -0.138722, -0.048732, 0.342214, // E -> A (Von Kries) 1.052848, 0.020457, 0.000000, 0.186247, 0.983669, 0.000000, -0.140810, -0.004127, 0.355469, // E -> A (XYZ Scaling) 1.098280, 0.000000, 0.000000, 0.000000, 1.000000, 0.000000, 0.000000, 0.000000, 0.355470, // E -> B (Bradford) 1.012951, 0.005123, -0.005910, 0.005370, 1.003671, 0.010188, -0.027601, -0.008795, 0.847953, // E -> B (Von Kries) 1.004757, 0.001841, 0.000000, 0.016766, 0.998529, 0.000000, -0.030798, -0.000371, 0.852227, // E -> B (XYZ Scaling) 0.990720, 0.000000, 0.000000, 0.000000, 1.000000, 0.000000, 0.000000, 0.000000, 0.852230, // E -> C (Bradford) 0.962209, -0.026032, 0.006709, -0.019703, 1.012944, -0.010744, 0.037905, 0.013088, 1.185066, // E -> C (Von Kries) 0.987012, -0.005028, 0.000000, -0.045772, 1.004013, 0.000000, 0.039174, 0.001014, 1.181026, // E -> C (XYZ Scaling) 0.980410, 0.000000, 0.000000, 0.000000, 1.000000, 0.000000, 0.000000, 0.000000, 1.181030, // E -> D50 (Bradford) 0.997754, -0.009768, -0.007417, -0.004163, 1.018316, 0.013442, -0.029371, -0.008549, 0.819186, // E -> D50 (Von Kries) 0.999887, -0.000044, 0.000000, -0.000393, 1.000033, 0.000000, -0.035270, 0.000010, 0.825207, // E -> D50 (XYZ Scaling) 0.964220, 0.000000, 0.000000, 0.000000, 1.000000, 0.000000, 0.000000, 0.000000, 0.825210, // E -> D55 (Bradford) 0.979467, -0.022009, -0.003832, -0.013568, 1.023820, 0.007632, -0.009659, -0.001811, 0.917050, // E -> D55 (Von Kries) 0.993574, -0.002488, 0.000000, -0.022644, 1.001984, 0.000000, -0.014684, 0.000503, 0.920847, // E -> D55 (XYZ Scaling) 0.956240, 0.000000, 0.000000, 0.000000, 1.000000, 0.000000, 0.000000, 0.000000, 0.920850, // E -> D65 (Bradford) 0.953167, -0.038259, 0.002612, -0.026600, 1.028843, -0.003042, 0.023901, 0.009415, 1.089399, // E -> D65 (Von Kries) 0.984385, -0.006045, 0.000000, -0.055029, 1.004824, 0.000000, 0.021116, 0.001220, 1.088965, // E -> D65 (XYZ Scaling) 0.950467, 0.000000, 0.000000, 0.000000, 1.000000, 0.000000, 0.000000, 0.000000, 1.088969, // E -> D75 (Bradford) 0.934355, -0.049157, 0.007910, -0.035658, 1.030889, -0.011919, 0.050694, 0.018268, 1.229589, // E -> D75 (Von Kries) 0.977754, -0.008612, 0.000000, -0.078398, 1.006874, 0.000000, 0.050039, 0.001738, 1.225576, // E -> D75 (XYZ Scaling) 0.949390, 0.000000, 0.000000, 0.000000, 1.000000, 0.000000, 0.000000, 0.000000, 1.225580, // E -> E 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0 }; return CAmatrix[index]; } // public methods public: static double gamma(RGBSpaces rgb_space) { if (rgb_space == ADOBE_RGB) { return 2.2; } else if (rgb_space == APPLE_RGB) { return 1.8; } else if (rgb_space == BEST_RGB) { return 2.2; } else if (rgb_space == BETA_RGB) { return 2.2; } else if (rgb_space == BRUCE_RGB) { return 2.2; } else if (rgb_space == CIE_RGB) { return 2.2; } else if (rgb_space == DON_RGB4) { return 1.8; } else if (rgb_space == ECI_RGB) { return 2.2; } else if (rgb_space == EKTA_SPACE) { return 2.2; } else if (rgb_space == NTSC_RGB) { return 2.2; } else if (rgb_space == PAL_RGB) { return 2.2; } else if (rgb_space == PROPHOTO) { return 1.8; } else if (rgb_space == SMPTE_C) { return 2.2; } else if (rgb_space == SRGB) { return 2.2; // about 2.2 } else if (rgb_space == WIDE_GAMUT) { return 2.2; } else { assert(false); return 0.0; } } static Illuminant refIlluminant(RGBSpaces rgb_space) { // RGB WORKING SPACE DATA // // Illuminant Reference for each RGB Space. // if (rgb_space == ADOBE_RGB) { return ILLUMINANT_D65; } else if (rgb_space == APPLE_RGB) { return ILLUMINANT_D65; } else if (rgb_space == BEST_RGB) { return ILLUMINANT_D50; } else if (rgb_space == BETA_RGB) { return ILLUMINANT_D50; } else if (rgb_space == BRUCE_RGB) { return ILLUMINANT_D65; } else if (rgb_space == CIE_RGB) { return ILLUMINANT_E; } else if (rgb_space == DON_RGB4) { return ILLUMINANT_D50; } else if (rgb_space == ECI_RGB) { return ILLUMINANT_D50; } else if (rgb_space == EKTA_SPACE) { return ILLUMINANT_D50; } else if (rgb_space == NTSC_RGB) { return ILLUMINANT_C; } else if (rgb_space == PAL_RGB) { return ILLUMINANT_D65; } else if (rgb_space == PROPHOTO) { return ILLUMINANT_D50; } else if (rgb_space == SMPTE_C) { return ILLUMINANT_D65; } else if (rgb_space == SRGB) { return ILLUMINANT_D65; } else if (rgb_space == WIDE_GAMUT) { return ILLUMINANT_D50; } else { assert(false); return ILLUMINANT_INVALID; } } static Color4 RGBtoHSV(const Color4 & color) { double h,s,v; RGBtoHSV(static_cast(color[0]), static_cast(color[1]), static_cast(color[2]), h,s,v); Color4 c(h,s,v,color[3]); return c; } static void RGBtoHSV(double R, double G, double B, double &H, double &S, double &V) { double v = std::min(R, G); double v_min = std::min(v, B); // Min value of RGB double v2 = std::max(R, G); double v_max = std::max(v2, B); // Max value of RGB double delta = v_max - v_min; //Delta RGB value V = v_max; if (delta < 0.00000000001) // This is a gray, no chroma... { H = 0.0; // HSV results = 0 1 S = 0.0; } else // Chromatic data... { S = delta / v_max; double deltaR = (((v_max - R) / 6) + (delta/2.0) ) / delta; double deltaG = (((v_max - G) / 6) + (delta/2.0) ) / delta; double deltaB = (((v_max - B) / 6) + (delta/2.0) ) / delta; if ( R == v_max ) H = deltaB - deltaG; else if (G == v_max) H = (1.0 / 3.0) + deltaR - deltaB; else if (B == v_max) H = (2.0 / 3.0) + deltaG - deltaR; if ( H < 0 ) H += 1.0; if ( H > 1 ) H -= 1.0; } } static Color4 HSVtoRGB(const Color4 & color) { double r,g,b; HSVtoRGB(static_cast(color[0]), static_cast(color[1]), static_cast(color[2]), r,g,b); Color4 c(r,g,b,color[3]); return c; } static void HSVtoRGB(double H, double S, double V, double &R, double &G, double &B) { if (S == 0) { R = V; G = V; B = V; } else { double var_h = H * 6.0; if (var_h == 6.0) var_h = 0.0; // H must be < 1 int var_i = static_cast(var_h); double var_1 = V * (1.0 - S); double var_2 = V * (1.0 - S * (var_h - var_i )); double var_3 = V * (1.0 - S * (1.0 - (var_h - var_i))); double var_r, var_g, var_b; if (var_i == 0) { var_r = V; var_g = var_3; var_b = var_1; } else if (var_i == 1) { var_r = var_2; var_g = V; var_b = var_1; } else if (var_i == 2) { var_r = var_1; var_g = V; var_b = var_3; } else if (var_i == 3) { var_r = var_1; var_g = var_2; var_b = V; } else if (var_i == 4) { var_r = var_3; var_g = var_1; var_b = V; } else { var_r = V; var_g = var_1; var_b = var_2; } R = var_r; G = var_g; B = var_b; } } static Color4 XYZtoRGB(const Color4 & color, Illuminant src, RGBSpaces dest, ConeResponse response = BRADFORD) { double r,g,b; XYZtoRGB(static_cast(color[0]), static_cast(color[1]), static_cast(color[2]), src, r,g,b, dest, response); Color4 c(r,g,b,color[3]); return c; } static void XYZtoRGB(double X, double Y, double Z, Illuminant src, double &R, double &G, double &B, RGBSpaces space, ConeResponse response = BRADFORD) { double Xp, Yp, Zp; chromaticAdaptation(X, Y, Z, src, Xp, Yp, Zp, refIlluminant(space), response); int index = static_cast(space) * 3 * 3; double r = Xp * XYZ2RGB(index) + Yp * XYZ2RGB(index+3) + Zp * XYZ2RGB(index+6); double g = Xp * XYZ2RGB(index+1) + Yp * XYZ2RGB(index+4) + Zp * XYZ2RGB(index+7); double b = Xp * XYZ2RGB(index+2) + Yp * XYZ2RGB(index+5) + Zp * XYZ2RGB(index+8); // Account for gamma correction if (space == SRGB) { if (r > 0.0031308) R = 1.055 * pow(r, 1.0/2.4) - 0.055; else R = 12.92 * r; if (g > 0.0031308) G = 1.055 * pow(g, 1.0/2.4) - 0.055; else G = 12.92 * g; if (b > 0.0031308) B = 1.055 * pow(b, 1.0/2.4) - 0.055; else B = 12.92 * b; } else { double lambda = gamma(space); R = pow(r, 1.0/lambda); G = pow(g, 1.0/lambda); B = pow(b, 1.0/lambda); } } static Color4 RGBtoXYZ(const Color4 & color, RGBSpaces space, Illuminant dest, ConeResponse response = BRADFORD) { double x,y,z; RGBtoXYZ(static_cast(color[0]), static_cast(color[1]), static_cast(color[2]), space, x,y,z, dest, response); Color4 c(x,y,z,color[3]); return c; } static void RGBtoXYZ(double R, double G, double B, RGBSpaces space, double &X, double &Y, double &Z, Illuminant dest, ConeResponse response = BRADFORD) { // Account for Gamma Correction double r,g,b; if (space == SRGB) { if (R <= 0.04045) r = R / 12.92; else r = pow((R + 0.055) / 1.055, 2.4); if (G <= 0.04045) g = G / 12.92; else g = pow((G + 0.055) / 1.055, 2.4); if (B <= 0.04045) b = B / 12.92; else b = pow((B + 0.055) / 1.055, 2.4); } else { double lambda = gamma(space); r = pow(R, lambda); g = pow(G, lambda); b = pow(B, lambda); } int index = static_cast(space) * 3 * 3; double Xt = r * RGB2XYZ(index) + g * RGB2XYZ(index+3) + b * RGB2XYZ(index+6); double Yt = r * RGB2XYZ(index+1) + g * RGB2XYZ(index+4) + b * RGB2XYZ(index+7); double Zt = r * RGB2XYZ(index+2) + g * RGB2XYZ(index+5) + b * RGB2XYZ(index+8); // Convert from reference illuminant to the desired one chromaticAdaptation(Xt, Yt, Zt, refIlluminant(space), X, Y, Z, dest, response); } static Color4 XYZtoCIELab(const Color4 & color, Illuminant ref) { double L,a,b; XYZtoCIELab(static_cast(color[0]), static_cast(color[1]), static_cast(color[2]), L,a,b, ref); Color4 c(L,a,b,color[3]); return c; } static void XYZtoCIELab(double X, double Y, double Z, double &L, double &a, double &b, Illuminant whiteRef) { // Reference white computation // Note: The reference white depends only on the illuminant // (it is independent on the RGB Working Space) double Xr, Yr, Zr; RGBtoXYZ(1.0, 1.0, 1.0, SRGB, Xr, Yr, Zr, whiteRef); double xr = X / Xr; double yr = Y / Yr; double zr = Z / Zr; double cieEpsilon = CIE_EPSILON(); double cieKi = CIE_KI(); double fx; if (xr > cieEpsilon) fx = pow(xr, 1.0/3.0); else fx = (cieKi * xr + 16.0) / 116.0; double fy; if (yr > cieEpsilon) fy = pow(yr, 1.0/3.0); else fy = (cieKi * yr + 16.0) / 116.0; double fz; if (zr > cieEpsilon) fz = pow(zr, 1.0/3.0); else fz = (cieKi * zr + 16.0) / 116.0; L = 116.0 * fy - 16.0; a = 500.0 * (fx - fy); b = 200.0 * (fy - fz); } static Color4 CIELabtoXYZ(const Color4 & color, Illuminant ref) { double x,y,z; CIELabtoXYZ(static_cast(color[0]), static_cast(color[1]), static_cast(color[2]), x,y,z, ref); Color4 c(x,y,z,color[3]); return c; } static void CIELabtoXYZ(double L, double a, double b, double &X, double &Y, double &Z, Illuminant whiteRef) { double cieEpsilon = CIE_EPSILON(); double cieKi = CIE_KI(); double value; double yr; if (L > cieKi * cieEpsilon) { value = (L + 16.0) / 116.0; yr = value * value * value; } else yr = L / cieKi; double fy; if (yr > cieEpsilon) fy = (L + 16.0) / 116.0; else fy = (cieKi * yr + 16.0) / 116.0; double fz = fy - (b / 200.0); double fz_cubed = fz * fz * fz; double fx = (a / 500.0) + fy; double fx_cubed = fx * fx * fx; double xr; if (fx_cubed > cieEpsilon) xr = fx_cubed; else xr = (116.0 * fx - 16.0) / cieKi; double zr; if (fz_cubed > cieEpsilon) zr = fz_cubed; else zr = (116.0 * fz - 16.0) / cieKi; // Reference white computation // Note: The reference white depends only on the illuminant // (it is independent on the RGB Working Space) double Xr, Yr, Zr; RGBtoXYZ(1.0, 1.0, 1.0, SRGB, Xr, Yr, Zr, whiteRef); X = xr * Xr; Y = yr * Yr; Z = zr * Zr; } // RGB --> HSL static Color4 RGBtoHSL(const Color4 & color) { double h,s,l; RGBtoHSL(static_cast(color[0]), static_cast(color[1]), static_cast(color[2]), h,s,l); Color4 c(h,s,l,color[3]); return c; } // RGB --> HSL static void RGBtoHSL(double R, double G, double B, double &H, double &S, double &L) { double v = std::min(R,G); double v_min = std::min(v, B); // Min value of RGB v = std::max(R,G); double v_max = std::max(v, B); // Max value of RGB double delta = v_max - v_min; // Delta RGB value L = (v_max + v_min) / 2.0; if (delta == 0.0) // This is a gray, no chroma... { H = 0.0; S = 0.0; } else // Chromatic data... { if ( L < 0.5 ) S = delta / (v_max + v_min); else S = delta / (2.0 - v_max - v_min); double deltaR = (((v_max - R) / 6.0) + (delta/2.0)) / delta; double deltaG = (((v_max - G) / 6.0) + (delta/2.0)) / delta; double deltaB = (((v_max - B) / 6.0) + (delta/2.0)) / delta; if (R == v_max) H = deltaB - deltaG; else if (G == v_max) H = (1.0 / 3.0) + deltaR - deltaB; else if (B == v_max) H = (2.0 / 3.0) + deltaG - deltaR; if ( H < 0.0 ) H += 1.0; if ( H > 1.0 ) H -= 1.0; } } static Color4 HSLtoRGB(const Color4 & color) { double r,g,b; HSLtoRGB(static_cast(color[0]), static_cast(color[1]), static_cast(color[2]), r,g,b); Color4 c(r,g,b,color[3]); return c; } // HSL --> RGB static void HSLtoRGB(double H, double S, double L, double &R, double &G, double &B) { if (S == 0.0) { R = L; G = L; B = L; } else { double var_1, var_2; if (L < 0.5) var_2 = L * ( 1 + S ); else var_2 = ( L + S ) - ( S * L ); var_1 = 2 * L - var_2; R = Hue2RGB(var_1, var_2, H + (1.0/3.0)); G = Hue2RGB(var_1, var_2, H ); B = Hue2RGB(var_1, var_2, H - (1.0/3.0)); } } static double Hue2RGB(double v1, double v2, double vH) { if ( vH < 0 ) vH += 1.0; if ( vH > 1 ) vH -= 1.0; if ( (6.0 * vH) < 1.0) return (v1 + ( v2 - v1 ) * 6.0 * vH); if ( (2.0 * vH) < 1.0) return v2; if ( (3.0 * vH) < 2.0) return ( v1 + ( v2 - v1 ) * ((2.0/3.0) - vH) * 6.0); return v1; } static Color4 xyYtoXYZ(const Color4 & color) { double X,Y,Z; xyYtoXYZ(static_cast(color[0]), static_cast(color[1]), static_cast(color[2]), X,Y,Z); Color4 c(X,Y,Z,color[3]); return c; } // CIE xyY --> CIE XYZ static void xyYtoXYZ(double x, double y, double _Y, double &X, double &Y, double &Z) { X = x * (Y / y); Y = _Y; Z = (1.0 - x - y) * (Y / y); } static Color4 XYZtoxyY(const Color4 & color) { double x,y,Y; XYZtoxyY(static_cast(color[0]), static_cast(color[1]), static_cast(color[2]), x, y, Y); Color4 c(x,y,Y,color[3]); return c; } // CIE XYZ --> CIE xyY static void XYZtoxyY(double X, double _Y, double Z, double &x, double &y, double &Y) { x = X / (X + Y + Z); y = Y / (X + Y + Z); Y = _Y; } // XYZ (Illuminant src) --> XYZ (Illuminant dest) - [ILLUMINANT CHANGE] static Color4 chromaticAdaptation(const Color4 & color, Illuminant src, Illuminant dst, ConeResponse response = BRADFORD) { double X,Y,Z; chromaticAdaptation(static_cast(color[0]), static_cast(color[1]), static_cast(color[2]), src, X, Y, Z, dst, response); Color4 c(X,Y,Z,color[3]); return c; } // XYZ (Illuminant src) --> XYZ (Illuminant dest) - [ILLUMINANT CHANGE] static void chromaticAdaptation(double Xi, double Yi, double Zi, Illuminant src, double &X, double &Y, double &Z, Illuminant dst, ConeResponse response = BRADFORD) { int index = static_cast(src) * 8 * 3 * 3 * 3 + static_cast(dst) * 3 * 3 * 3 + static_cast(response) * 3 * 3; X = CA(index) * Xi + CA(index+3) * Yi + CA(index+6) * Zi; Y = CA(index+1) * Xi + CA(index+4) * Yi + CA(index+7) * Zi; Z = CA(index+2) * Xi + CA(index+5) * Yi + CA(index+8) * Zi; } // RGB (working space src) --> RGB (working space dest) - [RGB WORKING SPACE CHANGE] static Color4 RGBtoRGB(const Color4 & color, RGBSpaces rgbsrc, RGBSpaces rgbdest, ConeResponse response = BRADFORD) { double R,G,B; RGBtoRGB(static_cast(color[0]), static_cast(color[1]), static_cast(color[2]), rgbsrc, R,G,B, rgbdest, response); Color4 c(R,G,B,color[3]); return c; } // RGB (working space src) --> RGB (working space dest) - [RGB WORKING SPACE CHANGE] static void RGBtoRGB(double Ri, double Gi, double Bi, RGBSpaces rgbsrc, double &R, double &G, double &B, RGBSpaces rgbdest, ConeResponse response = BRADFORD) { double X,Y,Z; RGBtoXYZ(Ri, Gi, Bi, rgbsrc, X,Y,Z, refIlluminant(rgbsrc)); XYZtoRGB(X,Y,Z, refIlluminant(rgbsrc), R,G,B, rgbdest); } }; } // end of NameSpace VCG #endif /* __VCGLIB_COLORSPACE */ qutemol/vcg/vcg/space/box.h0000444000175000017500000002571310171204302014212 0ustar mbamba/**************************************************************************** * VCGLib o o * * Visual and Computer Graphics Library o o * * _ O _ * * Copyright(C) 2004 \/)\/ * * Visual Computing Lab /\/| * * ISTI - Italian National Research Council | * * \ * * All rights reserved. * * * * 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. * * * * 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 (http://www.gnu.org/licenses/gpl.txt) * * for more details. * * * ****************************************************************************/ /**************************************************************************** History $Log: box.h,v $ Revision 1.2 2005/01/12 11:23:46 ganovelli correction on point<3 Revision 1.1 2004/03/16 03:07:38 tarini "dimensionally unified" version: first commit Revision 1.5 2004/03/05 17:51:28 tarini Errorino "ScalarType" -> "S" Revision 1.4 2004/03/03 14:32:13 cignoni Yet another cr lf mismatch Revision 1.3 2004/02/23 23:44:21 cignoni cr lf mismatch Revision 1.2 2004/02/19 15:40:56 cignoni Added doxygen groups Revision 1.1 2004/02/13 02:16:22 cignoni First working release. ****************************************************************************/ #ifndef __VCGLIB_BOX #define __VCGLIB_BOX #include #include #include namespace vcg { /** \addtogroup space */ /*@{*/ /** Templated class for 3D boxes. This is the class for definition of a axis aligned box in 2D or 3D space. Typically used as bounding boxes. It is stored just as two Points (at the opposite vertices). @param S (template parameter) Specifies the type of scalar used to represent coords. */ template class Box : public Space , Linear { public: typedef S ScalarType; typedef Point ParamType; typedef Point PointType; enum {Dimension=N}; /// The scalar type protected: /// _min coordinate point Point3 _min; /// _max coordinate point Point3 _max; public: inline const PointType &Max() const { return _max; } inline PointType &Max() { return _max; } inline const PointType &Min() const { return _min; } inline PointType &Min() { return _min; } /// The box constructor inline Box() { _min.X()= 1;_max.X()= -1; _min.Y()= 1;_max.Y()= -1; if (N>2) {_min.Z()= 1;_max.Z()= -1;} } /// Min Max constructor inline Box( const PointType & mi, const PointType & ma ) { _min = mi; _max = ma; } /// The box distructor inline ~Box() { } /// Operator to compare two boxes inline bool operator == ( Box const & p ) const { return _min==p._min && _max==p._max; } /// Operator to dispare two boxes inline bool operator != ( Box const & p ) const { return _min!=p._min || _max!=p._max; } /** Infaltes the box of a percentage.. @param s Scalar value. E.g if s=0.1 the box enlarges of 10% in every direction if S==0.5 box doubles (+50% in every direction) if S < 0 box shrinks if S==0.5 box reduces to a point */ void Inflate( const S s ) { Inflate( (_max-_min)*s ); } /** Enlarges the box dimensions by k in every direction, with k = bbox.diag*s */ void InflateFix( const S s ) { S k = Diag()*s; if (N==2) Inflate( PointType (k,k)); if (N==3) Inflate( PointType (k,k,k)); } /** Enlarges the box dimensions by a fixed delta. @param delta Point in D space. If delta > 0 box enlarges. If delta < 0 box reduces. */ void Inflate( const PointType & delta ) { _min -= delta; _max += delta; } /// Initializing the box void Set( const PointType & p ) { _min = _max = p; } /// Set the box to a null value void SetNull() { _min.X()= 1; _max.X()= -1; _min.Y()= 1; _max.Y()= -1; _min.Z()= 1; _max.Z()= -1; } /** Add two boxex: Returns minimal box that contains both operands. @param b The box to add */ void Add( Box const & b ) { if(IsNull()) *this=b; else Add(_min); Add(_max); } /** Add a point to a box. The box is modified is the added point is aoutside it. @param p The point to add */ void Add( const PointType & p ) { if(IsNull()) Set(p); else { if(_min.X() > p.X()) _min.X() = p.X(); else if(_max.X() < p.X()) _max.X() = p.X(); if(_min.Y() > p.Y()) _min.Y() = p.Y(); else if(_max.Y() < p.Y()) _max.Y() = p.Y(); if (N>2) { if(_min.Z() > p.Z()) _min.Z() = p.Z(); else if(_max.Z() < p.Z()) _max.Z() = p.Z(); }; } } /** Coputes intersection of Boxes: the minimal box containing both operands. @param b The other operand */ void Intersect( const Box & b ) { if(_min.X() < b._min.X()) _min.X() = b._min.X(); if(_min.Y() < b._min.Y()) _min.Y() = b._min.Y(); if (N>2) if(_min.Z() < b._min.Z()) _min.Z() = b._min.Z(); if(_max.X() > b._max.X()) _max.X() = b._max.X(); if(_max.Y() > b._max.Y()) _max.Y() = b._max.Y(); if (N>2) if(_max.Z() > b._max.Z()) _max.Z() = b._max.Z(); if(_min.X()>_max.X() || _min.Y()>_max.Y() ) SetNull(); else if (N>2) if (_min.Z()>_max.Z()) SetNull(); } /** Traslalate the box. @param p: the translation vector */ void Translate( const PointType & p ) { _min += p; _max += p; } /** Check wheter a point is inside box. @param p The point @returns True if inside, false otherwise */ bool IsIn( PointType const & p ) const { if (N==2) return ( _min.X() <= p.X() && p.X() <= _max.X() && _min.Y() <= p.Y() && p.Y() <= _max.Y() ); if (N==3) return ( _min.X() <= p.X() && p.X() <= _max.X() && _min.Y() <= p.Y() && p.Y() <= _max.Y() && _min.Z() <= p.Z() && p.Z() <= _max.Z() ); } /** Check wheter a point is inside box, open at left and closed at right [min..max) @param p The point 3D @returns True if inside, false otherwise */ bool IsInEx( PointType const & p ) const { if (N==2) return ( _min.X() <= p.X() && p.X() < _max.X() && _min.Y() <= p.Y() && p.Y() < _max.Y() ); if (N==3) return ( _min.X() <= p.X() && p.X() < _max.X() && _min.Y() <= p.Y() && p.Y() < _max.Y() && _min.Z() <= p.Z() && p.Z() < _max.Z() ); } /** TODO: Move TO COLLIDE!!! Verifica se due box collidono cioe' se hanno una intersezione non vuota. Per esempio due box adiacenti non collidono. @param b A box @return True se collidoo, false altrimenti */ bool Collide(Box const &b) { return b._min.X()<_max.X() && b._max.X()>_min.X() && b._min.Y()<_max.Y() && b._max.Y()>_min.Y() && b._min.Z()<_max.Z() && b._max.Z()>_min.Z() ; } /** Controlla se il box e' nullo. @return True se il box e' nullo, false altrimenti */ bool IsNull() const { return _min.X()>_max.X() || _min.Y()>_max.Y() || _min.Z()>_max.Z(); } /** Controlla se il box e' vuoto. @return True se il box e' vuoto, false altrimenti */ bool IsEmpty() const { return _min==_max; } /// Restituisce la lunghezza della diagonale del box. S Diag() const { return Distance(_min,_max); } /// Calcola il quadrato della diagonale del box. S SquaredDiag() const { return SquaredDistance(_min,_max); } /// Calcola il centro del box. PointType Center() const { return (_min+_max)/2; } /// Returns global coords of a local point expressed in [0..1]^3 PointType LocalToGlobal(PointType const & p) const{ return PointType( _min[0] + p[0]*(_max[0]-_min[0]), _min[1] + p[1]*(_max[1]-_min[1]), _min[2] + p[2]*(_max[2]-_min[2])); } /// Returns local coords expressed in [0..1]^3 of a point in 3D PointType GlobalToLocal(PointType const & p) const{ return PointType( (p[0]-_min[0])/(_max[0]-_min[0]), (p[1]-_min[1])/(_max[1]-_min[1]), (p[2]-_min[2])/(_max[2]-_min[2]) ); } /// Computes the Volume for the box. inline S Volume() const { if (N==2) return (_max.X()-_min.X())*(_max.Y()-_min.Y()); if (N==3) return (_max.X()-_min.X())*(_max.Y()-_min.Y())*(_max.Z()-_min.Z()); } /// Area() and Volume() are sinonims (a inline S Area() const { return Volume(); }; /// Compute box size. PointType Size() const { return (_max-_min); } /// Compute box size X. inline S SizeX() const { return _max.X()-_min.X();} /// Compute box size Y. inline S SizeY() const { return _max.Y()-_min.Y();} /// Compute box size Z. inline S SizeZ() const { static_assert(N>2); return _max.Z()-_min.Z();} /** @name Linearity for boxes **/ /// sets a point to Zero inline void Zero() { _min.Zero(); _max.Zero(); } inline Box operator + ( Box const & p) const { return Box(_min+p._min,_max+p._max); } inline Box operator - ( Box const & p) const { return Box(_min-p._min,_max-p._max); } inline Box operator * ( const S s ) const { return Box(_min*s,_max*s); } inline Box operator / ( const S s ) const { S inv=S(1.0)/s; return Box(_min*inv,_max*inv); } inline Box & operator += ( Box const & p) { _min+=p._min; _max+=p._max; return *this; } inline Box & operator -= ( Box const & p) { _min-=p._min; _max-=p._max; return *this; } inline Box & operator *= ( const S s ) { _min*=s; _max*=s; return *this; } inline Box & operator /= ( const S s ) { S inv=S(1.0)/s; _min*=s; _max*=s; return *this; return *this; } inline Box operator - () const { return Box(-_min,-_max); } //@} //@{ /** @name Iporters (for boxes in different spaces and with different scalar types) **/ /// imports the box template inline void Import( const Box & b ) { _max.Import( b._max );_min.Import( b._min ); } template /// constructs a new ray importing it from an existing one static Box Construct( const Box & b ) { return Box(PointType::Construct(b._min),PointType::Construct(b._max)); } }; // end class definition typedef Box<3,short> Box3s; typedef Box<3,int> Box3i; typedef Box<3,float> Box3f; typedef Box<3,double> Box3d; typedef Box<2,short> Box2s; typedef Box<2,int> Box2i; typedef Box<2,float> Box2f; typedef Box<2,double> Box2d; /*@}*/ } // end namespace #endif qutemol/vcg/vcg/space/sphere3.h0000444000175000017500000001646310632267131015010 0ustar mbamba/**************************************************************************** * VCGLib o o * * Visual and Computer Graphics Library o o * * _ O _ * * Copyright(C) 2004 \/)\/ * * Visual Computing Lab /\/| * * ISTI - Italian National Research Council | * * \ * * All rights reserved. * * * * 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. * * * * 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 (http://www.gnu.org/licenses/gpl.txt) * * for more details. * * * ****************************************************************************/ /**************************************************************************** History $Log: sphere3.h,v $ Revision 1.10 2007/06/08 14:57:29 ponchio *** empty log message *** Revision 1.9 2006/07/06 12:40:34 ganovelli typdef ..ScalarType added Revision 1.8 2005/02/22 14:18:15 ponchio assert addded. Revision 1.7 2005/02/21 17:03:03 ponchio Added Tight creation. Revision 1.6 2004/12/01 16:06:59 ponchio Distance Revision 1.5 2004/09/29 13:55:33 ponchio Added Distance shpere - point. Revision 1.4 2004/04/02 09:49:01 ponchio Ehm... a couople of small errors. Revision 1.3 2004/04/02 09:44:13 ponchio Sphere ->Sphere3 Revision 1.2 2004/03/25 17:25:46 ponchio #include sbagliato. Revision 1.1 2004/03/21 17:51:57 ponchio First version. ****************************************************************************/ #ifndef VCG_SPHERE_H #define VCG_SPHERE_H #include #include namespace vcg { /** \addtogroup space */ /*@{*/ /** Templated class for 3D sphere. This is the class for definition of a sphere in 3D space. It is stored just as a Point3 and a radius @param T (template parameter) Specifies the type of scalar used to represent coords. Various policy could be added to improve efficience (keeping square of radius for instance). */ template class Sphere3 { protected: Point3 _center; T _radius; public: typedef T ScalarType; Sphere3(): _radius(-1) {} Sphere3(const Point3 ¢er, T radius): _center(center), _radius(radius) {} T &Radius() { return _radius; } const T &Radius() const { return _radius; } Point3 &Center() { return _center; } const Point3 &Center() const { return _center; } bool IsEmpty() const { return _radius < 0; } ///return true if @param p - Center() <= Radius() bool IsIn(const Point3 &p) const; void Add(const Point3 &p); void Add(const Sphere3 &sphere); void Intersect(const Sphere3 &sphere); int CreateFromBox(int n, const Point3 *points); //makes 36 iterations over the data... but get good results. int CreateTight(int n, const Point3 *points, T threshold = 1.01, T speed = 0.6); }; template T Distance(const Sphere3 &sphere, const Point3 &point) { T dist = Distance(point, sphere.Center()) - sphere.Radius(); if(dist < 0) dist = 0; return dist; } template T Distance(const Sphere3 &sphere, const Sphere3 &s) { T dist = Distance(s.Center(), sphere.Center()) - sphere.Radius() - s.Radius(); if(dist < 0) dist = 0; return dist; } typedef Sphere3 Sphere3f; typedef Sphere3 Sphere3d; template void Sphere3::Add(const Sphere3 &sphere) { if(IsEmpty()) { *this = sphere; return; } Point3 dist = sphere.Center() - _center; float distance = dist.Norm(); float fartest = distance + sphere.Radius(); if(fartest <= _radius) return; if(distance == 0) _radius = sphere.Radius(); else { _center += dist * ((fartest - _radius) / (dist.Norm() * 2)); _radius = (_radius + fartest)/2; } } template void Sphere3::Add(const Point3 &p) { if(IsEmpty()) { _center = p; _radius = 0; } Point3 dist = p - _center; float fartest = dist.Norm(); if(fartest <= _radius) return; _center += dist * ((fartest - _radius) / (fartest*2)); _radius = (_radius + fartest)/2; } template bool Sphere3::IsIn(const Point3 &p) const { if(IsEmpty()) return false; Point3 dist = p - _center; return dist.SquaredNorm() <= _radius*_radius; } template void Sphere3::Intersect(const Sphere3 &s) { float dist = Distance(_center, s.Center()); float r = 0.5 * (_radius + s.Radius() - dist); if(r < 0) { _radius = -1; return; } _center = (s.Center()*(_radius - r) + _center*(s.Radius() - r))/dist; _radius = r; } template int Sphere3::CreateFromBox(int n, const Point3 *points) { Point3f max(-1e100, -1e100, -1e100); Point3f min(1e100, 1e100, 1e100); for(int i = 0; i < n; i++) { for(int k = 0; k < 3; k++) { if(max[k] < points[i][k]) max[k] = points[i][k]; if(min[k] > points[i][k]) min[k] = points[i][k]; } } Center() = (min + max)/2; Radius() = (min - max).Norm()/2; return 0; } template int Sphere3::CreateTight(int n, const Point3 *points, T threshold, T speed) { //This is quantized gradient descent... really ugly. But simple :P //TODO step should adapt to terrain... for(int i = 0; i < n; i++) Add(points[i]); Radius() *= 1.0001; Point3 center; T radius; //Test with 6 directions Point3f pert[6]; T step = Radius()/8; int count = 0; while(1) { count++; T radius = Radius(); pert[0] = Point3f(step, 0, 0); pert[1] = -pert[0]; pert[2] = Point3f(0, step, 0); pert[3] = -pert[2]; pert[4] = Point3f(0, 0, step); pert[5] = -pert[4]; unsigned int best = 6; T best_radius = Radius()/threshold; for(unsigned int k = 0; k < 6; k++) { center = Center() + pert[k]; radius = 0; for(unsigned int i = 0; i < n; i++) { float r = Distance(center, points[i]); if(r > radius) radius = r; } if(radius < best_radius) { best = k; best_radius = radius; } } if(best != 6) { Center() = Center() + pert[best]; Radius() = best_radius; } step *= speed; if(step < Radius() * (threshold - 1)) break; } Radius() *= 1.01; //Test we did it correctly. for(int i = 0; i < n; i++) assert(IsIn(points[i])); return count; } } //namespace #endif qutemol/vcg/vcg/space/plane3.h0000444000175000017500000001454110620143534014611 0ustar mbamba/**************************************************************************** * VCGLib o o * * Visual and Computer Graphics Library o o * * _ O _ * * Copyright(C) 2004 \/)\/ * * Visual Computing Lab /\/| * * ISTI - Italian National Research Council | * * \ * * All rights reserved. * * * * 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. * * * * 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 (http://www.gnu.org/licenses/gpl.txt) * * for more details. * * * ****************************************************************************/ /**************************************************************************** History $Log: plane3.h,v $ Revision 1.10 2007/05/08 18:54:20 ganovelli debug: function Offset called without pars Revision 1.9 2007/04/04 23:22:29 pietroni setted to const the parameter passed to function Projection Revision 1.8 2005/09/26 19:49:30 m_di_benedetto Method Set(off, dir) now correctly normalizes direction and offset if template parameter NORM is set. Revision 1.7 2005/03/18 16:34:42 fiorin minor changes to comply gcc compiler Revision 1.6 2004/10/09 13:48:02 ponchio Fixed bug in init. Revision 1.5 2004/05/10 13:15:54 cignoni missing ending newline Revision 1.4 2004/05/05 08:20:47 cignoni syntax error in set and better comment Revision 1.3 2004/04/28 16:36:55 turini Changed : in Distance(plane, point) : return plane.Direction() * point - plane.Offset; in return plane.Direction() * point - plane.Offset(); Revision 1.2 2004/04/28 11:19:52 turini Changed : in Init(p0, norm) _dist = p0 * _dir; in _offset = p0 * _dir; Changed : in Init(p0, p1, p2) _offset = p0 * _dist; in _offset = p0 * _dir; Revision 1.1 2004/03/31 22:19:24 ponchio Untested first draft. ****************************************************************************/ #ifndef VCG_PLANE3_H #define VCG_PLANE3_H #include namespace vcg { /** \addtogroup space */ /*@{*/ /** Templated class for 2D planes in 3D spaces. This is the class for infinite planes in 3D space. A Plane is stored just as a Point3 and a scalar: a direction (not necessarily normalized), and a distance from the origin @param T (template parameter) Specifies the type of scalar used to represent coords. @param NORM: if on, the direction is always Normalized */ template class Plane3 { public: typedef T ScalarType; typedef Point3 PointType; private: /// Distance ScalarType _offset; ///Direction (not necessarily normalized unless NORM is true) PointType _dir; public: //@{ /** @name Constructors **/ /// The empty constructor Plane3() {} /// The (distance, direction) constructor Plane3(const ScalarType &dist, const PointType &dir) { Set(dist, dir); } //@{ /** @name Members to access the distance or direction Direction() cannot be assigned directly. Use SetDirection() or Set() instead. This is mandatory to make possible the automatic autonormalization template mechanism. Note that if you have to set both direction and offset it can be more efficient to set them toghether **/ const ScalarType &Offset() const { return _offset; } ScalarType &Offset() { return _offset; } /// sets the origin void SetOffset( const ScalarType &o ) { _offset=o; } const PointType &Direction() const { return _dir; } /// sets the direction void SetDirection( const PointType & dir) { _dir=dir; if (NORM) _dir.Normalize(); } /// sets origin and direction. void Set( const ScalarType & off, const PointType & dir ) { if (NORM) { const ScalarType normFactor = dir.Norm(); this->_dir = dir / normFactor; this->_offset = off / normFactor; } else { this->_offset = off; this->_dir = dir; } } void Set( const PointType & dir, const ScalarType & off) {Set(off,dir);} /// Operator to compare two lines bool operator==(Plane3 const &p) const { return _offset == p._offset && _dir == p._dir; } /// Operator to dispare two lines bool operator!=(Plane3 const &p) const { return _offset != p._offset || _dir != p._dir; } ///Project a point on the plane PointType Projection(const PointType &p) const { ScalarType k = p * _dir - _offset; return p - _dir * k; } /// Function to normalize direction void Normalize() { _dir.Normalize(); } /// Calculates the plane passing through three points (Rename this method) void Init(const PointType &p0, const PointType &p1, const PointType &p2) { _dir = (p2 - p0) ^ (p1 - p0); if(NORM) Normalize(); _offset = p0 * _dir; } /// Calculates the plane passing through a point and the normal (Rename this method inline void Init(const PointType &p0, const PointType &norm) { _dir = norm; _offset = p0 * _dir; } }; // end class Plane3 typedef Plane3 Plane3f; typedef Plane3 Plane3d; ///Distance plane - point (Move this function to somewhere else) template T Distance(const Plane3 &plane, const Point3 &point) { return plane.Direction() * point - plane.Offset(); } ///Distance point-plane (Move this function to somewhere else) template T Distance(const Point3 &point, const Plane3 &plane) { return plane.Direction() * point - plane.Offset(); } } // end namespace #endif qutemol/vcg/vcg/space/intersection3.h0000444000175000017500000007203210632203770016221 0ustar mbamba/**************************************************************************** * VCGLib o o * * Visual and Computer Graphics Library o o * * _ O _ * * Copyright(C) 2004 \/)\/ * * Visual Computing Lab /\/| * * ISTI - Italian National Research Council | * * \ * * All rights reserved. * * * * 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. * * * * 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 (http://www.gnu.org/licenses/gpl.txt) * * for more details. * * * ****************************************************************************/ /**************************************************************************** History $Log: intersection3.h,v $ Revision 1.34 2007/06/08 07:40:40 fiorin Corrected error in the comment to method IntersectionSphereTriangle Revision 1.33 2007/06/07 15:16:39 fiorin Added IntersectionSphereTriangle Revision 1.32 2007/05/29 14:33:29 fiorin Added IntersectionSegmentSphere Revision 1.31 2007/04/16 09:08:15 cignoni commented out non compiling intersectionSpherePlane Revision 1.30 2007/04/10 22:26:47 pietroni IntersectionPlanePlane first parameter is a const Revision 1.29 2007/04/04 23:19:40 pietroni - Changed name of intersection function between plane and triangle from Intersection to IntersectionPlaneTriangle. - Added Intersection_Plane_Sphere function. Revision 1.28 2007/02/21 02:40:52 m_di_benedetto Added const qualifier to bbox parameter in Intersection_Triangle_Box(). Revision 1.27 2006/10/25 16:04:32 pietroni added intersection control between bounding boxes for intersection between segment and triangle function Revision 1.26 2006/09/14 08:39:07 ganovelli Intersection_sphere_sphere added Revision 1.25 2006/06/06 14:35:31 zifnab1974 Changes for compilation on linux AMD64. Some remarks: Linux filenames are case-sensitive. _fileno and _filelength do not exist on linux Revision 1.24 2006/06/01 08:38:02 pietroni Added functions: - Intersection_Segment_Triangle - Intersection_Plane_Box - Intersection_Triangle_Box Revision 1.23 2006/03/29 07:53:36 cignoni Missing ';' (thx Maarten) Revision 1.22 2006/03/20 14:42:49 pietroni IntersectionSegmentPlane and Intersection_Segment_Box functions Added Revision 1.21 2006/01/20 16:35:51 pietroni added Intersection_Segment_Box function Revision 1.20 2005/10/03 16:07:50 ponchio Changed order of functions intersection_line_box and intersectuion_ray_box Revision 1.19 2005/09/30 13:11:39 pietroni corrected 1 compiling error on Ray_Box_Intersection function Revision 1.18 2005/09/29 15:30:10 pietroni Added function RayBoxIntersection, renamed intersection line box from "Intersection" to "Intersection_Line_Box" Revision 1.17 2005/09/29 11:48:00 m_di_benedetto Added functor RayTriangleIntersectionFunctor. Revision 1.16 2005/09/28 19:40:55 m_di_benedetto Added intersection for ray-triangle (with Ray3 type). Revision 1.15 2005/06/29 15:28:31 callieri changed intersection names to more specific to avoid ambiguity Revision 1.14 2005/03/15 11:22:39 ganovelli added intersection between tow planes (porting from old vcg lib) Revision 1.13 2005/01/26 10:03:08 spinelli aggiunta intersect ray-box Revision 1.12 2004/10/13 12:45:51 cignoni Better Doxygen documentation Revision 1.11 2004/09/09 14:41:32 ponchio forgotten typename SEGMENTTYPE::... Revision 1.10 2004/08/09 09:48:43 pietroni correcter .dir to .Direction and .ori in .Origin() Revision 1.9 2004/08/04 20:55:02 pietroni added rey triangle intersections funtions Revision 1.8 2004/07/11 22:08:04 cignoni Added a cast to remove a warning Revision 1.7 2004/05/14 03:14:29 ponchio Fixed some minor bugs Revision 1.6 2004/05/13 23:43:54 ponchio minor bug Revision 1.5 2004/05/05 08:21:55 cignoni syntax errors in inersection plane line. Revision 1.4 2004/05/04 02:37:58 ganovelli Triangle3 replaced by TRIANGLE Segment replaced by EDGETYPE Revision 1.3 2004/04/29 10:48:44 ganovelli error in plane segment corrected Revision 1.2 2004/04/26 12:34:50 ganovelli plane line plane segment triangle triangle added Revision 1.1 2004/04/21 14:22:27 cignoni Initial Commit ****************************************************************************/ #ifndef __VCGLIB_INTERSECTION_3 #define __VCGLIB_INTERSECTION_3 #include #include #include #include #include #include #include #include #include namespace vcg { /** \addtogroup space */ /*@{*/ /** Function computing the intersection between couple of geometric primitives in 3 dimension */ /// interseciton between sphere and line template inline bool IntersectionLineSphere( const Sphere3 & sp, const Line3 & li, Point3 & p0,Point3 & p1 ){ // Per prima cosa si sposta il sistema di riferimento // fino a portare il centro della sfera nell'origine Point3 neworig=li.Origin()-sp.Center(); // poi si risolve il sistema di secondo grado (con maple...) T t1 = li.Direction().X()*li.Direction().X(); T t2 = li.Direction().Y()*li.Direction().Y(); T t3 = li.Direction().Z()*li.Direction().Z(); T t6 = neworig.Y()*li.Direction().Y(); T t7 = neworig.X()*li.Direction().X(); T t8 = neworig.Z()*li.Direction().Z(); T t15 = sp.Radius()*sp.Radius(); T t17 = neworig.Z()*neworig.Z(); T t19 = neworig.Y()*neworig.Y(); T t21 = neworig.X()*neworig.X(); T t28 = T(2.0*t7*t6+2.0*t6*t8+2.0*t7*t8+t1*t15-t1*t17-t1*t19-t2*t21+t2*t15-t2*t17-t3*t21+t3*t15-t3*t19); if(t28<0) return false; T t29 = sqrt(t28); T val0 = 1/(t1+t2+t3)*(-t6-t7-t8+t29); T val1 = 1/(t1+t2+t3)*(-t6-t7-t8-t29); p0=li.P(val0); p1=li.P(val1); return true; } /* * Function computing the intersection between a sphere and a segment. * @param[in] sphere the sphere * @param[in] segment the segment * @param[out] intersection the intersection point, meaningful only if the segment intersects the sphere * \return (0, 1 or 2) the number of intersections between the segment and the sphere. * t1 is a valid intersection only if the returned value is at least 1; * similarly t2 is valid iff the returned value is 2. */ template < class SCALAR_TYPE > inline int IntersectionSegmentSphere(const Sphere3& sphere, const Segment3& segment, Point3 & t0, Point3 & t1) { typedef SCALAR_TYPE ScalarType; typedef typename vcg::Point3< ScalarType > Point3t; Point3t s = segment.P0() - sphere.Center(); Point3t r = segment.P1() - segment.P0(); ScalarType rho2 = sphere.Radius()*sphere.Radius(); ScalarType sr = s*r; ScalarType r_squared_norm = r.SquaredNorm(); ScalarType s_squared_norm = s.SquaredNorm(); ScalarType sigma = sr*sr - r_squared_norm*(s_squared_norm-rho2); if (sigma(lambda1, ScalarType(0.0)); t0 = segment.P0() + r*t_enter; solution_count++; } if (ScalarType(0.0)<=lambda2 && lambda2<=ScalarType(1.0)) { Point3t *pt = (solution_count>0) ? &t1 : &t0; ScalarType t_exit = vcg::math::Min< ScalarType >(lambda2, ScalarType(1.0)); *pt = segment.P0() + r*t_exit; solution_count++; } return solution_count; }; // end of IntersectionSegmentSphere /*! * Compute the intersection between a sphere and a triangle. * \param[in] sphere the input sphere * \param[in] triangle the input triangle * \param[out] witness it is the point on the triangle nearest to the center of the sphere (even when there isn't intersection) * \param[out] res if not null, in the first item is stored the minimum distance between the triangle and the sphere, * while in the second item is stored the penetration depth * \return true iff there is an intersection between the sphere and the triangle */ template < class SCALAR_TYPE > bool IntersectionSphereTriangle(const vcg::Sphere3 < SCALAR_TYPE > & sphere , const vcg::Triangle3< SCALAR_TYPE > & triangle, vcg::Point3 < SCALAR_TYPE > & witness , std::pair< SCALAR_TYPE, SCALAR_TYPE > * res=NULL) { typedef SCALAR_TYPE ScalarType; typedef typename vcg::Point3< ScalarType > Point3t; typedef typename vcg::Triangle3< ScalarType > Triangle3t; bool penetration_detected = false; ScalarType radius = sphere.Radius(); Point3t center = sphere.Center(); Point3t p0 = triangle.P(0)-center; Point3t p1 = triangle.P(1)-center; Point3t p2 = triangle.P(2)-center; Point3t p10 = p1-p0; Point3t p21 = p2-p1; Point3t p20 = p2-p0; ScalarType delta0_p01 = p10*p1; ScalarType delta1_p01 = -p10*p0; ScalarType delta0_p02 = p20*p2; ScalarType delta2_p02 = -p20*p0; ScalarType delta1_p12 = p21*p2; ScalarType delta2_p12 = -p21*p1; // the closest point can be one of the vertices of the triangle if (delta1_p01<=ScalarType(0.0) && delta2_p02<=ScalarType(0.0)) { witness = p0; } else if (delta0_p01<=ScalarType(0.0) && delta2_p12<=ScalarType(0.0)) { witness = p1; } else if (delta0_p02<=ScalarType(0.0) && delta1_p12<=ScalarType(0.0)) { witness = p2; } else { ScalarType temp = p10*p2; ScalarType delta0_p012 = delta0_p01*delta1_p12 + delta2_p12*temp; ScalarType delta1_p012 = delta1_p01*delta0_p02 - delta2_p02*temp; ScalarType delta2_p012 = delta2_p02*delta0_p01 - delta1_p01*(p20*p1); // otherwise, can be a point lying on same edge of the triangle if (delta0_p012<=ScalarType(0.0)) { ScalarType denominator = delta1_p12+delta2_p12; ScalarType mu1 = delta1_p12/denominator; ScalarType mu2 = delta2_p12/denominator; witness = (p1*mu1 + p2*mu2); } else if (delta1_p012<=ScalarType(0.0)) { ScalarType denominator = delta0_p02+delta2_p02; ScalarType mu0 = delta0_p02/denominator; ScalarType mu2 = delta2_p02/denominator; witness = (p0*mu0 + p2*mu2); } else if (delta2_p012<=ScalarType(0.0)) { ScalarType denominator = delta0_p01+delta1_p01; ScalarType mu0 = delta0_p01/denominator; ScalarType mu1 = delta1_p01/denominator; witness = (p0*mu0 + p1*mu1); } else { // or else can be an point internal to the triangle ScalarType denominator = delta0_p012 + delta1_p012 + delta2_p012; ScalarType lambda0 = delta0_p012/denominator; ScalarType lambda1 = delta1_p012/denominator; ScalarType lambda2 = delta2_p012/denominator; witness = p0*lambda0 + p1*lambda1 + p2*lambda2; } } if (res!=NULL) { ScalarType witness_norm = witness.Norm(); res->first = vcg::math::Max< ScalarType >( witness_norm-radius, ScalarType(0.0) ); res->second = vcg::math::Max< ScalarType >( radius-witness_norm, ScalarType(0.0) ); } penetration_detected = (witness.SquaredNorm() <= (radius*radius)); witness += center; return penetration_detected; }; //end of IntersectionSphereTriangle /// intersection between line and plane template inline bool IntersectionLinePlane( const Plane3 & pl, const Line3 & li, Point3 & po){ const T epsilon = T(1e-8); T k = pl.Direction() * li.Direction(); // Compute 'k' factor if( (k > -epsilon) && (k < epsilon)) return false; T r = (pl.Offset() - pl.Direction()*li.Origin())/k; // Compute ray distance po = li.Origin() + li.Direction()*r; return true; } /// intersection between segment and plane template inline bool IntersectionSegmentPlane( const Plane3 & pl, const Segment3 & s, Point3 & po){ vcg::Line3 l; l.Set(s.P0(),s.P1()-s.P0()); l.Normalize(); if (IntersectionLinePlane(pl,l,po)) return((po-s.P0()).Norm()<=(s.P0()-s.P1()).Norm()); return false; } /// intersection between segment and plane template inline bool Intersection( const Plane3 & pl, const SEGMENTTYPE & sg, Point3 & po){ typedef typename SEGMENTTYPE::ScalarType T; const T epsilon = T(1e-8); T k = pl.Direction() * (sg.P1()-sg.P0()); if( (k > -epsilon) && (k < epsilon)) return false; T r = (pl.Offset() - pl.Direction()*sg.P0())/k; // Compute ray distance if( (r<0) || (r > 1.0)) return false; po = sg.P0()*(1-r)+sg.P1() * r; return true; } /// intersection between plane and triangle // not optimal: uses plane-segment intersection (and the fact the two or none edges can be intersected) template inline bool IntersectionPlaneTriangle( const Plane3 & pl, const TRIANGLETYPE & tr, Segment3 & sg){ typedef typename TRIANGLETYPE::ScalarType T; if(Intersection(pl,Segment3(tr.P(0),tr.P(1)),sg.P0())){ if(Intersection(pl,Segment3(tr.P(0),tr.P(2)),sg.P1())) return true; else { Intersection(pl,Segment3(tr.P(1),tr.P(2)),sg.P1()); return true; } }else { if(Intersection(pl,Segment3(tr.P(1),tr.P(2)),sg.P0())) { Intersection(pl,Segment3(tr.P(0),tr.P(2)),sg.P1()); return true; } } return false; } /// intersection between two triangles template inline bool Intersection(const TRIANGLETYPE & t0,const TRIANGLETYPE & t1){ return NoDivTriTriIsect(t0.P0(0),t0.P0(1),t0.P0(2), t1.P0(0),t1.P0(1),t1.P0(2)); } template inline bool Intersection(Point3 V0,Point3 V1,Point3 V2, Point3 U0,Point3 U1,Point3 U2){ return NoDivTriTriIsect(V0,V1,V2,U0,U1,U2); } template inline bool Intersection(Point3 V0,Point3 V1,Point3 V2, Point3 U0,Point3 U1,Point3 U2,int *coplanar, Point3 &isectpt1,Point3 &isectpt2){ return tri_tri_intersect_with_isectline(V0,V1,V2,U0,U1,U2, coplanar,isectpt1,isectpt2); } template inline bool Intersection(const TRIANGLETYPE & t0,const TRIANGLETYPE & t1,bool &coplanar, SEGMENTTYPE & sg){ Point3 ip0,ip1; return tri_tri_intersect_with_isectline(t0.P0(0),t0.P0(1),t0.P0(2), t1.P0(0),t1.P0(1),t1.P0(2), coplanar,sg.P0(),sg.P1() ); } // ray-triangle, gives barycentric coords of intersection and distance along ray template bool Intersection( const Line3 & ray, const Point3 & vert0, const Point3 & vert1, const Point3 & vert2, T & a ,T & b, T & dist) { // small (hum) borders around triangle const T EPSILON2= T(1e-8); const T EPSILON = T(1e-8); Point3 edge1 = vert1 - vert0; Point3 edge2 = vert2 - vert0; // determinant Point3 pvec = ray.Direction() ^ edge2; T det = edge1*pvec; // if determinant is near zero, ray lies in plane of triangle if (fabs(det) < EPSILON) return false; // calculate distance from vert0 to ray origin Point3 tvec = ray.Origin()- vert0; // calculate A parameter and test bounds a = tvec * pvec; if (a < -EPSILON2*det || a > det+det*EPSILON2) return false; // prepare to test V parameter Point3 qvec = tvec ^ edge1; // calculate B parameter and test bounds b = ray.Direction() * qvec ; if (b < -EPSILON2*det || b + a > det+det*EPSILON2) return false; // calculate t, scale parameters, ray intersects triangle dist = edge2 * qvec; if (dist<0) return false; T inv_det = T(1.0) / det; dist *= inv_det; a *= inv_det; b *= inv_det; return true; } // ray-triangle, gives barycentric coords of intersection and distance along ray. // Ray3 type used. template bool Intersection( const Ray3 & ray, const Point3 & vert0, const Point3 & vert1, const Point3 & vert2, T & a ,T & b, T & dist) { // small (hum) borders around triangle const T EPSILON2= T(1e-8); const T EPSILON = T(1e-8); Point3 edge1 = vert1 - vert0; Point3 edge2 = vert2 - vert0; // determinant Point3 pvec = ray.Direction() ^ edge2; T det = edge1*pvec; // if determinant is near zero, ray lies in plane of triangle if (fabs(det) < EPSILON) return false; // calculate distance from vert0 to ray origin Point3 tvec = ray.Origin()- vert0; // calculate A parameter and test bounds a = tvec * pvec; if (a < -EPSILON2*det || a > det+det*EPSILON2) return false; // prepare to test V parameter Point3 qvec = tvec ^ edge1; // calculate B parameter and test bounds b = ray.Direction() * qvec ; if (b < -EPSILON2*det || b + a > det+det*EPSILON2) return false; // calculate t, scale parameters, ray intersects triangle dist = edge2 * qvec; if (dist<0) return false; T inv_det = T(1.0) / det; dist *= inv_det; a *= inv_det; b *= inv_det; return true; } // ray-triangle, gives intersection 3d point and distance along ray template bool Intersection( const Line3 & ray, const Point3 & vert0, const Point3 & vert1, const Point3 & vert2, Point3 & inte) { // small (hum) borders around triangle const T EPSILON2= T(1e-8); const T EPSILON = T(1e-8); Point3 edge1 = vert1 - vert0; Point3 edge2 = vert2 - vert0; // determinant Point3 pvec = ray.Direction() ^ edge2; T det = edge1*pvec; // if determinant is near zero, ray lies in plane of triangle if (fabs(det) < EPSILON) return false; // calculate distance from vert0 to ray origin Point3 tvec = ray.Origin() - vert0; // calculate A parameter and test bounds T a = tvec * pvec; if (a < -EPSILON2*det || a > det+det*EPSILON2) return false; // prepare to test V parameter Point3 qvec = tvec ^ edge1; // calculate B parameter and test bounds T b = ray.Direction() * qvec ; if (b < -EPSILON2*det || b + a > det+det*EPSILON2) return false; // calculate t, scale parameters, ray intersects triangle double dist = edge2 * qvec; //if (dist<0) return false; T inv_det = 1.0 / det; dist *= inv_det; a *= inv_det; b *= inv_det; inte = vert0 + edge1*a + edge2*b; return true; } // line-box template bool Intersection_Line_Box( const Box3 & box, const Line3 & r, Point3 & coord ) { const int NUMDIM = 3; const int RIGHT = 0; const int LEFT = 1; const int MIDDLE = 2; int inside = 1; char quadrant[NUMDIM]; int i; int whichPlane; Point3 maxT,candidatePlane; // Find candidate planes; this loop can be avoided if // rays cast all from the eye(assume perpsective view) for (i=0; i box.max[i]) { quadrant[i] = RIGHT; candidatePlane[i] = box.max[i]; inside = 0; } else { quadrant[i] = MIDDLE; } } // Ray origin inside bounding box if(inside){ coord = r.Origin(); return true; } // Calculate T distances to candidate planes for (i = 0; i < NUMDIM; i++) { if (quadrant[i] != MIDDLE && r.Direction()[i] !=0.) maxT[i] = (candidatePlane[i]-r.Origin()[i]) / r.Direction()[i]; else maxT[i] = -1.; } // Get largest of the maxT's for final choice of intersection whichPlane = 0; for (i = 1; i < NUMDIM; i++) if (maxT[whichPlane] < maxT[i]) whichPlane = i; // Check final candidate actually inside box if (maxT[whichPlane] < 0.) return false; for (i = 0; i < NUMDIM; i++) if (whichPlane != i) { coord[i] = r.Origin()[i] + maxT[whichPlane] *r.Direction()[i]; if (coord[i] < box.min[i] || coord[i] > box.max[i]) return false; } else { coord[i] = candidatePlane[i]; } return true; // ray hits box } // ray-box template bool Intersection_Ray_Box( const Box3 & box, const Ray3 & r, Point3 & coord ) { Line3 l; l.SetOrigin(r.Origin()); l.SetDirection(r.Direction()); return(Intersection_Line_Box(box,l,coord)); } // segment-box return fist intersection found from p0 to p1 template bool Intersection_Segment_Box( const Box3 & box, const Segment3 & s, Point3 & coord ) { //as first perform box-box intersection Box3 test; test.Add(s.P0()); test.Add(s.P1()); if (!test.Collide(box)) return false; else { Line3 l; Point3 dir=s.P1()-s.P0(); dir.Normalize(); l.SetOrigin(s.P0()); l.SetDirection(dir); if(Intersection_Line_Box(box,l,coord)) return (test.IsIn(coord)); return false; } } // segment-box intersection , return number of intersections and intersection points template int Intersection_Segment_Box( const Box3 & box, const Segment3 & s, Point3 & coord0, Point3 & coord1 ) { int num=0; Segment3 test= s; if (Intersection_Segment_Box(box,test,coord0 )) { num++; Point3 swap=test.P0(); test.P0()=test.P1(); test.P1()=swap; if (Intersection_Segment_Box(box,test,coord1 )) num++; } return num; } // segment-triangle intersection template bool Intersection_Segment_Triangle( const vcg::Segment3 & seg, const Point3 & vert0, const Point3 & vert1, const Point3 & vert2, ScalarType & a ,ScalarType & b, ScalarType & dist) { //control intersection of bounding boxes vcg::Box3 bb0,bb1; bb0.Add(seg.P0()); bb0.Add(seg.P1()); bb1.Add(vert0); bb1.Add(vert1); bb1.Add(vert2); Point3 inter; if (!bb0.Collide(bb1)) return false; if (!vcg::Intersection_Segment_Box(bb1,seg,inter)) return false; //first set both directions of ray vcg::Ray3 ray; vcg::Point3 dir; dir=(seg.P1()-seg.P0()); dir.Normalize(); ray.Set(seg.P0(),dir); //then control for each direction the intersection with triangle if ((Intersection(ray,vert0,vert1,vert2,a,b,dist)) ||(Intersection(ray,vert1,vert0,vert2,b,a,dist))) return (dist<(seg.P1()-seg.P0()).Norm()); else return(false); } template bool Intersection_Plane_Box(const vcg::Plane3 &pl, vcg::Box3 &bbox) { typedef typename vcg::Segment3 SegmentType; typedef typename vcg::Point3 CoordType; SegmentType diag[4]; CoordType intersection; //find the 4 diagonals diag[0]=SegmentType(bbox.P(0),bbox.P(7)); diag[1]=SegmentType(bbox.P(1),bbox.P(6)); diag[2]=SegmentType(bbox.P(2),bbox.P(5)); diag[3]=SegmentType(bbox.P(3),bbox.P(4)); ScalarType a,b,dist; for (int i=0;i<3;i++) //call intersection of segment and plane if (vcg::Intersection(pl,diag[i],intersection)) return true; return false; } ///if exists return the center and ardius of circle ///that is the intersectionk between the sphere and //the plane template bool Intersection_Plane_Sphere(const Plane3 &pl, const Sphere3 &sphere, Point3 ¢er, ScalarType &radius) { /* ///set the origin on the center of the sphere vcg::Plane3 pl1; vcg::Point3 p_plane=pl.Direction()*pl.Offset(); vcg::Point3 p_plane=p_plane-sphere.Center(); ///set again the plane pl1.Set(p_plane,pl.Direction()); ///test d must be positive d=pl1.Offset(); vcg::Point3 n=pl1.Direction(); ///invert d if is <0 if (d<0) { n=-n; d=-d; } ///no intersection occour if (d>r) return false; else { ///calculate center and translate in back center=n*d; center+=sphere.Center(); radius=math::Sqrt((r*r)-(d*d)); } */ assert(0); return true; } template bool Intersection_Triangle_Box(const vcg::Box3 &bbox, const vcg::Point3 &p0, const vcg::Point3 &p1, const vcg::Point3 &p2) { typedef typename vcg::Point3 CoordType; CoordType intersection; /// control bounding box collision vcg::Box3 test; test.SetNull(); test.Add(p0); test.Add(p1); test.Add(p2); if (!test.Collide(bbox)) return false; /// control if each point is inside the bouding box if ((bbox.IsIn(p0))||(bbox.IsIn(p1))||(bbox.IsIn(p2))) return true; /////control plane of the triangle with bbox //vcg::Plane3 plTri=vcg::Plane3(); //plTri.Init(p0,p1,p2); //if (!Intersection_Plane_Box(plTri,bbox)) // return false; ///then control intersection of segments with box if (Intersection_Segment_Box(bbox,vcg::Segment3(p0,p1),intersection)|| Intersection_Segment_Box(bbox,vcg::Segment3(p1,p2),intersection)|| Intersection_Segment_Box(bbox,vcg::Segment3(p2,p0),intersection)) return true; ///control intersection of diagonal of the cube with triangle Segment3 diag[4]; diag[0]=Segment3(bbox.P(0),bbox.P(7)); diag[1]=Segment3(bbox.P(1),bbox.P(6)); diag[2]=Segment3(bbox.P(2),bbox.P(5)); diag[3]=Segment3(bbox.P(3),bbox.P(4)); ScalarType a,b,dist; for (int i=0;i<3;i++) if (Intersection_Segment_Triangle(diag[i],p0,p1,p2,a,b,dist)) return true; return false; } template bool Intersection_Sphere_Sphere( const SphereType & s0,const SphereType & s1){ return (s0.Center()-s1.Center()).SquaredNorm() < (s0.Radius()+s1.Radius())*(s0.Radius()+s1.Radius()); } template bool IntersectionPlanePlane (const Plane3 & plane0, const Plane3 & plane1, Line3 & line) { // If Cross(N0,N1) is zero, then either planes are parallel and separated // or the same plane. In both cases, 'false' is returned. Otherwise, // the intersection line is // // L(t) = t*Cross(N0,N1) + c0*N0 + c1*N1 // // for some coefficients c0 and c1 and for t any real number (the line // parameter). Taking dot products with the normals, // // d0 = Dot(N0,L) = c0*Dot(N0,N0) + c1*Dot(N0,N1) // d1 = Dot(N1,L) = c0*Dot(N0,N1) + c1*Dot(N1,N1) // // which are two equations in two unknowns. The solution is // // c0 = (Dot(N1,N1)*d0 - Dot(N0,N1)*d1)/det // c1 = (Dot(N0,N0)*d1 - Dot(N0,N1)*d0)/det // // where det = Dot(N0,N0)*Dot(N1,N1)-Dot(N0,N1)^2. T n00 = plane0.Direction()*plane0.Direction(); T n01 = plane0.Direction()*plane1.Direction(); T n11 = plane1.Direction()*plane1.Direction(); T det = n00*n11-n01*n01; const T tolerance = (T)(1e-06f); if ( math::Abs(det) < tolerance ) return false; T invDet = 1.0f/det; T c0 = (n11*plane0.Offset() - n01*plane1.Offset())*invDet; T c1 = (n00*plane1.Offset() - n01*plane0.Offset())*invDet; line.SetDirection(plane0.Direction()^plane1.Direction()); line.SetOrigin(plane0.Direction()*c0+ plane1.Direction()*c1); return true; } // Ray-Triangle Functor template class RayTriangleIntersectionFunctor { public: template inline bool operator () (const TRIANGLETYPE & f, const Ray3 & ray, SCALARTYPE & t) { typedef SCALARTYPE ScalarType; ScalarType a; ScalarType b; bool bret = Intersection(ray, Point3::Construct(f.P(0)), Point3::Construct(f.P(1)), Point3::Construct(f.P(2)), a, b, t); if (BACKFACETEST) { if (!bret) { bret = Intersection(ray, Point3::Construct(f.P(0)), Point3::Construct(f.P(2)), Point3::Construct(f.P(1)), a, b, t); } } return (bret); } }; /*@}*/ } // end namespace #endif qutemol/vcg/vcg/space/line3.h0000444000175000017500000001742510220324021014431 0ustar mbamba/**************************************************************************** * VCGLib o o * * Visual and Computer Graphics Library o o * * _ O _ * * Copyright(C) 2004 \/)\/ * * Visual Computing Lab /\/| * * ISTI - Italian National Research Council | * * \ * * All rights reserved. * * * * 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. * * * * 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 (http://www.gnu.org/licenses/gpl.txt) * * for more details. * * * ****************************************************************************/ /**************************************************************************** History $Log: line3.h,v $ Revision 1.9 2005/03/23 17:32:01 pietroni corrected 1 bug in distance function (use of templated coords type) Revision 1.8 2004/05/14 03:14:04 ponchio Added Distance Revision 1.7 2004/05/10 10:58:35 ganovelli name of the constructor changed from LineType to Line3 Revision 1.6 2004/03/11 11:47:20 tarini minor updates, corrections, added documentations, etc. Revision 1.5 2004/03/10 15:27:48 tarini added Normalized flag Revision 1.1 2004/03/08 16:15:48 tarini first version (tarini) ****************************************************************************/ #ifndef __VCGLIB_LINE3 #define __VCGLIB_LINE3 #include namespace vcg { /** \addtogroup space */ /*@{*/ /** Templated class for 3D lines. This is the class for infinite lines in 3D space. A Line is stored just as two Point3: an origin and a direction (not necessarily normalized). @param LineScalarType (template parameter) Specifies the type of scalar used to represent coords. @param NORM: if on, the direction is always Normalized */ template class Line3 { public: /// The scalar type typedef LineScalarType ScalarType; /// The point type typedef Point3 PointType; /// The line type typedef Line3 LineType; private: /// Origin PointType _ori; /// Direction (not necessarily normalized, unless so specified by NORM) PointType _dir; public: //@{ /** @name Members to access the origin or direction Direction() cannot be assigned directly. Use SetDirection() or Set() instead. **/ /// inline const PointType &Origin() const { return _ori; } inline PointType &Origin() { return _ori; } inline const PointType &Direction() const { return _dir; } /// sets the origin inline void SetOrigin( const PointType & ori ) { _ori=ori; } /// sets the direction inline void SetDirection( const PointType & dir) { _dir=dir; if (NORM) _dir.Normalize(); } /// sets origin and direction. inline void Set( const PointType & ori, const PointType & dir ) { SetOrigin(ori); SetDirection(dir); } //@} //@{ /** @name Constructors **/ /// The empty constructor Line3() {}; /// The (origin, direction) constructor Line3(const PointType &ori, const PointType &dir) {SetOrigin(ori); SetDirection(dir);}; //@} /// Operator to compare two lines inline bool operator == ( LineType const & p ) const { return _ori==p._ori && _dir==p._dir; } /// Operator to dispare two lines inline bool operator != ( LineType const & p ) const { return _ori!=p._ori || _dir!=p._dir; } /// Projects a point on the line inline ScalarType Projection( const PointType &p ) const { if (NORM) return ScalarType((p-_ori)*_dir); else return ScalarType((p-_ori)*_dir/_dir.SquaredNorm()); } /// returns wheter this type is normalized or not static bool IsNormalized() {return NORM;}; /// calculates the point of parameter t on the line. inline PointType P( const ScalarType t ) const { return _ori + _dir * t; } /// normalizes direction field (returns a Normalized Line) inline Line3 &Normalize() { if (!NORM) _dir.Normalize(); return *((Line3*)this);} /// normalizes direction field (returns a Normalized Line) - static version static Line3 &Normalize(LineType &p) { p.Normalize(); return *((Line3*)(&p));} /// importer for different line types (with any scalar type or normalization beaviour) template inline void Import( const Line3 & b ) { _ori.Import( b.Origin() ); _dir.Import( b.Direction() ); if ((NORM) && (!K)) _dir.Normalize(); //printf("(=)%c->%c ",(!NORM)?'N':'n', NORM?'N':'n'); } /// constructs a new line importing it from an existing one template static LineType Construct( const Line3 & b ) { LineType res; res.Import(b); return res; } PointType ClosestPoint(const PointType & p) const{ return P(Projection(p)); } /// flips the line inline void Flip(){ _dir=-_dir; }; //@{ /** @name Linearity for 3d lines (operators +, -, *, /) so a line can be set as a linear combination of several lines. Note that the result of any operation returns a non-normalized line; however, the command r0 = r1*a + r2*b is licit even if r0,r1,r2 are normalized lines, as the normalization will take place within the final assignement operation. **/ inline Line3 operator + ( LineType const & p) const {return Line3 ( _ori+p.Origin(), _dir+p.Direction() );} inline Line3 operator - ( LineType const & p) const {return Line3 ( _ori-p.Origin(), _dir-p.Direction() );} inline Line3 operator * ( const ScalarType s ) const {return Line3 ( _ori*s, _dir*s );} inline Line3 operator / ( const ScalarType s ) const {ScalarType s0=((ScalarType)1.0)/s; return LineType( _ori*s0, _dir*s0 );} //@} //@{ /** @name Automatic normalized to non-normalized "Line3dN r0 = r1" is equivalent to "Line3dN r0 = r1.Normalize()" if r1 is a Line3d **/ /// copy constructor that takes opposite beaviour Line3 (const Line3 &r) { Import(r); }; /// assignment inline LineType & operator = ( Line3 const &r) { Import(r); return *this; }; //@} }; // end class definition typedef Line3 Line3s; typedef Line3 Line3i; typedef Line3 Line3f; typedef Line3 Line3d; typedef Line3 Line3sN; typedef Line3 Line3iN; typedef Line3 Line3fN; typedef Line3 Line3dN; /// returns closest point template Point3 ClosestPoint( Line3 l, const Point3 & p) { return l.P(l.Projection(p)); } template ScalarType Distance(const Line3 &l, const Point3 &p) { Point3 o = l.ClosestPoint(p); return (o - p).Norm(); } /*@}*/ } // end namespace #endif qutemol/vcg/vcg/space/segment2.h0000444000175000017500000001335110546750234015161 0ustar mbamba/**************************************************************************** * VCGLib o o * * Visual and Computer Graphics Library o o * * _ O _ * * Copyright(C) 2004 \/)\/ * * Visual Computing Lab /\/| * * ISTI - Italian National Research Council | * * \ * * All rights reserved. * * * * 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. * * * * 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 (http://www.gnu.org/licenses/gpl.txt) * * for more details. * * * ****************************************************************************/ /**************************************************************************** History ****************************************************************************/ #ifndef __VCGLIB_SEGMENT2 #define __VCGLIB_SEGMENT2 #include #include #include namespace vcg { /** \addtogroup space */ /*@{*/ /** Templated class for 3D segment. This is the class for a segment in 3D space. A Segment is stored just as its two extrema (Point3). @param SegmentScalarType (template parameter) Specifies the type of scalar used to represent coords. */ template class Segment2 { public: /// The scalar type typedef SegmentScalarType ScalarType; /// The point type typedef Point2 PointType; /// The point type typedef Segment2 SegmentType; private: /// _extrema PointType _p0,_p1; public: /// Members to access either extrema inline const PointType &P0() const { return _p0; } inline const PointType &P1() const { return _p1; } inline PointType &P0() { return _p0; } inline PointType &P1() { return _p1; } /// The empty constructor Segment2() {}; /// The (a,b) constructor Segment2(const PointType &a, const PointType &b) { _p0=a; _p1=b; }; /// Operator to compare segments inline bool operator == ( SegmentType const & p ) const { return _p0==p._p0 && _p1==p._p1; } /// Operator to dispare segments inline bool operator != ( SegmentType const & p ) const { return _p0!=p._p0 || _p1!=p._p1; } /// initializes the segment with its extrema void Set( const PointType &a, const PointType &b) { _p0=a; _p1=b;} /// calculates the point of parameter t on the segment. /// if t is in [0..1] returned point is inside the segment inline PointType P( const ScalarType t ) const { return _p0 + (_p1 - _p0) * t; } /// return the middle point inline PointType MidPoint( ) const { return ( _p0 + _p1) / ScalarType(2.0) ; } /// return the bounding box inline Box2 BBox( ) const { Box2 t; t.Add(_p0); t.Add(_p1); return t; } /// returns segment length ScalarType Length() { return (_p0 - _p1).Norm(); } /// return segment squared lenght ScalarType SquaredLength() { return (_p0 - _p1).SquaredNorm(); } /// flips: a-b becomes b-a void Flip() { PointType t=_p0; _p0=_p1; _p1=t; } /// importer for different line types template inline void Import( const Segment2 & b ) { _p0.Import( b.P0() ); _p1.Import( b.P1() ); } /// copy constructor (builds a new segment importing an existing one) template static SegmentType Construct( const Segment2 & b ) { return SegmentType(PointType::Construct(b.P0()), PointType::Construct(b.P1()));} //@{ /** @name Linearity for 3d segments (operators +, -, *, /) **/ inline SegmentType operator + ( SegmentType const & p) const {return SegmentType( _p0+p.P0(), _p1+p.P1() );} inline SegmentType operator - ( SegmentType const & p) const {return SegmentType( _p0-p.P0(), _p1-p.P1() );} inline SegmentType operator * ( const ScalarType s ) const {return SegmentType( _p0*s, _p1*s );} inline SegmentType operator / ( const ScalarType s ) const {ScalarType s0=((ScalarType)1.0)/s; return SegmentType( _p0*s0, _p1*s0 );} //@} }; // end class definition typedef Segment2 Segment2s; typedef Segment2 Segment2i; typedef Segment2 Segment2f; typedef Segment2 Segment2d; template Point2 ClosestPoint( Segment2 s, const Point2 & p) { vcg::Line2 l; l.Set(s.P0(),s.P1()-s.P0()); l.Normalize(); Point2 clos=vcg::ClosestPoint(l,p) ;//attention to call vcg::Box2 b; b.Add(s.P0()); b.Add(s.P1()); if (b.IsIn(clos)) return clos; else { ScalarType d0=(s.P0()-p).Norm(); ScalarType d1=(s.P1()-p).Norm(); if (d01) return s.P0(); return s.P(t);*/ } /*@}*/ } // end namespace #endif qutemol/vcg/vcg/space/fitting3.h0000444000175000017500000001167210324176345015167 0ustar mbamba/**************************************************************************** * VCGLib o o * * Visual and Computer Graphics Library o o * * _ O _ * * Copyright(C) 2004 \/)\/ * * Visual Computing Lab /\/| * * ISTI - Italian National Research Council | * * \ * * All rights reserved. * * * * 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. * * * * 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 (http://www.gnu.org/licenses/gpl.txt) * * for more details. * * * ****************************************************************************/ /**************************************************************************** History $Log: fitting3.h,v $ Revision 1.3 2005/10/15 12:58:13 ponchio Typename... as usual Revision 1.2 2005/10/13 14:59:57 ganovelli versione con svd Revision 1.1 2005/03/14 17:04:24 ganovelli created ****************************************************************************/ #ifndef __VCGLIB_FITTING3 #define __VCGLIB_FITTING3 #include #include #include #include #include namespace vcg { template bool PlaneFittingPoints( std::vector< Point3 > & samples,Plane3 &p){ int j; Matrix44 m;m.SetZero(); typename std::vector< Point3 > ::iterator i; Point3 c; c.Zero(); for(i = samples.begin(); i != samples.end(); ++i) c+=*i; c/=samples.size(); for(i = samples.begin(); i != samples.end(); ++i){ Point3 p = (*i)-c; for(j = 0 ; j < 3;++j) *(Point3*)&m[j][0] += p * p[j]; } m[0][3]= m[1][3]=m[2][3]=0.0; m[3][3]= 1.0; m[3][0]= m[3][1]=m[3][2]=0.0; int n; Matrix44 res; Point4 e; Point3 d; Jacobi(m,e,res,n); S mx = fabs(e[0]); int mxi=0; for(j=1; j < 3; ++j) if( (fabs(e[j]) < mx) ) {mx=fabs(e[j]); mxi = j;} d[0]=res[0][mxi]; d[1]=res[1][mxi]; d[2]=res[2][mxi]; p.SetOffset(c*d/d.Norm()); p.SetDirection(d/d.Norm()); return true; } template inline double FIT_VExp( const Point3 & x, const int i ) { assert(i>=0); assert(i<4); if(i==0) return 1; else return x[i-1]; } /** Fitting di piani: trova il piano che meglio approssima l'insieme di punti dato */ template bool PlaneFittingPointsOld( std::vector< Point3 > & samples, Plane3 & p ) { Point3 d; const int N = 4; S P[N][N]; // A = s' . s S U[N][N]; int i,j,k,n; n = (int)samples.size(); if(n<3) return false; //printf("\n p_prima: %f %f %f %f \n",p.Offset(),p.Direction()[0],p.Direction()[1],p.Direction()[2]); for(i=0;i m; for(i=0;i s;s.Zero(); // // s.Normalize(); // printf("\n RES %f %f %f %f \n",s[0],s[1],s[2],s[3]); //printf("\n GJ \n"); // for(i=0;i(U[1][2]*U[2][3]-U[1][3],-U[2][3],1).Norm(); p.SetDirection(Point3(U[1][2]*U[2][3]-U[1][3],-U[2][3],1)); p.SetOffset(-(U[0][2]*U[2][3]-U[0][3]+U[0][1]*U[1][3]-U[0][1]*U[1][2]*U[2][3])/norm); //printf("\n p: %f %f %f %f \n",p.Offset(),p.Direction()[0],p.Direction()[1],p.Direction()[2]); return true; } } // end namespace #endif qutemol/vcg/vcg/space/point3.h0000444000175000017500000003623310526631617014656 0ustar mbamba/**************************************************************************** * VCGLib o o * * Visual and Computer Graphics Library o o * * _ O _ * * Copyright(C) 2004 \/)\/ * * Visual Computing Lab /\/| * * ISTI - Italian National Research Council | * * \ * * All rights reserved. * * * * 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. * * * * 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 (http://www.gnu.org/licenses/gpl.txt) * * for more details. * * * ****************************************************************************/ /**************************************************************************** History $Log: point3.h,v $ Revision 1.27 2006/11/15 15:34:39 corsini fix polar coordinates Revision 1.26 2006/11/13 13:03:45 ponchio Added GetBBox in Point3 (declaration) the body of the function is in box3.h Revision 1.25 2006/10/13 12:59:24 cignoni Added **explicit** constructor from three coords of a different scalartype Revision 1.24 2006/09/28 13:37:35 m_di_benedetto added non const * V() Revision 1.23 2005/11/09 16:11:55 cignoni Added Abs and LowClampToZero Revision 1.22 2005/09/14 14:09:21 m_di_benedetto Added specialized Convert() for the same scalar type. Revision 1.21 2005/05/06 14:45:33 spinelli cambiato parentesi nel costruttore di GetUV per rendere compatibile tale costruttore con MVC e borland Revision 1.20 2005/04/27 16:05:19 callieri line 466, added parentesis on default value creator getUV [borland] Revision 1.19 2004/11/09 15:49:07 ganovelli added GetUV Revision 1.18 2004/10/13 12:45:51 cignoni Better Doxygen documentation Revision 1.17 2004/09/10 14:01:40 cignoni Added polar to cartesian Revision 1.16 2004/03/21 17:14:56 ponchio Added a math:: Revision 1.15 2004/03/07 22:45:32 cignoni Moved quality and normal functions to the triangle class. Revision 1.14 2004/03/05 17:55:01 tarini errorino: upper case in Zero() Revision 1.13 2004/03/03 14:22:48 cignoni Yet against cr lf mismatch Revision 1.12 2004/02/23 23:42:26 cignoni Translated comments, removed unusued stuff. corrected linefeed/cr Revision 1.11 2004/02/19 16:12:28 cignoni cr lf mismatch 2 Revision 1.10 2004/02/19 16:06:24 cignoni cr lf mismatch Revision 1.8 2004/02/19 15:13:40 cignoni corrected sqrt and added doxygen groups Revision 1.7 2004/02/17 02:08:47 cignoni Di prova... Revision 1.6 2004/02/15 23:35:47 cignoni Cambiato nome type template in accordo alla styleguide Revision 1.5 2004/02/10 01:07:15 cignoni Edited Comments and GPL license Revision 1.4 2004/02/09 13:48:02 cignoni Edited doxygen comments ****************************************************************************/ #ifndef __VCGLIB_POINT3 #define __VCGLIB_POINT3 #include #include namespace vcg { /** \addtogroup space */ /*@{*/ /** The templated class for representing a point in 3D space. The class is templated over the ScalarType class that is used to represent coordinates. All the usual operator overloading (* + - ...) is present. */ template class Box3; template class Point3 { protected: /// The only data member. Hidden to user. P3ScalarType _v[3]; public: typedef P3ScalarType ScalarType; enum {Dimension = 3}; //@{ /** @name Standard Constructors and Initializers No casting operators have been introduced to avoid automatic unattended (and costly) conversion between different point types **/ inline Point3 () { } inline Point3 ( const P3ScalarType nx, const P3ScalarType ny, const P3ScalarType nz ) { _v[0] = nx; _v[1] = ny; _v[2] = nz; } inline Point3 ( Point3 const & p ) { _v[0]= p._v[0]; _v[1]= p._v[1]; _v[2]= p._v[2]; } inline Point3 ( const P3ScalarType nv[3] ) { _v[0] = nv[0]; _v[1] = nv[1]; _v[2] = nv[2]; } inline Point3 & operator =( Point3 const & p ) { _v[0]= p._v[0]; _v[1]= p._v[1]; _v[2]= p._v[2]; return *this; } inline void Zero() { _v[0] = 0; _v[1] = 0; _v[2] = 0; } /// Padding function: give a default 0 value to all the elements that are not in the [0..2] range. /// Useful for managing in a consistent way object that could have point2 / point3 / point4 inline P3ScalarType Ext( const int i ) const { if(i>=0 && i<=2) return _v[i]; else return 0; } template inline void Import( const Point3 & b ) { _v[0] = P3ScalarType(b[0]); _v[1] = P3ScalarType(b[1]); _v[2] = P3ScalarType(b[2]); } template static inline Point3 Construct( const Point3 & b ) { return Point3(P3ScalarType(b[0]),P3ScalarType(b[1]),P3ScalarType(b[2])); } template static inline Point3 Construct( const Q & P0, const Q & P1, const Q & P2) { return Point3(P3ScalarType(P0),P3ScalarType(P1),P3ScalarType(P2)); } static inline Point3 Construct( const Point3 & b ) { return b; } //@} //@{ /** @name Data Access. access to data is done by overloading of [] or explicit naming of coords (x,y,z)**/ inline P3ScalarType & operator [] ( const int i ) { assert(i>=0 && i<3); return _v[i]; } inline const P3ScalarType & operator [] ( const int i ) const { assert(i>=0 && i<3); return _v[i]; } inline const P3ScalarType &X() const { return _v[0]; } inline const P3ScalarType &Y() const { return _v[1]; } inline const P3ScalarType &Z() const { return _v[2]; } inline P3ScalarType &X() { return _v[0]; } inline P3ScalarType &Y() { return _v[1]; } inline P3ScalarType &Z() { return _v[2]; } inline const P3ScalarType * V() const { return _v; } inline P3ScalarType * V() { return _v; } inline P3ScalarType & V( const int i ) { assert(i>=0 && i<3); return _v[i]; } inline const P3ScalarType & V( const int i ) const { assert(i>=0 && i<3); return _v[i]; } //@} //@{ /** @name Classical overloading of operators Note **/ inline Point3 operator + ( Point3 const & p) const { return Point3( _v[0]+p._v[0], _v[1]+p._v[1], _v[2]+p._v[2] ); } inline Point3 operator - ( Point3 const & p) const { return Point3( _v[0]-p._v[0], _v[1]-p._v[1], _v[2]-p._v[2] ); } inline Point3 operator * ( const P3ScalarType s ) const { return Point3( _v[0]*s, _v[1]*s, _v[2]*s ); } inline Point3 operator / ( const P3ScalarType s ) const { return Point3( _v[0]/s, _v[1]/s, _v[2]/s ); } /// Dot product inline P3ScalarType operator * ( Point3 const & p ) const { return ( _v[0]*p._v[0] + _v[1]*p._v[1] + _v[2]*p._v[2] ); } /// Cross product inline Point3 operator ^ ( Point3 const & p ) const { return Point3 ( _v[1]*p._v[2] - _v[2]*p._v[1], _v[2]*p._v[0] - _v[0]*p._v[2], _v[0]*p._v[1] - _v[1]*p._v[0] ); } inline Point3 & operator += ( Point3 const & p) { _v[0] += p._v[0]; _v[1] += p._v[1]; _v[2] += p._v[2]; return *this; } inline Point3 & operator -= ( Point3 const & p) { _v[0] -= p._v[0]; _v[1] -= p._v[1]; _v[2] -= p._v[2]; return *this; } inline Point3 & operator *= ( const P3ScalarType s ) { _v[0] *= s; _v[1] *= s; _v[2] *= s; return *this; } inline Point3 & operator /= ( const P3ScalarType s ) { _v[0] /= s; _v[1] /= s; _v[2] /= s; return *this; } // Norme inline P3ScalarType Norm() const { return math::Sqrt( _v[0]*_v[0] + _v[1]*_v[1] + _v[2]*_v[2] ); } inline P3ScalarType SquaredNorm() const { return ( _v[0]*_v[0] + _v[1]*_v[1] + _v[2]*_v[2] ); } // Scalatura differenziata inline Point3 & Scale( const P3ScalarType sx, const P3ScalarType sy, const P3ScalarType sz ) { _v[0] *= sx; _v[1] *= sy; _v[2] *= sz; return *this; } inline Point3 & Scale( const Point3 & p ) { _v[0] *= p._v[0]; _v[1] *= p._v[1]; _v[2] *= p._v[2]; return *this; } // Normalizzazione inline Point3 & Normalize() { P3ScalarType n = math::Sqrt(_v[0]*_v[0] + _v[1]*_v[1] + _v[2]*_v[2]); if(n>0.0) { _v[0] /= n; _v[1] /= n; _v[2] /= n; } return *this; } /** * Convert to polar coordinates from cartesian coordinates. * * Theta is the azimuth angle and ranges between [0, 360) degrees. * Phi is the elevation angle (not the polar angle) and ranges between [-90, 90] degrees. * * /note Note that instead of the classical polar angle, which ranges between * 0 and 180 degrees we opt for the elevation angle to obtain a more * intuitive spherical coordinate system. */ void ToPolar(P3ScalarType &ro, P3ScalarType &theta, P3ScalarType &phi) const { ro = Norm(); theta = (P3ScalarType)atan2(_v[2], _v[0]); phi = (P3ScalarType)asin(_v[1]/ro); } /** * Convert from polar coordinates to cartesian coordinates. * * Theta is the azimuth angle and ranges between [0, 360) degrees. * Phi is the elevation angle (not the polar angle) and ranges between [-90, 90] degrees. * * \note Note that instead of the classical polar angle, which ranges between * 0 and 180 degrees, we opt for the elevation angle to obtain a more * intuitive spherical coordinate system. */ void FromPolar(const P3ScalarType &ro, const P3ScalarType &theta, const P3ScalarType &phi) { _v[0]= ro*cos(theta)*cos(phi); _v[1]= ro*sin(phi); _v[2]= ro*sin(theta)*cos(phi); } Box3 GetBBox(Box3 &bb) const; //@} //@{ /** @name Comparison Operators. Note that the reverse z prioritized ordering, useful in many situations. **/ inline bool operator == ( Point3 const & p ) const { return _v[0]==p._v[0] && _v[1]==p._v[1] && _v[2]==p._v[2]; } inline bool operator != ( Point3 const & p ) const { return _v[0]!=p._v[0] || _v[1]!=p._v[1] || _v[2]!=p._v[2]; } inline bool operator < ( Point3 const & p ) const { return (_v[2]!=p._v[2])?(_v[2] ( Point3 const & p ) const { return (_v[2]!=p._v[2])?(_v[2]>p._v[2]): (_v[1]!=p._v[1])?(_v[1]>p._v[1]): (_v[0]>p._v[0]); } inline bool operator <= ( Point3 const & p ) const { return (_v[2]!=p._v[2])?(_v[2]< p._v[2]): (_v[1]!=p._v[1])?(_v[1]< p._v[1]): (_v[0]<=p._v[0]); } inline bool operator >= ( Point3 const & p ) const { return (_v[2]!=p._v[2])?(_v[2]> p._v[2]): (_v[1]!=p._v[1])?(_v[1]> p._v[1]): (_v[0]>=p._v[0]); } inline Point3 operator - () const { return Point3 ( -_v[0], -_v[1], -_v[2] ); } //@} }; // end class definition template inline P3ScalarType Angle( Point3 const & p1, Point3 const & p2 ) { P3ScalarType w = p1.Norm()*p2.Norm(); if(w==0) return -1; P3ScalarType t = (p1*p2)/w; if(t>1) t = 1; else if(t<-1) t = -1; return (P3ScalarType) acos(t); } // versione uguale alla precedente ma che assume che i due vettori sono unitari template inline P3ScalarType AngleN( Point3 const & p1, Point3 const & p2 ) { P3ScalarType w = p1*p2; if(w>1) w = 1; else if(w<-1) w=-1; return (P3ScalarType) acos(w); } template inline P3ScalarType Norm( Point3 const & p ) { return p.Norm(); } template inline P3ScalarType SquaredNorm( Point3 const & p ) { return p.SquaredNorm(); } template inline Point3 & Normalize( Point3 & p ) { p.Normalize(); return p; } template inline P3ScalarType Distance( Point3 const & p1,Point3 const & p2 ) { return (p1-p2).Norm(); } template inline P3ScalarType SquaredDistance( Point3 const & p1,Point3 const & p2 ) { return (p1-p2).SquaredNorm(); } // Dot product preciso numericamente (solo double!!) // Implementazione: si sommano i prodotti per ordine di esponente // (prima le piu' grandi) template double stable_dot ( Point3 const & p0, Point3 const & p1 ) { P3ScalarType k0 = p0._v[0]*p1._v[0]; P3ScalarType k1 = p0._v[1]*p1._v[1]; P3ScalarType k2 = p0._v[2]*p1._v[2]; int exp0,exp1,exp2; frexp( double(k0), &exp0 ); frexp( double(k1), &exp1 ); frexp( double(k2), &exp2 ); if( exp0 P3ScalarType PSDist( const Point3 & p, const Point3 & v1, const Point3 & v2, Point3 & q ) { Point3 e = v2-v1; P3ScalarType t = ((p-v1)*e)/e.SquaredNorm(); if(t<0) t = 0; else if(t>1) t = 1; q = v1+e*t; return Distance(p,q); } template void GetUV( Point3 &n,Point3 &u, Point3 &v, Point3 up=(Point3(0,1,0)) ) { n.Normalize(); const double LocEps=double(1e-7); u=n^up; double len = u.Norm(); if(len < LocEps) { if(fabs(n[0])(1,0,0); // x is the min else up=Point3(0,0,1); // z is the min }else { if(fabs(n[1])(0,1,0); // y is the min else up=Point3(0,0,1); // z is the min } u=n^up; } u.Normalize(); v=n^u; v.Normalize(); Point3 uv=u^v; } template inline Point3 Abs(const Point3 & p) { return (Point3(math::Abs(p[0]), math::Abs(p[1]), math::Abs(p[2]))); } // probably a more uniform naming should be defined... template inline Point3 LowClampToZero(const Point3 & p) { return (Point3(math::Max(p[0], (SCALARTYPE)0), math::Max(p[1], (SCALARTYPE)0), math::Max(p[2], (SCALARTYPE)0))); } typedef Point3 Point3s; typedef Point3 Point3i; typedef Point3 Point3f; typedef Point3 Point3d; /*@}*/ } // end namespace #endif qutemol/vcg/vcg/space/triangle3.h0000444000175000017500000003504110776373167015340 0ustar mbamba/**************************************************************************** * VCGLib o o * * Visual and Computer Graphics Library o o * * _ O _ * * Copyright(C) 2004 \/)\/ * * Visual Computing Lab /\/| * * ISTI - Italian National Research Council | * * \ * * All rights reserved. * * * * 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. * * * * 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 (http://www.gnu.org/licenses/gpl.txt) * * for more details. * * * ****************************************************************************/ /**************************************************************************** History $Log: triangle3.h,v $ Revision 1.22 2008/04/07 10:24:55 pietroni added default constructor Revision 1.21 2007/12/02 07:39:19 cignoni disambiguated sqrt call Revision 1.20 2007/11/26 14:11:38 ponchio Added Mean Ratio metric for triangle quality. Revision 1.19 2007/11/19 17:04:05 ponchio QualityRadii values fixed. Revision 1.18 2007/11/18 19:12:54 ponchio Typo (missing comma). Revision 1.17 2007/11/16 14:22:35 ponchio Added qualityRadii: computes inradius /circumradius. (ok the name is ugly...) Revision 1.16 2007/10/10 15:11:30 ponchio Added Circumcenter function. Revision 1.15 2007/05/10 09:31:15 cignoni Corrected InterpolationParameters invocation Revision 1.14 2007/05/04 16:33:27 ganovelli moved InterpolationParamaters out the class Triangle Revision 1.13 2007/04/04 23:23:55 pietroni - corrected and renamed distance to point ( function TrianglePointDistance) Revision 1.12 2007/01/13 00:25:23 cignoni Added (Normalized) Normal version templated on three points (instead forcing the creation of a new triangle) Revision 1.11 2006/10/17 06:51:33 fiorin In function Barycenter, replaced calls to (the inexistent) cP(i) with P(i) Revision 1.10 2006/10/10 09:33:47 cignoni added quality for triangle wrap Revision 1.9 2006/09/14 08:44:07 ganovelli changed t.P(*) in t.cP() nella funzione Barycenter Revision 1.8 2006/06/01 08:38:58 pietroni added PointDistance function Revision 1.7 2006/03/01 15:35:09 pietroni compiled InterspolationParameters function Revision 1.6 2006/01/22 10:00:56 cignoni Very Important Change: Area->DoubleArea (and no more Area function) Revision 1.5 2005/09/23 14:18:27 ganovelli added constructor Revision 1.4 2005/04/14 11:35:09 ponchio *** empty log message *** Revision 1.3 2004/07/15 13:22:37 cignoni Added the standard P() access function instead of the shortcut P0() Revision 1.2 2004/07/15 10:17:42 pietroni correct access to point funtions call in usage of triangle3 (ex. t.P(0) in t.P0(0)) Revision 1.1 2004/03/08 01:13:31 cignoni Initial commit ****************************************************************************/ #ifndef __VCG_TRIANGLE3 #define __VCG_TRIANGLE3 #include #include #include namespace vcg { /** \addtogroup space */ /*@{*/ /** Templated class for storing a generic triangle in a 3D space. Note the relation with the Face class of TriMesh complex, both classes provide the P(i) access functions to their points and therefore they share the algorithms on it (e.g. area, normal etc...) */ template class Triangle3 { public: typedef ScalarTriangleType ScalarType; typedef Point3< ScalarType > CoordType; /// The bounding box type typedef Box3 BoxType; /********************************************* blah blah **/ Triangle3(){} Triangle3(const CoordType & c0,const CoordType & c1,const CoordType & c2){_v[0]=c0;_v[1]=c1;_v[2]=c2;} protected: /// Vector of vertex pointer incident in the face Point3 _v[3]; public: /// Shortcut per accedere ai punti delle facce inline CoordType & P( const int j ) { return _v[j];} inline CoordType & P0( const int j ) { return _v[j];} inline CoordType & P1( const int j ) { return _v[(j+1)%3];} inline CoordType & P2( const int j ) { return _v[(j+2)%3];} inline const CoordType & P( const int j ) const { return _v[j];} inline const CoordType & P0( const int j ) const { return _v[j];} inline const CoordType & P1( const int j ) const { return _v[(j+1)%3];} inline const CoordType & P2( const int j ) const { return _v[(j+2)%3];} inline const CoordType & cP0( const int j ) const { return _v[j];} inline const CoordType & cP1( const int j ) const { return _v[(j+1)%3];} inline const CoordType & cP2( const int j ) const { return _v[(j+2)%3];} bool InterpolationParameters(const CoordType & bq, ScalarType &a, ScalarType &b, ScalarType &_c ) const{ return InterpolationParameters(*this, bq, a, b,_c ); } /// Return the _q of the face, the return value is in [0,sqrt(3)/2] = [0 - 0.866.. ] ScalarType QualityFace( ) const { return Quality(P(0), P(1), P(2)); } }; //end Class /// Returns the normal to the plane passing through p0,p1,p2 template typename TriangleType::ScalarType QualityFace(const TriangleType &t) { return Quality(t.cP(0), t.cP(1), t.cP(2)); } /** Calcola i coefficienti della combinazione convessa. @param bq Punto appartenente alla faccia @param a Valore di ritorno per il vertice V(0) @param b Valore di ritorno per il vertice V(1) @param _c Valore di ritorno per il vertice V(2) @return true se bq appartiene alla faccia, false altrimenti */ template bool InterpolationParameters(const TriangleType t,const vcg::Point3 & bq, ScalarType &a, ScalarType &b, ScalarType &_c ) { const ScalarType EPSILON = ScalarType(0.000001); #define x1 (t.P(0).X()) #define y1 (t.P(0).Y()) #define z1 (t.P(0).Z()) #define x2 (t.P(1).X()) #define y2 (t.P(1).Y()) #define z2 (t.P(1).Z()) #define x3 (t.P(2).X()) #define y3 (t.P(2).Y()) #define z3 (t.P(2).Z()) #define px (bq[0]) #define py (bq[1]) #define pz (bq[2]) ScalarType t1 = px*y2; ScalarType t2 = px*y3; ScalarType t3 = py*x2; ScalarType t4 = py*x3; ScalarType t5 = x2*y3; ScalarType t6 = x3*y2; ScalarType t8 = x1*y2; ScalarType t9 = x1*y3; ScalarType t10 = y1*x2; ScalarType t11 = y1*x3; ScalarType t13 = t8-t9-t10+t11+t5-t6; if(fabs(t13)>=EPSILON) { ScalarType t15 = px*y1; ScalarType t16 = py*x1; a = (t1 -t2-t3 +t4+t5-t6 )/t13; b = -(t15-t2-t16+t4+t9-t11)/t13; _c = (t15-t1-t16+t3+t8-t10)/t13; return true; } t1 = px*z2; t2 = px*z3; t3 = pz*x2; t4 = pz*x3; t5 = x2*z3; t6 = x3*z2; t8 = x1*z2; t9 = x1*z3; t10 = z1*x2; t11 = z1*x3; t13 = t8-t9-t10+t11+t5-t6; if(fabs(t13)>=EPSILON) { ScalarType t15 = px*z1; ScalarType t16 = pz*x1; a = (t1 -t2-t3 +t4+t5-t6 )/t13; b = -(t15-t2-t16+t4+t9-t11)/t13; _c = (t15-t1-t16+t3+t8-t10)/t13; return true; } t1 = pz*y2; t2 = pz*y3; t3 = py*z2; t4 = py*z3; t5 = z2*y3; t6 = z3*y2; t8 = z1*y2; t9 = z1*y3; t10 = y1*z2; t11 = y1*z3; t13 = t8-t9-t10+t11+t5-t6; if(fabs(t13)>=EPSILON) { ScalarType t15 = pz*y1; ScalarType t16 = py*z1; a = (t1 -t2-t3 +t4+t5-t6 )/t13; b = -(t15-t2-t16+t4+t9-t11)/t13; _c = (t15-t1-t16+t3+t8-t10)/t13; return true; } #undef x1 #undef y1 #undef z1 #undef x2 #undef y2 #undef z2 #undef x3 #undef y3 #undef z3 #undef px #undef py #undef pz return false; } /// Compute a shape quality measure of the triangle composed by points p0,p1,p2 /// It Returns 2*AreaTri/(MaxEdge^2), /// the range is range [0.0, 0.866] /// e.g. Equilateral triangle sqrt(3)/2, halfsquare: 1/2, ... up to a line that has zero quality. template P3ScalarType Quality( Point3 const &p0, Point3 const & p1, Point3 const & p2) { Point3 d10=p1-p0; Point3 d20=p2-p0; Point3 d12=p1-p2; Point3 x = d10^d20; P3ScalarType a = Norm( x ); if(a==0) return 0; // Area zero triangles have surely quality==0; P3ScalarType b = SquaredNorm( d10 ); P3ScalarType t = b; t = SquaredNorm( d20 ); if ( b P3ScalarType QualityRadii(Point3 const &p0, Point3 const &p1, Point3 const &p2) { P3ScalarType a=(p1-p0).Norm(); P3ScalarType b=(p2-p0).Norm(); P3ScalarType c=(p1-p2).Norm(); P3ScalarType sum = (a + b + c)*0.5; P3ScalarType area2 = sum*(a+b-sum)*(a+c-sum)*(b+c-sum); if(area2 <= 0) return 0; //circumradius: (a*b*c)/(4*sqrt(area2)) //inradius: (a*b*c)/(4*circumradius*sum) => sqrt(area2)/sum; return (8*area2)/(a*b*c*sum); } /// Compute a shape quality measure of the triangle composed by points p0,p1,p2 /// It Returns mean ratio 2sqrt(a, b)/(a+b) where a+b are the eigenvalues of the M^tM of the /// transformation matrix into a regular simplex /// the range is range [0, 1] template P3ScalarType QualityMeanRatio(Point3 const &p0, Point3 const &p1, Point3 const &p2) { P3ScalarType a=(p1-p0).Norm(); P3ScalarType b=(p2-p0).Norm(); P3ScalarType c=(p1-p2).Norm(); P3ScalarType sum = (a + b + c)*0.5; //semiperimeter P3ScalarType area2 = sum*(a+b-sum)*(a+c-sum)*(b+c-sum); if(area2 <= 0) return 0; return (4.0*sqrt(3.0)*sqrt(area2))/(a*a + b*b + c*c); } /// Returns the normal to the plane passing through p0,p1,p2 template Point3 Normal(const TriangleType &t) { return (( t.P(1) - t.P(0)) ^ (t.P(2) - t.P(0))); } template Point3Type Normal( Point3Type const &p0, Point3Type const & p1, Point3Type const & p2) { return (( p1 - p0) ^ (p2 - p0)); } /// Like the above, it returns the normal to the plane passing through p0,p1,p2, but normalized. template Point3 NormalizedNormal(const TriangleType &t) { return (( t.P(1) - t.P(0)) ^ (t.P(2) - t.P(0))).Normalize(); } template Point3Type NormalizedNormal( Point3Type const &p0, Point3Type const & p1, Point3Type const & p2) { return (( p1 - p0) ^ (p2 - p0)).Normalize(); } /// Return the Double of area of the triangle // NOTE the old Area function has been removed to intentionally // cause compiling error that will help people to check their code... // A some people used Area assuming that it returns the double and some not. // So please check your codes!!! // And please DO NOT Insert any Area named function here! template typename TriangleType::ScalarType DoubleArea(const TriangleType &t) { return Norm( (t.P(1) - t.P(0)) ^ (t.P(2) - t.P(0)) ); } template Point3 Barycenter(const TriangleType &t) { return ((t.P(0)+t.P(1)+t.P(2))/(typename TriangleType::ScalarType) 3.0); } template typename TriangleType::ScalarType Perimeter(const TriangleType &t) { return Distance(t.P(0),t.P(1))+ Distance(t.P(1),t.P(2))+ Distance(t.P(2),t.P(0)); } template Point3 Circumcenter(const TriangleType &t) { typename TriangleType::ScalarType a2 = (t.P(1) - t.P(2)).SquaredNorm(); typename TriangleType::ScalarType b2 = (t.P(2) - t.P(0)).SquaredNorm(); typename TriangleType::ScalarType c2 = (t.P(0) - t.P(1)).SquaredNorm(); Point3c = t.P(0)*a2*(-a2 + b2 + c2) + t.P(1)*b2*( a2 - b2 + c2) + t.P(2)*c2*( a2 + b2 - c2); c /= 2*(a2*b2 + a2*c2 + b2*c2) - a2*a2 - b2*b2 - c2*c2; return c; } template void TrianglePointDistance(const TriangleType &t, const typename TriangleType::CoordType & q, typename TriangleType::ScalarType & dist, typename TriangleType::CoordType & closest ) { typedef typename TriangleType::CoordType CoordType; typedef typename TriangleType::ScalarType ScalarType; CoordType clos[3]; ScalarType distv[3]; CoordType clos_proj; ScalarType distproj; ///find distance on the plane vcg::Plane3 plane; plane.Init(t.P(0),t.P(1),t.P(2)); clos_proj=plane.Projection(q); ///control if inside/outside CoordType n=(t.P(1)-t.P(0))^(t.P(2)-t.P(0)); CoordType n0=(t.P(0)-clos_proj)^(t.P(1)-clos_proj); CoordType n1=(t.P(1)-clos_proj)^(t.P(2)-clos_proj); CoordType n2=(t.P(2)-clos_proj)^(t.P(0)-clos_proj); distproj=(clos_proj-q).Norm(); if (((n*n0)>=0)&&((n*n1)>=0)&&((n*n2)>=0)) { closest=clos_proj; dist=distproj; return; } //distance from the edges vcg::Segment3 e0=vcg::Segment3(t.P(0),t.P(1)); vcg::Segment3 e1=vcg::Segment3(t.P(1),t.P(2)); vcg::Segment3 e2=vcg::Segment3(t.P(2),t.P(0)); clos[0]=ClosestPoint( e0, q); clos[1]=ClosestPoint( e1, q); clos[2]=ClosestPoint( e2, q); distv[0]=(clos[0]-q).Norm(); distv[1]=(clos[1]-q).Norm(); distv[2]=(clos[2]-q).Norm(); int min=0; ///find minimum distance for (int i=1;i<3;i++) { if (distv[i] #include namespace vcg { /** \addtogroup space */ /*@{*/ /** Triangle/triangle intersection ,based on the algorithm presented in "A Fast Triangle-Triangle Intersection Test", Journal of Graphics Tools, 2(2), 1997 */ #define FABS(x) (T(fabs(x))) #define USE_EPSILON_TEST #define TRI_TRI_INT_EPSILON 0.000001 #define CROSS(dest,v1,v2){ \ dest[0]=v1[1]*v2[2]-v1[2]*v2[1]; \ dest[1]=v1[2]*v2[0]-v1[0]*v2[2]; \ dest[2]=v1[0]*v2[1]-v1[1]*v2[0];} #define DOT(v1,v2) (v1[0]*v2[0]+v1[1]*v2[1]+v1[2]*v2[2]) #define SUB(dest,v1,v2){ \ dest[0]=v1[0]-v2[0]; \ dest[1]=v1[1]-v2[1]; \ dest[2]=v1[2]-v2[2];} #define SORT(a,b) \ if(a>b) \ { \ T c; \ c=a; \ a=b; \ b=c; \ } #define EDGE_EDGE_TEST(V0,U0,U1) \ Bx=U0[i0]-U1[i0]; \ By=U0[i1]-U1[i1]; \ Cx=V0[i0]-U0[i0]; \ Cy=V0[i1]-U0[i1]; \ f=Ay*Bx-Ax*By; \ d=By*Cx-Bx*Cy; \ if((f>0 && d>=0 && d<=f) || (f<0 && d<=0 && d>=f)) \ { \ e=Ax*Cy-Ay*Cx; \ if(f>0) \ { \ if(e>=0 && e<=f) return 1; \ } \ else \ { \ if(e<=0 && e>=f) return 1; \ } \ } #define EDGE_AGAINST_TRI_EDGES(V0,V1,U0,U1,U2) \ { \ T Ax,Ay,Bx,By,Cx,Cy,e,d,f; \ Ax=V1[i0]-V0[i0]; \ Ay=V1[i1]-V0[i1]; \ /* test edge U0,U1 against V0,V1 */ \ EDGE_EDGE_TEST(V0,U0,U1); \ /* test edge U1,U2 against V0,V1 */ \ EDGE_EDGE_TEST(V0,U1,U2); \ /* test edge U2,U1 against V0,V1 */ \ EDGE_EDGE_TEST(V0,U2,U0); \ } #define POINT_IN_TRI(V0,U0,U1,U2) \ { \ T a,b,c,d0,d1,d2; \ /* is T1 completly inside T2? */ \ /* check if V0 is inside tri(U0,U1,U2) */ \ a=U1[i1]-U0[i1]; \ b=-(U1[i0]-U0[i0]); \ c=-a*U0[i0]-b*U0[i1]; \ d0=a*V0[i0]+b*V0[i1]+c; \ \ a=U2[i1]-U1[i1]; \ b=-(U2[i0]-U1[i0]); \ c=-a*U1[i0]-b*U1[i1]; \ d1=a*V0[i0]+b*V0[i1]+c; \ \ a=U0[i1]-U2[i1]; \ b=-(U0[i0]-U2[i0]); \ c=-a*U2[i0]-b*U2[i1]; \ d2=a*V0[i0]+b*V0[i1]+c; \ if(d0*d1>0.0) \ { \ if(d0*d2>0.0) return 1; \ } \ } template /** CHeck two triangles for coplanarity @param N @param V0 A vertex of the first triangle @param V1 A vertex of the first triangle @param V2 A vertex of the first triangle @param U0 A vertex of the second triangle @param U1 A vertex of the second triangle @param U2 A vertex of the second triangle @return true se due triangoli sono cooplanari, false altrimenti */ bool coplanar_tri_tri(const Point3 N, const Point3 V0, const Point3 V1,const Point3 V2, const Point3 U0, const Point3 U1,const Point3 U2) { T A[3]; short i0,i1; /* first project onto an axis-aligned plane, that maximizes the area */ /* of the triangles, compute indices: i0,i1. */ A[0]=FABS(N[0]); A[1]=FABS(N[1]); A[2]=FABS(N[2]); if(A[0]>A[1]) { if(A[0]>A[2]) { i0=1; /* A[0] is greatest */ i1=2; } else { i0=0; /* A[2] is greatest */ i1=1; } } else /* A[0]<=A[1] */ { if(A[2]>A[1]) { i0=0; /* A[2] is greatest */ i1=1; } else { i0=0; /* A[1] is greatest */ i1=2; } } /* test all edges of triangle 1 against the edges of triangle 2 */ EDGE_AGAINST_TRI_EDGES(V0,V1,U0,U1,U2); EDGE_AGAINST_TRI_EDGES(V1,V2,U0,U1,U2); EDGE_AGAINST_TRI_EDGES(V2,V0,U0,U1,U2); /* finally, test if tri1 is totally contained in tri2 or vice versa */ POINT_IN_TRI(V0,U0,U1,U2); POINT_IN_TRI(U0,V0,V1,V2); return 0; } #define NEWCOMPUTE_INTERVALS(VV0,VV1,VV2,D0,D1,D2,D0D1,D0D2,A,B,C,X0,X1) \ { \ if(D0D1>0.0f) \ { \ /* here we know that D0D2<=0.0 */ \ /* that is D0, D1 are on the same side, D2 on the other or on the plane */ \ A=VV2; B=(VV0-VV2)*D2; C=(VV1-VV2)*D2; X0=D2-D0; X1=D2-D1; \ } \ else if(D0D2>0.0f)\ { \ /* here we know that d0d1<=0.0 */ \ A=VV1; B=(VV0-VV1)*D1; C=(VV2-VV1)*D1; X0=D1-D0; X1=D1-D2; \ } \ else if(D1*D2>0.0f || D0!=0.0f) \ { \ /* here we know that d0d1<=0.0 or that D0!=0.0 */ \ A=VV0; B=(VV1-VV0)*D0; C=(VV2-VV0)*D0; X0=D0-D1; X1=D0-D2; \ } \ else if(D1!=0.0f) \ { \ A=VV1; B=(VV0-VV1)*D1; C=(VV2-VV1)*D1; X0=D1-D0; X1=D1-D2; \ } \ else if(D2!=0.0f) \ { \ A=VV2; B=(VV0-VV2)*D2; C=(VV1-VV2)*D2; X0=D2-D0; X1=D2-D1; \ } \ else \ { \ /* triangles are coplanar */ \ return coplanar_tri_tri(N1,V0,V1,V2,U0,U1,U2); \ } \ } template /* @param V0 A vertex of the first triangle @param V1 A vertex of the first triangle @param V2 A vertex of the first triangle @param U0 A vertex of the second triangle @param U1 A vertex of the second triangle @param U2 A vertex of the second triangle @return true if the two triangles interesect */ bool NoDivTriTriIsect(const Point3 V0,const Point3 V1,const Point3 V2, const Point3 U0,const Point3 U1,const Point3 U2) { Point3 E1,E2; Point3 N1,N2; T d1,d2; T du0,du1,du2,dv0,dv1,dv2; Point3 D; T isect1[2], isect2[2]; T du0du1,du0du2,dv0dv1,dv0dv2; short index; T vp0,vp1,vp2; T up0,up1,up2; T bb,cc,max; /* compute plane equation of triangle(V0,V1,V2) */ SUB(E1,V1,V0); SUB(E2,V2,V0); CROSS(N1,E1,E2); N1.Normalize(); // aggiunto rispetto al codice orig. d1=-DOT(N1,V0); /* plane equation 1: N1.X+d1=0 */ /* put U0,U1,U2 into plane equation 1 to compute signed distances to the plane*/ du0=DOT(N1,U0)+d1; du1=DOT(N1,U1)+d1; du2=DOT(N1,U2)+d1; /* coplanarity robustness check */ #ifdef USE_TRI_TRI_INT_EPSILON_TEST if(FABS(du0)0.0f && du0du2>0.0f) /* same sign on all of them + not equal 0 ? */ return 0; /* no intersection occurs */ /* compute plane of triangle (U0,U1,U2) */ SUB(E1,U1,U0); SUB(E2,U2,U0); CROSS(N2,E1,E2); d2=-DOT(N2,U0); /* plane equation 2: N2.X+d2=0 */ /* put V0,V1,V2 into plane equation 2 */ dv0=DOT(N2,V0)+d2; dv1=DOT(N2,V1)+d2; dv2=DOT(N2,V2)+d2; #ifdef USE_TRI_TRI_INT_EPSILON_TEST if(FABS(dv0)0.0f && dv0dv2>0.0f) /* same sign on all of them + not equal 0 ? */ return 0; /* no intersection occurs */ /* compute direction of intersection line */ CROSS(D,N1,N2); /* compute and index to the largest component of D */ max=(T)FABS(D[0]); index=0; bb=(T)FABS(D[1]); cc=(T)FABS(D[2]); if(bb>max) max=bb,index=1; if(cc>max) max=cc,index=2; /* this is the simplified projection onto L*/ vp0=V0[index]; vp1=V1[index]; vp2=V2[index]; up0=U0[index]; up1=U1[index]; up2=U2[index]; /* compute interval for triangle 1 */ T a,b,c,x0,x1; NEWCOMPUTE_INTERVALS(vp0,vp1,vp2,dv0,dv1,dv2,dv0dv1,dv0dv2,a,b,c,x0,x1); /* compute interval for triangle 2 */ T d,e,f,y0,y1; NEWCOMPUTE_INTERVALS(up0,up1,up2,du0,du1,du2,du0du1,du0du2,d,e,f,y0,y1); T xx,yy,xxyy,tmp; xx=x0*x1; yy=y0*y1; xxyy=xx*yy; tmp=a*xxyy; isect1[0]=tmp+b*x1*yy; isect1[1]=tmp+c*x0*yy; tmp=d*xxyy; isect2[0]=tmp+e*xx*y1; isect2[1]=tmp+f*xx*y0; SORT(isect1[0],isect1[1]); SORT(isect2[0],isect2[1]); if(isect1[1]b) \ { \ float c; \ c=a; \ a=b; \ b=c; \ smallest=1; \ } \ else smallest=0; template inline void isect2(Point3 VTX0,Point3 VTX1,Point3 VTX2,float VV0,float VV1,float VV2, float D0,float D1,float D2,float *isect0,float *isect1,Point3 &isectpoint0,Point3 &isectpoint1) { float tmp=D0/(D0-D1); float diff[3]; *isect0=VV0+(VV1-VV0)*tmp; SUB(diff,VTX1,VTX0); MULT(diff,diff,tmp); ADD(isectpoint0,diff,VTX0); tmp=D0/(D0-D2); *isect1=VV0+(VV2-VV0)*tmp; SUB(diff,VTX2,VTX0); MULT(diff,diff,tmp); ADD(isectpoint1,VTX0,diff); } template inline int compute_intervals_isectline(Point3 VERT0,Point3 VERT1,Point3 VERT2, float VV0,float VV1,float VV2,float D0,float D1,float D2, float D0D1,float D0D2,float *isect0,float *isect1, Point3 & isectpoint0, Point3 & isectpoint1) { if(D0D1>0.0f) { /* here we know that D0D2<=0.0 */ /* that is D0, D1 are on the same side, D2 on the other or on the plane */ isect2(VERT2,VERT0,VERT1,VV2,VV0,VV1,D2,D0,D1,isect0,isect1,isectpoint0,isectpoint1); } else if(D0D2>0.0f) { /* here we know that d0d1<=0.0 */ isect2(VERT1,VERT0,VERT2,VV1,VV0,VV2,D1,D0,D2,isect0,isect1,isectpoint0,isectpoint1); } else if(D1*D2>0.0f || D0!=0.0f) { /* here we know that d0d1<=0.0 or that D0!=0.0 */ isect2(VERT0,VERT1,VERT2,VV0,VV1,VV2,D0,D1,D2,isect0,isect1,isectpoint0,isectpoint1); } else if(D1!=0.0f) { isect2(VERT1,VERT0,VERT2,VV1,VV0,VV2,D1,D0,D2,isect0,isect1,isectpoint0,isectpoint1); } else if(D2!=0.0f) { isect2(VERT2,VERT0,VERT1,VV2,VV0,VV1,D2,D0,D1,isect0,isect1,isectpoint0,isectpoint1); } else { /* triangles are coplanar */ return 1; } return 0; } #define COMPUTE_INTERVALS_ISECTLINE(VERT0,VERT1,VERT2,VV0,VV1,VV2,D0,D1,D2,D0D1,D0D2,isect0,isect1,isectpoint0,isectpoint1) \ if(D0D1>0.0f) \ { \ /* here we know that D0D2<=0.0 */ \ /* that is D0, D1 are on the same side, D2 on the other or on the plane */ \ isect2(VERT2,VERT0,VERT1,VV2,VV0,VV1,D2,D0,D1,&isect0,&isect1,isectpoint0,isectpoint1); \ } #if 0 else if(D0D2>0.0f) \ { \ /* here we know that d0d1<=0.0 */ \ isect2(VERT1,VERT0,VERT2,VV1,VV0,VV2,D1,D0,D2,&isect0,&isect1,isectpoint0,isectpoint1); \ } \ else if(D1*D2>0.0f || D0!=0.0f) \ { \ /* here we know that d0d1<=0.0 or that D0!=0.0 */ \ isect2(VERT0,VERT1,VERT2,VV0,VV1,VV2,D0,D1,D2,&isect0,&isect1,isectpoint0,isectpoint1); \ } \ else if(D1!=0.0f) \ { \ isect2(VERT1,VERT0,VERT2,VV1,VV0,VV2,D1,D0,D2,&isect0,&isect1,isectpoint0,isectpoint1); \ } \ else if(D2!=0.0f) \ { \ isect2(VERT2,VERT0,VERT1,VV2,VV0,VV1,D2,D0,D1,&isect0,&isect1,isectpoint0,isectpoint1); \ } \ else \ { \ /* triangles are coplanar */ \ coplanar=1; \ return coplanar_tri_tri(N1,V0,V1,V2,U0,U1,U2); \ } #endif template bool tri_tri_intersect_with_isectline( Point3 V0,Point3 V1,Point3 V2, Point3 U0,Point3 U1,Point3 U2,bool &coplanar, Point3 &isectpt1,Point3 &isectpt2) { Point3 E1,E2; Point3 N1,N2; T d1,d2; float du0,du1,du2,dv0,dv1,dv2; Point3 D; float isect1[2], isect2[2]; Point3 isectpointA1,isectpointA2; Point3 isectpointB1,isectpointB2; float du0du1,du0du2,dv0dv1,dv0dv2; short index; float vp0,vp1,vp2; float up0,up1,up2; float b,c,max; Point3 diff; int smallest1,smallest2; /* compute plane equation of triangle(V0,V1,V2) */ SUB(E1,V1,V0); SUB(E2,V2,V0); CROSS(N1,E1,E2); d1=-DOT(N1,V0); /* plane equation 1: N1.X+d1=0 */ /* put U0,U1,U2 into plane equation 1 to compute signed distances to the plane*/ du0=DOT(N1,U0)+d1; du1=DOT(N1,U1)+d1; du2=DOT(N1,U2)+d1; /* coplanarity robustness check */ #ifdef USE_EPSILON_TEST if(fabs(du0)0.0f && du0du2>0.0f) /* same sign on all of them + not equal 0 ? */ return 0; /* no intersection occurs */ /* compute plane of triangle (U0,U1,U2) */ SUB(E1,U1,U0); SUB(E2,U2,U0); CROSS(N2,E1,E2); d2=-DOT(N2,U0); /* plane equation 2: N2.X+d2=0 */ /* put V0,V1,V2 into plane equation 2 */ dv0=DOT(N2,V0)+d2; dv1=DOT(N2,V1)+d2; dv2=DOT(N2,V2)+d2; #ifdef USE_EPSILON_TEST if(fabs(dv0)0.0f && dv0dv2>0.0f) /* same sign on all of them + not equal 0 ? */ return 0; /* no intersection occurs */ /* compute direction of intersection line */ CROSS(D,N1,N2); /* compute and index to the largest component of D */ max=fabs(D[0]); index=0; b=fabs(D[1]); c=fabs(D[2]); if(b>max) max=b,index=1; if(c>max) max=c,index=2; /* this is the simplified projection onto L*/ vp0=V0[index]; vp1=V1[index]; vp2=V2[index]; up0=U0[index]; up1=U1[index]; up2=U2[index]; /* compute interval for triangle 1 */ coplanar=compute_intervals_isectline(V0,V1,V2,vp0,vp1,vp2,dv0,dv1,dv2, dv0dv1,dv0dv2,&isect1[0],&isect1[1],isectpointA1,isectpointA2); if(coplanar) return coplanar_tri_tri(N1,V0,V1,V2,U0,U1,U2); /* compute interval for triangle 2 */ compute_intervals_isectline(U0,U1,U2,up0,up1,up2,du0,du1,du2, du0du1,du0du2,&isect2[0],&isect2[1],isectpointB1,isectpointB2); SORT2(isect1[0],isect1[1],smallest1); SORT2(isect2[0],isect2[1],smallest2); if(isect1[1]isect1[1]) { if(smallest1==0) { SET(isectpt2,isectpointA2); } else { SET(isectpt2,isectpointA1); } } else { if(smallest2==0) { SET(isectpt2,isectpointB2); } else { SET(isectpt2,isectpointB1); } } } return 1; } } // end namespace #undef FABS #undef USE_EPSILON_TEST #undef TRI_TRI_INT_EPSILON #undef CROSS #undef DOT #undef SUB #undef SORT #undef SORT2 #undef ADD #undef MULT #undef SET #undef EDGE_EDGE_TEST #undef EDGE_AGAINST_TRI_EDGE #undef POINT_IN_TRI #undef COMPUTE_INTERVALS_ISECTLINE #undef NEWCOMPUTE_INTERVALS #endif qutemol/vcg/vcg/space/point2.h0000444000175000017500000002365410617554657014671 0ustar mbamba/**************************************************************************** * VCGLib o o * * Visual and Computer Graphics Library o o * * _ O _ * * Copyright(C) 2004 \/)\/ * * Visual Computing Lab /\/| * * ISTI - Italian National Research Council | * * \ * * All rights reserved. * * * * 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. * * * * 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 (http://www.gnu.org/licenses/gpl.txt) * * for more details. * * * ****************************************************************************/ /**************************************************************************** History $Log: point2.h,v $ Revision 1.10 2007/05/07 07:47:59 fiorin Added enum Dimension; Revision 1.9 2006/10/07 16:51:43 m_di_benedetto Implemented Scale() method (was only declared). Revision 1.8 2006/01/19 13:53:19 m_di_benedetto Fixed product by scalar and SquaredNorm() Revision 1.7 2005/10/15 19:11:49 m_di_benedetto Corrected return type in Angle() and protected member access in unary operator - Revision 1.6 2005/03/18 16:34:42 fiorin minor changes to comply gcc compiler Revision 1.5 2004/05/10 13:22:25 cignoni small syntax error Math -> math in Angle Revision 1.4 2004/04/05 11:57:32 cignoni Add V() access function Revision 1.3 2004/03/10 17:42:40 tarini Added comments (Dox) ! Added Import(). Costruct(), ScalarType... Corrected cross prod (sign). Added Angle. Now using Math:: stuff for trigon. etc. Revision 1.2 2004/03/03 15:07:40 cignoni renamed protected member v -> _v Revision 1.1 2004/02/13 00:44:53 cignoni First commit... ****************************************************************************/ #ifndef __VCGLIB_POINT2 #define __VCGLIB_POINT2 #include #include namespace vcg { /** \addtogroup space */ /*@{*/ /** The templated class for representing a point in 2D space. The class is templated over the ScalarType class that is used to represent coordinates. All the usual operator overloading (* + - ...) is present. */ template class Point2 { protected: /// The only data member. Hidden to user. P2ScalarType _v[2]; public: /// the scalar type typedef P2ScalarType ScalarType; enum {Dimension = 2}; //@{ /** @name Access to Coords. access to coords is done by overloading of [] or explicit naming of coords (X,Y,) ("p[0]" or "p.X()" are equivalent) **/ inline const ScalarType &X() const {return _v[0];} inline const ScalarType &Y() const {return _v[1];} inline ScalarType &X() {return _v[0];} inline ScalarType &Y() {return _v[1];} inline const ScalarType * V() const { return _v; } inline ScalarType & V( const int i ) { assert(i>=0 && i<2); return _v[i]; } inline const ScalarType & V( const int i ) const { assert(i>=0 && i<2); return _v[i]; } inline const ScalarType & operator [] ( const int i ) const { assert(i>=0 && i<2); return _v[i]; } inline ScalarType & operator [] ( const int i ) { assert(i>=0 && i<2); return _v[i]; } //@} /// empty constructor (does nothing) inline Point2 () { } /// x,y constructor inline Point2 ( const ScalarType nx, const ScalarType ny ) { _v[0] = nx; _v[1] = ny; } /// copy constructor inline Point2 ( Point2 const & p) { _v[0]= p._v[0]; _v[1]= p._v[1]; } /// copy inline Point2 & operator =( Point2 const & p) { _v[0]= p._v[0]; _v[1]= p._v[1]; return *this; } /// sets the point to (0,0) inline void Zero() { _v[0] = 0;_v[1] = 0;} /// dot product inline ScalarType operator * ( Point2 const & p ) const { return ( _v[0]*p._v[0] + _v[1]*p._v[1] ); } /// cross product inline ScalarType operator ^ ( Point2 const & p ) const { return _v[0]*p._v[1] - _v[1]*p._v[0]; } //@{ /** @name Linearity for 2d points (operators +, -, *, /, *= ...) **/ inline Point2 operator + ( Point2 const & p) const { return Point2( _v[0]+p._v[0], _v[1]+p._v[1] ); } inline Point2 operator - ( Point2 const & p) const { return Point2( _v[0]-p._v[0], _v[1]-p._v[1] ); } inline Point2 operator * ( const ScalarType s ) const { return Point2( _v[0] * s, _v[1] * s ); } inline Point2 operator / ( const ScalarType s ) const { return Point2( _v[0] / s, _v[1] / s ); } inline Point2 & operator += ( Point2 const & p) { _v[0] += p._v[0]; _v[1] += p._v[1]; return *this; } inline Point2 & operator -= ( Point2 const & p) { _v[0] -= p._v[0]; _v[1] -= p._v[1]; return *this; } inline Point2 & operator *= ( const ScalarType s ) { _v[0] *= s; _v[1] *= s; return *this; } inline Point2 & operator /= ( const ScalarType s ) { _v[0] /= s; _v[1] /= s; return *this; } //@} /// returns the norm (Euclidian) inline ScalarType Norm( void ) const { return math::Sqrt( _v[0]*_v[0] + _v[1]*_v[1] ); } /// returns the squared norm (Euclidian) inline ScalarType SquaredNorm( void ) const { return ( _v[0]*_v[0] + _v[1]*_v[1] ); } inline Point2 & Scale( const ScalarType sx, const ScalarType sy ) { _v[0] *= sx; _v[1] *= sy; return * this; } /// normalizes, and returns itself as result inline Point2 & Normalize( void ) { ScalarType n = math::Sqrt(_v[0]*_v[0] + _v[1]*_v[1]); if(n>0.0) { _v[0] /= n; _v[1] /= n; } return *this; } /// points equality inline bool operator == ( Point2 const & p ) const { return (_v[0]==p._v[0] && _v[1]==p._v[1]); } /// disparity between points inline bool operator != ( Point2 const & p ) const { return ( (_v[0]!=p._v[0]) || (_v[1]!=p._v[1]) ); } /// lexical ordering inline bool operator < ( Point2 const & p ) const { return (_v[1]!=p._v[1])?(_v[1] ( Point2 const & p ) const { return (_v[1]!=p._v[1])?(_v[1]>p._v[1]): (_v[0]>p._v[0]); } /// lexical ordering inline bool operator <= ( Point2 const & p ) const { return (_v[1]!=p._v[1])?(_v[1]< p._v[1]): (_v[0]<=p._v[0]); } /// lexical ordering inline bool operator >= ( Point2 const & p ) const { return (_v[1]!=p._v[1])?(_v[1]> p._v[1]): (_v[0]>=p._v[0]); } /// returns the distance to another point p inline ScalarType Distance( Point2 const & p ) const { return Norm(*this-p); } /// returns the suqared distance to another point p inline ScalarType SquaredDistance( Point2 const & p ) const { return Norm2(*this-p); } /// returns the angle with X axis (radiants, in [-PI, +PI] ) inline ScalarType Angle() const { return math::Atan2(_v[1],_v[0]); } /// transform the point in cartesian coords into polar coords inline Point2 & Cartesian2Polar() { ScalarType t = Angle(); _v[0] = Norm(); _v[1] = t; return *this; } /// transform the point in polar coords into cartesian coords inline Point2 & Polar2Cartesian() { ScalarType l = _v[0]; _v[0] = (ScalarType)(l*math::Cos(_v[1])); _v[1] = (ScalarType)(l*math::Sin(_v[1])); return *this; } /// rotates the point of an angle (radiants, counterclockwise) inline Point2 & Rotate( const ScalarType rad ) { ScalarType t = _v[0]; ScalarType s = math::Sin(rad); ScalarType c = math::Cos(rad); _v[0] = _v[0]*c - _v[1]*s; _v[1] = t *s + _v[1]*c; return *this; } /// Questa funzione estende il vettore ad un qualsiasi numero di dimensioni /// paddando gli elementi estesi con zeri inline ScalarType Ext( const int i ) const { if(i>=0 && i<2) return _v[i]; else return 0; } /// imports from 2D points of different types template inline void Import( const Point2 & b ) { _v[0] = b.X(); _v[1] = b.Y(); } /// constructs a 2D points from an existing one of different type template static Point2 Construct( const Point2 & b ) { return Point2(b.X(),b.Y()); } }; // end class definition template inline T Angle( Point2 const & p0, Point2 const & p1 ) { return p1.Angle() - p0.Angle(); } template inline Point2 operator - ( Point2 const & p ){ return Point2( -p[0], -p[1] ); } template inline Point2 operator * ( const T s, Point2 const & p ){ return Point2( p[0] * s, p[1] * s ); } template inline T Norm( Point2 const & p ){ return p.Norm(); } template inline T SquaredNorm( Point2 const & p ){ return p.SquaredNorm(); } template inline Point2 & Normalize( Point2 & p ){ return p.Normalize(); } template inline T Distance( Point2 const & p1,Point2 const & p2 ){ return Norm(p1-p2); } template inline T SquaredDistance( Point2 const & p1,Point2 const & p2 ){ return SquaredNorm(p1-p2); } typedef Point2 Point2s; typedef Point2 Point2i; typedef Point2 Point2f; typedef Point2 Point2d; /*@}*/ } // end namespace #endif qutemol/vcg/vcg/space/texcoord2.h0000444000175000017500000001622010747313364015346 0ustar mbamba/**************************************************************************** * VCGLib o o * * Visual and Computer Graphics Library o o * * _ O _ * * Copyright(C) 2004 \/)\/ * * Visual Computing Lab /\/| * * ISTI - Italian National Research Council | * * \ * * All rights reserved. * * * * 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. * * * * 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 (http://www.gnu.org/licenses/gpl.txt) * * for more details. * * * ****************************************************************************/ #ifndef __VCGLIB_TEXCOORD2__ #define __VCGLIB_TEXCOORD2__ #include namespace vcg { /** \addtogroup space */ /*@{*/ /** Templated class for a set of 2D texture coord. It for each is templated over two parameters: the type of the tex coord and the number of texcoord to be stored. This class is intended to be used when many textures id are shared over the same surface, so for each coord the id of the texture is stored. If no id is needed see the vcg::TexCoord2Simple class. */ template class TexCoord2 { public: typedef Point2 PointType; typedef T ScalarType; private: PointType _t[NMAX]; short _n[NMAX]; public: TexCoord2(T u, T v) { _t[0][0]=u; _t[0][1]=v; }; TexCoord2() { }; inline const PointType &P() const { return _t[0]; }; inline PointType &P() { return _t[0]; }; inline const PointType &P(const int i) const { assert(i>0 && i0 && i0 && i0 && i0 && i0 && i0 && i0 && i (lowercase ones). DEPRECATED. TO BE REMOVED SOON.*/ /**/inline T & u() { return _t[0][0]; } /**/inline T & v() { return _t[0][1]; } /**/inline const T & u() const { return _t[0][0]; } /**/inline const T & v() const { return _t[0][1]; } /**/inline T & u(const int i) { return _t[i][0]; } /**/inline T & v(const int i) { return _t[i][1]; } /**/inline const T & u(const int i) const { return _t[i][0]; } /**/inline const T & v(const int i) const { return _t[i][1]; } /**/ /**/inline short & n() { return _n[0]; } /**/inline const short n() const { return _n[0]; } /**/ /**/inline short & n(const int i) { return _n[i]; } /**/inline const short n(const int i) const { return _n[i]; } /**/ /**/inline Point2 & t(const int i) { return _t[i]; } /**/inline Point2 t(const int i) const { return _t[i]; } /**/ /**/inline Point2 & t() { return _t[0]; } /**/inline Point2 t() const { return _t[0]; } /* */ inline bool operator == ( TexCoord2 const & p ) const { for(int i=0;i class TexCoord2Simple { public: typedef Point2 PointType; typedef T ScalarType; private: Point2 _t; inline short & static_n() const { static short _n = 0; return _n; } public: inline T & U() { return _t[0]; } inline T & V() { return _t[1]; } inline const T & U() const { return _t[0]; } inline const T & V() const { return _t[1]; } inline T & U(const int i) { assert(i==0); return _t[0]; } inline T & V(const int i) { assert(i==0); return _t[1]; } inline const T & U(const int i) const { assert(i==0); return _t[0]; } inline const T & V(const int i) const { assert(i==0); return _t[1]; } inline Point2 & P(const int i) { assert(i==0); return _t; } inline Point2 P(const int i) const { assert(i==0); return _t; } inline Point2 & P() { return _t; } inline Point2 P() const { return _t; } inline short & N() { assert(static_n()==0); return static_n(); } inline short N() const { assert(static_n()==0); return 0; } inline short & N(const int i) { assert(i==0); return static_n(); } inline short N(const int i) const { assert(i==0); return 0; } /* (lowercase ones). DEPRECATED. TO BE REMOVED SOON.*/ inline T & u() { return _t[0]; } inline T & v() { return _t[1]; } inline const T & u() const { return _t[0]; } inline const T & v() const { return _t[1]; } inline T & u(const int i) { assert(i==0); return _t[0]; } inline T & v(const int i) { assert(i==0); return _t[1]; } inline const T & u(const int i) const { assert(i==0); return _t[0]; } inline const T & v(const int i) const { assert(i==0); return _t[1]; } inline Point2 & t(const int i) { assert(i==0); return _t; } inline Point2 t(const int i) const { assert(i==0); return _t; } inline Point2 & t() { return _t; } inline Point2 t() const { return _t; } inline short & n() { assert(static_n()==0); return static_n(); } inline short n() const { assert(static_n()==0); return 0; } inline short & n(const int i) { assert(i==0); return static_n(); } inline short n(const int i) const { assert(i==0); return 0; } /* */ inline bool operator == ( TexCoord2Simple const & p ) const { return _t==p._t; } enum { n_coords=1}; }; /*@}*/ } #endif qutemol/vcg/vcg/space/triangle2.h0000444000175000017500000001200310557237032015313 0ustar mbamba/**************************************************************************** * VCGLib o o * * Visual and Computer Graphics Library o o * * _ O _ * * Copyright(C) 2004 \/)\/ * * Visual Computing Lab /\/| * * ISTI - Italian National Research Council | * * \ * * All rights reserved. * * * * 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. * * * * 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 (http://www.gnu.org/licenses/gpl.txt) * * for more details. * * * ****************************************************************************/ /**************************************************************************** History ****************************************************************************/ #ifndef __VCG_TRIANGLE2 #define __VCG_TRIANGLE2 #include #include #include namespace vcg { /** \addtogroup space */ /*@{*/ /** Templated class for storing a generic triangle in a 2D space. Note the relation with the Face class of TriMesh complex, both classes provide the P(i) access functions to their points and therefore they share the algorithms on it (e.g. area, normal etc...) */ template class Triangle2 { public: typedef SCALAR_TRIANGLE_TYPE ScalarTriangleType; typedef ScalarTriangleType ScalarType; typedef Point2< ScalarType > CoordType; typedef typename Triangle2 TriangleType; protected: /// Vector of vertex pointer incident in the face Point2 _v[3]; public: Triangle2() {} Triangle2(const CoordType &p0,const CoordType &p1,const CoordType &p2) { P(0)=p0; P(1)=p1; P(2)=p2; } /// Shortcut per accedere ai punti delle facce inline CoordType & P( const int j ) { return _v[j];} inline CoordType & P0( const int j ) { return _v[j];} inline CoordType & P1( const int j ) { return _v[(j+1)%3];} inline CoordType & P2( const int j ) { return _v[(j+2)%3];} inline const CoordType & P( const int j ) const { return _v[j];} inline const CoordType & P0( const int j ) const { return _v[j];} inline const CoordType & P1( const int j ) const { return _v[(j+1)%3];} inline const CoordType & P2( const int j ) const { return _v[(j+2)%3];} inline const CoordType & cP0( const int j ) const { return _v[j];} inline const CoordType & cP1( const int j ) const { return _v[(j+1)%3];} inline const CoordType & cP2( const int j ) const { return _v[(j+2)%3];} /** evaluate barycentric coordinates @param bq Point on the face @param a barycentric value for V(0) @param b barycentric value for V(1) @param c barycentric value for V(2) @return true se bq appartain to the face, false otherwise */ bool InterpolationParameters(const CoordType & bq, ScalarType &a, ScalarType &b, ScalarType &c ) const { const ScalarType EPSILON = ScalarType(0.0001); ScalarType AreaGlobal=(P(1) - P(0)) ^ (P(2) - P(0)); ScalarType Area0=(P(2) - P(1)) ^ (bq - P(1)); ScalarType Area1=(P(0) - P(2)) ^ (bq - P(2)); ScalarType Area2=(P(1) - P(0)) ^ (bq - P(0)); /*if ((Area0>(AreaGlobal+EPSILON))||(Area1>(AreaGlobal+EPSILON))||(Area2>(AreaGlobal+EPSILON))) return false;*/ a=Area0/AreaGlobal; b=Area1/AreaGlobal; c=Area2/AreaGlobal; ///test inside/outside if((a>(ScalarType)1+EPSILON)||(b>(ScalarType)1+EPSILON)||(c>(ScalarType)1+EPSILON)) return false; if(a>1) a=(ScalarType)1; if(b>1) b=(ScalarType)1; if(c>1) c=(ScalarType)1; return true; } ///return the distance to the point q and neighors point p void PointDistance(const CoordType & q, typename ScalarType & dist, typename CoordType & p ) const { dist=FLT_MAX; ///find distance to each segment and take minimum for (int i=0;i<3;i++) { vcg::Segment2 s=vcg::Segment2(P(i),P((i+1)%3)); CoordType clos=ClosestPoint(s,q); ScalarType dis_test=(clos-q).Norm(); if (dis_test Segment3 in constructor (g++ complained) Revision 1.4 2004/05/08 14:07:50 ganovelli return type of length and squaredlength corrected Revision 1.3 2004/03/11 11:47:20 tarini minor updates, corrections, added documentations, etc. Revision 1.1 2004/03/08 19:46:47 tarini First Version (tarini) ****************************************************************************/ #ifndef __VCGLIB_SEGMENT3 #define __VCGLIB_SEGMENT3 #include #include #include namespace vcg { /** \addtogroup space */ /*@{*/ /** Templated class for 3D segment. This is the class for a segment in 3D space. A Segment is stored just as its two extrema (Point3). @param SegmentScalarType (template parameter) Specifies the type of scalar used to represent coords. */ template class Segment3 { public: /// The scalar type typedef SegmentScalarType ScalarType; /// The point type typedef Point3 PointType; /// The point type typedef Segment3 SegmentType; private: /// _extrema PointType _p0,_p1; public: /// Members to access either extrema inline const PointType &P0() const { return _p0; } inline const PointType &P1() const { return _p1; } inline PointType &P0() { return _p0; } inline PointType &P1() { return _p1; } /// The empty constructor Segment3() {}; /// The (a,b) constructor Segment3(const PointType &a, const PointType &b) { _p0=a; _p1=b; }; /// Operator to compare segments inline bool operator == ( SegmentType const & p ) const { return _p0==p._p0 && _p1==p._p1; } /// Operator to dispare segments inline bool operator != ( SegmentType const & p ) const { return _p0!=p._p0 || _p1!=p._p1; } /// initializes the segment with its extrema void Set( const PointType &a, const PointType &b) { _p0=a; _p1=b;} /// calculates the point of parameter t on the segment. /// if t is in [0..1] returned point is inside the segment inline PointType P( const ScalarType t ) const { return _p0 + (_p1 - _p0) * t; } /// return the middle point inline PointType MidPoint( ) const { return ( _p0 + _p1) / ScalarType(2.0) ; } /// return the bounding box inline Box3 BBox( ) const { Box3 t; if (_p0[0]<_p1[0]) { t.min[0]=_p0[0];t.max[0]=_p1[0];} else { t.min[0]=_p1[0];t.max[0]=_p0[0];} if (_p0[1]<_p1[1]) { t.min[1]=_p0[1];t.max[1]=_p1[1];} else { t.min[1]=_p1[1];t.max[1]=_p0[1];} if (_p0[2]<_p1[2]) { t.min[2]=_p0[2];t.max[2]=_p1[2];} else { t.min[2]=_p1[2];t.max[2]=_p0[2];} return t; } /// returns segment length ScalarType Length() { return (_p0 - _p1).Norm(); } /// return segment squared lenght ScalarType SquaredLength() { return (_p0 - _p1).SquaredNorm(); } /// flips: a-b becomes b-a void Flip() { PointType t=_p0; _p0=_p1; _p1=t; } /// importer for different line types template inline void Import( const Segment3 & b ) { _p0.Import( b.P0() ); _p1.Import( b.P1() ); } /// copy constructor (builds a new segment importing an existing one) template static SegmentType Construct( const Segment3 & b ) { return SegmentType(PointType::Construct(b.P0()), PointType::Construct(b.P1()));} //@{ /** @name Linearity for 3d segments (operators +, -, *, /) **/ inline SegmentType operator + ( SegmentType const & p) const {return SegmentType( _p0+p.P0(), _p1+p.P1() );} inline SegmentType operator - ( SegmentType const & p) const {return SegmentType( _p0-p.P0(), _p1-p.P1() );} inline SegmentType operator * ( const ScalarType s ) const {return SegmentType( _p0*s, _p1*s );} inline SegmentType operator / ( const ScalarType s ) const {ScalarType s0=((ScalarType)1.0)/s; return SegmentType( _p0*s0, _p1*s0 );} //@} }; // end class definition typedef Segment3 Segment3s; typedef Segment3 Segment3i; typedef Segment3 Segment3f; typedef Segment3 Segment3d; /* * Computes the minimum distance between a segment and a point * @param[in] segment The input segment * @param[in] p The input point * @return The distance between the segment and the point p */ template < class ScalarType > ScalarType SquaredDistance(Segment3< ScalarType > &segment, Point3< ScalarType > &p) { typedef typename vcg::Point3< ScalarType > Point3t; Point3t dir = (segment.P1()-segment.P0()).Normalize(); ScalarType h = dir * (p-segment.P0()); if (h<=ScalarType(0.0)) return vcg::SquaredDistance(p, segment.P0()); else if (h>=segment.Length()) return vcg::SquaredDistance(p, segment.P1()); else { dir = segment.P0() + dir*h; return vcg::SquaredDistance(p, dir); } }; //end of Distance method template Point3 ClosestPoint( Segment3 s, const Point3 & p) { vcg::Line3 l; l.Set(s.P0(),s.P1()-s.P0()); l.Normalize(); Point3 clos=vcg::ClosestPoint(l,p) ;//attention to call vcg::Box3 b; b.Add(s.P0()); b.Add(s.P1()); if (b.IsIn(clos)) return clos; else { ScalarType d0=(s.P0()-p).Norm(); ScalarType d1=(s.P1()-p).Norm(); if (d01) return s.P0(); return s.P(t);*/ } /*@}*/ } // end namespace #endif qutemol/vcg/vcg/space/tetra3.h0000444000175000017500000003311410705165275014640 0ustar mbamba/**************************************************************************** * VCGLib o o * * Visual and Computer Graphics Library o o * * _ O _ * * Copyright(C) 2004 \/)\/ * * Visual Computing Lab /\/| * * ISTI - Italian National Research Council | * * \ * * All rights reserved. * * * * 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. * * * * 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 (http://www.gnu.org/licenses/gpl.txt) * * for more details. * * * ****************************************************************************/ /**************************************************************************** History $Log: tetra3.h,v $ Revision 1.16 2007/10/16 16:45:49 cignoni added missing typenames Revision 1.15 2007/07/31 12:35:42 ganovelli added ScalarType to tetra3 Revision 1.14 2006/07/06 12:39:51 ganovelli adde barycenter() Revision 1.13 2006/06/06 14:35:31 zifnab1974 Changes for compilation on linux AMD64. Some remarks: Linux filenames are case-sensitive. _fileno and _filelength do not exist on linux Revision 1.12 2006/03/01 15:59:34 pietroni added InterpolationParameters function Revision 1.11 2005/12/12 11:15:26 ganovelli modifications to compile with gcc Revision 1.10 2005/11/29 16:20:33 pietroni added IsInside() function Revision 1.9 2004/10/13 12:45:51 cignoni Better Doxygen documentation Revision 1.8 2004/09/01 12:21:11 pietroni minor changes to comply gcc compiler (typename's ) Revision 1.7 2004/07/09 10:08:21 ganovelli ComputeVOlume moved outside the class and other minor corrections Revision 1.6 2004/06/25 18:17:03 ganovelli minor changes Revision 1.5 2004/05/13 12:51:00 turini Changed SolidAngle : table EV in table EofV Changed DiedralAngle : tables FE and FV in tables FofE and FofV Revision 1.4 2004/05/13 08:42:36 pietroni the relation between entities functions are in tetra class (don't neeed template argoument) Revision 1.3 2004/04/28 16:31:17 turini Changed : in SolidAngle(vind) : double da0=DiedralAngle(EV(vind,0)); double da1=DiedralAngle(EV(vind,1)); double da2=DiedralAngle(EV(vind,2)); in double da0=DiedralAngle(EofV(vind,0)); double da1=DiedralAngle(EofV(vind,1)); double da2=DiedralAngle(EofV(vind,2)); Changed : in DiedralAngle(edgeind) : int f1=FE(edgeind,0); int f2=FE(edgeind,1); in int f1=FofE(edgeind,0); int f2=FofE(edgeind,1); Changed : in DiedralAngle(edgeind) : Point3d p0=FV(f1,0)->P(); Point3d p1=FV(f1,1)->P(); Point3d p2=FV(f1,2)->P(); in Point3d p0=_v[FofV(f1,0)]; Point3d p1=_v[FofV(f1,1)]; Point3d p2=_v[FofV(f1,2)]; Changed : in DiedralAngle(edgeind) : p0=FV(f2,0)->P(); p1=FV(f2,1)->P(); p2=FV(f2,2)->P(); in p0=_v[FofV(f2,0)]; p1=_v[FofV(f2,1)]; p2=_v[FofV(f2,2)]; Revision 1.2 2004/04/28 11:37:15 pietroni *** empty log message *** Revision 1.1 2004/04/22 13:19:12 ganovelli first version Revision 1.2 2004/04/20 16:26:48 pietroni *** empty log message *** Revision 1.1 2004/04/15 08:54:20 pietroni *** empty log message *** Revision 1.1 2004/04/08 01:13:31 pietroni Initial commit ****************************************************************************/ #ifndef __VCG_TETRA3 #define __VCG_TETRA3 #include #include #include namespace vcg { /** \addtogroup space */ /*@{*/ /** Templated class for storing a generic tetrahedron */ class Tetra { public: //Tatrahedron Functions to retrieve information about relation between faces of tetrahedron(faces,adges,vertices). static int VofE(const int &indexE,const int &indexV) { assert ((indexE<6)&&(indexV<2)); static int edgevert[6][2] ={{0,1}, {0,2}, {0,3}, {1,2}, {1,3}, {2,3}}; return (edgevert[indexE][indexV]); } static int VofF(const int &indexF,const int &indexV) { assert ((indexF<4)&&(indexV<3)); static int facevert[4][3]={{0,1,2}, {0,3,1}, {0,2,3}, {1,3,2}}; return (facevert[indexF][indexV]); } static int EofV(const int &indexV,const int &indexE) { assert ((indexE<3)&&(indexV<4)); static int vertedge[4][3]={{0,1,2}, {0,3,4}, {5,1,3}, {4,5,2}}; return vertedge[indexV][indexE]; } static int EofF(const int &indexF,const int &indexE) { assert ((indexF<4)&&(indexE<3)); static int faceedge[4][3]={{0,3,1}, {2,4,0}, {1,5,2}, {4,5,3} }; return faceedge [indexF][indexE]; } static int FofV(const int &indexV,const int &indexF) { assert ((indexV<4)&&(indexF<3)); static int vertface[4][3]={{0,1,2}, {0,3,1}, {0,2,3}, {1,3,2}}; return vertface[indexV][indexF]; } static int FofE(const int &indexE,const int &indexSide) { assert ((indexE<6)&&(indexSide<2)); static int edgeface[6][2]={{0,1}, {0,2}, {1,2}, {0,3}, {1,3}, {2,3}}; return edgeface [indexE][indexSide]; } static int VofEE(const int &indexE0,const int &indexE1) { assert ((indexE0<6)&&(indexE0>=0)); assert ((indexE1<6)&&(indexE1>=0)); static int edgesvert[6][6]={{-1,0,0,1,1,-1}, {0,-1,0,2,-1,2}, {0,0,-1,-1,3,3}, {1,2,-1,-1,1,2}, {1,-1,3,1,-1,3}, {-1,2,3,2,3,-1}}; return (edgesvert[indexE0][indexE1]); } static int VofFFF(const int &indexF0,const int &indexF1,const int &indexF2) { assert ((indexF0<4)&&(indexF0>=0)); assert ((indexF1<4)&&(indexF1>=0)); assert ((indexF2<4)&&(indexF2>=0)); static int facesvert[4][4][4]={ {//0 {-1,-1,-1,-1},{-1,-1,0,1},{-1,0,-1,2},{-1,1,2,-1} }, {//1 {-1,-1,0,1},{-1,-1,-1,-1},{0,-1,-1,3},{1,-1,3,-1} }, {//2 {-1,0,-1,2},{0,-1,-1,3},{-1,-1,-1,-1},{2,3,-1,-1} }, {//3 {-1,1,2,-1},{1,-1,3,-1},{2,3,-1,-1},{-1,-1,-1,-1} } }; return facesvert[indexF0][indexF1][indexF2]; } static int EofFF(const int &indexF0,const int &indexF1) { assert ((indexF0<4)&&(indexF0>=0)); assert ((indexF1<4)&&(indexF1>=0)); static int facesedge[4][4]={{-1, 0, 1, 3}, { 0, -1, 2, 4}, { 1, 2, -1, 5}, { 3, 4, 5, -1}}; return (facesedge[indexF0][indexF1]); } static int EofVV(const int &indexV0,const int &indexV1) { assert ((indexV0<4)&&(indexV0>=0)); assert ((indexV1<4)&&(indexV1>=0)); static int verticesedge[4][4]={{-1, 0, 1, 2}, { 0, -1, 3, 4}, { 1, 3, -1, 5}, { 2, 4, 5, -1}}; return verticesedge[indexV0][indexV1]; } static int FofVVV(const int &indexV0,const int &indexV1,const int &indexV2) { assert ((indexV0<4)&&(indexV0>=0)); assert ((indexV1<4)&&(indexV1>=0)); assert ((indexV2<4)&&(indexV2>=0)); static int verticesface[4][4][4]={ {//0 {-1,-1,-1,-1},{-1,-1,0,1},{-1,0,-1,2},{-1,1,2,-1} }, {//1 {-1,-1,0,1},{-1,-1,-1,-1},{0,-1,-1,3},{1,-1,3,-1} }, {//2 {-1,0,-1,2},{0,-1,-1,3},{-1,-1,-1,-1},{2,3,-1,-1} }, {//3 {-1,1,2,-1},{1,-1,3,-1},{2,3,-1,-1},{-1,-1,-1,-1} } }; return verticesface[indexV0][indexV1][indexV2]; } static int FofEE(const int &indexE0,const int &indexE1) { assert ((indexE0<6)&&(indexE0>=0)); assert ((indexE1<6)&&(indexE1>=0)); static int edgesface[6][6]={{-1,0,1,0,1,-1}, {0,-1,2,0,-1,2}, {1,2,-1,-1,1,2}, {0,0,-1,-1,3,3}, {1,-1,1,3,-1,3}, {-1,2,2,3,3,-1}}; return edgesface[indexE0][indexE1]; } }; /** Templated class for storing a generic tetrahedron in a 3D space. Note the relation with the Face class of TetraMesh complex, both classes provide the P(i) access functions to their points and therefore they share the algorithms on it (e.g. area, normal etc...) */ template class Tetra3:public Tetra { public: typedef Point3< ScalarType > CoordType; //typedef typename ScalarType ScalarType; /********************************************* **/ private: /// Vector of the 4 points that defines the tetrahedron CoordType _v[4]; public: /// Shortcut per accedere ai punti delle facce inline CoordType & P( const int j ) { return _v[j];} inline CoordType const & cP( const int j )const { return _v[j];} inline CoordType & P0( const int j ) { return _v[j];} inline CoordType & P1( const int j ) { return _v[(j+1)%4];} inline CoordType & P2( const int j ) { return _v[(j+2)%4];} inline CoordType & P3( const int j ) { return _v[(j+3)%4];} inline const CoordType & P0( const int j ) const { return _v[j];} inline const CoordType & P1( const int j ) const { return _v[(j+1)%4];} inline const CoordType & P2( const int j ) const { return _v[(j+2)%4];} inline const CoordType & P3( const int j ) const { return _v[(j+3)%4];} inline const CoordType & cP0( const int j ) const { return _v[j];} inline const CoordType & cP1( const int j ) const { return _v[(j+1)%4];} inline const CoordType & cP2( const int j ) const { return _v[(j+2)%4];} inline const CoordType & cP3( const int j ) const { return _v[(j+3)%4];} /// compute and return the barycenter of a tetrahedron CoordType ComputeBarycenter() { return((_v[0] + _v[1] + _v[2]+ _v[3])/4); } /// compute and return the solid angle on a vertex double SolidAngle(int vind) { double da0=DiedralAngle(EofV(vind,0)); double da1=DiedralAngle(EofV(vind,1)); double da2=DiedralAngle(EofV(vind,2)); return((da0 + da1 + da2)- M_PI); } /// compute and return the diadedral angle on an edge double DiedralAngle(int edgeind) { int f1=FofE(edgeind,0); int f2=FofE(edgeind,1); CoordType p0=_v[FofV(f1,0)]; CoordType p1=_v[FofV(f1,1)]; CoordType p2=_v[FofV(f1,2)]; CoordType norm1=((p1-p0)^(p2-p0)); p0=_v[FofV(f2,0)]; p1=_v[FofV(f2,1)]; p2=_v[FofV(f2,2)]; CoordType norm2=((p1-p0)^(p2-p0)); norm1.Normalize(); norm2.Normalize(); return (M_PI-acos(double(norm1*norm2))); } /// compute and return the aspect ratio of the tetrahedron ScalarType ComputeAspectRatio() { double a0=SolidAngle(0); double a1=SolidAngle(1); double a2=SolidAngle(2); double a3=SolidAngle(3); return (ScalarType)math::Min(a0,math::Min(a1,math::Min(a2,a3))); } ///return true of p is inside tetrahedron's volume bool IsInside(const CoordType &p) { //bb control vcg::Box3 bb; for (int i=0;i<4;i++) bb.Add(_v[i]); if (!bb.IsIn(p)) return false; vcg::Matrix44 M0; vcg::Matrix44 M1; vcg::Matrix44 M2; vcg::Matrix44 M3; vcg::Matrix44 M4; CoordType p1=_v[0]; CoordType p2=_v[1]; CoordType p3=_v[2]; CoordType p4=_v[3]; M0[0][0]=p1.V(0); M0[0][1]=p1.V(1); M0[0][2]=p1.V(2); M0[1][0]=p2.V(0); M0[1][1]=p2.V(1); M0[1][2]=p2.V(2); M0[2][0]=p3.V(0); M0[2][1]=p3.V(1); M0[2][2]=p3.V(2); M0[3][0]=p4.V(0); M0[3][1]=p4.V(1); M0[3][2]=p4.V(2); M0[0][3]=1; M0[1][3]=1; M0[2][3]=1; M0[3][3]=1; M1=M0; M1[0][0]=p.V(0); M1[0][1]=p.V(1); M1[0][2]=p.V(2); M2=M0; M2[1][0]=p.V(0); M2[1][1]=p.V(1); M2[1][2]=p.V(2); M3=M0; M3[2][0]=p.V(0); M3[2][1]=p.V(1); M3[2][2]=p.V(2); M4=M0; M4[3][0]=p.V(0); M4[3][1]=p.V(1); M4[3][2]=p.V(2); ScalarType d0=M0.Determinant(); ScalarType d1=M1.Determinant(); ScalarType d2=M2.Determinant(); ScalarType d3=M3.Determinant(); ScalarType d4=M4.Determinant(); // all determinant must have same sign return (((d0>0)&&(d1>0)&&(d2>0)&&(d3>0)&&(d4>0))||((d0<0)&&(d1<0)&&(d2<0)&&(d3<0)&&(d4<0))); } void InterpolationParameters(const CoordType & bq, ScalarType &a, ScalarType &b, ScalarType &c ,ScalarType &d) { const ScalarType EPSILON = ScalarType(0.000001); Matrix33 M; CoordType v0=P(0)-P(2); CoordType v1=P(1)-P(2); CoordType v2=P(3)-P(2); CoordType v3=bq-P(2); M[0][0]=v0.X(); M[1][0]=v0.Y(); M[2][0]=v0.Z(); M[0][1]=v1.X(); M[1][1]=v1.Y(); M[2][1]=v1.Z(); M[0][2]=v2.X(); M[1][2]=v2.Y(); M[2][2]=v2.Z(); Matrix33 inv_M =vcg::Inverse(M); CoordType Barycentric=inv_M*v3; a=Barycentric.V(0); b=Barycentric.V(1); c=Barycentric.V(2); d=1-(a+b+c); } }; //end Class // compute the barycenter template Point3 Barycenter(const Tetra3 &t) { return ((t.cP(0)+t.cP(1)+t.cP(2)+t.cP(3))/(ScalarType) 4.0); } // compute and return the volume of a tetrahedron template typename TetraType::ScalarType ComputeVolume( const TetraType & t){ return (typename TetraType::ScalarType)((( t.cP(2)-t.cP(0))^(t.cP(1)-t.cP(0) ))*(t.cP(3)-t.cP(0))/6.0); } /// Returns the normal to the face face of the tetrahedron t template Point3 Normal( const TetraType &t,const int &face) { return(((t.cP(Tetra::VofF(face,1))-t.cP(Tetra::VofF(face,0)))^(t.cP(Tetra::VofF(face,2))-t.cP(Tetra::VofF(face,0)))).Normalize()); } /*@}*/ } // end namespace #endif qutemol/vcg/vcg/space/color4.h0000444000175000017500000002611411003447027014630 0ustar mbamba/**************************************************************************** * VCGLib o o * * Visual and Computer Graphics Library o o * * _ O _ * * Copyright(C) 2004 \/)\/ * * Visual Computing Lab /\/| * * ISTI - Italian National Research Council | * * \ * * All rights reserved. * * * * 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. * * * * 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 (http://www.gnu.org/licenses/gpl.txt) * * for more details. * * * ****************************************************************************/ /**************************************************************************** History $Log: color4.h,v $ Revision 1.16 2008/04/22 20:44:07 cignoni added construct from and to float Revision 1.15 2007/09/21 11:34:10 ponchio Just a clarification comment Revision 1.14 2006/06/08 08:52:02 zifnab1974 gcc 4 needs the extra template keyword Revision 1.13 2005/06/24 12:21:48 ponchio Fixed "lerp" function. Revision 1.12 2005/04/14 11:35:09 ponchio *** empty log message *** Revision 1.11 2004/09/09 12:51:28 fasano corrected ColorRamp code (template specialization) Revision 1.10 2004/09/09 08:39:33 cignoni added a 'template<>' to the specialized constructors from a enum Revision 1.9 2004/09/03 13:58:48 fasano Corretto errore sintattico nelle specializzazioni parziali (float e char) di due costruttori di Color4 Revision 1.8 2004/07/15 11:01:43 ganovelli added inclusion of point3.h Revision 1.7 2004/06/24 07:55:50 cignoni Now color ramp can do reverse color ramp Revision 1.6 2004/05/26 15:10:29 cignoni Corrected bug in setgrayshade Revision 1.5 2004/05/07 12:46:55 cignoni added ifdef for gcc [Bug c++/14479] Revision 1.4 2004/05/07 10:06:55 cignoni Corrected template specialization syntax for gcc compiling Revision 1.3 2004/03/10 21:38:40 cignoni Written some documentation and added to the space module Revision 1.2 2004/03/10 00:35:01 cignoni Removed a wrong (?) copy constructor Revision 1.1 2004/02/10 01:11:28 cignoni Edited Comments and GPL license ****************************************************************************/ #ifndef __VCGLIB_COLOR4 #define __VCGLIB_COLOR4 #include #include namespace vcg { /** \addtogroup space */ /*@{*/ /** The templated class for representing 4 entity color. The class is templated over the ScalarType. class that is used to represent color with float or with unsigned chars. All the usual operator overloading (* + - ...) is present. */ template class Color4 : public Point4 { public: /// Constant for storing standard colors. /// Each color is stored in a simple in so that the bit pattern match with the one of Color4b. enum ColorConstant { Black =0xff000000, Gray =0xff808080, White =0xffffffff, Red =0xff0000ff, Green =0xff00ff00, Blue =0xffff0000, Cyan =0xffffff00, Yellow =0xff00ffff, Magenta=0xffff00ff, LightGray =0xffc0c0c0, LightRed =0xff8080ff, LightGreen =0xff80ff80, LightBlue =0xffff8080, DarkGray =0xff404040, DarkRed =0xff000040, DarkGreen =0xff004000, DarkBlue =0xff400000 }; inline Color4 ( const T nx, const T ny, const T nz , const T nw ) :Point4(nx,ny,nz,nw) {}; // inline Color4 ( Color4 &c) :Point4(c) {}; inline Color4 (){}; inline Color4 (ColorConstant cc); template inline void Import(const Color4 & b ) { Point4::_v[0] = T(b[0]); Point4::_v[1] = T(b[1]); Point4::_v[2] = T(b[2]); Point4::_v[3] = T(b[3]); } template inline void Import(const Point4 & b ) { Point4::_v[0] = T(b[0]); Point4::_v[1] = T(b[1]); Point4::_v[2] = T(b[2]); Point4::_v[3] = T(b[3]); } template static inline Color4 Construct( const Color4 & b ) { return Color4(T(b[0]),T(b[1]),T(b[2]),T(b[3])); } //inline void Import(const Color4 &b); //inline void Import(const Color4 &b); inline void lerp(const Color4 &c0, const Color4 &c1, const float x); inline void lerp(const Color4 &c0, const Color4 &c1, const Color4 &c2, const Point3f &ip); /// given a float and a range set the corresponding color in the well known red->green->blue color ramp. To reverse the direction of the ramp just swap minf and maxf. inline void ColorRamp(const float &minf,const float &maxf ,float v ); inline void SetRGB( unsigned char r, unsigned char g, unsigned char b ) { Point4::_v[0] = r; Point4::_v[1] = g; Point4::_v[2] = b; Point4::_v[3] = 0; } void SetHSVColor( float h, float s, float v){ float r,g,b; if(s==0.0){ // gray color r = g = b = v; Point4::_v[0]=(unsigned char)(255*r); Point4::_v[1]=(unsigned char)(255*g); Point4::_v[2]=(unsigned char)(255*b); Point4::_v[3]=255; return; } if(h==1.0) h = 0.0; int i = int( floor(h*6.0) ); float f = float(h*6.0f - floor(h*6.0f)); float p = v*(1.0f-s); float q = v*(1.0f-s*f); float t = v*(1.0f-s*(1.0f-f)); switch(i){ case 0: r=v; g=t; b=p; break; case 1: r=q; g=v; b=p; break; case 2: r=p; g=v; b=t; break; case 3: r=p; g=q; b=v; break; case 4: r=t; g=p; b=v; break; case 5: r=v; g=p; b=q; break; } Point4::_v[0]=(unsigned char)(255*r); Point4::_v[1]=(unsigned char)(255*g); Point4::_v[2]=(unsigned char)(255*b); Point4::_v[3]=255; // _v[0]=r*256;_v[1]=g*256;_v[2]=b*256; } inline static Color4 GrayShade(float f) { return Color4(f,f,f,1); } inline void SetGrayShade(float f) { Import(Color4(f,f,f,1)); } /** Given an integer returns a well ordering of colors // so that every color differs as much as possible form the previous one // params: // n is the maximum expected value (max of the range) // v is the requested position */ inline static Color4 Scatter(int n, int a,float Sat=.3f,float Val=.9f) { int b, k, m=n; int r =n; for (b=0, k=1; k=m) { if (b==0) r = k; b += k; a -= (m+1)>>1; m >>= 1; } else m = (m+1)>>1; if (r>n-b) r = n-b; //TRACE("Scatter range 0..%i, in %i out %i\n",n,a,b); Color4 rc; rc.SetHSVColor(float(b)/float(n),Sat,Val); return rc; } }; template inline void Color4::lerp(const Color4 &c0, const Color4 &c1, const float x) { assert(x>=0); assert(x<=1); Point4::_v[0]=(T)(c1._v[0]*x + c0._v[0]*(1.0f-x)); Point4::_v[1]=(T)(c1._v[1]*x + c0._v[1]*(1.0f-x)); Point4::_v[2]=(T)(c1._v[2]*x + c0._v[2]*(1.0f-x)); Point4::_v[3]=(T)(c1._v[3]*x + c0._v[3]*(1.0f-x)); } template inline void Color4::lerp(const Color4 &c0, const Color4 &c1, const Color4 &c2, const Point3f &ip) { assert(fabs(ip[0]+ip[1]+ip[2]-1)<0.00001); Point4::_v[0]=(T)(c0[0]*ip[0] + c1[0]*ip[1]+ c2[0]*ip[2]); Point4::_v[1]=(T)(c0[1]*ip[0] + c1[1]*ip[1]+ c2[1]*ip[2]); Point4::_v[2]=(T)(c0[2]*ip[0] + c1[2]*ip[1]+ c2[2]*ip[2]); Point4::_v[3]=(T)(c0[3]*ip[0] + c1[3]*ip[1]+ c2[3]*ip[2]); } template inline void Color4::ColorRamp(const float &minf,const float &maxf ,float v ) { if(minf>maxf) { ColorRamp(maxf,minf,maxf+(minf-v)); return; } if(v < minf ) { *this=Color4(Color4::Red); return; } //the case v > maxf is handled automatically at the end of the function float step=(maxf-minf)/4; v-=minf; if(v(Color4::Red), Color4(Color4::Yellow),v/step); return;} v-=step; if(v(Color4::Yellow),Color4(Color4::Green),v/step);return;} v-=step; if(v(Color4::Green),Color4(Color4::Cyan),v/step); return;} v-=step; if(v(Color4::Cyan),Color4(Color4::Blue),v/step); return;} *this= Color4(Color4::Blue); } #if !defined(__GNUC__) || (__GNUC__ > 3) template <> #endif template <> inline void Color4::Import(const Color4 &b) { this->_v[0]=b[0]/255.0f; this->_v[1]=b[1]/255.0f; this->_v[2]=b[2]/255.0f; this->_v[3]=b[3]/255.0f; } #if !defined(__GNUC__) || (__GNUC__ > 3) template <> // [Bug c++/14479] enum definition in template class with template methods causes error. #endif template <> inline void Color4::Import(const Color4 &b) { this->_v[0]=(unsigned char)(b[0]*255.0f); this->_v[1]=(unsigned char)(b[1]*255.0f); this->_v[2]=(unsigned char)(b[2]*255.0f); this->_v[3]=(unsigned char)(b[3]*255.0f); } #if !defined(__GNUC__) || (__GNUC__ > 3) template <> // [Bug c++/14479] enum definition in template class with template methods causes error. #endif template <> inline void Color4::Import(const Point4 &b) { this->_v[0]=(unsigned char)(b[0]*255.0f); this->_v[1]=(unsigned char)(b[1]*255.0f); this->_v[2]=(unsigned char)(b[2]*255.0f); this->_v[3]=(unsigned char)(b[3]*255.0f); } #if !defined(__GNUC__) || (__GNUC__ > 3) template <> #endif template <> inline Color4 Color4::Construct( const Color4 & b ) { return Color4( (unsigned char)(b[0]*255.0f), (unsigned char)(b[1]*255.0f), (unsigned char)(b[2]*255.0f), (unsigned char)(b[3]*255.0f)); } #if !defined(__GNUC__) || (__GNUC__ > 3) template <> #endif template <> inline Color4 Color4::Construct( const Color4 & b ) { return Color4( (float)(b[0])/255.0f, (float)(b[1])/255.0f, (float)(b[2])/255.0f, (float)(b[3])/255.0f); } //template //inline void Color4::Import(const Color4 &b) //{ // _v[0] = T(b[0]); // _v[1] = T(b[1]); // _v[2] = T(b[2]); // _v[3] = T(b[3]); //} // template<> inline Color4::Color4(Color4::ColorConstant cc) { *((int *)this )= cc; } template<> inline Color4::Color4(Color4::ColorConstant cc) { Import(Color4((Color4::ColorConstant)cc)); } typedef Color4 Color4b; typedef Color4 Color4f; /*@}*/ } // end of NameSpace #endif qutemol/vcg/vcg/space/point4.h0000444000175000017500000002530010446224155014644 0ustar mbamba/**************************************************************************** * VCGLib o o * * Visual and Computer Graphics Library o o * * _ O _ * * Copyright(C) 2004 \/)\/ * * Visual Computing Lab /\/| * * ISTI - Italian National Research Council | * * \ * * All rights reserved. * * * * 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. * * * * 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 (http://www.gnu.org/licenses/gpl.txt) * * for more details. * * * ****************************************************************************/ /**************************************************************************** History $Log: point4.h,v $ Revision 1.13 2006/06/21 11:07:25 ganovelli forgot & Revision 1.12 2006/06/21 11:06:16 ganovelli changed return type of Zero() (to void) Revision 1.11 2005/04/13 09:40:30 ponchio Including math/bash.h Revision 1.10 2005/03/18 16:34:42 fiorin minor changes to comply gcc compiler Revision 1.9 2005/01/21 18:02:11 ponchio Removed dependence from matrix44 and changed VectProd Revision 1.8 2005/01/12 11:25:02 ganovelli added Dimension Revision 1.7 2004/10/11 17:46:11 ganovelli added definition of vector product (not implemented) Revision 1.6 2004/05/10 11:16:19 ganovelli include assert.h added Revision 1.5 2004/03/31 10:09:58 cignoni missing return value in zero() Revision 1.4 2004/03/11 17:17:49 tarini added commets (doxy), uniformed with new style, now using math::, ... added HomoNormalize(), Zero()... remade StableDot() (hand made sort). Revision 1.1 2004/02/10 01:11:28 cignoni Edited Comments and GPL license ****************************************************************************/ #ifndef __VCGLIB_POINT4 #define __VCGLIB_POINT4 #include #include namespace vcg { /** \addtogroup space */ /*@{*/ /** The templated class for representing a point in 4D space. The class is templated over the ScalarType class that is used to represent coordinates. All the usual operator (* + - ...) are defined. */ template class Point4 { public: /// The only data member. Hidden to user. T _v[4]; public: typedef T ScalarType; enum {Dimension = 4}; //@{ /** @name Standard Constructors and Initializers No casting operators have been introduced to avoid automatic unattended (and costly) conversion between different point types **/ inline Point4 () { } inline Point4 ( const T nx, const T ny, const T nz , const T nw ) { _v[0] = nx; _v[1] = ny; _v[2] = nz; _v[3] = nw; } inline Point4 ( const T p[4] ) { _v[0] = p[0]; _v[1]= p[1]; _v[2] = p[2]; _v[3]= p[3]; } inline Point4 ( const Point4 & p ) { _v[0]= p._v[0]; _v[1]= p._v[1]; _v[2]= p._v[2]; _v[3]= p._v[3]; } inline void Zero() { _v[0] = _v[1] = _v[2] = _v[3]= 0; } template /// importer from different Point4 types inline void Import( const Point4 & b ) { _v[0] = T(b[0]); _v[1] = T(b[1]); _v[2] = T(b[2]); _v[3] = T(b[3]); } /// constuctor that imports from different Point4 types template static inline Point4 Construct( const Point4 & b ) { return Point4(T(b[0]),T(b[1]),T(b[2]),T(b[3])); } //@} //@{ /** @name Data Access. access to data is done by overloading of [] or explicit naming of coords (x,y,z,w) **/ inline const T & operator [] ( const int i ) const { assert(i>=0 && i<4); return _v[i]; } inline T & operator [] ( const int i ) { assert(i>=0 && i<4); return _v[i]; } inline T &X() {return _v[0];} inline T &Y() {return _v[1];} inline T &Z() {return _v[2];} inline T &W() {return _v[3];} inline T const * V() const { return _v; } inline const T & V ( const int i ) const { assert(i>=0 && i<4); return _v[i]; } inline T & V ( const int i ) { assert(i>=0 && i<4); return _v[i]; } /// Padding function: give a default 0 value to all the elements that are not in the [0..2] range. /// Useful for managing in a consistent way object that could have point2 / point3 / point4 inline T Ext( const int i ) const { if(i>=0 && i<=3) return _v[i]; else return 0; } //@} //@{ /** @name Linear operators and the likes **/ inline Point4 operator + ( const Point4 & p) const { return Point4( _v[0]+p._v[0], _v[1]+p._v[1], _v[2]+p._v[2], _v[3]+p._v[3] ); } inline Point4 operator - ( const Point4 & p) const { return Point4( _v[0]-p._v[0], _v[1]-p._v[1], _v[2]-p._v[2], _v[3]-p._v[3] ); } inline Point4 operator * ( const T s ) const { return Point4( _v[0]*s, _v[1]*s, _v[2]*s, _v[3]*s ); } inline Point4 operator / ( const T s ) const { return Point4( _v[0]/s, _v[1]/s, _v[2]/s, _v[3]/s ); } inline Point4 & operator += ( const Point4 & p) { _v[0] += p._v[0]; _v[1] += p._v[1]; _v[2] += p._v[2]; _v[3] += p._v[3]; return *this; } inline Point4 & operator -= ( const Point4 & p ) { _v[0] -= p._v[0]; _v[1] -= p._v[1]; _v[2] -= p._v[2]; _v[3] -= p._v[3]; return *this; } inline Point4 & operator *= ( const T s ) { _v[0] *= s; _v[1] *= s; _v[2] *= s; _v[3] *= s; return *this; } inline Point4 & operator /= ( const T s ) { _v[0] /= s; _v[1] /= s; _v[2] /= s; _v[3] /= s; return *this; } inline Point4 operator - () const { return Point4( -_v[0], -_v[1], -_v[2], -_v[3] ); } inline Point4 VectProd ( const Point4 &x, const Point4 &z ) const { Point4 res; const Point4 &y = *this; res[0] = y[1]*x[2]*z[3]-y[1]*x[3]*z[2]-x[1]*y[2]*z[3]+ x[1]*y[3]*z[2]+z[1]*y[2]*x[3]-z[1]*y[3]*x[2]; res[1] = y[0]*x[3]*z[2]-z[0]*y[2]*x[3]-y[0]*x[2]* z[3]+z[0]*y[3]*x[2]+x[0]*y[2]*z[3]-x[0]*y[3]*z[2]; res[2] = -y[0]*z[1]*x[3]+x[0]*z[1]*y[3]+y[0]*x[1]* z[3]-x[0]*y[1]*z[3]-z[0]*x[1]*y[3]+z[0]*y[1]*x[3]; res[3] = -z[0]*y[1]*x[2]-y[0]*x[1]*z[2]+x[0]*y[1]* z[2]+y[0]*z[1]*x[2]-x[0]*z[1]*y[2]+z[0]*x[1]*y[2]; return res; } //@} //@{ /** @name Norms and normalizations **/ /// Euclidian normal inline T Norm() const { return math::Sqrt( _v[0]*_v[0] + _v[1]*_v[1] + _v[2]*_v[2] + _v[3]*_v[3] ); } /// Squared euclidian normal inline T SquaredNorm() const { return _v[0]*_v[0] + _v[1]*_v[1] + _v[2]*_v[2] + _v[3]*_v[3]; } /// Euclidian normalization inline Point4 & Normalize() { T n = sqrt(_v[0]*_v[0] + _v[1]*_v[1] + _v[2]*_v[2] + _v[3]*_v[3] ); if(n>0.0) { _v[0] /= n; _v[1] /= n; _v[2] /= n; _v[3] /= n; } return *this; } /// Homogeneous normalization (division by W) inline Point4 & HomoNormalize(){ if (_v[3]!=0.0) { _v[0] /= _v[3]; _v[1] /= _v[3]; _v[2] /= _v[3]; _v[3]=1.0; } return *this; }; //@} //@{ /** @name Comparison operators (lexicographical order) **/ inline bool operator == ( const Point4& p ) const { return _v[0]==p._v[0] && _v[1]==p._v[1] && _v[2]==p._v[2] && _v[3]==p._v[3]; } inline bool operator != ( const Point4 & p ) const { return _v[0]!=p._v[0] || _v[1]!=p._v[1] || _v[2]!=p._v[2] || _v[3]!=p._v[3]; } inline bool operator < ( Point4 const & p ) const { return (_v[3]!=p._v[3])?(_v[3] ( const Point4 & p ) const { return (_v[3]!=p._v[3])?(_v[3]>p._v[3]): (_v[2]!=p._v[2])?(_v[2]>p._v[2]): (_v[1]!=p._v[1])?(_v[1]>p._v[1]): (_v[0]>p._v[0]); } inline bool operator <= ( const Point4 & p ) const { return (_v[3]!=p._v[3])?(_v[3]< p._v[3]): (_v[2]!=p._v[2])?(_v[2]< p._v[2]): (_v[1]!=p._v[1])?(_v[1]< p._v[1]): (_v[0]<=p._v[0]); } inline bool operator >= ( const Point4 & p ) const { return (_v[3]!=p._v[3])?(_v[3]> p._v[3]): (_v[2]!=p._v[2])?(_v[2]> p._v[2]): (_v[1]!=p._v[1])?(_v[1]> p._v[1]): (_v[0]>=p._v[0]); } //@} //@{ /** @name Dot products **/ // dot product inline T operator * ( const Point4 & p ) const { return _v[0]*p._v[0] + _v[1]*p._v[1] + _v[2]*p._v[2] + _v[3]*p._v[3]; } inline Point4 operator ^ ( const Point4& p ) const { assert(0);// not defined by two vectors (only put for metaprogramming) return Point4(); } /// slower version, more stable (double precision only) T StableDot ( const Point4 & p ) const { T k0=_v[0]*p._v[0], k1=_v[1]*p._v[1], k2=_v[2]*p._v[2], k3=_v[3]*p._v[3]; int exp0,exp1,exp2,exp3; frexp( double(k0), &exp0 );frexp( double(k1), &exp1 ); frexp( double(k2), &exp2 );frexp( double(k3), &exp3 ); if (exp0>exp1) { math::Swap(k0,k1); math::Swap(exp0,exp1); } if (exp2>exp3) { math::Swap(k2,k3); math::Swap(exp2,exp3); } if (exp0>exp2) { math::Swap(k0,k2); math::Swap(exp0,exp2); } if (exp1>exp3) { math::Swap(k1,k3); math::Swap(exp1,exp3); } if (exp2>exp3) { math::Swap(k2,k3); math::Swap(exp2,exp3); } return ( (k0 + k1) + k2 ) +k3; } //@} }; // end class definition template T Angle( const Point4& p1, const Point4 & p2 ) { T w = p1.Norm()*p2.Norm(); if(w==0) return -1; T t = (p1*p2)/w; if(t>1) t=1; return T( math::Acos(t) ); } template inline T Norm( const Point4 & p ) { return p.Norm(); } template inline T SquaredNorm( const Point4 & p ) { return p.SquaredNorm(); } template inline T Distance( const Point4 & p1, const Point4 & p2 ) { return Norm(p1-p2); } template inline T SquaredDistance( const Point4 & p1, const Point4 & p2 ) { return SquaredNorm(p1-p2); } /// slower version of dot product, more stable (double precision only) template double StableDot ( Point4 const & p0, Point4 const & p1 ) { return p0.StableDot(p1); } typedef Point4 Point4s; typedef Point4 Point4i; typedef Point4 Point4f; typedef Point4 Point4d; /*@}*/ } // end namespace #endif qutemol/vcg/vcg/space/point.h0000444000175000017500000006501610553546420014571 0ustar mbamba/**************************************************************************** * VCGLib o o * * Visual and Computer Graphics Library o o * * _ O _ * * Copyright(C) 2004 \/)\/ * * Visual Computing Lab /\/| * * ISTI - Italian National Research Council | * * \ * * All rights reserved. * * * * 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. * * * * 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 (http://www.gnu.org/licenses/gpl.txt) * * for more details. * * * ****************************************************************************/ /**************************************************************************** History $Log: point.h,v $ Revision 1.10 2007/01/18 01:27:44 cignoni Corrected a syntax error in stabledot Revision 1.9 2006/12/20 15:23:52 ganovelli using of locally defined variable removed Revision 1.8 2006/04/11 08:10:05 zifnab1974 changes necessary for gcc 3.4.5 on linux 64bit. Revision 1.7 2005/12/12 11:22:32 ganovelli compiled with gcc Revision 1.6 2005/01/12 11:25:52 ganovelli corrected Point<3 Revision 1.5 2004/10/20 16:45:21 ganovelli first compiling version (MC,INtel,gcc) Revision 1.4 2004/04/29 10:47:06 ganovelli some siyntax error corrected Revision 1.3 2004/04/05 12:36:43 tarini unified version: PointBase version, with no guards "(N==3)" Revision 1.1 2004/03/16 03:07:38 tarini "dimensionally unified" version: first commit ****************************************************************************/ #ifndef __VCGLIB_POINT #define __VCGLIB_POINT #include #include #include namespace vcg { namespace ndim{ template class Point; /** \addtogroup space */ /*@{*/ /** The templated class for representing a point in R^N space. The class is templated over the ScalarType class that is used to represent coordinates. PointBase provides the interface and the common operators for points of any dimensionality. */ template class PointBase { public: typedef S ScalarType; typedef VoidType ParamType; typedef Point PointType; enum {Dimension=N}; protected: /// The only data member. Hidden to user. S _v[N]; public: //@{ /** @name Standard Constructors and Initializers No casting operators have been introduced to avoid automatic unattended (and costly) conversion between different PointType types **/ inline PointBase () { }; // inline PointBase ( const S nv[N] ); /// Padding function: give a default 0 value to all the elements that are not in the [0..2] range. /// Useful for managing in a consistent way object that could have point2 / point3 / point4 inline S Ext( const int i ) const { if(i>=0 && i<=N) return _v[i]; else return 0; } /// importer for points with different scalar type and-or dimensionality template inline void Import( const Point & b ) { _v[0] = ScalarType(b[0]); _v[1] = ScalarType(b[1]); if (N>2) { if (N2>2) _v[2] = ScalarType(b[2]); else _v[2] = 0;}; if (N>3) { if (N2>3) _v[3] = ScalarType(b[3]); else _v[3] = 0;}; } /// constructor for points with different scalar type and-or dimensionality template static inline PointType Construct( const Point & b ) { PointType p; p.Import(b); return p; } /// importer for homogeneous points template inline void ImportHomo( const Point & b ) { _v[0] = ScalarType(b[0]); _v[1] = ScalarType(b[1]); if (N>2) { _v[2] = ScalarType(_v[2]); }; _v[N-1] = 1.0; } /// constructor for homogeneus point. template static inline PointType Construct( const Point & b ) { PointType p; p.ImportHomo(b); return p; } //@} //@{ /** @name Data Access. access to data is done by overloading of [] or explicit naming of coords (x,y,z)**/ inline S & operator [] ( const int i ) { assert(i>=0 && i=0 && i2); return _v[2]; } /// W is in any case the last coordinate. /// (in a 2D point, W() == Y(). In a 3D point, W()==Z() /// in a 4D point, W() is a separate component) inline const S &W() const { return _v[N-1]; } inline S &X() { return _v[0]; } inline S &Y() { return _v[1]; } inline S &Z() { static_assert(N>2); return _v[2]; } inline S &W() { return _v[N-1]; } inline const S * V() const { return _v; } inline S & V( const int i ) { assert(i>=0 && i=0 && i static S Norm(const PT &p ); /// Squared Euclidean norm inline S SquaredNorm() const; /// Squared Euclidean norm, static version template static S SquaredNorm(const PT &p ); /// Normalization (division by norm) inline PointType & Normalize(); /// Normalization (division by norm), static version template static PointType & Normalize(const PT &p); /// Homogeneous normalization (division by W) inline PointType & HomoNormalize(); /// norm infinity: largest absolute value of compoenet inline S NormInfinity() const; /// norm 1: sum of absolute values of components inline S NormOne() const; //@} /// Signed area operator /// a % b returns the signed area of the parallelogram inside a and b inline S operator % ( PointType const & p ) const; /// the sum of the components inline S Sum() const; /// returns the biggest component inline S Max() const; /// returns the smallest component inline S Min() const; /// returns the index of the biggest component inline int MaxI() const; /// returns the index of the smallest component inline int MinI() const; /// Per component scaling inline PointType & Scale( const PointType & p ); /// Convert to polar coordinates void ToPolar( S & ro, S & tetha, S & fi ) const { ro = Norm(); tetha = (S)atan2( _v[1], _v[0] ); fi = (S)acos( _v[2]/ro ); } //@{ /** @name Comparison Operators. Lexicographic order. **/ inline bool operator == ( PointType const & p ) const; inline bool operator != ( PointType const & p ) const; inline bool operator < ( PointType const & p ) const; inline bool operator > ( PointType const & p ) const; inline bool operator <= ( PointType const & p ) const; inline bool operator >= ( PointType const & p ) const; //@} //@{ /** @name Glocal to Local and viceversa (provided for uniformity with other spatial classes. trivial for points) **/ inline PointType LocalToGlobal(ParamType p) const{ return *this; } inline ParamType GlobalToLocal(PointType p) const{ ParamType p(); return p; } //@} }; // end class definition template class Point2 : public PointBase<2,S> { public: typedef S ScalarType; typedef Point2 PointType; using PointBase<2,S>::_v; using PointBase<2,S>::V; using PointBase<2,S>::W; //@{ /** @name Special members for 2D points. **/ /// default inline Point2 (){} /// yx constructor inline Point2 ( const S a, const S b){ _v[0]=a; _v[1]=b; }; /// unary orthogonal operator (2D equivalent of cross product) /// returns orthogonal vector (90 deg left) inline Point2 operator ~ () const { return Point2 ( -_v[2], _v[1] ); } /// returns the angle with X axis (radiants, in [-PI, +PI] ) inline ScalarType &Angle(){ return math::Atan2(_v[1],_v[0]);} /// transform the point in cartesian coords into polar coords inline Point2 & ToPolar(){ ScalarType t = Angle(); _v[0] = Norm(); _v[1] = t; return *this;} /// transform the point in polar coords into cartesian coords inline Point2 & ToCartesian() { ScalarType l = _v[0]; _v[0] = (ScalarType)(l*math::Cos(_v[1])); _v[1] = (ScalarType)(l*math::Sin(_v[1])); return *this;} /// rotates the point of an angle (radiants, counterclockwise) inline Point2 & Rotate( const ScalarType rad ){ ScalarType t = _v[0]; ScalarType s = math::Sin(rad); ScalarType c = math::Cos(rad); _v[0] = _v[0]*c - _v[1]*s; _v[1] = t *s + _v[1]*c; return *this;} //@} //@{ /** @name Implementation of standard functions for 3D points **/ inline void Zero(){ _v[0]=0; _v[1]=0; }; inline Point2 ( const S nv[2] ){ _v[0]=nv[0]; _v[1]=nv[1]; }; inline Point2 operator + ( Point2 const & p) const { return Point2( _v[0]+p._v[0], _v[1]+p._v[1]); } inline Point2 operator - ( Point2 const & p) const { return Point2( _v[0]-p._v[0], _v[1]-p._v[1]); } inline Point2 operator * ( const S s ) const { return Point2( _v[0]*s, _v[1]*s ); } inline Point2 operator / ( const S s ) const { S t=1.0/s; return Point2( _v[0]*t, _v[1]*t ); } inline Point2 operator - () const { return Point2 ( -_v[0], -_v[1] ); } inline Point2 & operator += ( Point2 const & p ) { _v[0] += p._v[0]; _v[1] += p._v[1]; return *this; } inline Point2 & operator -= ( Point2 const & p ) { _v[0] -= p._v[0]; _v[1] -= p._v[1]; return *this; } inline Point2 & operator *= ( const S s ) { _v[0] *= s; _v[1] *= s; return *this; } inline Point2 & operator /= ( const S s ) { S t=1.0/s; _v[0] *= t; _v[1] *= t; return *this; } inline S Norm() const { return math::Sqrt( _v[0]*_v[0] + _v[1]*_v[1] );} template static S Norm(const PT &p ) { return math::Sqrt( p.V(0)*p.V(0) + p.V(1)*p.V(1) );} inline S SquaredNorm() const { return ( _v[0]*_v[0] + _v[1]*_v[1] );} template static S SquaredNorm(const PT &p ) { return ( p.V(0)*p.V(0) + p.V(1)*p.V(1) );} inline S operator * ( Point2 const & p ) const { return ( _v[0]*p._v[0] + _v[1]*p._v[1]) ; } inline bool operator == ( Point2 const & p ) const { return _v[0]==p._v[0] && _v[1]==p._v[1] ;} inline bool operator != ( Point2 const & p ) const { return _v[0]!=p._v[0] || _v[1]!=p._v[1] ;} inline bool operator < ( Point2 const & p ) const{ return (_v[1]!=p._v[1])?(_v[1]< p._v[1]) : (_v[0] ( Point2 const & p ) const { return (_v[1]!=p._v[1])?(_v[1]> p._v[1]) : (_v[0]>p._v[0]); } inline bool operator <= ( Point2 const & p ) { return (_v[1]!=p._v[1])?(_v[1]< p._v[1]) : (_v[0]<=p._v[0]); } inline bool operator >= ( Point2 const & p ) const { return (_v[1]!=p._v[1])?(_v[1]> p._v[1]) : (_v[0]>=p._v[0]); } inline Point2 & Normalize() { PointType n = Norm(); if(n!=0.0) { n=1.0/n; _v[0]*=n; _v[1]*=n;} return *this;}; template Point2 & Normalize(const PT &p){ PointType n = Norm(); if(n!=0.0) { n=1.0/n; V(0)*=n; V(1)*=n; } return *this;}; inline Point2 & HomoNormalize(){ if (_v[2]!=0.0) { _v[0] /= W(); W()=1.0; } return *this;}; inline S NormInfinity() const { return math::Max( math::Abs(_v[0]), math::Abs(_v[1]) ); } inline S NormOne() const { return math::Abs(_v[0])+ math::Abs(_v[1]);} inline S operator % ( Point2 const & p ) const { return _v[0] * p._v[1] - _v[1] * p._v[0]; } inline S Sum() const { return _v[0]+_v[1];} inline S Max() const { return math::Max( _v[0], _v[1] ); } inline S Min() const { return math::Min( _v[0], _v[1] ); } inline int MaxI() const { return (_v[0] < _v[1]) ? 1:0; }; inline int MinI() const { return (_v[0] > _v[1]) ? 1:0; }; inline PointType & Scale( const PointType & p ) { _v[0] *= p._v[0]; _v[1] *= p._v[1]; return *this; } inline S StableDot ( const PointType & p ) const { return _v[0]*p._v[0] +_v[1]*p._v[1]; } //@} }; template class Point3 : public PointBase<3,S> { public: typedef S ScalarType; typedef Point3 PointType; using PointBase<3,S>::_v; using PointBase<3,S>::V; using PointBase<3,S>::W; //@{ /** @name Special members for 3D points. **/ /// default inline Point3 ():PointBase<3,S>(){} /// yxz constructor inline Point3 ( const S a, const S b, const S c){ _v[0]=a; _v[1]=b; _v[2]=c; }; /// Cross product for 3D points inline PointType operator ^ ( PointType const & p ) const { return Point3 ( _v[1]*p._v[2] - _v[2]*p._v[1], _v[2]*p._v[0] - _v[0]*p._v[2], _v[0]*p._v[1] - _v[1]*p._v[0] ); } //@} //@{ /** @name Implementation of standard functions for 3D points **/ inline void Zero(){ _v[0]=0; _v[1]=0; _v[2]=0; }; inline Point3 ( const S nv[3] ){ _v[0]=nv[0]; _v[1]=nv[1]; _v[2]=nv[2]; }; inline Point3 operator + ( Point3 const & p) const{ return Point3( _v[0]+p._v[0], _v[1]+p._v[1], _v[2]+p._v[2]); } inline Point3 operator - ( Point3 const & p) const { return Point3( _v[0]-p._v[0], _v[1]-p._v[1], _v[2]-p._v[2]); } inline Point3 operator * ( const S s ) const { return Point3( _v[0]*s, _v[1]*s , _v[2]*s ); } inline Point3 operator / ( const S s ) const { S t=1.0/s; return Point3( _v[0]*t, _v[1]*t , _v[2]*t ); } inline Point3 operator - () const { return Point3 ( -_v[0], -_v[1] , -_v[2] ); } inline Point3 & operator += ( Point3 const & p ) { _v[0] += p._v[0]; _v[1] += p._v[1]; _v[2] += p._v[2]; return *this; } inline Point3 & operator -= ( Point3 const & p ) { _v[0] -= p._v[0]; _v[1] -= p._v[1]; _v[2] -= p._v[2]; return *this; } inline Point3 & operator *= ( const S s ) { _v[0] *= s; _v[1] *= s; _v[2] *= s; return *this; } inline Point3 & operator /= ( const S s ) { S t=1.0/s; _v[0] *= t; _v[1] *= t; _v[2] *= t; return *this; } inline S Norm() const { return math::Sqrt( _v[0]*_v[0] + _v[1]*_v[1] + _v[2]*_v[2] );} template static S Norm(const PT &p ) { return math::Sqrt( p.V(0)*p.V(0) + p.V(1)*p.V(1) + p.V(2)*p.V(2) );} inline S SquaredNorm() const { return ( _v[0]*_v[0] + _v[1]*_v[1] + _v[2]*_v[2] );} template static S SquaredNorm(const PT &p ) { return ( p.V(0)*p.V(0) + p.V(1)*p.V(1) + p.V(2)*p.V(2) );} inline S operator * ( PointType const & p ) const { return ( _v[0]*p._v[0] + _v[1]*p._v[1] + _v[2]*p._v[2]) ; } inline bool operator == ( PointType const & p ) const { return _v[0]==p._v[0] && _v[1]==p._v[1] && _v[2]==p._v[2] ;} inline bool operator != ( PointType const & p ) const { return _v[0]!=p._v[0] || _v[1]!=p._v[1] || _v[2]!=p._v[2] ;} inline bool operator < ( PointType const & p ) const{ return (_v[2]!=p._v[2])?(_v[2]< p._v[2]): (_v[1]!=p._v[1])?(_v[1]< p._v[1]) : (_v[0] ( PointType const & p ) const { return (_v[2]!=p._v[2])?(_v[2]> p._v[2]): (_v[1]!=p._v[1])?(_v[1]> p._v[1]) : (_v[0]>p._v[0]); } inline bool operator <= ( PointType const & p ) { return (_v[2]!=p._v[2])?(_v[2]< p._v[2]): (_v[1]!=p._v[1])?(_v[1]< p._v[1]) : (_v[0]<=p._v[0]); } inline bool operator >= ( PointType const & p ) const { return (_v[2]!=p._v[2])?(_v[2]> p._v[2]): (_v[1]!=p._v[1])?(_v[1]> p._v[1]) : (_v[0]>=p._v[0]); } inline PointType & Normalize() { S n = Norm(); if(n!=0.0) { n=S(1.0)/n; _v[0]*=n; _v[1]*=n; _v[2]*=n; } return *this;}; template PointType & Normalize(const PT &p){ S n = Norm(); if(n!=0.0) { n=1.0/n; V(0)*=n; V(1)*=n; V(2)*=n; } return *this;}; inline PointType & HomoNormalize(){ if (_v[2]!=0.0) { _v[0] /= W(); _v[1] /= W(); W()=1.0; } return *this;}; inline S NormInfinity() const { return math::Max( math::Max( math::Abs(_v[0]), math::Abs(_v[1]) ), math::Abs(_v[3]) ); } inline S NormOne() const { return math::Abs(_v[0])+ math::Abs(_v[1])+math::Max(math::Abs(_v[2]));} inline S operator % ( PointType const & p ) const { S t = (*this)*p; /* Area, general formula */ return math::Sqrt( SquaredNorm() * p.SquaredNorm() - (t*t) );}; inline S Sum() const { return _v[0]+_v[1]+_v[2];} inline S Max() const { return math::Max( math::Max( _v[0], _v[1] ), _v[2] ); } inline S Min() const { return math::Min( math::Min( _v[0], _v[1] ), _v[2] ); } inline int MaxI() const { int i= (_v[0] < _v[1]) ? 1:0; if (_v[i] < _v[2]) i=2; return i;}; inline int MinI() const { int i= (_v[0] > _v[1]) ? 1:0; if (_v[i] > _v[2]) i=2; return i;}; inline PointType & Scale( const PointType & p ) { _v[0] *= p._v[0]; _v[1] *= p._v[1]; _v[2] *= p._v[2]; return *this; } inline S StableDot ( const PointType & p ) const { S k0=_v[0]*p._v[0], k1=_v[1]*p._v[1], k2=_v[2]*p._v[2]; int exp0,exp1,exp2; frexp( double(k0), &exp0 ); frexp( double(k1), &exp1 ); frexp( double(k2), &exp2 ); if( exp0 class Point4 : public PointBase<4,S> { public: typedef S ScalarType; typedef Point4 PointType; using PointBase<3,S>::_v; using PointBase<3,S>::V; using PointBase<3,S>::W; //@{ /** @name Special members for 4D points. **/ /// default inline Point4 (){} /// xyzw constructor //@} inline Point4 ( const S a, const S b, const S c, const S d){ _v[0]=a; _v[1]=b; _v[2]=c; _v[3]=d; }; //@{ /** @name Implementation of standard functions for 3D points **/ inline void Zero(){ _v[0]=0; _v[1]=0; _v[2]=0; _v[3]=0; }; inline Point4 ( const S nv[4] ){ _v[0]=nv[0]; _v[1]=nv[1]; _v[2]=nv[2]; _v[3]=nv[3]; }; inline Point4 operator + ( Point4 const & p) const { return Point4( _v[0]+p._v[0], _v[1]+p._v[1], _v[2]+p._v[2], _v[3]+p._v[3] ); } inline Point4 operator - ( Point4 const & p) const { return Point4( _v[0]-p._v[0], _v[1]-p._v[1], _v[2]-p._v[2], _v[3]-p._v[3] ); } inline Point4 operator * ( const S s ) const { return Point4( _v[0]*s, _v[1]*s , _v[2]*s , _v[3]*s ); } inline PointType operator ^ ( PointType const & p ) const { assert(0); return *this; } inline Point4 operator / ( const S s ) const { S t=1.0/s; return Point4( _v[0]*t, _v[1]*t , _v[2]*t , _v[3]*t ); } inline Point4 operator - () const { return Point4 ( -_v[0], -_v[1] , -_v[2] , -_v[3] ); } inline Point4 & operator += ( Point4 const & p ) { _v[0] += p._v[0]; _v[1] += p._v[1]; _v[2] += p._v[2]; _v[3] += p._v[3]; return *this; } inline Point4 & operator -= ( Point4 const & p ) { _v[0] -= p._v[0]; _v[1] -= p._v[1]; _v[2] -= p._v[2]; _v[3] -= p._v[3]; return *this; } inline Point4 & operator *= ( const S s ) { _v[0] *= s; _v[1] *= s; _v[2] *= s; _v[3] *= s; return *this; } inline Point4 & operator /= ( const S s ) { S t=1.0/s; _v[0] *= t; _v[1] *= t; _v[2] *= t; _v[3] *= t; return *this; } inline S Norm() const { return math::Sqrt( _v[0]*_v[0] + _v[1]*_v[1] + _v[2]*_v[2] + _v[3]*_v[3] );} template static S Norm(const PT &p ) { return math::Sqrt( p.V(0)*p.V(0) + p.V(1)*p.V(1) + p.V(2)*p.V(2) + p.V(3)*p.V(3) );} inline S SquaredNorm() const { return ( _v[0]*_v[0] + _v[1]*_v[1] + _v[2]*_v[2] + _v[3]*_v[3] );} template static S SquaredNorm(const PT &p ) { return ( p.V(0)*p.V(0) + p.V(1)*p.V(1) + p.V(2)*p.V(2) + p.V(3)*p.V(3) );} inline S operator * ( PointType const & p ) const { return ( _v[0]*p._v[0] + _v[1]*p._v[1] + _v[2]*p._v[2] + _v[3]*p._v[3] ); } inline bool operator == ( PointType const & p ) const { return _v[0]==p._v[0] && _v[1]==p._v[1] && _v[2]==p._v[2] && _v[3]==p._v[3];} inline bool operator != ( PointType const & p ) const { return _v[0]!=p._v[0] || _v[1]!=p._v[1] || _v[2]!=p._v[2] || _v[3]!=p._v[3];} inline bool operator < ( PointType const & p ) const{ return (_v[3]!=p._v[3])?(_v[3]< p._v[3]) : (_v[2]!=p._v[2])?(_v[2]< p._v[2]): (_v[1]!=p._v[1])?(_v[1]< p._v[1]) : (_v[0] ( PointType const & p ) const { return (_v[3]!=p._v[3])?(_v[3]> p._v[3]) : (_v[2]!=p._v[2])?(_v[2]> p._v[2]): (_v[1]!=p._v[1])?(_v[1]> p._v[1]) : (_v[0]>p._v[0]); } inline bool operator <= ( PointType const & p ) { return (_v[3]!=p._v[3])?(_v[3]< p._v[3]) : (_v[2]!=p._v[2])?(_v[2]< p._v[2]): (_v[1]!=p._v[1])?(_v[1]< p._v[1]) : (_v[0]<=p._v[0]); } inline bool operator >= ( PointType const & p ) const { return (_v[3]!=p._v[3])?(_v[3]> p._v[3]) : (_v[2]!=p._v[2])?(_v[2]> p._v[2]): (_v[1]!=p._v[1])?(_v[1]> p._v[1]) : (_v[0]>=p._v[0]); } inline PointType & Normalize() { PointType n = Norm(); if(n!=0.0) { n=1.0/n; _v[0]*=n; _v[1]*=n; _v[2]*=n; _v[3]*=n; } return *this;}; template PointType & Normalize(const PT &p){ PointType n = Norm(); if(n!=0.0) { n=1.0/n; V(0)*=n; V(1)*=n; V(2)*=n; V(3)*=n; } return *this;}; inline PointType & HomoNormalize(){ if (_v[3]!=0.0) { _v[0] /= W(); _v[1] /= W(); _v[2] /= W(); W()=1.0; } return *this;}; inline S NormInfinity() const { return math::Max( math::Max( math::Abs(_v[0]), math::Abs(_v[1]) ), math::Max( math::Abs(_v[2]), math::Abs(_v[3]) ) ); } inline S NormOne() const { return math::Abs(_v[0])+ math::Abs(_v[1])+math::Max(math::Abs(_v[2]),math::Abs(_v[3]));} inline S operator % ( PointType const & p ) const { S t = (*this)*p; /* Area, general formula */ return math::Sqrt( SquaredNorm() * p.SquaredNorm() - (t*t) );}; inline S Sum() const { return _v[0]+_v[1]+_v[2]+_v[3];} inline S Max() const { return math::Max( math::Max( _v[0], _v[1] ), math::Max( _v[2], _v[3] )); } inline S Min() const { return math::Min( math::Min( _v[0], _v[1] ), math::Min( _v[2], _v[3] )); } inline int MaxI() const { int i= (_v[0] < _v[1]) ? 1:0; if (_v[i] < _v[2]) i=2; if (_v[i] < _v[3]) i=3; return i;}; inline int MinI() const { int i= (_v[0] > _v[1]) ? 1:0; if (_v[i] > _v[2]) i=2; if (_v[i] > _v[3]) i=3; return i;}; inline PointType & Scale( const PointType & p ) { _v[0] *= p._v[0]; _v[1] *= p._v[1]; _v[2] *= p._v[2]; _v[3] *= p._v[3]; return *this; } inline S StableDot ( const PointType & p ) const { S k0=_v[0]*p._v[0], k1=_v[1]*p._v[1], k2=_v[2]*p._v[2], k3=_v[3]*p._v[3]; int exp0,exp1,exp2,exp3; frexp( double(k0), &exp0 );frexp( double(k1), &exp1 ); frexp( double(k2), &exp2 );frexp( double(k3), &exp3 ); if (exp0>exp1) { math::Swap(k0,k1); math::Swap(exp0,exp1); } if (exp2>exp3) { math::Swap(k2,k3); math::Swap(exp2,exp3); } if (exp0>exp2) { math::Swap(k0,k2); math::Swap(exp0,exp2); } if (exp1>exp3) { math::Swap(k1,k3); math::Swap(exp1,exp3); } if (exp2>exp3) { math::Swap(k2,k3); math::Swap(exp2,exp3); } return ( (k0 + k1) + k2 ) +k3; } //@} }; template inline S Angle( Point3 const & p1, Point3 const & p2 ) { S w = p1.Norm()*p2.Norm(); if(w==0) return -1; S t = (p1*p2)/w; if(t>1) t = 1; else if(t<-1) t = -1; return (S) acos(t); } // versione uguale alla precedente ma che assume che i due vettori siano unitari template inline S AngleN( Point3 const & p1, Point3 const & p2 ) { S w = p1*p2; if(w>1) w = 1; else if(w<-1) w=-1; return (S) acos(w); } template inline S Norm( Point const & p ) { return p.Norm(); } template inline S SquaredNorm( Point const & p ) { return p.SquaredNorm(); } template inline Point & Normalize( Point & p ) { p.Normalize(); return p; } template inline S Distance( Point const & p1,Point const & p2 ) { return (p1-p2).Norm(); } template inline S SquaredDistance( Point const & p1,Point const & p2 ) { return (p1-p2).SquaredNorm(); } //template //struct Point2:public Point<2,S>{ // inline Point2(){}; // inline Point2(Point<2,S> const & p):Point<2,S>(p){} ; // inline Point2( const S a, const S b):Point<2,S>(a,b){}; //}; // //template //struct Point3:public Point3 { // inline Point3(){}; // inline Point3(Point3 const & p):Point3 (p){} // inline Point3( const S a, const S b, const S c):Point3 (a,b,c){}; //}; // // //template //struct Point4:public Point4{ // inline Point4(){}; // inline Point4(Point4 const & p):Point4(p){} // inline Point4( const S a, const S b, const S c, const S d):Point4(a,b,c,d){}; //}; typedef Point2 Point2s; typedef Point2 Point2i; typedef Point2 Point2f; typedef Point2 Point2d; typedef Point2 Vector2s; typedef Point2 Vector2i; typedef Point2 Vector2f; typedef Point2 Vector2d; typedef Point3 Point3s; typedef Point3 Point3i; typedef Point3 Point3f; typedef Point3 Point3d; typedef Point3 Vector3s; typedef Point3 Vector3i; typedef Point3 Vector3f; typedef Point3 Vector3d; typedef Point4 Point4s; typedef Point4 Point4i; typedef Point4 Point4f; typedef Point4 Point4d; typedef Point4 Vector4s; typedef Point4 Vector4i; typedef Point4 Vector4f; typedef Point4 Vector4d; /*@}*/ } // end namespace ndim } // end namespace vcg #endif qutemol/vcg/vcg/space/smallest_enclosing.h0000444000175000017500000001152110720526317017314 0ustar mbamba#pragma once /**************************************************************************** * VCGLib o o * * Visual and Computer Graphics Library o o * * _ O _ * * Copyright(C) 2004 \/)\/ * * Visual Computing Lab /\/| * * ISTI - Italian National Research Council | * * \ * * All rights reserved. * * * * 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. * * * * 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 (http://www.gnu.org/licenses/gpl.txt) * * for more details. * * * ****************************************************************************/ /**************************************************************************** History $Log: smallest_enclosing.h,v $ Revision 1.6 2007/11/20 09:45:51 ganovelli missing typename Revision 1.5 2007/11/07 09:37:20 ganovelli added draft for sphereofsphres enclosing Revision 1.4 2006/09/14 08:46:00 ganovelli added inclusion of sphere3 Revision 1.3 2006/07/12 12:13:23 zifnab1974 static keyword only in declaration not in implementation Revision 1.2 2006/07/10 10:38:16 turini minor changes in SphereOfTetra() Revision 1.1 2006/07/06 12:37:18 ganovelli draft version. For the triangle is not tehe smallest enclosing sphere and for the set of spheres works only for two spheres ****************************************************************************/ #include #include #include #include namespace vcg{ /** \addtogroup space */ /*@{*/ /** Class for function computing the smallest enclosing bounding volume */ struct SmallestEnclosing { /// computes the smallest enclosing sphere of a triangle template static Sphere3 SphereOfTriangle(const TriangleType & t); /// computes the smallest enclosing sphere of a tetrahedron template static Sphere3 SphereOfTetra(const TetraType & t); /// computes the smallest enclosing sphere of two spheres template static SphereType SphereOfSpheres( const SphereType & s0,const SphereType & s1); /// computes the smallest enclosing sphere of a container of spheres template static typename SphereContType::value_type SphereOfSpheres( const SphereContType & t); }; /*@}*/ template Sphere3 SmallestEnclosing::SphereOfTriangle(const TriangleType & t){ return Sphere3(t.Barycenter(),(t.Barycenter()-t.cP(0)).Norm() ); } template Sphere3 SmallestEnclosing::SphereOfTetra(const TetraType & t){ return Sphere3( t.Barycenter(),( t.Barycenter() - t.cP(0) ).Norm() ); } template SphereType SmallestEnclosing:: SphereOfSpheres( const SphereType & s0, const SphereType & s1) { typename SphereType::ScalarType radius; vcg::Point3f center; if(s0.Radius()==-1.0) return s1; else if(s1.Radius()==-1.0) return s0; float dst = (s1.Center()-s0.Center()).Norm() ; radius = (dst+s1.Radius()+s0.Radius())/2; Point3f a=s0.Center(); Point3f b=s1.Center(); Point3f dir = (b-a).Normalize(); a = a - dir*s0.Radius(); b = b + dir*s1.Radius(); center = (a+b)/2.0; return SphereType(center,radius); } template typename SphereContType::value_type SmallestEnclosing:: SphereOfSpheres( const SphereContType & spheres) { typename SphereContType::value_type::ScalarType radius; typename SphereContType::value_type res; typename SphereContType::const_iterator si; for(si = spheres.begin(); si != spheres.end(); ++si){ res = SphereOfSpheres(res,*si); } return res; } } qutemol/vcg/vcg/space/box3.h0000444000175000017500000004377210776373302014324 0ustar mbamba/**************************************************************************** * VCGLib o o * * Visual and Computer Graphics Library o o * * _ O _ * * Copyright(C) 2004 \/)\/ * * Visual Computing Lab /\/| * * ISTI - Italian National Research Council | * * \ * * All rights reserved. * * * * 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. * * * * 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 (http://www.gnu.org/licenses/gpl.txt) * * for more details. * * * ****************************************************************************/ /**************************************************************************** History $Log: box3.h,v $ Revision 1.20 2008/04/07 10:26:10 pietroni corrected 1 warning in DistancePoint3Box3 function Revision 1.19 2008/03/05 11:48:08 pietroni correct 1 error on DistancePoint3Box3 (if the point is inside the box return distance to the nearest face instead of zero) Revision 1.18 2008/02/03 23:50:51 cignoni Important Change. Now adding a null bbox to a bbox leave it unchanged (instead of trashing it) Revision 1.17 2007/07/12 06:41:24 cignoni added a missing static to the Construct() member Revision 1.16 2007/03/22 18:12:00 pietroni *** empty log message *** Revision 1.15 2007/03/22 17:29:16 pietroni *** empty log message *** Revision 1.14 2006/11/13 13:03:45 ponchio Added GetBBox in Point3 (declaration) the body of the function is in box3.h Revision 1.13 2006/09/28 13:37:13 m_di_benedetto Added "const" to Collide() Revision 1.12 2006/07/06 12:42:10 ganovelli tolto il tipo enumerato axis Revision 1.11 2006/06/29 13:22:04 ganovelli Aggiunte funzioni che determinano il lato magiore (minore) Revision 1.10 2006/06/09 07:26:37 m_di_benedetto Added const qualifier to P() method. Revision 1.9 2005/09/30 15:03:57 cignoni Added Center-Radius Constructor Revision 1.8 2004/07/20 23:10:01 cignoni Uncommented Add of matrix transformed bbox Revision 1.7 2004/07/15 09:47:55 ganovelli added function P(int i) to list the box's vertices Revision 1.6 2004/07/07 23:26:25 cignoni removed the infamous Inflate. Now only Offset exists Revision 1.5 2004/03/05 17:51:28 tarini Errorino "ScalarType" -> "BoxScalarType" Revision 1.4 2004/03/03 14:32:13 cignoni Yet another cr lf mismatch Revision 1.3 2004/02/23 23:44:21 cignoni cr lf mismatch Revision 1.2 2004/02/19 15:40:56 cignoni Added doxygen groups Revision 1.1 2004/02/13 02:16:22 cignoni First working release. ****************************************************************************/ #ifndef __VCGLIB_BOX3 #define __VCGLIB_BOX3 #include #include #include #include namespace vcg { /** \addtogroup space */ /*@{*/ /** Templated class for 3D boxes. This is the class for definition of a axis aligned bounding box in 3D space. It is stored just as two Point3 @param BoxScalarType (template parameter) Specifies the type of scalar used to represent coords. */ template class Box3 { public: /// The scalar type typedef BoxScalarType ScalarType; /// min coordinate point Point3 min; /// max coordinate point Point3 max; /// The bounding box constructor inline Box3() { min.X()= 1;max.X()= -1;min.Y()= 1;max.Y()= -1;min.Z()= 1;max.Z()= -1;} /// Copy constructor inline Box3( const Box3 & b ) { min=b.min; max=b.max; } /// Min Max constructor inline Box3( const Point3 & mi, const Point3 & ma ) { min = mi; max = ma; } /// Point Radius Constructor inline Box3(const Point3 & center, const BoxScalarType & radius) { min = center-Point3(radius,radius,radius); max = center+Point3(radius,radius,radius); } /// The bounding box distructor inline ~Box3() { } /// Operator to compare two bounding box inline bool operator == ( Box3 const & p ) const { return min==p.min && max==p.max; } /// Operator to dispare two bounding box inline bool operator != ( Box3 const & p ) const { return min!=p.min || max!=p.max; } /** Varia le dimensioni del bounding box scalandole rispetto al parametro scalare. @param s Valore scalare che indica di quanto deve variare il bounding box */ void Offset( const BoxScalarType s ) { Offset( Point3 (s,s,s)); } /** Varia le dimensioni del bounding box del valore fornito attraverso il parametro. @param delta Point in 3D space */ void Offset( const Point3 & delta ) { min -= delta; max += delta; } /// Initializing the bounding box void Set( const Point3 & p ) { min = max = p; } /// Set the bounding box to a null value void SetNull() { min.X()= 1; max.X()= -1; min.Y()= 1; max.Y()= -1; min.Z()= 1; max.Z()= -1; } /** Function to add two bounding box @param b Il bounding box che si vuole aggiungere */ void Add( Box3 const & b ) { if(b.IsNull()) return; // Adding a null bbox should do nothing if(IsNull()) *this=b; else { if(min.X() > b.min.X()) min.X() = b.min.X(); if(min.Y() > b.min.Y()) min.Y() = b.min.Y(); if(min.Z() > b.min.Z()) min.Z() = b.min.Z(); if(max.X() < b.max.X()) max.X() = b.max.X(); if(max.Y() < b.max.Y()) max.Y() = b.max.Y(); if(max.Z() < b.max.Z()) max.Z() = b.max.Z(); } } /** Funzione per aggiungere un punto al bounding box. Il bounding box viene modificato se il punto cade fuori da esso. @param p The point 3D */ void Add( const Point3 & p ) { if(IsNull()) Set(p); else { if(min.X() > p.X()) min.X() = p.X(); if(min.Y() > p.Y()) min.Y() = p.Y(); if(min.Z() > p.Z()) min.Z() = p.Z(); if(max.X() < p.X()) max.X() = p.X(); if(max.Y() < p.Y()) max.Y() = p.Y(); if(max.Z() < p.Z()) max.Z() = p.Z(); } } // Aggiunge ad un box un altro box trasformato secondo la matrice m void Add( const Matrix44 &m, const Box3 & b ) { const Point3 &mn= b.min; const Point3 &mx= b.max; Add(m*(Point3(mn[0],mn[1],mn[2]))); Add(m*(Point3(mx[0],mn[1],mn[2]))); Add(m*(Point3(mn[0],mx[1],mn[2]))); Add(m*(Point3(mx[0],mx[1],mn[2]))); Add(m*(Point3(mn[0],mn[1],mx[2]))); Add(m*(Point3(mx[0],mn[1],mx[2]))); Add(m*(Point3(mn[0],mx[1],mx[2]))); Add(m*(Point3(mx[0],mx[1],mx[2]))); } /** Calcola l'intersezione tra due bounding box. Al bounding box viene assegnato il valore risultante. @param b Il bounding box con il quale si vuole effettuare l'intersezione */ void Intersect( const Box3 & b ) { if(min.X() < b.min.X()) min.X() = b.min.X(); if(min.Y() < b.min.Y()) min.Y() = b.min.Y(); if(min.Z() < b.min.Z()) min.Z() = b.min.Z(); if(max.X() > b.max.X()) max.X() = b.max.X(); if(max.Y() > b.max.Y()) max.Y() = b.max.Y(); if(max.Z() > b.max.Z()) max.Z() = b.max.Z(); if(min.X()>max.X() || min.Y()>max.Y() || min.Z()>max.Z()) SetNull(); } /** Trasla il bounding box di un valore definito dal parametro. @param p Il bounding box trasla sulla x e sulla y in base alle coordinate del parametro */ void Translate( const Point3 & p ) { min += p; max += p; } /** Verifica se un punto appartiene ad un bounding box. @param p The point 3D @return True se p appartiene al bounding box, false altrimenti */ bool IsIn( Point3 const & p ) const { return ( min.X() <= p.X() && p.X() <= max.X() && min.Y() <= p.Y() && p.Y() <= max.Y() && min.Z() <= p.Z() && p.Z() <= max.Z() ); } /** Verifica se un punto appartiene ad un bounding box aperto sul max. @param p The point 3D @return True se p appartiene al bounding box, false altrimenti */ bool IsInEx( Point3 const & p ) const { return ( min.X() <= p.X() && p.X() < max.X() && min.Y() <= p.Y() && p.Y() < max.Y() && min.Z() <= p.Z() && p.Z() < max.Z() ); } /** Verifica se due bounding box collidono cioe' se hanno una intersezione non vuota. Per esempio due bounding box adiacenti non collidono. @param b A bounding box @return True se collidoo, false altrimenti */ /* old version bool Collide(Box3 const &b) { Box3 bb=*this; bb.Intersect(b); return bb.IsValid(); } */ bool Collide(Box3 const &b) const { return b.min.X()min.X() && b.min.Y()min.Y() && b.min.Z()min.Z() ; } /** Controlla se il bounding box e' nullo. @return True se il bounding box e' nullo, false altrimenti */ bool IsNull() const { return min.X()>max.X() || min.Y()>max.Y() || min.Z()>max.Z(); } /** Controlla se il bounding box e' vuoto. @return True se il bounding box e' vuoto, false altrimenti */ bool IsEmpty() const { return min==max; } /// Restituisce la lunghezza della diagonale del bounding box. BoxScalarType Diag() const { return Distance(min,max); } /// Calcola il quadrato della diagonale del bounding box. BoxScalarType SquaredDiag() const { return SquaredDistance(min,max); } /// Calcola il centro del bounding box. Point3 Center() const { return (min+max)/2; } /// Compute bounding box size. Point3 Dim() const { return (max-min); } /// Returns global coords of a local point expressed in [0..1]^3 Point3 LocalToGlobal(Point3 const & p) const{ return Point3( min[0] + p[0]*(max[0]-min[0]), min[1] + p[1]*(max[1]-min[1]), min[2] + p[2]*(max[2]-min[2])); } /// Returns local coords expressed in [0..1]^3 of a point in 3D Point3 GlobalToLocal(Point3 const & p) const{ return Point3( (p[0]-min[0])/(max[0]-min[0]), (p[1]-min[1])/(max[1]-min[1]), (p[2]-min[2])/(max[2]-min[2]) ); } /// Calcola il volume del bounding box. BoxScalarType Volume() const { return (max.X()-min.X())*(max.Y()-min.Y())*(max.Z()-min.Z()); } /// Calcola la dimensione del bounding box sulla x. inline BoxScalarType DimX() const { return max.X()-min.X();} /// Calcola la dimensione del bounding box sulla y. inline BoxScalarType DimY() const { return max.Y()-min.Y();} /// Calcola la dimensione del bounding box sulla z. inline BoxScalarType DimZ() const { return max.Z()-min.Z();} /// Calcola il lato di lunghezza maggiore inline unsigned char MaxDim() const { int i; Point3 diag = max-min; if(diag[0]>diag[1]) i=0; else i=1; return (diag[i]>diag[2])? i: 2; } /// Calcola il lato di lunghezza minore inline unsigned char MinDim() const { int i; Point3 diag = max-min; if(diag[0] inline void Import( const Box3 & b ) { min.Import(b.min); max.Import(b.max); } template static inline Box3 Construct( const Box3 & b ) { return Box3(Point3::Construct(b.min),Point3::Construct(b.max)); } /// gives the ith box vertex in order: (x,y,z),(X,y,z),(x,Y,z),(X,Y,z),(x,y,Z),(X,y,Z),(x,Y,Z),(X,Y,Z) Point3 P(const int & i) const { return Point3( min[0]+ (i%2) * DimX(), min[1]+ ((i / 2)%2) * DimY(), min[2]+ (i>3)* DimZ()); } }; // end class definition template Box3 Point3::GetBBox(Box3 &bb) const { bb.Set( *this ); } template ScalarType DistancePoint3Box3(const Point3 &test, const Box3 &bbox) { ///if fall inside return distance to a face if (bbox.IsIn(test)) { ScalarType dx=std::min(bbox.max.X()-test.X(),test.X()-bbox.min.X()); ScalarType dy=std::min(bbox.max.Y()-test.Y(),test.Y()-bbox.min.Y()); ScalarType dz=std::min(bbox.max.Z()-test.Z(),test.Z()-bbox.min.Z()); return std::min(dx,std::min(dy,dz)); } ///find the right quandrant bool XM=(test.X()>=bbox.max.X()); bool Xm=(test.X()<=bbox.min.X()); bool YM=(test.Y()>=bbox.max.Y()); bool Ym=(test.Y()<=bbox.min.Y()); bool ZM=(test.Z()>=bbox.max.Z()); bool Zm=(test.Z()<=bbox.min.Z()); ///VERTICES CASES if ((Xm)&&(Ym)&&(Zm)) return ((test-bbox.P(0)).Norm()); if ((Ym)&&(Zm)&&(XM)) return ((test-bbox.P(1)).Norm()); if ((Xm)&&(Zm)&&(YM)) return ((test-bbox.P(2)).Norm()); if ((XM)&&(YM)&&(Zm)) return ((test-bbox.P(3)).Norm()); if ((Xm)&&(Ym)&&(ZM)) return ((test-bbox.P(4)).Norm()); if ((XM)&&(ZM)&&(Ym)) return ((test-bbox.P(5)).Norm()); if ((YM)&&(ZM)&&(Xm)) return ((test-bbox.P(6)).Norm()); if ((XM)&&(YM)&&(ZM)) return ((test-bbox.P(7)).Norm()); bool Xin=((test.X()>=bbox.min.X())&&(test.X()<=bbox.max.X())); bool Yin=((test.Y()>=bbox.min.Y())&&(test.Y()<=bbox.max.Y())); bool Zin=((test.Z()>=bbox.min.Z())&&(test.Z()<=bbox.max.Z())); ///EDGES CASES ///edge case 0 if ((Xin) &&(Ym)&&(Zm)) { vcg::Line3 edge; vcg::Point3 dir=bbox.P(1)-bbox.P(0); dir.Normalize(); edge.Set(bbox.P(0),dir); vcg::Point3 clos=vcg::ClosestPoint(edge,test); return ((test-clos).Norm()); } ///edge case 1 if ((Zin)&&(XM)&&(Ym)) { vcg::Line3 edge; vcg::Point3 dir=bbox.P(5)-bbox.P(1); dir.Normalize(); edge.Set(bbox.P(1),dir); vcg::Point3 clos=vcg::ClosestPoint(edge,test); return ((test-clos).Norm()); } ///edge case 2 if ((Xin)&&(Ym)&&(ZM)) { vcg::Line3 edge; vcg::Point3 dir=bbox.P(5)-bbox.P(4); dir.Normalize(); edge.Set(bbox.P(4),dir); vcg::Point3 clos=vcg::ClosestPoint(edge,test); return ((test-clos).Norm()); } ///edge case 3 if ((Zin)&&(Xm)&&(Ym)) { vcg::Line3 edge; vcg::Point3 dir=bbox.P(4)-bbox.P(0); dir.Normalize(); edge.Set(bbox.P(0),dir); vcg::Point3 clos=vcg::ClosestPoint(edge,test); return ((test-clos).Norm()); } ///edge case 4 if ((Xin)&&(YM)&&(Zm)) { vcg::Line3 edge; vcg::Point3 dir=bbox.P(3)-bbox.P(2); dir.Normalize(); edge.Set(bbox.P(2),dir); vcg::Point3 clos=vcg::ClosestPoint(edge,test); return ((test-clos).Norm()); } ///edge case 5 if ((Zin)&&(XM)&&(YM)) { vcg::Line3 edge; vcg::Point3 dir=bbox.P(7)-bbox.P(3); dir.Normalize(); edge.Set(bbox.P(3),dir); vcg::Point3 clos=vcg::ClosestPoint(edge,test); return ((test-clos).Norm()); } ///edge case 6 if ((Xin)&&(ZM)&&(YM)) { vcg::Line3 edge; vcg::Point3 dir=bbox.P(7)-bbox.P(6); dir.Normalize(); edge.Set(bbox.P(6),dir); vcg::Point3 clos=vcg::ClosestPoint(edge,test); return ((test-clos).Norm()); } ///edge case 7 if ((Zin)&&(Xm)&&(YM)) { vcg::Line3 edge; vcg::Point3 dir=bbox.P(6)-bbox.P(2); dir.Normalize(); edge.Set(bbox.P(2),dir); vcg::Point3 clos=vcg::ClosestPoint(edge,test); return ((test-clos).Norm()); } ///edge case 8 if ((Yin)&&(Xm)&&(Zm)) { vcg::Line3 edge; vcg::Point3 dir=bbox.P(2)-bbox.P(0); dir.Normalize(); edge.Set(bbox.P(0),dir); vcg::Point3 clos=vcg::ClosestPoint(edge,test); return ((test-clos).Norm()); } ///edge case 9 if ((Yin)&&(XM)&&(Zm)) { vcg::Line3 edge; vcg::Point3 dir=bbox.P(3)-bbox.P(1); dir.Normalize(); edge.Set(bbox.P(1),dir); vcg::Point3 clos=vcg::ClosestPoint(edge,test); return ((test-clos).Norm()); } ///edge case 10 if ((Yin)&&(XM)&&(ZM)) { vcg::Line3 edge; vcg::Point3 dir=bbox.P(7)-bbox.P(5); dir.Normalize(); edge.Set(bbox.P(5),dir); vcg::Point3 clos=vcg::ClosestPoint(edge,test); return ((test-clos).Norm()); } ///edge case 11 if ((Yin)&&(Xm)&&(ZM)) { vcg::Line3 edge; vcg::Point3 dir=bbox.P(6)-bbox.P(4); dir.Normalize(); edge.Set(bbox.P(4),dir); vcg::Point3 clos=vcg::ClosestPoint(edge,test); return ((test-clos).Norm()); } ///FACES CASES //face 0 if ((Xin)&&(Zin)&&(Ym)) return (fabs(bbox.min.Y()-test.Y())); //face 1 if ((Xin)&&(Zin)&&(YM)) return (fabs(bbox.min.Y()-test.Y())); //face 2 if ((Xin)&&(Yin)&&(Zm)) return (fabs(bbox.min.Z()-test.Z())); //face 3 if ((Xin)&&(Yin)&&(ZM)) return (fabs(bbox.min.Z()-test.Z())); //face 4 if ((Yin)&&(Zin)&&(Xm)) return (fabs(bbox.min.X()-test.X())); //face 5 if ((Yin)&&(Zin)&&(XM)) return (fabs(bbox.min.X()-test.X())); //no more cases assert(0); ///this is for warnings return(0); } typedef Box3 Box3s; typedef Box3 Box3i; typedef Box3 Box3f; typedef Box3 Box3d; /*@}*/ } // end namespace #endif qutemol/vcg/vcg/space/box2.h0000444000175000017500000002256410763503740014314 0ustar mbamba/**************************************************************************** * VCGLib o o * * Visual and Computer Graphics Library o o * * _ O _ * * Copyright(C) 2004 \/)\/ * * Visual Computing Lab /\/| * * ISTI - Italian National Research Council | * * \ * * All rights reserved. * * * * 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. * * * * 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 (http://www.gnu.org/licenses/gpl.txt) * * for more details. * * * ****************************************************************************/ /**************************************************************************** History $Log: box2.h,v $ Revision 1.9 2008/03/05 11:45:36 pietroni added DistancePoint2Box2 Revision 1.8 2007/07/02 10:01:00 corsini fix area Revision 1.7 2006/10/07 16:50:26 m_di_benedetto Added Dim() method. Revision 1.6 2005/06/14 13:46:20 ponchio Minibug: Box2f -> Box2 in the template. Revision 1.5 2005/05/06 14:02:37 croccia replaced all the occurences of min.v[0] with min.X(), max.v[0] with max.X() etc. Revision 1.3 2005/05/05 10:20:24 croccia changed #include to #include croccia Revision 1.2 2004/03/10 21:38:39 cignoni Written some documentation and added to the space module Revision 1.1 2004/02/15 23:34:04 cignoni Initial commit ****************************************************************************/ #ifndef __VCGLIB_BOX2 #define __VCGLIB_BOX2 #include #include #include namespace vcg { /** \addtogroup space */ /*@{*/ /** Templated class for a 2D bounding box. It is stored just as two Point2 @param BoxScalarType (Template Parameter) Specifies the scalar field. */ template class Box2 { public: /// The scalar type typedef BoxScalarType ScalarType; /// min coordinate point Point2 min; /// max coordinate point Point2 max; /// Standard constructor inline Box2() { min.X()= 1; max.X()= -1; min.Y()= 1; max.Y()= -1; } /// Copy constructor inline Box2( const Box2 & b ) { min=b.min; max=b.max; } /// Distructor inline ~Box2() { } /// Operator to compare two bounding box inline bool operator == ( Box2 const & p ) const { return min==p.min && max==p.max; } /// Initializing the bounding box with a point void Set( const Point2 & p ) { min = max = p; } // Initializing with the values inline void Set( BoxScalarType minx, BoxScalarType miny, BoxScalarType maxx, BoxScalarType maxy ) { min[0] = minx; min[1] = miny; max[0] = maxx; max[1] = maxy; } /// Set the bounding box to a null value void SetNull() { min.X()= 1; max.X()= -1; min.Y()= 1; max.Y()= -1; } /** Function to add two bounding box @param b Il bounding box che si vuole aggiungere */ void Add( Box2 const & b ) { if(IsNull()) { min=b.min; max=b.max; } else { if(min.X() > b.min.X()) min.X() = b.min.X(); if(min.Y() > b.min.Y()) min.Y() = b.min.Y(); if(max.X() < b.max.X()) max.X() = b.max.X(); if(max.Y() < b.max.Y()) max.Y() = b.max.Y(); } } /** Funzione per aggiungere un punto al bounding box. Il bounding box viene modificato se il punto cade fuori da esso. @param p The point 2D */ void Add( const Point2 & p ) { if(IsNull()) Set(p); else { if(min.X() > p.X()) min.X() = p.X(); if(min.Y() > p.Y()) min.Y() = p.Y(); if(max.X() < p.X()) max.X() = p.X(); if(max.Y() < p.Y()) max.Y() = p.Y(); } } /** Calcola l'intersezione tra due bounding box. Al bounding box viene assegnato il valore risultante. @param b Il bounding box con il quale si vuole effettuare l'intersezione */ void Intersect( const Box2 & b ) { if(min.X() < b.min.X()) min.X() = b.min.X(); if(min.Y() < b.min.Y()) min.Y() = b.min.Y(); if(max.X() > b.max.X()) max.X() = b.max.X(); if(max.Y() > b.max.Y()) max.Y() = b.max.Y(); if(min.X()>max.X() || min.Y()>max.Y()) SetNull(); } /** Trasla il bounding box di un valore definito dal parametro. @param p Il bounding box trasla sulla x e sulla y in base alle coordinate del parametro */ void Translate( const Point2 & p ) { min += p; max += p; } /** Verifica se un punto appartiene ad un bounding box. @param p The point 2D @return True se p appartiene al bounding box, false altrimenti */ bool IsIn( Point2 const & p ) const { return ( min.X() <= p.X() && p.X() <= max.X() && min.Y() <= p.Y() && p.Y() <= max.Y() ); } /** Verifica se un punto appartiene ad un bounding box aperto sul max. @param p The point 2D @return True se p appartiene al bounding box, false altrimenti */ bool IsInEx( Point2 const & p ) const { return ( min.X() <= p.X() && p.X() < max.X() && min.Y() <= p.Y() && p.Y() < max.Y() ); } /** Verifica se due bounding box collidono cioe' se hanno una intersezione non vuota. Per esempio due bounding box adiacenti non collidono. @param b A bounding box @return True se collidoo, false altrimenti */ bool Collide( Box2 const &b ) { Box2 bb=*this; bb.Intersect(b); return bb.IsValid(); } /** Controlla se il bounding box e' nullo. @return True se il bounding box e' nullo, false altrimenti */ inline bool IsNull() const { return min.X()>max.X() || min.Y()>max.Y(); } /** Controlla se il bounding box e' consistente. @return True se il bounding box e' consistente, false altrimenti */ inline bool IsValid() const { return min.X() Center() const { return (min+max)/2; } /// Calcola l'area del Bounding box. inline BoxScalarType Area() const { return (max[0]-min[0])*(max[1]-min[1]); } /// Calcola la dimensione del bounding box sulla x. inline BoxScalarType DimX() const { return max.X()-min.X(); } /// Calcola la dimensione del bounding box sulla y. inline BoxScalarType DimY() const { return max.Y()-min.Y(); } /// Calcola la dimensione del bounding box. inline Point2 Dim() const { return max-min; } inline void Normalize( Point2 & p ) { p -= min; p[0] /= max[0]-min[0]; p[1] /= max[1]-min[1]; } }; // end class definition template ScalarType DistancePoint2Box2(const Point2 &test, const Box2 &bbox) { ///test possible position respect to bounding box if (!bbox.IsIN(test)){ if ((test.X()<=bbox.min.X())&&(test.Y()<=bbox.min.Y())) return ((test-bbox.min).Norm()); else if ((test.X()>=bbox.min.X())&& (test.X()<=bbox.max.X())&& (test.Y()<=bbox.min.Y())) return (bbox.min.Y()-test.Y()); else if ((test.X()>=bbox.max.X())&& (test.Y()<=bbox.min.Y())) return ((test-vcg::Point2(bbox.max.X(),bbox.min.Y())).Norm()); else if ((test.Y()>=bbox.min.Y())&& (test.Y()<=bbox.max.Y())&& (test.X()>=bbox.max.X())) return (test.X()-bbox.max.X()); else if ((test.X()>=bbox.max.X())&&(test.Y()>=bbox.max.Y())) return ((test-bbox.max).Norm()); else if ((test.X()>=bbox.min.X())&& (test.X()<=bbox.max.X())&& (test.Y()>=bbox.max.Y())) return (test.Y()-bbox.max.Y()); else if ((test.X()<=bbox.min.X())&& (test.Y()>=bbox.max.Y())) return ((test-vcg::Point2(bbox.min.X(),bbox.max.Y())).Norm()); else if ((test.X()<=bbox.min.X())&& (test.Y()<=bbox.max.Y())&& (test.Y()>=bbox.min.Y())) return (bbox.min.X()-test.X()); } else { //return minimum distance ScalarType dx=std::min(fabs(test.X()-bbox.min.X()),fabs(bbox.max.X()-test.X())); ScalarType dy=std::min(fabs(test.Y()-bbox.min.Y()),fabs(bbox.max.Y()-test.Y())); return(std::min(dx,dy)); } } /// Specificazione di box of short typedef Box2 Box2s; /// Specificazione di box of int typedef Box2 Box2i; /// Specificazione di box of float typedef Box2 Box2f; /// Specificazione di box of double typedef Box2 Box2d; /*@}*/ } // end namespace #endif qutemol/vcg/vcg/space/intersection2.h0000444000175000017500000002040610620077724016223 0ustar mbamba/**************************************************************************** * VCGLib o o * * Visual and Computer Graphics Library o o * * _ O _ * * Copyright(C) 2004 \/)\/ * * Visual Computing Lab /\/| * * ISTI - Italian National Research Council | * * \ * * All rights reserved. * * * * 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. * * * * 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 (http://www.gnu.org/licenses/gpl.txt) * * for more details. * * * ****************************************************************************/ /**************************************************************************** History $Log: intersection2.h,v $ Revision 1.7 2007/05/08 13:49:08 pietroni corrected error on intersection line-circle Revision 1.6 2007/05/08 12:11:58 pietroni added circle-line intersection ****************************************************************************/ #ifndef __VCGLIB_INTERSECTION_2 #define __VCGLIB_INTERSECTION_2 #include #include #include #include #include #include namespace vcg { /** \addtogroup space */ /*@{*/ /** Function computing the intersection between couple of geometric primitives in 2 dimension */ /// return true if the algle is convex (right rotation) template inline bool Convex(const Point2 & p0,const Point2 & p1,const Point2 & p2) { const SCALAR_TYPE EPSILON= SCALAR_TYPE(1e-8); return (((p0-p1)^(p2-p1))<=EPSILON); } ///return if exist the intersection point ///between 2 lines in a 2d plane template inline bool LineLineIntersection(const vcg::Line2 & l0, const vcg::Line2 & l1, Point2 &p) { const SCALAR_TYPE EPSILON= SCALAR_TYPE(1e-8); ///first line SCALAR_TYPE x1=l0.Origin().X(); SCALAR_TYPE y1=l0.Origin().Y(); SCALAR_TYPE x2=x1+l0.Direction().X(); SCALAR_TYPE y2=y1+l0.Direction().Y(); ///second line SCALAR_TYPE x3=l1.Origin().X(); SCALAR_TYPE y3=l1.Origin().Y(); SCALAR_TYPE x4=x3+l1.Direction().X(); SCALAR_TYPE y4=y3+l1.Direction().Y(); ///then find intersection ///denominator SCALAR_TYPE den=((x1-x2)*(y3-y4))-((y1-y2)*(x3-x4)); if (fabs(den) inline bool RayLineIntersection(const vcg::Line2 & l, const vcg::Ray2 & r, Point2 &p) { ///construct line from ray vcg::Line2 l_test; l_test.Set(r.Origin(),r.Direction()); if (!LineLineIntersection(l,l_test,p)) return false; Point2 dir=p-r.Origin(); dir.Normalize(); return (dir*r.Direction()>0); } /// interseciton between point and triangle template inline bool RaySegmentIntersection(const vcg::Ray2 & r, const vcg::Segment2 &seg, Point2 &p_inters) { ///first compute intersection between lines vcg::Line2 line2; line2.SetOrigin(seg.P0()); vcg::Point2 dir=seg.P1()-seg.P0(); dir.Normalize(); line2.SetDirection(dir); if(!RayLineIntersection(line2,r,p_inters)) return false; ///then test if intersection point is nearest ///to both extremes then lenght of the segment SCALAR_TYPE d0=(seg.P1()-p_inters).Norm(); SCALAR_TYPE d1=(seg.P0()-p_inters).Norm(); SCALAR_TYPE lenght=(seg.P0()-seg.P1()).Norm(); return ((d0 inline bool LineSegmentIntersection(const vcg::Line2 & line, const vcg::Segment2 &seg, Point2 &p_inters) { ///first compute intersection between lines vcg::Line2 line2; line2.SetOrigin(seg.P0()); vcg::Point2 dir=seg.P1()-seg.P0(); dir.Normalize(); line2.SetDirection(dir); if(!LineLineIntersection(line,line2,p_inters)) return false; ///then test if intersection point is nearest ///to both extremes then lenght of the segment SCALAR_TYPE d0=(seg.P1()-p_inters).Norm(); SCALAR_TYPE d1=(seg.P0()-p_inters).Norm(); SCALAR_TYPE lenght=(seg.P0()-seg.P1()).Norm(); return ((d0 inline bool SegmentSegmentIntersection(const vcg::Segment2 &seg0, const vcg::Segment2 &seg1, Point2 &p_inters) { ///test intersection of bbox vcg::Box2 bb0,bb1; bb0.Add(seg0.P0()); bb0.Add(seg0.P1()); bb1.Add(seg1.P0()); bb1.Add(seg1.P1()); if (!bb0.Collide(bb1)) return false; else { ///first compute intersection between lines vcg::Line2 l0,l1; l0.SetOrigin(seg0.P0()); vcg::Point2 dir0=seg0.P1()-seg0.P0(); dir0.Normalize(); l0.SetDirection(dir0); l1.SetOrigin(seg1.P0()); vcg::Point2 dir1=seg1.P1()-seg1.P0(); dir1.Normalize(); l1.SetDirection(dir1); return ((LineSegmentIntersection(l0,seg1,p_inters))&& (LineSegmentIntersection(l1,seg0,p_inters))); } } /// interseciton between point and triangle template inline bool IsInsideTrianglePoint( const Triangle2 & t,const Point2 & p) { Point2 p0=t.P0(0); Point2 p1=t.P0(1); Point2 p2=t.P0(2); ///first test with bounding box vcg::Box2 b2d; b2d.Add(p0); b2d.Add(p1); b2d.Add(p2); if (!b2d.IsIn(p)) return false; ///then text convex if (!Convex(p0,p1,p2)) std::swap >(p1,p2); return((Convex(p,p0,p1))&&(Convex(p,p1,p2))&&(Convex(p,p2,p0))); //return((Convex(p,p0,p1))&&(Convex(p,p1,p2))&&(Convex(p,p2,p0))); } //intersection between a circle and a line template inline bool CircleLineIntersection(const vcg::Line2 & line, const vcg::Point2 ¢er, const SCALAR_TYPE &radius, vcg::Point2 &p0, vcg::Point2 &p1) { typedef typename SCALAR_TYPE ScalarType; ///translate with origin on the center ScalarType x1,x2,y1,y2; x1=line.Origin().X()-center.X(); y1=line.Origin().Y()-center.Y(); x2=x1+line.Direction().X(); y2=y1+line.Direction().Y(); ScalarType dx,dy,dr,D,delta,sign; dx=x2-x1; dy=y2-y1; dr=sqrt(dx*dx+dy*dy); D=x1*y2-x2*y1; delta=radius*radius*dr*dr-D*D; if (dy>=0) sign=1; else sign=-1; if (delta<0.000001) return false;///no intersection else { p0.X()=(D*dy+sign*dx*sqrt(delta))/dr*dr; p0.Y()=(-D*dx+fabs(dy)*sqrt(delta))/dr*dr; p1.X()=(D*dy-sign*dx*sqrt(delta))/dr*dr; p1.Y()=(-D*dx-fabs(dy)*sqrt(delta))/dr*dr; p0+=center; p1+=center; return true; } } /*@}*/ } // end namespace #endif qutemol/vcg/vcg/space/line2.h0000444000175000017500000001710710703643101014436 0ustar mbamba/**************************************************************************** * VCGLib o o * * Visual and Computer Graphics Library o o * * _ O _ * * Copyright(C) 2004 \/)\/ * * Visual Computing Lab /\/| * * ISTI - Italian National Research Council | * * \ * * All rights reserved. * * * * 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. * * * * 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 (http://www.gnu.org/licenses/gpl.txt) * * for more details. * * * ****************************************************************************/ /**************************************************************************** History ****************************************************************************/ #ifndef __VCGLIB_LINE2 #define __VCGLIB_LINE2 #include namespace vcg { /** \addtogroup space */ /*@{*/ /** Templated class for 2D lines. This is the class for infinite lines in 3D space. A Line is stored just as two Point2: an origin and a direction (not necessarily normalized). @param LineScalarType (template parameter) Specifies the type of scalar used to represent coords. @param NORM: if on, the direction is always Normalized */ template class Line2 { public: /// The scalar type typedef LineScalarType ScalarType; /// The point type typedef Point2 PointType; /// The line type typedef Line2 LineType; private: /// Origin PointType _ori; /// Direction (not necessarily normalized, unless so specified by NORM) PointType _dir; public: //@{ /** @name Members to access the origin or direction Direction() cannot be assigned directly. Use SetDirection() or Set() instead. **/ /// inline const PointType &Origin() const { return _ori; } inline PointType &Origin() { return _ori; } inline const PointType &Direction() const { return _dir; } /// sets the origin inline void SetOrigin( const PointType & ori ) { _ori=ori; } /// sets the direction inline void SetDirection( const PointType & dir) { _dir=dir; if (NORM) _dir.Normalize(); } /// sets origin and direction. inline void Set( const PointType & ori, const PointType & dir ) { SetOrigin(ori); SetDirection(dir); } //@} //@{ /** @name Constructors **/ /// The empty constructor Line2() {}; /// The (origin, direction) constructor Line2(const PointType &ori, const PointType &dir) {SetOrigin(ori); SetDirection(dir);}; //@} /// Operator to compare two lines inline bool operator == ( LineType const & p ) const { return _ori==p._ori && _dir==p._dir; } /// Operator to dispare two lines inline bool operator != ( LineType const & p ) const { return _ori!=p._ori || _dir!=p._dir; } /// Projects a point on the line inline ScalarType Projection( const PointType &p ) const { if (NORM) return ScalarType((p-_ori)*_dir); else return ScalarType((p-_ori)*_dir/_dir.SquaredNorm()); } /// returns wheter this type is normalized or not static bool IsNormalized() {return NORM;}; /// calculates the point of parameter t on the line. inline PointType P( const ScalarType t ) const { return _ori + _dir * t; } /// normalizes direction field (returns a Normalized Line) inline Line2 &Normalize() { if (!NORM) _dir.Normalize(); return *((Line2*)this);} /// normalizes direction field (returns a Normalized Line) - static version static Line2 &Normalize(LineType &p) { p.Normalize(); return *((Line2*)(&p));} /// importer for different line types (with any scalar type or normalization beaviour) template inline void Import( const Line2 & b ) { _ori.Import( b.Origin() ); _dir.Import( b.Direction() ); if ((NORM) && (!K)) _dir.Normalize(); //printf("(=)%c->%c ",(!NORM)?'N':'n', NORM?'N':'n'); } /// constructs a new line importing it from an existing one template static LineType Construct( const Line2 & b ) { LineType res; res.Import(b); return res; } PointType ClosestPoint(const PointType & p) const{ return P(Projection(p)); } /// flips the line inline void Flip(){ _dir=-_dir; }; //@{ /** @name Linearity for 3d lines (operators +, -, *, /) so a line can be set as a linear combination of several lines. Note that the result of any operation returns a non-normalized line; however, the command r0 = r1*a + r2*b is licit even if r0,r1,r2 are normalized lines, as the normalization will take place within the final assignement operation. **/ inline Line2 operator + ( LineType const & p) const {return Line2 ( _ori+p.Origin(), _dir+p.Direction() );} inline Line2 operator - ( LineType const & p) const {return Line2 ( _ori-p.Origin(), _dir-p.Direction() );} inline Line2 operator * ( const ScalarType s ) const {return Line2 ( _ori*s, _dir*s );} inline Line2 operator / ( const ScalarType s ) const {ScalarType s0=((ScalarType)1.0)/s; return LineType( _ori*s0, _dir*s0 );} //@} //@{ /** @name Automatic normalized to non-normalized "Line3dN r0 = r1" is equivalent to "Line3dN r0 = r1.Normalize()" if r1 is a Line3d **/ /// copy constructor that takes opposite beaviour Line2 (const Line2 &r) { Import(r); }; /// assignment inline LineType & operator = ( Line2 const &r) { Import(r); return *this; }; //@} }; // end class definition typedef Line2 Line2s; typedef Line2 Line2i; typedef Line2 Line2f; typedef Line2 Line2d; typedef Line2 Line2sN; typedef Line2 Line2iN; typedef Line2 Line2fN; typedef Line2 Line2dN; /// returns closest point template Point2 ClosestPoint( Line2 l, const Point2 & p) { return l.P(l.Projection(p)); } template ScalarType Distance(const Line2 &l, const Point2 &p) { Point2 o = l.ClosestPoint(p); return (o - p).Norm(); } template vcg::Point2 Mirror(const vcg::Line2 &l, const vcg::Point2 &p) { vcg::Point2 nearest=vcg::ClosestPoint(l,p); vcg::Point2 dir=(nearest - p); nearest+=dir; return nearest; } /*@}*/ } // end namespace #endif qutemol/vcg/wrap/0000755000175000017500000000000011633404241012352 5ustar mbambaqutemol/vcg/wrap/system/0000755000175000017500000000000011633404241013676 5ustar mbambaqutemol/vcg/wrap/system/getopt.cpp0000444000175000017500000005567310131456677015736 0ustar mbamba/* Getopt for GNU. NOTE: getopt is now part of the C library, so if you don't know what "Keep this file name-space clean" means, talk to roland@gnu.ai.mit.edu before changing it! Copyright (C) 1987, 88, 89, 90, 91, 92, 1993 Free Software Foundation, Inc. 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, or (at your option) any later version. 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, 675 Mass Ave, Cambridge, MA 02139, USA. */ /* NOTE!!! AIX requires this to be the first thing in the file. Do not put ANYTHING before it! */ #ifdef HAVE_CONFIG_H # include #endif /* HAVE_CONFIG_H */ #if !__STDC__ && !defined(const) && IN_GCC #define const #endif /* This tells Alpha OSF/1 not to define a getopt prototype in . */ #ifndef _NO_PROTO #define _NO_PROTO #endif #include #define HAVE_STRING_H #ifdef HAVE_STRING_H # include #else # include #endif /* alloca header */ #ifdef WIN32 #include #endif /* Comment out all this code if we are using the GNU C Library, and are not actually compiling the library itself. This code is part of the GNU C Library, but also included in many other GNU distributions. Compiling and linking in this code is a waste when using the GNU C library (especially if it is a shared library). Rather than having every GNU program understand `configure --with-gnu-libc' and omit the object files, it is simpler to just do this in the source for each such file. */ #if defined (_LIBC) || !defined (__GNU_LIBRARY__) #include /* If GETOPT_COMPAT is defined, `+' as well as `--' can introduce a long-named option. Because this is not POSIX.2 compliant, it is being phased out. */ /* #define GETOPT_COMPAT */ /* This version of `getopt' appears to the caller like standard Unix `getopt' but it behaves differently for the user, since it allows the user to intersperse the options with the other arguments. As `getopt' works, it permutes the elements of ARGV so that, when it is done, all the options precede everything else. Thus all application programs are extended to handle flexible argument order. Setting the environment variable POSIXLY_CORRECT disables permutation. Then the behavior is completely standard. GNU application programs can use a third alternative mode in which they can distinguish the relative order of options and other arguments. */ /* `gettext (FOO)' is long to write, so we use `_(FOO)'. If NLS is unavailable, _(STRING) simply returns STRING. */ #ifdef HAVE_NLS # define _(string) gettext (string) # ifdef HAVE_LIBINTL_H # include # endif /* HAVE_LIBINTL_H */ #else /* not HAVE_NLS */ # define _(string) string #endif /* not HAVE_NLS */ #include "getopt.h" const char *exec_name; /* For communication from `getopt' to the caller. When `getopt' finds an option that takes an argument, the argument value is returned here. Also, when `ordering' is RETURN_IN_ORDER, each non-option ARGV-element is returned here. */ char *optarg = 0; /* Index in ARGV of the next element to be scanned. This is used for communication to and from the caller and for communication between successive calls to `getopt'. On entry to `getopt', zero means this is the first call; initialize. When `getopt' returns EOF, this is the index of the first of the non-option elements that the caller should itself scan. Otherwise, `optind' communicates from one call to the next how much of ARGV has been scanned so far. */ /* XXX 1003.2 says this must be 1 before any call. */ int optind = 0; /* The next char to be scanned in the option-element in which the last option character we returned was found. This allows us to pick up the scan where we left off. If this is zero, or a null string, it means resume the scan by advancing to the next ARGV-element. */ static char *nextchar; /* Callers store zero here to inhibit the error message for unrecognized options. */ int opterr = 1; /* Set to an option character which was unrecognized. This must be initialized on some systems to avoid linking in the system's own getopt implementation. */ int optopt = '?'; /* Describe how to deal with options that follow non-option ARGV-elements. If the caller did not specify anything, the default is REQUIRE_ORDER if the environment variable POSIXLY_CORRECT is defined, PERMUTE otherwise. REQUIRE_ORDER means don't recognize them as options; stop option processing when the first non-option is seen. This is what Unix does. This mode of operation is selected by either setting the environment variable POSIXLY_CORRECT, or using `+' as the first character of the list of option characters. PERMUTE is the default. We permute the contents of ARGV as we scan, so that eventually all the non-options are at the end. This allows options to be given in any order, even with programs that were not written to expect this. RETURN_IN_ORDER is an option available to programs that were written to expect options and other ARGV-elements in any order and that care about the ordering of the two. We describe each non-option ARGV-element as if it were the argument of an option with character code 1. Using `-' as the first character of the list of option characters selects this mode of operation. The special argument `--' forces an end of option-scanning regardless of the value of `ordering'. In the case of RETURN_IN_ORDER, only `--' can cause `getopt' to return EOF with `optind' != ARGC. */ static enum { REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER } ordering; #ifdef __GNU_LIBRARY__ /* We want to avoid inclusion of string.h with non-GNU libraries because there are many ways it can cause trouble. On some systems, it contains special magic macros that don't work in GCC. */ #include #define my_index strchr #define my_bcopy(src, dst, n) memcpy ((dst), (src), (n)) #else /* Avoid depending on library functions or files whose names are inconsistent. */ char *getenv (); static char * my_index (const char *str, int chr) { while (*str) { if (*str == chr) return (char *) str; str++; } return 0; } static void my_bcopy (const char *from, char *to, int size) { int i; for (i = 0; i < size; i++) to[i] = from[i]; } #endif /* GNU C library. */ /* Handle permutation of arguments. */ /* Describe the part of ARGV that contains non-options that have been skipped. `first_nonopt' is the index in ARGV of the first of them; `last_nonopt' is the index after the last of them. */ static int first_nonopt; static int last_nonopt; /* Exchange two adjacent subsequences of ARGV. One subsequence is elements [first_nonopt,last_nonopt) which contains all the non-options that have been skipped so far. The other is elements [last_nonopt,optind), which contains all the options processed since those non-options were skipped. `first_nonopt' and `last_nonopt' are relocated so that they describe the new indices of the non-options in ARGV after they are moved. */ static void exchange (char **argv) { int nonopts_size = (last_nonopt - first_nonopt) * sizeof (char *); char **temp = (char **) alloca (nonopts_size); /* Interchange the two blocks of data in ARGV. */ my_bcopy ((char *) &argv[first_nonopt], (char *) temp, nonopts_size); my_bcopy ((char *) &argv[last_nonopt], (char *) &argv[first_nonopt], (optind - last_nonopt) * sizeof (char *)); my_bcopy ((char *) temp, (char *) &argv[first_nonopt + optind - last_nonopt], nonopts_size); /* Update records for the slots the non-options now occupy. */ first_nonopt += (optind - last_nonopt); last_nonopt = optind; } /* Scan elements of ARGV (whose length is ARGC) for option characters given in OPTSTRING. If an element of ARGV starts with '-', and is not exactly "-" or "--", then it is an option element. The characters of this element (aside from the initial '-') are option characters. If `getopt' is called repeatedly, it returns successively each of the option characters from each of the option elements. If `getopt' finds another option character, it returns that character, updating `optind' and `nextchar' so that the next call to `getopt' can resume the scan with the following option character or ARGV-element. If there are no more option characters, `getopt' returns `EOF'. Then `optind' is the index in ARGV of the first ARGV-element that is not an option. (The ARGV-elements have been permuted so that those that are not options now come last.) OPTSTRING is a string containing the legitimate option characters. If an option character is seen that is not listed in OPTSTRING, return '?' after printing an error message. If you set `opterr' to zero, the error message is suppressed but we still return '?'. If a char in OPTSTRING is followed by a colon, that means it wants an arg, so the following text in the same ARGV-element, or the text of the following ARGV-element, is returned in `optarg'. Two colons mean an option that wants an optional arg; if there is text in the current ARGV-element, it is returned in `optarg', otherwise `optarg' is set to zero. If OPTSTRING starts with `-' or `+', it requests different methods of handling the non-option ARGV-elements. See the comments about RETURN_IN_ORDER and REQUIRE_ORDER, above. Long-named options begin with `--' instead of `-'. Their names may be abbreviated as long as the abbreviation is unique or is an exact match for some defined option. If they have an argument, it follows the option name in the same ARGV-element, separated from the option name by a `=', or else the in next ARGV-element. When `getopt' finds a long-named option, it returns 0 if that option's `flag' field is nonzero, the value of the option's `val' field if the `flag' field is zero. The elements of ARGV aren't really const, because we permute them. But we pretend they're const in the prototype to be compatible with other systems. LONGOPTS is a vector of `struct option' terminated by an element containing a name which is zero. LONGIND returns the index in LONGOPT of the long-named option found. It is only valid when a long-named option has been found by the most recent call. If LONG_ONLY is nonzero, '-' as well as '--' can introduce long-named options. */ int _getopt_internal (int argc, char *const *argv, const char *optstring, const struct option *longopts, int *longind, int long_only) { int option_index; optarg = 0; /* Initialize the internal data when the first call is made. Start processing options with ARGV-element 1 (since ARGV-element 0 is the program name); the sequence of previously skipped non-option ARGV-elements is empty. */ if (optind == 0) { first_nonopt = last_nonopt = optind = 1; nextchar = NULL; /* Determine how to handle the ordering of options and nonoptions. */ if (optstring[0] == '-') { ordering = RETURN_IN_ORDER; ++optstring; } else if (optstring[0] == '+') { ordering = REQUIRE_ORDER; ++optstring; } else if (getenv ("POSIXLY_CORRECT") != NULL) ordering = REQUIRE_ORDER; else ordering = PERMUTE; } if (nextchar == NULL || *nextchar == '\0') { if (ordering == PERMUTE) { /* If we have just processed some options following some non-options, exchange them so that the options come first. */ if (first_nonopt != last_nonopt && last_nonopt != optind) exchange ((char **) argv); else if (last_nonopt != optind) first_nonopt = optind; /* Now skip any additional non-options and extend the range of non-options previously skipped. */ while (optind < argc && (argv[optind][0] != '-' || argv[optind][1] == '\0') #ifdef GETOPT_COMPAT && (longopts == NULL || argv[optind][0] != '+' || argv[optind][1] == '\0') #endif /* GETOPT_COMPAT */ ) optind++; last_nonopt = optind; } /* Special ARGV-element `--' means premature end of options. Skip it like a null option, then exchange with previous non-options as if it were an option, then skip everything else like a non-option. */ if (optind != argc && !strcmp (argv[optind], "--")) { optind++; if (first_nonopt != last_nonopt && last_nonopt != optind) exchange ((char **) argv); else if (first_nonopt == last_nonopt) first_nonopt = optind; last_nonopt = argc; optind = argc; } /* If we have done all the ARGV-elements, stop the scan and back over any non-options that we skipped and permuted. */ if (optind == argc) { /* Set the next-arg-index to point at the non-options that we previously skipped, so the caller will digest them. */ if (first_nonopt != last_nonopt) optind = first_nonopt; return EOF; } /* If we have come to a non-option and did not permute it, either stop the scan or describe it to the caller and pass it by. */ if ((argv[optind][0] != '-' || argv[optind][1] == '\0') #ifdef GETOPT_COMPAT && (longopts == NULL || argv[optind][0] != '+' || argv[optind][1] == '\0') #endif /* GETOPT_COMPAT */ ) { if (ordering == REQUIRE_ORDER) return EOF; optarg = argv[optind++]; return 1; } /* We have found another option-ARGV-element. Start decoding its characters. */ nextchar = (argv[optind] + 1 + (longopts != NULL && argv[optind][1] == '-')); } if (longopts != NULL && ((argv[optind][0] == '-' && (argv[optind][1] == '-' || long_only)) #ifdef GETOPT_COMPAT || argv[optind][0] == '+' #endif /* GETOPT_COMPAT */ )) { const struct option *p; char *s = nextchar; int exact = 0; int ambig = 0; const struct option *pfound = NULL; int indfound; indfound = 0; /* To silence the compiler. */ while (*s && *s != '=') s++; /* Test all options for either exact match or abbreviated matches. */ for (p = longopts, option_index = 0; p->name; p++, option_index++) if (!strncmp (p->name, nextchar, s - nextchar)) { if (s - nextchar == strlen (p->name)) { /* Exact match found. */ pfound = p; indfound = option_index; exact = 1; break; } else if (pfound == NULL) { /* First nonexact match found. */ pfound = p; indfound = option_index; } else /* Second nonexact match found. */ ambig = 1; } if (ambig && !exact) { if (opterr) fprintf (stderr, _("%s: option `%s' is ambiguous\n"), exec_name, argv[optind]); nextchar += strlen (nextchar); optind++; return '?'; } if (pfound != NULL) { option_index = indfound; optind++; if (*s) { /* Don't test has_arg with >, because some C compilers don't allow it to be used on enums. */ if (pfound->has_arg) optarg = s + 1; else { if (opterr) { if (argv[optind - 1][1] == '-') /* --option */ fprintf (stderr, _("%s: option `--%s' doesn't allow an argument\n"), exec_name, pfound->name); else /* +option or -option */ fprintf (stderr, _("%s: option `%c%s' doesn't allow an argument\n"), exec_name, argv[optind - 1][0], pfound->name); } nextchar += strlen (nextchar); return '?'; } } else if (pfound->has_arg == 1) { if (optind < argc) optarg = argv[optind++]; else { if (opterr) fprintf (stderr, _("%s: option `%s' requires an argument\n"), exec_name, argv[optind - 1]); nextchar += strlen (nextchar); return optstring[0] == ':' ? ':' : '?'; } } nextchar += strlen (nextchar); if (longind != NULL) *longind = option_index; if (pfound->flag) { *(pfound->flag) = pfound->val; return 0; } return pfound->val; } /* Can't find it as a long option. If this is not getopt_long_only, or the option starts with '--' or is not a valid short option, then it's an error. Otherwise interpret it as a short option. */ if (!long_only || argv[optind][1] == '-' #ifdef GETOPT_COMPAT || argv[optind][0] == '+' #endif /* GETOPT_COMPAT */ || my_index (optstring, *nextchar) == NULL) { if (opterr) { if (argv[optind][1] == '-') /* --option */ fprintf (stderr, _("%s: unrecognized option `--%s'\n"), exec_name, nextchar); else /* +option or -option */ fprintf (stderr, _("%s: unrecognized option `%c%s'\n"), exec_name, argv[optind][0], nextchar); } nextchar = (char *) ""; optind++; return '?'; } } /* Look at and handle the next option-character. */ { char c = *nextchar++; char *temp = my_index (optstring, c); /* Increment `optind' when we start to process its last character. */ if (*nextchar == '\0') ++optind; if (temp == NULL || c == ':') { if (opterr) { #if 0 if (c < 040 || c >= 0177) fprintf (stderr, "%s: unrecognized option, character code 0%o\n", exec_name, c); else fprintf (stderr, "%s: unrecognized option `-%c'\n", exec_name, c); #else /* 1003.2 specifies the format of this message. */ fprintf (stderr, _("%s: illegal option -- %c\n"), exec_name, c); #endif } optopt = c; return '?'; } if (temp[1] == ':') { if (temp[2] == ':') { /* This is an option that accepts an argument optionally. */ if (*nextchar != '\0') { optarg = nextchar; optind++; } else optarg = 0; nextchar = NULL; } else { /* This is an option that requires an argument. */ if (*nextchar != '\0') { optarg = nextchar; /* If we end this ARGV-element by taking the rest as an arg, we must advance to the next element now. */ optind++; } else if (optind == argc) { if (opterr) { #if 0 fprintf (stderr, "%s: option `-%c' requires an argument\n", exec_name, c); #else /* 1003.2 specifies the format of this message. */ fprintf (stderr, _("%s: option requires an argument -- %c\n"), exec_name, c); #endif } optopt = c; if (optstring[0] == ':') c = ':'; else c = '?'; } else /* We already incremented `optind' once; increment it again when taking next ARGV-elt as argument. */ optarg = argv[optind++]; nextchar = NULL; } } return c; } } /* Calls internal getopt function to enable long option names. */ int getopt_long (int argc, char *const *argv, const char *shortopts, const struct option *longopts, int *longind) { return _getopt_internal (argc, argv, shortopts, longopts, longind, 0); } int getopt (int argc, char *const *argv, const char *optstring) { return _getopt_internal (argc, argv, optstring, (const struct option *) 0, (int *) 0, 0); } #endif /* _LIBC or not __GNU_LIBRARY__. */ #ifdef TEST /* Compile with -DTEST to make an executable for use in testing the above definition of `getopt'. */ int main (argc, argv) int argc; char **argv; { int c; int digit_optind = 0; while (1) { int this_option_optind = optind ? optind : 1; c = getopt (argc, argv, "abc:d:0123456789"); if (c == EOF) break; switch (c) { case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': if (digit_optind != 0 && digit_optind != this_option_optind) printf ("digits occur in two different argv-elements.\n"); digit_optind = this_option_optind; printf ("option %c\n", c); break; case 'a': printf ("option a\n"); break; case 'b': printf ("option b\n"); break; case 'c': printf ("option c with value `%s'\n", optarg); break; case '?': break; default: printf ("?? getopt returned character code 0%o ??\n", c); } } if (optind < argc) { printf ("non-option ARGV-elements: "); while (optind < argc) printf ("%s ", argv[optind++]); printf ("\n"); } exit (0); } #endif /* TEST */ qutemol/vcg/wrap/system/getopt.h0000444000175000017500000000756310131456677015376 0ustar mbamba/* Declarations for getopt. Copyright (C) 1989, 1990, 1991, 1992, 1993 Free Software Foundation, Inc. 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, or (at your option) any later version. 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, 675 Mass Ave, Cambridge, MA 02139, USA. */ #ifndef _GETOPT_H #define _GETOPT_H 1 #ifdef __cplusplus extern "C" { #endif extern const char *exec_name; /* For communication from `getopt' to the caller. When `getopt' finds an option that takes an argument, the argument value is returned here. Also, when `ordering' is RETURN_IN_ORDER, each non-option ARGV-element is returned here. */ extern char *optarg; /* Index in ARGV of the next element to be scanned. This is used for communication to and from the caller and for communication between successive calls to `getopt'. On entry to `getopt', zero means this is the first call; initialize. When `getopt' returns EOF, this is the index of the first of the non-option elements that the caller should itself scan. Otherwise, `optind' communicates from one call to the next how much of ARGV has been scanned so far. */ extern int optind; /* Callers store zero here to inhibit the error message `getopt' prints for unrecognized options. */ extern int opterr; /* Set to an option character which was unrecognized. */ extern int optopt; /* Describe the long-named options requested by the application. The LONG_OPTIONS argument to getopt_long or getopt_long_only is a vector of `struct option' terminated by an element containing a name which is zero. The field `has_arg' is: no_argument (or 0) if the option does not take an argument, required_argument (or 1) if the option requires an argument, optional_argument (or 2) if the option takes an optional argument. If the field `flag' is not NULL, it points to a variable that is set to the value given in the field `val' when the option is found, but left unchanged if the option is not found. To have a long-named option do something other than set an `int' to a compiled-in constant, such as set a value from `optarg', set the option's `flag' field to zero and its `val' field to a nonzero value (the equivalent single-letter option character, if there is one). For long options that have a zero `flag' field, `getopt' returns the contents of the `val' field. */ struct option { #if __STDC__ const char *name; #else char *name; #endif /* has_arg can't be an enum because some compilers complain about type mismatches in all the code that assumes it is an int. */ int has_arg; int *flag; int val; }; /* Names for the values of the `has_arg' field of `struct option'. */ #define no_argument 0 #define required_argument 1 #define optional_argument 2 extern int getopt (int argc, char *const *argv, const char *shortopts); extern int getopt_long (int argc, char *const *argv, const char *shortopts, const struct option *longopts, int *longind); extern int getopt_long_only (int argc, char *const *argv, const char *shortopts, const struct option *longopts, int *longind); /* Internal only. Users should not call this directly. */ extern int _getopt_internal (int argc, char *const *argv, const char *shortopts, const struct option *longopts, int *longind, int long_only); #ifdef __cplusplus } #endif #endif /* _GETOPT_H */ qutemol/vcg/wrap/math/0000755000175000017500000000000011633404241013303 5ustar mbambaqutemol/vcg/wrap/math/sparse_matrix.h0000444000175000017500000000203410243356110016327 0ustar mbamba#include #include #include ///this class define the interface to use sparse matrix ///you must extend this class and implement the code of each function in order ///to the system solver you're using. ///For details on implementation see system_interface_LDL.h as example template class SparseMatrix{ public: std::vector _Ap; std::vector _Ai; std::vector _Ax; typedef typename std::pair IndexType; int _dimension; public: ///initilaization of the system virtual void Initalize(int dimension) {_dimension=dimension;} ///create a sparse matrix given a set of entries as vector ///of pair of int virtual void CreateSparse(std::vector Entries) {} ///return the value of the matrix virtual ScalarType &A(int row,int col) {return (_Ax[0]);} ///return true if the rapresention of sparse matriz is symmetric virtual bool IsSymmetric() {return false;} virtual void Zero() {} ///return the dimension of the matrix virtual int Size(){return _dimension;} };qutemol/vcg/wrap/math/system_interface_ldl.h0000444000175000017500000000653010243356110017652 0ustar mbambaextern "C"{ #include } #include #include #include #include class SystemLDL:SparseMatrix{ private: typedef std::map mapType; std::vector _B; std::vector _X; std::vector Lx,D,Y ; std::vector Li,Lp,Parent,Lnz,Flag,Pattern; mapType _M; public: ///allocate the resources for the system of equations void Initalize(int dimension) { _dimension=dimension; _Ap.resize(_dimension+1); _M.clear(); _B.resize(_dimension); _X.resize(_dimension); } double &A(int row,int col) { IndexType I=IndexType(row,col); mapType::const_iterator ci=_M.find(I); if (ci==_M.end()) { std::swap(I.first,I.second); ci=_M.find(I); } assert(ci!=_M.end()); int index=(*ci).second; return(_Ax[index]); } double &B(int i) {return(_B[i]);} double &X(int i) {return (_X[i]);} void Solve() { int d,i; // /* factorize A into LDL' (P and Pinv not used) */ ldl_symbolic (_dimension, &(*_Ap.begin()), &(*_Ai.begin()), &(*Lp.begin()), &(*Parent.begin()), &(*Lnz.begin()), &(*Flag.begin()), NULL, NULL) ; // printf ("Nonzeros in L, excluding diagonal: %d\n", Lp [_dimension]) ; d = ldl_numeric (_dimension, &(*_Ap.begin()), &(*_Ai.begin()), &(*_Ax.begin()), &(*Lp.begin()) , &(*Parent.begin()), &(*Lnz.begin()), &(*Li.begin()), &(*Lx.begin()), &(*D.begin()), &(*Y.begin()), &(*Pattern.begin()), &(*Flag.begin()), NULL, NULL) ; if (d == _dimension) { /* solve Ax=b, overwriting b with the solution x */ ldl_lsolve (_dimension, &(*_B.begin()), &(*Lp.begin()), &(*Li.begin()), &(*Lx.begin())) ; ldl_dsolve (_dimension, &(*_B.begin()), (&*D.begin()) ); ldl_ltsolve (_dimension, &(*_B.begin()), &(*Lp.begin()), &(*Li.begin()), &(*Lx.begin())) ; for (i = 0 ; i < _dimension ; i++) _X[i]=_B[i];//printf ("x [%d] = %g\n", i, b [i]) ; } else///dl_numeric failed { assert(0); } } bool IsSymmetric() {return true;} void Zero() { for (int i=0;i Entries) { _Ax.clear(); _Ai.clear(); int _nonzero=0; ///put the index of vertices for each edge ///in the right order for simmetry of the sistem std::vector::iterator Vi; for (Vi=Entries.begin();Vi=0); assert((*Vi).second>=0); if ((*Vi).first>(*Vi).second) std::swap((*Vi).first,(*Vi).second); } ///the sort and erase duplicates std::sort(Entries.begin(),Entries.end()); std::vector::iterator Vend=std::unique(Entries.begin(),Entries.end()); Entries.erase(Vend,Entries.end()); _Ax.resize(Entries.size()); _Ai.resize(Entries.size()); _M.clear(); int col=0; int i=0; Vi=Entries.begin(); while (Vi(I,_nonzero)); _Ai[_nonzero]=(*Vi).second; _nonzero++; Vi++; } i++; } _Ap[_dimension]=_nonzero; Lx.resize(_nonzero); D.resize(_dimension); Y.resize(_dimension); Li.resize(_nonzero); Lp.resize(_dimension+1); Parent.resize(_dimension); Lnz.resize(_dimension); Flag.resize(_dimension); Pattern.resize(_dimension); } };qutemol/vcg/wrap/utils.h0000444000175000017500000000647110513710055013670 0ustar mbamba/**************************************************************************** * VCGLib o o * * Visual and Computer Graphics Library o o * * _ O _ * * Copyright(C) 2004 \/)\/ * * Visual Computing Lab /\/| * * ISTI - Italian National Research Council | * * \ * * All rights reserved. * * * * 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. * * * * 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 (http://www.gnu.org/licenses/gpl.txt) * * for more details. * * * ****************************************************************************/ /**************************************************************************** History $Log: utils.h,v $ Revision 1.4 2006/10/13 13:10:05 cignoni Changed barycenter functor to the new Baricenter(face) style Revision 1.3 2005/11/12 18:10:35 cignoni Removed Abs and LowClampToZero and added comments Revision 1.2 2005/09/29 22:22:59 m_di_benedetto Added classes GetBox3Functor and GetBarycenter3Functor. Revision 1.1 2005/09/28 20:01:35 m_di_benedetto First Commit. ****************************************************************************/ #ifndef __VCGLIB_WRAPUTILS_H #define __VCGLIB_WRAPUTILS_H // vcg headers #include #include #include namespace vcg { class EmptyClass { public: typedef EmptyClass ClassType; }; class GetPointerFunctor { public: typedef GetPointerFunctor ClassType; template inline T * operator () (T & t) { return (&t); } template inline T * operator () (T * & t) { return (t); } }; /// Helper class used to build in a easy way a functor that gives the bbox of a face /// used mainly in the aabbtree that require such a functor as a parameter class GetBox3Functor { public: template void operator () (const OBJTYPE & obj, Box3 & box) { Box3 tb; obj.GetBBox(tb); box.Import(tb); } }; class GetBarycenter3Functor { public: template void operator () (const OBJTYPE & obj, Point3 & bar) { bar.Import(Barycenter(obj)); } }; } // end namespace vcg #endif // #ifndef __VCGLIB_WRAPUTILS_H qutemol/vcg/wrap/dae/0000755000175000017500000000000011633404241013103 5ustar mbambaqutemol/vcg/wrap/dae/colladaformat.h0000444000175000017500000007365310761521303016100 0ustar mbamba#ifndef _COLLADA_FORMAT_H #define _COLLADA_FORMAT_H #include #include #include #include template struct CoordNumber { public: static unsigned int coord() { return 0; } }; template<> struct CoordNumber { public: static unsigned int coord() { return 2; } }; template<> struct CoordNumber { public: static unsigned int coord() { return 3; } }; template<> struct CoordNumber { public: static unsigned int coord() { return 4; } }; namespace Collada { namespace Tags { static const QString testSharp(const QString& str) { QString sharp = ""; if (str.at(0) != '#') sharp = '#'; return (sharp + str); } class ColladaTag : public XMLTag { public: ColladaTag() :XMLTag("COLLADA") { _attributes.push_back(TagAttribute("xmlns","http://www.collada.org/2005/11/COLLADASchema")); _attributes.push_back(TagAttribute("version","1.4.1")); } }; class AssetTag : public XMLTag { public: AssetTag() :XMLTag("asset") { } }; class ContributorTag : public XMLTag { public: ContributorTag() :XMLTag("contributor") { } }; class AuthorTag : public XMLLeafTag { public: AuthorTag() :XMLLeafTag("author") { _text.push_back("VCGLab"); } }; class AuthoringToolTag : public XMLLeafTag { public: AuthoringToolTag() :XMLLeafTag("authoring_tool") { _text.push_back("VCGLib | MeshLab"); } }; class UpAxisTag : public XMLLeafTag { public: UpAxisTag(const QString& up = "Y_UP") :XMLLeafTag("up_axis") { _text.push_back(up); } }; class LibraryImagesTag : public XMLTag { public: LibraryImagesTag() :XMLTag("library_images") { } }; class ImageTag : public XMLTag { public: ImageTag(const QString& id,const QString& name) :XMLTag("image") { _attributes.push_back(TagAttribute("id",id)); _attributes.push_back(TagAttribute("name",name)); } }; class InitFromTag : public XMLLeafTag { public: InitFromTag(const QString& txtpathname) :XMLLeafTag("init_from") { _text.push_back(txtpathname); } }; class LibraryMaterialsTag : public XMLTag { public: LibraryMaterialsTag() :XMLTag("library_materials") { } }; class MaterialTag : public XMLTag { public: MaterialTag(const QString& id,const QString& name) :XMLTag("material") { _attributes.push_back(TagAttribute("id",id)); _attributes.push_back(TagAttribute("name",name)); } }; class InstanceEffectTag : public XMLLeafTag { public: InstanceEffectTag(const QString& url) :XMLLeafTag("instance_effect") { _attributes.push_back(TagAttribute("url",testSharp(url))); } }; class LibraryEffectsTag : public XMLTag { public: LibraryEffectsTag() :XMLTag("library_effects") { } }; class EffectTag : public XMLTag { public: EffectTag(const QString& id) :XMLTag("effect") { _attributes.push_back(TagAttribute("id",id)); } }; class ProfileCommonTag : public XMLTag { public: ProfileCommonTag() :XMLTag("profile_COMMON") { } }; class NewParamTag : public XMLTag { public: NewParamTag(const QString& sid) :XMLTag("newparam") { _attributes.push_back(TagAttribute("sid",sid)); } }; class SurfaceTag : public XMLTag { public: SurfaceTag(const QString& type = QString("2D")) :XMLTag("surface") { _attributes.push_back(TagAttribute("type",type)); } }; class FormatTag : public XMLLeafTag { public: FormatTag(const QString& format) :XMLLeafTag("format") { _text.push_back(format); } }; class Sampler2DTag : public XMLTag { public: Sampler2DTag() :XMLTag("sampler2D") { } }; class SourceTag : public XMLLeafTag { public: SourceTag(const QString& id,const QString& name) :XMLLeafTag("source") { _attributes.push_back(TagAttribute("id",id)); _attributes.push_back(TagAttribute("name",name)); } SourceTag(const QString& source) :XMLLeafTag("source") { _text.push_back(source); } }; class MinFilterTag : public XMLLeafTag { public: MinFilterTag(const QString& filter) :XMLLeafTag("minfilter") { _text.push_back(filter); } }; class MagFilterTag : public XMLLeafTag { public: MagFilterTag(const QString& filter) :XMLLeafTag("magfilter") { _text.push_back(filter); } }; class TechniqueTag : public XMLTag { public: TechniqueTag(const QString& sid) :XMLTag("technique") { _attributes.push_back(TagAttribute("sid",sid)); } }; class TechniqueCommonTag : public XMLTag { public: TechniqueCommonTag() :XMLTag("technique_common") { } }; class BlinnTag : public XMLTag { public: BlinnTag() :XMLTag("blinn") { } }; class EmissionTag : public XMLTag { public: EmissionTag() :XMLTag("emission") { } }; class ColorTag : public XMLLeafTag { public: ColorTag(const float r,const float g,const float b,const float a) :XMLLeafTag("color") { _text.push_back(QString::number(r)); _text.push_back(QString::number(g)); _text.push_back(QString::number(b)); _text.push_back(QString::number(a)); } }; class AmbientTag : public XMLTag { public: AmbientTag() :XMLTag("ambient") { } }; class DiffuseTag : public XMLTag { public: DiffuseTag() :XMLTag("diffuse") { } }; class TextureTag : public XMLLeafTag { public: TextureTag(const QString& texture,const QString& texcoord) :XMLLeafTag("texture") { _attributes.push_back(TagAttribute("texture",texture)); _attributes.push_back(TagAttribute("texcoord",texcoord)); } }; class SpecularTag : public XMLTag { public: SpecularTag() :XMLTag("specular") { } }; class ShininessTag : public XMLTag { public: ShininessTag() :XMLTag("shininess") { } }; class FloatTag : public XMLLeafTag { public: FloatTag(const float floatnum) :XMLLeafTag("float") { _text.push_back(QString::number(floatnum)); } }; class ReflectiveTag : public XMLTag { public: ReflectiveTag() :XMLTag("reflective") { } }; class ReflectivityTag : public XMLTag { public: ReflectivityTag() :XMLTag("reflectivity") { } }; class TransparentTag : public XMLTag { public: TransparentTag() :XMLTag("transparent") { } }; class TransparencyTag : public XMLTag { public: TransparencyTag() :XMLTag("transparency") { } }; class IndexOfRefractionTag : public XMLTag { public: IndexOfRefractionTag() :XMLTag("index_of_refraction") { } }; class LibraryGeometriesTag : public XMLTag { public: LibraryGeometriesTag() :XMLTag("library_geometries") { } }; class GeometryTag : public XMLTag { public: GeometryTag(const QString& id,const QString& name) :XMLTag("geometry") { _attributes.push_back(TagAttribute("id",id)); _attributes.push_back(TagAttribute("name",name)); } }; class MeshTag : public XMLTag { public: MeshTag() :XMLTag("mesh") { } }; class ArraySourceTag : public XMLTag { public: ArraySourceTag(const QString& id,const QString& name) :XMLTag("source") { _attributes.push_back(TagAttribute("id",id)); _attributes.push_back(TagAttribute("name",name)); } }; class FloatArrayTag : public XMLLeafTag { public: enum ARRAYSEMANTIC {VERTPOSITION,VERTNORMAL,FACENORMAL,WEDGETEXCOORD}; template FloatArrayTag(const QString& id,const int count,const MESHTYPE& m,ARRAYSEMANTIC sem,const unsigned int componenttype) :XMLLeafTag("float_array") { _attributes.push_back(TagAttribute("id",id)); _attributes.push_back(TagAttribute("count",QString::number(count))); if ((sem == VERTPOSITION) || (sem == VERTNORMAL)) { for(typename MESHTYPE::ConstVertexIterator vit = m.vert.begin();vit != m.vert.end();++vit) { for(unsigned int ii = 0; ii < componenttype;++ii) { if (sem == VERTPOSITION) _text.push_back(QString::number(vit->P()[ii])); else { typename MESHTYPE::VertexType::NormalType r = vit->cN(); r.Normalize(); _text.push_back(QString::number(r[ii])); } } } } else { for(typename MESHTYPE::ConstFaceIterator fit = m.face.begin();fit != m.face.end();++fit) { if (sem == FACENORMAL) { for(unsigned int ii = 0; ii < componenttype;++ii) { typename MESHTYPE::FaceType::NormalType r = fit->cN(); r.Normalize(); _text.push_back(QString::number(r[ii])); } } else { for(unsigned int ii = 0; ii < 3;++ii) { _text.push_back(QString::number(fit->cWT(ii).U())); _text.push_back(QString::number(fit->cWT(ii).V())); } } } } } }; //class FloatWedgeArrayTag : public XMLLeafTag //{ //public: // template // FloatWedgeArrayTag(const QString& id,const int count,const MESHTYPE& m,const AccessorComponentNumberInfo& accessor) // :XMLLeafTag("float_array") // { // _attributes.push_back(TagAttribute("id",id)); // _attributes.push_back(TagAttribute("count",QString::number(count))); // for(typename SIMPLEXACCESSOR::ConstIterator it= accessor._a.begin();it != accessor._a.end(); ++it) // { // for(unsigned int ii = 0; ii < 3;++ii) // { // _text.push_back(QString::number(accessor._a(*it,ii).U())); // _text.push_back(QString::number(accessor._a(*it,ii).V())); // } // } // } //}; class AccessorTag : public XMLTag { public: AccessorTag(const int count,const QString& source,const int stride) :XMLTag("accessor") { _attributes.push_back(TagAttribute("count",QString::number(count))); _attributes.push_back(TagAttribute("source",testSharp(source))); _attributes.push_back(TagAttribute("stride",QString::number(stride))); } }; class ParamTag : public XMLTag { public: ParamTag(const QString& name,const QString& type) :XMLTag("param") { _attributes.push_back(TagAttribute("name",name)); _attributes.push_back(TagAttribute("type",type)); } }; class VerticesTag : public XMLTag { public: VerticesTag(const QString& id) :XMLTag("vertices") { _attributes.push_back(TagAttribute("id",id)); } }; class InputTag : public XMLTag { public: InputTag(const QString& semantic,const QString& source) :XMLTag("input") { _attributes.push_back(TagAttribute("semantic",semantic)); _attributes.push_back(TagAttribute("source",testSharp(source))); } InputTag(const int offset,const QString& semantic,const QString& source) :XMLTag("input") { _attributes.push_back(TagAttribute("offset",QString::number(offset))); _attributes.push_back(TagAttribute("semantic",semantic)); _attributes.push_back(TagAttribute("source",testSharp(source))); } }; class TrianglesTag : public XMLTag { public: TrianglesTag(const int count) :XMLTag("triangles") { _attributes.push_back(TagAttribute("count",QString::number(count))); } TrianglesTag(const int count,const QString& material) :XMLTag("triangles") { _attributes.push_back(TagAttribute("count",QString::number(count))); _attributes.push_back(TagAttribute("material",material)); } }; class PTag : public XMLLeafTag { public: template PTag(const MESHTYPE& m,const unsigned int nedge,bool norm = false,bool texcoord = false) :XMLLeafTag("p") { int cont = 0; for(typename MESHTYPE::ConstFaceIterator it= m.face.begin();it != m.face.end(); ++it) { for(unsigned int ii = 0; ii < nedge; ++ii) { int dist = it->V(ii) - &(*m.vert.begin()); _text.push_back(QString::number(dist)); if (norm) _text.push_back(QString::number(cont)); if (texcoord) _text.push_back(QString::number(cont * nedge + ii)); } ++cont; } } template PTag(const MESHTYPE& m,const unsigned int nedge,QVector& patchfaces,bool norm = false,bool texcoord = false) :XMLLeafTag("p") { int cont = 0; for(QVector::iterator it = patchfaces.begin();it != patchfaces .end(); ++it) { for(unsigned int ii = 0; ii < nedge; ++ii) { const typename MESHTYPE::FaceType& f = m.face[*it]; int dist = f.V(ii) - &(*m.vert.begin()); _text.push_back(QString::number(dist)); if (norm) _text.push_back(QString::number(*it)); if (texcoord) _text.push_back(QString::number(*it * nedge + ii)); } ++cont; } } }; class LibraryVisualScenesTag : public XMLTag { public: LibraryVisualScenesTag() :XMLTag("library_visual_scenes") { } }; class VisualSceneTag : public XMLTag { public: VisualSceneTag(const QString& id,const QString& name) :XMLTag("visual_scene") { _attributes.push_back(TagAttribute("id",id)); _attributes.push_back(TagAttribute("name",name)); } }; class NodeTag : public XMLTag { public: NodeTag(const QString& id,const QString& name) :XMLTag("node") { _attributes.push_back(TagAttribute("id",id)); _attributes.push_back(TagAttribute("name",name)); } }; class RotateTag : public XMLLeafTag { public: RotateTag(const QString& sid,const vcg::Point4f& p) :XMLLeafTag("rotate") { _attributes.push_back(TagAttribute("sid",sid)); for(unsigned int ii =0;ii < 4; ++ii) _text.push_back(QString::number(p[ii])); } }; class TranslateTag : public XMLLeafTag { public: TranslateTag(const QString& sid,const vcg::Point4f& p) :XMLLeafTag("translate") { _attributes.push_back(TagAttribute("sid",sid)); for(unsigned int ii =0;ii < 4; ++ii) _text.push_back(QString::number(p[ii])); } }; class InstanceGeometryTag : public XMLTag { public: InstanceGeometryTag(const QString& url) :XMLTag("instance_geometry") { _attributes.push_back(TagAttribute("url",testSharp(url))); } }; class BindMaterialTag : public XMLTag { public: BindMaterialTag() :XMLTag("bind_material") { } }; class InstanceMaterialTag : public XMLTag { public: InstanceMaterialTag(const QString& symbol,const QString& target) :XMLTag("instance_material") { _attributes.push_back(TagAttribute("symbol",symbol)); _attributes.push_back(TagAttribute("target",testSharp(target))); } }; class BindVertexInputTag : public XMLTag { public: BindVertexInputTag(const QString& semantic,const QString& input_semantic,const QString& input_set) :XMLTag("bind_vertex_input") { _attributes.push_back(TagAttribute("semantic",semantic)); _attributes.push_back(TagAttribute("input_semantic",input_semantic)); } }; class SceneTag : public XMLTag { public: SceneTag() :XMLTag("scene") { } }; #include class CreatedTag : public XMLLeafTag//added { public: CreatedTag() :XMLLeafTag("created") { QDateTime dateCreated = QDateTime::currentDateTime().toUTC(); QString dateCreatedStr = dateCreated.toString(); _text.push_back(dateCreatedStr); } }; class ModifiedTag : public XMLLeafTag//added { public: ModifiedTag() :XMLLeafTag("modified") { QDateTime dateModified = QDateTime::currentDateTime().toUTC(); QString dateModifiedStr = dateModified.toString(); _text.push_back(dateModifiedStr); } }; class InstanceVisualSceneTag : public XMLTag { public: InstanceVisualSceneTag(const QString& url) :XMLTag("instance_visual_scene") { _attributes.push_back(TagAttribute("url",testSharp(url))); } }; } //Tags class DocumentManager { private: static void connectHierarchyNode(XMLInteriorNode* node0,XMLInteriorNode* node1,XMLLeafNode* leaf) { node1->_sons.push_back(leaf); node0->_sons.push_back(node1); } static void connectHierarchyNode(XMLInteriorNode* node0,XMLInteriorNode* node1,XMLInteriorNode* node2,XMLInteriorNode* node3,XMLNode* node4) { node3->_sons.push_back(node4); node2->_sons.push_back(node3); node1->_sons.push_back(node2); node0->_sons.push_back(node1); } static void connectHierarchyNode(XMLInteriorNode* node0,XMLInteriorNode* node1,XMLInteriorNode* node2,XMLInteriorNode* node3) { node2->_sons.push_back(node3); node1->_sons.push_back(node2); node0->_sons.push_back(node1); } static void connectHierarchyNode(XMLInteriorNode* node0,XMLInteriorNode* node1,XMLInteriorNode* node2) { node1->_sons.push_back(node2); node0->_sons.push_back(node1); } template static void splitMeshInTexturedPatches(const MESHMODELTYPE& m,QVector >& patches) { patches.resize(m.textures.size()); int cc = 0; for(typename MESHMODELTYPE::ConstFaceIterator itf = m.face.begin();itf != m.face.end();++itf) { int tmp = itf->cWT(0).N(); patches[tmp].push_back(cc); ++cc; } } public: template static XMLDocument* createColladaDocument(const MESHMODELTYPE& m,const int mask) { //for now we export only triangularface const unsigned int edgefacenum = 3; typedef XMLInteriorNode XNode; typedef XMLLeafNode XLeaf; XNode* root = new XNode(new Tags::ColladaTag()); XNode* assetnode = new XNode(new Tags::AssetTag()); XNode* contributornode = new XNode(new Tags::ContributorTag()); contributornode->_sons.push_back(new XLeaf(new Tags::AuthorTag())); contributornode->_sons.push_back(new XLeaf(new Tags::AuthoringToolTag())); assetnode->_sons.push_back(contributornode); assetnode->_sons.push_back(new XLeaf(new Tags::UpAxisTag())); assetnode->_sons.push_back(new XLeaf(new Tags::CreatedTag()));//added assetnode->_sons.push_back(new XLeaf(new Tags::ModifiedTag())); root->_sons.push_back(assetnode); XNode* libimages = new XNode(new Tags::LibraryImagesTag()); for(unsigned int ii = 0;ii < m.textures.size();++ii) { QString subfix = QString::number(ii); XNode* imagenode = new XNode(new Tags::ImageTag(QString("texture") + subfix,QString("texture") + subfix)); XLeaf* initfromnode = new XLeaf(new Tags::InitFromTag(QString::fromStdString(m.textures[ii]))); imagenode->_sons.push_back(initfromnode); libimages->_sons.push_back(imagenode); } root->_sons.push_back(libimages); XNode* libmaterials = new XNode(new Tags::LibraryMaterialsTag()); for(unsigned int ii = 0;ii < m.textures.size();++ii) { QString subfix = QString::number(ii); QString mat = "material" + subfix; XNode* materialnode = new XNode(new Tags::MaterialTag(mat,mat)); XLeaf* instanceeff = new XLeaf(new Tags::InstanceEffectTag(mat+"-fx")); materialnode->_sons.push_back(instanceeff); libmaterials->_sons.push_back(materialnode); } root->_sons.push_back(libmaterials); XNode* libeffects = new XNode(new Tags::LibraryEffectsTag()); for(unsigned int ii = 0;ii < m.textures.size();++ii) { QString subfix = QString::number(ii); QString mat = "material" + subfix + "-fx"; XNode* effectnode = new XNode(new Tags::EffectTag(mat)); XNode* procommnode = new XNode(new Tags::ProfileCommonTag()); QString tex = QString("texture")+subfix; XNode* newparamnode = new XNode(new Tags::NewParamTag(tex+"-surface")); XNode* surfacenode = new XNode(new Tags::SurfaceTag()); XLeaf* initfromnode = new XLeaf(new Tags::InitFromTag(tex)); QImage img(QString::fromStdString(m.textures[ii])); QImage::Format f = img.format(); QString form = "R8G8B8"; if (f==QImage::Format_ARGB32) form = "A8R8G8B8"; XLeaf* formatnode = new XLeaf(new Tags::FormatTag(form)); surfacenode->_sons.push_back(initfromnode); surfacenode->_sons.push_back(formatnode); newparamnode->_sons.push_back(surfacenode); procommnode->_sons.push_back(newparamnode); XNode* newparamnode2 = new XNode(new Tags::NewParamTag(tex+"-sampler")); XNode* samplernode = new XNode(new Tags::Sampler2DTag()); XLeaf* sourcenode = new XLeaf(new Tags::SourceTag(tex+"-surface")); XLeaf* minfilt = new XLeaf(new Tags::MinFilterTag("LINEAR")); XLeaf* magfilt = new XLeaf(new Tags::MagFilterTag("LINEAR")); samplernode->_sons.push_back(sourcenode); samplernode->_sons.push_back(minfilt); samplernode->_sons.push_back(magfilt); newparamnode2->_sons.push_back(samplernode); procommnode->_sons.push_back(newparamnode2); XNode* technode = new XNode(new Tags::TechniqueTag("common")); XNode* blinnnode = new XNode(new Tags::BlinnTag()); XNode* emissionnode = new XNode(new Tags::EmissionTag()); XLeaf* colorem = new XLeaf(new Tags::ColorTag(0,0,0,1)); XNode* ambientnode = new XNode(new Tags::AmbientTag()); XLeaf* coloramb = new XLeaf(new Tags::ColorTag(0,0,0,1)); XNode* diffusenode = new XNode(new Tags::DiffuseTag()); XLeaf* texturenode = new XLeaf(new Tags::TextureTag(tex,"UVSET0")); XNode* specularnode = new XNode(new Tags::SpecularTag()); XLeaf* colorspec = new XLeaf(new Tags::ColorTag(0,0,0,1)); XNode* shinenode = new XNode(new Tags::ShininessTag()); XLeaf* floatshine = new XLeaf(new Tags::FloatTag(0.3)); XNode* reflectivenode = new XNode(new Tags::ReflectiveTag()); XLeaf* colorref = new XLeaf(new Tags::ColorTag(0,0,0,1)); XNode* reflectivitynode = new XNode(new Tags::ReflectivityTag()); XLeaf* floatrefl = new XLeaf(new Tags::FloatTag(0.5)); XNode* transparentnode = new XNode(new Tags::TransparentTag()); XLeaf* colortra = new XLeaf(new Tags::ColorTag(0,0,0,1)); XNode* transparencynode = new XNode(new Tags::TransparencyTag()); XLeaf* floattra = new XLeaf(new Tags::FloatTag(0.0)); XNode* refranode = new XNode(new Tags::IndexOfRefractionTag()); XLeaf* floatrefrac = new XLeaf(new Tags::FloatTag(0.0)); connectHierarchyNode(blinnnode,emissionnode,colorem); connectHierarchyNode(blinnnode,ambientnode,coloramb); connectHierarchyNode(blinnnode,diffusenode,texturenode); connectHierarchyNode(blinnnode,specularnode,colorspec); connectHierarchyNode(blinnnode,shinenode,floatshine); connectHierarchyNode(blinnnode,reflectivenode,colorref); connectHierarchyNode(blinnnode,reflectivitynode,floatrefl); connectHierarchyNode(blinnnode,transparentnode,colortra); connectHierarchyNode(blinnnode,transparencynode,floattra); connectHierarchyNode(blinnnode,refranode,floatrefrac); connectHierarchyNode(procommnode,technode,blinnnode); effectnode->_sons.push_back(procommnode); libeffects->_sons.push_back(effectnode); } root->_sons.push_back(libeffects); XNode* libgeo = new XNode(new Tags::LibraryGeometriesTag()); QString subfix = "0"; QString shape = "shape" + subfix; XNode* geometrynode = new XNode(new Tags::GeometryTag(shape+"-lib",shape)); XNode* meshnode = new XNode(new Tags::MeshTag()); XNode* sourcepos = new XNode(new Tags::SourceTag(shape+"-lib-positions","position")); //AccessorComponentNumberInfo> acc(m); unsigned int return_component_number = CoordNumber::coord(); XLeaf* floatarr = new XLeaf(new Tags::FloatArrayTag(shape+"-lib-positions-array",m.vert.size() * return_component_number,m,Tags::FloatArrayTag::VERTPOSITION,return_component_number)); XNode* techcommnode = new XNode(new Tags::TechniqueCommonTag()); XNode* accessornode = new XNode(new Tags::AccessorTag(m.vert.size(),shape+"-lib-positions-array",return_component_number)); XNode* paramx = new XNode(new Tags::ParamTag("X","float")); XNode* paramy = new XNode(new Tags::ParamTag("Y","float")); XNode* paramz = new XNode(new Tags::ParamTag("Z","float")); sourcepos->_sons.push_back(floatarr); accessornode->_sons.push_back(paramx); accessornode->_sons.push_back(paramy); accessornode->_sons.push_back(paramz); techcommnode->_sons.push_back(accessornode); sourcepos->_sons.push_back(techcommnode); meshnode->_sons.push_back(sourcepos); //CHANGE THIS PIECE OF CODE! bool normalmask = bool((mask & vcg::tri::io::Mask::IOM_FACENORMAL) || (mask & vcg::tri::io::Mask::IOM_WEDGNORMAL) || (mask & vcg::tri::io::Mask::IOM_VERTNORMAL)); if (normalmask) { XNode* sourcenormal = new XNode(new Tags::SourceTag(shape+"-lib-normals","normal")); //we export only triangular face XLeaf* floatnormarr = new XLeaf(new Tags::FloatArrayTag(shape+"-lib-normals-array",m.face.size() * return_component_number,m,Tags::FloatArrayTag::FACENORMAL,return_component_number)); XNode* techcommnormnode = new XNode(new Tags::TechniqueCommonTag()); XNode* accessornormnode = new XNode(new Tags::AccessorTag(m.face.size(),shape+"-lib-normals-array",return_component_number)); //I have to make up the following piece of code XNode* paramnormx = new XNode(new Tags::ParamTag("X","float")); XNode* paramnormy = new XNode(new Tags::ParamTag("Y","float")); XNode* paramnormz = new XNode(new Tags::ParamTag("Z","float")); sourcenormal->_sons.push_back(floatnormarr); accessornormnode->_sons.push_back(paramnormx); accessornormnode->_sons.push_back(paramnormy); accessornormnode->_sons.push_back(paramnormz); techcommnormnode->_sons.push_back(accessornormnode); sourcenormal->_sons.push_back(techcommnormnode); meshnode->_sons.push_back(sourcenormal); } bool texmask = bool(mask & vcg::tri::io::Mask::IOM_WEDGTEXCOORD); if (texmask) { XNode* sourcewedge = new XNode(new Tags::SourceTag(shape+"-lib-map","map")); return_component_number = CoordNumber::coord(); //we export only triangular face XLeaf* floatwedgearr = new XLeaf(new Tags::FloatArrayTag(shape+"-lib-map-array",m.face.size() * return_component_number * edgefacenum,m,Tags::FloatArrayTag::WEDGETEXCOORD,return_component_number)); XNode* techcommwedgenode = new XNode(new Tags::TechniqueCommonTag()); XNode* accessorwedgenode = new XNode(new Tags::AccessorTag(m.face.size() * edgefacenum,shape+"-lib-map-array",return_component_number)); //I have to make up the following piece of code XNode* paramwedgeu = new XNode(new Tags::ParamTag("U","float")); XNode* paramwedgev = new XNode(new Tags::ParamTag("V","float")); sourcewedge->_sons.push_back(floatwedgearr); accessorwedgenode->_sons.push_back(paramwedgeu); accessorwedgenode->_sons.push_back(paramwedgev); techcommwedgenode->_sons.push_back(accessorwedgenode); sourcewedge->_sons.push_back(techcommwedgenode); meshnode->_sons.push_back(sourcewedge); } XNode* vertnode = new XNode(new Tags::VerticesTag(shape+"-lib-vertices")); XNode* inputposnode = new XNode(new Tags::InputTag("POSITION",shape+"-lib-positions")); vertnode->_sons.push_back(inputposnode); meshnode->_sons.push_back(vertnode); XNode* trianglesnode = NULL; //if ((m.textures.size() == 0) || (!texmask)) //{ // //there isn't any texture file // trianglesnode = new XNode(new Tags::TrianglesTag(m.face.size())); //} //else //{ // std::vector> _mytripatches(m.textures.size()); // if ((texmask) && (m.textures.size() > 1)) // { // //there are many textures files - I have to split the mesh in triangular patches that share the same texture's file. // for(MESHMODELTYPE::ConstFaceIterator itf = m.face.begin();itf != m.face.end();++itf) // { // // } // trianglesnode = new XNode(new Tags::TrianglesTag(m.face.size(),"instancematerial")); //} QVector > mytripatches; if ((texmask) && (m.textures.size() != 0)) splitMeshInTexturedPatches(m,mytripatches); QVector >::iterator itp = mytripatches.begin(); int indmat = 0; do { if ((m.textures.size() == 0) || (!texmask)) { //there isn't any texture file trianglesnode = new XNode(new Tags::TrianglesTag(m.face.size())); } else trianglesnode = new XNode(new Tags::TrianglesTag(mytripatches[indmat].size(),"material" + QString::number(indmat))); XNode* inputtrinode = new XNode(new Tags::InputTag(0,"VERTEX",shape+"-lib-vertices")); trianglesnode->_sons.push_back(inputtrinode); if (normalmask) { XNode* inputnormnode = new XNode(new Tags::InputTag(1,"NORMAL",shape+"-lib-normals")); trianglesnode->_sons.push_back(inputnormnode); } if (texmask) { XNode* inputwedgenode = new XNode(new Tags::InputTag(2,"TEXCOORD",shape+"-lib-map")); trianglesnode->_sons.push_back(inputwedgenode); } XLeaf* polyleaf = NULL; if (itp == mytripatches.end()) polyleaf = new XLeaf(new Tags::PTag(m,edgefacenum,normalmask,texmask)); else polyleaf = new XLeaf(new Tags::PTag(m,edgefacenum,(*itp),normalmask,texmask)); trianglesnode->_sons.push_back(polyleaf); meshnode->_sons.push_back(trianglesnode); ++indmat; if (itp != mytripatches.end()) ++itp; }while(itp != mytripatches.end()); connectHierarchyNode(libgeo,geometrynode,meshnode); root->_sons.push_back(libgeo); XNode* libvisualnode = new XNode(new Tags::LibraryVisualScenesTag()); XNode* visualscenenode = new XNode(new Tags::VisualSceneTag("VisualSceneNode","VisualScene")); XNode* nodenode = new XNode(new Tags::NodeTag("node","node")); XNode* instgeonode = new XNode(new Tags::InstanceGeometryTag(shape+"-lib")); XNode* bindnode = new XNode(new Tags::BindMaterialTag()); XNode* techcommmatnode = new XNode(new Tags::TechniqueCommonTag()); for(unsigned int ii = 0; ii < m.textures.size(); ++ii) { XNode* instmatnode = new XNode(new Tags::InstanceMaterialTag("material" + QString::number(ii),"material" + QString::number(ii))); XNode* bindvertnode = new XNode(new Tags::BindVertexInputTag("UVSET0","TEXCOORD","0")); connectHierarchyNode(techcommmatnode,instmatnode,bindvertnode); } connectHierarchyNode(visualscenenode,nodenode,instgeonode,bindnode,techcommmatnode); libvisualnode->_sons.push_back(visualscenenode); root->_sons.push_back(libvisualnode); XNode* scenenode = new XNode(new Tags::SceneTag()); XNode* instvisualscenenode = new XNode(new Tags::InstanceVisualSceneTag("VisualSceneNode")); scenenode->_sons.push_back(instvisualscenenode); root->_sons.push_back(scenenode); return new XMLDocument(root); } static void destroyColladaDocument(XMLDocument* doc) { delete doc; } //template //static int importColladaDocument(const QDomDocument& doc,MESHMODELTYPE& m,const int mask) //{ // QDomElement root = doc.toElement(); // if (root.isNull()) // return UtilDAE::E_BAD_CONVERTION_FROM_NODE_TO_ELEMENT; // QDomNodeList lst = root.elementsByTagName("COLLADA"); // int err = UtilDAE::checkOccurencies(lst,UtilDAE::ONE); // if ( // return vcg::tri::io::UtilDAE::E_NOERROR; //} }; } //Collada #endifqutemol/vcg/wrap/dae/util_dae.h0000444000175000017500000003377710753017270015065 0ustar mbamba#ifndef __VCGLIB_UTILDAE #define __VCGLIB_UTILDAE #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace vcg { namespace tri { namespace io { class InfoDAE { public: InfoDAE() { doc = NULL; } ~InfoDAE() { delete doc; } QDomDocument* doc; }; class AdditionalInfoDAE : public AdditionalInfo { public: vcg::tri::io::InfoDAE* dae; std::vector texturefile; AdditionalInfoDAE() :AdditionalInfo() { mask = 0; numvert = 0; numface = 0; } ~AdditionalInfoDAE() { delete dae; texturefile.clear(); } }; class UtilDAE { public: enum DAEError { E_NOERROR, // 0 E_CANTOPEN, // 1 E_NOGEOMETRYLIBRARY, // 2 E_NOMESH, // 3 E_NOVERTEXPOSITION, // 4 E_NO3DVERTEXPOSITION, // 5 E_NO3DSCENE, // 6 E_INCOMPATIBLECOLLADA141FORMAT, //7 E_UNREFERENCEBLEDCOLLADAATTRIBUTE, // 8 E_NOPOLYGONALMESH, //9 E_CANTSAVE //10 }; template class MyPolygon { public: typedef VERTEX_TYPE BaseVertexType; int _nvert; std::vector _pv; std::vector< vcg::TexCoord2 > _txc; MyPolygon(int n) :_nvert(n),_pv(_nvert),_txc(_nvert) { } }; template class PolygonalMesh { public: typedef POLYGONAL_TYPE FaceType; enum PERWEDGEATTRIBUTETYPE {NONE = 0,NORMAL = 1,MULTITEXTURECOORD = 2,MULTICOLOR = 4}; typedef typename FaceType::BaseVertexType VertexType; typedef VertexType* VertexPointer; typedef typename std::vector::iterator VertexIterator; typedef typename std::vector::iterator PolygonIterator; vcg::Box3 bbox; std::vector vert; std::vector _pols; void generatePointsVector(std::vector >& v) { for(typename PolygonalMesh::PolygonIterator itp = _pols.begin();itp != _pols.end();++itp) { v.push_back(std::vector()); for(typename std::vector::iterator itv = itp->_pv.begin();itv != itp->_pv.end();++itv) { v[v.size() - 1].push_back((*itv)->P()); } } } void usePerWedgeAttributes(PERWEDGEATTRIBUTETYPE att,const unsigned int multitexture = 1,const unsigned int multicolor = 1) { if (att != NONE) { for(PolygonIterator itp = _pols.begin();itp != _pols.end();++itp) { if (att & MULTICOLOR) itp->usePerWedgeColor(multicolor); if (att & MULTITEXTURECOORD) itp->usePerWedgeMultiTexture(multitexture); if (att & NORMAL) itp->usePerWedgeNormal(); } } } template void triangulate(TRIMESH& mesh) { std::vector > pl; mesh.vert.resize(vert.size()); int multicoor = 0; //PolygonalMesh's points has been copied in TriangularMesh for(size_t jj = 0;jj < mesh.vert.size();++jj) mesh.vert[jj].P() = vert[jj].P(); bool texen = mesh.face.IsWedgeTexEnabled(); unsigned int totaltri = 0; for(size_t ii = 0;ii < _pols.size();++ii) totaltri += _pols[ii]._nvert - 2; mesh.face.resize(totaltri); //transform the polygonal mesh in a vector> generatePointsVector(pl); int trioff = 0; //foreach Polygon for(size_t ii = 0;ii < pl.size();++ii) { std::vector tx; std::vector > pl2(1); pl2[0] = pl[ii]; vcg::glu_tesselator::tesselate(pl2,tx); size_t ntri = tx.size() / 3; assert(tx.size() % 3 == 0); int polvert = 0; //foreach triangle for(size_t tr = 0;tr < ntri;++tr) { //typename TRIMESH::FaceType& f = mesh.face[tr]; //typename TRIMESH::FaceType& f = mesh.face[tr]; for(unsigned int tt = 0;tt < 3; ++tt) { mesh.face[trioff + tr].V(tt) = &(mesh.vert[_pols[ii]._pv[tx[3 * tr + tt]] - &(vert[0])]); //vcg::Point3f ppp = mesh.face[tr].V(tt)->P(); if (texen) { /* f.WT(multicoor).U() = _pols[ii]._txc[polvert].U(); f.WT(multicoor).V() = _pols[ii]._txc[polvert].V(); f.WT(multicoor).N() = _pols[ii]._txc[polvert].N();*/ } polvert = (polvert + 1) % _pols[ii]._nvert; } //mesh.face.push_back(f); } trioff += ntri; } assert(trioff == totaltri); } }; static const char *ErrorMsg(int error) { static const char * dae_error_msg[] = { "No errors", "Can't open file", "File without a geometry library", "There isn't mesh in file", "The meshes in file haven't the vertex position attribute", "The importer assumes that the OpenMeshType uses a 3D point for the vertex position", "There isn't any scene in Collada file", "The input file is not compatible with COLLADA 1.41 standard format", "Collada file is trying to referece an attribute that is not in the file", "This version of Collada Importer support only triangular and polygonal mesh file" }; if(error>9 || error<0) return "Unknown error"; else return dae_error_msg[error]; }; protected: inline static void referenceToANodeAttribute(const QDomNode n,const QString& attr,QString& url_st) { url_st = n.toElement().attribute(attr); int sz = url_st.size() - 1; url_st = url_st.right(sz); assert(url_st.size() != 0); } inline static QDomNode findNodeBySpecificAttributeValue(const QDomNodeList& ndl,const QString& attrname,const QString& attrvalue) { int ndl_size = ndl.size(); int ind = 0; while(ind < ndl_size) { QString st = ndl.at(ind).toElement().attribute(attrname); if (st == attrvalue) return ndl.at(ind); ++ind; } return QDomNode(); } inline static QDomNode findNodeBySpecificAttributeValue(const QDomNode n,const QString& tag,const QString& attrname,const QString& attrvalue) { return findNodeBySpecificAttributeValue(n.toElement().elementsByTagName(tag),attrname,attrvalue); } inline static QDomNode findNodeBySpecificAttributeValue(const QDomDocument n,const QString& tag,const QString& attrname,const QString& attrvalue) { return findNodeBySpecificAttributeValue(n.elementsByTagName(tag),attrname,attrvalue); } inline static bool isThereTag(const QDomNodeList& list) { return ((list.size() > 0) ? true : false); } inline static bool isThereTag(const QDomNode n,const QString& tagname) { return isThereTag(n.toElement().elementsByTagName(tagname)); } inline static bool isThereTag(const QDomDocument n,const QString& tagname) { return isThereTag(n.elementsByTagName(tagname)); } inline static QDomNode attributeSourcePerSimplex(const QDomNode n,const QDomDocument startpoint,const QString& sem) { QDomNodeList vertattr = n.toElement().elementsByTagName("input"); for(int ind = 0;ind < vertattr.size();++ind) { if (vertattr.at(ind).toElement().attribute("semantic") == sem) { QString url; referenceToANodeAttribute(vertattr.at(ind),"source",url); return findNodeBySpecificAttributeValue(startpoint,"source","id",url); } } return QDomNode(); } inline static void valueStringList(QStringList& res,const QDomNode srcnode,const QString& tag) { QDomNodeList list = srcnode.toElement().elementsByTagName(tag); assert(list.size() == 1); QString nd = list.at(0).firstChild().nodeValue(); res = nd.split(" "); if (res.last() == "") res.removeLast(); } /*inline static bool removeChildNode(QDomNodeList*/ inline static bool removeChildNodeList(QDomNodeList& nodelst,const QString& tag = "", const QString& attribname = "", const QString& attribvalue = "") { for(int jj = 0;jj < nodelst.size();++jj) { removeChildNode(nodelst.at(jj),tag,attribname,attribvalue); } return true; } inline static bool removeChildNode(QDomNode node,const QString& tag = "", const QString& attribname = "", const QString& attribvalue = "") { QDomNodeList clst = node.childNodes(); for(int ii = 0;ii < clst.size();++ii) { QDomNode oldchild = node.childNodes().at(ii); if (tag != "") { if ((attribname != "") && (attribvalue != "")) { if (clst.at(ii).toElement().attribute(attribname) == attribvalue) node.removeChild(oldchild); } else { QString nm = clst.at(ii).nodeName(); if (clst.at(ii).nodeName() == tag) { node.removeChild(oldchild); } } } else node.removeChild(oldchild); } return true; } static void ParseRotationMatrix(vcg::Matrix44f& m,const std::vector& t) { vcg::Matrix44f tmp; tmp.SetIdentity(); for(unsigned int ii = 0;ii < t.size();++ii) { QString rt = t[ii].firstChild().nodeValue(); QStringList rtl = rt.split(" "); if (rtl.last() == "") rtl.removeLast(); assert(rtl.size() == 4); tmp.SetRotate(rtl.at(3).toFloat(),vcg::Point3f(rtl.at(0).toFloat(),rtl.at(1).toFloat(),rtl.at(2).toFloat())); tmp *= tmp; } m = m * tmp; } static void AddTranslation(vcg::Matrix44f& m,const QDomNode t) { QDomNode tr = t.firstChild(); QString coord = tr.nodeValue(); QStringList coordlist = coord.split(" "); if (coordlist.last() == "") coordlist.removeLast(); assert(coordlist.size() == 3); m[0][0] = 1.0f; m[1][1] = 1.0f; m[2][2] = 1.0f; m[3][3] = 1.0f; m[0][3] = coordlist.at(0).toFloat(); m[1][3] = coordlist.at(1).toFloat(); m[2][3] = coordlist.at(2).toFloat(); } static void TransfMatrix(const QDomNode parentnode,const QDomNode presentnode,vcg::Matrix44f& m) { if (presentnode == parentnode) return; else { QDomNode par = presentnode.parentNode(); std::vector rotlist; QDomNode trans; for(int ch = 0;ch < par.childNodes().size();++ch) { if (par.childNodes().at(ch).nodeName() == "rotate") rotlist.push_back(par.childNodes().at(ch)); else if (par.childNodes().at(ch).nodeName() == "translate") { trans = par.childNodes().at(ch); } } vcg::Matrix44f tmp; tmp.SetIdentity(); if (!trans.isNull()) AddTranslation(tmp,trans); ParseRotationMatrix(tmp,rotlist); m = m * tmp; TransfMatrix(parentnode,par,m); } } inline static int findOffSetForASingleSimplex(QDomNode node) { QDomNodeList wedatts = node.toElement().elementsByTagName("input"); int max = 0; if (wedatts.size() == 0) return -1; else { for(int ii = 0;ii < wedatts.size();++ii) { int tmp = wedatts.at(ii).toElement().attribute("offset").toInt(); if (tmp > max) max = tmp; } } return max + 1; } inline static int findStringListAttribute(QStringList& list,const QDomNode node,const QDomNode poly,const QDomDocument startpoint,const char* token) { int offset; if (!node.isNull()) { offset = node.toElement().attribute("offset").toInt(); QDomNode st = attributeSourcePerSimplex(poly,startpoint,token); valueStringList(list,st,"float_array"); } return offset; } inline static QDomNode textureFinder(const QString& textname,const QDomDocument doc) { //visual_scene -> instance_material QDomNodeList vis_scn = doc.elementsByTagName("library_visual_scenes"); if (vis_scn.size() != 1) return QDomNode(); QDomNode symb = findNodeBySpecificAttributeValue(vis_scn.at(0),QString("instance_material"),QString("symbol"),textname); if (symb.isNull()) return QDomNode(); QString tar = symb.toElement().attribute("target"); if (tar.isNull()) return QDomNode(); tar = tar.remove('#'); //library_material -> material -> instance_effect QDomNodeList lib_mat = doc.elementsByTagName("library_materials"); if (lib_mat.size() != 1) return QDomNode(); QDomNode material = findNodeBySpecificAttributeValue(lib_mat.at(0),QString("material"),QString("id"),tar); if (material.isNull()) return QDomNode(); QDomNodeList in_eff = material.toElement().elementsByTagName("instance_effect"); if (vis_scn.size() == 0) return QDomNode(); QString url = in_eff.at(0).toElement().attribute("url"); if ((url.isNull()) || (url == "")) return QDomNode(); url = url.remove('#'); //library_effects -> effect -> instance_effect QDomNodeList lib_eff = doc.elementsByTagName("library_effects"); if (lib_eff.size() != 1) return QDomNode(); QDomNode effect = findNodeBySpecificAttributeValue(lib_eff.at(0),QString("effect"),QString("id"),url); if (effect.isNull()) return QDomNode(); QDomNodeList init_from = effect.toElement().elementsByTagName("init_from"); if (init_from.size() == 0) return QDomNode(); QString img_id = init_from.at(0).toElement().text(); if ((img_id.isNull()) || (img_id == "")) return QDomNode(); //library_images -> image QDomNodeList lib_img = doc.elementsByTagName("library_images"); if (lib_img.size() != 1) return QDomNode(); QDomNode img = findNodeBySpecificAttributeValue(lib_img.at(0),QString("image"),QString("id"),img_id); if (img.isNull()) return QDomNode(); return img; } static int indexTextureByImgNode(const QDomDocument doc,const QDomNode node) { QDomNodeList libim = doc.elementsByTagName(QString("library_images")); if (libim.size() != 1) return -1; QDomNodeList imgs = libim.at(0).toElement().elementsByTagName("image"); int ii = 0; bool found = false; while((ii < imgs.size()) && (!found)) { if (imgs.at(ii) == node) found = true; else ++ii; } if (found) return ii; else return -1; } struct WedgeAttribute { QDomNode wnsrc; QStringList wn; int offnm; QDomNode wtsrc; QStringList wt; int stride; int offtx; QDomNode wcsrc; QStringList wc; int offcl; }; }; } } } #endif qutemol/vcg/wrap/dae/xmldocumentmanaging.h0000444000175000017500000000663510750033134017323 0ustar mbamba#ifndef _XML_DOCUMENT_MANAGING_H #define _XML_DOCUMENT_MANAGING_H #include #include #include #include #include #include #include class XMLTag { public: typedef std::pair TagAttribute; typedef QVector TagAttributes; QString _tagname; TagAttributes _attributes; XMLTag(const QString& tagname = QString(),const TagAttributes& attr = TagAttributes()) :_tagname(tagname),_attributes(attr) { } virtual ~XMLTag() { } }; class XMLLeafTag : public XMLTag { public: QVector _text; XMLLeafTag(const QString& tagname = QString(),const QVector& text = QVector()) :XMLTag(tagname),_text(text) { } virtual ~XMLLeafTag() { } }; class XMLDocumentWriter; class Visitor; class XMLNode { public: XMLNode(XMLTag* tag); virtual ~XMLNode(); virtual void applyProcedure(Visitor& v) = 0; XMLTag* _tag; }; class XMLInteriorNode : public XMLNode { public: XMLInteriorNode(XMLTag* tag); XMLNode* son(int ii); QVector< XMLNode* > sons(); void applyProcedure(Visitor& v); ~XMLInteriorNode(); QVector< XMLNode* > _sons; }; class XMLLeafNode : public XMLNode { public: XMLLeafNode(XMLLeafTag* leaftag); void applyProcedure(Visitor& v); virtual ~XMLLeafNode(); }; class XMLDocument { public: XMLDocument(XMLInteriorNode* root) :_root(root) { } ~XMLDocument() { delete (_root); } XMLInteriorNode* _root; }; class Visitor { public: virtual void operator()(XMLLeafNode& leaf) = 0; virtual void operator()(XMLInteriorNode& intnode) = 0; }; class XMLDocumentWriter : public Visitor { private: QXmlStreamWriter _stream; QFile _file; bool _error; void writeText(XMLLeafNode& node) { XMLLeafTag* leaftag = static_cast(node._tag); for(QVector::iterator it = leaftag->_text.begin();it != leaftag->_text.end();++it) { QString tmp = ""; if (it != leaftag->_text.begin()) tmp = QString(" "); _stream.writeCharacters(tmp + *it); } } void writeAttributes(XMLNode& node) { QXmlStreamAttributes attr; for(XMLTag::TagAttributes::iterator it = node._tag->_attributes.begin();it != node._tag->_attributes.end();++it) attr.append(it->first,it->second); _stream.writeAttributes(attr); } void recursiveStep(XMLInteriorNode& intnode) { QVector< XMLNode* > sons = intnode.sons(); for(QVector< XMLNode* >::iterator its = sons.begin();its != sons.end();++its) (*its)->applyProcedure(*this); } public: void operator()(XMLLeafNode& node) { _stream.writeStartElement(node._tag->_tagname); writeAttributes(node); writeText(node); _stream.writeEndElement(); } void operator()(XMLInteriorNode& intnode) { _stream.writeStartElement(intnode._tag->_tagname); writeAttributes(intnode); recursiveStep(intnode); _stream.writeEndElement(); } void operator()(XMLDocument& doc) { _stream.writeStartDocument(); operator()(*(doc._root)); _stream.writeEndDocument(); } void write(XMLDocument& doc) { (*this)(doc); } bool isReliable() const { return !_error; } XMLDocumentWriter(const char* filename,const bool autoformatting = true) :_stream(),_file(filename),_error(false) { if (!_file.open(QIODevice::WriteOnly | QIODevice::Text)) _error = true; _stream.setDevice(&_file); _stream.setAutoFormatting(autoformatting); } ~XMLDocumentWriter() { _file.close(); } }; #endifqutemol/vcg/wrap/dae/xmldocumentmanaging.cpp0000444000175000017500000000134710750033134017651 0ustar mbamba#include #include XMLNode::XMLNode(XMLTag* tag) :_tag(tag) { } XMLNode::~XMLNode() { delete _tag; } XMLLeafNode::XMLLeafNode(XMLLeafTag* leaftag) :XMLNode(leaftag) { } XMLLeafNode::~XMLLeafNode() { } void XMLLeafNode::applyProcedure(Visitor& v) { v(*this); } XMLInteriorNode::XMLInteriorNode(XMLTag* tag) :XMLNode(tag) { } XMLNode* XMLInteriorNode::son(int ii) { assert((ii > 0) && (ii < _sons.size())); return _sons[ii]; } QVector< XMLNode* > XMLInteriorNode::sons() { return _sons; } XMLInteriorNode::~XMLInteriorNode() { for(QVector< XMLNode* >::iterator it = _sons.begin();it != _sons.end();++it) delete (*it); } void XMLInteriorNode::applyProcedure(Visitor& v) { v(*this); }qutemol/vcg/wrap/io_edgemesh/0000755000175000017500000000000011633404241014622 5ustar mbambaqutemol/vcg/wrap/io_edgemesh/export_svg.h0000444000175000017500000003722310776071230017205 0ustar mbamba/**************************************************************************** * VCGLib o o * * Visual and Computer Graphics Library o o * * _ O _ * * Copyright(C) 2006 \/)\/ * * Visual Computing Lab /\/| * * ISTI - Italian National Research Council | * * \ * * All rights reserved. * * * * 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. * * * * 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 (http://www.gnu.org/licenses/gpl.txt) * * for more details. * * * ****************************************************************************/ /**************************************************************************** History $Log: export_svg.h,v $ Revision 1.12 2008/04/06 06:50:00 cignoni added missing namespaces Revision 1.11 2007/07/12 11:02:06 andrenucci Scale in SingleFile mode changed, it have to be calcolated before draw. Revision 1.10 2007/07/10 07:48:41 cignoni changed a template >> into > > Revision 1.9 2007/07/10 06:58:31 cignoni added a missing typename Revision 1.8 2007/07/09 15:36:40 andrenucci fix bug with exporting of translate plans Revision 1.7 2007/06/13 09:17:14 andrenucci Fix problem with scale Revision 1.5 2007/05/29 10:09:29 cignoni Added a const (and reformatted) Revision 1.4 2007/05/21 13:22:40 cignoni Corrected gcc compiling issues Revision 1.3 2006/02/16 15:16:51 corsini Add reference plane support Revision 1.2 2006/02/15 15:40:06 corsini Decouple SVG properties and exporter for simmetry with the other exporter Revision 1.1 2006/02/13 16:18:09 corsini first working version ****************************************************************************/ #ifndef __VCG_LIB_EXPORTER_SVG #define __VCG_LIB_EXPORTER_SVG namespace vcg { namespace edge { namespace io { /** * SVG Properties. * * Support class to set the properties of the SVG exporter. */ class SVGProperties { // definitions public: //! Stroke colors. enum StrokeColor { BLACK, SILVER, GRAY, WHITE, MAROON, RED, PURPLE, FUCHSIA, GREEN, LIME, OLIVE, YELLOW, NAVY, BLUE, TEAL, AQUA }; //! Stroke linecap types. enum StrokeLineCap { BUTT, ROUND, SQUARE }; static const int DEFAULT_LINE_WIDTH=2; //in single-file export make the grid of sessiones int numCol; int numRow; // private data members private: // Line width. int lwidth; // Stroke color (see StrokeColor). std::string stroke_color; // Stroke linecap (see StrokeLineCap). std::string stroke_linecap; // Plane where to project the edge mesh. Plane3d proj; // Scale of rdrawing respect coordinates of mesh float scale; // Dimension of the drawing square Point2d ViewBox; int width,height; //Express in cm // Position of the drawing square Point2d position; //Text details bool showDetails; //Starting offset float Xmin, Ymin; Point2f* minPos; Point2f* maxPos; // construction public: SVGProperties() { lwidth = DEFAULT_LINE_WIDTH; const char * DEFAULT_LINE_COLOR = "black"; const char * DEFAULT_LINE_CAP= "round"; stroke_color = DEFAULT_LINE_COLOR; stroke_linecap = DEFAULT_LINE_CAP; // default projection plane (XZ plane) Point3d n(0.0, 1.0, 0.0); proj.SetDirection(n); proj.SetOffset(0.0); scale=0; //scale=0 it means expanded to the boards of the canvas ViewBox=Point2d(1000, 1000); position=Point2d(0, 0); width=10; //width of the windows height=10; //height of the windows showDetails=true; Xmin=0; Ymin=0; minPos= new Point2f(0,0); maxPos= new Point2f(0,0); } // public methods public: //! Set the line width. void setLineWidth(int width) { lwidth = width; } //! Set the stroke color. void setColor(enum StrokeColor color) { switch (color) { case BLACK : stroke_color = "black"; break; case SILVER : stroke_color = "silver"; break; case GRAY : stroke_color = "gray"; break; case WHITE : stroke_color = "white"; break; case MAROON : stroke_color = "maroon"; break; case RED : stroke_color = "red"; break; case PURPLE : stroke_color = "purple"; break; case FUCHSIA: stroke_color = "fuchsia"; break; case GREEN : stroke_color = "green"; break; case OLIVE : stroke_color = "olive"; break; case LIME : stroke_color = "lime"; break; case NAVY : stroke_color = "navy"; break; case TEAL : stroke_color = "teal"; break; case AQUA : stroke_color = "aqua"; break; default: assert(0); } } //! Set the line cap style. void setLineCap(enum StrokeLineCap linecap) { if (linecap == BUTT) stroke_linecap = "butt"; else if (linecap == ROUND) stroke_linecap = "round"; else if (linecap == SQUARE) stroke_linecap = "square"; } void setPlane(double distance, const Point3d &direction) { proj.SetDirection(direction); proj.SetOffset(distance); } void setScale(float x){ scale=x; } //Define the scale between 2d coordinate and mesh void setViewBox(Point2d x) { ViewBox=x; }//Define the dimension of the square void setPosition(Point2d x) { position=x;}//Define the starting position of the canvas void setTextDetails(bool x){showDetails=x;} void setDimension(int width, int height){ this->width=width; this->height=height;} // accessors public: int lineWidth(){return lwidth;} const char * lineColor(){return stroke_color.c_str();} const char * lineCapStyle(){return stroke_linecap.c_str();} const Plane3d * projPlane(){return &proj;} float getScale(){return scale;} Point2d getViewBox(){return ViewBox;} Point2d getPosition(){return position;} int getWidth(){return width;} bool showTextDetails(){return showDetails;} int getHeight(){return height;} void setMinPoint(Point2f* p){ minPos = p; } void setMaxPoint(Point2f* p){ maxPos = p; } Point2f* getminPoint(){return (minPos);} Point2f* getmaxPoint(){return (maxPos);} }; /** * SVG exporter. * * This exporter save a mesh of EdgeMesh type in the SVG format. * Most of the features of the SVG format are not supported. * The given EdgeMesh is saved as a set lines. The properties * of the SVG export can be set through the SVGProp class. */ template class ExporterSVG { public: //! Save with the default SVG properties. static bool Save(EdgeMeshType *mp, const char *filename) { SVGProperties properties; return Save(mp, filename, properties); } static bool Save(std::vector *vp, const char *filename, SVGProperties & pro){ //Function that export a vector of EdgeMesh in an unic single SVG file. FILE * o = fopen(filename,"w"); if (o==NULL) return false; int num = (*vp).size(); //number of square to draw WriteXmlHead(o,pro.getWidth(),pro.getHeight(),pro.getViewBox(),Point2d(0,0)); float scale= pro.getScale(); typename std::vector::iterator it; int i=0; Point2f pmin(100000000.0f, 100000000.0f); Point2f pmax(-10000000.0f, -10000000.0f); for(it=(*vp).begin(); it!=(*vp).end(); it++){ EdgeMeshType* ed; ed=(*it); Save(ed,o,pro, -2); Point2f* pmi=pro.getminPoint(); Point2f* pma=pro.getmaxPoint(); pmin[0]=min(pmin[0], pmi->X()); pmin[1]=min(pmin[1], pmi->Y()); pmax[0]=max(pmax[0], pma->X()); pmax[1]=max(pmax[1], pma->Y()); } float maxEdge=std::max(pmax[0]-pmin[0], pmax[1]-pmin[1]); float scl = (pro.getViewBox().V(0)/pro.numCol) /maxEdge ; pro.setScale(scl); pro.setMinPoint(new Point2f(pmin[0],pmin[1])); pro.setMaxPoint(new Point2f(pmax[0],pmax[1])); for(it=(*vp).begin(); it!=(*vp).end(); it++){ EdgeMeshType* ed; ed=(*it); pro.setPosition(Point2d((pro.getViewBox().V(0)/pro.numCol)*i,40)); int x=pro.getViewBox().V(0); int y=pro.getViewBox().V(1); /* fprintf(o, " \n",x/pro.numCol,y, (x/pro.numCol)*i, 40); */ Save(ed,o,pro, i); if(pro.showTextDetails()){ fprintf(o,"\n",(x/pro.numCol)*i); fprintf(o,"Slice num:%d \n", i);} i++; } fprintf(o, ""); fclose(o); return true; } //! Save with the given SVG properties. static bool Save(EdgeMeshType *mp, const char *filename, SVGProperties & props ) { FILE * o = fopen(filename,"w"); if (o==NULL) return false; WriteXmlHead(o, props.getWidth(),props.getHeight(), props.getViewBox(), props.getPosition()); props.setPosition(Point2d(0,40)); Save(mp, o, props, -1); fprintf(o, ""); // final xml tags fclose(o); return true; } static void Save(EdgeMeshType *mp, FILE* o, SVGProperties props, int numSlice) { bool preCal=false; if(numSlice==-2) preCal=true; // build vector basis (n, v1, v2) Point3d p1(0.0,0.0,0.0); Point3d p2(1.0,0.0,0.0); Point3d p2less(-1.0,0.0,0.0); Point3d d = props.projPlane()->Direction() - p2; Point3d dless = props.projPlane()->Direction() - p2less; Point3d v1; if ((d.Norm() < 0.5)||(dless.Norm() <0.5)) v1 = Point3d(0.0,0.0,1.0) - p1; else v1 = p2 - p1; v1.Normalize(); Point3d v2 = v1 ^ props.projPlane()->Direction(); //Global points std::vector< std::vector >* glb; std::vector pts; pts.clear(); Point2f pmin(100000000.0f, 100000000.0f); Point2f pmax(-100000000.0f, -100000000.0f); Point3d bbMin; typename EdgeMeshType::EdgeIterator i; for (i = mp->edges.begin(); i != mp->edges.end(); ++i) { Point3 p1; Point3 p2; p1 = (*i).V(0)->P(); p2 = (*i).V(1)->P(); Point3d p1d(p1[0], p1[1], p1[2]); Point3d p2d(p2[0], p2[1], p2[2]); // Project the line on the reference plane Point3d p1proj = props.projPlane()->Projection(p1d); Point3d p2proj = props.projPlane()->Projection(p2d); // Convert the 3D coordinates of the line to the uv coordinates of the plane Point2f pt1(static_cast(p1proj * v1), static_cast(p1proj * v2)); Point2f pt2(static_cast(p2proj * v1), static_cast(p2proj * v2)); pts.push_back(pt1); pts.push_back(pt2); pmin[0]=math::Min(math::Min(pt1[0],pmin[0]), pt2[0]); pmin[1]=math::Min(math::Min(pt1[1],pmin[1]), pt2[1]); pmax[0]=math::Max(math::Max(pt1[0],pmax[0]), pt2[0]); pmax[1]=math::Max(math::Max(pt1[1],pmax[1]), pt2[1]); } //Point2f bbp(static_cast(bbMin * v1), static_cast(bbMin * v2)); if(!preCal){ float scale=props.getScale(); // line settings Point2d pos=props.getPosition(); fprintf(o, " \n", props.lineColor(), props.lineCapStyle()); float maxEdges= math::Max((pmax[0]-pmin[0]), (pmax[1]-pmin[1])); if (numSlice==0) Draw_proportions_scale(o,maxEdges, props); fprintf(o, "\n", numSlice ); int x=props.getViewBox().V(0); int y=props.getViewBox().V(1); if(numSlice>=0) fprintf(o, " \n",x/props.numCol,y, (x/props.numCol)*numSlice, 40); else fprintf(o, " \n",x/props.numCol,y, 0, 40); std::vector::iterator itPoints; for(itPoints = pts.begin(); itPoints != pts.end(); ++itPoints) { Point2f p1 = *itPoints; ++itPoints; Point2f p2 = *itPoints; if(numSlice==-1){ fprintf(o, " \n"); } else{ fprintf(o, " X()) * scale), pos.Y()+((p1[1]-props.getminPoint()->Y()) * scale), pos.X()+((p2[0]-props.getminPoint()->X()) * scale), pos.Y()+((p2[1]-props.getminPoint()->Y()) * scale )); fprintf(o, " stroke-width = \"%d\" ",props.lineWidth()); fprintf(o, "/>\n");} } fprintf(o, ""); fprintf(o, " \n"); } else{ Point2f* pmi=props.getminPoint(); Point2f* pma=props.getmaxPoint(); pmi->X()=pmin[0]; pmi->Y()=pmin[1]; pma->X()=pmax[0]; pma->Y()=pmax[1]; props.setMinPoint(pmi); props.setMaxPoint(pma); } } private: static void Draw_proportions_scale(FILE *o, float maxEdge,SVGProperties & prop){ if(prop.showTextDetails()){ int num_order=log10(maxEdge); int pox= pow(10.0, num_order); int assX=prop.getViewBox()[0]; int assY=prop.getViewBox()[1]; int nullAss=0; int OffsetXAs=50; float comput= OffsetXAs+(pox*prop.getScale()); fprintf(o, " \n"); fprintf(o,"",(nullAss+OffsetXAs), (assY+80)); fprintf(o,"%d px -- Scale %f : 1 ", pox ,prop.getScale()); } } static void WriteXmlHead(FILE *o,int width, int height, Point2d viewBox, Point2d position){ int Vx=viewBox[0]; int Vy=viewBox[1]; // initial xml tags fprintf(o, "\n"); fprintf(o, "\n"); fprintf(o, " \n"); fprintf(o, " \n"); fprintf(o, " \n"); fprintf(o, " \n"); fprintf(o, " \n"); fprintf(o, " image/svg+xml \n"); fprintf(o, " \n"); fprintf(o, " \n"); fprintf(o, " \n"); fprintf(o, " \n"); } }; }; // namespace io }; // namespace edge }; // namespace vcg #endif // __VCG_LIB_EXPORTER_SVG �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������qutemol/vcg/wrap/io_edgemesh/export_dxf.h�����������������������������������������������������������0000444�0001750�0001750�00000007016�10200707375�017162� 0����������������������������������������������������������������������������������������������������ustar �mba�����������������������������mba��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������/**************************************************************************** * VCGLib o o * * Visual and Computer Graphics Library o o * * _ O _ * * Copyright(C) 2004 \/)\/ * * Visual Computing Lab /\/| * * ISTI - Italian National Research Council | * * \ * * All rights reserved. * * * * 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. * * * * 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 (http://www.gnu.org/licenses/gpl.txt) * * for more details. * * * ****************************************************************************/ /**************************************************************************** History $Log: export_dxf.h,v $ Revision 1.5 2005/02/04 15:04:29 spinelli corretto nome costruttore.... Revision 1.4 2005/02/03 11:22:34 spinelli ricorretti i metodi save per rendere compatibile il formato dxf con il formato di autocad specificato nel dxf reference 2005 Revision 1.3 2004/07/02 17:08:12 ganovelli created Revision 1.2 2004/06/10 15:15:16 ganovelli changes to comply dxf specs Revision 1.1 2004/05/27 13:24:08 ganovelli export_dxf created ****************************************************************************/ #ifndef __VCG_LIB_EXPORTER_DXF #define __VCG_LIB_EXPORTER_DXF namespace vcg { namespace edge { namespace io { template class ExporterDXF { public: ExporterDXF(void){} static bool Save(EdgeMeshType *mp, const char * filename) { FILE * o = fopen(filename,"w"); if(o==NULL) return false; fprintf(o,"0\n"); fprintf(o,"SECTION\n"); fprintf(o,"2\n"); fprintf(o,"ENTITIES\n"); Save(mp,o); fprintf(o,"0\n"); fprintf(o,"ENDSEC\n"); fprintf(o,"0\n"); fprintf(o,"EOF\n"); fclose(o); return true; } static void Save(EdgeMeshType *mp, FILE* o ) { EdgeMeshType::EdgeIterator i; for(i=mp->edges.begin(); i!=mp->edges.end();++i) { Point3f p1 = (*i).V(0)->P(); Point3f p2 = (*i).V(1)->P(); fprintf(o,"0\n"); fprintf(o,"LINE\n"); fprintf(o,"8\n"); fprintf(o,"0\n"); fprintf(o,"10\n"); fprintf(o,"%f\n", p1[0]); //X fprintf(o,"20\n"); fprintf(o,"%f\n", p1[1]); //Y fprintf(o,"30\n"); fprintf(o,"%f\n", p1[2]); //Z fprintf(o,"11\n"); fprintf(o,"%f\n", p2[0]); //X fprintf(o,"21\n"); fprintf(o,"%f\n", p2[1]); //Y fprintf(o,"31\n"); fprintf(o,"%f\n", p2[2]); //Z } } }; }; }; }; #endif ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������qutemol/vcg/wrap/mt/��������������������������������������������������������������������������������0000755�0001750�0001750�00000000000�11633404241�012772� 5����������������������������������������������������������������������������������������������������ustar �mba�����������������������������mba��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������qutemol/vcg/wrap/mt/mt.h����������������������������������������������������������������������������0000444�0001750�0001750�00000023025�10032777025�013570� 0����������������������������������������������������������������������������������������������������ustar �mba�����������������������������mba��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������/**************************************************************************** * VCGLib o o * * Visual and Computer Graphics Library o o * * _ O _ * * Copyright(C) 2004 \/)\/ * * Visual Computing Lab /\/| * * ISTI - Italian National Research Council | * * \ * * All rights reserved. * * * * 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. * * * * 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 (http://www.gnu.org/licenses/gpl.txt) * * for more details. * * * ****************************************************************************/ /**************************************************************************** History $Log: mt.h,v $ Revision 1.1 2004/04/01 11:33:41 ponchio Untested first draft. ****************************************************************************/ #ifndef VCG_MT_H #define VCG_MT_H #include #include #include #include #include #include namespace vcg { /** \addtogroup mt */ /*@{*/ /** The templated class for representing a mt structure. The class is templated over the Cell class which MUST implement this functions: float Error(); float Distance(Cell &c, Point3f &p); see mt_file.h for an example. */ template class MT { public: typedef C Cell; private: class Frag:public std::vector {}; struct Node { std::vector in; std::vector out; std::vector frags; float error; bool visited; }; std::vector nodes; public: /** Update class for defining the history. Notice how the Update class holds pointers. You are responsible of holding the Cell structure and rebuild the structure if the pointers change. */ class Update { public: std::vector erased; std::vector created; }; ///build mt strucure from a sequence of updates. void Load(std::vector &updates) { //The last update erases everything. assert(updates[0].erased.size() == 0); //maps cell -> node containing it std::map cell_node; nodes.resize(updates.size()); //building fragments and nodes. unsigned int current_node = 0; std::vector::iterator u; for(u = updates.begin(); u != updates.end(); u++) { Node &node = nodes[current_node]; node.error = 0; //created cells belong to this node, we look also for max error. for(unsigned int i = 0; i < (*u).created.size(); i++) { Cell *cell = (*u).created[i]; if(cell->Error() > node.error) node.error = cell->Error(); cell_node[cell] = current_node; } //Every erased cell already belonged to a node. //we record for each node its cells. std::map > node_erased; for(unsigned int i = 0; i < (*u).erased.size(); i++) { Cell *cell = (*u).erased[i]; assert(cell_node.count(cell)); node_erased[cell_node[cell]].push_back(cell); } //for every node with erased cells we build a frag and put the corresponding cells in it. std::map >::iterator e; for(e = node_erased.begin(); e != node_erased.end(); e++) { //Build a new Frag. Frag fr; float max_err = -1; //Fill it with erased cells. std::vector &cells = (*e).second; std::vector::iterator k; for(k = cells.begin(); k != cells.end(); k++) { Cell *cell = (*k); fr.push_back(cell); if(cell->Error() > max_err) max_err = cell->Error(); } //Add the new Frag to the node. unsigned int floor_node = (*e).first; Node &oldnode = nodes[floor_node]; oldnode.frags.push_back(fr); if(node.error < max_err) node.error = max_err; //Update in and out of the nodes. node.in.push_back(&oldnode); oldnode.out.push_back(&node); } current_node++; } } void Clear() { nodes.clear(); } ///error based extraction template void Extract(CONT &selected, float error) { std::vector::iterator n; for(n = nodes.begin(); n != nodes.end(); n++) (*n).visited = false; std::queue qnodo; qnodo.push(&nodes[0]); nodes[0].visited = true; for( ; !qnodo.empty(); qnodo.pop()) { Node &node = *qnodo.front(); std::vector::iterator fragment; std::vector::iterator on; for(on = node.out.begin(), fragment = node.frags.begin(); on != node.out.end(); ++on, ++fragment) { if((*on)->visited) continue; if(error < (*on)->error) { //need to expand this node. qnodo.push(*on); (*on)->visited = 1; } else { vector::iterator cell; for(cell=(*fragment).begin(); cell != (*fragment).end(); ++cell) selected.push_back(*cell); } } } } //custom extraction template void Extract(CONT &selected, POLICY &policy) { std::vector::iterator n; for(n = nodes.begin(); n != nodes.end(); n++) (*n).visited = false; std::queue qnodo; qnodo.push(&nodes[0]); nodes[0].visited = true; for( ; !qnodo.empty(); qnodo.pop()) { Node &node = *qnodo.front(); std::vector::iterator i; std::vector::iterator on; for(i = node.frags.begin(), on = node.out.begin(); i != node.frags.end(); i++, on++) { if((*on)->visited) continue; Frag &frag = (*i); std::vector::iterator cell; for(cell = frag.begin(); cell != frag.end(); cell++) { if(policy.Expand(*cell)) visit(*on, qnodo); } } } Extract(selected); } //extract using a user class which must provides: //bool refineCell(Cell *cell, Frustum &frustum); //void addCell(Cell *cell); //void removeCell(Cell *cell); //template void extract(std::vector &selected, Frustum &frustum, T &error); ///extract using the visited flag in nodes to a STL container of Cell * template void Extract(CONT &selected) { selected.clear(); std::vector::iterator i; for(i = nodes.begin(); i != nodes.end(); i++) { Node &node = *i; if(!node.visited) continue; std::vector::iterator n; std::vector::iterator f; for(n = node.out.begin(), f = node.frags.begin(); n != node.out.end(); n++, f++) { if(!(*n)->visited || (*n)->error == 0) { vector::iterator c; Frag &frag = (*f); for(c = frag.begin(); c != frag.end(); c++) selected.insert(selected.end(), *c); } } } } ///add a node to the queue recursively mantaining coherence. void Visit(Node *node, std::queue &qnode) { std::vector::iterator n; for(n = node->in.begin(); n != node->in.end(); n++) if(!(*n)->visited) visit(*n, qnode); node->visited = true; qnode.push(node); } }; template class FrustumPolicy { public: typedef C Cell; Frustumf frustum; ///target error in screen space (pixels) float error; bool Expand(Cell *cell) { if(cell->Error() == 0) return false; float dist = Distance(*cell, frustum.ViewPoint()); /*Point3f line = frustum.viewPoint() - cell->sphere.center; float dist = line.Norm() - cell->sphere.radius; */ if(dist < 0) return true; dist = pow(dist, 1.2); float res = cell->Error() / (frustum.Resolution()*dist); return res; } }; ///really simple example policy template class DiracPolicy { public: typedef C Cell; Point3f focus; ///max error in object space at distance 0 float error; DiracPolicy(Point3f &f = Point3f(0, 0, 0), float e = 0): focus(f), error(e) {} bool Expand(Cell *cell) { if(cell->Error() == 0) return false; float dist = Distance(*cell, focus); if(dist > 0) return true; return false; } }; }//namespace vcg #endif�����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������qutemol/vcg/wrap/ply/�������������������������������������������������������������������������������0000755�0001750�0001750�00000000000�11633404241�013156� 5����������������������������������������������������������������������������������������������������ustar �mba�����������������������������mba��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������qutemol/vcg/wrap/ply/plylib.h�����������������������������������������������������������������������0000444�0001750�0001750�00000021407�10343707265�014635� 0����������������������������������������������������������������������������������������������������ustar �mba�����������������������������mba��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������/**************************************************************************** * VCGLib o o * * Visual and Computer Graphics Library o o * * _ O _ * * Copyright(C) 2004 \/)\/ * * Visual Computing Lab /\/| * * ISTI - Italian National Research Council | * * \ * * All rights reserved. * * * * 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. * * * * 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 (http://www.gnu.org/licenses/gpl.txt) * * for more details. * * * ****************************************************************************/ /**************************************************************************** Acknowlegments Portions of this file were based on the original code of the Ply library of Greg Turk and on the work of Claudio Rocchini ****************************************************************************/ /**************************************************************************** History $Log: plylib.h,v $ Revision 1.6 2005/12/02 00:00:53 cignoni Moved and corrected interpret_texture_name from plystuff.h to plylib.cpp Revision 1.5 2005/11/26 00:12:25 cignoni added prototype of interpret_texture_name Revision 1.4 2005/11/12 07:07:47 cignoni Changed Offset types to remove warnings Revision 1.3 2005/01/03 10:35:59 cignoni Improved the compatibility for ply format for faces having the list size (e.g. number of vertexes of a face) as a char instead of a uchar. Added a couple of new face descriptors, corrected a bug in error reporting function (and restructured) and translated a few comments. Thanks to Patrick Min for the careful bug reporting Revision 1.2 2004/04/27 13:29:19 turini *** empty log message *** Revision 1.1 2004/03/03 15:00:51 cignoni Initial commit ****************************************************************************/ #ifndef __VCG_PLYLIB #define __VCG_PLYLIB #include #include #include #include namespace vcg { namespace ply { // Data types supported by the ply format enum PlyTypes { T_NOTYPE, T_CHAR, T_SHORT, T_INT, T_UCHAR, T_USHORT, T_UINT, T_FLOAT, T_DOUBLE, T_MAXTYPE }; // Error codes reported by GetError enum PlyError { E_NOERROR, // 0 // Errors of open(..) E_CANTOPEN, // 1 E_NOTHEADER, // 2 E_UNESPECTEDEOF, // 3 E_NOFORMAT, // 4 E_SYNTAX, // 5 E_PROPOUTOFELEMENT, // 6 E_BADTYPENAME, // 7 // Errors of addtoread(..) E_ELEMNOTFOUND, // 8 E_PROPNOTFOUND, // 9 E_BADTYPE, // 10 E_INCOMPATIBLETYPE, // 11 E_BADCAST, // 12 E_MAXPLYERRORS }; // file formats supported by the ply format enum PlyFormat { F_UNSPECIFIED, F_ASCII, F_BINLITTLE, F_BINBIG }; #ifdef USE_ZLIB typedef void * GZFILE; #else typedef FILE * GZFILE; #endif // Messaggio di errore //extern const char * ply_error_msg[]; // TIPO FILE // Descrittore esterno di propieta' class PropDescriptor { public: char * elemname; // Nome dell'elemento char * propname; // Nome della propieta' int stotype1; // Tipo dell'elemento su file (se lista tipo degli elementi della lista) int memtype1; // Tipo dell'elemento in memoria (se lista tipo degli elementi della lista) size_t offset1; // Offset del valore in memoria int islist; // 1 se lista, 0 altrimenti int alloclist; // 1 se alloca lista, 0 se preallocata int stotype2; // Tipo del numero di elementi della lista su file int memtype2; // Tipo del numero di elementi della lista in memoria size_t offset2; // Offset valore memoria int format; // duplicazione del formato size_t stotypesize() const; // per sapere quanto e'grande un dato descrittore sul file size_t memtypesize() const; // per sapere quanto e'grande un dato descrittore in memoria const char *memtypename() const; const char *stotypename() const; }; // Reading Callback (used to copy a data prop) typedef bool (* readelemcb) ( GZFILE fp, void * mem, PropDescriptor * p ); class PlyProperty { public: inline PlyProperty() { tipo = 0; islist = 0; tipoindex = 0; bestored = 0; } inline PlyProperty( const char * na, int ti, int isl, int t2 ) { assert(na); assert(ti>0); assert(ti0 || (t2==0 && isl==0) ); assert(t2=0); name = std::string(na); number = nu; } inline void SetName( const char * na ) { name = std::string(na); } inline void SetNumbert( int nu ) { assert(nu>0); number = nu; } void AddProp( const char * na, int ti, int isl, int t2 ); int AddToRead( const char * propname, int stotype1, int memtype1, size_t offset1, int islist, int alloclist, int stotype2, int memtype2, size_t offset2 ); // Vedi struttura PropDescriptor PlyProperty * FindProp( const char * name ); std::string name; // Nome dell'elemento int number; // Numero di elementi di questo tipo std::vector props; // Vettore dinamico delle property }; class PlyFile { private: void compile( PlyElement * e ); void compile( PlyProperty * p ); public: // Modi di apertura enum { MODE_READ, MODE_WRITE }; PlyFile(); ~PlyFile(); // Apre un file ply int Open( const char * filename, int mode ); // Chiude un file e disalloca la memoria void Destroy(); // Ritorna il codice dell'ultimo errore inline int GetError() const { return error; } // Definizione di lettura (Vedi struttura PropDescriptor) int AddToRead( const char * elemname, const char * propname, int stotype1, int memtype1, size_t offset1, int islist, int alloclist, int stotype2, int memtype2, size_t offset2 ); // Come sopra ma con descrittore inline int AddToRead( const PropDescriptor & p ) { return AddToRead(p.elemname,p.propname,p.stotype1, p.memtype1,p.offset1,p.islist,p.alloclist,p.stotype2, p.memtype2,p.offset2 ); } // Ritorna il numero di oggetti di un tipo di elemento const char * ElemName( int i ); int ElemNumber( int i ) const; // Setta il tipo di elemento corrente per effetture // la lettura inline void SetCurElement( int i ) { if(i<0 || i>=int(elements.size())) cure = 0; else { cure = &(elements[i]); compile(cure); } } // Lettura du un elemento int Read( void * mem ); std::vector elements; // Vettore degli elementi std::vector comments; // Vettore dei commenti static const char * typenames[9]; static const char * newtypenames[9]; inline const char * GetHeader() const { return header; } protected: GZFILE gzfp; float version; // Versione del file int error; // Errore corrente (vedi enum) int format; // Formato del file (vedi enum ) char header[4096]; // Testo dell'header PlyElement * cure; // Elemento da leggere // Callback di lettura: vale ReadBin o ReadAcii int (* ReadCB)( GZFILE fp, const PlyProperty * r, void * mem, int fmt ); int OpenRead( const char * filename ); int OpenWrite( const char * filename ); PlyElement * AddElement( const char * name, int number ); int FindType( const char * name ) const; PlyElement * FindElement( const char * name ); }; void interpret_texture_name(const char*a, const char*fn, char*output); } // end namespace ply } // end namespace vcg #endif ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������qutemol/vcg/wrap/ply/plylib.cpp���������������������������������������������������������������������0000444�0001750�0001750�00000242443�10621023631�015160� 0����������������������������������������������������������������������������������������������������ustar �mba�����������������������������mba��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������/**************************************************************************** * VCGLib o o * * Visual and Computer Graphics Library o o * * _ O _ * * Copyright(C) 2004 \/)\/ * * Visual Computing Lab /\/| * * ISTI - Italian National Research Council | * * \ * * All rights reserved. * * * * 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. * * * * 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 (http://www.gnu.org/licenses/gpl.txt) * * for more details. * * * ****************************************************************************/ /**************************************************************************** Acknowlegments Portions of this file were based on the original code of the Ply library of Greg Turk and on the work of Claudio Rocchini ****************************************************************************/ /**************************************************************************** History $Log: plylib.cpp,v $ Revision 1.13 2007/05/11 08:21:45 cignoni Added ifdef for manage bigendianess of ppc machines Revision 1.12 2006/01/27 09:09:10 corsini Fix signed/unsigned mismatch Revision 1.11 2005/12/02 00:00:53 cignoni Moved and corrected interpret_texture_name from plystuff.h to plylib.cpp Revision 1.10 2005/11/26 00:22:46 cignoni added untested code of interpret_texture Revision 1.9 2005/11/12 07:07:47 cignoni Changed Offset types to remove warnings Revision 1.8 2005/03/15 11:46:52 cignoni Cleaning of the automatic bbox caching support for ply files. First working version. Revision 1.7 2005/01/03 10:35:59 cignoni Improved the compatibility for ply format for faces having the list size (e.g. number of vertexes of a face) as a char instead of a uchar. Added a couple of new face descriptors, corrected a bug in error reporting function (and restructured) and translated a few comments. Thanks to Patrick Min for the careful bug reporting Revision 1.6 2004/06/23 15:36:57 cignoni Restructured management of error, now the standard open for any mesh type return the error code, the default success value is zero Any import class has a method ErrorMsg that give a verbal description of an error code. Revision 1.5 2004/06/23 00:06:45 ponchio Moved #define LITTLE_MACHINE outside of #ifdef WIN32 (linux on PC is little too). Revision 1.4 2004/05/12 17:21:08 ganovelli inclusion of io.h removed (unnecessary) Revision 1.3 2004/05/12 10:13:29 ganovelli direct.h was included also without WIN32 definition Revision 1.2 2004/04/06 21:48:50 cignoni Commented out unused parameter names Revision 1.1 2004/03/03 15:00:51 cignoni Initial commit ****************************************************************************/ // Note that on ppc mac (the only bigendian machine around) // the preprocessor def __BIG_ENDIAN__ is always defined. // Otherwise we should be on a little endian machine (intel/amd based) #ifndef __BIG_ENDIAN__ #define LITTLE_MACHINE #endif #ifdef WIN32 #define assert ASSERT #pragma warning( disable : 4267 ) #else #include #endif #ifdef WIN32 #include #endif #include #include #include #include #include #include #include #include #include #include #include #include "plylib.h" using namespace std; namespace vcg{ namespace ply{ typedef unsigned short ushort; typedef unsigned long ulong; typedef unsigned char uchar; typedef unsigned int uint; //#ifdef USE_ZLIB //#include //#define XFILE void //#define pb_fclose gzclose //#define pb_fopen gzopen //#define pb_fgets(s,n,f) gzgets(f,s,n) //#define pb_fread(b,s,n,f) gzread(f,b,(s)*(n)) //#else #define XFILE FILE #define pb_fclose fclose #define pb_fopen fopen #define pb_fgets(s,n,f) fgets(s,n,f) #define pb_fread(b,s,n,f) fread(b,s,n,f) //#endif //#ifdef WIN32 #define pb_mkdir(n) _mkdir(n) #define pb_access _access #define pb_stat _stat #define pb_open _open #define pb_close _close /* #else #define pb_mkdir(n) mkdir(n,0) #define pb_access access #define pb_stat stat #define pb_open open #define pb_close close #endif */ // Funzioni statiche per la lettura di un elemento int ReadBin ( XFILE * fp, const PlyProperty * pr, void * mem, int fmt ); int ReadAscii( XFILE * fp, const PlyProperty * pr, void * mem, int fmt ); const char * ::vcg::ply::PlyFile::typenames[9]= { "none", "char", "short", "int", "uchar", "ushort", "uint", "float", "double" }; const char * PlyFile::newtypenames[9]= { "none", "int8", "int16", "int32", "uint8", "uint16", "uint32", "float32", "float64" }; static int TypeSize[] = { 0, 1, 2, 4, 1, 2, 4, 4, 8 }; size_t PropDescriptor::memtypesize() const {return TypeSize[memtype1];} size_t PropDescriptor::stotypesize() const {return TypeSize[stotype1];} const char *PropDescriptor::memtypename() const {return PlyFile::typenames[memtype1];} const char *PropDescriptor::stotypename() const {return PlyFile::typenames[stotype1];} static char CrossType[9][9]= { {0,0,0,0,0,0,0,0,0}, {0,1,1,1,1,1,1,0,0}, {0,0,1,1,0,1,1,0,0}, {0,0,0,1,0,0,1,0,0}, {0,1,1,1,1,1,1,0,0}, {0,0,1,1,0,1,1,0,0}, {0,0,0,1,0,0,1,0,0}, {0,0,0,0,0,0,0,1,1}, {0,0,0,0,0,0,0,1,1} }; // ****************************************************** // Funzioni di supporto per la lettura/scrittura dei dati // ****************************************************** // Big-little endian static inline void SwapShort( ushort * s ) { assert(s); *s = ushort( (int(*s)>>8) | (int(*s)<<8) ); } static inline void SwapInt( uint * x ) { assert(x); *x = ( ((*x)>>24) & 0x000000FF ) | ( ((*x)>> 8) & 0x0000FF00 ) | ( ((*x)<< 8) & 0x00FF0000 ) | ( ((*x)<<24) & 0xFF000000 ) ; } static inline void SwapDouble( double * /*d*/ ) { // Come si fa? assert(0); } // Lettura tipi binari static inline int ReadCharB( XFILE * fp, char * c, int /*format*/ ) { assert(fp); assert(c); return pb_fread(c,1,1,fp); } static inline int ReadShortB( XFILE * fp, short * s, int format ) { assert(fp); assert(s); int r; r = pb_fread(s,sizeof(short),1,fp); #ifdef LITTLE_MACHINE if(format==F_BINBIG) #else if(format==F_BINLITTLE) #endif SwapShort((ushort *)s); return r; } static inline int ReadIntB( XFILE * fp, int * i, int format ) { assert(fp); assert(i); int r; r = pb_fread(i,sizeof(int),1,fp); #ifdef LITTLE_MACHINE if(format==F_BINBIG) #else if(format==F_BINLITTLE) #endif SwapInt((uint *)i); return r; } static inline int ReadUCharB( XFILE * fp, uchar * uc, int /*format*/ ) { assert(fp); assert(uc); return pb_fread(uc,1,1,fp); } static inline int ReadUShortB( XFILE * fp, ushort * us, int format ) { assert(fp); assert(us); int r; r = pb_fread(us,sizeof(ushort),1,fp); #ifdef LITTLE_MACHINE if(format==F_BINBIG) #else if(format==F_BINLITTLE) #endif SwapShort(us); return r; } static inline int ReadUIntB( XFILE * fp, uint * ui, int format ) { assert(fp); assert(ui); int r; r = pb_fread(ui,sizeof(uint),1,fp); #ifdef LITTLE_MACHINE if(format==F_BINBIG) #else if(format==F_BINLITTLE) #endif SwapInt(ui); return r; } static inline int ReadFloatB( XFILE * fp, float * f, int format ) { assert(fp); assert(f); int r; r = pb_fread(f,sizeof(float),1,fp); #ifdef LITTLE_MACHINE if(format==F_BINBIG) #else if(format==F_BINLITTLE) #endif SwapInt((uint *)f); return r; } static inline int ReadDoubleB( XFILE * fp, double * d, int format ) { assert(fp); assert(d); int r; r = pb_fread(d,sizeof(double),1,fp); #ifdef LITTLE_MACHINE if(format==F_BINBIG) #else if(format==F_BINLITTLE) #endif SwapDouble(d); return r; } // --- simulazione di scanf ------ //static bool sbuffer_ok = false; //static const int SBUFFERSIZE = 4096; //static char sbuffer[SBUFFERSIZE]; //static const char * separators = " \t,\n\r\f"; static void InitSBuffer() { //sbuffer_ok = false; } static inline int ReadInt( XFILE * fp, int & t ) { /* char * p; if(!sbuffer_ok) { pb_fgets(sbuffer,SBUFFERSIZE,fp); p = strtok(sbuffer,separators); sbuffer_ok = true; } else p = strtok(0,separators); if(p==0) { pb_fgets(sbuffer,SBUFFERSIZE,fp); p = strtok(sbuffer,separators); } t = atoi(p); return 1; */ int r = fscanf(fp,"%d",&t); if(r==EOF) r = 0; return r; } static inline int ReadUInt( XFILE * fp, unsigned int & t ) { /* char * p; if(!sbuffer_ok) { pb_fgets(sbuffer,SBUFFERSIZE,fp); p = strtok(sbuffer,separators); sbuffer_ok = true; } else p = strtok(0,separators); if(p==0) { pb_fgets(sbuffer,SBUFFERSIZE,fp); p = strtok(sbuffer,separators); } t = atoi(p); return 1; */ int r = fscanf(fp,"%u",&t); if(r==EOF) r = 0; return r; } static inline int ReadFloat( XFILE * fp, float & f ) { /* char * p; if(!sbuffer_ok) { pb_fgets(sbuffer,SBUFFERSIZE,fp); p = strtok(sbuffer,separators); sbuffer_ok = true; } else p = strtok(0,separators); if(p==0) { pb_fgets(sbuffer,SBUFFERSIZE,fp); p = strtok(sbuffer,separators); } f = atof(p); return 1; */ int r = fscanf(fp,"%f",&f); if(r==EOF) r = 0; return r; } static inline int ReadDouble( XFILE * fp, double & d ) { /* char * p; if(!sbuffer_ok) { pb_fgets(sbuffer,SBUFFERSIZE,fp); p = strtok(sbuffer,separators); sbuffer_ok = true; } else p = strtok(0,separators); if(p==0) { pb_fgets(sbuffer,SBUFFERSIZE,fp); p = strtok(sbuffer,separators); } d = atof(p); return 1; */ int r = fscanf(fp,"%lf",&d); if(r==EOF) r = 0; return r; } // Lettura tipi ascii static inline int ReadCharA( XFILE * fp, char * c ) { assert(fp); assert(c); int r,t; r = ReadInt(fp,t); *c = (char)t; return r; } static inline int ReadShortA( XFILE * fp, short * s ) { assert(fp); assert(s); int r,t; r = ReadInt(fp,t); *s = (short)t; return r; } static inline int ReadIntA( XFILE * fp, int * i ) { assert(fp); assert(i); return ReadInt(fp,*i); } static inline int ReadUCharA( XFILE * fp, uchar * uc ) { assert(fp); assert(uc); int r; uint t; r = ReadUInt(fp,t); *uc = (uchar)t; return r; } static inline int ReadUShortA( XFILE * fp, ushort * us ) { assert(fp); assert(us); int r; uint t; r = ReadUInt(fp,t); *us = (ushort)t; return r; } static inline int ReadUIntA( XFILE * fp, uint * ui ) { assert(fp); assert(ui); return ReadUInt(fp,*ui); } static inline int ReadFloatA( XFILE * fp, float * f ) { assert(fp); assert(f); return ReadFloat(fp,*f); } static inline int ReadDoubleA( XFILE * fp, double * d ) { assert(fp); assert(d); return ReadDouble(fp,*d); } // Memorizza il valore val nella variabile mem di tipo tm static inline void StoreInt( void * mem, const int tm, const int val ) { assert(mem); switch(tm) { case T_CHAR: *(char *)mem = (char )val; break; case T_SHORT: *(short *)mem = (short )val; break; case T_INT: *(int *)mem = (int )val; break; case T_UCHAR: *(uchar *)mem = (uchar )val; break; case T_USHORT: *(ushort *)mem = (ushort)val; break; case T_UINT: *(uint *)mem = (uint )val; break; case T_FLOAT: *(float *)mem = (float )val; break; case T_DOUBLE: *(double *)mem = (double)val; break; default: assert(0); } } // Salta un valore nel file static inline int SkipScalarA( XFILE * fp, const int tf ) { int t; float f; assert(fp); switch(tf) { case T_CHAR: case T_SHORT: case T_INT: case T_UCHAR: case T_USHORT: case T_UINT: return ReadInt(fp,t); case T_FLOAT: case T_DOUBLE: return ReadFloat(fp,f); default: assert(0); return 0; } } static inline int SkipScalarB( XFILE * fp, const int tf) { static char dummy[8]; assert(fp); return pb_fread(dummy,1,TypeSize[tf],fp); } static int ReadScalarB( XFILE * fp, void * mem, const int tf, const int tm, int fmt ) { static char ch; static short sh; static int in; static uchar uc; static ushort us; static uint ui; static float fl; static double dd; int r = 0; switch(tf) { case T_CHAR: //================== Lettura char r = ReadCharB(fp,&ch,fmt); switch(tm) { case T_CHAR: *(char *)mem = (char )ch; break; case T_SHORT: *(short *)mem = (short )ch; break; case T_INT: *(int *)mem = (int )ch; break; case T_UCHAR: *(uchar *)mem = (uchar )ch; break; case T_USHORT: *(ushort *)mem = (ushort)ch; break; case T_UINT: *(uint *)mem = (uint )ch; break; case T_FLOAT: *(float *)mem = (float )ch; break; case T_DOUBLE: *(double *)mem = (double)ch; break; default: assert(0); } break; case T_SHORT: //================== Lettura short r = ReadShortB(fp,&sh,fmt); switch(tm) { case T_CHAR: *(char *)mem = (char )sh; break; case T_SHORT: *(short *)mem = (short )sh; break; case T_INT: *(int *)mem = (int )sh; break; case T_UCHAR: *(uchar *)mem = (uchar )sh; break; case T_USHORT: *(ushort *)mem = (ushort)sh; break; case T_UINT: *(uint *)mem = (uint )sh; break; case T_FLOAT: *(float *)mem = (float )sh; break; case T_DOUBLE: *(double *)mem = (double)sh; break; default: assert(0); } break; case T_INT: //================== Lettura int r = ReadIntB(fp,&in,fmt); switch(tm) { case T_CHAR: *(char *)mem = (char )in; break; case T_SHORT: *(short *)mem = (short )in; break; case T_INT: *(int *)mem = (int )in; break; case T_UCHAR: *(uchar *)mem = (uchar )in; break; case T_USHORT: *(ushort *)mem = (ushort)in; break; case T_UINT: *(uint *)mem = (uint )in; break; case T_FLOAT: *(float *)mem = (float )in; break; case T_DOUBLE: *(double *)mem = (double)in; break; default: assert(0); } break; case T_UCHAR: //================== Lettura uchar r = ReadUCharB(fp,&uc,fmt); switch(tm) { case T_CHAR: *(char *)mem = (char )uc; break; case T_SHORT: *(short *)mem = (short )uc; break; case T_INT: *(int *)mem = (int )uc; break; case T_UCHAR: *(uchar *)mem = (uchar )uc; break; case T_USHORT: *(ushort *)mem = (ushort)uc; break; case T_UINT: *(uint *)mem = (uint )uc; break; case T_FLOAT: *(float *)mem = (float )uc; break; case T_DOUBLE: *(double *)mem = (double)uc; break; default: assert(0); } break; case T_USHORT: //================== Lettura ushort r = ReadUShortB(fp,&us,fmt); switch(tm) { case T_CHAR: *(char *)mem = (char )us; break; case T_SHORT: *(short *)mem = (short )us; break; case T_INT: *(int *)mem = (int )us; break; case T_UCHAR: *(uchar *)mem = (uchar )us; break; case T_USHORT: *(ushort *)mem = (ushort)us; break; case T_UINT: *(uint *)mem = (uint )us; break; case T_FLOAT: *(float *)mem = (float )us; break; case T_DOUBLE: *(double *)mem = (double)us; break; default: assert(0); } break; case T_UINT: //================== Lettura uint r = ReadUIntB(fp,&ui,fmt); switch(tm) { case T_CHAR: *(char *)mem = (char )ui; break; case T_SHORT: *(short *)mem = (short )ui; break; case T_INT: *(int *)mem = (int )ui; break; case T_UCHAR: *(uchar *)mem = (uchar )ui; break; case T_USHORT: *(ushort *)mem = (ushort)ui; break; case T_UINT: *(uint *)mem = (uint )ui; break; case T_FLOAT: *(float *)mem = (float )ui; break; case T_DOUBLE: *(double *)mem = (double)ui; break; default: assert(0); } break; case T_FLOAT: //================== Lettura float r = ReadFloatB(fp,&fl,fmt); switch(tm) { case T_FLOAT: *(float *)mem = fl; break; case T_DOUBLE: *(double *)mem = fl; break; default: assert(0); } break; case T_DOUBLE: //================== Lettura double r = ReadDoubleB(fp,&dd,fmt); switch(tm) { case T_FLOAT: *(float *)mem = (float)dd; break; case T_DOUBLE: *(double *)mem = dd; break; default: assert(0); } break; default: assert(0); } return r; } // Legge un valore di tipo tf e lo memorizza col tipo tm static int ReadScalarA( XFILE * fp, void * mem, const int tf, const int tm ) { static char ch; static short sh; static int in; static uchar uc; static ushort us; static uint ui; static float fl; static double dd; int r = 0; switch(tf) { case T_CHAR: //================== Lettura char r = ReadCharA(fp,&ch); switch(tm) { case T_CHAR: *(char *)mem = (char )ch; break; case T_SHORT: *(short *)mem = (short )ch; break; case T_INT: *(int *)mem = (int )ch; break; case T_UCHAR: *(uchar *)mem = (uchar )ch; break; case T_USHORT: *(ushort *)mem = (ushort)ch; break; case T_UINT: *(uint *)mem = (uint )ch; break; case T_FLOAT: *(float *)mem = (float )ch; break; case T_DOUBLE: *(double *)mem = (double)ch; break; default: assert(0); } break; case T_SHORT: //================== Lettura short r = ReadShortA(fp,&sh); switch(tm) { case T_CHAR: *(char *)mem = (char )sh; break; case T_SHORT: *(short *)mem = (short )sh; break; case T_INT: *(int *)mem = (int )sh; break; case T_UCHAR: *(uchar *)mem = (uchar )sh; break; case T_USHORT: *(ushort *)mem = (ushort)sh; break; case T_UINT: *(uint *)mem = (uint )sh; break; case T_FLOAT: *(float *)mem = (float )sh; break; case T_DOUBLE: *(double *)mem = (double)sh; break; default: assert(0); } break; case T_INT: //================== Lettura int r = ReadIntA(fp,&in); switch(tm) { case T_CHAR: *(char *)mem = (char )in; break; case T_SHORT: *(short *)mem = (short )in; break; case T_INT: *(int *)mem = (int )in; break; case T_UCHAR: *(uchar *)mem = (uchar )in; break; case T_USHORT: *(ushort *)mem = (ushort)in; break; case T_UINT: *(uint *)mem = (uint )in; break; case T_FLOAT: *(float *)mem = (float )in; break; case T_DOUBLE: *(double *)mem = (double)in; break; default: assert(0); } break; case T_UCHAR: //================== Lettura uchar r = ReadUCharA(fp,&uc); switch(tm) { case T_CHAR: *(char *)mem = (char )uc; break; case T_SHORT: *(short *)mem = (short )uc; break; case T_INT: *(int *)mem = (int )uc; break; case T_UCHAR: *(uchar *)mem = (uchar )uc; break; case T_USHORT: *(ushort *)mem = (ushort)uc; break; case T_UINT: *(uint *)mem = (uint )uc; break; case T_FLOAT: *(float *)mem = (float )uc; break; case T_DOUBLE: *(double *)mem = (double)uc; break; default: assert(0); } break; case T_USHORT: //================== Lettura ushort r = ReadUShortA(fp,&us); switch(tm) { case T_CHAR: *(char *)mem = (char )us; break; case T_SHORT: *(short *)mem = (short )us; break; case T_INT: *(int *)mem = (int )us; break; case T_UCHAR: *(uchar *)mem = (uchar )us; break; case T_USHORT: *(ushort *)mem = (ushort)us; break; case T_UINT: *(uint *)mem = (uint )us; break; case T_FLOAT: *(float *)mem = (float )us; break; case T_DOUBLE: *(double *)mem = (double)us; break; default: assert(0); } break; case T_UINT: //================== Lettura uint r = ReadUIntA(fp,&ui); switch(tm) { case T_CHAR: *(char *)mem = (char )ui; break; case T_SHORT: *(short *)mem = (short )ui; break; case T_INT: *(int *)mem = (int )ui; break; case T_UCHAR: *(uchar *)mem = (uchar )ui; break; case T_USHORT: *(ushort *)mem = (ushort)ui; break; case T_UINT: *(uint *)mem = (uint )ui; break; case T_FLOAT: *(float *)mem = (float )ui; break; case T_DOUBLE: *(double *)mem = (double)ui; break; default: assert(0); } break; case T_FLOAT: //================== Lettura float r = ReadFloatA(fp,&fl); switch(tm) { case T_FLOAT: *(float *)mem = fl; break; case T_DOUBLE: *(double *)mem = fl; break; default: assert(0); } break; case T_DOUBLE: //================== Lettura double r = ReadDoubleA(fp,&dd); switch(tm) { case T_FLOAT: *(float *)mem = (float)dd; break; case T_DOUBLE: *(double *)mem = dd; break; default: assert(0); } break; default: assert(0); } return r; } //####################### Classe PlyElement void PlyElement::AddProp( const char * na, int ti, int isl, int t2 ) { assert(na); assert(ti>0); assert(ti0 || (t2==0 && isl==0)); assert(t2::iterator i; for(i=props.begin();i!=props.end();++i) if( i->name == na ) return &*i; return 0; } int PlyElement::AddToRead( const char * propname, int stotype1, int memtype1, size_t offset1, int islist, int alloclist, int stotype2, int memtype2, size_t offset2 ) // Vedi struttura PropDescriptor { assert(propname); PlyProperty * p = FindProp(propname); if(p==0) { return E_PROPNOTFOUND; } if( stotype1<1 || stotype1>=T_MAXTYPE || memtype1<1 || memtype1>=T_MAXTYPE ) { return E_BADTYPE; } if( islist && (stotype2<1 || stotype2>=T_MAXTYPE || memtype2<1 || memtype2>=T_MAXTYPE ) ) { return E_BADTYPE; } if( islist!= p->islist || stotype1 != p->tipo || ( islist && stotype2!=p->tipoindex) ) { return E_INCOMPATIBLETYPE; } if( !CrossType[p->tipo][stotype1] || (islist && !CrossType[p->tipoindex][stotype2] ) ) { return E_BADCAST; } p->bestored = 1; p->desc.stotype1 = stotype1; p->desc.memtype1 = memtype1; p->desc.offset1 = offset1; p->desc.islist = islist; p->desc.alloclist = alloclist; p->desc.stotype2 = stotype2; p->desc.memtype2 = memtype2; p->desc.offset2 = offset2; return E_NOERROR; } //####################### Classe PlyFile PlyFile::PlyFile( void ) { gzfp = 0; version = 0.0f; error = E_NOERROR; format = F_UNSPECIFIED; cure = 0; ReadCB = 0; InitSBuffer(); } PlyFile::~PlyFile( void ) { Destroy(); } int PlyFile::Open( const char * filename, int mode ) { if(filename==0 || (mode!=MODE_READ && mode!=MODE_WRITE) ) { error = E_CANTOPEN; return -1; } if(mode==MODE_READ) return OpenRead(filename); else return OpenWrite(filename); } void PlyFile::Destroy( void ) { if(gzfp!=0) { pb_fclose(gzfp); gzfp = 0; } ReadCB = 0; } int PlyFile::OpenRead( const char * filename ) { // Tokens dell'intestazione static const char * SEP = " \t\n\r"; static const char * HEADER = "ply"; static const char * FORMAT = "format"; static const char * TASCII = "ascii"; static const char * TBINBIG = "binary_big_endian"; static const char * TBINLITTLE = "binary_little_endian"; static const char * COMMENT = "comment"; static const char * OBJ_INFO = "obj_info"; static const char * ELEMENT = "element"; static const char * PROPERTY = "property"; static const char * ENDHEADER = "end_header"; static const char * LIST = "list"; const int MAXB = 512; char buf[MAXB]; char * token; PlyElement * curelement; // Predistruzione Destroy(); // Apertura file gzfp = pb_fopen(filename,"rb"); if(gzfp==0) { error = E_CANTOPEN; goto error; } header[0] = 0; // ********* Parsing header *********** // Controllo header if( pb_fgets(buf,MAXB-1,gzfp)==0 ) { error = E_UNESPECTEDEOF; goto error; } strcat(header,buf); if( strncmp(buf,HEADER,strlen(HEADER)) ) { error = E_NOTHEADER; goto error; } // Lettura tipo e versione if( pb_fgets(buf,MAXB-1,gzfp)==0 ) { error = E_UNESPECTEDEOF; goto error; } strcat(header,buf); token = strtok(buf,SEP); if(token==0) { error = E_UNESPECTEDEOF; goto error; } if( strcmp(token,FORMAT) ) { error = E_NOFORMAT; goto error; } token = strtok(0,SEP); if(token==0) { error = E_UNESPECTEDEOF; goto error; } if( !strcmp(token,TASCII) ) format = F_ASCII; else if( !strcmp(token,TBINBIG) ) format = F_BINBIG; else if( !strcmp(token,TBINLITTLE) ) format = F_BINLITTLE; else { error = E_NOFORMAT; goto error; } token = strtok(0,SEP); if(token==0) { error = E_UNESPECTEDEOF; goto error; } version = float(atof(token)); //************* Ciclo lettura elementi **************** curelement = 0; for(;;) { if( pb_fgets(buf,MAXB-1,gzfp)==0 ) { error = E_UNESPECTEDEOF; goto error; } strcat(header,buf); token = strtok(buf,SEP); if(token==0) { error = E_UNESPECTEDEOF; goto error; } if( !strcmp(token,COMMENT) ) { comments.push_back( string(token+strlen(token)+1) ); //AddComment( token+strlen(token)+1 ); } else if( !strcmp(token,OBJ_INFO) ) { comments.push_back( string(token+strlen(token)+1) ); //AddComment( token+strlen(token)+1 ); } else if( !strcmp(token,ENDHEADER) ) { break; } else if( !strcmp(token,ELEMENT) ) { // Lettura nome elemento char * name = strtok(0,SEP); if(name==0) { error = E_SYNTAX; goto error; } // Lettura numero di elementi token = strtok(0,SEP); if(name==0) { error = E_SYNTAX; goto error; } int number = atoi(token); PlyElement t(name,number); elements.push_back(t); curelement = &(elements.back()); } else if( !strcmp(token,PROPERTY) ) { if(curelement==0) { error = E_PROPOUTOFELEMENT; goto error; } token = strtok(0,SEP); if(token==0) { error = E_SYNTAX; goto error; } if( !strcmp(token,LIST) ) { token = strtok(0,SEP); if(token==0) { error = E_SYNTAX; goto error; } int t2 = FindType(token); if(t2==-1) { error = E_BADTYPENAME; goto error; } token = strtok(0,SEP); if(token==0) { error = E_SYNTAX; goto error; } int t1 = FindType(token); if(t1==-1) { error = E_BADTYPENAME; goto error; } token = strtok(0,SEP); if(token==0) { error = E_SYNTAX; goto error; } //curelement->AddProp(token,t1,1,t2); prima del 5/9/03 era cosi' ma swappava i due tipi. curelement->AddProp(token,t1,1,t2); } else { int t1 = FindType(token); if(t1==-1) { error = E_BADTYPENAME; goto error; } token = strtok(0,SEP); if(token==0) { error = E_SYNTAX; goto error; } curelement->AddProp(token,t1,0,T_NOTYPE); } } else { error = E_SYNTAX; goto error; } } if(format==F_ASCII) ReadCB = ReadAscii; else ReadCB = ReadBin; return 0; error: Destroy(); return -1; } int PlyFile::OpenWrite( const char * /*filename*/ ) { // Per ora non implementato assert(0); return -1; } //################# Funzioni di supporto int PlyFile::FindType( const char * name ) const { int i; assert(name); for(i=1;i<9;++i) if( !strcmp(name,typenames[i]) || !strcmp(name,newtypenames[i])) return i; return -1; } PlyElement * PlyFile::FindElement( const char * na ) { assert(na); vector::iterator i; for(i=elements.begin();i!=elements.end();++i) if( i->name == na ) return &*i; return 0; } int PlyFile::AddToRead( const char * elemname, const char * propname, int stotype1, int memtype1, size_t offset1, int islist, int alloclist, int stotype2, int memtype2, size_t offset2 ) // Vedi struttura PropDescriptor { assert(elemname); PlyElement * e = FindElement(elemname); if(e==0) { error = E_ELEMNOTFOUND; return -1; } int r = e->AddToRead(propname,stotype1,memtype1,offset1,islist, alloclist,stotype2,memtype2,offset2 ); if(r==E_NOERROR) return 0; else { error = r; return -1; } } const char * PlyFile::ElemName( int i ) { if(i<0 || i>=int(elements.size())) return 0; else return elements[i].name.c_str(); } int PlyFile::ElemNumber( int i ) const { if(i<0 || i>=int(elements.size())) return 0; else return elements[i].number; } // *** callbacks *** static bool cb_skip_bin1( GZFILE fp, void * /*mem*/, PropDescriptor * /*d*/ ) { static char dummy[1]; assert(fp); return pb_fread(dummy,1,1,fp)!=0; } static bool cb_skip_bin2( GZFILE fp, void * /*mem*/, PropDescriptor * /*d*/ ) { static char dummy[2]; assert(fp); return pb_fread(dummy,1,2,fp)!=0; } static bool cb_skip_bin4( GZFILE fp, void * /*mem*/, PropDescriptor * /*d*/ ) { static char dummy[4]; assert(fp); return pb_fread(dummy,1,4,fp)!=0; } static bool cb_skip_bin8( GZFILE fp, void * /*mem*/, PropDescriptor * /*d*/ ) { static char dummy[8]; assert(fp); return pb_fread(dummy,1,8,fp)!=0; } static bool cb_skip_float_ascii( GZFILE fp, void * /*mem*/, PropDescriptor * /*d*/ ) { static float dummy; assert(fp); return fscanf(fp,"%f",&dummy)!=EOF; } static bool cb_skip_int_ascii( GZFILE fp, void * /*mem*/, PropDescriptor * /*d*/ ) { static int dummy; assert(fp); return fscanf(fp,"%d",&dummy)!=EOF; } static bool cb_read_chch( GZFILE fp, void * mem, PropDescriptor * d ) { return pb_fread( ((char *)mem)+d->offset1,1,1,fp)!=0; } static bool cb_read_chsh( GZFILE fp, void * mem, PropDescriptor * d ) { char c; if( pb_fread(&c,1,1,fp)==0) return false; return true; *(short *)(((char *)mem)+d->offset1) = short(c); return true; } static bool cb_read_chin( GZFILE fp, void * mem, PropDescriptor * d ) { char c; if( pb_fread(&c,1,1,fp)==0) return false; return true; *(int *)(((char *)mem)+d->offset1) = int(c); return true; } static bool cb_read_chuc( GZFILE fp, void * mem, PropDescriptor * d ) { char c; if( pb_fread(&c,1,1,fp)==0) return false; return true; *(uchar *)(((char *)mem)+d->offset1) = uchar(c); return true; } static bool cb_read_chus( GZFILE fp, void * mem, PropDescriptor * d ) { char c; if( pb_fread(&c,1,1,fp)==0) return false; return true; *(ushort *)(((char *)mem)+d->offset1) = ushort(c); return true; } static bool cb_read_chui( GZFILE fp, void * mem, PropDescriptor * d ) { char c; if( pb_fread(&c,1,1,fp)==0) return false; return true; *(uint *)(((char *)mem)+d->offset1) = uint(c); return true; } static bool cb_read_chfl( GZFILE fp, void * mem, PropDescriptor * d ) { char c; if( pb_fread(&c,1,1,fp)==0) return false; return true; *(float *)(((char *)mem)+d->offset1) = float(c); return true; } static bool cb_read_chdo( GZFILE fp, void * mem, PropDescriptor * d ) { char c; if( pb_fread(&c,1,1,fp)==0) return false; return true; *(double *)(((char *)mem)+d->offset1) = double(c); return true; } static bool cb_read_shch( GZFILE fp, void * mem, PropDescriptor * d ) { short c; if( ReadShortB(fp,&c,d->format)==0) return false; *(char *)(((char *)mem)+d->offset1) = char(c); return true; } static bool cb_read_shsh( GZFILE fp, void * mem, PropDescriptor * d ) { short c; if( ReadShortB(fp,&c,d->format)==0) return false; *(short *)(((char *)mem)+d->offset1) = short(c); return true; } static bool cb_read_shin( GZFILE fp, void * mem, PropDescriptor * d ) { short c; if( ReadShortB(fp,&c,d->format)==0) return false; *(int *)(((char *)mem)+d->offset1) = int(c); return true; } static bool cb_read_shuc( GZFILE fp, void * mem, PropDescriptor * d ) { short c; if( ReadShortB(fp,&c,d->format)==0) return false; *(uchar *)(((char *)mem)+d->offset1) = uchar(c); return true; } static bool cb_read_shus( GZFILE fp, void * mem, PropDescriptor * d ) { short c; if( ReadShortB(fp,&c,d->format)==0) return false; *(ushort *)(((char *)mem)+d->offset1) = ushort(c); return true; } static bool cb_read_shui( GZFILE fp, void * mem, PropDescriptor * d ) { short c; if( ReadShortB(fp,&c,d->format)==0) return false; *(uint *)(((char *)mem)+d->offset1) = uint(c); return true; } static bool cb_read_shfl( GZFILE fp, void * mem, PropDescriptor * d ) { short c; if( ReadShortB(fp,&c,d->format)==0) return false; *(float *)(((char *)mem)+d->offset1) = float(c); return true; } static bool cb_read_shdo( GZFILE fp, void * mem, PropDescriptor * d ) { short c; if( ReadShortB(fp,&c,d->format)==0) return false; *(double *)(((char *)mem)+d->offset1) = double(c); return true; } static bool cb_read_inch( GZFILE fp, void * mem, PropDescriptor * d ) { int c; if( ReadIntB(fp,&c,d->format)==0 ) return false; *(char *)(((char *)mem)+d->offset1) = char(c); return true; } static bool cb_read_insh( GZFILE fp, void * mem, PropDescriptor * d ) { int c; if( ReadIntB(fp,&c,d->format)==0 ) return false; *(short *)(((char *)mem)+d->offset1) = short(c); return true; } static bool cb_read_inin( GZFILE fp, void * mem, PropDescriptor * d ) { int c; if( ReadIntB(fp,&c,d->format)==0 ) return false; *(int *)(((char *)mem)+d->offset1) = int(c); return true; } static bool cb_read_inuc( GZFILE fp, void * mem, PropDescriptor * d ) { int c; if( ReadIntB(fp,&c,d->format)==0 ) return false; *(uchar *)(((char *)mem)+d->offset1) = uchar(c); return true; } static bool cb_read_inus( GZFILE fp, void * mem, PropDescriptor * d ) { int c; if( ReadIntB(fp,&c,d->format)==0 ) return false; *(ushort *)(((char *)mem)+d->offset1) = ushort(c); return true; } static bool cb_read_inui( GZFILE fp, void * mem, PropDescriptor * d ) { int c; if( ReadIntB(fp,&c,d->format)==0 ) return false; *(uint *)(((char *)mem)+d->offset1) = uint(c); return true; } static bool cb_read_infl( GZFILE fp, void * mem, PropDescriptor * d ) { int c; if( ReadIntB(fp,&c,d->format)==0 ) return false; *(float *)(((char *)mem)+d->offset1) = float(c); return true; } static bool cb_read_indo( GZFILE fp, void * mem, PropDescriptor * d ) { int c; if( ReadIntB(fp,&c,d->format)==0 ) return false; *(double *)(((char *)mem)+d->offset1) = double(c); return true; } static bool cb_read_ucch( GZFILE fp, void * mem, PropDescriptor * d ) { uchar c; if( pb_fread(&c,1,1,fp)==0 ) return false; *(char *)(((char *)mem)+d->offset1) = char(c); return true; } static bool cb_read_ucsh( GZFILE fp, void * mem, PropDescriptor * d ) { uchar c; if( pb_fread(&c,1,1,fp)==0 ) return false; *(short *)(((char *)mem)+d->offset1) = short(c); return true; } static bool cb_read_ucin( GZFILE fp, void * mem, PropDescriptor * d ) { uchar c; if( pb_fread(&c,1,1,fp)==0 ) return false; *(int *)(((char *)mem)+d->offset1) = int(c); return true; } static bool cb_read_ucuc( GZFILE fp, void * mem, PropDescriptor * d ) { uchar c; if( pb_fread(&c,1,1,fp)==0 ) return false; *(uchar *)(((char *)mem)+d->offset1) = uchar(c); return true; } static bool cb_read_ucus( GZFILE fp, void * mem, PropDescriptor * d ) { uchar c; if( pb_fread(&c,1,1,fp)==0 ) return false; *(ushort *)(((char *)mem)+d->offset1) = ushort(c); return true; } static bool cb_read_ucui( GZFILE fp, void * mem, PropDescriptor * d ) { uchar c; if( pb_fread(&c,1,1,fp)==0 ) return false; *(uint *)(((char *)mem)+d->offset1) = uint(c); return true; } static bool cb_read_ucfl( GZFILE fp, void * mem, PropDescriptor * d ) { uchar c; if( pb_fread(&c,1,1,fp)==0 ) return false; *(float *)(((char *)mem)+d->offset1) = float(c); return true; } static bool cb_read_ucdo( GZFILE fp, void * mem, PropDescriptor * d ) { uchar c; if( pb_fread(&c,1,1,fp)==0 ) return false; *(double *)(((char *)mem)+d->offset1) = double(c); return true; } static bool cb_read_usch( GZFILE fp, void * mem, PropDescriptor * d ) { ushort c; if( ReadUShortB(fp,&c,d->format)==0) return false; *(char *)(((char *)mem)+d->offset1) = char(c); return true; } static bool cb_read_ussh( GZFILE fp, void * mem, PropDescriptor * d ) { ushort c; if( ReadUShortB(fp,&c,d->format)==0) return false; *(short *)(((char *)mem)+d->offset1) = short(c); return true; } static bool cb_read_usin( GZFILE fp, void * mem, PropDescriptor * d ) { ushort c; if( ReadUShortB(fp,&c,d->format)==0) return false; *(int *)(((char *)mem)+d->offset1) = int(c); return true; } static bool cb_read_usuc( GZFILE fp, void * mem, PropDescriptor * d ) { ushort c; if( ReadUShortB(fp,&c,d->format)==0) return false; *(uchar *)(((char *)mem)+d->offset1) = uchar(c); return true; } static bool cb_read_usus( GZFILE fp, void * mem, PropDescriptor * d ) { ushort c; if( ReadUShortB(fp,&c,d->format)==0) return false; *(ushort *)(((char *)mem)+d->offset1) = ushort(c); return true; } static bool cb_read_usui( GZFILE fp, void * mem, PropDescriptor * d ) { ushort c; if( ReadUShortB(fp,&c,d->format)==0) return false; *(uint *)(((char *)mem)+d->offset1) = uint(c); return true; } static bool cb_read_usfl( GZFILE fp, void * mem, PropDescriptor * d ) { ushort c; if( ReadUShortB(fp,&c,d->format)==0) return false; *(float *)(((char *)mem)+d->offset1) = float(c); return true; } static bool cb_read_usdo( GZFILE fp, void * mem, PropDescriptor * d ) { ushort c; if( ReadUShortB(fp,&c,d->format)==0) return false; *(double *)(((char *)mem)+d->offset1) = double(c); return true; } static bool cb_read_uich( GZFILE fp, void * mem, PropDescriptor * d ) { uint c; if( ReadUIntB(fp,&c,d->format)==0 ) return false; *(char *)(((char *)mem)+d->offset1) = char(c); return true; } static bool cb_read_uish( GZFILE fp, void * mem, PropDescriptor * d ) { uint c; if( ReadUIntB(fp,&c,d->format)==0 ) return false; *(short *)(((char *)mem)+d->offset1) = short(c); return true; } static bool cb_read_uiin( GZFILE fp, void * mem, PropDescriptor * d ) { uint c; if( ReadUIntB(fp,&c,d->format)==0 ) return false; *(int *)(((char *)mem)+d->offset1) = int(c); return true; } static bool cb_read_uiuc( GZFILE fp, void * mem, PropDescriptor * d ) { uint c; if( ReadUIntB(fp,&c,d->format)==0 ) return false; *(uchar *)(((char *)mem)+d->offset1) = uchar(c); return true; } static bool cb_read_uius( GZFILE fp, void * mem, PropDescriptor * d ) { uint c; if( ReadUIntB(fp,&c,d->format)==0 ) return false; *(ushort *)(((char *)mem)+d->offset1) = ushort(c); return true; } static bool cb_read_uiui( GZFILE fp, void * mem, PropDescriptor * d ) { uint c; if( ReadUIntB(fp,&c,d->format)==0 ) return false; *(uint *)(((char *)mem)+d->offset1) = uint(c); return true; } static bool cb_read_uifl( GZFILE fp, void * mem, PropDescriptor * d ) { uint c; if( ReadUIntB(fp,&c,d->format)==0 ) return false; *(float *)(((char *)mem)+d->offset1) = float(c); return true; } static bool cb_read_uido( GZFILE fp, void * mem, PropDescriptor * d ) { uint c; if( ReadUIntB(fp,&c,d->format)==0 ) return false; *(double *)(((char *)mem)+d->offset1) = double(c); return true; } static bool cb_read_flfl( GZFILE fp, void * mem, PropDescriptor * d ) { float c; if( ReadFloatB(fp,&c,d->format)==0 ) return false; *(float *)(((char *)mem)+d->offset1) = float(c); return true; } static bool cb_read_fldo( GZFILE fp, void * mem, PropDescriptor * d ) { float c; if( ReadFloatB(fp,&c,d->format)==0 ) return false; *(double *)(((char *)mem)+d->offset1) = double(c); return true; } static bool cb_read_dofl( GZFILE fp, void * mem, PropDescriptor * d ) { double c; if( ReadDoubleB(fp,&c,d->format)==0 ) return false; *(float *)(((char *)mem)+d->offset1) = float(c); return true; } static bool cb_read_dodo( GZFILE fp, void * mem, PropDescriptor * d ) { double c; if( ReadDoubleB(fp,&c,d->format)==0 ) return false; *(double *)(((char *)mem)+d->offset1) = double(c); return true; } // NON OTTIMIZZATO!! static bool cb_read_ascii( GZFILE fp, void * mem, PropDescriptor * d ) { return ReadScalarA(fp, ((char *)mem)+d->offset1, d->stotype1, d->memtype1)!=0; } const int SKIP_MAX_BUF = 512; static char skip_buf[SKIP_MAX_BUF]; static bool cb_skip_list_bin1( GZFILE fp, void * /*mem*/, PropDescriptor * /*d*/ ) { uchar n; // Solo indici uchar if( pb_fread(&n,1,1,fp)==0 ) return false; if( pb_fread(skip_buf,1,n,fp)==0) return false; return true; } static bool cb_skip_list_bin2( GZFILE fp, void * /*mem*/, PropDescriptor * /*d*/ ) { uchar n; // Solo indici uchar if( pb_fread(&n,1,1,fp)==0 ) return false; if( pb_fread(skip_buf,2,n,fp)==0) return false; return true; } static bool cb_skip_list_bin4( GZFILE fp, void * /*mem*/, PropDescriptor * /*d*/ ) { uchar n; // Solo indici uchar if( pb_fread(&n,1,1,fp)==0 ) return false; if( pb_fread(skip_buf,4,n,fp)==0) return false; return true; } static bool cb_skip_list_bin8( GZFILE fp, void * /*mem*/, PropDescriptor * /*d*/ ) { uchar n; // Solo indici uchar if( pb_fread(&n,1,1,fp)==0 ) return false; if( pb_fread(skip_buf,8,n,fp)==0) return false; return true; } static bool cb_skip_list_ascii ( GZFILE fp, void * /*mem*/, PropDescriptor * /*d*/ ) { int i,n; if( !ReadScalarA(fp,&n,T_INT, T_INT) )return false; for(i=0;ioffset2, d->memtype2, n); // Determinazione memoria vettore if(d->alloclist) { store = (char *)calloc(n,TypeSize[d->memtype1]); assert(store); *(char **)(((char *)mem)+d->offset1) = store; } else { store = ((char *)mem)+d->offset1; } for(i=0;imemtype1], d->stotype1, d->memtype1 ) ) return 0; } return true; } // static bool cb_read_list_chch( GZFILE fp, void * mem, PropDescriptor * d ) { uchar n,i; if( pb_fread(&n,1,1,fp)==0 ) return false; char * store; StoreInt( ((char *)mem)+d->offset2, d->memtype2, int(n)); if(d->alloclist) { store = (char *)calloc(n,sizeof(char)); assert(store); *(char **)(((char *)mem)+d->offset1) = store; } else store = ((char *)mem)+d->offset1; for(i=0;ioffset2, d->memtype2, int(n)); if(d->alloclist) { store = (char *)calloc(n,sizeof(short)); assert(store); *(char **)(((char *)mem)+d->offset1) = store; } else store = ((char *)mem)+d->offset1; for(i=0;ioffset2, d->memtype2, int(n)); if(d->alloclist) { store = (char *)calloc(n,sizeof(int)); assert(store); *(char **)(((char *)mem)+d->offset1) = store; } else store = ((char *)mem)+d->offset1; for(i=0;ioffset2, d->memtype2, int(n)); if(d->alloclist) { store = (char *)calloc(n,sizeof(uchar)); assert(store); *(char **)(((char *)mem)+d->offset1) = store; } else store = ((char *)mem)+d->offset1; for(i=0;ioffset2, d->memtype2, int(n)); if(d->alloclist) { store = (char *)calloc(n,sizeof(ushort)); assert(store); *(char **)(((char *)mem)+d->offset1) = store; } else store = ((char *)mem)+d->offset1; for(i=0;ioffset2, d->memtype2, int(n)); if(d->alloclist) { store = (char *)calloc(n,sizeof(uint)); assert(store); *(char **)(((char *)mem)+d->offset1) = store; } else store = ((char *)mem)+d->offset1; for(i=0;ioffset2, d->memtype2, int(n)); if(d->alloclist) { store = (char *)calloc(n,sizeof(float)); assert(store); *(char **)(((char *)mem)+d->offset1) = store; } else store = ((char *)mem)+d->offset1; for(i=0;ioffset2, d->memtype2, int(n)); if(d->alloclist) { store = (char *)calloc(n,sizeof(double)); assert(store); *(char **)(((char *)mem)+d->offset1) = store; } else store = ((char *)mem)+d->offset1; for(i=0;ioffset2, d->memtype2, int(n)); if(d->alloclist) { store = (char *)calloc(n,sizeof(char)); assert(store); *(char **)(((char *)mem)+d->offset1) = store; } else store = ((char *)mem)+d->offset1; for(i=0;iformat)==0) return false; *(char *)(store+i*sizeof(char)) = char(c); } return true; } static bool cb_read_list_shsh( GZFILE fp, void * mem, PropDescriptor * d ) { uchar n,i; if( pb_fread(&n,1,1,fp)==0 ) return false; char * store; StoreInt( ((char *)mem)+d->offset2, d->memtype2, int(n)); if(d->alloclist) { store = (char *)calloc(n,sizeof(short)); assert(store); *(char **)(((char *)mem)+d->offset1) = store; } else store = ((char *)mem)+d->offset1; for(i=0;iformat)==0) return false; *(short *)(store+i*sizeof(short)) = short(c); } return true; } static bool cb_read_list_shin( GZFILE fp, void * mem, PropDescriptor * d ) { uchar n,i; if( pb_fread(&n,1,1,fp)==0 ) return false; char * store; StoreInt( ((char *)mem)+d->offset2, d->memtype2, int(n)); if(d->alloclist) { store = (char *)calloc(n,sizeof(int)); assert(store); *(char **)(((char *)mem)+d->offset1) = store; } else store = ((char *)mem)+d->offset1; for(i=0;iformat)==0) return false; *(int *)(store+i*sizeof(int)) = int(c); } return true; } static bool cb_read_list_shuc( GZFILE fp, void * mem, PropDescriptor * d ) { uchar n,i; if( pb_fread(&n,1,1,fp)==0 ) return false; char * store; StoreInt( ((char *)mem)+d->offset2, d->memtype2, int(n)); if(d->alloclist) { store = (char *)calloc(n,sizeof(uchar)); assert(store); *(char **)(((char *)mem)+d->offset1) = store; } else store = ((char *)mem)+d->offset1; for(i=0;iformat)==0) return false; *(uchar *)(store+i*sizeof(uchar)) = uchar(c); } return true; } static bool cb_read_list_shus( GZFILE fp, void * mem, PropDescriptor * d ) { uchar n,i; if( pb_fread(&n,1,1,fp)==0 ) return false; char * store; StoreInt( ((char *)mem)+d->offset2, d->memtype2, int(n)); if(d->alloclist) { store = (char *)calloc(n,sizeof(ushort)); assert(store); *(char **)(((char *)mem)+d->offset1) = store; } else store = ((char *)mem)+d->offset1; for(i=0;iformat)==0) return false; *(ushort *)(store+i*sizeof(ushort)) = ushort(c); } return true; } static bool cb_read_list_shui( GZFILE fp, void * mem, PropDescriptor * d ) { uchar n,i; if( pb_fread(&n,1,1,fp)==0 ) return false; char * store; StoreInt( ((char *)mem)+d->offset2, d->memtype2, int(n)); if(d->alloclist) { store = (char *)calloc(n,sizeof(uint)); assert(store); *(char **)(((char *)mem)+d->offset1) = store; } else store = ((char *)mem)+d->offset1; for(i=0;iformat)==0) return false; *(uint *)(store+i*sizeof(uint)) = uint(c); } return true; } static bool cb_read_list_shfl( GZFILE fp, void * mem, PropDescriptor * d ) { uchar n,i; if( pb_fread(&n,1,1,fp)==0 ) return false; char * store; StoreInt( ((char *)mem)+d->offset2, d->memtype2, int(n)); if(d->alloclist) { store = (char *)calloc(n,sizeof(float)); assert(store); *(char **)(((char *)mem)+d->offset1) = store; } else store = ((char *)mem)+d->offset1; for(i=0;iformat)==0) return false; *(float *)(store+i*sizeof(float)) = float(c); } return true; } static bool cb_read_list_shdo( GZFILE fp, void * mem, PropDescriptor * d ) { uchar n,i; if( pb_fread(&n,1,1,fp)==0 ) return false; char * store; StoreInt( ((char *)mem)+d->offset2, d->memtype2, int(n)); if(d->alloclist) { store = (char *)calloc(n,sizeof(double)); assert(store); *(char **)(((char *)mem)+d->offset1) = store; } else store = ((char *)mem)+d->offset1; for(i=0;iformat)==0) return false; *(double *)(store+i*sizeof(double)) = double(c); } return true; } static bool cb_read_list_inch( GZFILE fp, void * mem, PropDescriptor * d ) { uchar n,i; if( pb_fread(&n,1,1,fp)==0 ) return false; char * store; StoreInt( ((char *)mem)+d->offset2, d->memtype2, int(n)); if(d->alloclist) { store = (char *)calloc(n,sizeof(char)); assert(store); *(char **)(((char *)mem)+d->offset1) = store; } else store = ((char *)mem)+d->offset1; for(i=0;iformat)==0 ) return false; *(char *)(store+i*sizeof(char)) = char(c); } return true; } static bool cb_read_list_insh( GZFILE fp, void * mem, PropDescriptor * d ) { uchar n,i; if( pb_fread(&n,1,1,fp)==0 ) return false; char * store; StoreInt( ((char *)mem)+d->offset2, d->memtype2, int(n)); if(d->alloclist) { store = (char *)calloc(n,sizeof(short)); assert(store); *(char **)(((char *)mem)+d->offset1) = store; } else store = ((char *)mem)+d->offset1; for(i=0;iformat)==0 ) return false; *(short *)(store+i*sizeof(short)) = short(c); } return true; } static bool cb_read_list_inin( GZFILE fp, void * mem, PropDescriptor * d ) { // uchar n,i; prima del 5/9/03 era cosi' // if( pb_fread(&n,1,1,fp)==0 ) return false; int n,i; switch(d->stotype2) { case T_CHAR : { char val; if( ReadCharB(fp,&val,d->format)==0 ) return false; n=val; } break; case T_UCHAR : { uchar val; if( ReadUCharB(fp,&val,d->format)==0 ) return false; n=val; } break; case T_SHORT : { short val; if( ReadShortB(fp,&val,d->format)==0 ) return false; n=val; } break; case T_UINT : { uint val; if( ReadUIntB(fp,&val,d->format)==0 ) return false; n=val; } break; case T_INT : { int val; if( ReadIntB(fp,&val,d->format)==0 ) return false; n=val; } break; default: assert(0); } char * store; StoreInt( ((char *)mem)+d->offset2, d->memtype2, int(n)); if(d->alloclist) { store = (char *)calloc(n,sizeof(int)); assert(store); *(char **)(((char *)mem)+d->offset1) = store; } else store = ((char *)mem)+d->offset1; for(i=0;iformat)==0 ) return false; } return true; } static bool cb_read_list_inuc( GZFILE fp, void * mem, PropDescriptor * d ) { uchar n,i; if( pb_fread(&n,1,1,fp)==0 ) return false; char * store; StoreInt( ((char *)mem)+d->offset2, d->memtype2, int(n)); if(d->alloclist) { store = (char *)calloc(n,sizeof(uchar)); assert(store); *(char **)(((char *)mem)+d->offset1) = store; } else store = ((char *)mem)+d->offset1; for(i=0;iformat)==0 ) return false; *(uchar *)(store+i*sizeof(uchar)) = uchar(c); } return true; } static bool cb_read_list_inus( GZFILE fp, void * mem, PropDescriptor * d ) { uchar n,i; if( pb_fread(&n,1,1,fp)==0 ) return false; char * store; StoreInt( ((char *)mem)+d->offset2, d->memtype2, int(n)); if(d->alloclist) { store = (char *)calloc(n,sizeof(ushort)); assert(store); *(char **)(((char *)mem)+d->offset1) = store; } else store = ((char *)mem)+d->offset1; for(i=0;iformat)==0 ) return false; *(ushort *)(store+i*sizeof(ushort)) = ushort(c); } return true; } static bool cb_read_list_inui( GZFILE fp, void * mem, PropDescriptor * d ) { uchar n,i; if( pb_fread(&n,1,1,fp)==0 ) return false; char * store; StoreInt( ((char *)mem)+d->offset2, d->memtype2, int(n)); if(d->alloclist) { store = (char *)calloc(n,sizeof(uint)); assert(store); *(char **)(((char *)mem)+d->offset1) = store; } else store = ((char *)mem)+d->offset1; for(i=0;iformat)==0 ) return false; *(uint *)(store+i*sizeof(uint)) = uint(c); } return true; } static bool cb_read_list_infl( GZFILE fp, void * mem, PropDescriptor * d ) { uchar n,i; if( pb_fread(&n,1,1,fp)==0 ) return false; char * store; StoreInt( ((char *)mem)+d->offset2, d->memtype2, int(n)); if(d->alloclist) { store = (char *)calloc(n,sizeof(float)); assert(store); *(char **)(((char *)mem)+d->offset1) = store; } else store = ((char *)mem)+d->offset1; for(i=0;iformat)==0 ) return false; *(float *)(store+i*sizeof(float)) = float(c); } return true; } static bool cb_read_list_indo( GZFILE fp, void * mem, PropDescriptor * d ) { uchar n,i; if( pb_fread(&n,1,1,fp)==0 ) return false; char * store; StoreInt( ((char *)mem)+d->offset2, d->memtype2, int(n)); if(d->alloclist) { store = (char *)calloc(n,sizeof(double)); assert(store); *(char **)(((char *)mem)+d->offset1) = store; } else store = ((char *)mem)+d->offset1; for(i=0;iformat)==0 ) return false; *(double *)(store+i*sizeof(double)) = double(c); } return true; } static bool cb_read_list_ucch( GZFILE fp, void * mem, PropDescriptor * d ) { uchar n,i; if( pb_fread(&n,1,1,fp)==0 ) return false; char * store; StoreInt( ((char *)mem)+d->offset2, d->memtype2, int(n)); if(d->alloclist) { store = (char *)calloc(n,sizeof(char)); assert(store); *(char **)(((char *)mem)+d->offset1) = store; } else store = ((char *)mem)+d->offset1; for(i=0;ioffset2, d->memtype2, int(n)); if(d->alloclist) { store = (char *)calloc(n,sizeof(short)); assert(store); *(char **)(((char *)mem)+d->offset1) = store; } else store = ((char *)mem)+d->offset1; for(i=0;ioffset2, d->memtype2, int(n)); if(d->alloclist) { store = (char *)calloc(n,sizeof(int)); assert(store); *(char **)(((char *)mem)+d->offset1) = store; } else store = ((char *)mem)+d->offset1; for(i=0;ioffset2, d->memtype2, int(n)); if(d->alloclist) { store = (char *)calloc(n,sizeof(uchar)); assert(store); *(char **)(((char *)mem)+d->offset1) = store; } else store = ((char *)mem)+d->offset1; for(i=0;ioffset2, d->memtype2, int(n)); if(d->alloclist) { store = (char *)calloc(n,sizeof(ushort)); assert(store); *(char **)(((char *)mem)+d->offset1) = store; } else store = ((char *)mem)+d->offset1; for(i=0;ioffset2, d->memtype2, int(n)); if(d->alloclist) { store = (char *)calloc(n,sizeof(uint)); assert(store); *(char **)(((char *)mem)+d->offset1) = store; } else store = ((char *)mem)+d->offset1; for(i=0;ioffset2, d->memtype2, int(n)); if(d->alloclist) { store = (char *)calloc(n,sizeof(float)); assert(store); *(char **)(((char *)mem)+d->offset1) = store; } else store = ((char *)mem)+d->offset1; for(i=0;ioffset2, d->memtype2, int(n)); if(d->alloclist) { store = (char *)calloc(n,sizeof(double)); assert(store); *(char **)(((char *)mem)+d->offset1) = store; } else store = ((char *)mem)+d->offset1; for(i=0;ioffset2, d->memtype2, int(n)); if(d->alloclist) { store = (char *)calloc(n,sizeof(char)); assert(store); *(char **)(((char *)mem)+d->offset1) = store; } else store = ((char *)mem)+d->offset1; for(i=0;iformat)==0) return false; *(char *)(store+i*sizeof(char)) = char(c); } return true; } static bool cb_read_list_ussh( GZFILE fp, void * mem, PropDescriptor * d ) { uchar n,i; if( pb_fread(&n,1,1,fp)==0 ) return false; char * store; StoreInt( ((char *)mem)+d->offset2, d->memtype2, int(n)); if(d->alloclist) { store = (char *)calloc(n,sizeof(short)); assert(store); *(char **)(((char *)mem)+d->offset1) = store; } else store = ((char *)mem)+d->offset1; for(i=0;iformat)==0) return false; *(short *)(store+i*sizeof(short)) = short(c); } return true; } static bool cb_read_list_usin( GZFILE fp, void * mem, PropDescriptor * d ) { uchar n,i; if( pb_fread(&n,1,1,fp)==0 ) return false; char * store; StoreInt( ((char *)mem)+d->offset2, d->memtype2, int(n)); if(d->alloclist) { store = (char *)calloc(n,sizeof(int)); assert(store); *(char **)(((char *)mem)+d->offset1) = store; } else store = ((char *)mem)+d->offset1; for(i=0;iformat)==0) return false; *(int *)(store+i*sizeof(int)) = int(c); } return true; } static bool cb_read_list_usuc( GZFILE fp, void * mem, PropDescriptor * d ) { uchar n,i; if( pb_fread(&n,1,1,fp)==0 ) return false; char * store; StoreInt( ((char *)mem)+d->offset2, d->memtype2, int(n)); if(d->alloclist) { store = (char *)calloc(n,sizeof(uchar)); assert(store); *(char **)(((char *)mem)+d->offset1) = store; } else store = ((char *)mem)+d->offset1; for(i=0;iformat)==0) return false; *(uchar *)(store+i*sizeof(uchar)) = uchar(c); } return true; } static bool cb_read_list_usus( GZFILE fp, void * mem, PropDescriptor * d ) { uchar n,i; if( pb_fread(&n,1,1,fp)==0 ) return false; char * store; StoreInt( ((char *)mem)+d->offset2, d->memtype2, int(n)); if(d->alloclist) { store = (char *)calloc(n,sizeof(ushort)); assert(store); *(char **)(((char *)mem)+d->offset1) = store; } else store = ((char *)mem)+d->offset1; for(i=0;iformat)==0) return false; *(ushort *)(store+i*sizeof(ushort)) = ushort(c); } return true; } static bool cb_read_list_usui( GZFILE fp, void * mem, PropDescriptor * d ) { uchar n,i; if( pb_fread(&n,1,1,fp)==0 ) return false; char * store; StoreInt( ((char *)mem)+d->offset2, d->memtype2, int(n)); if(d->alloclist) { store = (char *)calloc(n,sizeof(uint)); assert(store); *(char **)(((char *)mem)+d->offset1) = store; } else store = ((char *)mem)+d->offset1; for(i=0;iformat)==0) return false; *(uint *)(store+i*sizeof(uint)) = uint(c); } return true; } static bool cb_read_list_usfl( GZFILE fp, void * mem, PropDescriptor * d ) { uchar n,i; if( pb_fread(&n,1,1,fp)==0 ) return false; char * store; StoreInt( ((char *)mem)+d->offset2, d->memtype2, int(n)); if(d->alloclist) { store = (char *)calloc(n,sizeof(float)); assert(store); *(char **)(((char *)mem)+d->offset1) = store; } else store = ((char *)mem)+d->offset1; for(i=0;iformat)==0) return false; *(float *)(store+i*sizeof(float)) = float(c); } return true; } static bool cb_read_list_usdo( GZFILE fp, void * mem, PropDescriptor * d ) { uchar n,i; if( pb_fread(&n,1,1,fp)==0 ) return false; char * store; StoreInt( ((char *)mem)+d->offset2, d->memtype2, int(n)); if(d->alloclist) { store = (char *)calloc(n,sizeof(double)); assert(store); *(char **)(((char *)mem)+d->offset1) = store; } else store = ((char *)mem)+d->offset1; for(i=0;iformat)==0) return false; *(double *)(store+i*sizeof(double)) = double(c); } return true; } static bool cb_read_list_uich( GZFILE fp, void * mem, PropDescriptor * d ) { uchar n,i; if( pb_fread(&n,1,1,fp)==0 ) return false; char * store; StoreInt( ((char *)mem)+d->offset2, d->memtype2, int(n)); if(d->alloclist) { store = (char *)calloc(n,sizeof(char)); assert(store); *(char **)(((char *)mem)+d->offset1) = store; } else store = ((char *)mem)+d->offset1; for(i=0;iformat)==0 ) return false; *(char *)(store+i*sizeof(char)) = char(c); } return true; } static bool cb_read_list_uish( GZFILE fp, void * mem, PropDescriptor * d ) { uchar n,i; if( pb_fread(&n,1,1,fp)==0 ) return false; char * store; StoreInt( ((char *)mem)+d->offset2, d->memtype2, int(n)); if(d->alloclist) { store = (char *)calloc(n,sizeof(short)); assert(store); *(char **)(((char *)mem)+d->offset1) = store; } else store = ((char *)mem)+d->offset1; for(i=0;iformat)==0 ) return false; *(short *)(store+i*sizeof(short)) = short(c); } return true; } static bool cb_read_list_uiin( GZFILE fp, void * mem, PropDescriptor * d ) { uchar n,i; if( pb_fread(&n,1,1,fp)==0 ) return false; char * store; StoreInt( ((char *)mem)+d->offset2, d->memtype2, int(n)); if(d->alloclist) { store = (char *)calloc(n,sizeof(int)); assert(store); *(char **)(((char *)mem)+d->offset1) = store; } else store = ((char *)mem)+d->offset1; for(i=0;iformat)==0 ) return false; *(int *)(store+i*sizeof(int)) = int(c); } return true; } static bool cb_read_list_uiuc( GZFILE fp, void * mem, PropDescriptor * d ) { uchar n,i; if( pb_fread(&n,1,1,fp)==0 ) return false; char * store; StoreInt( ((char *)mem)+d->offset2, d->memtype2, int(n)); if(d->alloclist) { store = (char *)calloc(n,sizeof(uchar)); assert(store); *(char **)(((char *)mem)+d->offset1) = store; } else store = ((char *)mem)+d->offset1; for(i=0;iformat)==0 ) return false; *(uchar *)(store+i*sizeof(uchar)) = uchar(c); } return true; } static bool cb_read_list_uius( GZFILE fp, void * mem, PropDescriptor * d ) { uchar n,i; if( pb_fread(&n,1,1,fp)==0 ) return false; char * store; StoreInt( ((char *)mem)+d->offset2, d->memtype2, int(n)); if(d->alloclist) { store = (char *)calloc(n,sizeof(ushort)); assert(store); *(char **)(((char *)mem)+d->offset1) = store; } else store = ((char *)mem)+d->offset1; for(i=0;iformat)==0 ) return false; *(ushort *)(store+i*sizeof(ushort)) = ushort(c); } return true; } static bool cb_read_list_uiui( GZFILE fp, void * mem, PropDescriptor * d ) { uchar n,i; if( pb_fread(&n,1,1,fp)==0 ) return false; char * store; StoreInt( ((char *)mem)+d->offset2, d->memtype2, int(n)); if(d->alloclist) { store = (char *)calloc(n,sizeof(uint)); assert(store); *(char **)(((char *)mem)+d->offset1) = store; } else store = ((char *)mem)+d->offset1; for(i=0;iformat)==0 ) return false; *(uint *)(store+i*sizeof(uint)) = uint(c); } return true; } static bool cb_read_list_uifl( GZFILE fp, void * mem, PropDescriptor * d ) { uchar n,i; if( pb_fread(&n,1,1,fp)==0 ) return false; char * store; StoreInt( ((char *)mem)+d->offset2, d->memtype2, int(n)); if(d->alloclist) { store = (char *)calloc(n,sizeof(float)); assert(store); *(char **)(((char *)mem)+d->offset1) = store; } else store = ((char *)mem)+d->offset1; for(i=0;iformat)==0 ) return false; *(float *)(store+i*sizeof(float)) = float(c); } return true; } static bool cb_read_list_uido( GZFILE fp, void * mem, PropDescriptor * d ) { uchar n,i; if( pb_fread(&n,1,1,fp)==0 ) return false; char * store; StoreInt( ((char *)mem)+d->offset2, d->memtype2, int(n)); if(d->alloclist) { store = (char *)calloc(n,sizeof(double)); assert(store); *(char **)(((char *)mem)+d->offset1) = store; } else store = ((char *)mem)+d->offset1; for(i=0;iformat)==0 ) return false; *(double *)(store+i*sizeof(double)) = double(c); } return true; } static bool cb_read_list_flfl( GZFILE fp, void * mem, PropDescriptor * d ) { uchar n,i; if( pb_fread(&n,1,1,fp)==0 ) return false; char * store; StoreInt( ((char *)mem)+d->offset2, d->memtype2, int(n)); if(d->alloclist) { store = (char *)calloc(n,sizeof(float)); assert(store); *(char **)(((char *)mem)+d->offset1) = store; } else store = ((char *)mem)+d->offset1; for(i=0;iformat)==0 ) return false; *(float *)(store+i*sizeof(float)) = float(c); } return true; } static bool cb_read_list_fldo( GZFILE fp, void * mem, PropDescriptor * d ) { uchar n,i; if( pb_fread(&n,1,1,fp)==0 ) return false; char * store; StoreInt( ((char *)mem)+d->offset2, d->memtype2, int(n)); if(d->alloclist) { store = (char *)calloc(n,sizeof(double)); assert(store); *(char **)(((char *)mem)+d->offset1) = store; } else store = ((char *)mem)+d->offset1; for(i=0;iformat)==0 ) return false; *(double *)(store+i*sizeof(double)) = double(c); } return true; } static bool cb_read_list_dofl( GZFILE fp, void * mem, PropDescriptor * d ) { uchar n,i; if( pb_fread(&n,1,1,fp)==0 ) return false; char * store; StoreInt( ((char *)mem)+d->offset2, d->memtype2, int(n)); if(d->alloclist) { store = (char *)calloc(n,sizeof(float)); assert(store); *(char **)(((char *)mem)+d->offset1) = store; } else store = ((char *)mem)+d->offset1; for(i=0;iformat)==0 ) return false; *(float *)(store+i*sizeof(float)) = float(c); } return true; } static bool cb_read_list_dodo( GZFILE fp, void * mem, PropDescriptor * d ) { uchar n,i; if( pb_fread(&n,1,1,fp)==0 ) return false; char * store; StoreInt( ((char *)mem)+d->offset2, d->memtype2, int(n)); if(d->alloclist) { store = (char *)calloc(n,sizeof(double)); assert(store); *(char **)(((char *)mem)+d->offset1) = store; } else store = ((char *)mem)+d->offset1; for(i=0;iformat)==0 ) return false; *(double *)(store+i*sizeof(double)) = double(c); } return true; } void PlyFile::compile( PlyProperty * p ) { p->desc.format = format; // copiatura formato if(format==F_ASCII) { if(p->islist) { if(p->bestored) p->cb = cb_read_list_ascii; else p->cb = cb_skip_list_ascii; } else { if(p->bestored) { p->cb = cb_read_ascii; } else { switch(p->tipo) { case T_CHAR: case T_SHORT: case T_INT: case T_UCHAR: case T_USHORT: case T_UINT: p->cb = cb_skip_int_ascii; break; case T_FLOAT: case T_DOUBLE: p->cb = cb_skip_float_ascii; break; default: p->cb = 0; assert(0); break; } } } } else { if(p->islist) { if(p->bestored) { switch(p->desc.stotype1) { case T_CHAR: //================== Lettura char switch(p->desc.memtype1) { case T_CHAR: p->cb = cb_read_list_chch; break; case T_SHORT: p->cb = cb_read_list_chsh; break; case T_INT: p->cb = cb_read_list_chin; break; case T_UCHAR: p->cb = cb_read_list_chuc; break; case T_USHORT: p->cb = cb_read_list_chus; break; case T_UINT: p->cb = cb_read_list_chui; break; case T_FLOAT: p->cb = cb_read_list_chfl; break; case T_DOUBLE: p->cb = cb_read_list_chdo; break; default: assert(0); } break; case T_SHORT: //================== Lettura short switch(p->desc.memtype1) { case T_CHAR: p->cb = cb_read_list_shch; break; case T_SHORT: p->cb = cb_read_list_shsh; break; case T_INT: p->cb = cb_read_list_shin; break; case T_UCHAR: p->cb = cb_read_list_shuc; break; case T_USHORT: p->cb = cb_read_list_shus; break; case T_UINT: p->cb = cb_read_list_shui; break; case T_FLOAT: p->cb = cb_read_list_shfl; break; case T_DOUBLE: p->cb = cb_read_list_shdo; break; default: assert(0); } break; case T_INT: //================== Lettura int switch(p->desc.memtype1) { case T_CHAR: p->cb = cb_read_list_inch; break; case T_SHORT: p->cb = cb_read_list_insh; break; case T_INT: p->cb = cb_read_list_inin; break; case T_UCHAR: p->cb = cb_read_list_inuc; break; case T_USHORT: p->cb = cb_read_list_inus; break; case T_UINT: p->cb = cb_read_list_inui; break; case T_FLOAT: p->cb = cb_read_list_infl; break; case T_DOUBLE: p->cb = cb_read_list_indo; break; default: assert(0); } break; case T_UCHAR: //================== Lettura uchar switch(p->desc.memtype1) { case T_CHAR: p->cb = cb_read_list_ucch; break; case T_SHORT: p->cb = cb_read_list_ucsh; break; case T_INT: p->cb = cb_read_list_ucin; break; case T_UCHAR: p->cb = cb_read_list_ucuc; break; case T_USHORT: p->cb = cb_read_list_ucus; break; case T_UINT: p->cb = cb_read_list_ucui; break; case T_FLOAT: p->cb = cb_read_list_ucfl; break; case T_DOUBLE: p->cb = cb_read_list_ucdo; break; default: assert(0); } break; case T_USHORT: //================== Lettura ushort switch(p->desc.memtype1) { case T_CHAR: p->cb = cb_read_list_usch; break; case T_SHORT: p->cb = cb_read_list_ussh; break; case T_INT: p->cb = cb_read_list_usin; break; case T_UCHAR: p->cb = cb_read_list_usuc; break; case T_USHORT: p->cb = cb_read_list_usus; break; case T_UINT: p->cb = cb_read_list_usui; break; case T_FLOAT: p->cb = cb_read_list_usfl; break; case T_DOUBLE: p->cb = cb_read_list_usdo; break; default: assert(0); } break; case T_UINT: //================== Lettura uint switch(p->desc.memtype1) { case T_CHAR: p->cb = cb_read_list_uich; break; case T_SHORT: p->cb = cb_read_list_uish; break; case T_INT: p->cb = cb_read_list_uiin; break; case T_UCHAR: p->cb = cb_read_list_uiuc; break; case T_USHORT: p->cb = cb_read_list_uius; break; case T_UINT: p->cb = cb_read_list_uiui; break; case T_FLOAT: p->cb = cb_read_list_uifl; break; case T_DOUBLE: p->cb = cb_read_list_uido; break; default: assert(0); } break; case T_FLOAT: //================== Lettura float switch(p->desc.memtype1) { case T_FLOAT: p->cb = cb_read_list_flfl; break; case T_DOUBLE: p->cb = cb_read_list_fldo; break; default: assert(0); } break; case T_DOUBLE: //================== Lettura double switch(p->desc.memtype1) { case T_FLOAT: p->cb = cb_read_list_dofl; break; case T_DOUBLE: p->cb = cb_read_list_dodo; break; default: assert(0); } break; default: assert(0); } } else { switch(TypeSize[p->tipo]) { case 1: p->cb = cb_skip_list_bin1; break; case 2: p->cb = cb_skip_list_bin2; break; case 4: p->cb = cb_skip_list_bin4; break; case 8: p->cb = cb_skip_list_bin4; break; default:p->cb = 0; assert(0); break; } } } else { if(p->bestored) { switch(p->desc.stotype1) { case T_CHAR: //================== Lettura char switch(p->desc.memtype1) { case T_CHAR: p->cb = cb_read_chch; break; case T_SHORT: p->cb = cb_read_chsh; break; case T_INT: p->cb = cb_read_chin; break; case T_UCHAR: p->cb = cb_read_chuc; break; case T_USHORT: p->cb = cb_read_chus; break; case T_UINT: p->cb = cb_read_chui; break; case T_FLOAT: p->cb = cb_read_chfl; break; case T_DOUBLE: p->cb = cb_read_chdo; break; default: assert(0); } break; case T_SHORT: //================== Lettura short switch(p->desc.memtype1) { case T_CHAR: p->cb = cb_read_shch; break; case T_SHORT: p->cb = cb_read_shsh; break; case T_INT: p->cb = cb_read_shin; break; case T_UCHAR: p->cb = cb_read_shuc; break; case T_USHORT: p->cb = cb_read_shus; break; case T_UINT: p->cb = cb_read_shui; break; case T_FLOAT: p->cb = cb_read_shfl; break; case T_DOUBLE: p->cb = cb_read_shdo; break; default: assert(0); } break; case T_INT: //================== Lettura int switch(p->desc.memtype1) { case T_CHAR: p->cb = cb_read_inch; break; case T_SHORT: p->cb = cb_read_insh; break; case T_INT: p->cb = cb_read_inin; break; case T_UCHAR: p->cb = cb_read_inuc; break; case T_USHORT: p->cb = cb_read_inus; break; case T_UINT: p->cb = cb_read_inui; break; case T_FLOAT: p->cb = cb_read_infl; break; case T_DOUBLE: p->cb = cb_read_indo; break; default: assert(0); } break; case T_UCHAR: //================== Lettura uchar switch(p->desc.memtype1) { case T_CHAR: p->cb = cb_read_ucch; break; case T_SHORT: p->cb = cb_read_ucsh; break; case T_INT: p->cb = cb_read_ucin; break; case T_UCHAR: p->cb = cb_read_ucuc; break; case T_USHORT: p->cb = cb_read_ucus; break; case T_UINT: p->cb = cb_read_ucui; break; case T_FLOAT: p->cb = cb_read_ucfl; break; case T_DOUBLE: p->cb = cb_read_ucdo; break; default: assert(0); } break; case T_USHORT: //================== Lettura ushort switch(p->desc.memtype1) { case T_CHAR: p->cb = cb_read_usch; break; case T_SHORT: p->cb = cb_read_ussh; break; case T_INT: p->cb = cb_read_usin; break; case T_UCHAR: p->cb = cb_read_usuc; break; case T_USHORT: p->cb = cb_read_usus; break; case T_UINT: p->cb = cb_read_usui; break; case T_FLOAT: p->cb = cb_read_usfl; break; case T_DOUBLE: p->cb = cb_read_usdo; break; default: assert(0); } break; case T_UINT: //================== Lettura uint switch(p->desc.memtype1) { case T_CHAR: p->cb = cb_read_uich; break; case T_SHORT: p->cb = cb_read_uish; break; case T_INT: p->cb = cb_read_uiin; break; case T_UCHAR: p->cb = cb_read_uiuc; break; case T_USHORT: p->cb = cb_read_uius; break; case T_UINT: p->cb = cb_read_uiui; break; case T_FLOAT: p->cb = cb_read_uifl; break; case T_DOUBLE: p->cb = cb_read_uido; break; default: assert(0); } break; case T_FLOAT: //================== Lettura float switch(p->desc.memtype1) { case T_FLOAT: p->cb = cb_read_flfl; break; case T_DOUBLE: p->cb = cb_read_fldo; break; default: assert(0); } break; case T_DOUBLE: //================== Lettura double switch(p->desc.memtype1) { case T_FLOAT: p->cb = cb_read_dofl; break; case T_DOUBLE: p->cb = cb_read_dodo; break; default: assert(0); } break; default: assert(0); } } else { switch(TypeSize[p->tipo]) { case 1: p->cb = cb_skip_bin1; break; case 2: p->cb = cb_skip_bin2; break; case 4: p->cb = cb_skip_bin4; break; case 8: p->cb = cb_skip_bin8; break; default:p->cb = 0; assert(0); break; } } } } } void PlyFile::compile( PlyElement * e ) { vector::iterator i; for(i=e->props.begin();i!=e->props.end();++i) compile(&*i); } // Funzioni statiche per la lettura di un elemento int ReadBin ( XFILE * fp, const PlyProperty * pr, void * mem, int fmt ) { assert(pr); // Lettura di una lista if(pr->islist) { int i,n; if( !ReadScalarB(fp,&n,pr->tipoindex, T_INT, fmt) ) return 0; assert(n<12); // Valore abbastanza aleatorio // Lettura con memorizzazione if(pr->bestored) { char * store; StoreInt( ((char *)mem)+pr->desc.offset2, pr->desc.memtype2, n); // Determinazione memoria vettore if(pr->desc.alloclist) { store = (char *)calloc(n,TypeSize[pr->desc.memtype1]); assert(store); *(char **)(((char *)mem)+pr->desc.offset1) = store; } else { store = ((char *)mem)+pr->desc.offset1; } for(i=0;idesc.memtype1], pr->desc.stotype1, pr->desc.memtype1, fmt ) ) return 0; } } // Lettura senza memorizzazione else { for(i=0;itipo) ) return 0; } } // Lettura di uno scalare else { // Lettura con memorizzazione if(pr->bestored) return ReadScalarB( fp, ((char *)mem)+pr->desc.offset1, pr->desc.stotype1, pr->desc.memtype1, fmt ); // Lettura senza memorizzazione else return SkipScalarB(fp,pr->tipo); } return 1; } int ReadAscii( XFILE * fp, const PlyProperty * pr, void * mem, int /*fmt*/ ) { assert(pr); assert(mem); // Lettura di una lista if(pr->islist) { int i,n; if( !ReadScalarA(fp,&n,pr->tipoindex, T_INT) ) return 0; assert(n<12); // Valore abbastanza aleatorio // Lettura con memorizzazione if(pr->bestored) { char * store; StoreInt( ((char *)mem)+pr->desc.offset2, pr->desc.memtype2, n); // Determinazione memoria vettore if(pr->desc.alloclist) { store = (char *)calloc(n,TypeSize[pr->desc.memtype1]); assert(store); *(char **)(((char *)mem)+pr->desc.offset1) = store; } else { store = ((char *)mem)+pr->desc.offset1; } for(i=0;idesc.memtype1], pr->desc.stotype1, pr->desc.memtype1 ) ) return 0; } } // Lettura senza memorizzazione else { for(i=0;itipo) ) return 0; } } // Lettura scalare else { // Lettura con memorizzazione if(pr->bestored) return ReadScalarA( fp, ((char *)mem)+pr->desc.offset1, pr->desc.stotype1, pr->desc.memtype1 ); // Lettura senza memorizzazione else return SkipScalarA(fp,pr->tipo); } return 1; } // Finally! the main function int PlyFile::Read( void * mem ) { assert(cure); assert(ReadCB); vector::iterator i; for(i=cure->props.begin();i!=cure->props.end();++i) { if( ! i->cb(gzfp,mem,&(i->desc)) ) return -1; /* int r = ReadCB(gzfp,i,mem,format); if(!r) return -1; */ } return 0; } void interpret_texture_name(const char*a, const char*fn, char*output){ int ia=0,io=0; output[0]=0; while (a[ia]!=0){ if (a[ia]=='<') { if (static_cast(strlen(a)) > ia+5) { if ( ( (a[ia+1]=='t') || (a[ia+1]=='T') ) && ( (a[ia+2]=='h') || (a[ia+2]=='H') ) && ( (a[ia+3]=='i') || (a[ia+3]=='I') ) && ( (a[ia+4]=='s') || (a[ia+4]=='S') ) && ( a[ia+5]=='>' ) ) { // substitute "" with filename: // 1) remove path from filename int lastbar=0; int ifn=0; while (fn[ifn]!=0) { if ((fn[ifn]=='/') || (fn[ifn]=='\\')) lastbar=ifn+1; ifn++;} ifn=lastbar; char fn2[255]; while (fn[ifn]!=0) { fn2[ifn-lastbar]=fn[ifn]; ifn++;} fn2[ifn-lastbar]=0; // 2) remove ".ply" extention from filename int l=ifn-lastbar; if ((fn2[l-4]=='.') && ((fn2[l-3]=='P') || (fn2[l-3]=='p')) && ((fn2[l-2]=='L') || (fn2[l-2]=='l')) && ((fn2[l-1]=='Y') || (fn2[l-1]=='y')) ) fn2[l-4]=0; // 3) append output[io]=0; sprintf(output,"%s%s",output,fn2); io=strlen(output); ia+=6; //skip the "" continue; }; } } output[io++]=a[ia++]; }; output[io]=0; }; } } �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������qutemol/vcg/wrap/ply/plystuff.h���������������������������������������������������������������������0000444�0001750�0001750�00000023743�10746075566�015234� 0����������������������������������������������������������������������������������������������������ustar �mba�����������������������������mba��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������/**************************************************************************** * VCGLib o o * * Visual and Computer Graphics Library o o * * _ O _ * * Copyright(C) 2004 \/)\/ * * Visual Computing Lab /\/| * * ISTI - Italian National Research Council | * * \ * * All rights reserved. * * * * 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. * * * * 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 (http://www.gnu.org/licenses/gpl.txt) * * for more details. * * * ****************************************************************************/ /**************************************************************************** Acknowlegments Portions of this file were based on the original code of the Ply library of Greg Turk and on the work of Claudio Rocchini ****************************************************************************/ /**************************************************************************** History $Log: plystuff.h,v $ Revision 1.7 2008/01/24 11:50:14 cignoni solved slash backslash issue in vcg_cache Revision 1.6 2007/06/25 15:24:00 cignoni removed a possibly useless static kw Revision 1.5 2006/04/11 09:48:04 zifnab1974 changes needed for compilation on linux 64b with gcc 3.4.5 Revision 1.4 2005/12/02 00:00:53 cignoni Moved and corrected interpret_texture_name from plystuff.h to plylib.cpp Revision 1.3 2005/03/18 00:14:40 cignoni removed small gcc compiling issues Revision 1.2 2005/03/15 11:46:52 cignoni Cleaning of the automatic bbox caching support for ply files. First working version. */ //****************** Gestione cache ***************** #ifndef __VCG_PLYLIB_STUFF #define __VCG_PLYLIB_STUFF #include #include #include #ifdef WIN32 #include #endif #include #include using namespace vcg; #ifdef WIN32 #include #define pb_mkdir(n) _mkdir(n) #define pb_access _access #define pb_stat _stat #define pb_fstat _fstat #define pb_open _open #define pb_close _close #define DIR_SEP "\\" #else #define pb_mkdir(n) mkdir(n,0755) #define pb_access access #define pb_stat stat #define pb_fstat fstat #define pb_open open #define pb_close close #define _O_BINARY 0 // Does not exist on Unix #define _O_RDONLY O_RDONLY #define DIR_SEP "/" #endif namespace vcg { namespace ply { const int MAXBPATH = 256; // Stringhe per la cache const char * cachedir = "vcg_cache"; const char * bboxcacheext = ".bbox_cache"; const char * bboxheader = "BBOXCACH"; bool GetDirFromPath( const char * path, char * dir, char * name ) { strcpy(dir,path); char * p; p = strrchr(dir,'\\'); if(p==0) p=strrchr(dir,'/'); if(p==0) { dir[0] = 0; strcpy(name,path); } else { strcpy(name,p+1); *p = 0; } return true; } static bool CheckCacheDirectory( const char * dir ) { if( pb_access(dir,0)!=0 ) { if( pb_mkdir(dir)==-1 ) return false; } return true; } bool CheckCacheTime( const char * fname, const char * cname ) { if( pb_access(fname,4)==-1 ) return false; if( pb_access(cname,4)==-1 ) return false; int h,r; struct pb_stat st; time_t ft,bt; h = pb_open(fname,_O_BINARY|_O_RDONLY); if(h==0) return false; r = pb_fstat(h,&st); pb_close(h); if(r==-1) return false; ft = st.st_mtime; h = pb_open(cname,_O_BINARY|_O_RDONLY); if(h==0) return false; r = pb_fstat(h,&st); //_read(h,&box,sizeof(box)); pb_close(h); if(r==-1) return false; bt = st.st_mtime; if( difftime(bt,ft)>=0 ) return true; else return false; } // restituisce true se il file con la cache del bbox della mesh e' piu' recente del file ply // se fname2 != 0, allora deve essere piu recente anche di fname2. static bool CheckBBoxCache( const char * fname, Box3d & box, const char *fname2=0 ) { char d[MAXBPATH]; char n[MAXBPATH]; char h[8]; // Estrazione dati if( ! GetDirFromPath(fname,d,n) ) return false; // Controllo esistenza directory delle cache if(d[0]!=0) strcat(d,DIR_SEP); strcat(d,cachedir); if( !CheckCacheDirectory(d) ) return false; // Controllo esistenza e data file cache strcat(d,DIR_SEP); strcat(d,n); strcat(d,bboxcacheext); if( CheckCacheTime(fname,d) && (fname2==0 || CheckCacheTime(fname2,d)) ) { // Lettura bbox e controllo FILE * fp = fopen(d,"rb"); if(fp==0) return false; if( fread(h,1,8,fp)!=8 ) { fclose(fp); return false; } if( fread(&box,sizeof(Box3d),1,fp)!=1 ) { fclose(fp); return false; } fclose(fp); if( strncmp(h,bboxheader,8) ) return false; else return true; } else return false; } bool GetCacheName( const char * fname, const char * ext_name, char * cname ) { static char n[MAXBPATH]; // Estrazione dati if( ! GetDirFromPath(fname,cname,n) ) return false; // Controllo esistenza directory delle cache if(cname[0]!=0) strcat(cname,DIR_SEP); strcat(cname,cachedir); if( !CheckCacheDirectory(cname) ) return false; strcat(cname,DIR_SEP); strcat(cname,n); strcat(cname,ext_name); return true; } static bool SaveBBoxCache( const char * fname, const Box3d & box ) { char d[MAXBPATH]; if( !GetCacheName(fname,bboxcacheext,d) ) return false; // Lettura bbox e controllo FILE * fp = fopen(d,"wb"); if(fp==0) return false; if( fwrite(bboxheader,1,8,fp)!=8 ) { fclose(fp); return false; } if( fwrite(&box,sizeof(Box3d),1,fp)!=1 ) { fclose(fp); return false; } fclose(fp); return true; } struct PlyPoint3d { double x; double y; double z; }; // Calcola il bbox di un file ply bool ScanBBox( const char * fname, Box3d & box, bool use_cache=true ) { if(use_cache) { if( CheckBBoxCache(fname,box) ) return true; } static const PropDescriptor pv[3]= { {"vertex","x",T_FLOAT,T_DOUBLE,offsetof(PlyPoint3d,x),0,0,0,0,0 ,0}, // TO GET RID OF COMPILER WARNING I ADDED 0 TO INITIALIZE format (MV) {"vertex","y",T_FLOAT,T_DOUBLE,offsetof(PlyPoint3d,y),0,0,0,0,0 ,0}, // TO GET RID OF COMPILER WARNING I ADDED 0 TO INITIALIZE format (MV) {"vertex","z",T_FLOAT,T_DOUBLE,offsetof(PlyPoint3d,z),0,0,0,0,0, 0},// TO GET RID OF COMPILER WARNING I ADDED 0 TO INITIALIZE format (MV) }; PlyFile pf; if( pf.Open(fname,PlyFile::MODE_READ)==-1 ) { fprintf(stderr,"Warning: File %s not found\n",fname); return false; } if( pf.AddToRead(pv[0])==-1 ) { fprintf(stderr,"Warning: Read error\n"); return false; } if( pf.AddToRead(pv[1])==-1 ) { fprintf(stderr,"Warning: Read error\n"); return false; } if( pf.AddToRead(pv[2])==-1 ) { fprintf(stderr,"Warning: Read error\n"); return false; } box.SetNull(); char dummyspace[1024]; // sperando basti... for(int i=0;i class checkGLError { public: static QString makeString(const char* m) { QString message(m); switch(glGetError()) { case GL_NO_ERROR: return QString(); case GL_INVALID_ENUM: message+=(": invalid enum"); break; case GL_INVALID_VALUE: message+=(": invalid value"); break; case GL_INVALID_OPERATION: message+=(": invalid operation"); break; case GL_STACK_OVERFLOW: message+=(": stack overflow"); break; case GL_STACK_UNDERFLOW: message+=(": stack underflow"); break; case GL_OUT_OF_MEMORY: message+=(": out of memory"); break; } return message; } static void qDebug(const char* m) { QString message=makeString(m); if(message.isEmpty()) return; ::qDebug(qPrintable(message)); } static void QMessageBox(const char* m, const char* title) { QString message=makeString(m); QMessageBox::warning(0, title,message); } static void QMessageBox(const char* m) {QMessageBox(m,"GL error");}; }; �����qutemol/vcg/wrap/io_tetramesh/����������������������������������������������������������������������0000755�0001750�0001750�00000000000�11633404241�015035� 5����������������������������������������������������������������������������������������������������ustar �mba�����������������������������mba��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������qutemol/vcg/wrap/io_tetramesh/import_ts.h�����������������������������������������������������������0000444�0001750�0001750�00000004021�10620143704�017220� 0����������������������������������������������������������������������������������������������������ustar �mba�����������������������������mba��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������#ifndef __VCGLIB_IMPORTERTS #define __VCGLIB_IMPORTERTS #define NULL 0 #include #include namespace vcg { namespace tetra { namespace io { template class ImporterTS{ typedef MESHTYPE Tetramesh; typedef typename Tetramesh::VertexPointer VertexPointer; typedef typename Tetramesh::VertexType VertexType; typedef typename Tetramesh::TetraType FaceType; typedef typename Tetramesh::VertexIterator VertexIterator; typedef typename Tetramesh::TetraIterator FaceIterator; typedef typename Tetramesh::ScalarType ScalarType; typedef Point3 Point3x; static FILE *& F(){static FILE * f; return f;} inline static void ReadPos( Point3 &p){ fscanf(F(),"%lg %lg %lg",&p[0],&p[1],&p[2]); } inline static void ReadPos( Point3 &p){ fscanf(F(),"%f %f %f",&p[0],&p[1],&p[2]); } inline static void ReadPos( Point4 &p){ fscanf(F(),"%g %g %g %g",&p[0],&p[1],&p[2],&p[3]); } public: static int Open( Tetramesh & m, const char * filename ) { int nvertex; int ntetra; int tp0; int tp1; int tp2; int tp3; typename Tetramesh::VertexType p1; F() = fopen(filename,"r"); if(F() == NULL ) { printf( "The file was not opened\n" ); return -1; } else { fscanf(F(), "%i", &nvertex ); fscanf(F(), "%i", &ntetra ); m.tetra.reserve(ntetra); m.vert.reserve(nvertex); int j; for (j=0;j #include namespace vcg { namespace tetra { namespace io { /** Additional data needed or useful for parsing a ply mesh. This class can be passed to the ImporterPLY::Open() function for - retrieving additional per-vertex per-tetra data - specifying a callback for long ply parsing - knowing what data is contained in a ply file */ class PlyInfo { public: typedef ::vcg::ply::PropDescriptor PropDescriptor ; PlyInfo() { status=0; mask=0; cb=0; vdn=fdn=0; VertexData=TetraData=0; } /// Store the error codes enconutered when parsing a ply int status; /// It returns a bit mask describing the field preesnt in the ply file int mask; /// a Simple callback that can be used for long ply parsing. // it returns the current position, and formats a string with a description of what th efunction is doing (loading vertexes, faces...) CallBackPos *cb; /// the number of per-vertex descriptor (usually 0) int vdn; /// The additional vertex descriptor that a user can specify to load additional per-vertex non-standard data stored in a ply PropDescriptor *VertexData; /// the number of per-face descriptor (usually 0) int fdn; /// The additional vertex descriptor that a user can specify to load additional per-face non-standard data stored in a ply PropDescriptor *TetraData; /// a string containing the current ply header. Useful for showing it to the user. std::string header; enum Error { // Funzioni superiori E_NO_VERTEX, // 14 E_NO_FACE, // 15 E_SHORTFILE, // 16 E_NO_3VERTINFACE, // 17 E_BAD_VERT_INDEX, // 18 E_NO_6TCOORD, // 19 E_DIFFER_COLORS, // 20 }; }; // end class } // end namespace tri } // end namespace io } // end namespace vcg #endif �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������qutemol/vcg/wrap/io_tetramesh/export_ply.h����������������������������������������������������������0000444�0001750�0001750�00000043262�10057622260�017422� 0����������������������������������������������������������������������������������������������������ustar �mba�����������������������������mba��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������/**************************************************************************** * VCGLib o o * * Visual and Computer Graphics Library o o * * _ O _ * * Copyright(C) 2004 \/)\/ * * Visual Computing Lab /\/| * * ISTI - Italian National Research Council | * * \ * * All rights reserved. * * * * 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. * * * * 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 (http://www.gnu.org/licenses/gpl.txt) * * for more details. * * * ****************************************************************************/ /**************************************************************************** History $Log: export_ply.h,v $ Revision 1.1 2004/06/03 13:16:32 ganovelli created ****************************************************************************/ /** @name Load and Save in Ply format */ //@{ #ifndef __VCGLIB_TETRAEXPORT_PLY #define __VCGLIB_TETRAEXPORT_PLY #include #include #include namespace vcg { namespace tetra { namespace io { template class ExporterPLY { // Si occupa di convertire da un tipo all'altro. // usata nella saveply per matchare i tipi tra stotype e memtype. // Ad es se in memoria c'e' un int e voglio salvare un float // src sara in effetti un puntatore a int il cui valore deve // essere convertito al tipo di ritorno desiderato (stotype) template static void PlyConv(int mem_type, void *src, StoType &dest) { switch (mem_type){ case ply::T_FLOAT : dest = (StoType) (* ((float *) src)); break; case ply::T_DOUBLE: dest = (StoType) (* ((double *) src)); break; case ply::T_INT : dest = (StoType) (* ((int *) src)); break; case ply::T_SHORT : dest = (StoType) (* ((short *) src)); break; case ply::T_CHAR : dest = (StoType) (* ((char *) src)); break; case ply::T_UCHAR : dest = (StoType) (* ((unsigned char *)src)); break; default : assert(0); } } public: typedef ::vcg::ply::PropDescriptor PropDescriptor ; typedef typename SaveMeshType::VertexPointer VertexPointer; typedef typename SaveMeshType::ScalarType ScalarType; typedef typename SaveMeshType::VertexType VertexType; typedef typename SaveMeshType::TetraType TetraType; typedef typename SaveMeshType::TetraPointer TetraPointer; typedef typename SaveMeshType::VertexIterator VertexIterator; typedef typename SaveMeshType::TetraIterator TetraIterator; static bool Save(SaveMeshType &m, const char * filename, bool binary=true) { PlyInfo pi; return Save(m,filename,binary,pi); } static bool Save(SaveMeshType &m, const char * filename, int savemask ) { PlyInfo pi; pi.mask=savemask; return Save(m,filename,true,pi); } static bool Save(SaveMeshType &m, const char * filename, bool binary, PlyInfo &pi ) // V1.0 { FILE * fpout; int i; const char * hbin = "binary_little_endian"; const char * hasc = "ascii"; const char * h; bool multit = false; if(binary) h=hbin; else h=hasc; fpout = fopen(filename,"wb"); if(fpout==NULL) { pi.status=::vcg::ply::E_CANTOPEN; return false; } fprintf(fpout, "ply\n" "format %s 1.0\n" "comment VCGLIB generated\n" ,h ); //if( pi.mask & ply::PLYMask::PM_WEDGTEXCOORD ) //{ // //const char * TFILE = "TextureFile"; // //for(i=0;i1 && (HasPerWedgeTexture() || HasPerVertexTexture())) multit = true; //} //if( (pi.mask & PLYMask::PM_CAMERA) && camera.IsValid() ) /*{ fprintf(fpout, "element camera 1\n" "property float view_px\n" "property float view_py\n" "property float view_pz\n" "property float x_axisx\n" "property float x_axisy\n" "property float x_axisz\n" "property float y_axisx\n" "property float y_axisy\n" "property float y_axisz\n" "property float z_axisx\n" "property float z_axisy\n" "property float z_axisz\n" "property float focal\n" "property float scalex\n" "property float scaley\n" "property float centerx\n" "property float centery\n" "property int viewportx\n" "property int viewporty\n" "property float k1\n" "property float k2\n" "property float k3\n" "property float k4\n" ); }*/ fprintf(fpout, "element vertex %d\n" "property float x\n" "property float y\n" "property float z\n" ,m.vn ); if( pi.mask & ply::PLYMask::PM_VERTFLAGS ) { fprintf(fpout, "property int flags\n" ); } if( m.HasPerVertexColor() && (pi.mask & ply::PLYMask::PM_VERTCOLOR) ) { fprintf(fpout, "property uchar red\n" "property uchar green\n" "property uchar blue\n" "property uchar alpha\n" ); } if( m.HasPerVertexQuality() && (pi.mask & ply::PLYMask::PM_VERTQUALITY) ) { fprintf(fpout, "property float quality\n" ); } for(i=0;i FlagV; VertexPointer vp; VertexIterator vi; for(j=0,vi=m.vert.begin();vi!=m.vert.end();++vi) { vp=&(*vi); FlagV.push_back(vp->UberFlags()); // Salva in ogni caso flag del vertice if( ! vp->IsD() ) { if(binary) { float t; t = float(vp->UberP()[0]); fwrite(&t,sizeof(float),1,fpout); t = float(vp->UberP()[1]); fwrite(&t,sizeof(float),1,fpout); t = float(vp->UberP()[2]); fwrite(&t,sizeof(float),1,fpout); if( pi.mask & ply::PLYMask::PM_VERTFLAGS ) fwrite(&(vp->UberFlags()),sizeof(int),1,fpout); if( m.HasPerVertexColor() && (pi.mask & ply::PLYMask::PM_VERTCOLOR) ) fwrite(&( vp->C() ),sizeof(char),4,fpout); if( m.HasPerVertexQuality() && (pi.mask & ply::PLYMask::PM_VERTQUALITY) ) fwrite(&( vp->Q() ),sizeof(float),1,fpout); for(i=0;iP()[0],vp->P()[1],vp->P()[2]); if( pi.mask & ply::PLYMask::PM_VERTFLAGS ) fprintf(fpout,"%d ",vp->UberFlags()); if( m.HasPerVertexColor() && (pi.mask & ply::PLYMask::PM_VERTCOLOR) ) fprintf(fpout,"%d %d %d %d ",vp->C()[0],vp->C()[1],vp->C()[2],vp->C()[3] ); if( m.HasPerVertexQuality() && (pi.mask & ply::PLYMask::PM_VERTQUALITY) ) fprintf(fpout,"%g ",vp->Q()); for(i=0;iUberFlags()=j; // Trucco! Nascondi nei flags l'indice del vertice non deletato! j++; } } assert(j==m.vn); char c = 4; unsigned char b9 = 9; unsigned char b6 = 6; TetraPointer fp; int vv[4]; TetraIterator fi; int fcnt=0; for(j=0,fi=m.tetra.begin();fi!=m.tetra.end();++fi) { fp=&(*fi); if( ! fp->IsD() ) { fcnt++; if(binary) { vv[0]=fp->cV(0)->UberFlags(); vv[1]=fp->cV(1)->UberFlags(); vv[2]=fp->cV(2)->UberFlags(); vv[3]=fp->cV(2)->UberFlags(); fwrite(&c,1,1,fpout); fwrite(vv,sizeof(int),4,fpout); if( pi.mask & ply::PLYMask::PM_TETRAFLAGS ) fwrite(&(fp->Flags()),sizeof(int),1,fpout); if( m.HasPerVertexTexture() && (pi.mask & ply::PLYMask::PM_VERTTEXCOORD) ) { fwrite(&b6,sizeof(char),1,fpout); float t[6]; for(int k=0;k<4;++k) { t[k*2+0] = fp->V(k)->T().u(); t[k*2+1] = fp->V(k)->T().v(); } fwrite(t,sizeof(float),6,fpout); } //else if( m.HasPerWedgeTexture() && (pi.mask & ply::PLYMask::PM_WEDGTEXCOORD) ) //{ // fwrite(&b6,sizeof(char),1,fpout); // float t[6]; // for(int k=0;k<3;++k) // { // t[k*2+0] = fp->WT(k).u(); // t[k*2+1] = fp->WT(k).v(); // } // fwrite(t,sizeof(float),6,fpout); //} /* if(multit) { int t = fp->WT(0).n(); fwrite(&t,sizeof(int),1,fpout); } if( m.HasPerTetraColor() && (pi.mask & ply::PLYMask::PM_TETRACOLOR) ) fwrite(&( fp->C() ),sizeof(char),4,fpout);*/ //if( m.HasPerWedgeColor() && (pi.mask & ply::PLYMask::PM_WEDGCOLOR) ) //{ // fwrite(&b9,sizeof(char),1,fpout); // float t[3]; // for(int z=0;z<3;++z) // { // t[0] = float(fp->WC(z)[0])/255; // t[1] = float(fp->WC(z)[1])/255; // t[2] = float(fp->WC(z)[2])/255; // fwrite( t,sizeof(float),3,fpout); // } //} if( TetraType::HasTetraQuality() && (pi.mask & ply::PLYMask::PM_TETRAQUALITY) ) fwrite( &(fp->Q()),sizeof(float),1,fpout); for(i=0;icV(0)->UberFlags(), fp->cV(1)->UberFlags(), fp->cV(2)->UberFlags() ); if( pi.mask & ply::PLYMask::PM_TETRAFLAGS ) fprintf(fpout,"%d ",fp->Flags()); if( m.HasPerVertexTexture() && (pi.mask & ply::PLYMask::PM_VERTTEXCOORD) ) { fprintf(fpout,"6 "); for(int k=0;k<4;++k) fprintf(fpout,"%g %g " ,fp->V(k)->T().u() ,fp->V(k)->T().v() ); } //else if( m.HasPerWedgeTexture() && (pi.mask & ply::PLYMask::PM_WEDGTEXCOORD) ) //{ // fprintf(fpout,"6 "); // for(int k=0;k<3;++k) // fprintf(fpout,"%g %g " // ,fp->WT(k).u() // ,fp->WT(k).v() // ); //} /* if(multit) { fprintf(fpout,"%d ",fp->WT(0).n()); }*/ if( TetraType::HasTetraColor() && (pi.mask & ply::PLYMask::PM_TETRACOLOR) ) { float t[3]; t[0] = float(fp->C()[0])/255; t[1] = float(fp->C()[1])/255; t[2] = float(fp->C()[2])/255; fprintf(fpout,"9 "); fprintf(fpout,"%g %g %g ",t[0],t[1],t[2]); fprintf(fpout,"%g %g %g ",t[0],t[1],t[2]); fprintf(fpout,"%g %g %g ",t[0],t[1],t[2]); } //else if( m.HasPerWedgeColor() && (pi.mask & ply::PLYMask::PM_WEDGCOLOR) ) //{ // fprintf(fpout,"9 "); // for(int z=0;z<3;++z) // fprintf(fpout,"%g %g %g " // ,double(fp->WC(z)[0])/255 // ,double(fp->WC(z)[1])/255 // ,double(fp->WC(z)[2])/255 // ); //} if( m.HasPerTetraQuality() && (pi.mask & ply::PLYMask::PM_TETRAQUALITY) ) fprintf(fpout,"%g ",fp->Q()); for(i=0;i namespace vcg { namespace tetra { namespace io { template struct ExporterTS{ typedef typename MESHTYPE::VertexPointer VertexPointer; typedef typename MESHTYPE::VertexType VertexType; typedef typename MESHTYPE::TetraType FaceType; typedef typename MESHTYPE::VertexIterator VertexIterator; typedef typename MESHTYPE::TetraIterator TetraIterator; typedef typename MESHTYPE::ScalarType ScalarType; typedef Point3 Point3x; static FILE *& F(){static FILE * f; return f;} inline static void WritePos(const Point3 &p){ fprintf(F(),"%g %g %g\n",p[0],p[1],p[2]); } inline static void WritePos(const Point4 &p){ fprintf(F(),"%g %g %g %g\n",p[0],p[1],p[2],p[3]); } static int Save( MESHTYPE & m, const char * filename ) { F() = fopen(filename,"w"); if(F() == NULL ) { printf( "The file could not be opened\n" ); return -1; } else { fprintf(F(), "%i\n", m.vn ); fprintf(F(), "%i\n", m.tn ); VertexIterator vi; for (vi = m.vert.begin(); vi != m.vert.end();++vi) //fprintf(F(), "%f %f %f \n", (*vi).P()[0],(*vi).P()[1],(*vi).P()[2] ); WritePos((*vi).P()); TetraIterator ti; for( ti = m.tetra.begin(); ti != m.tetra.end(); ++ti) fprintf(F(), "%d %d %d %d \n", (*ti).V(0)-&*m.vert.begin(), (*ti).V(1)-&*m.vert.begin(), (*ti).V(2)-&*m.vert.begin(), (*ti).V(3)-&*m.vert.begin()); } return 0; } };// end class };// end of io };// end of tri };// end of vcg #endif �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������qutemol/vcg/wrap/io_tetramesh/import_ply.h����������������������������������������������������������0000444�0001750�0001750�00000057112�10575301160�017410� 0����������������������������������������������������������������������������������������������������ustar �mba�����������������������������mba��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������/**************************************************************************** * VCGLib o o * * Visual and Computer Graphics Library o o * * _ O _ * * Copyright(C) 2004 \/)\/ * * Visual Computing Lab /\/| * * ISTI - Italian National Research Council | * * \ * * All rights reserved. * * * * 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. * * * * 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 (http://www.gnu.org/licenses/gpl.txt) * * for more details. * * * ****************************************************************************/ /**************************************************************************** History $Log: import_ply.h,v $ Revision 1.2 2007/03/12 16:40:16 tarini Texture coord name change! "TCoord" and "Texture" are BAD. "TexCoord" is GOOD. Revision 1.1 2004/06/03 13:16:32 ganovelli created ****************************************************************************/ #ifndef __VCGLIB_TETRAIMPORTERPLY #define __VCGLIB_TETRAIMPORTERPLY #include #include #include #include #include namespace vcg { namespace tetra { namespace io { template int PlyType () { return 0;} template <> int PlyType () { return ply::T_FLOAT; } template <> int PlyType () { return ply::T_DOUBLE; } template <> int PlyType () { return ply::T_INT; } template <> int PlyType () { return ply::T_SHORT; } template <> int PlyType () { return ply::T_UCHAR; } /** This class encapsulate a filter for opening ply meshes. The ply file format is quite extensible... */ template class ImporterPLY { public: typedef ::vcg::ply::PropDescriptor PropDescriptor ; typedef typename OpenMeshType::VertexPointer VertexPointer; typedef typename OpenMeshType::ScalarType ScalarType; typedef typename OpenMeshType::VertexType VertexType; typedef typename OpenMeshType::TetraType TetraType; typedef typename OpenMeshType::VertexIterator VertexIterator; typedef typename OpenMeshType::TetraIterator TetraIterator; //template int PlyType () { assert(0); return 0;} #define MAX_USER_DATA 256 // Struttura ausiliaria per la lettura del file ply struct LoadPly_TetraAux { unsigned char size; int v[512]; int flags; float q; float texcoord[32]; unsigned char ntexcoord; int texcoordind; float colors[32]; unsigned char ncolors; unsigned char r; unsigned char g; unsigned char b; unsigned char data[MAX_USER_DATA]; }; //struct LoadPly_TristripAux //{ // int size; // int *v; // unsigned char data[MAX_USER_DATA]; //}; // Struttura ausiliaria per la lettura del file ply template struct LoadPly_VertAux { S p[3]; int flags; float q; unsigned char r; unsigned char g; unsigned char b; unsigned char data[MAX_USER_DATA]; }; // Struttura ausiliaria caricamento camera //struct LoadPly_Camera //{ // float view_px; // float view_py; // float view_pz; // float x_axisx; // float x_axisy; // float x_axisz; // float y_axisx; // float y_axisy; // float y_axisz; // float z_axisx; // float z_axisy; // float z_axisz; // float focal; // float scalex; // float scaley; // float centerx; // float centery; // int viewportx; // int viewporty; // float k1; // float k2; // float k3; // float k4; //}; static const PropDescriptor &VertDesc(int i) { const static PropDescriptor pv[9]={ {"vertex", "x", ply::T_FLOAT, PlyType(),offsetof(LoadPly_VertAux,p[0]),0,0,0,0,0}, {"vertex", "y", ply::T_FLOAT, PlyType(),offsetof(LoadPly_VertAux,p[1]),0,0,0,0,0}, {"vertex", "z", ply::T_FLOAT, PlyType(),offsetof(LoadPly_VertAux,p[2]),0,0,0,0,0}, {"vertex", "flags", ply::T_INT, ply::T_INT, offsetof(LoadPly_VertAux,flags),0,0,0,0,0}, {"vertex", "quality", ply::T_FLOAT, ply::T_FLOAT, offsetof(LoadPly_VertAux,q),0,0,0,0,0}, {"vertex", "red" , ply::T_UCHAR, ply::T_UCHAR, offsetof(LoadPly_VertAux,r),0,0,0,0,0}, {"vertex", "green", ply::T_UCHAR, ply::T_UCHAR, offsetof(LoadPly_VertAux,g),0,0,0,0,0}, {"vertex", "blue" , ply::T_UCHAR, ply::T_UCHAR, offsetof(LoadPly_VertAux,b),0,0,0,0,0}, {"vertex", "confidence",ply::T_FLOAT, ply::T_FLOAT, offsetof(LoadPly_VertAux,q),0,0,0,0,0}, }; return pv[i]; } static const PropDescriptor &TetraDesc(int i) { const static PropDescriptor qf[10]= { {"tetra", "vertex_indices", ply::T_INT, ply::T_INT, offsetof(LoadPly_TetraAux,v), 1,0,ply::T_UCHAR,ply::T_UCHAR,offsetof(LoadPly_TetraAux,size) }, {"tetra", "flags", ply::T_INT, ply::T_INT, offsetof(LoadPly_TetraAux,flags), 0,0,0,0,0}, {"tetra", "quality", ply::T_FLOAT, ply::T_FLOAT, offsetof(LoadPly_TetraAux,q), 0,0,0,0,0}, {"tetra", "texcoord", ply::T_FLOAT, ply::T_FLOAT, offsetof(LoadPly_TetraAux,texcoord), 1,0,ply::T_UCHAR,ply::T_UCHAR,offsetof(LoadPly_TetraAux,ntexcoord) }, {"tetra", "color", ply::T_FLOAT, ply::T_FLOAT, offsetof(LoadPly_TetraAux,colors), 1,0,ply::T_UCHAR,ply::T_UCHAR,offsetof(LoadPly_TetraAux,ncolors) }, {"tetra", "texnumber", ply::T_INT, ply::T_INT, offsetof(LoadPly_TetraAux,texcoordind), 0,0,0,0,0}, {"tetra", "red" , ply::T_UCHAR, ply::T_UCHAR, offsetof(LoadPly_TetraAux,r), 0,0,0,0,0}, {"tetra", "green", ply::T_UCHAR, ply::T_UCHAR, offsetof(LoadPly_TetraAux,g), 0,0,0,0,0}, {"tetra", "blue" , ply::T_UCHAR, ply::T_UCHAR, offsetof(LoadPly_TetraAux,b), 0,0,0,0,0}, {"tetra", "vertex_index", ply::T_INT, ply::T_INT, offsetof(LoadPly_TetraAux,v), 1,0,ply::T_UCHAR,ply::T_CHAR,offsetof(LoadPly_TetraAux,size) }, }; return qf[i]; } //static const PropDescriptor &TristripDesc(int i) //{ // const static PropDescriptor qf[1]= // { // {"tristrips","vertex_indices", ply::T_INT, ply::T_INT, offsetof(LoadPly_TristripAux,v), 1,1,ply::T_INT,ply::T_INT,offsetof(LoadPly_TristripAux,size) }, // }; // return qf[i]; //} //static const PropDescriptor &CameraDesc(int i) //{ // const static PropDescriptor cad[23] = // { // {"camera","view_px",ply::T_FLOAT,ply::T_FLOAT,offsetof(LoadPly_Camera,view_px),0,0,0,0,0}, // {"camera","view_py",ply::T_FLOAT,ply::T_FLOAT,offsetof(LoadPly_Camera,view_py),0,0,0,0,0}, // {"camera","view_pz",ply::T_FLOAT,ply::T_FLOAT,offsetof(LoadPly_Camera,view_pz),0,0,0,0,0}, // {"camera","x_axisx",ply::T_FLOAT,ply::T_FLOAT,offsetof(LoadPly_Camera,x_axisx),0,0,0,0,0}, // {"camera","x_axisy",ply::T_FLOAT,ply::T_FLOAT,offsetof(LoadPly_Camera,x_axisy),0,0,0,0,0}, // {"camera","x_axisz",ply::T_FLOAT,ply::T_FLOAT,offsetof(LoadPly_Camera,x_axisz),0,0,0,0,0}, // {"camera","y_axisx",ply::T_FLOAT,ply::T_FLOAT,offsetof(LoadPly_Camera,y_axisx),0,0,0,0,0}, // {"camera","y_axisy",ply::T_FLOAT,ply::T_FLOAT,offsetof(LoadPly_Camera,y_axisy),0,0,0,0,0}, // {"camera","y_axisz",ply::T_FLOAT,ply::T_FLOAT,offsetof(LoadPly_Camera,y_axisz),0,0,0,0,0}, // {"camera","z_axisx",ply::T_FLOAT,ply::T_FLOAT,offsetof(LoadPly_Camera,z_axisx),0,0,0,0,0}, // {"camera","z_axisy",ply::T_FLOAT,ply::T_FLOAT,offsetof(LoadPly_Camera,z_axisy),0,0,0,0,0}, // {"camera","z_axisz",ply::T_FLOAT,ply::T_FLOAT,offsetof(LoadPly_Camera,z_axisz),0,0,0,0,0}, // {"camera","focal" ,ply::T_FLOAT,ply::T_FLOAT,offsetof(LoadPly_Camera,focal ),0,0,0,0,0}, // {"camera","scalex" ,ply::T_FLOAT,ply::T_FLOAT,offsetof(LoadPly_Camera,scalex ),0,0,0,0,0}, // {"camera","scaley" ,ply::T_FLOAT,ply::T_FLOAT,offsetof(LoadPly_Camera,scaley ),0,0,0,0,0}, // {"camera","centerx",ply::T_FLOAT,ply::T_FLOAT,offsetof(LoadPly_Camera,centerx),0,0,0,0,0}, // {"camera","centery",ply::T_FLOAT,ply::T_FLOAT,offsetof(LoadPly_Camera,centery),0,0,0,0,0}, // {"camera","viewportx",ply::T_INT,ply::T_INT ,offsetof(LoadPly_Camera,viewportx),0,0,0,0,0}, // {"camera","viewporty",ply::T_INT,ply::T_INT ,offsetof(LoadPly_Camera,viewporty),0,0,0,0,0}, // {"camera","k1" ,ply::T_FLOAT,ply::T_FLOAT,offsetof(LoadPly_Camera,k1 ),0,0,0,0,0}, // {"camera","k2" ,ply::T_FLOAT,ply::T_FLOAT,offsetof(LoadPly_Camera,k2 ),0,0,0,0,0}, // {"camera","k3" ,ply::T_FLOAT,ply::T_FLOAT,offsetof(LoadPly_Camera,k3 ),0,0,0,0,0}, // {"camera","k4" ,ply::T_FLOAT,ply::T_FLOAT,offsetof(LoadPly_Camera,k4 ),0,0,0,0,0} // }; // return cad[i]; //} /// Standard call for reading a mesh static int Open( OpenMeshType &m, const char * filename, CallBackPos *cb=0) { PlyInfo pi; pi.cb=cb; return Open(m, filename, pi); } /// Read a mesh and store in loadmask the loaded field static int Open( OpenMeshType &m, const char * filename, int & loadmask, CallBackPos *cb =0) { PlyInfo pi; pi.mask=loadmask; return Open(m, filename,pi); loadmask=pi.mask; } /// read a mesh with all the possible option specified in the PlyInfo obj. static int Open( OpenMeshType &m, const char * filename, PlyInfo &pi ) { assert(filename!=0); vector index; LoadPly_TetraAux fa; // LoadPly_TristripAux tsa; LoadPly_VertAux va; pi.mask = 0; bool multit = false; // true if texture has a per face int spec the texture index va.flags = 42; pi.status = ::vcg::ply::E_NOERROR; // init defaults VertexType tv; tv.UberFlags() = 0; if( VertexType::HasQuality() ) tv.Q()=1.0; if( VertexType::HasColor() ) tv.C()=Color4b(Color4b::White); TetraType tf; tf.UberFlags() = 0; //if( FaceType::HasFaceQuality() ) tf.Q()=1.0; //if( FaceType::HasWedgeColor() ) tf.WC(0)=tf.WC(1)=tf.WC(2)=Color4b(Color4b::White); //if( FaceType::HasFaceColor() ) tf.C()=Color4b(Color4b::White); // Descrittori delle strutture //bool isvflags = false; // Il file contiene i flags // The main descriptor of the ply file vcg::ply::PlyFile pf; // Open the file and parse the header if( pf.Open(filename,vcg::ply::PlyFile::MODE_READ)==-1 ) { pi.status = pf.GetError(); return -1; } pi.header = pf.GetHeader(); // Descrittori della camera { // Check that all the camera properties are present. /* bool found = true; for(int i=0;i<23;++i) { if( pf.AddToRead(CameraDesc(i))==-1 ) { found = false; break; } } if(found) pi.mask |= ply::PLYMask::PM_CAMERA;*/ } // Descrittori dati standard (vertex coord e faces) if( pf.AddToRead(VertDesc(0))==-1 ) { pi.status = PlyInfo::E_NO_VERTEX; return -1; } if( pf.AddToRead(VertDesc(1))==-1 ) { pi.status = PlyInfo::E_NO_VERTEX; return -1; } if( pf.AddToRead(VertDesc(2))==-1 ) { pi.status = PlyInfo::E_NO_VERTEX; return -1; } if( pf.AddToRead(TetraDesc(0))==-1 ){ pi.status = PlyInfo::E_NO_VERTEX; return -1; } // Se fallisce si prova anche la sintassi di rapidform con index al posto di indices // if( pf.AddToRead(TetraDesc(9))==-1 ) // if(pf.AddToRead(TristripDesc(0))==-1) // Se fallisce tutto si prova a vedere se ci sono tristrip alla levoy. // { pi.status = PlyInfo::E_NO_FACE; return -1; } // Descrittori facoltativi dei flags if( pf.AddToRead(VertDesc(3))!=-1 ) pi.mask |= ply::PLYMask::PM_VERTFLAGS; if( VertexType::HasQuality() ) { if( pf.AddToRead(VertDesc(4))!=-1 || pf.AddToRead(VertDesc(8))!=-1 ) pi.mask |= ply::PLYMask::PM_VERTQUALITY; } if( VertexType::HasColor() ) { if( pf.AddToRead(VertDesc(5))!=-1 ) { pf.AddToRead(VertDesc(6)); pf.AddToRead(VertDesc(7)); pi.mask |= ply::PLYMask::PM_VERTCOLOR; } } // se ci sono i flag per vertice ci devono essere anche i flag per faccia if( pf.AddToRead(TetraDesc(1))!=-1 ) pi.mask |= ply::PLYMask::PM_TETRAFLAGS; if( TetraType::HasTetraQuality()) { if( pf.AddToRead(TetraDesc(2))!=-1 ) pi.mask |= ply::PLYMask::PM_TETRAQUALITY; } if( TetraType::HasTetraColor() ) { if( pf.AddToRead(TetraDesc(6))!=-1 ) { pf.AddToRead(TetraDesc(7)); pf.AddToRead(TetraDesc(8)); pi.mask |= ply::PLYMask::PM_TETRACOLOR; } } // if( FaceType::HasWedgeColor() || FaceType::HasFaceColor() || VertexType::HasColor()) //{ // if( pf.AddToRead(TetraDesc(4))!=-1 ) // { // pi.mask |= ply::PLYMask::PM_WEDGCOLOR; // } //} // Descrittori definiti dall'utente, vector VPV(pi.vdn); // property descriptor relative al tipo LoadPly_VertexAux vector FPV(pi.fdn); // property descriptor relative al tipo LoadPly_FaceAux if(pi.vdn>0){ // Compute the total size needed to load additional per vertex data. size_t totsz=0; for(int i=0;i,data)+totsz; totsz+=pi.VertexData[i].memtypesize(); if( pf.AddToRead(VPV[i])==-1 ) { pi.status = pf.GetError(); return -1; } } if(totsz > MAX_USER_DATA) { pi.status = vcg::ply::E_BADTYPE; return -1; } } if(pi.fdn>0){ size_t totsz=0; for(int i=0;i MAX_USER_DATA) { pi.status = vcg::ply::E_BADTYPE; return -1; } } /**************************************************************/ /* Main Reading Loop */ /**************************************************************/ m.Clear(); for(int i=0;i::AddVertices(m,n); for(j=0;j::AddTetra(m,n); pf.SetCurElement(i); for(j=0;j=m.vn ) { pi.status = PlyInfo::E_BAD_VERT_INDEX; return -1; } (*fi).V(k) = index[ fa.v[k] ]; } if( pi.mask & ply::PLYMask::PM_TETRAFLAGS ) { (*fi).UberFlags() = fa.flags; } if( pi.mask & ply::PLYMask::PM_TETRAQUALITY ) { (*fi).Q() = fa.q; } if( pi.mask & ply::PLYMask::PM_TETRACOLOR ) { (*fi).C()[0] = fa.r; (*fi).C()[1] = fa.g; (*fi).C()[2] = fa.b; (*fi).C()[3] = 255; } if(TetraType::HasTetraColor()){ { (*fi).C()[0] = (unsigned char)((fa.colors[0*3+0]*255+fa.colors[1*3+0]*255+fa.colors[2*3+0]*255)/3.0f); (*fi).C()[1] = (unsigned char)((fa.colors[0*3+1]*255+fa.colors[1*3+1]*255+fa.colors[2*3+1]*255)/3.0f); (*fi).C()[2] = (unsigned char)((fa.colors[0*3+2]*255+fa.colors[1*3+2]*255+fa.colors[2*3+2]*255)/3.0f); } } } for(k=0;k=numvert_tmp ) { // pi.status = PlyInfo::E_BAD_VERT_INDEX; // return -1; // } // if(tsa.v[k+2]==-1) // { // k+=2; // if(k%2) remainder=0; // else remainder=1; // continue; // } // tf.V(0) = index[ tsa.v[k+0] ]; // tf.V(1) = index[ tsa.v[k+1] ]; // tf.V(2) = index[ tsa.v[k+2] ]; // if((k+remainder)%2) swap (tf.V(0), tf.V(1) ); // m.face.push_back( tf ); // } // } // } else { // Skippaggio elementi non gestiti int n = pf.ElemNumber(i); pf.SetCurElement(i); for(int j=0;j32 && buf[i]<125 ) buf[j++] = buf[i]; // // buf[j] = 0; // char buf2[255]; // __interpret_texture_name( buf,filename,buf2 ); // textures.push_back( xstring(buf2) ); // } // if( !strncmp(c,NFILE,strlen(NFILE)) ) // { // strcpy(buf,c+strlen(NFILE)+1); // n = strlen(buf); // for(i=j=0;i32 && buf[i]<125 ) buf[j++] = buf[i]; // // buf[j] = 0; // char buf2[255]; // __interpret_texture_name( buf,filename,buf2 ); // normalmaps.push_back( xstring(buf2) ); // } //} // vn and fn should be correct but if someone wrongly saved some deleted elements they can be wrong. m.vn = 0; VertexIterator vi; for(vi=m.vert.begin();vi!=m.vert.end();++vi) if( ! (*vi).IsD() ) ++m.vn; m.tn = 0; TetraIterator fi; for(fi=m.tetra.begin();fi!=m.tetra.end();++fi) if( ! (*fi).IsD() ) ++m.tn; return 0; } // Caricamento camera da un ply int LoadCamera(const char * filename) { vcg::ply::PlyFile pf; if( pf.Open(filename,vcg::ply::PlyFile::MODE_READ)==-1 ) { pi.status = pf.GetError(); return -1; } bool found = true; int i; for(i=0;i<23;++i) { if( pf.AddToRead(CameraDesc(i))==-1 ) { found = false; break; } } if(!found) return -1; for(i=0;i #include #include #include #include #include #include namespace vcg { /*! @brief The base class for Trackball. This class is useful for using a Trackball instance in a scene graph, as a sort of interactive transform. */ class Transform { public: /*! @brief The constructor. Initialize: - track to the identity transform. - center to origin 0,0,0. - radius to unit size. */ Transform(); /// A trackball stores a transformation called 'track' that effectively rototranslate the object. Similarityf track; /// track position in model space. Point3f center; /// size of the widget in model space. float radius; }; /*! @brief Computes the linear interpolation between 2 transforms. @param a The first transform. @param b The second transform. @param t The interpolation value (0: just a, 0.5: middle from a to b, 1: just b). @return The linear interpolation. */ Transform interpolate(const Transform &a, const Transform &b, float t); class TrackMode; /*! @brief The manipulator manager system. Short usage note: - Center specify the center of rotation and scaling of the trackball and usually is set by the program and do not interactively change - Radius specify the radius of the interactive ball shaped icon to specify rotation. It is in absolute unit. - Like the previous one it is not changed during interaction. When you specify a translation with the trackball the trackball center remain \b unchanged, in other words it means that the object move out of the trackball icon. Similarly when you apply a scaling the size of the manipulator icon do not change. Typical use:

glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(60, float(width())/float(height()), 1, 100);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(0,0,3,   0,0,0,   0,1,0)

trackball.center=Point3f(0, 0, 0);
trackball.radius= 1;

trackball.GetView();
trackball.Apply(true); //false if you want an invisible trackball

float d=1.0f/mesh.bbox.Diag();
glScale(d);
glTranslate(-mesh.bbox.Center());
mesh->Render();
Note on the typical use: - Perspective and glulookat are choosed to frame the origin centered 1-radius trackball. - The final scale and translate are just to fit a generic mesh to the 1sized origin centered where the trackball stays box. - The trackball works also on Orthographic projections \b but that are not centered around origin (just move it back along the Z) */ class Trackball: public Transform { public: // the drawing code has been moved to the trackmodes // class DrawingHint { // DrawingHint DH; /// The componibile states of the manipulator system. enum Button { BUTTON_NONE = 0x0000, ///< No mouse button pressed. BUTTON_LEFT = 0x0001, ///< Left mouse button pressed. BUTTON_MIDDLE = 0x0002, ///< Middle mouse button pressed. BUTTON_RIGHT = 0x0004, ///< Right mouse button pressed. WHEEL = 0x0008, ///< Mouse wheel activated. KEY_SHIFT = 0x0010, ///< Shift key pressed. KEY_CTRL = 0x0020, ///< Ctrl key pressed. KEY_ALT = 0x0040, ///< Alt key pressed. HANDLE = 0x0080 ///< Application-defined state activated. }; /*! @brief The constructor. Initialize the internal state with default values and call setDefaultMapping(). */ Trackball(); /*! @brief The destructor. @warning The destructor does not deallocate the memory allocated by setDefaultMapping(), because the application can change the modes map. This can lead to small memory leaks, so please explicitally delete any manipulator in the modes map if you are going to repeatly allocate and deallocate Trackball instances. */ ~Trackball(); /*! @brief Reset the trackball. Equivalent to Reset(). */ void SetIdentity(); /*! @brief Set the position of the trackball. @param c The new position of the trackball. @param millisec Currently not in use. */ void SetPosition(const Point3f &c, int millisec = 0); /*! @brief Currently not in use. @param s Currently not in use. */ void SetScale(const float s) {radius=s;}; /*! @brief Currently not in use. @param transform Currently not in use. @param millisec Currently not in use. */ void SetTransform(const Transform &transform, int millisec = 0); /*! @brief Apply a translation on the current transformation. @param tr The translation vector. */ void Translate(Point3f tr); /*! @brief Apply a scaling on the current transformation. @param f The scale factor. */ void Scale(const float f); //operating /*! @brief Initialize the camera instance. */ void GetView(); /*! @brief Apply the current transformation on the OpenGL modelview matrix. @param Draw true if has to call DrawPostApply() after the application. */ void Apply(bool Draw); /*! @brief Old application of the transformation. @warning This function does \b not call DrawPostApply() after the application. */ void Apply (); /*! @brief Draw the current manipulator. Call the draw function of the current manipulator. If no manipulator is selected call the draw function of the manipulator associated to inactive_mode. @warning This function assumes that the OpenGL modelview matrix has been initialized with Apply (). */ void DrawPostApply(); /*! @brief Apply the \b inverse of current transformation on the OpenGL modelview matrix. */ void ApplyInverse(); // DrawIcon() has been moved to trackutils.h //void DrawIcon(); /*! @brief Reset the transformation and every mapped manipulator. */ void Reset(); // DrawCircle (), DrawPlane(), DrawPlaneHandle() has been moved to trackutils.h // the drawing code has been moved to the trackmodes // void DrawCircle (); // void DrawPlane(); // void DrawPlaneHandle(); //interface /*! @brief Interface function relative to mouse down event in QT/SDL. @param button The new state. */ void MouseDown(/*Button*/ int button); /*! @brief Interface function relative to mouse down event in QT/SDL. @param x The horizontal coordinate of the mouse pointer. @param y The vertical coordinate of the mouse pointer. @param button The new state. */ void MouseDown(int x, int y, /*Button*/ int button); /*! @brief Interface function relative to mouse down event in QT/SDL. @param x The horizontal coordinate of the mouse pointer. @param y The vertical coordinate of the mouse pointer. */ void MouseMove(int x, int y); /*! @brief Interface function relative to mouse down event in QT/SDL. @param x The horizontal coordinate of the mouse pointer. @param y The vertical coordinate of the mouse pointer. @param button The new state. */ void MouseUp(int x, int y, /*Button */ int button); /*! @brief Old interface function relative to mouse down event in QT/SDL. @param notch The mouse wheel notch (1: one forward step, -1: one backward step). */ void MouseWheel(float notch); /*! @brief Interface function relative to mouse down event in QT/SDL. @param notch The mouse wheel notch (1: one forward step, -1: one backward step). @param button The new state. */ void MouseWheel (float notch, /*Button */ int button); /*! @brief Interface function relative to key down event in QT/SDL. @param button the new state. */ void ButtonUp(Button button); /*! @brief Interface function relative to key up event in QT/SDL. @param button the new state. */ void ButtonDown(Button button); /*! @brief Undo function for manipulator system. A call of this function restores the state before last user action. This function calls %Undo() on every mapped manipulator. */ void Undo(); //default sensitivity 1 /*! @brief Currently not in use. @param s Currently not in use. */ void SetSensitivity(float s); //spinning interface /*! @brief Currently not in use. @param on Currently not in use. */ void SetSpinnable(bool on); /*! @brief Currently not in use. @return A meaningless boolean value. */ bool IsSpinnable(); /*! @brief Currently not in use. @param spin Currently not in use. */ void SetSpinning(Quaternionf &spin); /*! @brief Currently not in use. */ void StopSpinning(); /*! @brief Currently not in use. @return A meaningless boolean value. */ bool IsSpinning(); //interfaccia navigation: /*! @brief Currently not in use. */ void Back(); /*! @brief Currently not in use. */ void Forward(); /*! @brief Currently not in use. */ void Home(); /*! @brief Currently not in use. */ void Store(); /*! @brief Currently not in use. */ void HistorySize(int lenght); /* //internals // commented out no more used this stuff! enum Action { NONE = 0, VIEW_ROTATE = 1, // Axis Constrained Rotation TRACK_ROTATE_X = 3, TRACK_ROTATE_Y = 4, TRACK_ROTATE_Z = 5, // Drag constrained to an axis (trackball axis) DRAG_X = 6, DRAG_Y = 7, DRAG_Z = 8, // Drag constrained to a plane DRAG_XY = 9, DRAG_YZ = 10, DRAG_XZ = 11, //scale model respect to center of trackball VIEW_SCALE = 12, //scale trackball and model TRACK_SCALE = 13 }; */ // loads stores current status from/to ascii stings /*! @brief Stores current status into an ascii stings Stores current status into an ascii stings. This is useful for example to implement cut-and-paste operations of trackball status, or to embed used trackball into a comment inside a screenshot, etc. @param st The string where to export (must be allocated). */ void ToAscii(char * st); /*! @brief Loads current status from an ascii stings Loads current status from an ascii stings. This is useful for example to implement cut-and-paste operations of trackball status, or to embed used trackball into a comment inside a screenshot, etc. @param st The string where to read from (must be allocated). Use ToAscii() method to set it. @return True iff the trackball was successfully recovered. */ bool SetFromAscii(const char * st); //protected: /// The reference for point projection and unprojection from screen space to modelspace. View camera; /*! @brief Prepare Trackball and every mapped TrackMode for an user action. This function is called automatically when an user action begins. */ void SetCurrentAction(); /// Current state composition. int current_button; /// The selected manipulator. TrackMode *current_mode; /// The inactive manipulator. It is drawed when Trackball is inactive. TrackMode *inactive_mode; /*! @brief Reset modes to default mapping. Set the default modes mapping. The default mapping is: - \b LEFT : SphereMode. - \b LEFT+CTRL or \b MIDDLE : PanMode. - \b LEFT+SHIFT or \b WHEEL : ScaleMode. - \b LEFT+ALT : ZMode. @warning The memory allocated by this function is not automatically deallocated. see ~Trackball(). */ void setDefaultMapping (); /// The manipulator mapping. Needs to be explicitally managed for custom mappings. std::map modes; // undo_track and last_track have different meanings.. /// Transformation before current user action. Similarityf last_track; /// track after an Undo() call. Similarityf undo_track; /// Currently not in use. Similarityf last_view; /// Mouse cursor coordinates before current action. Point3f last_point; /// Currently not in use. std::vector Hits; /// Currently not in use. bool dragging; /// Currently not in use. int button_mask; /// Currently not in use. Quaternionf spin; /// Currently not in use. bool spinnable; /// Currently not in use. bool spinning; /// Currently not in use. std::list history; /// Currently not in use. int history_size; /// Manipulators needs full access to this class. friend class TrackMode; }; }//namespace #endif qutemol/vcg/wrap/gui/trackmode.h0000444000175000017500000007315010755376262015303 0ustar mbamba/**************************************************************************** * VCGLib o o * * Visual and Computer Graphics Library o o * * _ O _ * * Copyright(C) 2004 \/)\/ * * Visual Computing Lab /\/| * * ISTI - Italian National Research Council | * * \ * * All rights reserved. * * * * 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. * * * * 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 (http://www.gnu.org/licenses/gpl.txt) * * for more details. * * * ****************************************************************************/ /**************************************************************************** History $Log: trackmode.h,v $ Revision 1.16 2008/02/15 20:57:22 benedetti added snap to CylinderMode Revision 1.15 2007/07/14 12:43:44 benedetti Added Doxygen documentation. Revision 1.14 2007/07/09 22:47:18 benedetti Removed using namespace std and modified accordingly. Revision 1.13 2007/06/25 10:21:38 fiorin Added some std:: here and there Revision 1.12 2007/06/13 17:15:09 benedetti Added one-level undo system and sticky trackmodes. Revision 1.11 2007/05/15 14:59:10 benedetti Main restructuring. added many new modes Revision 1.10 2007/02/26 01:30:02 cignoni Added reflection Name Revision 1.9 2006/02/13 13:10:27 cignoni Added Zmode for moving objects along the perpendicular to the viewplane Revision 1.8 2004/07/18 06:54:08 cignoni Added Scaling Revision 1.7 2004/07/11 22:06:56 cignoni Added scaling by wheel Revision 1.6 2004/06/09 14:01:13 cignoni Heavily restructured. To be completed only rotation works... Revision 1.5 2004/05/14 03:15:09 ponchio Redesigned partial version. Revision 1.4 2004/05/07 12:46:08 cignoni Restructured and adapted in a better way to opengl Revision 1.3 2004/04/07 10:54:11 cignoni Commented out unused parameter names and other minor warning related issues Revision 1.2 2004/03/25 14:55:25 ponchio Adding copyright. ****************************************************************************/ #ifndef TRACKMODE_H #define TRACKMODE_H #include #include #include #include #include namespace vcg { class Trackball; /*! @brief Base class for all the manipulators. Functions in this class implements the default behaviour of a manipulator: doing nothing. Every manipulator must be subclass of this class. */ class TrackMode { public: /*! @brief The default virtual destructor */ virtual ~TrackMode () { } /*! @brief The default manipulator application for mouse drags. This default application does nothing. @param trackball the manipulator manager. @param new_point the new mouse pointer coordinate. */ virtual void Apply (Trackball * trackball, Point3f new_point); /*! @brief The default manipulator application for mouse scrolls. This default application does nothing. @param trackball the manipulator manager. @param WheelNotch the mouse wheel notch. */ virtual void Apply (Trackball * trackball, float WheelNotch); /*! @brief The default manipulator's begin action function. This default implementation does nothing. */ virtual void SetAction (); /*! @brief The default manipulator's reset function. If a manipulator has a state, it can be reset to the inital state calling this function. */ virtual void Reset (); /*! @brief The default manipulator's name. @return the constant string "TrackMode" */ virtual const char *Name (){ return "TrackMode"; }; /*! @brief The default manipulator's render function. @param trackball the manipulator manager. */ virtual void Draw (Trackball * trackball); /*! @brief The default avaibility to manipulator changes inside an action. Every manipulator class can choose if the manipulator manager can switch between it and another manipulator in the middle of an user action, e.g. switching Trackball's current_mode without releasing the mouse button. The default behaviour is to allow the switch. Blocking switches is useful for stateful manipulators, regarding state consistency respect to Trackball's %Undo() calls. @return false if manipulator permits the switch. */ virtual bool isSticky(); /*! @brief The default manipulator's undo function. If a manipulator has a state, it must be undoable with a call of this function. The undo must recreate the state present before the last Apply() call. This default implementation does nothing. */ virtual void Undo(); }; /*! @brief An inactive manipulator. This manipulator is useful only for drawing the inactive trackball and for feeding occasional Trackball's modes with inactive manipulators. */ class InactiveMode:public TrackMode { public: /*! @brief Return this manipulator's name. @return the constant string "InactiveMode" */ const char *Name () { return "InactiveMode"; }; /*! @brief Render this manipulator. @param trackball the manipulator manager. */ void Draw (Trackball * trackball); }; /* View space modes */ // old interfaces /* class SphereMode: public TrackMode { } class CylinderMode: public TrackMode { } class PlaneMode: public TrackMode { } class ZMode: public TrackMode { } class LineMode: public TrackMode { } class LineMode: public TrackMode { } class ScaleMode: public TrackMode { */ // Sphere mode. /*! @brief The classic \e arcball manipulator. This class implements the classic free rotation manipulator, called \e arcball or \e trackball. This is a stateless manipulator, result of the Apply function is determined only by the mouse coordinates. */ class SphereMode:public TrackMode { public: /*! @brief Apply a rotation, function of the user mouse drag action. Map a mouse drag action on a rotation, and apply the rotation to the manipulated objects. If the user does not hit the sphere that surrounds the manipulated object(s), a rotational hyperboloid is used to compute the rotation. @param trackball the manipulator manager. @param new_point the new mouse pointer coordinate. */ void Apply (Trackball * trackball, Point3f new_point); /*! @brief Return this manipulator's name. @return the constant string "SphereMode" */ const char *Name () { return "SphereMode"; }; /*! @brief Render this manipulator. @param trackball the manipulator manager. */ void Draw (Trackball * trackball); }; // Panning mode. /*! @brief The panning manipulator. This manipulator implements a bidimensional translation on the view plane. This is a stateless manipulator, result of the Apply function is determined only by the mouse coordinates. */ class PanMode:public TrackMode { public: /*! @brief Apply a translation, function of the user mouse drag action. The manipulated object is dragged in the plane parallel to the screen. @param trackball the manipulator manager. @param new_point the new mouse pointer coordinate. */ void Apply (Trackball * trackball, Point3f new_point); /*! @brief Return this manipulator's name. @return the constant string "PanMode" */ const char *Name () { return "PanMode"; }; /*! @brief Render this manipulator. @param trackball the manipulator manager. */ void Draw (Trackball * trackball); }; // Z mode. /*! @brief The Z-directional manipulator. This manipulator implements a monodimensional translation on the axis normal to the view plane. Dragging the mouse up and down or scrolling the mouse wheel will move the object along the Z of the camera. This is a stateless manipulator, result of the Apply functions is determined only either by the mouse coordinates or by the mouse wheel notch. */ class ZMode:public TrackMode { public: /*! @brief Return this manipulator's name. @return the constant string "ZMode" */ const char *Name () { return "ZMode"; }; /*! @brief Apply a translation, function of the user mouse drag action. The manipulated object is moved along the Z of the camera: - Dragging the mouse down will move the object nearer to the camera. - Dragging the mouse up will move the object farther from the camera. @param trackball the manipulator manager. @param new_point the new mouse pointer coordinate. */ void Apply (Trackball * trackball, Point3f new_point); /*! @brief Apply a translation, function of the user mouse wheel action. The manipulated object is moved along the Z of the camera: - Scrolling the mouse wheel down will move the object nearer to the camera. - Scrolling the mouse wheel up will move the object farther from the camera. @param trackball the manipulator manager. @param WheelNotch the mouse wheel notch. */ void Apply (Trackball * trackball, float WheelNotch); /*! @brief Render this manipulator. @param trackball the manipulator manager. */ void Draw (Trackball * trackball); }; // Scale Mode. /*! @brief The scale manipulator. This manipulator implements a scaling transformation. Dragging the mouse up and down or scrolling the mouse wheel will scale the object. This is a stateless manipulator, result of the Apply functions is determined only either by the mouse coordinates or by the mouse wheel notch. */ class ScaleMode:public TrackMode { public: /*! @brief Return this manipulator's name. @return the constant string "ScaleMode" */ const char *Name () { return "ScaleMode"; }; /*! @brief Apply a scaling, function of the user mouse drag action. The manipulated object is scaled in this way: - Dragging the mouse up will scale the object to a smaller dimension. - Dragging the mouse down will scale the object to a greater dimension. @param trackball the manipulator manager. @param new_point the new mouse pointer coordinate. */ void Apply (Trackball * trackball, Point3f new_point); /*! @brief Apply a scaling, function of the user mouse wheel action. The manipulated object is scaled in this way: - Scrolling the mouse wheel up will scale the object to a smaller dimension. - Scrolling the mouse wheel down will scale the object to a greater dimension. @param trackball the manipulator manager. @param WheelNotch the mouse wheel notch. */ void Apply (Trackball * trackball, float WheelNotch); /*! @brief Render this manipulator. @param trackball the manipulator manager. */ void Draw (Trackball * trackball); }; // Axis mode. /*! @brief The one-directional manipulator. This manipulator implements a monodimensional translation on a constrained direction. Dragging the mouse up and down or scrolling the mouse wheel will move the object along the direction. This is a stateless manipulator, result of the Apply functions is determined only either by the mouse coordinates or by the mouse wheel notch. */ class AxisMode:public TrackMode { public: /*! @brief The line constructor. This manipulator needs to be initialized with a direction. This constructor can initialize it with a Line3f. The line will be normalized. @param ln the line that represent the direction. */ AxisMode (const Line3f & ln) : axis (ln) { } /*! @brief The origin-direction constructor. This manipulator needs to be initialized with a direction. This constructor can initialize it with two Point3f, representing a point and a vector. @param origin a point on the line. @param direction the line direction. */ AxisMode (const Point3f & origin, const Point3f & direction) : axis(Line3fN (origin, direction)) { } /*! @brief Return this manipulator's name. @return the constant string "AxisMode" */ const char *Name () { return "AxisMode"; }; /*! @brief Apply a translation, function of the user mouse drag action. The manipulated object is moved along the direction. If the pointer ray is divergent from the direction the object is not moved. @param trackball the manipulator manager. @param new_point the new mouse pointer coordinate. */ void Apply (Trackball * trackball, Point3f new_point); /*! @brief Apply a translation, function of the user mouse wheel action. The manipulated object is moved along the direction. @param trackball the manipulator manager. @param WheelNotch the mouse wheel notch. */ void Apply (Trackball * trackball, float WheelNotch); /*! @brief Render this manipulator. @param trackball the manipulator manager. */ void Draw (Trackball * trackball); private: /// The direction, stored as a normalized line. Line3fN axis; }; // Plane mode. /*! @brief The planar manipulator. This manipulator implements a bidimensional translation on a constrained plane. This is a stateless manipulator, result of the Apply function is determined only by the mouse coordinates. */ class PlaneMode:public TrackMode { public: /*! @brief The plane costants constructor. This manipulator needs to be initialized with a plane. This constructor can initialize it with the four coefficients of the plane equation \f$ ax + by + cz + d = 0 \f$. @param a the first coefficient of the plane equation. @param b the second coefficient of the plane equation. @param c the third coefficient of the plane equation. @param d the fourth coefficient of the plane equation. */ PlaneMode (float a, float b, float c, float d) : plane(Plane3f(d,Point3f(a,b,c))){ } /*! @brief The plane constructor. This manipulator needs to be initialized with a plane. This constructor can initialize it with a Plane3f. @param pl the plane. */ PlaneMode (Plane3f & pl) : plane(pl) { } /*! @brief Return this manipulator's name. @return the constant string "PlaneMode" */ const char *Name () { return "PlaneMode"; }; /*! @brief Apply a translation, function of the user mouse drag action. The manipulated object is dragged in the plane. If the pointer ray is divergent from the plane the object is not moved. @param trackball the manipulator manager. @param new_point the new mouse pointer coordinate. */ void Apply (Trackball * trackball, Point3f new_point); /*! @brief Render this manipulator. @param trackball the manipulator manager. */ void Draw (Trackball * trackball); private: /// The plane. Plane3f plane; }; // Cylinder mode. /*! @brief The constrained rotation manipulator. This manipulator implements a rotation manipulator, that make the rotation constrained around a given axis. The user can either drag the mouse or scroll the wheel, in either cases the rotation's angle is influenced by the radius of the trackball. This is a stateless manipulator, result of the Apply functions is determined only either by the mouse coordinates or by the mouse wheel notch. */ class CylinderMode:public TrackMode { public: /*! @brief The line constructor. This manipulator needs to be initialized with an axis. This constructor can initialize it with a Line3f. The line will be normalized. @param ln the line that represent the axis. @param s a rotational snap angle non negative */ CylinderMode (Line3fN & ln,float s=0.0f) : axis (ln), snap(s){ assert(snap>=0.0); } /*! @brief The origin-direction constructor. This manipulator needs to be initialized with a axis. This constructor can initialize it with two Point3f, representing a point and a vector. @param origin a point on the axis. @param direction the axis direction. @param s a rotational snap angle (non negative) */ CylinderMode (const Point3f & origin, const Point3f & direction,float s=0.0f) : axis (Line3fN(origin,direction)), snap(s){ assert(snap>=0.0); } /*! @brief Return this manipulator's name. @return the constant string "CylinderMode" */ const char *Name () { return "CylinderMode"; }; /*! @brief Apply a rotation, function of the user mouse drag action. The manipulated object is rotated around the axis. if the axis is too perpendicular to view plane, the angle is specified only by the vertical component of the mouse drag and the radius. @param trackball the manipulator manager. @param new_point the new mouse pointer coordinate. */ void Apply (Trackball * trackball, Point3f new_point); /*! @brief Apply a rotation, function of the user mouse wheel action. The manipulated object is rotated around the axis. @param trackball the manipulator manager. @param WheelNotch the mouse wheel notch. */ void Apply (Trackball * trackball, float WheelNotch); /*! @brief Render this manipulator. @param trackball the manipulator manager. */ void Draw (Trackball * trackball); private: /// The axis, stored as a normalized line. Line3fN axis; /// The rotational snap value float snap; }; // Path mode. /*! @brief The path constrained manipulator. This manipulator moves the object along an eventually closed path. The user can either drag the mouse or scroll the wheel, when the user drags the mouse, the object tries to slide toward it. The object is assumed to initially be on the same position of the first point on the path. This is a \b stateful manipulator, result of the Apply functions is determined by the objects's position along the path and by either the mouse coordinates or the mouse wheel notch. */ class PathMode:public TrackMode { public: /*! @brief The vector-boolean constructor. The vector passed to build the path is copied locally. The boolean value specifies if the path is to be closed. If the boolean value is not specified, the path is not closed. @warning the path is \b not assumed to have 0-length segments, so, if you want to close the path, please do not add a copy of the first point on the end of the vector. @param pts the path nodes. @param w a boolean value that closes the path. */ PathMode ( const std::vector < Point3f > &pts, bool w = false) : points(), wrap(w), current_state(0), initial_state(0), old_hitpoint() { Init(pts); assert(min_seg_length > 0.0f); } /*! @brief The segment constructor. If the path is a simple segment, it can be specified just with the endpoints. @param start the starting point. @param end the ending point. */ PathMode ( const Point3f &start, const Point3f &end ) : points(), wrap(false), current_state(0), initial_state(0), old_hitpoint() { points.push_back(start); points.push_back(end); path_length=Distance(start,end); min_seg_length=path_length; assert(min_seg_length > 0.0f); } /*! @brief Return this manipulator's name. @return the constant string "PathMode" */ const char *Name () { return "PathMode"; }; /*! @brief Apply a translation, function of the user mouse drag action. The manipulated object is moved along the path. This function implements an algorithm that makes the object try to slide on the path towards the mouse pointer. @param trackball the manipulator manager. @param new_point the new mouse pointer coordinate. */ void Apply (Trackball * trackball, Point3f new_point); /*! @brief Apply a translation, function of the user mouse wheel action. The manipulated object is moved along the path. A step of the mouse wheel makes the object slide by a distance equal to the half of the shortest segment on the path. @param trackball the manipulator manager. @param WheelNotch the mouse wheel notch. */ void Apply (Trackball * trackball, float WheelNotch); /*! @brief Render this manipulator. @param trackball the manipulator manager. */ void Draw (Trackball * trackball); /*! @brief The begin action function. This function is to be called at the begin of an user action. */ void SetAction (); /*! @brief The reset function. This function reset the object position to the initial point. */ void Reset (); /*! @brief Try to set the inital point. This function try to set the starting point in the point passed as parameter, if the point passed does not reside on the path, the start is put on the closest point on it. @param p the point wished for the start. @return the starting point on the path. */ Point3f SetStartNear(Point3f p); /*! @brief The (non) avaibility to manipulator changes inside an action. This manipulator has an internal state and does not allow a switch in the middle of a function. @return the costant boolean true. */ bool isSticky(); /*! @brief The undo function. This function recreates the state present before the last Apply() call. */ void Undo(); private: /*! @brief The data initializer. Initialize the internal state and checks params validity. @param points the path nodes. */ void Init(const std::vector < Point3f > &points); /*! @brief The state interpreter. Given the state, return the current point, the previous node and the next node on the path. The algoritm is linear in the node paths. @param state the given state. @param point is set to the current point. @param prev_point is set to the point of current point's previous node. @param next_point is set to the point of current point's next node. */ void GetPoints(float state, Point3f & point, Point3f & prev_point, Point3f & next_point); /*! @brief The state normalizer. Normalize a given state in the right interval: - \f$ [0 \ldots 1] \f$ if the path is open. - \f$ [0 \ldots 1) \f$ if the path is closed (because it wraps). @param state the given state. */ float Normalize(float state); /*! @brief Compute the new point and the \f$\Delta\f$-state. Given a state and the mouse coords ray, computes the new state point and return the \f$\Delta\f$-state. The algoritm is linear in the node paths. @param state the given state. @param ray the ray relative to mouse coords. @param hit_point is set to the new state point. @return the \f$\Delta\f$-state. */ float HitPoint(float state, Ray3fN ray, Point3f &hit_point); /*! @brief Compute the verse to follow for slide nearer to a given point. Given the current state point, the point of previus and next node and a reference point, compute the verse to follow for the object to come closer to the reference point. @param reference_point @param current_point @param prev_point @param next_point @return -1, 0 or 1 if the verse is respectively towars the startpoint, null or towards the endpoint. */ int Verse(Point3f reference_point,Point3f current_point,Point3f prev_point,Point3f next_point); /// The node vector. std::vector < Point3f > points; /// True if the path is closed, false otherwise. bool wrap; /// The current state. float current_state; /// The initial state. float initial_state; /// The path length. float path_length; /// The length of the shostest path segment float min_seg_length; /// The point relative to the old state. Point3f old_hitpoint; /// current_state after an Undo() call. float undo_current_state; /// old_hitpoint after an Undo() call. Point3f undo_old_hitpoint; }; // Area mode. /*! @brief The area constrained manipulator. This manipulator moves the object inside a poligonal area. The user can drag the object inside a planar area, defined by a polygon. The polygon can be non convex, and is specified with a vector of vertexes. If the object's trajectory intersects some poligon side, it tries to slide around it, in a "rubber band flavoured" way. The object is assumed to initially be on the same position of the first vertex. This is a \b stateful manipulator, result of the Apply function is determined by the objects's position inside the area and by the mouse coordinates. */ class AreaMode:public TrackMode { public: /*! @brief The constructor. From the given vector, is calculated the plane of the polygon, then every point in the vector is projected on this plane. The vector passed to build the polygon is copied locally. @warning The vector is assumed to be formed of \b non collinear points. @warning The polygon is \b not assumed to have 0-length sides, so please do not add a copy of the first point on the end of the vector. @param pts the vertexes vector. */ AreaMode (const std::vector < Point3f > &pts) { Init(pts); assert(min_side_length > 0.0f); } /*! @brief Return this manipulator's name. @return the constant string "AreaMode" */ const char *Name () { return "AreaMode"; }; /*! @brief Apply a translation, function of the user mouse drag action. The manipulated object is moved inside the poligon. This function implements an algorithm that makes the object try to slide around the polygon borders. @param trackball the manipulator manager. @param new_point the new mouse pointer coordinate. */ void Apply (Trackball * trackball, Point3f new_point); /*! @brief Render this manipulator. @param trackball the manipulator manager. */ void Draw (Trackball * trackball); /*! @brief The begin action function. This function is to be called at the begin of an user action. */ void SetAction (); /*! @brief The reset function. This function reset the object position to the initial point. */ void Reset (); /*! @brief Try to set the inital point. This function try to set the starting point in the point passed as parameter, if the point passed does not reside in the area, the start is put in the closest point on it. @param p the point wished for the start. @return the starting point in the area. */ Point3f SetStartNear(Point3f p); /*! @brief The (non) avaibility to manipulator changes inside an action. This manipulator has an internal state and does not allow a switch in the middle of a function. @return The costant boolean true. */ bool isSticky(); /*! @brief The undo function. This function recreates the state present before the last Apply() call. */ void Undo(); private: /*! @brief The data initializer. Initialize the internal state and checks params validity. @param pts The polygon vertexes. */ void Init(const std::vector < Point3f > &pts); /*! @brief Point in Polygon test. Checks if a given point relies inside the poligon area, using the ray tracing algorithm, linear in the number of vertexes. @param point The point to test. @return true if the point is inside the polygon, false otherwise. */ bool Inside(Point3f point); /*! @brief Try to move the object inside the polygon Given a point inside the area and a destination in the poligon plane, try to move the point toward the destination, sliding on any evenual border of the polygon. The object can be imagined tied with a rubber attached to destination, so it won't go back from it to slide around a border. The algorithm is quadratic in the number of vertexes (worst case, really really unlikely). @param start the starting point assumed inside. @param end the destination assumed in the plane. @return the final move vector. */ Point3f Move(Point3f start,Point3f end); /// The vertexes vector. std::vector < Point3f > points; /// True in time inteval between a call to SetAction () and a call to Apply() bool begin_action; /// One of the two dimensions used during the point in polygon test. int first_coord_kept; /// One of the two dimensions used during the point in polygon test. int second_coord_kept; /// The length of the shortest border float min_side_length; /// The current status. Point3f status; /// The screen space differenve between the object and the cursor during an action. Point3f delta_mouse; /// The old status. Point3f old_status; /// The initial status. Point3f initial_status; /// The polygon plane Plane3f plane; /// The rubberband handle (current destination in Move()) Point3f rubberband_handle ; /// Current action's object trace std::vector < Point3f > path; /// begin_action after an Undo() call. bool undo_begin_action; /// status after an Undo() call. Point3f undo_status; /// delta_mouse after an Undo() call. Point3f undo_delta_mouse; /// old_status after an Undo() call. Point3f undo_old_status; /// rubberband_handle after an Undo() call. Point3f undo_rubberband_handle; /// path endpoint after an Undo() call. unsigned int undo_path_index; }; }//namespace #endif qutemol/vcg/wrap/gui/activecoordinateframe.h0000444000175000017500000001470510770756613017670 0ustar mbamba/**************************************************************************** * MeshLab o o * * A versatile mesh processing toolbox o o * * _ O _ * * Copyright(C) 2008 \/)\/ * * Visual Computing Lab /\/| * * ISTI - Italian National Research Council | * * \ * * All rights reserved. * * * * 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. * * * * 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 (http://www.gnu.org/licenses/gpl.txt) * * for more details. * * * ****************************************************************************/ /**************************************************************************** History $Log: activecoordinateframe.h,v $ Revision 1.2 2008/03/21 16:08:43 benedetti Added doxygen documentation Revision 1.1 2008/03/02 16:44:18 benedetti moved ActiveCoordinateFrame to its own files ****************************************************************************/ #ifndef ACTIVECOORDINATEFRAME_H #define ACTIVECOORDINATEFRAME_H #include "coordinateframe.h" #include #include namespace vcg { /*! @brief The ActiveCoordinateFrame class. This class implements an eulerian trackball over a Movable Coordinate Frame. */ class ActiveCoordinateFrame: public MovableCoordinateFrame { public: /*! @brief The constructor. Initialize the ActiveCoordinateFrame data. @param size the distance from the origin to the endpoint of the arrows. */ ActiveCoordinateFrame(float size); /*! @brief The destructor. The destructor. */ virtual ~ActiveCoordinateFrame(); /*! @brief Render the active coordinate frame in its position. @param glw the GL widget. */ virtual void Render(QGLWidget* glw); /*! @brief Reset the position and/or the rotation of the coordinate frame. @param reset_position set to true to reset the position. @param reset_alignment set to true to reset the rotation. */ virtual void Reset(bool reset_position,bool reset_alignment); /*! @brief Set the position of the coordinate frame. @param new_position the new position of the coordinate frame. */ virtual void SetPosition(const Point3f new_position); /*! @brief Set the rotation of the coordinate frame. @param new_rotation the new rotation of the coordinate frame. */ virtual void SetRotation(const Quaternionf rotation); /*! @brief Align the coordinate frame to one or two directions. If the primary direction of alignment is null this function does nothing, otherwise two rotations are performed: the first rotation aligns the axis named axis_1 to the primary direction of alignment, the second rotation never moves axis_1 away from the primary direction. If the secondary direction of alignment is not null and is not parallel to the primary direction the axis named axis_2 is rotated as much as possible to be aligned to secondary direction. If the secondary direction of alignment is null the axis named axis_2 is rotated as much as possible to be realigned to its old direction, if this is impossible the remaining axis is used. @param primary the primary direction of alignment. @param secondary the secondary direction of alignment. @param axis_1 the name of the axis to align to the primary direction, must be a char choosen from 'X', 'Y' and 'Z' @param axis_2 the name of the axis to align to the secondary direction, must be different from axis_1 and must be a char choosen from 'X', 'Y', 'Z' and ' '; if the char is ' ' the axis is choosen automatically. */ virtual void AlignWith(const Point3f primary, const Point3f secondary, const char axis_1, const char axis_2); /*! @brief Interface function relative to mouse down event in QT. @param x the x coordinate of the cursor. @param y the y coordinate of the cursor. @param button the keyboard modifiers state. */ void MouseDown(int x, int y, int button); /*! @brief Interface function relative to mouse move event in QT. @param x the x coordinate of the cursor. @param y the y coordinate of the cursor. */ void MouseMove(int x, int y); /*! @brief Interface function relative to mouse up event in QT. @param x the x coordinate of the cursor. @param y the y coordinate of the cursor. @param button the keyboard modifiers state. */ void MouseUp(int x, int y, int button); /*! @brief Interface function relative to keyboard up event in QT. @param button the keyboard modifiers state. */ void ButtonUp(int button); /*! @brief Interface function relative to keyboard down event in QT. @param button the keyboard modifiers state. */ void ButtonDown(int button); /*! @brief Set rotational snap value. @param value the new rotational snap value, in degrees. */ void SetSnap(float value); /// The eulerian trackball. Trackball *manipulator; /// The flag that enables moves feedback rendering bool drawmoves; /// The flag that enables rotations feedback rendering bool drawrotations; protected: // data: const int move_button,rotate_button; const int x_modifier,y_modifier,z_modifier; Point3f x_axis,y_axis,z_axis; float rot_snap_rad,mov_snap; // functions: virtual void Move(const Similarityf); void Update(); private: int movx,movy,movz,rotx,roty,rotz; }; }//namespace #endif /*ACTIVECOORDINATEFRAME_H*/ qutemol/vcg/wrap/gui/activecoordinateframe.cpp0000444000175000017500000002252710770756636020231 0ustar mbamba/**************************************************************************** * MeshLab o o * * A versatile mesh processing toolbox o o * * _ O _ * * Copyright(C) 2008 \/)\/ * * Visual Computing Lab /\/| * * ISTI - Italian National Research Council | * * \ * * All rights reserved. * * * * 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. * * * * 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 (http://www.gnu.org/licenses/gpl.txt) * * for more details. * * * ****************************************************************************/ /**************************************************************************** History $Log: activecoordinateframe.cpp,v $ Revision 1.2 2008/03/21 16:09:02 benedetti improved comments Revision 1.1 2008/03/02 16:44:18 benedetti moved ActiveCoordinateFrame to its own files ****************************************************************************/ #include #include #include #include #include "activecoordinateframe.h" using namespace vcg; ActiveCoordinateFrame::ActiveCoordinateFrame(float size) :MovableCoordinateFrame(size),manipulator(NULL),drawmoves(true), drawrotations(true),move_button(Trackball::BUTTON_RIGHT), rotate_button(Trackball::BUTTON_LEFT),x_modifier(Trackball::BUTTON_NONE), y_modifier(Trackball::KEY_CTRL),z_modifier(Trackball::KEY_SHIFT), x_axis(1,0,0),y_axis(0,1,0),z_axis(0,0,1),rot_snap_rad(0.0f),mov_snap(0.0f), movx(move_button | x_modifier),movy(move_button | y_modifier), movz(move_button | z_modifier),rotx(rotate_button | x_modifier), roty(rotate_button | y_modifier),rotz(rotate_button | z_modifier) { manipulator=new Trackball(); Update(); } ActiveCoordinateFrame::~ActiveCoordinateFrame() { if(manipulator!=NULL) { delete manipulator; manipulator=NULL; } } void ActiveCoordinateFrame::Render(QGLWidget* glw) { glPushMatrix(); manipulator->radius=size; manipulator->center=position; manipulator->GetView(); manipulator->Apply(false); MovableCoordinateFrame::Render(glw); // got nothing to draw if(!drawmoves && !drawrotations){ glPopMatrix(); return; } int current_mode=manipulator->current_button; bool rotating=(current_mode==rotx)||(current_mode==roty)||(current_mode==rotz); bool moving=(current_mode==movx)||(current_mode==movy)||(current_mode==movz); // maybe got something to draw glPushAttrib(GL_ALL_ATTRIB_BITS); glDisable(GL_LIGHTING); glDisable(GL_TEXTURE_2D); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glEnable(GL_LINE_SMOOTH); glEnable(GL_POINT_SMOOTH); QString message("this should never be seen"); char axis_name; float verse; if(current_mode==x_modifier){ glColor(xcolor); message = QString("move or rotate on X axis"); } else if(current_mode==y_modifier){ glColor(ycolor); message = QString("move or rotate on Y axis"); } else if(current_mode==z_modifier){ glColor(zcolor); message = QString("move or rotate on Z axis"); } else if(rotating && drawrotations){ // draw a rotation Point3f axis, arc_point; float angle; manipulator->track.rot.ToAxis(angle,axis); angle = -angle; if(current_mode==rotx){ verse=((axis+x_axis).Norm()<1?-1:1); glColor(xcolor); axis_name='x'; arc_point=y_axis*(size*0.8); } else if(current_mode==roty) { verse=((axis+y_axis).Norm()<1?-1:1); glColor(ycolor); axis_name='y'; arc_point=z_axis*(size*0.8); } else if(current_mode==rotz) { verse=((axis+z_axis).Norm()<1?-1:1); glColor(zcolor); axis_name='z'; arc_point=x_axis*(size*0.8); } else assert(0); // normalizing rotation between -180 and 180 degrees float sign = ((angle*verse)<0) ? -1 : 1; float abs_angle = (angle<0) ? -angle : angle; angle = sign * ( (abs_angle>M_PI) ? 2*M_PI-abs_angle : abs_angle ); axis = axis * verse; message = QString("rotated %1 deg around %2") .arg(((angle*180.0)/M_PI),5,'f',3) .arg(axis_name); Quaternionf arc_rot; arc_rot.FromAxis(angle/18.0,axis); glBegin(GL_POLYGON); glVertex(position); glVertex(position+arc_point); for(int i=0;i<18;i++){ arc_point = arc_rot.Rotate(arc_point); glVertex(position+arc_point); } glEnd(); } else if(moving && drawmoves){ // draw a traslation Point3f ntra=manipulator->track.tra; ntra.Normalize(); if(current_mode==movx){ verse=((ntra+x_axis).Norm()<1?-1:1); glColor(xcolor); axis_name='x'; }else if(current_mode==movy){ verse=((ntra+y_axis).Norm()<1?-1:1); glColor(ycolor); axis_name='y'; }else if(current_mode==movz){ verse=((ntra+z_axis).Norm()<1?-1:1); glColor(zcolor); axis_name='z'; }else assert(0); message = QString("moved %1 units along %2") .arg(verse*manipulator->track.tra.Norm(),5,'f',3) .arg(axis_name); Point3f old_pos = position-manipulator->track.tra; glLineWidth(2*linewidth); glPointSize(4*linewidth); glBegin(GL_LINES); glVertex(position); glVertex(old_pos); glEnd(); glBegin(GL_POINTS); glVertex(old_pos); glEnd(); } else { // got nothing to draw glPopAttrib(); glPopMatrix(); return; } // draw message below cursor font.setBold(true); font.setPixelSize(12); QPoint cursor=glw->mapFromGlobal(glw->cursor().pos()); glw->renderText(cursor.x()+16,cursor.y()+16,message,font); glPopAttrib(); glPopMatrix(); } void ActiveCoordinateFrame::Reset(bool reset_position,bool reset_alignment) { MovableCoordinateFrame::Reset(reset_position, reset_alignment); Update(); manipulator->Reset(); } void ActiveCoordinateFrame::SetPosition(const Point3f newpos) { MovableCoordinateFrame::SetPosition(newpos); Update(); manipulator->Reset(); } void ActiveCoordinateFrame::SetRotation(const Quaternionf newrot) { MovableCoordinateFrame::SetRotation(newrot); Update(); manipulator->Reset(); } void ActiveCoordinateFrame::AlignWith(const Point3f primary,const Point3f secondary,const char c1,const char c2) { MovableCoordinateFrame::AlignWith(primary,secondary,c1,c2); Update(); manipulator->Reset(); } void ActiveCoordinateFrame::MouseDown(int x, int y, /*Button*/ int button) { Move(manipulator->track); manipulator->Reset(); manipulator->MouseDown(x,y,button); } void ActiveCoordinateFrame::MouseMove(int x, int y) { manipulator->MouseMove(x,y); } void ActiveCoordinateFrame::MouseUp(int x, int y, /*Button */ int button) { Move(manipulator->track); manipulator->Reset(); manipulator->MouseUp(x, y, button); } void ActiveCoordinateFrame::ButtonUp(int button) { Move(manipulator->track); manipulator->Reset(); manipulator->ButtonUp((Trackball::Button) button); } void ActiveCoordinateFrame::ButtonDown(int button) { Move(manipulator->track); manipulator->Reset(); manipulator->ButtonDown((Trackball::Button) button); } void ActiveCoordinateFrame::SetSnap(float rot_deg) { assert((rot_deg>=0.0)&&(rot_deg<=180)); rot_snap_rad=rot_deg*M_PI/180.0; Update(); } void ActiveCoordinateFrame::Move(const Similarityf track) { MovableCoordinateFrame::Move(track); Update(); } void ActiveCoordinateFrame::Update() { movx=(move_button | x_modifier); movy=(move_button | y_modifier); movz=(move_button | z_modifier); rotx=(rotate_button | x_modifier); roty=(rotate_button | y_modifier); rotz=(rotate_button | z_modifier); Point3f p=position; Quaternionf r=Inverse(rotation); x_axis=r.Rotate(Point3f(1,0,0)); y_axis=r.Rotate(Point3f(0,1,0)); z_axis=r.Rotate(Point3f(0,0,1)); std::map::iterator it; for(it = manipulator->modes.begin(); it != manipulator->modes.end(); it++) { if ((*it).second) delete (*it).second; } manipulator->modes.clear(); manipulator->modes[0] = NULL; manipulator->modes[movx] = new AxisMode(p,x_axis); manipulator->modes[movy] = new AxisMode(p,y_axis); manipulator->modes[movz] = new AxisMode(p,z_axis); manipulator->modes[rotx] = new CylinderMode(p,x_axis,rot_snap_rad); manipulator->modes[roty] = new CylinderMode(p,y_axis,rot_snap_rad); manipulator->modes[rotz] = new CylinderMode(p,z_axis,rot_snap_rad); manipulator->SetCurrentAction(); } qutemol/vcg/wrap/gui/coordinateframe.h0000444000175000017500000001666710777372556016514 0ustar mbamba/**************************************************************************** * MeshLab o o * * A versatile mesh processing toolbox o o * * _ O _ * * Copyright(C) 2008 \/)\/ * * Visual Computing Lab /\/| * * ISTI - Italian National Research Council | * * \ * * All rights reserved. * * * * 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. * * * * 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 (http://www.gnu.org/licenses/gpl.txt) * * for more details. * * * ****************************************************************************/ /**************************************************************************** History $Log: coordinateframe.h,v $ Revision 1.8 2008/04/10 11:09:34 cignoni made generic functions static Revision 1.7 2008/03/14 16:54:34 benedetti Added doxygen documentation Revision 1.6 2008/03/02 16:44:18 benedetti moved ActiveCoordinateFrame to its own files Revision 1.5 2008/02/22 20:04:02 benedetti many user interface improvements, cleaned up a little Revision 1.4 2008/02/17 20:52:53 benedetti some generalization made Revision 1.3 2008/02/16 14:12:30 benedetti first version ****************************************************************************/ #ifndef COORDINATEFRAME_H #define COORDINATEFRAME_H #include #include #include namespace vcg { /*! @brief The CoordinateFrame class. This class can draw the standard icon for a 3D coordinate frame. */ class CoordinateFrame { public: // functions: /*! @brief The constructor. Initialize the CoordinateFrame data. @param size the distance from the origin to the endpoint of the arrows. */ CoordinateFrame(float size); /*! @brief The destructor. The destructor. */ virtual ~CoordinateFrame() {} /*! @brief Render the coordinate frame. @param glw the GL widget. */ virtual void Render(QGLWidget* glw); // data /// The color used for the ticks, the ticks values and the head of the arrows. Color4b basecolor; /// The color of the X axis and label. Color4b xcolor; /// The color of the Y axis and label. Color4b ycolor; /// The color of the Z axis and label. Color4b zcolor; /// The distance from the origin to the endpoint of the arrows. float size; /// The width of the lines. float linewidth; /// The font used for the labels and the ticks values. QFont font; /// The flag that enables axes rendering. bool drawaxis; /// The flag that enables lablels rendering. bool drawlabels; /// The flag that enables ticks values rendering. bool drawvalues; // useful functions: static void drawTickedLine(const Point3d &, const Point3d &, float, float,float); static float calcSlope(const Point3d &, const Point3d &, float, int , double *, double *, GLint *); static float niceRound(float); }; /*! @brief The MovableCoordinateFrame class. This class extends the coordinate frame with the ability of being programmatically rototranslated. */ class MovableCoordinateFrame: public CoordinateFrame { public: /*! @brief The constructor. Initialize the MovableCoordinateFrame data. @param size the distance from the origin to the endpoint of the arrows. */ MovableCoordinateFrame(float); /*! @brief The destructor. The destructor. */ virtual ~MovableCoordinateFrame(){} /*! @brief Render the movable coordinate frame in its position. @param glw the GL widget. */ virtual void Render(QGLWidget* glw); /*! @brief Reset the position and/or the rotation of the coordinate frame. @param reset_position set to true to reset the position. @param reset_alignment set to true to reset the rotation. */ virtual void Reset(bool reset_position,bool reset_alignment); /*! @brief Set the position of the coordinate frame. @param new_position the new position of the coordinate frame. */ virtual void SetPosition(const Point3f new_position); /*! @brief Set the rotation of the coordinate frame. @param new_rotation the new rotation of the coordinate frame. */ virtual void SetRotation(const Quaternionf rotation); /*! @brief Get the position of the coordinate frame. @return the position of the coordinate frame. */ virtual Point3f GetPosition(); /*! @brief Get the rotation of the coordinate frame. @return the rotation of the coordinate frame. */ virtual Quaternionf GetRotation(); /*! @brief Computes the transformation matrix relative to the current rototranslation. @param m is set to the transformation matrix. */ virtual void GetTransform(Matrix44f &m); /*! @brief Rotates the coordinate frame wrt itself. @param angle the angle of the rotation, in degrees. @param axis the axis of the rotation. */ virtual void Rot(float angle,const Point3f axis); /*! @brief Align the coordinate frame to one or two directions. If the primary direction of alignment is null this function does nothing, otherwise two rotations are performed: the first rotation aligns the axis named axis_1 to the primary direction of alignment, the second rotation never moves axis_1 away from the primary direction. If the secondary direction of alignment is not null and is not parallel to the primary direction the axis named axis_2 is rotated as much as possible to be aligned to secondary direction. If the secondary direction of alignment is null the axis named axis_2 is rotated as much as possible to be realigned to its old direction, if this is impossible the remaining axis is used. @param primary the primary direction of alignment. @param secondary the secondary direction of alignment. @param axis_1 the name of the axis to align to the primary direction, must be a char choosen from 'X', 'Y' and 'Z' @param axis_2 the name of the axis to align to the secondary direction, must be different from axis_1 and must be a char choosen from 'X', 'Y', 'Z' and ' '; if the char is ' ' the axis is choosen automatically. */ virtual void AlignWith(const Point3f primary, const Point3f secondary, const char axis_1, const char axis_2); protected: // data: Point3f position; Quaternionf rotation; // functions: virtual void Move(const Similarityf); void RotateToAlign(const Point3f, const Point3f); }; }//namespace #endif /*COORDINATEFRAME_H*/ qutemol/vcg/wrap/gui/trackutils.h0000444000175000017500000010663310761060273015507 0ustar mbamba/**************************************************************************** * VCGLib o o * * Visual and Computer Graphics Library o o * * _ O _ * * Copyright(C) 2004 \/)\/ * * Visual Computing Lab /\/| * * ISTI - Italian National Research Council | * * \ * * All rights reserved. * * * * 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. * * * * 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 (http://www.gnu.org/licenses/gpl.txt) * * for more details. * * * ****************************************************************************/ /**************************************************************************** History $Log: trackutils.h,v $ Revision 1.14 2008/02/26 18:55:55 ponchio removed some garbage. Revision 1.13 2008/02/26 18:46:55 ponchio Fixed bug in drawing position of the trackball when changin center. Revision 1.12 2008/02/24 18:10:54 ponchio Fixed scale behaviour. Revision 1.11 2008/02/24 18:05:08 ponchio Should work as before. I didn't test cylinder and other exotic modes. Revision 1.10 2008/02/24 14:37:00 ponchio Restored trackball functionality. Not very much tested, and code will need some cleanup. Revision 1.9 2008/02/22 18:57:47 benedetti first attempt to correct after quaternion ToMatrix() inversion (does not work yet) Revision 1.8 2008/02/15 20:54:45 benedetti removed some variable initialization related warning Revision 1.7 2007/10/22 14:39:54 cignoni corrected bug into the drawsphere (thanks to nico and guido!) Revision 1.6 2007/08/17 09:19:40 cignoni glEnable (GL_LINE_SMOOTH) should go before changing the linewidth. Revision 1.5 2007/07/14 12:44:40 benedetti Minor edits in Doxygen documentation. Revision 1.4 2007/07/09 22:41:22 benedetti Added Doxygen documentation, removed using namespace std, some other minor changes. Revision 1.3 2007/06/12 08:58:08 benedetti Minor fix in DrawUglyCylinderMode() Revision 1.2 2007/05/28 08:10:47 fiorin Removed type cast warnings Revision 1.1 2007/05/15 14:57:34 benedetti Utility functions for the trackmodes, first version ****************************************************************************/ #ifndef TRACKUTILS_H #define TRACKUTILS_H #include #include #include #include #include #include #include #include #include #include using namespace std; namespace vcg { /*! @brief This namespace contains some support functions used by TrackMode subclassess. \warning Many of these functions shouldn't be here and are supposed to be moved to some appropriate place by the library administrator. \warning The \e DrawUgly series of functions is a \b TEMPORARY solution, used while waiting for the \e DrawBeautiful series... */ namespace trackutils { /*! @brief Compute the plane perpedicular to view dir and passing through the manipulator center. @param camera the camera of the manipulator. @param center the center of the manipulator. @return the plane perpedicular to view dir and passing through the manipulator center. */ Plane3f GetViewPlane (const View < float >&camera, const Point3f & center) { Point3f vp = camera.ViewPoint (); Plane3f pl; Point3f plnorm = vp - center; plnorm.Normalize (); pl.Set (plnorm, plnorm * center); return pl; } /*! @brief Convert a line to a normalized ray. @param l the line to be converted. @return the normalized ray. */ Ray3f line2ray(const Line3f &l){ Ray3f r(l.Origin(),l.Direction()); r.Normalize(); return r; } /*! @brief Project a window coordinate point on the plane perpedicular to view dir and passing through the manipulator center. @param tb the manipulator. @param p the window coordinate point. @return p's projection on plane perpedicular to view dir and passing through the manipulator center. */ Point3f HitViewPlane (Trackball * tb, const Point3f & p) { Plane3f vp = GetViewPlane (tb->camera, tb->center); Line3fN ln = tb->camera.ViewLineFromWindow (Point3f (p[0], p[1], 0)); Point3f PonVP; IntersectionLinePlane < float >(vp, ln, PonVP); return PonVP; } // nota: non ho scritto io questa funzione, // quindi la documentazione doxy potrebbe non essere accurata al 100%. /*! @brief Project a window coordinate point on the rotational hyperboloid relative to the manipulator.
The original documentation (in italian) follows:
dato un punto in coordinate di schermo e.g. in pixel stile opengl 
calcola il punto di intersezione tra la viewline  che passa per 
viewpoint e per hitplane e l'iperboloide.
l'iperboloide si assume essere quello di rotazione attorno alla 
retta viewpoint-center e di raggio rad
si assume come sistema di riferimento quello con l'origine 
su center ecome x la retta center-viewpoint

eq linea
       hitplane.y
y = - ----------- * x + hitplane.y 
      viewpoint.x

eq hiperboloide di raggio r (e.g. che passa per (r/sqrt2,r/sqrt2) 

     1
y = --- * (r^2 /2.0)
     x 

 hitplane.y
 ----------- * x^2 - hitplane.y *x + (r^2/2.0) == 0
 viewpoint.x
@param center the center of the manipulator. @param radius the radius of the manipulator. @param viewpoint the view point. @param vp the view plane. @param hitplane the projection of the window coordinate point on the view plane. @param hit the projection of hitplane on the rotational hyperboloid relative to the manipulator. @return true if and only if hit is valid. */ bool HitHyper (Point3f center, float radius, Point3f viewpoint, Plane3f vp, Point3f hitplane, Point3f & hit) { float hitplaney = Distance (center, hitplane); float viewpointx = Distance (center, viewpoint); float a = hitplaney / viewpointx; float b = -hitplaney; float c = radius * radius / 2.0f; float delta = b * b - 4 * a * c; float x1, x2, xval, yval; if (delta > 0) { x1 = (-b - sqrt (delta)) / (2.0f * a); x2 = (-b + sqrt (delta)) / (2.0f * a); xval = x1; // always take the minimum value solution yval = c / xval; // alternatively it also could be the other part of the equation yval=-(hitplaney/viewpointx)*xval+hitplaney; } else { return false; } // Computing the result in 3d space; Point3f dirRadial = hitplane - center; dirRadial.Normalize (); Point3f dirView = vp.Direction (); dirView.Normalize (); hit = center + dirRadial * yval + dirView * xval; return true; } // nota: non ho scritto io questa funzione, // quindi la documentazione doxy potrebbe non essere accurata al 100%. /*! @brief Project a window coordinate point on the sphere relative to the manipulator.
The original documentation (in italian) follows:
dato un punto in coordinate di schermo e.g. in pixel stile opengl 
restituisce un punto in coordinate di mondo sulla superficie 
della trackball.
La superficie della trackball e' data da una sfera + una porzione 
di iperboloide di rotazione.
Assumiamo la sfera di raggio unitario e centrata sull'origine e 
di guardare lungo la y negativa.

                                    X   0   sqrt(1/2)  1  
eq sfera:              y=sqrt(1-x*x);   1   sqrt(1/2)  0   
eq iperboloide :       y=1/2*x;         inf  sqrt(1/2)  1/2
eq cono                y=x+sqrt(2);
@param tb the manipulator. @param p the window coordinate point. @return the projection of p on the sphere relative to the manipulator. */ Point3f HitSphere (Trackball * tb, const Point3f & p) { Point3f center = tb->center; Line3fN ln = tb->camera.ViewLineFromWindow (Point3f (p[0], p[1], 0)); Plane3f vp = GetViewPlane (tb->camera, center); Point3f hitPlane(0,0,0), //intersection view plane with point touched hitSphere(0,0,0), hitSphere1(0,0,0), hitSphere2(0,0,0), hitHyper(0,0,0); IntersectionLinePlane < float >(vp, ln, hitPlane); Sphere3f sphere (center, tb->radius);//trackball sphere bool resSp = IntersectionLineSphere < float >(sphere, ln, hitSphere1, hitSphere2); Point3f viewpoint = tb->camera.ViewPoint (); if (resSp == true) { if (Distance (viewpoint, hitSphere1) < Distance (viewpoint, hitSphere2)) hitSphere = hitSphere1; else hitSphere = hitSphere2; } /*float dl= */ Distance (ln, center); bool resHp = HitHyper (center, tb->radius, viewpoint, vp, hitPlane, hitHyper); // four cases // 1) Degenerate line tangent to both sphere and hyperboloid! if ((!resSp && !resHp)) { Point3f hit = ClosestPoint (ln, center); //printf("closest point to line %f\n",Distance(hit,tb->center)); return hit; } if ((resSp && !resHp)) return hitSphere; // 2) line cross only the sphere if ((!resSp && resHp)) return hitHyper; // 3) line cross only the hyperboloid // 4) line cross both sphere and hyperboloid: choose according angle. float angleDeg = math::ToDeg (Angle ((viewpoint - center), (hitSphere - center))); //printf("Angle %f (%5.2f %5.2f %5.2f) (%5.2f %5.2f %5.2f)\n",angleDeg,hitSphere[0],hitSphere[1],hitSphere[2],hitHyper[0],hitHyper[1],hitHyper[2]); if (angleDeg < 45) return hitSphere; else return hitHyper; // Codice ORIGINALE PONCHIO //vp.SetOffset(vp.Offset() + Thr); //Point3f hit; //bool res = Intersection(vp, ln, hit); //float d = Distance(tb->center - vn.Direction()*Thr, hit); //if(d < Thr) { // Point3f hit2; // Sphere3f sphere(tb->center, tb->radius); // bool res = Intersection(sphere, ln, hit, hit2); // //find closest intersection to sphere // float d = (hit - viewpoint).Norm(); // float d2 = (hit2 - viewpoint).Norm(); // if(d > d2) hit = hit2; // hit -= tb->center; //} else { // if(d > 2.99 * Thr) // d = 2.99 * Thr; // Point3f norm = (hit - tb->center)^(viewpoint - tb->center); // norm.Normalize(); // float phi = -M_PI/4 - 3*M_PI/8 *(d - Thr)/Thr; // Quaternionf q(phi, norm); // hit = q.Rotate((viewpoint - tb->center).Normalize() * tb->radius); //} // hit.Normalize(); // return hit; } /*! @brief Calculates the minimal distance between 2 lines. P and Q are the lines, P_s and Q_t are set to be the closest points on these lines. it's returned the distance from P_s and Q_t, and a boolean value which is true if the lines are parallel enough. if P and Q are parallel P_s and Q_t aren't set. the formula is taken from pages 81-83 of "Eric Lengyel - Mathematics for 3D Game Programming & Computer Graphics" @param P the first line. @param Q the second line. @param P_s the point on P closest to Q. @param Q_t the point on Q closest to P. @return a std::pair made with the distance from P_s to Q_t and a boolean value, true if and only if P and Q are almost parallel. */ std::pair< float, bool > LineLineDistance(const Line3f & P,const Line3f & Q,Point3f & P_s, Point3f & Q_t){ Point3f p0 = P.Origin (), Vp = P.Direction (); Point3f q0 = Q.Origin (), Vq = Q.Direction (); float VPVP = Vp * Vp; float VQVQ = Vq * Vq; float VPVQ = Vp * Vq; const float det = ( VPVP * VQVQ ) - ( VPVQ * VPVQ ); const float EPSILON = 0.00001f; if ( fabs(det) < EPSILON ) { return std::make_pair(Distance(P,q0), true); } float b1= (q0 - p0) * Vp; float b2= (p0 - q0) * Vq; float s = ( (VQVQ * b1) + (VPVQ * b2) ) / det; float t = ( (VPVQ * b1) + (VPVP * b2) ) / det; P_s = p0 + (Vp * s); Q_t = q0 + (Vq * t); return std::make_pair(Distance(P_s,Q_t),false); } /*! @brief Calculates the minimal distance between a ray and a line. R is the ray and Q is the line, R_s and Q_t are set to be the closest points on the ray and the line. it's returned the distance from R_s and Q_t, and a boolean value which is true if the ray and the line are parallel enough. if R and Q are parallel R_s and Q_t aren't set. @param R the ray. @param Q the line. @param R_s the point on R closest to Q. @param Q_t the point on Q closest to R. @return a std::pair made with the distance from R_s to Q_t and a boolean value, true if and only if P and Q are almost parallel. */ std::pair< float, bool > RayLineDistance(const Ray3f & R,const Line3f & Q,Point3f & R_s, Point3f & Q_t){ Point3f r0 = R.Origin (), Vr = R.Direction (); Point3f q0 = Q.Origin (), Vq = Q.Direction (); float VRVR = Vr * Vr; float VQVQ = Vq * Vq; float VRVQ = Vr * Vq; const float det = ( VRVR * VQVQ ) - ( VRVQ * VRVQ ); const float EPSILON = 0.00001f; if ( ( det >= 0.0f ? det : -det) < EPSILON ) { return std::make_pair(Distance(Q,r0), true); } float b1= (q0 - r0) * Vr; float b2= (r0 - q0) * Vq; float s = ( (VQVQ * b1) + (VRVQ * b2) ) / det; float t = ( (VRVQ * b1) + (VRVR * b2) ) / det; if(s<0){ R_s = r0; Q_t = ClosestPoint(Q,R_s); }else { R_s = r0 + (Vr * s); Q_t = q0 + (Vq * t); } return std::make_pair(Distance(R_s,Q_t),false); } /*! @brief Calculates the minimal distance between 2 segments. R e Q are the segments, R_s and Q_t are set to be the closest points on the segments. it's returned the distance from R_s and Q_t, and a boolean value which is true if the segments are parallel enough. @param R the first segment. @param Q the second segment. @param R_s the point on R closest to Q. @param Q_t the point on Q closest to R. @return a std::pair made with the distance from R_s to Q_t and a boolean value, true if and only if P and Q are almost parallel. */ std::pair< float, bool > SegmentSegmentDistance(const Segment3f & R, const Segment3f & Q, Point3f & R_s, Point3f & Q_t) { float R_len=Distance(R.P0(),R.P1()); float Q_len=Distance(Q.P0(),Q.P1()); const float EPSILON_LENGTH = std::max(R_len,Q_len)*0.0001f; if(R_len < EPSILON_LENGTH){ R_s=R.P0(); Q_t=ClosestPoint(Q,R_s); return std::make_pair(Distance(R_s,Q_t),true); } if( Q_len < EPSILON_LENGTH){ Q_t=Q.P0(); R_s=ClosestPoint(R,Q_t); return std::make_pair(Distance(R_s,Q_t),true); } Point3f r0 = R.P0(), Vr = (R.P1()-R.P0()).Normalize(); Point3f q0 = Q.P0(), Vq = (Q.P1()-Q.P0()).Normalize(); float VRVR = Vr * Vr; float VQVQ = Vq * Vq; float VRVQ = Vr * Vq; const float det = ( VRVR * VQVQ ) - ( VRVQ * VRVQ ); const float EPSILON = 0.00001f; if ( ( det >= 0.0f ? det : -det) < EPSILON ) { Line3f lR(R.P0(),R.P1()); float qa=lR.Projection(Q.P0()); float qb=lR.Projection(Q.P1()); if( (qa<=0.0f) && qb<=(0.0f)){ R_s=R.P0(); Q_t=ClosestPoint(Q,R_s); } else if ( (qa >= 1.0f) && (qb >= 1.0f) ){ R_s=R.P1(); Q_t=ClosestPoint(Q,R_s); } else { if( (qa >= 0.0f) && (qa <= 1.0f) ){ Q_t=Q.P0(); R_s=ClosestPoint(R,Q_t); } else if((qb >= 0.0f) && (qb <= 1.0f) ){ Q_t=Q.P1(); R_s=ClosestPoint(R,Q_t); } else { if( ((qa<=0.0f)&&(qb>=1.0f) ||((qb<=0.0f)&&(qa>=1.0f)))){ R_s=R.P0(); Q_t=ClosestPoint(Q,R_s); }else{ assert(0); } } } return std::make_pair(Distance(R_s,Q_t),true); } float b1= (q0 - r0) * Vr; float b2= (r0 - q0) * Vq; float s = ( (VQVQ * b1) + (VRVQ * b2) ) / det; float t = ( (VRVQ * b1) + (VRVR * b2) ) / det; if( s < 0 ){ R_s = R.P0(); }else if ( s > R_len ){ R_s = R.P1(); } else { R_s = r0 + (Vr * s); } if( t < 0){ Q_t = Q.P0(); }else if ( t > Q_len ){ Q_t = Q.P1(); }else{ Q_t = q0 + (Vq * t); } return std::make_pair(Distance(R_s,Q_t),false); } /*! @brief Compute the point on a line closest to the ray projection of a window coordinate point. Given a window coordinate point, computes a ray starting from the manipulator camera eye and passing through the point's projection on the viewplane, then uses RayLineDistance() to get the closest point to ray on a given line. @see RayLineDistance(const Ray3f & R,const Line3f & Q,Point3f & R_s, Point3f & Q_t) @param tb the manipulator. @param axis the axis. @param point the window coordinate point. @return a std::pair made with the point on axis closest to the ray projection of point and a boolean true if and only if the ray doesn't diverges respect to the axis. */ std::pair< Point3f,bool > HitNearestPointOnAxis (Trackball * tb,Line3f axis, Point3f point) { Ray3fN ray = line2ray(tb->camera.ViewLineFromWindow (point)); Point3f axis_p(0,0,0), ray_p(0,0,0); std::pair< float, bool > resp=RayLineDistance(ray,axis,ray_p,axis_p); if(resp.second || (ray_p == ray.Origin())){ return std::make_pair(Point3f(0,0,0),false); } return std::make_pair(axis_p,true); } /*! @brief Project a line into a plane. Given a line and a plane, returns the line projection on the plane. The line returned is \e not normalized. @param ln the line. @param pl the plane. @return the (non normalized) line projected. */ Line3f ProjectLineOnPlane(const Line3f & ln, const Plane3f & pl) { Point3f l0=ln.Origin(); Point3f l1=l0+ln.Direction(); Point3f p1,p2; p1=pl.Projection(l0); p2=pl.Projection(l1); Line3f res(p1,p2-p1); return res; } /*! @brief Computes a signed line-point distance. Given a line, a point and a positivity direction, computes the signed distance between the line and the point. @param line the line. @param pt the point. @param positive_dir the positivity direction. @return the signed distance. */ float signedDistance(Line3f line,Point3f pt,Point3f positive_dir) { return Distance(line,pt) * ((((pt-ClosestPoint(line,pt)) * positive_dir) >= 0.0f )? 1.0f: -1.0f); } /*! @brief Computes the verical component of an user mouse drag. @param tb the manipulator. @param new_point the new mouse pointer coordinate. @return The verical component of the user mouse drag. */ float getDeltaY(Trackball * tb, Point3f new_point) { float ScreenHeight = float (tb->camera.viewport[3] - tb->camera.viewport[1]); return (new_point[1] - tb->last_point[1]) / ScreenHeight; } /*! @brief Computes the intersection between a ray and a plane. @param pl the plane. @param ray the ray. @param po the intersection point. @return true if and only if there is intersection (po is valid). */ template inline bool IntersectionRayPlane( const Plane3 & pl, const Ray3 & ray, Point3 &po){ const T epsilon = T(1e-8); T k = pl.Direction() * ray.Direction(); // Compute 'k' factor if( (k > -epsilon) && (k < epsilon)) return false; T r = (pl.Offset() - pl.Direction()*ray.Origin())/k; // Compute ray distance if (r < 0) return false; po = ray.Origin() + ray.Direction()*r; return true; } /*! @brief Project a window coordinate point on a plane. Given a window coordinate point, computes a ray starting from the manipulator camera eye and passing through the point's projection on the viewplane, then uses IntersectionRayPlane() to get the ray intersection with a given plane. @see IntersectionRayPlane() @param tb the manipulator. @param point the window coordinate point. @param plane the plane. @return a std::pair made with p's projection on the.plane and a boolean true if and only if the ray doesn't diverges respect to the plane. */ std::pair< Point3f, bool > HitPlane (Trackball * tb, Point3f point, Plane3f plane) { Ray3fN ray = line2ray(tb->camera.ViewLineFromWindow (point)); Point3f p(0,0,0); bool res = IntersectionRayPlane < float >(plane, ray, p); return std::make_pair(p,res); } // drawing section // nota: non ho scritto io questa classe, // quindi la documentazione doxy potrebbe non essere accurata al 100%. /*! @brief Drawing hints for manipulators This class is an holder for drawing-related variables. It's mainly used for SphereMode and InactiveMode drawings. */ class DrawingHint { public: /*! @brief Drawing hints constructor assign the drawing-related variables. */ DrawingHint () { CircleStep = 64; HideStill = false; DrawTrack = false; LineWidthStill = 0.5f; LineWidthMoving = 1.5f; color = Color4b::LightBlue; } /// The circles resolution. int CircleStep; /// currently not in use. bool HideStill; /// currently not in use. bool DrawTrack; /// circle color Color4b color; /// circle line width when inactive. float LineWidthStill; /// circle line width when active. float LineWidthMoving; }; /// the drawing hint used by the manipulators DrawingHint DH; // nota: non ho scritto io questa funzione, // quindi la documentazione doxy potrebbe non essere accurata al 100%. /*! @brief Draw 2 squares, used by DrawCircle(). */ void DrawPlaneHandle () { float r = 1.0; float dr = r / 10.0f; glBegin (GL_LINE_STRIP); glVertex3f (+r + dr, +r, 0.0); glVertex3f (+r, +r + dr, 0.0); glVertex3f (+r - dr, +r, 0.0); glVertex3f (+r, +r - dr, 0.0); glVertex3f (+r + dr, +r, 0.0); glEnd (); glBegin (GL_LINE_STRIP); glVertex3f (-r + dr, -r, 0.0); glVertex3f (-r, -r + dr, 0.0); glVertex3f (-r - dr, -r, 0.0); glVertex3f (-r, -r - dr, 0.0); glVertex3f (-r + dr, -r, 0.0); glEnd (); } // nota: non ho scritto io questa funzione, // quindi la documentazione doxy potrebbe non essere accurata al 100%. /*! @brief Draw a circle with 2 squares, used by DrawSphereIcon(). */ void DrawCircle () { int nside = DH.CircleStep; const double pi2 = 3.14159265 * 2.0; glBegin (GL_LINE_LOOP); for (double i = 0; i < nside; i++) { glNormal3d (cos (i * pi2 / nside), sin (i * pi2 / nside), 0.0); glVertex3d (cos (i * pi2 / nside), sin (i * pi2 / nside), 0.0); } glEnd (); DrawPlaneHandle (); } /*! @brief Draw a spherical manipulator icon. @param tb the manipulator. @param active boolean to be set to true if the icon is active. */ void DrawSphereIcon (Trackball * tb,bool active) { glPushAttrib (GL_TRANSFORM_BIT |GL_ENABLE_BIT | GL_LINE_BIT | GL_CURRENT_BIT | GL_LIGHTING_BIT); glMatrixMode(GL_MODELVIEW); glPushMatrix (); Point3f center = tb->center + tb->track.InverseMatrix()*Point3f(0, 0, 0); glTranslate(center); glScale (tb->radius/tb->track.sca); float amb[4] = { .3f, .3f, .3f, 1.0f }; float col[4] = { .5f, .5f, .8f, 1.0f }; glEnable (GL_LINE_SMOOTH); if (active) glLineWidth (DH.LineWidthMoving); else glLineWidth (DH.LineWidthStill); glEnable (GL_LIGHTING); glEnable (GL_LIGHT0); glEnable (GL_BLEND); glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glColor (DH.color); glMaterialfv (GL_FRONT_AND_BACK, GL_EMISSION, amb); glMaterialfv (GL_FRONT_AND_BACK, GL_DIFFUSE, col); DrawCircle (); glRotatef (90, 1, 0, 0); DrawCircle (); glRotatef (90, 0, 1, 0); DrawCircle (); glPopMatrix (); glPopAttrib (); } // TEMPORARY drawing section // Disclaimer: the following code is of VERY POOR quality // feel free to delete and rewrite everything /*! @brief Support function for the \e DrawUgly series of functions Prepare the OpenGL attributes. \warning this method is part of the \e DrawUgly series of functions, which is a \b TEMPORARY solution, used while waiting for the \e DrawBeautiful series... */ void prepare_attrib() { float amb[4] = { .3f, .3f, .3f, 1.0f }; float col[4] = { .5f, .5f, .8f, 1.0f }; glEnable (GL_LIGHTING); glEnable (GL_LIGHT0); glEnable (GL_LINE_SMOOTH); glEnable (GL_BLEND); glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glMaterialfv (GL_FRONT_AND_BACK, GL_EMISSION, amb); glMaterialfv (GL_FRONT_AND_BACK, GL_DIFFUSE, col); } /*! @brief Support function for the \e DrawUgly series of functions. Draw a coordinate vector, usually a letter, near the manipulator icon in a user readable oriantation. \warning this method is part of the \e DrawUgly series of functions, which is a \b TEMPORARY solution, used while waiting for the \e DrawBeautiful series... @param tb the manipulator. @param ugly_letter the coordinate vector. */ void DrawUglyLetter(Trackball * tb,std::vector ugly_letter) { Point3f center=tb->camera.Project(tb->center); float offset=0; offset=std::max(offset,Distance(center,tb->camera.Project(tb->center+(Point3f(1,0,0) * tb->radius)))); offset=std::max(offset,Distance(center,tb->camera.Project(tb->center+(Point3f(0,1,0) * tb->radius)))); offset=std::max(offset,Distance(center,tb->camera.Project(tb->center+(Point3f(0,0,1) * tb->radius)))); glPushMatrix(); glPushAttrib (GL_ALL_ATTRIB_BITS); // go to world coords glTranslate (tb->center); glMultMatrix (tb->track.InverseMatrix ()); glTranslate (-tb->center); prepare_attrib(); glColor3f(1,1,1); glLineWidth(4.0); glBegin(GL_LINE_STRIP); for(unsigned int i=0;icamera.UnProject(center+(ugly_letter[i] * offset * 0.25) +Point3f(-offset,-offset,0))); } glEnd(); glPopAttrib (); glPopMatrix(); } /*! @brief PanMode drawing function, member of the \e DrawUgly series. Draw a PanMode manipulator in an ugly way. \warning this method is part of the \e DrawUgly series of functions, which is a \b TEMPORARY solution, used while waiting for the \e DrawBeautiful series... @param tb the manipulator. */ void DrawUglyPanMode(Trackball * tb) { std::vector ugly_p; ugly_p.push_back(Point3f(-1,-1,0)); ugly_p.push_back(Point3f(-1,1,0)); ugly_p.push_back(Point3f(1,1,0)); ugly_p.push_back(Point3f(1,0,0)); ugly_p.push_back(Point3f(-1,0,0)); DrawUglyLetter(tb,ugly_p); } /*! @brief ZMode drawing function, member of the \e DrawUgly series. Draw a ZMode manipulator in an ugly way. \warning this method is part of the \e DrawUgly series of functions, which is a \b TEMPORARY solution, used while waiting for the \e DrawBeautiful series... @param tb the manipulator. */ void DrawUglyZMode(Trackball * tb) { std::vector ugly_z; ugly_z.push_back(Point3f(-1,1,0)); ugly_z.push_back(Point3f(1,1,0)); ugly_z.push_back(Point3f(-1,-1,0)); ugly_z.push_back(Point3f(1,-1,0)); DrawUglyLetter(tb,ugly_z); } /*! @brief ScaleMode drawing function, member of the \e DrawUgly series. Draw a ScaleMode manipulator in an ugly way. \warning this method is part of the \e DrawUgly series of functions, which is a \b TEMPORARY solution, used while waiting for the \e DrawBeautiful series... @param tb the manipulator. */ void DrawUglyScaleMode(Trackball * tb) { std::vector ugly_s; ugly_s.push_back(Point3f(1,1,0)); ugly_s.push_back(Point3f(-1,1,0)); ugly_s.push_back(Point3f(-1,0,0)); ugly_s.push_back(Point3f(1,0,0)); ugly_s.push_back(Point3f(1,-1,0)); ugly_s.push_back(Point3f(-1,-1,0)); DrawUglyLetter(tb,ugly_s); } /*! @brief AxisMode drawing function, member of the \e DrawUgly series. Draw an AxisMode manipulator in an ugly way. \warning this method is part of the \e DrawUgly series of functions, which is a \b TEMPORARY solution, used while waiting for the \e DrawBeautiful series... @param tb the manipulator. @param axis AxisMode's axis. */ void DrawUglyAxisMode(Trackball * tb,Line3f axis) { glPushMatrix(); glPushAttrib (GL_ALL_ATTRIB_BITS); // go to world coords glTranslate (tb->center); glMultMatrix (tb->track.InverseMatrix ()); glTranslate (-tb->center); prepare_attrib(); glColor3f(0.9f, 0.9f, 0.2f); glLineWidth(2.0); glBegin(GL_LINES); glVertex(axis.Origin()+(axis.Direction()*100)); glVertex(axis.Origin()-(axis.Direction()*100)); glEnd(); glPointSize(8.0); glColor3f(0.2f, 0.2f, 0.9f); glBegin(GL_POINTS); glVertex(axis.Origin()); glEnd(); glPopAttrib (); glPopMatrix(); } /*! @brief PlaneMode drawing function, member of the \e DrawUgly series. Draw a PlaneMode manipulator in an ugly way. \warning this method is part of the \e DrawUgly series of functions, which is a \b TEMPORARY solution, used while waiting for the \e DrawBeautiful series... @param tb the manipulator. @param plane PlaneMode's plane. */ void DrawUglyPlaneMode(Trackball * tb,Plane3f plane) { glPushMatrix(); glPushAttrib (GL_ALL_ATTRIB_BITS); // go to world coords glTranslate (tb->center); glMultMatrix (tb->track.InverseMatrix ()); glTranslate (-tb->center); prepare_attrib(); Point3f p0,d1,d2,norm; norm=plane.Direction(); p0=plane.Projection(Point3f(0,0,0)); d1=Point3f(0,1,0); if(norm == d1 || norm == -d1) d1 = Point3f(1,0,0); d2=plane.Projection(d1); d1=(d2 - p0).Normalize(); d2=(d1 ^ norm).Normalize(); glLineWidth(3.0); glColor3f(0.2f, 0.2f, 0.9f); glBegin(GL_LINES); glVertex(p0); glVertex(p0+norm); glEnd(); glLineWidth(1.0); for(float i=0.5f; i<100.0f; i+=0.7f){ glBegin(GL_LINE_LOOP); for(int a=0;a<360;a+=10){ float f0=i*cosf((float(M_PI)*float(a))/180.0f); float f1=i*sinf((float(M_PI)*float(a))/180.0f); glVertex(p0+(d1*f0)+(d2*f1)); } glEnd(); } glColor3f(0.9f, 0.9f, 0.2f); glPointSize(8.0f); glBegin(GL_POINTS); glVertex(p0); glEnd(); glColor3f(0.7f, 0.7f, 0.0f); glPointSize(6.0); glBegin(GL_POINTS); glVertex(p0+norm); glEnd(); glPopAttrib (); glPopMatrix(); } /*! @brief CylinderMode drawing function, member of the \e DrawUgly series. Draw a CylinderMode manipulator in an ugly way. \warning this method is part of the \e DrawUgly series of functions, which is a \b TEMPORARY solution, used while waiting for the \e DrawBeautiful series... @param tb the manipulator. @param axis CylinderMode's axis. */ void DrawUglyCylinderMode(Trackball * tb,Line3f axis) { glPushMatrix(); glPushAttrib (GL_ALL_ATTRIB_BITS); // go to world coords glTranslate (tb->center); glMultMatrix (tb->track.InverseMatrix ()); glTranslate (-tb->center); prepare_attrib(); Plane3f plane; plane.Init(axis.Origin(),axis.Direction()); Point3f p0,d1,d2,norm; norm=plane.Direction(); p0=plane.Projection(Point3f(0,0,0)); d1=Point3f(0,1,0); if(norm == d1 || norm == -d1) d1 = Point3f(1,0,0); d2=plane.Projection(d1); d1=(d2 - p0).Normalize(); d2=(d1 ^ norm).Normalize(); glLineWidth(1.0); glColor3f(0.2f, 0.2f, 0.9f); for(int i=-100;i<100;i++){ glBegin(GL_LINE_LOOP); for(int a=0;a<360;a+=10){ float f0=(tb->radius)*cosf((float(M_PI)*float(a))/180.0f); float f1=(tb->radius)*sinf((float(M_PI)*float(a))/180.0f); glVertex(axis.Origin()+p0+(norm*float(i))+(d1*f0)+(d2*f1)); } glEnd(); } glLineWidth(3.0); glColor3f(0.2f, 0.2f, 0.9f); glBegin(GL_LINES); glVertex(axis.Origin()); glVertex(axis.Origin()+(axis.Direction()*100)); glEnd(); glLineWidth(1.5); glColor3f(0.9f, 0.2f, 0.9f); glBegin(GL_LINES); glVertex(axis.Origin()); glVertex(axis.Origin()-(axis.Direction()*100)); glEnd(); glColor3f(0.9f, 0.9f, 0.2f); glPointSize(8.0); glBegin(GL_POINTS); glVertex(axis.Origin()); glEnd(); glPopAttrib (); glPopMatrix(); } /*! @brief PathMode drawing function, member of the \e DrawUgly series. Draw a PathMode manipulator in an ugly way. \warning this method is part of the \e DrawUgly series of functions, which is a \b TEMPORARY solution, used while waiting for the \e DrawBeautiful series... @param tb the manipulator. @param points PathMode's points. @param current_point PathMode's current point. @param prev_point PathMode's prev point. @param next_point PathMode's next point. @param old_hitpoint PathMode's old hitpoint. @param wrap PathMode's wrap. */ void DrawUglyPathMode(Trackball * tb,const std::vector < Point3f > &points, Point3f current_point,Point3f prev_point, Point3f next_point,Point3f old_hitpoint,bool wrap) { glPushMatrix(); glPushAttrib (GL_ALL_ATTRIB_BITS); // go to world coords glTranslate (tb->center); glMultMatrix (tb->track.InverseMatrix ()); glTranslate (-tb->center); prepare_attrib(); glColor3f(0.9f, 0.9f, 0.2f); glLineWidth(2.0); if(wrap) glBegin(GL_LINE_LOOP); else glBegin(GL_LINE_STRIP); for (std::vector < Point3f >::const_iterator i = points.begin (); i != points.end (); ++i){ glVertex(*i); } glEnd(); glColor3f(1,0,1); glPointSize(8.0); glBegin(GL_POINTS); glVertex(current_point); glEnd(); glColor3f(0.6f, 0.0f, 0.6f); glPointSize(7.0); glBegin(GL_POINTS); glVertex(old_hitpoint); glEnd(); glColor3f(0.7f, 0.7f, 0.7f); glPointSize(6.5); glBegin(GL_POINTS); glVertex(prev_point); glVertex(next_point); glEnd(); glPopAttrib (); glPopMatrix(); } /*! @brief AreaMode drawing function, member of the \e DrawUgly series. Draw an AreaMode manipulator in an ugly way. \warning this method is part of the \e DrawUgly series of functions, which is a \b TEMPORARY solution, used while waiting for the \e DrawBeautiful series... @param tb the manipulator. @param points AreaMode's points. @param status AreaMode's status. @param old_status AreaMode's old status. @param plane AreaMode's plane. @param path AreaMode's path. @param rubberband_handle AreaMode's rubberband handle. */ void DrawUglyAreaMode(Trackball * tb,const std::vector < Point3f > &points, Point3f status,Point3f old_status,Plane3f plane, const std::vector < Point3f > &path,Point3f rubberband_handle) { glPushMatrix(); glPushAttrib (GL_ALL_ATTRIB_BITS); // go to world coords glTranslate (tb->center); glMultMatrix (tb->track.InverseMatrix ()); glTranslate (-tb->center); prepare_attrib(); glColor3f(0.9f, 0.9f, 0.2f); glLineWidth(2.0); glBegin(GL_LINE_LOOP); for (std::vector < Point3f >::const_iterator i = points.begin (); i != points.end (); ++i){ glVertex(*i); } glEnd(); glColor3f(0.0f, 0.9f, 0.2f); glLineWidth(1.2f); glBegin(GL_LINE_STRIP); for (std::vector < Point3f >::const_iterator i = path.begin (); i != path.end (); ++i){ glVertex(*i); } glEnd(); glColor3f(1,0,1); glPointSize(8.0); glBegin(GL_POINTS); glVertex(status); glEnd(); glColor3f(0.6f, 0.0f, 0.6f); glPointSize(7.0); glBegin(GL_POINTS); glVertex(old_status); glEnd(); glColor3f(0.6f, 0.0f, 0.0f); glPointSize(6.0); glBegin(GL_POINTS); glVertex(rubberband_handle); glEnd(); glLineWidth(1.0); glBegin(GL_LINES); glVertex(rubberband_handle); glVertex(status); glEnd(); Point3f p0,d1,d2,norm; norm=plane.Direction(); p0=plane.Projection(Point3f(0,0,0)); d1=Point3f(0,1,0); if(norm == d1 || norm == -d1) d1 = Point3f(1,0,0); d2=plane.Projection(d1); d1=(d2 - p0).Normalize(); d2=(d1 ^ norm).Normalize(); glLineWidth(3.0); glColor3f(0.2f, 0.2f, 0.9f); glBegin(GL_LINES); glVertex(p0); glVertex(p0+norm); glEnd(); glLineWidth(0.1f); for(float i=0.5f;i<100.0f; i+=0.7f){ glBegin(GL_LINE_LOOP); for(int a=0;a<360;a+=10){ float f0=i*cosf((float(M_PI)*float(a))/180.0f); float f1=i*sinf((float(M_PI)*float(a))/180.0f); glVertex(p0+(d1*f0)+(d2*f1)); } glEnd(); } glPopAttrib (); glPopMatrix(); } } //end namespace trackutils } //end namespace vcg #endif //TRACKUTILS_H qutemol/vcg/wrap/gui/trackball.cpp0000444000175000017500000003250310760330724015606 0ustar mbamba/**************************************************************************** * VCGLib o o * * Visual and Computer Graphics Library o o * * _ O _ * * Copyright(C) 2004 \/)\/ * * Visual Computing Lab /\/| * * ISTI - Italian National Research Council | * * \ * * All rights reserved. * * * * 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. * * * * 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 (http://www.gnu.org/licenses/gpl.txt) * * for more details. * * * ****************************************************************************/ /**************************************************************************** History $Log: trackball.cpp,v $ Revision 1.27 2008/02/24 18:05:08 ponchio Should work as before. I didn't test cylinder and other exotic modes. Revision 1.26 2008/02/24 14:37:00 ponchio Restored trackball functionality. Not very much tested, and code will need some cleanup. Revision 1.25 2008/02/22 18:57:46 benedetti first attempt to correct after quaternion ToMatrix() inversion (does not work yet) Revision 1.24 2007/12/21 12:29:34 tarini *** empty log message *** Revision 1.23 2007/10/12 14:02:39 corsini solve memory leak in dtor Revision 1.22 2007/07/09 22:47:18 benedetti Removed using namespace std and modified accordingly. Revision 1.21 2007/06/20 12:59:43 corsini adjust wheel back-compatibility Revision 1.20 2007/06/13 17:15:08 benedetti Added one-level undo system and sticky trackmodes. Revision 1.19 2007/05/15 15:00:27 benedetti Moved the drawing code to trackmodes, some other minor changes Revision 1.18 2007/02/26 01:30:02 cignoni Added reflection Name Revision 1.17 2007/01/15 15:04:15 tarini added "ToAscii" and "SetFromAscii" methods to load/store current trackball status from/to ascii strings (intended uses: clipboard operations and comments inside png snapshots!) Revision 1.16 2006/07/26 13:54:45 cignoni Reversed the direction of wheel scaling and added middle mouse panning Revision 1.15 2006/02/13 13:15:52 cignoni Added Scale and Translate methods. Added many drawing hints and raised the default num. of steps when drawing circles. Added MouseDown without coords (for remembering changes of keys modifiers) Added ZMode to the default modes under Alt+left Added DrawPostApply (to be completed) Revision 1.14 2005/10/17 01:29:46 cignoni Main restructuring. Removed the Draw function and slightly changed the meaning of the trackball itself. See the notes at the beginning of trackball.h Revision 1.13 2005/04/17 17:48:24 ganovelli modes deallocation commented (quick and dirty solution..to debug) Revision 1.12 2004/12/17 10:28:10 ricciodimare *** empty log message *** Revision 1.11 2004/09/28 15:30:12 ponchio Added a 'else'. Revision 1.10 2004/09/09 14:38:52 ponchio #include #include #include "trackball.h" #include #include using namespace vcg; Transform::Transform() { track.SetIdentity(); radius=1.0f; center=Point3f(0,0,0); } Trackball::Trackball(): current_button(0), current_mode(NULL), inactive_mode(NULL), dragging(false), spinnable(true), spinning(false), history_size(10){ setDefaultMapping (); } Trackball::~Trackball() { std::map::iterator it; for(it = modes.begin(); it != modes.end(); it++) { if ((*it).second) delete (*it).second; } } void Trackball::setDefaultMapping () { inactive_mode = new InactiveMode (); modes.clear (); modes[0] = NULL; modes[BUTTON_LEFT] = new SphereMode (); modes[BUTTON_LEFT | KEY_CTRL] = new PanMode (); modes[BUTTON_MIDDLE] = new PanMode (); modes[BUTTON_LEFT | KEY_SHIFT] = new ScaleMode (); modes[BUTTON_LEFT | KEY_ALT] = new ZMode (); modes[WHEEL] = new ScaleMode (); SetCurrentAction (); } void Trackball::SetIdentity() { track.SetIdentity(); Reset(); } void Trackball::SetPosition(const Point3f &c, int /* millisec */) { center = c; } void Trackball::GetView() { camera.GetView(); } // the drawing code has been moved to the trackmodes void Trackball::DrawPostApply() { if(current_mode !=NULL){ current_mode->Draw(this); }else{ assert(inactive_mode != NULL); inactive_mode->Draw(this); } } void Trackball::Apply () { glTranslate (center); glMultMatrix (track.Matrix()); glTranslate (-center); } void Trackball::Apply(bool ToDraw) { Apply(); if(ToDraw){ DrawPostApply(); } } void Trackball::ApplyInverse() { glTranslate(center); glMultMatrix(track.InverseMatrix()); glTranslate(-center); } void Trackball::Scale(const float s) { track.sca*=s; } void Trackball::Translate(Point3f tr) { Quaternionf irot = track.rot; irot.Invert(); track.tra = last_track.tra + irot.Rotate(tr)/track.sca; } /***************************************************************/ // DrawCircle () e DrawPlane() have been moved to trackutils.h // the drawing code has been moved to the trackmodes /* void Trackball::DrawCircle() { int nside=DH.CircleStep; const double pi2=3.14159265*2.0; glBegin(GL_LINE_LOOP); for(double i=0;i::iterator i; for(i = modes.begin(); i != modes.end(); i++){ TrackMode * mode=(*i).second; if(mode!=NULL) mode->Reset(); } assert(inactive_mode != NULL); inactive_mode->Reset(); } //interface void Trackball::MouseDown(int button) { undo_track = track; current_button |= button; SetCurrentAction(); Hits.clear(); } void Trackball::MouseDown(int x, int y, int button) { undo_track = track; current_button |= button; SetCurrentAction(); last_point = Point3f((float)x, (float)y, 0); Hits.clear(); } void Trackball::MouseMove(int x, int y) { if(current_mode == NULL) return; if(last_point[2] == -1) { //changed mode in the middle of moving last_point = Point3f((float)x, (float)y, 0); return; } undo_track = track; current_mode->Apply(this, Point3f(float(x), float(y), 0)); } void Trackball::MouseUp(int /* x */, int /* y */, int button) { undo_track = track; current_button &= (~button); SetCurrentAction(); } // it assumes that a notch of 1.0 is a single step of the wheel void Trackball::MouseWheel(float notch) { undo_track = track; int buttons = current_button; current_button = WHEEL | (buttons&(KEY_SHIFT|KEY_CTRL|KEY_ALT)); SetCurrentAction(); if (current_mode == NULL) { ScaleMode scalemode; scalemode.Apply (this, notch); } else { current_mode->Apply(this, notch); } current_button = buttons; SetCurrentAction(); } void Trackball::MouseWheel(float notch, int button) { undo_track = track; current_button |= button; SetCurrentAction(); if (current_mode == NULL) { ScaleMode scalemode; scalemode.Apply (this, notch); } else { current_mode->Apply (this, notch); } current_button &= (~button); SetCurrentAction (); } void Trackball::ButtonDown(Trackball::Button button) { bool old_sticky=false, new_sticky=false; assert (modes.count (0)); if ( ( modes.count (current_button) ) && ( modes[current_button] != NULL ) ) { old_sticky = modes[current_button]->isSticky(); } current_button |= button; if ( ( modes.count (current_button) ) && ( modes[current_button] != NULL ) ) { new_sticky = modes[current_button]->isSticky(); } if ( old_sticky || new_sticky) return; SetCurrentAction(); } void Trackball::ButtonUp(Trackball::Button button) { bool old_sticky=false, new_sticky=false; assert ( modes.count (0) ); if ( ( modes.count (current_button) ) && ( modes[current_button] != NULL ) ) { old_sticky = modes[current_button]->isSticky(); } current_button &= (~button); if ( ( modes.count (current_button) ) && ( modes[current_button] != NULL ) ) { new_sticky = modes[current_button]->isSticky(); } if ( old_sticky || new_sticky) return; SetCurrentAction(); } void Trackball::Undo(){ track = undo_track; if(current_mode != NULL) current_mode->Undo(); } //spinning interface void Trackball::SetSpinnable(bool /* on*/ ){} bool Trackball::IsSpinnable() { return spinnable; } void Trackball::SetSpinning(Quaternionf &/* spin*/){} void Trackball::StopSpinning(){} bool Trackball::IsSpinning() { return spinning; } //navigation interface: void Trackball::Back(){} void Trackball::Forward(){} void Trackball::Home(){} void Trackball::HistorySize(int /* length */){} void Trackball::SetCurrentAction () { //I use strict matching. assert (modes.count (0)); if (!modes.count (current_button)) { current_mode = NULL; } else { current_mode = modes[current_button]; if(current_mode != NULL) current_mode->SetAction(); } last_point = Point3f (0, 0, -1); last_track = track; } ////return center of trackball in Window coordinates. //Point3f Trackball::ScreenOrigin() { // return camera.Project(ModelOrigin()); //} //return center of trackball in Model coordinates //Point3f Trackball::ModelOrigin() { // return center; //} //Matrix44f Trackball::ScreenToModel() { // return camera.inverse; //} // //Similarityf Trackball::ModelToLocal() { // Similarityf m = local * last_track; // return m; //} qutemol/vcg/wrap/gui/coordinateframe.cpp0000444000175000017500000002752210766531317017025 0ustar mbamba/**************************************************************************** * MeshLab o o * * A versatile mesh processing toolbox o o * * _ O _ * * Copyright(C) 2008 \/)\/ * * Visual Computing Lab /\/| * * ISTI - Italian National Research Council | * * \ * * All rights reserved. * * * * 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. * * * * 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 (http://www.gnu.org/licenses/gpl.txt) * * for more details. * * * ****************************************************************************/ /**************************************************************************** History $Log: coordinateframe.cpp,v $ Revision 1.9 2008/03/14 17:15:59 benedetti improved comments Revision 1.8 2008/03/02 16:44:18 benedetti moved ActiveCoordinateFrame to its own files Revision 1.7 2008/02/26 18:22:42 benedetti corrected after quaternion/similarity/trackball changes Revision 1.6 2008/02/22 20:34:35 benedetti corrected typo Revision 1.5 2008/02/22 20:04:02 benedetti many user interface improvements, cleaned up a little Revision 1.4 2008/02/17 20:52:53 benedetti some generalization made Revision 1.3 2008/02/16 14:12:30 benedetti first version ****************************************************************************/ #include #include #include #include #include "coordinateframe.h" using namespace vcg; CoordinateFrame::CoordinateFrame(float s) :basecolor(Color4b::White),xcolor(Color4b::Red) ,ycolor(Color4b::Green),zcolor(Color4b::Blue),size(s),linewidth(2.0) ,font(),drawaxis(true),drawlabels(true),drawvalues(false) { font.setFamily("Helvetica"); } void CoordinateFrame::Render(QGLWidget* glw) { assert( glw!= NULL); glPushAttrib(GL_ALL_ATTRIB_BITS); glDisable(GL_LIGHTING); glDisable(GL_TEXTURE_2D); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glEnable(GL_LINE_SMOOTH); glEnable(GL_POINT_SMOOTH); glLineWidth(linewidth); glPointSize(linewidth*1.5); Point3d o(0,0,0); Point3d a(size,0,0); Point3d b(0,size,0); Point3d c(0,0,size); // Get gl state values double mm[16],mp[16]; GLint vp[4]; glGetDoublev(GL_MODELVIEW_MATRIX,mm); glGetDoublev(GL_PROJECTION_MATRIX,mp); glGetIntegerv(GL_VIEWPORT,vp); float slope_a=calcSlope(-a,a,2*size,10,mm,mp,vp); float slope_b=calcSlope(-b,b,2*size,10,mm,mp,vp); float slope_c=calcSlope(-c,c,2*size,10,mm,mp,vp); float scalefactor = size*0.02f; if(drawaxis){ glBegin(GL_LINES); glColor(xcolor); glVertex(-a); glVertex(a); glColor(ycolor); glVertex(-b); glVertex(b); glColor(zcolor); glVertex(-c); glVertex(c); glEnd(); glColor(basecolor); // positive axes drawTickedLine(o,a,size,slope_a,linewidth); // Draws x axis drawTickedLine(o,b,size,slope_b,linewidth); // Draws y axis drawTickedLine(o,c,size,slope_c,linewidth); // Draws z axis // negative axes drawTickedLine(o,-a,size,slope_a,linewidth); // Draws x axis drawTickedLine(o,-b,size,slope_b,linewidth); // Draws y axis drawTickedLine(o,-c,size,slope_c,linewidth); // Draws z axis glPushMatrix(); glTranslate(a); glScalef(scalefactor,scalefactor,scalefactor); Add_Ons::Cone(10,linewidth*1.5,linewidth*0.5,true); glPopMatrix(); glPushMatrix(); glTranslate(b); glRotatef(90,0,0,1); glScalef(scalefactor,scalefactor,scalefactor); Add_Ons::Cone(10,linewidth*1.5,linewidth*0.5,true); glPopMatrix(); glPushMatrix(); glTranslate(c); glRotatef(-90,0,1,0); glScalef(scalefactor,scalefactor,scalefactor); Add_Ons::Cone(10,linewidth*1.5,linewidth*0.5,true); glPopMatrix(); } if(drawlabels){ font.setBold(true); font.setPixelSize(12); float d=size+scalefactor*linewidth*1.5; glColor(xcolor); glw->renderText(d,0,0,QString("X"),font); glColor(ycolor); glw->renderText(0,d,0,QString("Y"),font); glColor(zcolor); glw->renderText(0,0,d,QString("Z"),font); } if(drawvalues){ font.setBold(false); font.setPixelSize(8); float i; glColor(Color4b::LightGray); for(i=slope_a;irenderText( i,0,0,QString(" %1").arg(i,3,'f',1),font); glw->renderText(-i,0,0,QString("-%1").arg(i,3,'f',1),font); } for(i=slope_b;irenderText(0, i,0,QString(" %1").arg(i,3,'f',1),font); glw->renderText(0,-i,0,QString("-%1").arg(i,3,'f',1),font); } for(i=slope_c;irenderText(0,0, i,QString(" %1").arg(i,3,'f',1),font); glw->renderText(0,0,-i,QString("-%1").arg(i,3,'f',1),font); } } glPopAttrib(); assert(!glGetError()); } void CoordinateFrame::drawTickedLine(const Point3d &a,const Point3d &b, float dim,float tickDist,float linewidth) { Point3d v(b-a); v = v /dim; // normalize without computing square roots and powers glBegin(GL_POINTS); float i; for(i=tickDist;i(niceRound(dim*.001f),nslope); // prevent too small slope return nslope; } float CoordinateFrame::niceRound(float val) { return powf(10.f,ceil(log10(val))); } MovableCoordinateFrame::MovableCoordinateFrame(float size) :CoordinateFrame(size),position(0,0,0),rotation(0,Point3f(1,0,0)) { // nothing here } void MovableCoordinateFrame::Render(QGLWidget* gla) { glPushMatrix(); glTranslate(position); Matrix44f mrot; rotation.ToMatrix(mrot); glMultMatrix(Inverse(mrot)); CoordinateFrame::Render(gla); glPopMatrix(); } void MovableCoordinateFrame::GetTransform(Matrix44f & transform) { // build the matrix that moves points in world coordinates // clean transform transform.SetIdentity(); // apply rotation Matrix44f rot; rotation.ToMatrix(rot); transform = Inverse(rot) * transform ; // apply translation Matrix44f pos; pos.SetTranslate(position); transform = pos * transform; } void MovableCoordinateFrame::Reset(bool reset_position,bool reset_alignment) { if(reset_position) position = Point3f(0,0,0); if(reset_alignment) rotation = Quaternionf(0,Point3f(1,0,0)); } void MovableCoordinateFrame::SetPosition(const Point3f newpos) { position = newpos; } void MovableCoordinateFrame::SetRotation(const Quaternionf newrot) { rotation = newrot; } Point3f MovableCoordinateFrame::GetPosition() { return position; } Quaternionf MovableCoordinateFrame::GetRotation() { return rotation; } void MovableCoordinateFrame::Rot(float angle_deg,const Point3f axis) { Similarityf s; s.SetRotate(angle_deg*M_PI/180.0f,(rotation).Rotate(axis)); Move(s); } void MovableCoordinateFrame::AlignWith(const Point3f pri,const Point3f secondary,const char c1, const char c2) { const float EPSILON=1e-6; Point3f primary=pri; if( primary.Norm() < EPSILON*size ) return; primary.Normalize(); Plane3f plane(0,primary); // projection plane for the second rotation Point3f x(1,0,0),y(0,1,0),z(0,0,1); Point3f first(0,0,0),second(0,0,0),third(0,0,0); if(c1=='X'){ first = x; if((c2=='Y')||(c2==' ')){ second = y; third = z; } else if(c2=='Z'){ second = z; third = y; } else assert (0); } else if(c1=='Y'){ first = y; if((c2=='Z')||(c2==' ')){ second = z; third = x; } else if(c2=='X'){ second = x; third = z; } else assert (0); } else if(c1=='Z'){ first = z; if((c2=='X')||(c2==' ')){ second = x; third = y; } else if(c2=='Y'){ second = y; third = x; } else assert (0); } else assert (0); Point3f old_first = Inverse(rotation).Rotate(first); // axis 1 Point3f old_second_pro = plane.Projection(Inverse(rotation).Rotate(second)); // axis 2 projection Point3f old_third_pro = plane.Projection(Inverse(rotation).Rotate(third)); // axis 3 projection // align axis 1 to primary RotateToAlign(old_first,primary); Point3f secondary_pro = plane.Projection(secondary); // secondary's projection Point3f new_second_pro = plane.Projection(Inverse(rotation).Rotate(second)); // axis 2 projection after the first rotation if( secondary.Norm() > EPSILON*size && secondary_pro.Norm() > EPSILON ){ // secondary is not null nor parallel to primary // align axis 2 projection after the first rotation to secondary's projection secondary_pro.Normalize(); RotateToAlign(new_second_pro,secondary_pro); return; } if ( old_second_pro.Norm() > EPSILON ) { // can realign axis 2 // align axis 2 projection after the first rotation to old axis 2 projection old_second_pro.Normalize(); RotateToAlign(new_second_pro,old_second_pro); return; } // realign axis 3 Point3f new_third_pro = plane.Projection(Inverse(rotation).Rotate(third));// axis 3 projection after the first rotation assert(old_third_pro.Norm() > EPSILON ); // old axis 3 projection should not be null // align axis 3 projection after the first rotation to old axis 3 projection old_third_pro.Normalize(); RotateToAlign(new_third_pro,old_third_pro); } void MovableCoordinateFrame::Move(const Similarityf track) { position = position + track.tra; rotation = rotation * Inverse(track.rot); } void MovableCoordinateFrame::RotateToAlign(const Point3f source, const Point3f dest) { const float EPSILON=1e-6; // source and dest must be versors assert( math::Abs(source.Norm() - 1) < EPSILON); assert( math::Abs(dest.Norm() - 1) < EPSILON); Point3f axis = dest ^ source; float sinangle = axis.Norm(); float cosangle = dest * source; float angle = math::Atan2(sinangle,cosangle); if( math::Abs(angle) < EPSILON ) return; // angle ~ 0, aborting if( math::Abs(math::Abs(angle)-M_PI) < EPSILON){ // must find a axis to flip on Plane3f plane(0,source); axis=plane.Projection(Point3f(1,0,0)); // project a "random" point on source's normal plane if(axis.Norm() < EPSILON){ // source was ~ [1,0,0]... axis=plane.Projection(Point3f(0,1,0)); assert(axis.Norm() > EPSILON); // this point must be good } } rotation = rotation * Quaternionf(angle,axis); } qutemol/vcg/wrap/gui/view.h0000444000175000017500000001740710567257651014310 0ustar mbamba/**************************************************************************** * VCGLib o o * * Visual and Computer Graphics Library o o * * _ O _ * * Copyright(C) 2004 \/)\/ * * Visual Computing Lab /\/| * * ISTI - Italian National Research Council | * * \ * * All rights reserved. * * * * 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. * * * * 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 (http://www.gnu.org/licenses/gpl.txt) * * for more details. * * * ****************************************************************************/ /**************************************************************************** History $Log: view.h,v $ Revision 1.16 2007/02/22 09:17:29 cignoni Added guards for opengl including in mac compiling Revision 1.15 2007/01/18 01:24:32 cignoni Added cast for mac compiling Revision 1.14 2005/10/15 15:23:32 ponchio Fixed viewport<->window coordinate change for the z. (z = 2*z -1 now) Accordingly to gluUnproject documentation. Revision 1.13 2005/02/11 11:53:18 tommyfranken changed pointf to point in ViewLineFromWindow Revision 1.12 2005/02/10 20:09:11 tarini dispelled the mega-evil of GL_TRANSPOSE_*_MATRIX_ARB Revision 1.11 2005/01/19 10:29:45 cignoni Removed the inclusion of a glext.h Revision 1.10 2005/01/18 16:47:42 ricciodimare *** empty log message *** Revision 1.9 2004/09/28 10:22:00 ponchio Added #include Revision 1.8 2004/05/26 15:15:46 cignoni Removed inclusion of gl extension stuff Revision 1.7 2004/05/14 03:15:40 ponchio Added ViewLineFromModel Revision 1.6 2004/05/12 20:55:18 ponchio *** empty log message *** Revision 1.5 2004/05/07 12:46:08 cignoni Restructured and adapted in a better way to opengl Revision 1.4 2004/04/07 10:54:11 cignoni Commented out unused parameter names and other minor warning related issues Revision 1.3 2004/03/31 15:07:37 ponchio CAMERA_H -> VCG_CAMERA_H Revision 1.2 2004/03/25 14:55:25 ponchio Adding copyright. ****************************************************************************/ #ifndef VCG_CAMERA_H #define VCG_CAMERA_H /********************** WARNING Everything here assumes the opengl window coord system. the 0,0 is bottom left y is upward! **********************/ #include #include #include #include #ifdef WIN32 #include #endif #if defined(__APPLE__) #include #else #include #endif namespace vcg { /** This class represent the viewing parameters under opengl. Mainly it stores the projection and modelview matrix and the viewport and it is used to simply project back and forth points, computing line of sight, planes etc. */ template class View { public: void GetView(); void SetView(); Point3 Project(const Point3 &p) const; Point3 UnProject(const Point3 &p) const; Point3 ViewPoint() const; /// Return the plane perpendicular to the view axis and passing through point P. Plane3 ViewPlaneFromModel(const Point3 &p); /// Return the line of view passing through point P. Line3 ViewLineFromModel(const Point3 &p); /// Return the line passing through the point p and the observer. Line3 ViewLineFromWindow(const Point3 &p); /// Convert coordinates from the range -1..1 of Normalized Device Coords to range 0 viewport[2] Point3 NormDevCoordToWindowCoord(const Point3 &p) const; /// Convert coordinates from 0--viewport[2] to the range -1..1 of Normalized Device Coords to Point3 WindowCoordToNormDevCoord(const Point3 &p) const; Matrix44 proj; Matrix44 model; Matrix44 matrix; Matrix44 inverse; int viewport[4]; }; template void View::GetView() { double m[16]; // Don't use GL_TRANSPOSE_*_MATRIX_ARB // they are veeeery evil! // On many OpenGL implementation they just don't work, causing endless hours of debugging! /* glGetDoublev(GL_TRANSPOSE_PROJECTION_MATRIX_ARB, m); proj.Import(Matrix44d(m)); glGetDoublev(GL_TRANSPOSE_MODELVIEW_MATRIX_ARB, m); model.Import(Matrix44d(m)); */ // Use standard routines, and transpose manually. // some 10^-20 seconds slower, but a lot safer glGetDoublev(GL_PROJECTION_MATRIX, m); proj.Import(Matrix44d(m)); Transpose(proj); glGetDoublev(GL_MODELVIEW_MATRIX, m); model.Import(Matrix44d(m)); Transpose(model); glGetIntegerv(GL_VIEWPORT, (GLint*)viewport); matrix = proj*model; inverse = matrix; Invert(inverse); } template void View::SetView() { } template Point3 View::ViewPoint() const { Matrix44 mi=model; Invert(mi); return mi* Point3(0, 0, 0); } // Note that p it is assumed to be in model coordinate. template Plane3 View::ViewPlaneFromModel(const Point3 &p) { Point3 vp=ViewPoint(); Plane3 pl; // plane perpedicular to view direction and passing through manip center pl.n=(vp-p); pl.d=pl.n*p; return pl; } // Note that p it is assumed to be in model coordinate. template Line3 View::ViewLineFromModel(const Point3 &p) { Point3 vp=ViewPoint(); Line3 line; line.SetOrigin(vp); line.SetDirection(p - vp); return line; } // Note that p it is assumed to be in window coordinate. template Line3 View::ViewLineFromWindow(const Point3 &p) { Line3 ln; // plane perpedicular to view direction and passing through manip center Point3 vp=ViewPoint(); Point3 pp=UnProject(p); ln.SetOrigin(vp); ln.SetDirection(pp-vp); return ln; } template Point3 View::Project(const Point3 &p) const { Point3 r; r = matrix * p; return NormDevCoordToWindowCoord(r); } template Point3 View::UnProject(const Point3 &p) const { Point3 s = WindowCoordToNormDevCoord(p); s = inverse * s ; return s; } // Come spiegato nelle glspec // dopo la perspective division le coordinate sono dette normalized device coords ( NDC ). // Per passare alle window coords si deve fare la viewport transformation. // Le coordinate di viewport stanno tra -1 e 1 template Point3 View::NormDevCoordToWindowCoord(const Point3 &p) const { Point3 a; a[0] = (p[0]+1)*(viewport[2]/(T)2.0)+viewport[0]; a[1] = (p[1]+1)*(viewport[3]/(T)2.0)+viewport[1]; //a[1] = viewport[3] - a[1]; a[2] = (p[2]+1)/2; return a; } template Point3 View::WindowCoordToNormDevCoord(const Point3 &p) const { Point3 a; a[0] = (p[0]- viewport[0])/ (viewport[2]/(T)2.0) - 1; a[1] = (p[1]- viewport[1])/ (viewport[3]/(T)2.0) - 1; //a[1] = -a[1]; a[2] = 2*p[2] - 1; return a; } }//namespace #endif qutemol/vcg/wrap/gui/trackrecorder.h0000444000175000017500000000610410227560237016146 0ustar mbamba/**************************************************************************** * VCGLib o o * * Visual and Computer Graphics Library o o * * _ O _ * * Copyright(C) 2004 \/)\/ * * Visual Computing Lab /\/| * * ISTI - Italian National Research Council | * * \ * * All rights reserved. * * * * 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. * * * * 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 (http://www.gnu.org/licenses/gpl.txt) * * for more details. * * * ****************************************************************************/ /**************************************************************************** History $Log: trackrecorder.h,v $ Revision 1.2 2005/04/14 21:29:03 ganovelli "void" added Revision 1.1 2005/04/14 21:23:39 ganovelli *** empty log message *** ****************************************************************************/ #ifndef VCGLIB_TRACKRECORDER #define VCGLIB_TRACKRECORDER #include #include #include namespace vcg{ struct TrackRecorder{ TrackRecorder(){Stop();} FILE * trackfile; enum { PLAY,REC,OFF } mode; int nextTime, startTime; void StartPlaying(char * namefile){ if(trackfile != NULL) return; trackfile = fopen(namefile,"rb"); startTime = clock(); mode = PLAY; fread(&nextTime,4,1,trackfile); } void UpdateTrackball(Trackball & t){ while( ( clock()-startTime > nextTime)&& !feof(trackfile)){ fread(&t.track,sizeof(float)*4 + sizeof(float)*5,1,trackfile); fread(&nextTime,4,1,trackfile); } if(feof(trackfile)) Stop(); } void StartRecording(char * namefile){ if(trackfile != NULL) return; trackfile = fopen(namefile,"wb"); startTime = clock(); mode = REC; } void RecordTrackball(Trackball & t){ nextTime = clock()-startTime; fwrite(&nextTime,4,1,trackfile); fwrite(&t.track,sizeof(float)*4 + sizeof(float)*5,1,trackfile); } void Stop(){mode = OFF; trackfile = NULL;}; }; } #endifqutemol/vcg/wrap/gui/frustum.h0000444000175000017500000001354010227452555015026 0ustar mbamba/**************************************************************************** * VCGLib o o * * Visual and Computer Graphics Library o o * * _ O _ * * Copyright(C) 2004 \/)\/ * * Visual Computing Lab /\/| * * ISTI - Italian National Research Council | * * \ * * All rights reserved. * * * * 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. * * * * 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 (http://www.gnu.org/licenses/gpl.txt) * * for more details. * * * ****************************************************************************/ /**************************************************************************** History $Log: frustum.h,v $ Revision 1.10 2005/04/14 11:35:09 ponchio *** empty log message *** Revision 1.9 2005/03/02 15:13:45 ponchio Minimal fix in remoteness (Bugged anyway) Revision 1.8 2005/02/22 14:33:04 ponchio small bugs Revision 1.7 2005/01/21 18:06:05 ponchio Added remoteness ("distance" from frustum) Revision 1.6 2004/10/04 12:33:02 ponchio Cleaning up and planes init more stable. Revision 1.5 2004/09/28 10:23:28 ponchio Various generic changes. Revision 1.4 2004/05/12 20:55:18 ponchio *** empty log message *** Revision 1.3 2004/03/31 15:06:41 ponchio #include -> #include Revision 1.2 2004/03/25 14:55:25 ponchio Adding copyright. ****************************************************************************/ #ifndef FRUSTUM_H #define FRUSTUM_H #include #include #include #include using namespace std; namespace vcg { template class Frustum: public View { public: void GetView(); Point3 ViewPoint(); T Resolution(float dist = 1); bool IsOutside(Point3 &point); float Remoteness(Point3 &point, T radius); bool IsOutside(Point3 &point, T radius); T Distance(Point3 &point, int plane); protected: T resolution; Plane3 planes[6]; Point3 view_point; }; typedef Frustum Frustumf; typedef Frustum Frustumd; //Implementation template Point3 Frustum::ViewPoint() { return view_point; } template T Frustum::Resolution(float dist) { return resolution * dist; } template bool Frustum::IsOutside(Point3 &point) { Point3 r = Project(point); if(r[0] < View::viewport[0] || r[0] > View::viewport[0]+View::viewport[2] || r[1] < View::viewport[1] || r[1] > View::viewport[1]+View::viewport[3]) return true; return false; } template float Frustum::Remoteness(Point3 &point, T radius) { Point3 r = Project(point); T dist = (point - view_point).Norm(); if(dist < radius) return 0; T rad = 1 + radius / (resolution * dist); T mindist = 0; T tmp; tmp = View::viewport[0] - r[0] - rad; if(tmp > mindist) mindist = tmp; tmp = r[0] - rad - (View::viewport[0] + View::viewport[2]); if(tmp > mindist) mindist = tmp; tmp = View::viewport[1] - r[1] - rad; if(tmp > mindist) mindist = tmp; tmp = r[1] - rad - (View::viewport[1] + View::viewport[3]); if(tmp > mindist) mindist = tmp; if(mindist == 0) return 0; return 1 + (mindist / (View::viewport[0] + View::viewport[2])); } template bool Frustum::IsOutside(Point3 &point, T radius) { for(int i = 0; i < 4; i++) { T dist = Distance(point, i); if(dist < -radius) return true; } return false; } template T Frustum::Distance(Point3 &point, int plane) { return vcg::Distance(planes[plane], point); } template void Frustum::GetView() { View::GetView(); float t = (float)(View::viewport[1] +View:: viewport[3]); float b = (float)View::viewport[1]; float r = (float)(View::viewport[0] + View::viewport[2]); float l = (float)View::viewport[0]; Point3 nw = UnProject(Point3(l, b, 0.0f)); Point3 sw = UnProject(Point3(l, t, 0.0f)); Point3 ne = UnProject(Point3(r, b, 0.0f)); Point3 se = UnProject(Point3(r, t, 0.0f)); Point3 NW = UnProject(Point3(l, b, 1.0f)); Point3 SW = UnProject(Point3(l, t, 1.0f)); Point3 NE = UnProject(Point3(r, b, 1.0f)); Point3 SE = UnProject(Point3(r, t, 1.0f)); view_point = View::ViewPoint(); planes[0].Init(nw, NW, NE); planes[1].Init(ne, NE, SE); planes[2].Init(se, SE, SW); planes[3].Init(sw, SW, NW); planes[4].Init(se, sw, nw); planes[5].Init(SW, SE, NE); //compute resolution: sizeo of a pixel unitary distance from view_point resolution = ((ne + NE) - (nw + NW)).Norm() / (View::viewport[2] * ((ne + NE) - view_point).Norm()); } }//namespace #endif qutemol/vcg/wrap/gui/trackmode.cpp0000444000175000017500000005461210761051711015622 0ustar mbamba/**************************************************************************** * VCGLib o o * * Visual and Computer Graphics Library o o * * _ O _ * * Copyright(C) 2004 \/)\/ * * Visual Computing Lab /\/| * * ISTI - Italian National Research Council | * * \ * * All rights reserved. * * * * 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. * * * * 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 (http://www.gnu.org/licenses/gpl.txt) * * for more details. * * * ****************************************************************************/ /**************************************************************************** History $Log: trackmode.cpp,v $ Revision 1.29 2008/02/26 18:00:41 benedetti corrected CylinderMode::Apply Revision 1.28 2008/02/24 18:05:08 ponchio Should work as before. I didn't test cylinder and other exotic modes. Revision 1.27 2008/02/24 14:37:00 ponchio Restored trackball functionality. Not very much tested, and code will need some cleanup. Revision 1.26 2008/02/15 20:56:41 benedetti removed some variable initialization related warning, added snap to CylinderMode Revision 1.25 2007/10/24 10:39:07 ponchio #include -> #include (it is case sensitive under linux...) Revision 1.24 2007/07/09 22:47:18 benedetti Removed using namespace std and modified accordingly. Revision 1.23 2007/06/13 17:15:09 benedetti Added one-level undo system and sticky trackmodes. Revision 1.22 2007/05/28 08:10:47 fiorin Removed type cast warnings Revision 1.21 2007/05/16 08:44:05 ganovelli added inclusion of glew.h Revision 1.20 2007/05/15 14:58:57 benedetti Main restructuring. added many new modes Revision 1.19 2006/08/30 07:01:54 cignoni Reverted to version 1.17. Version 1.18 was wrongly done starting from a outdated version. Revision 1.17 2006/07/26 13:54:45 cignoni Reversed the direction of wheel scaling and added middle mouse panning Revision 1.16 2006/02/13 13:10:27 cignoni Added Zmode for moving objects along the perpendicular to the viewplane Revision 1.15 2006/01/12 15:40:05 cignoni Corrected small bugs on rotating after scaling+translating changed void PlaneMode::Apply and void SphereMode::Apply Revision 1.14 2005/07/15 16:39:30 callieri in SphereMode::Hit added a check on the sphere intersection, if no intersection, calculating distance could generate a NAN exception Revision 1.13 2005/06/29 15:22:26 callieri changed the name of some intersection functions to avoid ambiguity Revision 1.12 2005/02/11 11:44:07 tommyfranken Trackball translation corrected Revision 1.11 2005/02/02 16:46:41 pietroni some warning corrected Revision 1.10 2005/01/14 15:44:03 ganovelli PlaneMode completed Revision 1.9 2004/09/09 22:59:21 cignoni Removed many small warnings Revision 1.8 2004/07/18 06:54:08 cignoni Added Scaling Revision 1.7 2004/07/11 22:06:56 cignoni Added scaling by wheel Revision 1.6 2004/06/09 14:01:13 cignoni Heavily restructured. To be completed only rotation works... Revision 1.5 2004/05/14 03:15:09 ponchio Redesigned partial version. Revision 1.4 2004/05/07 12:46:08 cignoni Restructured and adapted in a better way to opengl Revision 1.3 2004/04/07 10:54:11 cignoni Commented out unused parameter names and other minor warning related issues Revision 1.2 2004/03/25 14:55:25 ponchio Adding copyright. ****************************************************************************/ #include #include #include #include using namespace vcg; using namespace vcg::trackutils; // the old implementation is not used anymore, some of the old support functions, // like HitViewPlane, GetViewPlane, HitHyper and SphereMode::Hit were made // class-independent and moved to trackutils.h /* void TrackMode::Apply(Trackball *trackball, float WheelNotch) { } void ScaleMode::Apply(Trackball *tb, Point3f new_point) { } Plane3f TrackMode::GetViewPlane(const View &camera, const Point3f ¢er) { } Point3f TrackMode::HitViewPlane(Trackball *tb, const Point3f &p) { } void SphereMode::Apply(Trackball *tb, Point3f new_point) { } bool SphereMode::HitHyper(Point3f center, float radius, Point3f viewpoint, Plane3f vp, Point3f hitplane, Point3f &hit) { } Point3f SphereMode::Hit(Trackball *tb, const Point3f &p) { } void PlaneMode::Apply(Trackball *tb, Point3f new_point) { } void ZMode::Apply(Trackball *tb, Point3f new_point) { } */ // Track mode implementation, dummy. void TrackMode::Apply (Trackball * , float ){} void TrackMode::Apply (Trackball * , Point3f ){} void TrackMode::Draw(Trackball * ){} void TrackMode::SetAction (){} void TrackMode::Reset (){} bool TrackMode::isSticky() { return false; } void TrackMode::Undo(){} // draw an inactive trackball void InactiveMode::Draw(Trackball * tb){ DrawSphereIcon(tb,false); } // Sphere mode implementation. // the most important function; given a new point in window coord, // it update the transformation computed by the trackball. // General scheme : the transformation is a function of just // the begin and current mouse positions, with greater precision // is function of just two 3d points over the manipulator. void SphereMode::Apply (Trackball * tb, Point3f new_point) { Point3f hitOld = HitSphere (tb, tb->last_point); Point3f hitNew = HitSphere (tb, new_point); tb->Hits.push_back (hitNew); Point3f center = tb->center; Point3f axis = (hitNew - center) ^ (hitOld - center); // Figure out how much to rotate around that axis. float phi = Distance (hitNew, hitOld) / tb->radius; // tb->track.rot = tb->last_track.rot * Quaternionf (-phi, axis); tb->track.rot = Quaternionf (-phi, axis) * tb->last_track.rot; } void SphereMode::Draw(Trackball * tb){ DrawSphereIcon(tb,true ); } // Pan mode implementation. void PanMode::Apply (Trackball * tb, Point3f new_point) { Point3f hitOld = HitViewPlane (tb, tb->last_point); Point3f hitNew = HitViewPlane (tb, new_point); tb->Translate (hitNew - hitOld); } void PanMode::Draw(Trackball * tb){ DrawSphereIcon(tb,true ); DrawUglyPanMode(tb); } // Z mode implementation. void ZMode::Apply (Trackball * tb, float WheelNotch) { Point3f dir= (GetViewPlane (tb->camera, tb->center)).Direction(); dir.Normalize(); tb->Translate (dir * (-WheelNotch)); } void ZMode::Apply (Trackball * tb, Point3f new_point) { Point3f dir= (GetViewPlane (tb->camera, tb->center)).Direction(); dir.Normalize(); tb->Translate (dir * ( -2.0f * getDeltaY(tb,new_point))); } void ZMode::Draw(Trackball * tb){ DrawSphereIcon(tb,true ); DrawUglyZMode(tb); } // Scale mode implementation. void ScaleMode::Apply (Trackball * tb, float WheelNotch) { tb->track.sca *= pow (1.2f, -WheelNotch); } void ScaleMode::Apply (Trackball * tb, Point3f new_point) { tb->track.sca = tb->last_track.sca * pow (3.0f, -(getDeltaY(tb,new_point))); } void ScaleMode::Draw(Trackball * tb){ DrawSphereIcon(tb,true ); DrawUglyScaleMode(tb); } // Axis mode implementation. void AxisMode::Apply (Trackball * tb, float WheelNotch) { tb->Translate (axis.Direction () * (WheelNotch / 10.0f)); } void AxisMode::Apply (Trackball * tb, Point3f new_point) { std::pair< Point3f,bool > hitOld = HitNearestPointOnAxis (tb, axis, tb->last_point); std::pair< Point3f,bool > hitNew = HitNearestPointOnAxis (tb, axis, new_point); if (hitOld.second && hitNew.second){ tb->Translate (hitNew.first - hitOld.first); } } void AxisMode::Draw(Trackball * tb){ DrawSphereIcon(tb,true ); DrawUglyAxisMode(tb,axis); } // Plane mode implementation. void PlaneMode::Apply (Trackball * tb, Point3f new_point) { std::pair< Point3f, bool > hitOld = HitPlane(tb,tb->last_point,plane); std::pair< Point3f, bool > hitNew = HitPlane(tb,new_point,plane); if(hitOld.second && hitNew.second){ tb->Translate (hitNew.first - hitOld.first); } } void PlaneMode::Draw(Trackball * tb){ DrawSphereIcon(tb,true ); DrawUglyPlaneMode(tb, plane); } // Cylinder mode implementation. void CylinderMode::Apply (Trackball * tb, float WheelNotch) { const float PI2=6.283185307179586232f; float angle= (snap==0.0) ? WheelNotch/(tb->radius * PI2) : WheelNotch * snap; tb->track.rot = tb->last_track.rot * Quaternionf (angle,axis.Direction()); } void CylinderMode::Apply (Trackball * tb, Point3f new_point) { Plane3f viewplane=GetViewPlane (tb->camera, tb->center); Line3f axisproj; axisproj=ProjectLineOnPlane(axis,viewplane); float angle; const float EPSILON=0.005f; // this IS scale independent if(axisproj.Direction().Norm() < EPSILON){ angle=(10.0f * getDeltaY(tb,new_point)) / tb->radius; } else { Point3f hitOld = HitViewPlane (tb, tb->last_point); Point3f hitNew = HitViewPlane (tb, new_point); axisproj.Normalize(); Point3f plusdir= viewplane.Direction() ^ axisproj.Direction(); float distOld = signedDistance(axisproj,hitOld,plusdir); float distNew = signedDistance(axisproj,hitNew,plusdir); angle= (distNew-distOld) / tb->radius; } if(snap>0.0){ angle = ((angle<0)?-1:1)* floor((((angle<0)?-angle:angle)/snap)+0.5)*snap; } // tb->track.rot = tb->last_track.rot * Quaternionf (angle,axis.Direction()); tb->track.rot = Quaternionf (-angle,axis.Direction()) * tb->last_track.rot; } void CylinderMode::Draw(Trackball * tb){ DrawSphereIcon(tb,true ); DrawUglyCylinderMode(tb,axis); } // Path mode implementation. void PathMode::Init(const std::vector < Point3f > &pts) { unsigned int npts = int(pts.size()); assert(npts >= 2); points.reserve(npts); for(unsigned int i=0;i= 0.0 ); if(nearest_state > 1.0){ nearest_state=1.0; nearest_point=( wrap ? points[0] : points[npts-1] ); } initial_state=nearest_state; return nearest_point; } void PathMode::GetPoints(float state, Point3f & point, Point3f & prev_point, Point3f & next_point) { assert(state >= 0.0f); assert(state <= 1.0f); float remaining_norm=state; Point3f p0(0,0,0),p1(0,0,0); unsigned int npts = int(points.size()); for(unsigned int i = 1;i <= npts;i++){ if( i == npts){ if (wrap){ p0=points[npts-1]; p1=points[0]; } else { break; } } else { p0=points[i-1]; p1=points[i]; } float segment_norm= Distance(p0,p1) / path_length; if (segment_norm < remaining_norm){ remaining_norm -= segment_norm; continue; } prev_point = p0; next_point = p1; float ratio= remaining_norm / segment_norm; point = prev_point + (( next_point - prev_point ) * ratio); const float EPSILON=min_seg_length * 0.01f; if(Distance(point,prev_point) < EPSILON){ point=prev_point; if (i > 1){ prev_point=points[i-2]; } else if (wrap){ prev_point=points[npts-1]; } } else if (Distance(point,next_point) < EPSILON){ point=next_point; if( i < (npts-1)){ next_point=points[i+1]; } else { if (wrap){ next_point=points[1]; } else { next_point=points[npts-1]; } } } return; } // rounding errors can lead out of the for.. prev_point = p0; point = p1; if (wrap){ next_point=points[1]; }else{ next_point = points[npts-1]; } } void PathMode::Apply (Trackball * tb, float WheelNotch) { undo_current_state=current_state; undo_old_hitpoint=old_hitpoint; const float STEP_COEFF = min_seg_length * 0.5f; float delta=(WheelNotch*STEP_COEFF)/path_length; Point3f old_point,new_point,prev_point,next_point; GetPoints(current_state,old_point,prev_point,next_point); current_state=Normalize(current_state+delta); GetPoints(current_state,new_point,prev_point,next_point); tb->Translate (new_point - old_point); } float PathMode::Normalize(float state) { if ( wrap ) { double intpart; float fractpart; fractpart =(float) modf(state,&intpart); if( fractpart < 0.0f ) fractpart += 1.0f; return fractpart; } if ( state < 0.0f ) return 0.0f; if ( state > 1.0f ) return 1.0f; return state; } int PathMode::Verse(Point3f reference_point,Point3f current_point,Point3f prev_point,Point3f next_point) { Point3f reference_dir = reference_point - current_point ; Point3f prev_dir = prev_point - current_point ; Point3f next_dir = next_point - current_point ; const float EPSILON=min_seg_length * 0.005f; if (reference_dir.Norm() < EPSILON) reference_dir = Point3f(0,0,0); if (prev_dir.Norm() < EPSILON) prev_dir = Point3f(0,0,0); if (next_dir.Norm() < EPSILON) next_dir = Point3f(0,0,0); reference_dir.Normalize(); prev_dir.Normalize(); next_dir.Normalize(); float prev_coeff,next_coeff; prev_coeff = prev_dir * reference_dir; next_coeff = next_dir * reference_dir; if (prev_coeff < 0.0f) prev_coeff = 0.0f; if (next_coeff < 0.0f) next_coeff = 0.0f; if( (prev_coeff == 0.0f) && (next_coeff == 0.0f)){ return 0; } if ( prev_coeff <= next_coeff ){ return 1; } return -1; } float PathMode::HitPoint(float state, Ray3fN ray, Point3f &hit_point) { Point3f current_point, next_point, prev_point; GetPoints(state,current_point,prev_point,next_point); Point3f closest_point; closest_point=ray.ClosestPoint(current_point); int verse=Verse(closest_point,current_point,prev_point,next_point); if (verse == 0){ hit_point=current_point; return 0.0f; } Segment3f active_segment; if (verse > 0){ active_segment=Segment3f(current_point,next_point); } else { active_segment= Segment3f(current_point,prev_point); } hit_point=ClosestPoint(active_segment,closest_point); return verse * ((hit_point-current_point).Norm() / path_length); } void PathMode::SetAction (){ Point3f temp1,temp2; GetPoints(current_state,old_hitpoint,temp1,temp2); } void PathMode::Apply (Trackball * tb, Point3f new_point) { undo_current_state=current_state; undo_old_hitpoint=old_hitpoint; Ray3fN ray = line2ray(tb->camera.ViewLineFromWindow (new_point)); Point3f hit_point; float delta_state=HitPoint(current_state,ray,hit_point); current_state=Normalize(current_state+delta_state); tb->Translate (hit_point - old_hitpoint); } bool PathMode::isSticky() { return true; } void PathMode::Undo(){ current_state=undo_current_state; old_hitpoint=undo_old_hitpoint; } void PathMode::Draw(Trackball * tb){ DrawSphereIcon(tb,true ); Point3f current_point,prev_point,next_point; GetPoints(current_state,current_point,prev_point,next_point); DrawUglyPathMode(tb,points,current_point,prev_point, next_point,old_hitpoint,wrap); } // Area mode implementation. void AreaMode::Init(const std::vector < Point3f > &pts) { unsigned int npts = int(pts.size()); assert(npts >= 3); //get the plane Point3f p0=pts[0]; unsigned int onethird=(unsigned int)floor(npts/3.0); const float EPSILON = 0.005f; bool pts_not_in_line=false; Point3f a,b; for(unsigned int i=0;i EPSILON; if(pts_not_in_line){ plane.Init( pts[i%npts], pts[(i+(onethird))%npts], pts[(i+(2*onethird))%npts]); break; } } assert(pts_not_in_line); float ncx,ncy,ncz; ncx=fabs(plane.Direction()[0]); ncy=fabs(plane.Direction()[1]); ncz=fabs(plane.Direction()[2]); if(( ncx > ncy ) && ( ncx > ncz )){ first_coord_kept=1; second_coord_kept=2; } else if(( ncy > ncx ) && ( ncy > ncz)){ first_coord_kept=0; second_coord_kept=2; } else { first_coord_kept=0; second_coord_kept=1; } points.reserve(npts); for(unsigned int i=0;icamera.Project(status)-new_point; begin_action=false; } std::pair< Point3f, bool > hitNew = HitPlane(tb,new_point+delta_mouse,plane); if(! hitNew.second){ return; } Point3f hit_point=hitNew.first; Point3f delta_status=Move(status,hit_point); status += delta_status; tb->Translate (status - old_status); rubberband_handle=hit_point; } void AreaMode::SetAction () { begin_action=true; old_status=status; path.clear(); path.push_back(status); rubberband_handle=status; } Point3f AreaMode::Move(Point3f start,Point3f end) { const float EPSILON=min_side_length*0.001f; Point3f pt=start; bool done=false; bool end_inside=Inside(end); while(!done){ path.push_back(pt); Segment3f segment(pt,end); bool p_on_side = false; bool hit=false; Point3f pside(0,0,0),phit(0,0,0); bool slide=false,mid_inside; int np = int(points.size()), i, j; for (i = 0, j = np-1; i < np; j = i++) { Segment3f side(points[i],points[j]); Point3f pseg,psid; std::pair res=SegmentSegmentDistance(segment,side,pseg,psid); if(res.first < EPSILON && ! res.second){ float dist= Distance(pt,pseg); if(dist < EPSILON){ Point3f pn=ClosestPoint(side,end); if(!p_on_side || (Distance(pn,end) EPSILON; if (hit) mid_inside = Inside( pt + ( ( phit - pt ) / 2) ); if ( !hit && end_inside ){ pt = end; done = true; } else if ( hit && (!p_on_side || (p_on_side && mid_inside))) { pt = phit; } else if ( p_on_side && slide) { pt = pside; } else { done = true; } } path.push_back(pt); return pt - start; } // adapted from the original C code by W. Randolph Franklin // http://www.ecse.rpi.edu/Homepages/wrf/Research/Short_Notes/pnpoly.html bool AreaMode::Inside(Point3f point) { bool inside=false; float x=point[first_coord_kept]; float y=point[second_coord_kept]; float yi, yj, xi, xj; int i, j, np=int(points.size()); for (i = 0, j = np-1; i < np; j = i++) { xi=points[i][first_coord_kept]; yi=points[i][second_coord_kept]; xj=points[j][first_coord_kept]; yj=points[j][second_coord_kept]; if ( ( ( (yi<=y) && (y undo_path_index; --i) path.pop_back(); } void AreaMode::Draw(Trackball * tb) { DrawSphereIcon(tb,true ); DrawUglyAreaMode(tb,points,status,old_status,plane,path,rubberband_handle); } qutemol/vcg/wrap/gui/rubberband.h0000444000175000017500000001073510765446036015436 0ustar mbamba/**************************************************************************** * MeshLab o o * * A versatile mesh processing toolbox o o * * _ O _ * * Copyright(C) 2008 \/)\/ * * Visual Computing Lab /\/| * * ISTI - Italian National Research Council | * * \ * * All rights reserved. * * * * 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. * * * * 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 (http://www.gnu.org/licenses/gpl.txt) * * for more details. * * * ****************************************************************************/ /**************************************************************************** History $Log: rubberband.h,v $ Revision 1.2 2008/03/11 09:08:46 benedetti Added doxygen documentation Revision 1.1 2008/02/16 12:00:34 benedetti first version, adapted from meshlab's editmeasure plugin ****************************************************************************/ #ifndef RUBBERBAND_H #define RUBBERBAND_H #include #include namespace vcg { /*! @brief The Rubberband class. This class is useful for interactively draw a straight line between 2 pickable points in a GL widget. */ class Rubberband { public: //data: /// The color of the rubberband Color4b color; // functions: /*! @brief The constructor. Initialize the rubberband data. */ Rubberband(Color4b); /*! @brief The destructor. The destructor. */ virtual ~Rubberband() {} /*! @brief Render the rubberband and do the picking. Is important that this function is called in order to apply the Drag and Pin commands. @param glw the GL widget. */ void Render(QGLWidget* glw); /*! @brief Set the current rubberband endpoint. This function should be called after MouseMove events. @param cursor the cursor position. */ void Drag(QPoint cursor); /*! @brief Ask for picking. This function should be called after MouseRelease events. The first time is called, if the picking is successful, sets the startpoint. The second time sets, if the picking is successful, the endpoint. After the second time this has no effect. @param cursor the cursor position. */ void Pin(QPoint cursor); /*! @brief Reset the rubberband. */ void Reset(); /*! @brief Return true if the rubberband has been drawn. @return true if the line has been drawn, false otherwise. */ bool IsReady(); /*! @brief Get the rubberband start and end points. @param startpoint is set to the rubberband start point. @param endpoint is set to the rubberband end point. @warning Don't call this function until IsReady() returns true! */ void GetPoints(Point3f &startpoint,Point3f &endpoint); /*! @brief Render a text label near the endpoint (if it exists). @param text the text to render. @param glw the GL widget. */ void RenderLabel(QString text,QGLWidget* glw); private: // types: typedef enum { RUBBER_BEGIN = 0, RUBBER_DRAGGING = 1, RUBBER_DRAGGED = 2, } RubberPhase; // data: RubberPhase currentphase; QPoint qt_cursor; Point3f start, end; bool have_to_pick; QFont font; // functions: Point3f PixelConvert(const Point3f); }; }//namespace #endif /*RUBBERBAND_H*/ qutemol/vcg/wrap/gui/rubberband.cpp0000444000175000017500000001612610755550143015763 0ustar mbamba/**************************************************************************** * MeshLab o o * * A versatile mesh processing toolbox o o * * _ O _ * * Copyright(C) 2008 \/)\/ * * Visual Computing Lab /\/| * * ISTI - Italian National Research Council | * * \ * * All rights reserved. * * * * 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. * * * * 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 (http://www.gnu.org/licenses/gpl.txt) * * for more details. * * * ****************************************************************************/ /**************************************************************************** History $Log: rubberband.cpp,v $ Revision 1.1 2008/02/16 12:00:35 benedetti first version, adapted from meshlab's editmeasure plugin ****************************************************************************/ #include #include #include #include "rubberband.h" using namespace vcg; Rubberband::Rubberband(Color4b c) :color(c),currentphase(RUBBER_BEGIN),qt_cursor(), start(0,0,0),end(0,0,0),have_to_pick(false),font() { font.setFamily("Helvetica"); font.setPixelSize(10); } void Rubberband::Render(QGLWidget* gla) { if(have_to_pick){ assert(currentphase!=RUBBER_DRAGGED); Point3f pick_point; bool picked = Pick(qt_cursor.x(), gla->height() - qt_cursor.y(), pick_point); if(picked){ // we have not picked the background have_to_pick=false; switch(currentphase){ case RUBBER_BEGIN: start = pick_point; gla->setMouseTracking(true); currentphase = RUBBER_DRAGGING; break; case RUBBER_DRAGGING: if(pick_point==start){ have_to_pick=true; break; } end = pick_point; gla->setMouseTracking(false); currentphase = RUBBER_DRAGGED; break; default: assert(0); } } } if(currentphase==RUBBER_BEGIN) return; // Drawing of the current line glPushAttrib(GL_DEPTH_BUFFER_BIT | GL_ENABLE_BIT | GL_LINE_BIT | GL_POINT_BIT | GL_CURRENT_BIT | GL_LIGHTING_BIT | GL_COLOR_BUFFER_BIT); glDisable(GL_LIGHTING); glDisable(GL_TEXTURE_2D); glDepthMask(false); glLineWidth(2.5); glPointSize(5.0); if(currentphase==RUBBER_DRAGGING ) { Point3f qt_start_point; qt_start_point = PixelConvert(start); glColor(color); glMatrixMode(GL_PROJECTION); glPushMatrix(); glLoadIdentity(); gluOrtho2D(0,gla->width(),gla->height(),0); glMatrixMode(GL_MODELVIEW); glPushMatrix(); glLoadIdentity(); glDisable(GL_DEPTH_TEST); glBegin(GL_LINES); glVertex2f(qt_start_point[0],qt_start_point[1]); glVertex2f(qt_cursor.x(),qt_cursor.y()); glEnd(); glEnable(GL_DEPTH_TEST); glMatrixMode(GL_PROJECTION); glPopMatrix(); glMatrixMode(GL_MODELVIEW); glPopMatrix(); } else { assert(currentphase == RUBBER_DRAGGED); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA); glEnable(GL_LINE_SMOOTH); glEnable(GL_POINT_SMOOTH); glColor(color); glBegin(GL_LINES); glVertex(start); glVertex(end); glEnd(); glBegin(GL_POINTS); glVertex(start); glVertex(end); glEnd(); glDisable(GL_DEPTH_TEST); glLineWidth(0.7); glPointSize(1.4); glBegin(GL_LINES); glVertex(start); glVertex(end); glEnd(); glBegin(GL_POINTS); glVertex(start); glVertex(end); glEnd(); } glPopAttrib(); assert(!glGetError()); } void Rubberband::Drag(QPoint p) { if(currentphase==RUBBER_DRAGGING); qt_cursor=p; } void Rubberband::Pin(QPoint p) { if(IsReady()) return; qt_cursor=p; have_to_pick=true; } void Rubberband::Reset() { currentphase = RUBBER_BEGIN; qt_cursor = QPoint(); start = Point3f(0,0,0); end = Point3f(0,0,0); have_to_pick = false; } bool Rubberband::IsReady() { return currentphase==RUBBER_DRAGGED; } void Rubberband::GetPoints(Point3f &s,Point3f &e) { assert(IsReady()); s=start; e=end; } void Rubberband::RenderLabel(QString text,QGLWidget* gla) { if(currentphase==RUBBER_BEGIN) return; int x,y; if(currentphase==RUBBER_DRAGGING){ x=qt_cursor.x()+16; y=qt_cursor.y()+16; } else { Point3f qt_start = PixelConvert(start); Point3f qt_end = PixelConvert(end); if(qt_start[0]>qt_end[0]){ x=int(qt_start[0]+5); y=int(qt_start[1]); }else{ x=int(qt_end[0]+5); y=int(qt_end[1]); } } QFontMetrics fm(font); QRect brec=fm.boundingRect(text); glPushAttrib(GL_CURRENT_BIT | GL_DEPTH_BUFFER_BIT | GL_ENABLE_BIT | GL_LINE_BIT ); glDisable(GL_LIGHTING); glDisable(GL_TEXTURE_2D); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA); glMatrixMode(GL_PROJECTION); glPushMatrix(); glLoadIdentity(); gluOrtho2D(0,gla->width(),gla->height(),0); glMatrixMode(GL_MODELVIEW); glPushMatrix(); glLoadIdentity(); glColor4f(0,0,0,0.5); glBegin(GL_QUADS); glVertex2f(x+brec.left(),y+brec.bottom()); glVertex2f(x+brec.right(),y+brec.bottom()); glVertex2f(x+brec.right(),y+brec.top()); glVertex2f(x+brec.left(),y+brec.top()); glEnd(); int offset=2; glColor4f(0,0,0,0.2); glBegin(GL_QUADS); glVertex2f(x+brec.left()-offset,y+brec.bottom()+offset); glVertex2f(x+brec.right()+offset,y+brec.bottom()+offset); glVertex2f(x+brec.right()+offset,y+brec.top()-offset); glVertex2f(x+brec.left()-offset,y+brec.top()-offset); glEnd(); glColor3f(1,1,1); gla->renderText(x,y,0.99f,text,font); glMatrixMode(GL_PROJECTION); glPopMatrix(); glMatrixMode(GL_MODELVIEW); glPopMatrix(); glPopAttrib(); } Point3f Rubberband::PixelConvert(const Point3f p) { GLint vm[4]; GLdouble mm[16]; GLdouble pm[16]; glGetIntegerv(GL_VIEWPORT, vm); glGetDoublev(GL_MODELVIEW_MATRIX, mm); glGetDoublev(GL_PROJECTION_MATRIX, pm); GLdouble wx,wy,wz; gluProject(p[0], p[1], p[2], mm, pm, vm, &wx, &wy, &wz); return Point3f(wx,vm[3]-wy,wz); } qutemol/vcg/wrap/bmt/0000755000175000017500000000000011633404241013134 5ustar mbambaqutemol/vcg/wrap/bmt/bmt.cpp0000444000175000017500000001213510034774046014431 0ustar mbamba#include using namespace std; using namespace vcg; Bmt::Bmt(): fp(NULL) {} Bmt::~Bmt() {} bool Bmt::Load(const std::string &filename) { fp = fopen(filename.c_str(), "rb"); if(!fp) return false; unsigned int magic; fread(&magic, sizeof(unsigned int), 1, fp); if(magic != 0x62647421) //bmt! return false; //signature fread(&signature, sizeof(unsigned int), 1, fp); //sphere fread(&sphere, sizeof(Sphere3f), 1, fp); //index and history offsets and size; fread(&index_offset, sizeof(unsigned int), 1, fp); fread(&index_size, sizeof(unsigned int), 1, fp); fread(&history_offset, sizeof(unsigned int), 1, fp); fread(&history_size, sizeof(unsigned int), 1, fp); //index index.resize(index_size); fread(&index[0], sizeof(Bmt::Cell), index.size(), fp); //history history.resize(history_size); for(unsigned int i = 0; i < history.size(); i++) { vector &created = history[i].created; vector &erased = history[i].erased; unsigned int created_size; fread(&created_size, sizeof(unsigned int), 1, fp); created.resize(created_size); fread(&*created.begin(), sizeof(unsigned int), created.size(), fp); for(unsigned int k = 0; k < created_size; k++) created[k] = &(index[(unsigned int)created[k]]); unsigned int erased_size; fread(&erased_size, sizeof(unsigned int), 1, fp); erased.resize(erased_size); fread(&*erased.begin(), sizeof(unsigned int), erased.size(), fp); for(unsigned int k = 0; k < erased_size; k++) erased[k] = &(index[(unsigned int)erased[k]]); } return true; } char *Bmt::GetData(unsigned int &size, unsigned int offset) { fseek(fp, offset, SEEK_SET); fread(&size, sizeof(unsigned int), 1, fp); assert(size < 64000); char *data = new char[size]; fread(data, 1, size, fp); return data; } /*unsigned int &Bmt::IndexOffset(); unsigned int &Bmt::IndexSize(); Bmt::Cell *Bmt::IndexBegin(); unsigned int &Bmt::HistoryOffset(); unsigned int &Bmt::HistorySize(); unsigned int *Bmt::HistoryBegin(); */ /**** BMT BUILDER ****/ BmtBuilder::BmtBuilder(): ftmp(NULL), fout(NULL) {} BmtBuilder::~BmtBuilder() {} bool BmtBuilder::Create(unsigned int sign) { signature = sign; ftmp = fopen("tmp.bmt", "wb+"); if(!ftmp) return false; return true; } unsigned int BmtBuilder::AddCell(Bmt::Cell cell, unsigned int size, char *data) { sphere.Add(cell.sphere); cell.offset = ftell(ftmp); index.push_back(cell); //TODO: add padding to 4 or 8 bytes. fwrite(&size, sizeof(unsigned int), 1, ftmp); fwrite(data, 1, size, ftmp); return index.size()-1; } void BmtBuilder::AddUpdate(std::vector &created, std::vector &erased) { creation.push_back(created); deletion.push_back(erased); } bool BmtBuilder::Save(const std::string &filename) { assert(ftmp); //TODO: reorganize data to be spatially coherent (both index and related data. fout = fopen(filename.c_str(), "wb+"); if(!fout) { fclose(ftmp); return false; } //first thing we write a magic constant "bmt!" unsigned int magic = 0x62647421; //bmt! fwrite(&magic, sizeof(unsigned int), 1, fout); //signature: fwrite(&signature, sizeof(unsigned int), 1, fout); //sphere fwrite(&sphere, sizeof(Sphere3f), 1, fout); //next we write index and history offset and size unsigned int index_offset = 5 * sizeof(unsigned int) + sizeof(Sphere3f); unsigned int index_size = index.size(); fwrite(&index_offset, sizeof(unsigned int), 1, fout); fwrite(&index_size, sizeof(unsigned int), 1, fout); unsigned int history_offset = index_offset + index_size * sizeof(Bmt::Cell); unsigned int history_size = creation.size(); fwrite(&history_offset, sizeof(unsigned int), 1, fout); fwrite(&history_size, sizeof(unsigned int), 1, fout); unsigned int index_start = ftell(fout); //writing index (but its a fake... it will need to be rewritten late5r with correct offsets fwrite(&index[0], sizeof(Bmt::Cell), index.size(), fout); //writing history for(unsigned int i = 0; i < creation.size(); i++) { vector &created = creation[i]; vector &erased = deletion[i]; unsigned int created_size = created.size(); fwrite(&created_size, sizeof(unsigned int), 1, fout); fwrite(&*created.begin(), sizeof(unsigned int), created.size(), fout); unsigned int erased_size = erased.size(); fwrite(&erased_size, sizeof(unsigned int), 1, fout); fwrite(&*created.begin(), sizeof(unsigned int), erased.size(), fout); } //writing data vector::iterator k; for(k = index.begin(); k != index.end(); k++) { Bmt::Cell &cell = *k; fseek(ftmp, cell.offset, SEEK_SET); unsigned int size; fread(&size, sizeof(unsigned int), 1, ftmp); char *data = new char[size]; fread(data, 1, size, ftmp); cell.offset = ftell(fout); fwrite(&size, sizeof(unsigned int), 1, fout); fwrite(data, 1, size, fout); delete []data; } //writing index again fseek(fout, index_start, SEEK_SET); fwrite(&index[0], sizeof(Bmt::Cell), index.size(), fout); fclose(fout); return true; } qutemol/vcg/wrap/bmt/bmt.h0000444000175000017500000000711410034774046014077 0ustar mbamba/**************************************************************************** * VCGLib o o * * Visual and Computer Graphics Library o o * * _ O _ * * Copyright(C) 2004 \/)\/ * * Visual Computing Lab /\/| * * ISTI - Italian National Research Council | * * \ * * All rights reserved. * * * * 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. * * * * 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 (http://www.gnu.org/licenses/gpl.txt) * * for more details. * * * ****************************************************************************/ /**************************************************************************** History $Log: bmt.h,v $ Revision 1.1 2004/04/07 12:46:30 ponchio Backup (working on it). ****************************************************************************/ #ifndef VCG_BMT_H #define VCG_BMT_H #include #include #include #include namespace vcg { /** \addtogroup bmt */ /*@{*/ /** The class for representing a batched mt structure. See bmt.cpp for details on the structure of the file. */ class Bmt { public: ///Cell structure for the mt representation class Cell { public: //this effectively limits databases to 4Gb in size. unsigned int offset; float error; Sphere3f sphere; float Error() { return error; } }; ///tells what is inside each cell. unsigned int signature; ///Bounding sphere Sphere3f sphere; std::vector index; std::vector< MT::Update > history; Bmt(); ~Bmt(); bool Load(const std::string &filename); char *GetData(unsigned int &size, unsigned int offset); private: FILE *fp; unsigned int index_offset; unsigned int index_size; unsigned int history_offset; unsigned int history_size; }; class BmtBuilder { public: BmtBuilder(); ~BmtBuilder(); ///tells what is inside each cell. unsigned int signature; ///Bounding sphere Sphere3f sphere; std::vector index; std::vector > creation; std::vector > deletion; bool Create(unsigned int signature); unsigned int AddCell(Bmt::Cell cell, unsigned int size, char *data); void AddUpdate(std::vector &created, std::vector &erased); bool Save(const std::string &filename); private: FILE *ftmp; FILE *fout; }; float Distance(Bmt::Cell &cell, Point3f &p); }//end namespace #endifqutemol/vcg/wrap/bmt/strip_mesh.h0000444000175000017500000000527210034774046015475 0ustar mbamba/**************************************************************************** * VCGLib o o * * Visual and Computer Graphics Library o o * * _ O _ * * Copyright(C) 2004 \/)\/ * * Visual Computing Lab /\/| * * ISTI - Italian National Research Council | * * \ * * All rights reserved. * * * * 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. * * * * 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 (http://www.gnu.org/licenses/gpl.txt) * * for more details. * * * ****************************************************************************/ /**************************************************************************** History $Log: strip_mesh.h,v $ Revision 1.1 2004/04/07 12:46:30 ponchio Backup (working on it). ****************************************************************************/ #ifndef VCG_STRIP_MESH_H #define VCG_STRIP_MESH_H #include namespace vcg { class StripMesh { public: enum Signature { NORMAL = 1, COLOR = 2, STRIP = 4 }; StripMesh(char *s); private: unsigned short _vert_size; unsigned short _norm_size; unsigned short _color_size; unsigned short _strip_size; Point3f *_vert_start; short *_norm_start; unsigned char *_color_start; unsigned short *_strip_start; }; class StripMeshBuilder { public: std::vector vert; std::vector norm; std::vector color; std::vector strip; unsigned int Signature(); ///required size; unsigned int Size(); void Write(char *buffer, unsigned int size); }; }//namespace #endif qutemol/vcg/wrap/gl/0000755000175000017500000000000011633404241012754 5ustar mbambaqutemol/vcg/wrap/gl/glu_tesselator.h0000444000175000017500000001673410755245447016211 0ustar mbamba/**************************************************************************** * VCGLib o o * * Visual and Computer Graphics Library o o * * _ O _ * * Copyright(C) 2004 \/)\/ * * Visual Computing Lab /\/| * * ISTI - Italian National Research Council | * * \ * * All rights reserved. * * * * 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. * * * * 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 (http://www.gnu.org/licenses/gpl.txt) * * for more details. * * * ****************************************************************************/ /**************************************************************************** History $Log: glu_tesselator.h,v $ Revision 1.5 2008/02/15 08:19:51 cignoni removed unused vars Revision 1.4 2007/12/01 18:09:14 m_di_benedetto Added cast to prevent pointer truncation warning/error messages. Revision 1.3 2007/08/28 05:43:56 cignoni Added ifdef needed for mac gcc compilation Revision 1.2 2007/08/25 08:43:33 cignoni moved here callback def and added some needed opengl related casts Revision 1.1 2007/05/14 22:23:36 m_di_benedetto First Commit. ****************************************************************************/ #ifndef __VCGLIB_GLU_TESSELATOR_H #define __VCGLIB_GLU_TESSELATOR_H #include //#include #ifndef CALLBACK #ifdef WIN32 #define CALLBACK __stdcall #else #define CALLBACK #endif #endif namespace vcg { class glu_tesselator { public: typedef glu_tesselator this_type; /* Works with Point2 and Point3; sample usage: // tesselation input: each outline represents a polygon contour std::vector< std::vector > outlines = ...; // tesselation output (triangles indices) std::vector indices; // compute triangles indices glu_tesselator::tesselate(outlines, indices); // unroll input contours points std::vector points; for (size_t i=0; i static inline void unroll(const std::vector< std::vector > & outlines, std::vector & points) { for (size_t i=0; i static inline void tesselate(const std::vector< std::vector > & outlines, std::vector & indices) { tess_prim_data_vec t_data; this_type::do_tesselation(outlines, t_data); //int k = 0; for (size_t i=0; i indices; tess_prim_data(void) { } tess_prim_data(GLenum t) : type(t) { } }; typedef std::vector tess_prim_data_vec; static void CALLBACK begin_cb(GLenum type, void * polygon_data) { tess_prim_data_vec * t_data = (tess_prim_data_vec *)polygon_data; t_data->push_back(tess_prim_data(type)); } static void CALLBACK end_cb(void * polygon_data) { (void)polygon_data; } static void CALLBACK vertex_cb(void * vertex_data, void * polygon_data) { tess_prim_data_vec * t_data = (tess_prim_data_vec *)polygon_data; t_data->back().indices.push_back((int)((size_t)vertex_data)); } template static void do_tesselation(const std::vector< std::vector > & outlines, tess_prim_data_vec & t_data) { GLUtesselator * tess = gluNewTess(); #ifdef __APPLE__ gluTessCallback(tess, GLU_TESS_BEGIN_DATA, (GLvoid (CALLBACK *)(...))(this_type::begin_cb)); gluTessCallback(tess, GLU_TESS_END_DATA, (GLvoid (CALLBACK *)(...))(this_type::end_cb)); gluTessCallback(tess, GLU_TESS_VERTEX_DATA, (GLvoid (CALLBACK *)(...))(this_type::vertex_cb)); #else gluTessCallback(tess, GLU_TESS_BEGIN_DATA, (GLvoid (CALLBACK *)())(this_type::begin_cb)); gluTessCallback(tess, GLU_TESS_END_DATA, (GLvoid (CALLBACK *)())(this_type::end_cb)); gluTessCallback(tess, GLU_TESS_VERTEX_DATA, (GLvoid (CALLBACK *)())(this_type::vertex_cb)); #endif void * polygon_data = (void *)(&t_data); GLdouble vertex[3]; int k = 0; gluTessBeginPolygon(tess, polygon_data); for (size_t i=0; i static inline void get_position(const vcg::Point2 & p, GLdouble * d) { d[0] = (GLdouble)(p[0]); d[1] = (GLdouble)(p[1]); d[2] = (GLdouble)(0); } template static inline void get_position(const vcg::Point3 & p, GLdouble * d) { d[0] = (GLdouble)(p[0]); d[1] = (GLdouble)(p[1]); d[2] = (GLdouble)(p[2]); } }; } // end namespace vcg #endif // __VCGLIB_GLU_TESSELATOR_H qutemol/vcg/wrap/gl/space.h0000444000175000017500000002535410661243560014234 0ustar mbamba/**************************************************************************** * VCGLib o o * * Visual and Computer Graphics Library o o * * _ O _ * * Copyright(C) 2004 \/)\/ * * Visual Computing Lab /\/| * * ISTI - Italian National Research Council | * * \ * * All rights reserved. * * * * 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. * * * * 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 (http://www.gnu.org/licenses/gpl.txt) * * for more details. * * * ****************************************************************************/ /**************************************************************************** History $Log: space.h,v $ Revision 1.11 2007/08/17 07:00:00 cignoni added a missing typename Revision 1.10 2007/07/31 12:21:50 ganovelli added gltetra, added normal gltriangle Revision 1.9 2007/05/08 18:55:38 ganovelli glTriangle added Revision 1.8 2007/01/18 01:26:23 cignoni Added cast for mac compiling Revision 1.7 2005/10/13 08:32:26 cignoni Added glscale(scalar) and corrected bug in glscale(point2) Revision 1.6 2005/06/30 10:17:04 ganovelli added draw plane Revision 1.5 2005/05/05 12:28:13 cignoni added glboxwire Revision 1.4 2004/07/07 23:30:28 cignoni Added box3 drawing functions Revision 1.3 2004/05/26 15:13:01 cignoni Removed inclusion of gl extension stuff and added glcolor stuff Revision 1.2 2004/05/13 23:44:47 ponchio --> Revision 1.1 2004/04/05 11:56:14 cignoni First working version! ****************************************************************************/ #ifndef VCG_GL_SPACE_H #define VCG_GL_SPACE_H // Please note that this file assume that you have already included your // gl-extension wrapping utility, and that therefore all the extension symbol are already defined. #include #include #include #include #include #include #include namespace vcg { inline void glScale(float const & p){ glScalef(p,p,p);} inline void glScale(double const & p){ glScaled(p,p,p);} inline void glVertex(Point2 const & p) { glVertex2iv((const GLint*)p.V());} inline void glVertex(Point2 const & p) { glVertex2sv(p.V());} inline void glVertex(Point2 const & p) { glVertex2fv(p.V());} inline void glVertex(Point2 const & p){ glVertex2dv(p.V());} inline void glTexCoord(Point2 const & p) { glTexCoord2iv((const GLint*)p.V());} inline void glTexCoord(Point2 const & p) { glTexCoord2sv(p.V());} inline void glTexCoord(Point2 const & p) { glTexCoord2fv(p.V());} inline void glTexCoord(Point2 const & p){ glTexCoord2dv(p.V());} inline void glTranslate(Point2 const & p) { glTranslatef(p[0],p[1],0);} inline void glTranslate(Point2 const & p){ glTranslated(p[0],p[1],0);} inline void glScale(Point2 const & p) { glScalef(p[0],p[1],1.0);} inline void glScale(Point2 const & p){ glScaled(p[0],p[1],1.0);} inline void glVertex(Point3 const & p) { glVertex3iv((const GLint*)p.V());} inline void glVertex(Point3 const & p) { glVertex3sv(p.V());} inline void glVertex(Point3 const & p) { glVertex3fv(p.V());} inline void glVertex(Point3 const & p){ glVertex3dv(p.V());} inline void glNormal(Point3 const & p) { glNormal3iv((const GLint*)p.V());} inline void glNormal(Point3 const & p) { glNormal3sv(p.V());} inline void glNormal(Point3 const & p) { glNormal3fv(p.V());} inline void glNormal(Point3 const & p){ glNormal3dv(p.V());} inline void glTexCoord(Point3 const & p) { glTexCoord3iv((const GLint*)p.V());} inline void glTexCoord(Point3 const & p) { glTexCoord3sv(p.V());} inline void glTexCoord(Point3 const & p) { glTexCoord3fv(p.V());} inline void glTexCoord(Point3 const & p){ glTexCoord3dv(p.V());} inline void glTranslate(Point3 const & p) { glTranslatef(p[0],p[1],p[2]);} inline void glTranslate(Point3 const & p){ glTranslated(p[0],p[1],p[2]);} inline void glScale(Point3 const & p) { glScalef(p[0],p[1],p[2]);} inline void glScale(Point3 const & p){ glScaled(p[0],p[1],p[2]);} inline void glColor(Color4b const & c) { glColor4ubv(c.V());} inline void glClearColor(Color4b const &c) { ::glClearColor(float(c[0])/255.0f,float(c[1])/255.0f,float(c[2])/255.0f,1.0f);} inline void glLight(GLenum light, GLenum pname, Color4b const & c) { static float cf[4]; cf[0]=float(cf[0]/255.0); cf[1]=float(c[1]/255.0); cf[2]=float(c[2]/255.0); cf[3]=float(c[3]/255.0); glLightfv(light,pname,cf); } template inline void glBoxWire(Box3 const & b) { glPushAttrib(GL_ENABLE_BIT); glDisable(GL_LIGHTING); glBegin(GL_LINE_STRIP); glVertex3f((float)b.min[0],(float)b.min[1],(float)b.min[2]); glVertex3f((float)b.max[0],(float)b.min[1],(float)b.min[2]); glVertex3f((float)b.max[0],(float)b.max[1],(float)b.min[2]); glVertex3f((float)b.min[0],(float)b.max[1],(float)b.min[2]); glVertex3f((float)b.min[0],(float)b.min[1],(float)b.min[2]); glEnd(); glBegin(GL_LINE_STRIP); glVertex3f((float)b.min[0],(float)b.min[1],(float)b.max[2]); glVertex3f((float)b.max[0],(float)b.min[1],(float)b.max[2]); glVertex3f((float)b.max[0],(float)b.max[1],(float)b.max[2]); glVertex3f((float)b.min[0],(float)b.max[1],(float)b.max[2]); glVertex3f((float)b.min[0],(float)b.min[1],(float)b.max[2]); glEnd(); glBegin(GL_LINES); glVertex3f((float)b.min[0],(float)b.min[1],(float)b.min[2]); glVertex3f((float)b.min[0],(float)b.min[1],(float)b.max[2]); glVertex3f((float)b.max[0],(float)b.min[1],(float)b.min[2]); glVertex3f((float)b.max[0],(float)b.min[1],(float)b.max[2]); glVertex3f((float)b.max[0],(float)b.max[1],(float)b.min[2]); glVertex3f((float)b.max[0],(float)b.max[1],(float)b.max[2]); glVertex3f((float)b.min[0],(float)b.max[1],(float)b.min[2]); glVertex3f((float)b.min[0],(float)b.max[1],(float)b.max[2]); glEnd(); glPopAttrib(); }; template /// Funzione di utilita' per la visualizzazione in OpenGL (flat shaded) inline void glBoxFlat(Box3 const & b) { glPushAttrib(GL_SHADE_MODEL); glShadeModel(GL_FLAT); glBegin(GL_QUAD_STRIP); glNormal3f(.0f,.0f,1.0f); glVertex3f(b.min[0], b.max[1], b.max[2]); glVertex3f(b.min[0], b.min[1], b.max[2]); glVertex3f(b.max[0], b.max[1], b.max[2]); glVertex3f(b.max[0], b.min[1], b.max[2]); glNormal3f(1.0f,.0f,.0f); glVertex3f(b.max[0], b.max[1], b.min[2]); glVertex3f(b.max[0], b.min[1], b.min[2]); glNormal3f(.0f,.0f,-1.0f); glVertex3f(b.min[0], b.max[1], b.min[2]); glVertex3f(b.min[0], b.min[1], b.min[2]); glNormal3f(-1.0f,.0f,.0f); glVertex3f(b.min[0], b.max[1], b.max[2]); glVertex3f(b.min[0], b.min[1], b.max[2]); glEnd(); glBegin(GL_QUADS); glNormal3f(.0f,1.0f,.0f); glVertex3f(b.min[0], b.max[1], b.max[2]); glVertex3f(b.max[0], b.max[1], b.max[2]); glVertex3f(b.max[0], b.max[1], b.min[2]); glVertex3f(b.min[0], b.max[1], b.min[2]); glNormal3f(.0f,-1.0f,.0f); glVertex3f(b.min[0], b.min[1], b.min[2]); glVertex3f(b.max[0], b.min[1], b.min[2]); glVertex3f(b.max[0], b.min[1], b.max[2]); glVertex3f(b.min[0], b.min[1], b.max[2]); glEnd(); glPopAttrib(); }; template /// Setta i sei clip planes di opengl a far vedere solo l'interno del box inline void glBoxClip(const Box3 & b) { double eq[4]; eq[0]= 1; eq[1]= 0; eq[2]= 0; eq[3]=(double)-b.min[0]; glClipPlane(GL_CLIP_PLANE0,eq); eq[0]=-1; eq[1]= 0; eq[2]= 0; eq[3]=(double) b.max[0]; glClipPlane(GL_CLIP_PLANE1,eq); eq[0]= 0; eq[1]= 1; eq[2]= 0; eq[3]=(double)-b.min[1]; glClipPlane(GL_CLIP_PLANE2,eq); eq[0]= 0; eq[1]=-1; eq[2]= 0; eq[3]=(double) b.max[1]; glClipPlane(GL_CLIP_PLANE3,eq); eq[0]= 0; eq[1]= 0; eq[2]= 1; eq[3]=(double)-b.min[2]; glClipPlane(GL_CLIP_PLANE4,eq); eq[0]= 0; eq[1]= 0; eq[2]=-1; eq[3]=(double) b.max[2]; glClipPlane(GL_CLIP_PLANE5,eq); } template inline void glBoxWire(const Box2 & b) { glPushAttrib(GL_ENABLE_BIT); glDisable(GL_LIGHTING); glBegin(GL_LINE_LOOP); glVertex2f((float)b.min[0],(float)b.min[1]); glVertex2f((float)b.max[0],(float)b.min[1]); glVertex2f((float)b.max[0],(float)b.max[1]); glVertex2f((float)b.min[0],(float)b.max[1]); glEnd(); glPopAttrib(); }; template inline void glPlane3( Plane3 p, Point3 c, T size ) { Point3 w = p.Direction(); Point3 u,v,c1; GetUV(w,u,v); c1 = p.Projection(c); u.Normalize(); w.Normalize(); v.Normalize(); Matrix44 m; *(Point3*)&m[0][0] = *(Point3*)&u[0];m[0][3]=0; *(Point3*)&m[1][0] = *(Point3*)&w[0];m[1][3]=0; *(Point3*)&m[2][0] = *(Point3*)&v[0];m[2][3]=0; *(Point3*)&m[3][0] = *(Point3*)&c1[0];m[3][3]=1; vcg::Transpose(m); glPushMatrix(); glMultMatrix(m); glBegin(GL_QUADS); glNormal(Point3(0,1,0)); glVertex(Point3(-size,0,-size)); glVertex(Point3(size ,0,-size)); glVertex(Point3(size ,0, size)); glVertex(Point3(-size,0, size)); glEnd(); glPopMatrix(); } template inline void glTriangle3( TriangleType & c ) { vcg::Point3 n = vcg::Normal(c); glBegin(GL_TRIANGLES); glNormal(n); glVertex(c.P(0)); glVertex(c.P(1)); glVertex(c.P(2)); glEnd(); } template inline void glTetra3( TetraType & c ) { glTriangle3(Triangle3(c.P(0),c.P(1),c.P(2))); glTriangle3(Triangle3(c.P(1),c.P(3),c.P(2))); glTriangle3(Triangle3(c.P(0),c.P(2),c.P(3))); glTriangle3(Triangle3(c.P(1),c.P(0),c.P(3))); } }//namespace #endif qutemol/vcg/wrap/gl/trimesh.h0000444000175000017500000006606310747313466014626 0ustar mbamba/**************************************************************************** * VCGLib o o * * Visual and Computer Graphics Library o o * * _ O _ * * Copyright(C) 2004 \/)\/ * * Visual Computing Lab /\/| * * ISTI - Italian National Research Council | * * \ * * All rights reserved. * * * * 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. * * * * 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 (http://www.gnu.org/licenses/gpl.txt) * * for more details. * * * ****************************************************************************/ /**************************************************************************** History $Log: trimesh.h,v $ Revision 1.28 2008/01/28 08:49:58 cignoni added sanity checks when deleting buffers Revision 1.27 2007/12/05 11:08:16 mischitelli Renamed some unmeaningful variable names (b -> array_buffers ; h -> curr_hints) Revision 1.26 2007/12/04 17:59:41 mischitelli - Fixed DrawFill method, which required the hint 'HNUseVArray' enabled in order to render the mesh with VBO. This was also causing extra overhead in the Update method since HNUseVArray has to be enabled and therefore extra calculation were done to copy vertices in VArrays even if the user was using only VBOs. Revision 1.25 2007/09/12 16:20:24 m_di_benedetto *** empty log message *** Revision 1.24 2007/09/12 14:48:50 m_di_benedetto Corrected indexing for non textured faces. Revision 1.23 2007/01/18 01:26:23 cignoni Added cast for mac compiling Revision 1.22 2006/12/12 11:06:58 cignoni Slightly changed the colormaterial mode for the flatwire Revision 1.21 2006/10/14 16:26:26 ponchio Aggiunti un paio di typename... al solito. Revision 1.20 2006/05/25 09:40:14 cignoni gcc dislike doubleline comments; removed. Revision 1.19 2006/02/13 13:05:05 cignoni Removed glew inclusion Revision 1.18 2006/02/09 10:00:39 cignoni Switched from rough zoffset to glpolygonoffset for hiddenline and flatlines modes. Less zfighting... Revision 1.17 2005/12/15 14:05:59 spinelli add test (tm==TMPerWedgeMulti) Revision 1.16 2005/12/14 00:18:43 cignoni multiple texture support Revision 1.15 2005/12/02 10:38:07 cignoni Changed a wrong uppercase in the include Revision 1.14 2005/12/02 00:03:22 cignoni Added support for one texture mode (perwedge) Changed texturemapid array into a safer vector Revision 1.13 2005/11/24 08:06:50 cignoni Added bound checking in texture access Revision 1.12 2005/11/22 23:57:28 cignoni Added a missing colormaterial for flatwire. Revision 1.11 2005/10/12 18:24:30 ponchio another bunch of typenames. Revision 1.10 2005/10/12 17:19:03 ponchio Added gazillions typenames, commented out old broken functions, added unsigned int TextureMapID[128], and unsigned int & TMId(int i). Revision 1.9 2005/05/09 11:28:48 spinelli ho tolto 2 warning del tipo unreferenced formal parameter, commentando le var che producevano tale warning. Revision 1.8 2005/04/22 15:16:48 turini Minor Changes To Compile With List Containers. Revision 1.7 2005/02/26 12:45:23 spinelli ripristinata la modalita' di render bbox.... Revision 1.6 2005/01/12 14:39:41 tommyfranken constructor name was wrong (old class name) Revision 1.5 2004/12/15 18:45:07 tommyfranken *** empty log message *** Revision 1.4 2004/09/30 01:40:39 ponchio --> Revision 1.3 2004/07/13 11:25:57 pietroni changed order of initial include ( it had problems with extension of openGL) Revision 1.2 2004/07/12 15:57:33 ganovelli first draft: it includes glew ! ****************************************************************************/ #ifndef __VCG_GLTRIMESH #define __VCG_GLTRIMESH #include #include //#include #include #include namespace vcg { // classe base di glwrap usata solo per poter usare i vari drawmode, normalmode senza dover // specificare tutto il tipo (a volte lunghissimo) // della particolare classe glwrap usata. class GLW { public: enum DrawMode {DMNone, DMBox, DMPoints, DMWire, DMHidden, DMFlat, DMSmooth, DMFlatWire, DMRadar, DMLast} ; enum NormalMode {NMNone, NMPerVert, NMPerFace, NMPerWedge, NMLast}; enum ColorMode {CMNone, CMPerMesh, CMPerFace, CMPerVert, CMLast}; enum TextureMode{TMNone, TMPerVert, TMPerWedge, TMPerWedgeMulti}; enum Hint { HNUseTriStrip = 0x0001, // ha bisogno che ci sia la fftopology gia calcolata! // HNUseEdgeStrip = 0x0002, // HNUseDisplayList = 0x0004, HNCacheDisplayList = 0x0008, // Each mode has its dl; HNLazyDisplayList = 0x0010, // Display list are generated only when requested HNIsTwoManifold = 0x0020, // There is no need to make DetachComplex before . HNUsePerWedgeNormal = 0x0040, // HNHasFFTopology = 0x0080, // E' l'utente che si preoccupa di tenere aggiornata la topologia ff HNHasVFTopology = 0x0100, // E' l'utente che si preoccupa di tenere aggiornata la topologia vf HNHasVertNormal = 0x0200, // E' l'utente che si preoccupa di tenere aggiornata le normali per faccia HNHasFaceNormal = 0x0400, // E' l'utente che si preoccupa di tenere aggiornata le normali per vertice HNUseVArray = 0x0800, HNUseLazyEdgeStrip = 0x1000, // Edge Strip are generated only when requested HNUseVBO = 0x2000 // Use Vertex Buffer Object }; enum Change { CHVertex = 0x01, CHNormal = 0x02, CHColor = 0x04, CHFace = 0x08, CHFaceNormal = 0x10, CHRender = 0x20, CHAll = 0xff }; enum HintParami { HNPDisplayListSize =0 }; enum HintParamf { HNPCreaseAngle =0, // crease angle in radians HNPZTwist = 1 // Z offset used in Flatwire and hiddenline modality }; template class VertToSplit { public: typename MESH_TYPE::face_base_pointer f; char z; char edge; bool newp; typename MESH_TYPE::vertex_pointer v; }; // GL Array Elemet class GLAElem { public : int glmode; int len; int start; }; }; template > class GlTrimesh : public GLW { public: typedef MESH_TYPE mesh_type; FACE_POINTER_CONTAINER face_pointers; std::vector TMId; unsigned int array_buffers[3]; int curr_hints; // the current hints // The parameters of hints int HNParami[8]; float HNParamf[8]; MESH_TYPE *m; GlTrimesh() { m=0; dl=0xffffffff; curr_hints=HNUseLazyEdgeStrip; cdm=DMNone; ccm=CMNone; cnm=NMNone; SetHintParamf(HNPCreaseAngle,float(M_PI/5)); SetHintParamf(HNPZTwist,0.00005f); } ~GlTrimesh() { //Delete the VBOs if(curr_hints&HNUseVBO) { for(int i=0;i<3;++i) if(glIsBuffer(array_buffers[i])) glDeleteBuffersARB(1, (GLuint *)(array_buffers+i)); } } void SetHintParami(const HintParami hip, const int value) { HNParami[hip]=value; } int GetHintParami(const HintParami hip) const { return HNParami[hip]; } void SetHintParamf(const HintParamf hip, const float value) { HNParamf[hip]=value; } float GetHintParamf(const HintParamf hip) const { return HNParamf[hip]; } void SetHint(Hint hn) { curr_hints |= hn; } void ClearHint(Hint hn) { curr_hints&=(~hn); } unsigned int dl; std::vector indices; DrawMode cdm; // Current DrawMode NormalMode cnm; // Current NormalMode ColorMode ccm; // Current ColorMode void Update(/*Change c=CHAll*/) { if(m==0) return; if(curr_hints&HNUseVArray || curr_hints&HNUseVBO) { typename MESH_TYPE::FaceIterator fi; indices.clear(); for(fi = m->face.begin(); fi != m->face.end(); ++fi) { indices.push_back((unsigned int)((*fi).V(0) - &(*m->vert.begin()))); indices.push_back((unsigned int)((*fi).V(1) - &(*m->vert.begin()))); indices.push_back((unsigned int)((*fi).V(2) - &(*m->vert.begin()))); } if(curr_hints&HNUseVBO) { if(!glIsBuffer(array_buffers[1])) glGenBuffers(2,(GLuint*)array_buffers); glBindBuffer(GL_ARRAY_BUFFER,array_buffers[0]); glBufferData(GL_ARRAY_BUFFER_ARB, m->vn * sizeof(typename MESH_TYPE::VertexType), (char *)&(m->vert[0].P()), GL_STATIC_DRAW_ARB); glBindBuffer(GL_ARRAY_BUFFER,array_buffers[1]); glBufferData(GL_ARRAY_BUFFER_ARB, m->vn * sizeof(typename MESH_TYPE::VertexType), (char *)&(m->vert[0].N()), GL_STATIC_DRAW_ARB); } glVertexPointer(3,GL_FLOAT,sizeof(typename MESH_TYPE::VertexType),0); glNormalPointer(GL_FLOAT,sizeof(typename MESH_TYPE::VertexType),0); } //int C=c; //if((C&CHVertex) || (C&CHFace)) { // ComputeBBox(*m); // if(!(curr_hints&HNHasFaceNormal)) m->ComputeFaceNormal(); // if(!(curr_hints&HNHasVertNormal)) m->ComputeVertexNormal(); // C= (C | CHFaceNormal); //} //if((C&CHFace) && (curr_hints&HNUseEdgeStrip)) ComputeEdges(); //if((C&CHFace) && (curr_hints&HNUseLazyEdgeStrip)) ClearEdges(); //if(MESH_TYPE::HasFFTopology()) // if((C&CHFace) && (curr_hints&HNUseTriStrip)) { // if(!(curr_hints&HNHasFFTopology)) m->FFTopology(); // ComputeTriStrip(); // } //if((C&CHFaceNormal) && (curr_hints&HNUsePerWedgeNormal)) { // if(!(curr_hints&HNHasVFTopology)) m->VFTopology(); // CreaseWN(*m,MESH_TYPE::scalar_type(GetHintParamf(HNPCreaseAngle))); //} //if(C!=0) { // force the recomputation of display list // cdm=DMNone; // ccm=CMNone; // cnm=NMNone; //} //if((curr_hints&HNUseVArray) && (curr_hints&HNUseTriStrip)) // { // ConvertTriStrip(*m,TStrip,TStripF,TStripVED,TStripVEI); // } } void Draw(DrawMode dm ,ColorMode cm, TextureMode tm) { switch(dm) { case DMNone : Draw(cm,tm); break; case DMBox : Draw(cm,tm); break; case DMPoints : Draw(cm,tm); break; case DMWire : Draw(cm,tm); break; case DMHidden : Draw(cm,tm); break; case DMFlat : Draw(cm,tm); break; case DMSmooth : Draw(cm,tm); break; case DMFlatWire: Draw(cm,tm); break; default : break; } } template< DrawMode dm > void Draw(ColorMode cm, TextureMode tm) { switch(cm) { case CMNone : Draw(tm); break; case CMPerMesh : Draw(tm); break; case CMPerFace : Draw(tm); break; case CMPerVert : Draw(tm); break; default : break; } } template< DrawMode dm, ColorMode cm > void Draw(TextureMode tm) { switch(tm) { case TMNone : Draw(); break; case TMPerVert : Draw(); break; case TMPerWedge : Draw(); break; case TMPerWedgeMulti : Draw(); break; default : break; } } template< DrawMode dm, ColorMode cm, TextureMode tm> void Draw() { if(!m) return; if((curr_hints & HNUseDisplayList)){ if (cdm==dm && ccm==cm){ glCallList(dl); return; } else { if(dl==0xffffffff) dl=glGenLists(1); glNewList(dl,GL_COMPILE); } } glPushMatrix(); switch(dm) { case DMNone : break; case DMBox : DrawBBox(cm);break; case DMPoints : DrawPoints();break; case DMHidden : DrawHidden();break; case DMFlat : DrawFill();break; case DMFlatWire : DrawFlatWire();break; case DMRadar : DrawRadar();break; case DMWire : DrawWire();break; case DMSmooth : DrawFill();break; default : break; } glPopMatrix(); if((curr_hints & HNUseDisplayList)){ cdm=dm; ccm=cm; glEndList(); glCallList(dl); } } /*********************************************************************************************/ /*********************************************************************************************/ template void DrawFill() { typename FACE_POINTER_CONTAINER::iterator fp; typename MESH_TYPE::FaceIterator fi; typename std::vector::iterator fip; short curtexname=-1; if(cm == CMPerMesh) glColor(m->C()); if(tm == TMPerWedge || tm == TMPerWedgeMulti ) glDisable(GL_TEXTURE_2D); if(curr_hints&HNUseVBO) { if( (cm==CMNone) || (cm==CMPerMesh) ) { if (nm==NMPerVert) glEnableClientState (GL_NORMAL_ARRAY); glEnableClientState (GL_VERTEX_ARRAY); if (nm==NMPerVert) { glBindBuffer(GL_ARRAY_BUFFER,array_buffers[1]); glNormalPointer(GL_FLOAT,sizeof(typename MESH_TYPE::VertexType),0); } glBindBuffer(GL_ARRAY_BUFFER,array_buffers[0]); glVertexPointer(3,GL_FLOAT,sizeof(typename MESH_TYPE::VertexType),0); glDrawElements(GL_TRIANGLES ,m->fn*3,GL_UNSIGNED_INT, &(*indices.begin()) ); glDisableClientState (GL_VERTEX_ARRAY); if (nm==NMPerVert) glDisableClientState (GL_NORMAL_ARRAY); glBindBuffer(GL_ARRAY_BUFFER, 0); return; } } if(curr_hints&HNUseVArray) { if( (cm==CMNone) || (cm==CMPerMesh) ) { if (nm==NMPerVert) glEnableClientState (GL_NORMAL_ARRAY); glEnableClientState (GL_VERTEX_ARRAY); if (nm==NMPerVert) glNormalPointer(GL_FLOAT,sizeof(typename MESH_TYPE::VertexType),&(m->vert.begin()->N()[0])); glVertexPointer(3,GL_FLOAT,sizeof(typename MESH_TYPE::VertexType),&(m->vert.begin()->P()[0])); glDrawElements(GL_TRIANGLES ,m->fn*3,GL_UNSIGNED_INT, &(*indices.begin()) ); glDisableClientState (GL_VERTEX_ARRAY); if (nm==NMPerVert) glDisableClientState (GL_NORMAL_ARRAY); return; } } else if(curr_hints&HNUseTriStrip) { //if( (nm==NMPerVert) && ((cm==CMNone) || (cm==CMPerMesh))) // if(curr_hints&HNUseVArray){ // glEnableClientState (GL_NORMAL_ARRAY ); // glNormalPointer(GL_FLOAT,sizeof(MESH_TYPE::VertexType),&(m->vert[0].cN())); // glEnableClientState (GL_VERTEX_ARRAY); // glVertexPointer(3,GL_FLOAT,sizeof(MESH_TYPE::VertexType),&(m->vert[0].cP())); // std::vector::iterator vi; // for(vi=TStripVED.begin();vi!=TStripVED.end();++vi) // glDrawElements(vi->glmode ,vi->len,GL_UNSIGNED_SHORT,&TStripVEI[vi->start] ); // // glDisableClientState (GL_NORMAL_ARRAY ); // glDisableClientState (GL_VERTEX_ARRAY); // return; // } //std::vector< MESH_TYPE::VertexType *>::iterator vi; //glBegin(GL_TRIANGLE_STRIP); //if(nm == NMPerFace) fip=TStripF.begin(); //for(vi=TStrip.begin();vi!=TStrip.end(); ++vi){ // if((*vi)){ // if(nm==NMPerVert) glNormal((*vi)->cN()); // if(nm==NMPerFace) glNormal((*fip)->cN()); // glVertex((*vi)->P()); // } // else // { // glEnd(); // glBegin(GL_TRIANGLE_STRIP); // } // if(nm == NMPerFace) ++fip; // } //glEnd(); } else { if(partial) fp = face_pointers.begin(); else fi = m->face.begin(); if(tm==TMPerWedgeMulti) { curtexname=(*fi).WT(0).n(); if (curtexname >= 0) { glEnable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D,TMId[curtexname]); } else { glDisable(GL_TEXTURE_2D); } } glBegin(GL_TRIANGLES); while( (partial)?(fp!=face_pointers.end()):(fi!=m->face.end())) { typename MESH_TYPE::FaceType & f = (partial)?(*(*fp)): *fi; if(!f.IsD()) { if(tm==TMPerWedgeMulti) if(f.WT(0).n() != curtexname) { curtexname=(*fi).WT(0).n(); glEnd(); if (curtexname >= 0) { glEnable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D,TMId[curtexname]); } else { glDisable(GL_TEXTURE_2D); } glBegin(GL_TRIANGLES); } if(nm == NMPerFace) glNormal(f.cN()); if(nm == NMPerVert) glNormal(f.V(0)->cN()); if(nm == NMPerWedge)glNormal(f.WN(0)); if(cm == CMPerFace) glColor(f.C()); if(cm == CMPerVert) glColor(f.V(0)->C()); // if(tm==TMPerVert) glTexCoord(f.V(0)->T()); if( (tm==TMPerWedge)||(tm==TMPerWedgeMulti) )glTexCoord(f.WT(0).t(0)); glVertex(f.V(0)->P()); if(nm == NMPerVert) glNormal(f.V(1)->cN()); if(nm == NMPerWedge)glNormal(f.WN(1)); if(cm == CMPerVert) glColor(f.V(1)->C()); // if(tm==TMPerVert) glTexCoord(f.V(1)->T()); if( (tm==TMPerWedge)|| (tm==TMPerWedgeMulti)) glTexCoord(f.WT(1).t(0)); glVertex(f.V(1)->P()); if(nm == NMPerVert) glNormal(f.V(2)->cN()); if(nm == NMPerWedge)glNormal(f.WN(2)); if(cm == CMPerVert) glColor(f.V(2)->C()); // if(tm==TMPerVert) glTexCoord(f.V(2)->T()); if( (tm==TMPerWedge)|| (tm==TMPerWedgeMulti)) glTexCoord(f.WT(2).t(0)); glVertex(f.V(2)->P()); } if(partial) ++fp; else ++fi; } glEnd(); } } template void DrawPoints() { typename MESH_TYPE::VertexIterator vi; glBegin(GL_POINTS); if(cm==CMPerMesh) glColor(m->C()); for(vi=m->vert.begin();vi!=m->vert.end();++vi)if(!(*vi).IsD()) { if(nm==NMPerVert) glNormal((*vi).cN()); if(cm==CMPerVert) glColor((*vi).C()); glVertex((*vi).P()); } glEnd(); } void DrawHidden() { //const float ZTWIST=HNParamf[HNPZTwist]; glPushAttrib(GL_ENABLE_BIT | GL_CURRENT_BIT | GL_LIGHTING_BIT ); glEnable(GL_POLYGON_OFFSET_FILL); glPolygonOffset(1.0, 1); //glDepthRange(ZTWIST,1.0f); glDisable(GL_LIGHTING); glColorMask(GL_FALSE,GL_FALSE,GL_FALSE,GL_FALSE); DrawFill(); glDisable(GL_POLYGON_OFFSET_FILL); glEnable(GL_LIGHTING); glColorMask(GL_TRUE,GL_TRUE,GL_TRUE,GL_TRUE); //glDepthRange(0.0f,1.0f-ZTWIST); DrawWire(); glPopAttrib(); // glDepthRange(0,1.0f); } template void DrawFlatWire() { //const float ZTWIST=HNParamf[HNPZTwist]; //glDepthRange(ZTWIST,1.0f); glPushAttrib(GL_ENABLE_BIT | GL_CURRENT_BIT | GL_LIGHTING_BIT ); glEnable(GL_POLYGON_OFFSET_FILL); glPolygonOffset(1.0, 1); DrawFill(); glDisable(GL_POLYGON_OFFSET_FILL); //glDepthRange(0.0f,1.0f-ZTWIST); glEnable(GL_COLOR_MATERIAL); glColorMaterial(GL_FRONT_AND_BACK,GL_AMBIENT_AND_DIFFUSE); //glColorMaterial(GL_FRONT,GL_DIFFUSE); glColor3f(.3f,.3f,.3f); DrawWire(); glPopAttrib(); //glDepthRange(0,1.0f); } template void DrawRadar() { const float ZTWIST=HNParamf[HNPZTwist]; glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glDepthMask(0); glDepthRange(ZTWIST,1.0f); if (cm == CMNone) glColor4f(0.2f, 1.0f, 0.4f, 0.2f); // DrawFill(); Draw(); glDepthMask(1); glColorMask(GL_FALSE,GL_FALSE,GL_FALSE,GL_FALSE); // DrawFill(); Draw(); glDepthRange(0.0f,1.0f-ZTWIST); glColorMask(GL_TRUE,GL_TRUE,GL_TRUE,GL_TRUE); glColor4f(0.1f, 1.0f, 0.2f, 0.6f); Draw(); glDisable(GL_BLEND); glDepthRange(0,1.0f); } #ifdef GL_TEXTURE0_ARB // Multitexturing nel caso voglia usare due texture unit. void DrawTexture_NPV_TPW2() { unsigned int texname=(*(m->face.begin())).WT(0).n(0); glBindTexture(GL_TEXTURE_2D,TMId[texname]); typename MESH_TYPE::FaceIterator fi; glBegin(GL_TRIANGLES); for(fi=m->face.begin();fi!=m->face.end();++fi)if(!(*fi).IsD()){ if(texname!=(*fi).WT(0).n(0)) { texname=(*fi).WT(0).n(0); glEnd(); glBindTexture(GL_TEXTURE_2D,TMId[texname]); glBegin(GL_TRIANGLES); } glMultiTexCoordARB(GL_TEXTURE0_ARB, (*fi).WT(0).t(0)); glMultiTexCoordARB(GL_TEXTURE1_ARB, (*fi).WT(0).t(0)); glNormal((*fi).V(0)->N()); glVertex((*fi).V(0)->P()); glMultiTexCoordARB(GL_TEXTURE0_ARB, (*fi).WT(1).t(0)); glMultiTexCoordARB(GL_TEXTURE1_ARB, (*fi).WT(1).t(0)); glNormal((*fi).V(1)->N()); glVertex((*fi).V(1)->P()); glMultiTexCoordARB(GL_TEXTURE0_ARB, (*fi).WT(2).t(0)); glMultiTexCoordARB(GL_TEXTURE1_ARB, (*fi).WT(2).t(0)); glNormal((*fi).V(2)->N()); glVertex((*fi).V(2)->P()); } glEnd(); } #endif /*int MemUsed() { int tot=sizeof(GlTrimesh); tot+=sizeof(mesh_type::edge_type)*edge.size(); tot+=sizeof(MESH_TYPE::VertexType *) * EStrip.size(); tot+=sizeof(MESH_TYPE::VertexType *) * TStrip.size(); tot+=sizeof(MESH_TYPE::FaceType *) * TStripF.size(); return tot; }*/ private: template void DrawWire() { //if(!(curr_hints & (HNUseEdgeStrip | HNUseLazyEdgeStrip) ) ) // { glPushAttrib(GL_POLYGON_BIT); glPolygonMode(GL_FRONT_AND_BACK ,GL_LINE); DrawFill(); glPopAttrib(); // } //else // { // if(!HasEdges()) ComputeEdges(); //if(cm==CMPerMesh) glColor(m->C()); //std::vector< MESH_TYPE::VertexType *>::iterator vi; //glBegin(GL_LINE_STRIP); //for(vi=EStrip.begin();vi!=EStrip.end(); ++vi){ // if((*vi)){ // glNormal((*vi)->N()); // glVertex((*vi)->P()); // } // else // { // glEnd(); // glBegin(GL_LINE_STRIP); // } //} //glEnd(); // } } void DrawBBox(ColorMode cm) { if(cm==CMPerMesh) glColor(m->C()); glBoxWire(m->bbox); } };// end class /* Crease Angle Assume che: la mesh abbia la topologia ff la mesh non abbia complex (o se li aveva fossero stati detached) Abbia le normali per faccia normalizzate!! Prende una mesh e duplica tutti gli edge le cui normali nelle facce incidenti formano un angolo maggiore di (espresso in rad). foreach face foreach unvisited vert vi scan the star of triangles around vi duplicating vi each time we encounter a crease angle. the new (and old) vertexes are put in a std::vector that is swapped with the original one at the end. */ // uncomment one of the following line to enable the Verbose Trace for Crease #define VCTRACE (void)0 //#define VCTRACE TRACE template void Crease(MESH_TYPE &m, typename MESH_TYPE::scalar_type angleRad) { assert(m.HasFFTopology()); typename MESH_TYPE::scalar_type cosangle=Cos(angleRad); std::vector > SPL; std::vector newvert; newvert.reserve(m.fn*3); // indica se un il vertice z della faccia e' stato processato enum {VISITED_0= MESH_TYPE::FaceType::USER0, VISITED_1= MESH_TYPE::FaceType::USER0<<1, VISITED_2= MESH_TYPE::FaceType::USER0<<2} ; int vis[3]={VISITED_0,VISITED_1,VISITED_2}; int _t2=clock(); typename MESH_TYPE::FaceIterator fi; for(fi=m.face.begin();fi!=m.face.end();++fi) if(!(*fi).IsD()) (*fi).Supervisor_Flags()&= (~(VISITED_0 | VISITED_1 | VISITED_2)); for(fi=m.face.begin();fi!=m.face.end();++fi) if(!(*fi).IsD()) for(int j=0;j<3;++j) if(!((*fi).Supervisor_Flags() & (vis[j]))) { //VCTRACE("Face %i Spinning around vertex %i\n",fi-m.face.begin(), (*fi).V(j)-m.vert.begin()); //(*fi).Supervisor_Flags() |= vis[j]; typename MESH_TYPE::hedgepos_type he(&*fi,j,(*fi).V(j)); typename MESH_TYPE::hedgepos_type she=he; typename MESH_TYPE::face_base_pointer nextf; GLW::VertToSplit spl; spl.newp=false; spl.edge=-1; //Primo giro per trovare un bordo da cui partire do { he.FlipF(); he.FlipE(); if(he.IsBorder()) break; } while(he!=she); if(he==she) // non c'e'bordi allora si cerca un crease { do { he.FlipF(); he.FlipE(); nextf=he.f->F(he.z); typename MESH_TYPE::scalar_type ps=nextf->N()*he.f->N(); if(psV(he.z)) vz=he.z; if(he.v == he.f->V((he.z+1)%3)) vz=(he.z+1)%3; assert((he.f->Supervisor_Flags() & vis[vz] )==0); } while(he!=she); } he.FlipE(); she=he; newvert.push_back(*(*fi).V(j)); typename MESH_TYPE::vertex_pointer curvert=&newvert.back(); // VCTRACE("Starting from face %i edge %i vert %i \n",he.f-m.face.begin(), he.z, he.v-m.vert.begin()); // Secondo giro in cui si riempie il vettore SPL con tutte le info per fare i nuovi vertici do{ //TRACE(" -- spinning face %i edge %i vert %i\n",he.f-m.face.begin(), he.z, he.v-m.vert.begin()); spl.v=curvert; spl.f=he.f; spl.z=-1; if(he.v == he.f->V(he.z)) spl.z=he.z; if(he.v == he.f->V((he.z+1)%3)) spl.z=(he.z+1)%3; assert(spl.z>=0); //VCTRACE(" -- spinning face vert %i Adding spl face %i vert %i\n", // he.v-m.vert.begin(), spl.f-m.face.begin(), spl.z ); assert((spl.f->Supervisor_Flags() & vis[spl.z] )==0); spl.f->Supervisor_Flags() |= vis[spl.z]; SPL.push_back(spl); spl.newp=false; spl.edge=-1; if(he.IsBorder()) break; nextf=he.f->F(he.z); if(nextf==she.f) break; typename MESH_TYPE::scalar_type ps=nextf->N()*he.f->N(); if(ps >::iterator vsi; for(vsi=SPL.begin();vsi!=SPL.end();++vsi) { (*vsi).f->V((*vsi).z)=(*vsi).v; if((*vsi).newp){ assert((*vsi).edge>=0 && (*vsi).edge<3); if(!(*vsi).f->IsBorder( (*vsi).edge) ) (*vsi).f->Detach((*vsi).edge); } } m.vert.math::Swap(newvert); m.vn=m.vert.size(); } /* Secondo tipo di crease angle. ha bisogno del per wedge normal e delle adiacence per vertice faccia gia fatte; Assume che le normali per faccia siano gia'state fatte (se ci sono) */ /*template void CreaseWN(MESH_TYPE &m, typename MESH_TYPE::scalar_type angle) { if(!(MESH_TYPE::FaceType::OBJ_TYPE & MESH_TYPE::FaceType::OBJ_TYPE_WN) ) { assert(0); // You needs a mesh with faces having per wedge normals return; } typename MESH_TYPE::scalar_type cosangle=Cos(angle); typename MESH_TYPE::FaceIterator fi; // Clear the per wedge normals for(fi=m.face.begin();fi!=m.face.end();++fi) if(!(*fi).IsD()) { (*fi).WN(0)=MESH_TYPE::vectorial_type(0,0,0); (*fi).WN(1)=MESH_TYPE::vectorial_type(0,0,0); (*fi).WN(2)=MESH_TYPE::vectorial_type(0,0,0); } typename MESH_TYPE::FaceType::vectorial_type nn; for(fi=m.face.begin();fi!=m.face.end();++fi) if(!(*fi).IsD()) { nn=(*fi).cN(); for(int i=0;i<3;++i) { VEdgePosB x; for(x.f = (*fi).V(i)->Fp(), x.z = (*fi).V(i)->Zp(); x.f!=0; x.NextF() ) { assert(x.f->V(x.z)==(*fi).V(i)); if(x.f->cN()*nn > cosangle) x.f->WN(x.z)+=nn; } } } }*/ } // end namespace #endif qutemol/vcg/wrap/gl/gl_geometry.h0000444000175000017500000001171410762546274015463 0ustar mbamba#ifndef _VCG_GL_GEOMETRY_ #define _VCG_GL_GEOMETRY_ /* Portion of this file were more or less adapted from * freeglut_geometry.c * * Copyright (c) 1999-2000 Pawel W. Olszta. All Rights Reserved. * that was Written by Pawel W. Olszta, */ #include #include /* * Compute lookup table of cos and sin values forming a cirle * * Notes: * It is the responsibility of the caller to free these tables * The size of the table is (n+1) to form a connected loop * The last entry is exactly the same as the first * The sign of n can be flipped to get the reverse loop */ static void fghCircleTable(double **sint,double **cost,const int n) { int i; /* Table size, the sign of n flips the circle direction */ const int size = abs(n); /* Determine the angle between samples */ const double angle = 2*M_PI/(double)( ( n == 0 ) ? 1 : n ); /* Allocate memory for n samples, plus duplicate of first entry at the end */ *sint = (double *) calloc(sizeof(double), size+1); *cost = (double *) calloc(sizeof(double), size+1); /* Bail out if memory allocation fails, fgError never returns */ if (!(*sint) || !(*cost)) { free(*sint); free(*cost); abort(); //fgError("Failed to allocate memory in fghCircleTable"); } /* Compute cos and sin around the circle */ (*sint)[0] = 0.0; (*cost)[0] = 1.0; for (i=1; i0)?1:0]; r0 = 0.0; r1 = sint2[(stacks>0)?1:0]; glBegin(GL_TRIANGLE_FAN); glNormal3d(0,0,1); glVertex3d(0,0,radius); for (j=slices; j>=0; j--) { glNormal3d(cost1[j]*r1, sint1[j]*r1, z1 ); glVertex3d(cost1[j]*r1*radius, sint1[j]*r1*radius, z1*radius); } glEnd(); /* Cover each stack with a quad strip, except the top and bottom stacks */ for( i=1; i #include #include #include #include "gl_object.h" class FrameBufferSemantic { public: typedef enum { COLOR, DEPTH, STENCIL } FBSType; virtual FBSType Semantic(void) const = 0; virtual bool ValidateFormat(GLenum format) const = 0; static bool ValidateFormat(FBSType type, GLenum format) { switch (type) { case COLOR : return FrameBufferSemantic::ValidateColor(format); case DEPTH : return FrameBufferSemantic::ValidateDepth(format); case STENCIL : return FrameBufferSemantic::ValidateStencil(format); default : return false; } } static bool ValidateColor(GLenum type) { return true; } static bool ValidateDepth(GLenum type) { return true; } static bool ValidateStencil(GLenum type) { return true; } }; class Texture : public GLObject, public Bindable, public FrameBufferSemantic { public: Texture(void) : GLObject(), Bindable(), FrameBufferSemantic() { this->format = GL_NONE; } void Gen(void) { this->Del(); glGenTextures(1, &(this->objectID)); } void Del(void) { if (this->objectID == 0) return; glDeleteTextures(1, &(this->objectID)); this->objectID = 0; } GLenum Format(void) const { return this->format; } virtual GLint Dimensions(void) const = 0; virtual GLsizei Size(const unsigned int i) const = 0; virtual GLenum Target(void) const = 0; protected: GLenum format; void DoBind(void) { glBindTexture(this->Target(), this->objectID); } void DoUnbind(void) { glBindTexture(this->Target(), 0); } }; class ColorTexture : public virtual Texture { public: ColorTexture(void) : Texture() { } FrameBufferSemantic::FBSType Semantic(void) const { return FrameBufferSemantic::COLOR; } bool ValidateFormat(GLenum format) const { return FrameBufferSemantic::ValidateColor(format); } }; class DepthTexture : public virtual Texture { public: DepthTexture(void) : Texture() { } FrameBufferSemantic::FBSType Semantic(void) const { return FrameBufferSemantic::DEPTH; } bool ValidateFormat(GLenum format) const { return FrameBufferSemantic::ValidateDepth(format); } }; class StencilTexture : public virtual Texture { public: StencilTexture(void) : Texture() { } FrameBufferSemantic::FBSType Semantic(void) const { return FrameBufferSemantic::STENCIL; } bool ValidateFormat(GLenum format) const { return FrameBufferSemantic::ValidateStencil(format); } }; class Texture1D : public virtual Texture { public: Texture1D(void) : Texture() { this->dims[0] = 0; this->wraps[0] = GL_CLAMP_TO_EDGE; } GLsizei Width(void) const { return this->dims[0]; } GLint Dimensions(void) const { return 1; } GLsizei Size(const unsigned int i) const { if (i > 0) return 0; return this->dims[0]; } GLenum Target(void) const { return GL_TEXTURE_1D; } bool Set(GLint level, GLint internalFormat, GLsizei width, GLint border, GLenum format, GLenum type, const GLvoid * pixels) { if (!this->ValidateFormat(internalFormat)) return false; this->Bind(); glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexImage1D(GL_TEXTURE_1D, level, internalFormat, width, border, format, type, pixels); this->Unbind(); this->format = internalFormat; this->dims[0] = width; return true; } protected: GLsizei dims[1]; GLenum wraps[1]; }; class Texture2D : public virtual Texture { public: Texture2D(void) : Texture() { this->dims[0] = 0; this->dims[1] = 0; } GLsizei Width(void) const { return this->dims[0]; } GLsizei Height(void) const { return this->dims[1]; } GLint Dimensions(void) const { return 2; } GLsizei Size(const unsigned int i) const { if (i > 1) return 0; return this->dims[i]; } GLenum Target(void) const { return GL_TEXTURE_2D; } bool Set(GLint level, GLint internalFormat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid * pixels) { if (!this->ValidateFormat(internalFormat)) return false; this->Bind(); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, width, height, border, format, type, pixels); this->Unbind(); this->format = internalFormat; this->dims[0] = width; this->dims[1] = height; return true; } protected: GLsizei dims[2]; void DoBind(void) { glBindTexture(GL_TEXTURE_2D, this->objectID); } void DoUnbind(void) { glBindTexture(GL_TEXTURE_2D, 0); } }; class Texture3D : public virtual Texture { public: Texture3D(void) : Texture() { this->dims[0] = 0; this->dims[1] = 0; this->dims[2] = 0; } GLsizei Width(void) const { return this->dims[0]; } GLsizei Height(void) const { return this->dims[1]; } GLsizei Depth(void) const { return this->dims[2]; } GLint Dimensions(void) const { return 3; } GLsizei Size(const unsigned int i) const { if (i > 2) return 0; return this->dims[i]; } GLenum Target(void) const { return GL_TEXTURE_3D; } bool Set(GLint level, GLint internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid * pixels) { if (!this->ValidateFormat(internalFormat)) return false; this->Bind(); glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexImage3D(GL_TEXTURE_3D, 0, internalFormat, width, height, depth, border, format, type, pixels); this->Unbind(); this->format = internalFormat; this->dims[0] = width; this->dims[1] = height; this->dims[2] = depth; return true; } protected: GLsizei dims[3]; void DoBind(void) { glBindTexture(GL_TEXTURE_3D, this->objectID); } void DoUnbind(void) { glBindTexture(GL_TEXTURE_3D, 0); } }; class ColorTexture1D : public virtual ColorTexture, public virtual Texture1D { public: ColorTexture1D(void) : ColorTexture(), Texture1D() { } }; class ColorTexture2D : public virtual ColorTexture, public virtual Texture2D { public: ColorTexture2D(void) : ColorTexture(), Texture2D() { } }; class ColorTexture3D : public virtual ColorTexture, public virtual Texture3D { public: ColorTexture3D(void) : ColorTexture(), Texture3D() { } }; class DepthTexture2D : public virtual DepthTexture, public virtual Texture2D { public: DepthTexture2D(void) : DepthTexture(), Texture2D() { } }; class StencilTexture2D : public virtual StencilTexture, public virtual Texture2D { public: StencilTexture2D(void) : StencilTexture(), Texture2D() { } }; class FrameBuffer; class RenderTarget : public GLObject, public Bindable, public FrameBufferSemantic { friend class FrameBuffer; public: typedef enum { BUFFER, TEXTURE } RTStorageType; RenderTarget(void) : GLObject(), Bindable(), FrameBufferSemantic() { this->frameBuffer = 0; } bool Attach(FrameBuffer * fb); bool Detach(void); FrameBuffer * GetFrameBuffer(void) { return this->frameBuffer; } const FrameBuffer * GetFrameBuffer(void) const { return this->frameBuffer; } virtual GLsizei Width(void) const = 0; virtual GLsizei Height(void) const = 0; virtual GLenum Format(void) const = 0; virtual GLenum Attachment(void) const = 0; virtual bool ValidateAttachment(GLenum attachment) const = 0; virtual RTStorageType StorageType(void) const = 0; protected: FrameBuffer * frameBuffer; virtual bool BindToFB(void) = 0; }; class BufferRenderTarget : public virtual RenderTarget { public: BufferRenderTarget(void) : RenderTarget() { this->width = 0; this->height = 0; this->format = GL_NONE; } void Gen(void) { this->Del(); glGenRenderbuffersEXT(1, &(this->objectID)); } void Del(void) { if (this->objectID == 0) return; glDeleteRenderbuffersEXT(1, &(this->objectID)); this->objectID = 0; } GLsizei Width(void) const { return this->width; } GLsizei Height(void) const { return this->height; } GLenum Format(void) const { return this->format; } RTStorageType StorageType(void) const { return RenderTarget::BUFFER; } bool Set(GLenum format, GLsizei width, GLsizei height) { if (!this->ValidateFormat(format)) return false; this->Bind(); glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, format, width, height); this->Unbind(); this->format = format; this->width = width; this->height = height; return true; } bool BindToFB(void) { if (this->frameBuffer == 0) return false; glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, this->Attachment(), GL_RENDERBUFFER_EXT, this->objectID); return true; } protected: GLenum format; GLsizei width; GLsizei height; void DoBind(void) { glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, this->objectID); } void DoUnbind(void) { glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0); } }; class TextureRenderTarget : public virtual RenderTarget { public: TextureRenderTarget(void) : RenderTarget() { this->tex = 0; this->level = 0; } void Gen(void) { } void Del(void) { } GLsizei Width(void) const { if (this->tex == 0) return 0; return this->tex->Width(); } GLsizei Height(void) const { if (this->tex == 0) return 0; return this->tex->Height(); } GLenum Format(void) const { if (this->tex == 0) return GL_NONE; return this->tex->Format(); } RTStorageType StorageType(void) const { return RenderTarget::TEXTURE; } void SetLevel(GLint level) { if (level < 0) level = 0; this->level = level; } bool Set(Texture2D * tex) { this->Unset(); if (tex == 0) return true; if (this->Semantic() != tex->Semantic()) return false; this->tex = tex; return true; } bool Unset(void) { this->tex = 0; return true; } Texture2D * GetTexture(void) { return (this->tex); } bool BindToFB(void) { if (this->frameBuffer == 0) return false; if (this->tex == 0) return false; glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, this->Attachment(), GL_TEXTURE_2D, this->tex->ObjectID(), this->level); return true; } protected: Texture2D * tex; GLint level; void DoBind(void) { } void DoUnbind(void) { } }; class ColorRenderTarget : public virtual RenderTarget { public: ColorRenderTarget(void) : RenderTarget() { this->attachment = GL_COLOR_ATTACHMENT0_EXT; } FrameBufferSemantic::FBSType Semantic(void) const { return FrameBufferSemantic::COLOR; } bool ValidateFormat(GLenum format) const { return FrameBufferSemantic::ValidateColor(format); } bool ValidateAttachment(GLenum attachment) const { return (((GL_COLOR_ATTACHMENT0_EXT) <= attachment) && (attachment <= (GL_COLOR_ATTACHMENT0_EXT + 3))); } void SetAttachment(GLenum attachment) { if (!this->ValidateAttachment(attachment)) return; this->attachment = attachment; } GLenum Attachment(void) const { return this->attachment; } protected: GLenum attachment; }; class DepthRenderTarget : public virtual RenderTarget { public: DepthRenderTarget(void) : RenderTarget() { } FrameBufferSemantic::FBSType Semantic(void) const { return FrameBufferSemantic::DEPTH; } bool ValidateFormat(GLenum format) const { return FrameBufferSemantic::ValidateDepth(format); } bool ValidateAttachment(GLenum attachment) const { return (attachment == GL_DEPTH_ATTACHMENT_EXT); } GLenum Attachment(void) const { return GL_DEPTH_ATTACHMENT_EXT; } }; class StencilRenderTarget : public virtual RenderTarget { public: StencilRenderTarget(void) : RenderTarget() { } FrameBufferSemantic::FBSType Semantic(void) const { return FrameBufferSemantic::STENCIL; } bool ValidateFormat(GLenum format) const { return FrameBufferSemantic::ValidateStencil(format); } bool ValidateAttachment(GLenum attachment) const { return (attachment == GL_STENCIL_ATTACHMENT_EXT); } GLenum Attachment(void) const { return GL_STENCIL_ATTACHMENT_EXT; } }; class ColorRenderBuffer : public virtual ColorRenderTarget, public virtual BufferRenderTarget { public: ColorRenderBuffer(void) : ColorRenderTarget(), BufferRenderTarget() { } }; class ColorRenderTexture : public virtual ColorRenderTarget, public virtual TextureRenderTarget { public: ColorRenderTexture(void) : ColorRenderTarget(), TextureRenderTarget() { } ColorRenderTexture(Texture2D * tex) : ColorRenderTarget(), TextureRenderTarget() { this->Set(tex); } }; class DepthRenderBuffer : public virtual DepthRenderTarget, public virtual BufferRenderTarget { public: DepthRenderBuffer(void) : DepthRenderTarget(), BufferRenderTarget() { } }; class DepthRenderTexture : public virtual DepthRenderTarget, public virtual TextureRenderTarget { public: DepthRenderTexture(void) : DepthRenderTarget(), TextureRenderTarget() { } DepthRenderTexture(Texture2D * tex) : DepthRenderTarget(), TextureRenderTarget() { this->Set(tex); } }; class StencilRenderBuffer : public virtual StencilRenderTarget, public virtual BufferRenderTarget { public: StencilRenderBuffer(void) : StencilRenderTarget(), BufferRenderTarget() { } }; class StencilRenderTexture : public virtual StencilRenderTarget, public virtual TextureRenderTarget { public: StencilRenderTexture(void) : StencilRenderTarget(), TextureRenderTarget() { } StencilRenderTexture(Texture2D * tex) : StencilRenderTarget(), TextureRenderTarget() { this->Set(tex); } }; class FrameBuffer : public GLObject, public Bindable { friend class RenderTarget; public: FrameBuffer(void) : GLObject(), Bindable() { } void Gen(void) { this->Del(); glGenFramebuffersEXT(1, &(this->objectID)); } void Del(void) { if (this->objectID == 0) return; glDeleteFramebuffersEXT(1, &(this->objectID)); this->objectID = 0; } bool DetachAll(void) { return false; } bool IsValid(void) const { const GLenum s = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT); //return (s == GL_FRAMEBUFFER_COMPLETE_EXT); switch (s) { case GL_FRAMEBUFFER_COMPLETE_EXT: printf("ok\n"); break; case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT: printf("i a\n"); break; case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT: printf("i m a\n"); break; case GL_FRAMEBUFFER_INCOMPLETE_DUPLICATE_ATTACHMENT_EXT: printf("i d a\n"); break; case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT: printf("i d\n"); break; case GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT: printf("i f\n"); break; case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT: printf("i d b\n"); break; case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT: printf("i r b\n"); break; case GL_FRAMEBUFFER_UNSUPPORTED_EXT: printf("u\n"); break; default: printf("def\n"); break; } return (s == GL_FRAMEBUFFER_COMPLETE_EXT); } protected: typedef std::map RTMap; typedef RTMap::iterator RTMap_i; typedef RTMap::const_iterator RTMap_ci; RTMap renderTargets; void DoBind(void) { glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, this->objectID); std::vector colorDrawBuffers; colorDrawBuffers.reserve(this->renderTargets.size()); for (RTMap_i rt=this->renderTargets.begin(); rt!=this->renderTargets.end(); ++rt) { RenderTarget * prt = (*rt).second; if (prt->Semantic() == FrameBufferSemantic::COLOR) { colorDrawBuffers.push_back(prt->Attachment()); } prt->BindToFB(); } const GLsizei sz = (GLsizei)(colorDrawBuffers.size()); if (sz > 0) { glDrawBuffers(sz, &(colorDrawBuffers[0])); } } void DoUnbind(void) { glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); } bool AddRT(RenderTarget * rt) { if (rt == 0) return false; RTMap_i it = this->renderTargets.find(rt->Attachment()); if (it == this->renderTargets.end()) { this->renderTargets.insert(std::make_pair(rt->Attachment(), rt)); return true; } return false; } bool RemoveRT(RenderTarget * rt) { if (rt == 0) return false; RTMap_i it = this->renderTargets.find(rt->Attachment()); if ((*it).second == rt) { this->renderTargets.erase(it); return true; } return false; } }; bool RenderTarget::Attach(FrameBuffer * fb) { this->Detach(); if (fb == 0) return true; if (fb->AddRT(this)) { this->frameBuffer = fb; return true; } return false; } bool RenderTarget::Detach(void) { if (this->frameBuffer == 0) return false; this->frameBuffer->RemoveRT(this); this->frameBuffer = 0; return true; } #endif // __FBO_H__ qutemol/vcg/wrap/gl/pos.h0000444000175000017500000000661110620143622013726 0ustar mbamba/**************************************************************************** * VCGLib o o * * Visual and Computer Graphics Library o o * * _ O _ * * Copyright(C) 2004 \/)\/ * * Visual Computing Lab /\/| * * ISTI - Italian National Research Council | * * \ * * All rights reserved. * * * * 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. * * * * 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 (http://www.gnu.org/licenses/gpl.txt) * * for more details. * * * ****************************************************************************/ /**************************************************************************** History $Log: pos.h,v $ Revision 1.2 2007/05/08 18:55:14 ganovelli adde vf iterator Revision 1.1 2006/12/10 19:59:28 ganovelli first draft of the class the draw a Pos ****************************************************************************/ #ifndef VCG_GL_POS_H #define VCG_GL_POS_H // Please note that this file assume that you have already included your // gl-extension wrapping utility, and that therefore all the extension symbol are already defined. #include #include namespace vcg { template struct GlPos{ typedef typename PosType::ScalarType S; static void Draw(PosType & p){ Point3 bc = Barycenter(*(p.f)); Point3 mid = (p.f->P(p.z)+p.f->P(((p.z+1)%3)))*0.5f; Point3 up = ((bc- p.v->P()) ^ (mid- p.f->P(p.z) )).Normalize(); Point3 ax = ( up ^ (mid-p.f->P(p.z)) ) .Normalize(); S proj = (bc-mid)*(ax)*0.5; Point3 bc1 = mid+ (ax)*proj; glBegin(GL_TRIANGLES); glVertex(p.v->P()); if( p.v == p.f->V(p.z)) { glVertex(mid); glVertex(bc1);} else {glVertex(bc1); glVertex(mid);} glEnd(); } }; template struct GlVfIterator{ typedef typename VfIteType::ScalarType S; static void Draw(VfIteType & v){ Point3 p = v.F()->P(v.I());// anchor Point3 c[3]; for(int i = 0; i < 3;++i) { c[i] = v.F()->P(i)*0.9 + v.F()->P1(i)*0.05 + v.F()->P2(i)*0.05; if(v.F()->VFp(i) != NULL) { glBegin(GL_LINES); glVertex(c[i]); glVertex( vcg::Barycenter(*(v.F()->VFp(i)))); glEnd(); } } } }; }//namespace #endif qutemol/vcg/wrap/gl/gl_surface.h0000444000175000017500000003337310705136453015254 0ustar mbamba/**************************************************************************** * VCGLib o o * * Visual and Computer Graphics Library o o * * _ O _ * * Copyright(C) 2004 \/)\/ * * Visual Computing Lab /\/| * * ISTI - Italian National Research Council | * * \ * * All rights reserved. * * * * 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. * * * * 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 (http://www.gnu.org/licenses/gpl.txt) * * for more details. * * * ****************************************************************************/ /**************************************************************************** History $Log: gl_surface.h,v $ Revision 1.2 2007/10/16 13:31:23 m_di_benedetto Added a GLenum cast to suppress warning message. Revision 1.1 2007/07/26 16:22:47 m_di_benedetto First Commit. ****************************************************************************/ #ifndef VCGLIB_GL_SURFACE_H #define VCGLIB_GL_SURFACE_H #include #include namespace vcg { /**************************************************************************** The gl_surface class simplify the render-to-texture OpenGL functionality. It provides a framebuffer composed of single or multiple color buffers and a depth buffer; color-only and depth-only framebuffers can also be created. Sample usage: **************************************************************** // *** declaration gl_surface my_srf; *********************** // *** initialization: single color render target, with depth buffer { std::vector color_formats; color_formats.push_back(GL_RGBA8); my_srf.set(width, height, color_formats, GL_DEPTH_COMPONENT); } *********************** *********************** // *** initialization: two color render targets, without depth buffer // NOTE: the maximum number of color targets is implementation dependent. // NOTE: DX10 class hardware allows different formats for each color target. { std::vector color_formats; color_formats.push_back(GL_RGBA8); color_formats.push_back(GL_RGBA8); my_srf.set(width, height, color_formats, GL_NONE); } *********************** *********************** // *** usage: render-to-targets { my_srf.begin_write(); application_draw_code(); my_srf.end_write(); } *********************** *********************** // *** usage: using rendered textures { // 2 buffers // bind the second glActiveTexture(GL_TEXTURE1); my_srf.begin_read_color(1); // actually does a glBindTexture(); // bind the first glActiveTexture(GL_TEXTURE0); my_srf.begin_read_color(0); application_draw_code(); // unbind the second glActiveTexture(GL_TEXTURE1); my_srf.end_read_color(1); // unbind first glActiveTexture(GL_TEXTURE0); my_srf.end_read_color(0); } *********************** // *** usage: use depth map { my_srf.begin_read_depth(); // use depth map here application_draw_code(); my_srf.end_read_depth(); } *********************** // *** usage: cleanup { my_srf.clear(); // clear() is also safely called in the destructor. } *********************** Other commodity methods for getting/setting pixels are also provided. ****************************************************************************/ class gl_surface { public: typedef gl_surface this_type; gl_surface(void) : width(0), height(0), depth_tex(0), fb(0) { ; } ~gl_surface(void) { this->clear(); } bool set(int width, int height, const std::vector & color_formats, GLenum depth_format) { this->clear(); this->width = width; this->height = height; this->color_formats = color_formats; this->color_texs.resize(color_formats.size()); for (size_t i=0; icolor_texs.size(); ++i) { glGenTextures (1, &(this->color_texs[i])); glBindTexture (GL_TEXTURE_2D, this->color_texs[i]); glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexImage2D (GL_TEXTURE_2D, 0, this->color_formats[i], this->width, this->height, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, 0); } this->depth_format = depth_format; if (this->depth_format != GL_NONE) { glGenTextures (1, &(this->depth_tex)); glBindTexture (GL_TEXTURE_2D, this->depth_tex); glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri (GL_TEXTURE_2D, GL_DEPTH_TEXTURE_MODE_ARB, GL_LUMINANCE); glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE_ARB, GL_COMPARE_R_TO_TEXTURE_ARB); glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC_ARB, GL_LEQUAL); glTexImage2D (GL_TEXTURE_2D, 0, this->depth_format, this->width, this->height, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, 0); } glGenFramebuffersEXT(1, &(this->fb)); glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, this->fb); std::vector sites(this->color_texs.size()); for (size_t i=0; icolor_texs.size(); ++i) { sites[i] = GL_COLOR_ATTACHMENT0_EXT + ((GLenum)i); glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, sites[i], GL_TEXTURE_2D, this->color_texs[i], 0); } if (this->depth_format != GL_NONE) { glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_2D, this->depth_tex, 0); } if (!sites.empty()) { glDrawBuffers((GLsizei)(sites.size()), &(sites[0])); } const GLenum s = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT); const bool res = (s == GL_FRAMEBUFFER_COMPLETE_EXT); glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); if (!res) { glDeleteFramebuffersEXT(1, &(this->fb)); this->fb = 0; for (size_t i=0; icolor_texs.size(); ++i) { glDeleteTextures(1, &(this->color_texs[i])); } this->color_texs.clear(); this->color_formats.clear(); if (this->depth_tex != 0) { glDeleteTextures(1, &(this->depth_tex)); this->depth_tex = 0; } this->width = 0; this->height = 0; return false; } return true; } bool set_simple(int width, int height) { std::vector c_formats; c_formats.push_back(GL_RGBA8); return this->set(width, height, c_formats, GL_DEPTH_COMPONENT); } bool set_color_only(int width, int height, GLenum color_format) { std::vector c_formats; c_formats.push_back(color_format); return this->set(width, height, c_formats, GL_NONE); } bool set_color_only(int width, int height, const std::vector & color_formats) { return this->set(width, height, color_formats, GL_NONE); } bool set_depth_only(int width, int height, GLenum depth_format) { std::vector c_formats; return this->set(width, height, c_formats, depth_format); } bool clear(void) { if (!this->is_valid()) return false; glDeleteFramebuffersEXT(1, &(this->fb)); this->fb = 0; for (size_t i=0; icolor_texs.size(); ++i) { glDeleteTextures(1, &(this->color_texs[i])); } this->color_texs.clear(); this->color_formats.clear(); if (this->depth_tex != 0) { glDeleteTextures(1, &(this->depth_tex)); this->depth_tex = 0; } this->width = 0; this->height = 0; return true; } bool is_valid(void) const { return (this->fb != 0); } int get_width(void) const { return this->width; } int get_height(void) const { return this->height; } int color_attachments_count(void) const { return ((int)(this->color_texs.size())); } GLenum get_color_attachment_format(int attachment) const { if (!this->is_valid()) return GL_NONE; if ((attachment < 0) || (attachment >= this->color_attachments_count())) return GL_NONE; return this->color_formats[attachment]; } bool has_depth_attachment(void) const { return (this->depth_tex != 0); } GLenum get_depth_attachment_format(void) const { if (!this->is_valid()) return GL_NONE; if (!this->has_depth_attachment()) return GL_NONE; return this->depth_format; } bool set_color_pixels(int attachment, GLenum format, GLenum type, const void * pixels) { if (!this->begin_read_color(attachment)) return false; glTexImage2D(GL_TEXTURE_2D, 0, this->color_formats[attachment], this->width, this->height, 0, format, type, pixels); this->end_read_color(attachment); return true; } bool get_color_pixels(int attachment, GLenum format, GLenum type, void * pixels) { if (!this->begin_read_color(attachment)) return false; glGetTexImage(GL_TEXTURE_2D, 0, format, type, pixels); this->end_read_color(attachment); return true; } bool set_depth_pixels(GLenum format, GLenum type, const void * pixels) { if (!this->is_valid()) return false; if (!this->has_depth_attachment()) return false; glTexImage2D(GL_TEXTURE_2D, 0, this->depth_format, this->width, this->height, 0, format, type, pixels); return true; } bool get_depth_pixels(GLenum format, GLenum type, void * pixels) { if (!this->begin_read_depth()) return false; glGetTexImage(GL_TEXTURE_2D, 0, format, type, pixels); this->end_read_depth(); return true; } bool begin_read_color(int attachment) { if (!this->is_valid()) return false; if ((attachment < 0) || (attachment >= this->color_attachments_count())) return false; glBindTexture(GL_TEXTURE_2D, this->color_texs[attachment]); return true; } bool end_read_color(int attachment) { if (!this->is_valid()) return false; if ((attachment < 0) || (attachment >= this->color_attachments_count())) return false; glBindTexture(GL_TEXTURE_2D, 0); return true; } bool begin_read_depth(void) { if (!this->is_valid()) return false; if (!this->has_depth_attachment()) return false; glBindTexture(GL_TEXTURE_2D, this->depth_tex); return true; } bool end_read_depth(void) { if (!this->is_valid()) return false; if (!this->has_depth_attachment()) return false; glBindTexture(GL_TEXTURE_2D, 0); return true; } bool begin_write(void) { if (!this->is_valid()) return false; glPushAttrib(GL_VIEWPORT_BIT); glViewport(0, 0, this->width, this->height); glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, this->fb); return true; } bool end_write(void) { if (!this->is_valid()) return false; glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); glPopAttrib(); return true; } bool draw_color_attachment(int x, int y, int width, int height, int attachment) { if (!this->is_valid()) return false; if ((attachment < 0) || (attachment >= this->color_attachments_count())) return false; glPushAttrib(GL_ALL_ATTRIB_BITS); glViewport(x, y, width, height); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); glMatrixMode(GL_PROJECTION); glPushMatrix(); glLoadIdentity(); glMatrixMode(GL_MODELVIEW); glPushMatrix(); glLoadIdentity(); this->begin_read_color(attachment); glBegin(GL_QUADS); glTexCoord2f(0.0f, 0.0f); glVertex2f(-1.0f, -1.0f); glTexCoord2f(1.0f, 0.0f); glVertex2f( 1.0f, -1.0f); glTexCoord2f(1.0f, 1.0f); glVertex2f( 1.0f, 1.0f); glTexCoord2f(0.0f, 1.0f); glVertex2f(-1.0f, 1.0f); glEnd(); this->end_read_color(attachment); glMatrixMode(GL_PROJECTION); glPopMatrix(); glMatrixMode(GL_MODELVIEW); glPopMatrix(); glPopAttrib(); } bool draw_depth_attachment(int x, int y, int width, int height) { if (!this->is_valid()) return false; if (!this->has_depth_attachment()) return false; glPushAttrib(GL_ALL_ATTRIB_BITS); glViewport(x, y, width, height); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); glMatrixMode(GL_PROJECTION); glPushMatrix(); glLoadIdentity(); glMatrixMode(GL_MODELVIEW); glPushMatrix(); glLoadIdentity(); this->begin_read_depth(); glBegin(GL_QUADS); glTexCoord2f(0.0f, 0.0f); glVertex2f(-1.0f, -1.0f); glTexCoord2f(1.0f, 0.0f); glVertex2f( 1.0f, -1.0f); glTexCoord2f(1.0f, 1.0f); glVertex2f( 1.0f, 1.0f); glTexCoord2f(0.0f, 1.0f); glVertex2f(-1.0f, 1.0f); glEnd(); this->end_read_depth(); glMatrixMode(GL_PROJECTION); glPopMatrix(); glMatrixMode(GL_MODELVIEW); glPopMatrix(); glPopAttrib(); } protected: int width; int height; std::vector color_formats; std::vector color_texs; GLenum depth_format; GLuint depth_tex; GLuint fb; }; } // end namespace vcg #endif // VCGLIB_GL_SURFACE_H qutemol/vcg/wrap/gl/shot.h0000444000175000017500000007707210627513754014131 0ustar mbamba/**************************************************************************** * VCGLib o o * * Visual and Computer Graphics Library o o * * _ O _ * * Copyright(C) 2004 \/)\/ * * Visual Computing Lab /\/| * * ISTI - Italian National Research Council | * * \ * * All rights reserved. * * * * 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. * * * * 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 (http://www.gnu.org/licenses/gpl.txt) * * for more details. * * * ****************************************************************************/ /**************************************************************************** History $Log: shot.h,v $ Revision 1.13 2007/05/31 09:39:56 cignoni Small gcc compiling issues Revision 1.12 2006/12/18 16:02:57 matteodelle minor eroor correction on variable names Revision 1.11 2006/12/18 15:26:24 callieri added a function to approximate a far plane value given a shot and the mesh bbox Revision 1.10 2006/12/18 14:28:07 matteodelle *** empty log message *** Revision 1.9 2006/12/18 09:46:39 callieri camera+shot revamp: changed field names to something with more sense, cleaning of various functions, correction of minor bugs/incongruences, removal of the infamous reference in shot. Revision 1.8 2006/01/11 16:06:25 matteodelle *** empty log message *** Revision 1.8 2005/01/11 17:06:30 dellepiane FromTrackball() coorected (similarity->Extrinsics Revision 1.7 2005/11/25 10:33:33 spinelli shot.camera -> shot.Intrinsics shot.similarity.Matrix() -> shot.Extrinsics.Matrix() Revision 1.6 2005/02/22 11:15:01 ganovelli added vcg namespace Revision 1.5 2005/02/11 11:43:09 tommyfranken FromTrackball() corrected Revision 1.4 2004/12/15 18:45:06 tommyfranken *** empty log message *** Revision 1.3 2004/11/03 09:41:57 ganovelli added FromTrackball and fixed include names (Poiint to point) Revision 1.2 2004/10/05 19:04:45 ganovelli changed from classes to functions Revision 1.1 2004/09/15 22:59:13 ganovelli creation Revision 1.2 2004/09/06 21:41:30 ganovelli *** empty log message *** Revision 1.1 2004/09/03 13:01:51 ganovelli creation ****************************************************************************/ #ifndef __VCGLIB_GLSHOT #define __VCGLIB_GLSHOT // include vcg stuff #include #include #include #include // include wrap stuff #include #include #include template struct GlShot { typedef typename ShotType::ScalarType ScalarType; typedef GlCamera GlCameraType; /// returns the OpenGL 4x4 MODELVIEW matrix that describes the shot position and orientation (extrinsics) static void MatrixGL(ShotType & shot,vcg::Matrix44 & m) { m = shot.Extrinsics.Matrix(); } /// set the OpenGL MODELVIEW matrix to match the shot (extrinsics) static void TransformGL(vcg::Shot & shot) { vcg::Matrix44 m; MatrixGL(shot,m); glMultMatrix(m); } /// set the OpenGL PROJECTION and MODELVIEW matrix to match camera+shot. requires near and far plane static void SetView(vcg::Shot & shot, ScalarType nearDist, ScalarType farDist) { assert(glGetError() == 0); glMatrixMode(GL_PROJECTION); glPushMatrix(); glLoadIdentity(); assert(glGetError() == 0); GlCameraType::TransformGL(shot.Intrinsics, nearDist, farDist); // apply camera/projection transformation assert(glGetError() == 0); glMatrixMode(GL_MODELVIEW); glPushMatrix(); glLoadIdentity(); GlShot::TransformGL(shot); // apply similarity/modelview transformation assert(glGetError() == 0); } /// restore the previous OpenGL modelview and projection state. to be called AFTER a SetView static void UnsetView() { glPushAttrib(GL_TRANSFORM_BIT); glMatrixMode(GL_MODELVIEW); glPopMatrix(); glMatrixMode(GL_PROJECTION); glPopMatrix(); glPopAttrib(); } /// given a shot and the mesh bounding box, returns an approximate far plane distance /// distance is always approximated by excess static ScalarType GetFarPlane(vcg::Shot & shot, vcg::Box3 bbox) { ScalarType farDist; vcg::Point3 farcorner; vcg::Point3 campos = shot.Extrinsics.tra; if (abs(campos.X() - bbox.max.X()) > abs(campos.X() - bbox.min.X())) farcorner.X() = bbox.max.X(); else farcorner.X() = bbox.min.X(); if (abs(campos.Y() - bbox.max.Y()) > abs(campos.Y() - bbox.min.Y())) farcorner.Y() = bbox.max.Y(); else farcorner.Y() = bbox.min.Y(); if (abs(campos.Z() - bbox.max.Z()) > abs(campos.Z() - bbox.min.Z())) farcorner.Z() = bbox.max.Z(); else farcorner.Z() = bbox.min.Z(); farDist = (campos - farcorner).Norm(); return farDist; } static void SetSubView(vcg::Shot & shot, vcg::Point2 p1, vcg::Point2 p2) { glMatrixMode(GL_PROJECTION); glPushMatrix(); glLoadIdentity(); assert(glGetError() == 0); GlCameraType::SetSubView(shot.Intrinsics,p1,0,1000,p2); assert(glGetError() == 0); glMatrixMode(GL_MODELVIEW); glPushMatrix(); glLoadIdentity(); GlShot::TransformGL(shot); // apply similarity/modelview transformation assert(glGetError() == 0); } /********************************** DEFINE SHOT FROM TRACKBALL Adds to a given shot the trackball transformations. After this operation the trackball should be resetted, to avoid multiple apply of the same transformation. ***********************************/ static void FromTrackball(const vcg::Trackball & tr, vcg::Shot & sShot, vcg::Shot & shot ) { vcg::Point3 cen; cen.Import(tr.center); vcg::Point3 tra; tra.Import(tr.track.tra); vcg::Matrix44 trM; trM.FromMatrix(tr.track.Matrix()); vcg::Point3 vp = Inverse(trM)*(sShot.GetViewPoint()-cen) +cen +tra; shot.SetViewPoint(vp); shot.Extrinsics.rot = sShot.Extrinsics.rot*trM; shot.Extrinsics.sca = sShot.Extrinsics.sca*(ScalarType)tr.track.sca; } }; #endif //private: // // static inline S SQRT( S x) { return sqrt(fabs(x)); } // static inline S CBRT ( S x ) // { // if (x == 0) return 0; // else if (x > 0) return pow (x, 1.0 / 3.0); // else return -pow (-x, 1.0 / 3.0); // } // static inline void SINCOS( S x, S & s, S & c) // { // s=sin(x); // c=cos(x); // } // static inline void SINCOSd( double x, double & s, double & c) // { // s=sin(x); // c=cos(x); // } // static inline S CUB( S x ) { return x*x*x; } // static inline S SQR( S x ) { return x*x; } // //public: // void undistorted_to_distorted_sensor_coord (S Xu, S Yu, S & Xd, S & Yd) const // { // const S SQRT3 = S(1.732050807568877293527446341505872366943); // S Ru,Rd,lambda,c,d,Q,R,D,S,T,sinT,cosT; // // if((Xu==0 && Yu==0) || k[0] == 0) // { // Xd = Xu; // Yd = Yu; // return; // } // // Ru = hypot (Xu, Yu); /* SQRT(Xu*Xu+Yu*Yu) */ // c = 1 / k[0]; // d = -c * Ru; // // Q = c / 3; // R = -d / 2; // D = CUB (Q) + SQR (R); // // if (D >= 0) /* one real root */ // { // D = SQRT (D); // S = CBRT (R + D); // T = CBRT (R - D); // Rd = S + T; // // if (Rd < 0) // Rd = SQRT (-1 / (3 * k[0])); // } // else /* three real roots */ // { // D = SQRT (-D); // S = CBRT (hypot (R, D)); // T = atan2 (D, R) / 3; // SINCOS (T, sinT, cosT); // // /* the larger positive root is 2*S*cos(T) */ // /* the smaller positive root is -S*cos(T) + SQRT(3)*S*sin(T) */ // /* the negative root is -S*cos(T) - SQRT(3)*S*sin(T) */ // Rd = -S * cosT + SQRT3 * S * sinT; /* use the smaller positive root */ // } // // lambda = Rd / Ru; // // Xd = Xu * lambda; // Yd = Yu * lambda; // } // // //void correction(double k, float i, float j, float &disi, float &disj) //{ // // (i,j) punto nell'immagine distorta // // (disi,disj) punto nell'immagine corretta (undistorted) // float hyp; // float I,J,ni,nj; // float ratio = 1; // // ni = i-viewport[0]/2; // nj = j-viewport[1]/2; // hyp = ni*ni + nj*nj; // // I = ni * (1+ k * hyp); // J = nj * (1+ k * hyp); // // disi = (I*ratio+viewport[0]/2); // disj = (J*ratio+viewport[1]/2); //} // // // //void distorsion( float k ,float i, float j,double & disi, double &disj) //{ // // (i,j) punto nell'immagine corretta (undistorted) // // (disi,disj) punto nell'immagine distorta // float hyp; // int _I,_J; // float I,J,ni,nj; // I = i-viewport[0]/2; // J = j-viewport[1]/2; // hyp = sqrt(I*I + J*J); // if((k==0.0) || (hyp <0.001)) // { // disi = i; // disj = j; // } // else // { // undistorted_to_distorted_sensor_coord (I, J, disi, disj); // disi += viewport[0]/2; // disj += viewport[1]/2; // // //// hyp = (viewport[0]*viewport[0] + viewport[1]*viewport[1])/4; //// ni = SX/2 + SX/2 * cam.k[0] * hyp; ///// nj = SY/2 + SY/2 * cam.k[0] * hyp; //// float ratio = sqrt(hyp/(ni*ni + nj*nj)); // float ratio=1; // // // // //----------- Maple // // float t0,t1,t2,sol; // // //t0 = 1/k*pow((108.0*hyp+12.0*sqrt(3.0)*sqrt((4.0+27.0*hyp*hyp*k)/k))*k*k,0.3333333333333333)/6.0-2.0/pow((108.0*hyp+12.0*sqrt(3.0)*sqrt((4.0+27.0*hyp*hyp*k)/k))*k*k,0.3333333333333333); // // // //t1 = -1/k*pow((108.0*hyp+12.0*sqrt(3.0)*sqrt((4.0+27.0*hyp*hyp*k)/k))*k*k,0.3333333333333333)/12.0+1/pow((108.0*hyp+12.0*sqrt(3.0)*sqrt((4.0+27.0*hyp* // //hyp*k)/k))*k*k,0.3333333333333333)+sqrt(-1.0)*sqrt(3.0)*(1/k*pow((108.0*hyp+ // //12.0*sqrt(3.0)*sqrt((4.0+27.0*hyp*hyp*k)/k))*k*k,0.3333333333333333)/6.0+2.0/ // //pow((108.0*hyp+12.0*sqrt(3.0)*sqrt((4.0+27.0*hyp*hyp*k)/k))*k*k, // //0.3333333333333333))/2.0; // // //t2 = -1/k*pow((108.0*hyp+12.0*sqrt(3.0)*sqrt((4.0+27.0*hyp*hyp*k)/k))*k*k,0.3333333333333333)/12.0+1/pow((108.0*hyp+12.0*sqrt(3.0)*sqrt((4.0+27.0*hyp* // //hyp*k)/k))*k*k,0.3333333333333333)-sqrt(-1.0)*sqrt(3.0)*(1/k*pow((108.0*hyp+ // //12.0*sqrt(3.0)*sqrt((4.0+27.0*hyp*hyp*k)/k))*k*k,0.3333333333333333)/6.0+2.0/ // //pow((108.0*hyp+12.0*sqrt(3.0)*sqrt((4.0+27.0*hyp*hyp*k)/k))*k*k, // //0.3333333333333333))/2.0; // // //sol = (t0>t1)?t0:t1; // //sol = (sol (i/(double)(si-1),j/(double)(sj-1)); // { // double disi,disj; // distorsion( k[0] ,(i/(double)(si-1))*viewport[0], (j/(double)(sj-1))*viewport[1],disi,disj); // gridMap[i][j] = Point2 (disi/viewport[0],disj/viewport[1]); // } // } // // inline Intrinsics // { // k[0]=k[1]=k[2]=k[3]=0.0; // valid = false; // ortho = false; // ResizeGridMap(100,100);// da spostare altrove // } // // inline bool IsValid() // { // return valid; // } // // inline bool IsOrtho() const // { // return ortho; // } // // inline void SetInvalid() // { // valid = false; // } // // inline void SetOrtho(bool isOrtho=true) // { // ortho = isOrtho; // } // // // Genera una camera standard // void Standard() // { // valid = true; // ortho = false; // view_p = vectorial(0,0,0); // x_axis = vectorial(1,0,0); // y_axis = vectorial(0,1,0); // z_axis = vectorial(0,0,1); // f = 25.75; // s = Point2(0.0074,0.0074); // c = Point2(320,240); // viewport[0] = 640; // viewport[1] = 480; // k[0] = 0; // k[1] = 0; // k[2] = 0; // k[3] = 0; // } // // // Trasla la camera (world coordinate) // inline void Translate( const vectorial & t ) // { // view_p += t; // } // // // Trasla la camera (camera coordinate) // inline void Move( const vectorial & t ) // { // view_p+= x_axis * t[0]+y_axis * t[1] + z_axis * t[2]; // } // // // scala la camera // inline void Scale(const scalar & sc){ // view_p *=sc; // s[0]*=sc; // s[1]*=sc; // f*=sc; // //printf("sc\n"); // } // // // // // NOTA funziona solo se l'ultima colonna di m e' 0,0,0,1 // void Apply( const Matrix44 & m ) // { // // Passo 1: calcolo pseudo inversa di m // S s11,s12,s13; // S s21,s22,s23; // S s31,s32,s33; // S s41,s42,s43; // // { // S t4 = m[0][0]*m[1][1]; // S t6 = m[0][0]*m[2][1]; // S t8 = m[1][0]*m[0][1]; // S t10 = m[1][0]*m[2][1]; // S t12 = m[2][0]*m[0][1]; // S t14 = m[2][0]*m[1][1]; // S t17 = 1/(t4*m[2][2]-t6*m[1][2]-t8*m[2][2]+t10*m[0][2]+t12*m[1][2]-t14*m[0][2]); // S t27 = m[1][0]*m[2][2]; // S t28 = m[2][0]*m[1][2]; // S t31 = m[0][0]*m[2][2]; // S t32 = m[2][0]*m[0][2]; // S t35 = m[0][0]*m[1][2]; // S t36 = m[1][0]*m[0][2]; // S t49 = m[3][0]*m[1][1]; // S t51 = m[3][0]*m[2][1]; // S t59 = m[3][0]*m[0][1]; // s11 = -(-m[1][1]*m[2][2]+m[2][1]*m[1][2])*t17; // s12 = -( m[0][1]*m[2][2]-m[2][1]*m[0][2])*t17; // s13 = ( m[0][1]*m[1][2]-m[1][1]*m[0][2])*t17; // s21 = (-t27+t28)*t17; // s22 = -(-t31+t32)*t17; // s23 = -( t35-t36)*t17; // s31 = -(-t10+t14)*t17; // s32 = (-t6 +t12)*t17; // s33 = ( t4 -t8 )*t17; // s41 = -(t10*m[3][2]-t27*m[3][1]-t14*m[3][2]+t28*m[3][1]+t49*m[2][2]-t51*m[1][2])*t17; // s42 = -(-t6*m[3][2]+t31*m[3][1]+t12*m[3][2]-t32*m[3][1]-t59*m[2][2]+t51*m[0][2])*t17; // s43 = (-t4*m[3][2]+t35*m[3][1]+t8 *m[3][2]-t36*m[3][1]-t59*m[1][2]+t49*m[0][2])*t17; // 1.0; // } // // //Matrix44 t2 = tt*m; // //print(t2); // // Fase 2: Calcolo nuovo punto di vista // { // S t1 = view_p[2]*s31; // S t3 = view_p[2]*s21; // S t5 = s43*s21; // S t7 = s43*s31; // S t9 = view_p[1]*s31; // S t11 = view_p[1]*s21; // S t13 = s42*s31; // S t15 = s42*s21; // S t17 = view_p[0]*s32; // S t19 = view_p[0]*s22; // S t21 = s41*s32; // S t23 = s41*s22; // S t25 = -t1*s22+t3*s32-t5*s32+t7*s22+t9*s23-t11*s33-t13*s23+t15*s33-t17*s23+t19*s33+t21*s23-t23*s33; // S t39 = 1/(s11*s22*s33-s11*s32*s23-s21*s12*s33+s21*s32*s13+s31*s12*s23-s31*s22*s13); // S t41 = view_p[0]*s12; // S t45 = s41*s12; // S t47 = view_p[2]*s11; // S t50 = s43*s11; // S t53 = view_p[1]*s11; // S t56 = s42*s11; // S t59 = t41*s33-t17*s13+t21*s13-t45*s33+t47*s32-t1*s12-t50*s32+t7*s12-t53*s33+t9*s13+t56*s33-t13*s13; // S t73 = t15*s13-t56*s23+t19*s13-t41*s23-t23*s13+t45*s23-t11*s13+t53*s23+t3*s12-t47*s22-t5*s12+t50*s22; // // view_p[0] = t25*t39; // view_p[1] = -t59*t39; // view_p[2] = -t73*t39; // } // // // Fase 3: Calcol nuovo sistema di riferimento // { // S A00 = s11*x_axis[0]+s12*x_axis[1]+s13*x_axis[2]; // S A01 = s11*y_axis[0]+s12*y_axis[1]+s13*y_axis[2]; // S A02 = s11*z_axis[0]+s12*z_axis[1]+s13*z_axis[2]; // // S A03 = 0.0; // S A10 = s21*x_axis[0]+s22*x_axis[1]+s23*x_axis[2]; // S A11 = s21*y_axis[0]+s22*y_axis[1]+s23*y_axis[2]; // S A12 = s21*z_axis[0]+s22*z_axis[1]+s23*z_axis[2]; // // S A13 = 0.0; // S A20 = s31*x_axis[0]+s32*x_axis[1]+s33*x_axis[2]; // S A21 = s31*y_axis[0]+s32*y_axis[1]+s33*y_axis[2]; // S A22 = s31*z_axis[0]+s32*z_axis[1]+s33*z_axis[2]; // // x_axis[0] = A00; x_axis[1] = A10; x_axis[2] = A20; // y_axis[0] = A01; y_axis[1] = A11; y_axis[2] = A21; // z_axis[0] = A02; z_axis[1] = A12; z_axis[2] = A22; // // S A1[2][3] = 0.0; // // S A1[3][0] = 0.0; // // S A1[3][1] = 0.0; // // S A1[3][2] = 0.0; // // S A1[3][3] = 1.0; // } // } // // /* // // Applica una trasformazione // void Apply( const Matrix44 & m ) // { // Point3 tx = view_p+x_axis; // Point3 ty = view_p+y_axis; // Point3 tz = view_p+z_axis; // // view_p = m.Apply(view_p); // // x_axis = m.Apply(tx) - view_p; // y_axis = m.Apply(ty) - view_p; // z_axis = m.Apply(tz) - view_p; // } // // // Applica una trasformazione ma bene! // void Stable_Apply( const Matrix44 & m ) // { // Point3 tx = view_p+x_axis; // Point3 ty = view_p+y_axis; // Point3 tz = view_p+z_axis; // // view_p = m.Stable_Apply(view_p); // // x_axis = m.Stable_Apply(tx) - view_p; // y_axis = m.Stable_Apply(ty) - view_p; // z_axis = m.Stable_Apply(tz) - view_p; // } // // */ // // void Project( const vectorial & p, Point2 & q ) const // { // vectorial dp = p - view_p; // S dx = dp*x_axis; // S dy = dp*y_axis; // S dz = dp*z_axis; // // S tx = dx; // S ty = -dy; // S qx,qy; // // // nota: per le camere ortogonali viewportM vale 1 // if(!IsOrtho()) // { // tx *= f/dz; // ty *= f/dz; // // undistorted_to_distorted_sensor_coord(tx,ty,qx,qy); // // q[0] = qx/s[0]+c[0]; // q[1] = qy/s[1]+c[1]; // } // else // { // q[0] = tx/(s[0]*viewportM)+c[0]; // q[1] = ty/(s[1]*viewportM)+c[1]; // } // } // //#if 1 // void Show( FILE * fp ) // { // if(valid) // fprintf(fp, // "posiz.: %g %g %g\n" // "x axis: %g %g %g\n" // "y axis: %g %g %g\n" // "z axis: %g %g %g\n" // "focal : %g scale: %g %g center: %g %g\n" // "viewp.: %d %d distorsion: %g %g %g %g\n" // ,view_p[0],view_p[1],view_p[2] // ,x_axis[0],x_axis[1],x_axis[2] // ,y_axis[0],y_axis[1],y_axis[2] // ,z_axis[0],z_axis[1],z_axis[2] // ,f,s[0],s[1],c[0],c[1] // ,viewport[0],viewport[1],k[0],k[1],k[2],k[3] // ); // else // fprintf(fp,"Invalid\n"); // } //#endif // // // Legge una camera in descrizione tsai binario // static void load_tsai_bin (FILE *fp, tsai_camera_parameters *cp, tsai_calibration_constants *cc) // { // double sa, // ca, // sb, // cb, // sg, // cg; // // fread(&(cp->Ncx),sizeof(double),1,fp); // fread(&(cp->Nfx),sizeof(double),1,fp); // fread(&(cp->dx),sizeof(double),1,fp); // fread(&(cp->dy),sizeof(double),1,fp); // fread(&(cp->dpx),sizeof(double),1,fp); // fread(&(cp->dpy),sizeof(double),1,fp); // fread(&(cp->Cx),sizeof(double),1,fp); // fread(&(cp->Cy),sizeof(double),1,fp); // fread(&(cp->sx),sizeof(double),1,fp); // // fread(&(cc->f),sizeof(double),1,fp); // fread(&(cc->kappa1),sizeof(double),1,fp); // fread(&(cc->Tx),sizeof(double),1,fp); // fread(&(cc->Ty),sizeof(double),1,fp); // fread(&(cc->Tz),sizeof(double),1,fp); // fread(&(cc->Rx),sizeof(double),1,fp); // fread(&(cc->Ry),sizeof(double),1,fp); // fread(&(cc->Rz),sizeof(double),1,fp); // // // SINCOSd (cc->Rx, sa, ca); // SINCOSd (cc->Ry, sb, cb); // SINCOSd (cc->Rz, sg, cg); // // cc->r1 = cb * cg; // cc->r2 = cg * sa * sb - ca * sg; // cc->r3 = sa * sg + ca * cg * sb; // cc->r4 = cb * sg; // cc->r5 = sa * sb * sg + ca * cg; // cc->r6 = ca * sb * sg - cg * sa; // cc->r7 = -sb; // cc->r8 = cb * sa; // cc->r9 = ca * cb; // // fread(&(cc->p1),sizeof(double),1,fp); // fread(&(cc->p2),sizeof(double),1,fp); // } // // void load_tsai (FILE *fp, tsai_camera_parameters *cp, tsai_calibration_constants *cc) // { // double sa, // ca, // sb, // cb, // sg, // cg; // // fscanf (fp, "%lf", &(cp->Ncx)); // fscanf (fp, "%lf", &(cp->Nfx)); // fscanf (fp, "%lf", &(cp->dx)); // fscanf (fp, "%lf", &(cp->dy)); // fscanf (fp, "%lf", &(cp->dpx)); // fscanf (fp, "%lf", &(cp->dpy)); // fscanf (fp, "%lf", &(cp->Cx)); // fscanf (fp, "%lf", &(cp->Cy)); // fscanf (fp, "%lf", &(cp->sx)); // // fscanf (fp, "%lf", &(cc->f)); // fscanf (fp, "%lf", &(cc->kappa1)); // fscanf (fp, "%lf", &(cc->Tx)); // fscanf (fp, "%lf", &(cc->Ty)); // fscanf (fp, "%lf", &(cc->Tz)); // fscanf (fp, "%lf", &(cc->Rx)); // fscanf (fp, "%lf", &(cc->Ry)); // fscanf (fp, "%lf", &(cc->Rz)); // // SINCOSd (cc->Rx, sa, ca); // SINCOSd (cc->Ry, sb, cb); // SINCOSd (cc->Rz, sg, cg); // // cc->r1 = cb * cg; // cc->r2 = cg * sa * sb - ca * sg; // cc->r3 = sa * sg + ca * cg * sb; // cc->r4 = cb * sg; // cc->r5 = sa * sb * sg + ca * cg; // cc->r6 = ca * sb * sg - cg * sa; // cc->r7 = -sb; // cc->r8 = cb * sa; // cc->r9 = ca * cb; // // fscanf (fp, "%lf", &(cc->p1)); // fscanf (fp, "%lf", &(cc->p2)); // } // // // Importa una camera dal formato tsai // void import( const tsai_camera_parameters & cp, // const tsai_calibration_constants & cc, // const int image_viewport[2] // ) // { // assert(!IsOrtho()); // valid = true; // x_axis[0] = cc.r1; x_axis[1] = cc.r2; x_axis[2] = cc.r3; // y_axis[0] = cc.r4; y_axis[1] = cc.r5; y_axis[2] = cc.r6; // z_axis[0] = cc.r7; z_axis[1] = cc.r8; z_axis[2] = cc.r9; // // view_p[0] = - (cc.Tx * x_axis[0] + cc.Ty * y_axis[0] + cc.Tz * z_axis[0]); // view_p[1] = - (cc.Tx * x_axis[1] + cc.Ty * y_axis[1] + cc.Tz * z_axis[1]); // view_p[2] = - (cc.Tx * x_axis[2] + cc.Ty * y_axis[2] + cc.Tz * z_axis[2]); // // s[0] = cp.dpx/cp.sx; // s[1] = cp.dpy; // c[0] = cp.Cx; // c[1] = cp.Cy; // // f = cc.f; // viewport[0] = image_viewport[0]; // viewport[1] = image_viewport[1]; // // k[0] = cc.kappa1; // k[1] = cc.kappa1; // k[2] = 0; // k[2] = 0; // } // // // Esporta una camera in formato tsai // void export( tsai_camera_parameters & cp, // tsai_calibration_constants & cc, // int image_viewport[2] // ) // { // assert(!IsOrtho()); // cc.r1 = x_axis[0]; cc.r2 = x_axis[1]; cc.r3= x_axis[2] ; // cc.r4 = y_axis[0]; cc.r5 = y_axis[1]; cc.r6= y_axis[2] ; // cc.r7 = z_axis[0]; cc.r8 = z_axis[1]; cc.r9= z_axis[2] ; // // cc.Tx = - (view_p[0] * x_axis[0] + view_p[1] * x_axis[1] + view_p[2] * x_axis[2]); // cc.Ty = - (view_p[0] * y_axis[0] + view_p[1] * y_axis[1] + view_p[2] * y_axis[2]); // cc.Tz = - (view_p[0] * z_axis[0] + view_p[1] * z_axis[1] + view_p[2] * z_axis[2]); // // cp.dpx = s[0]; // cp.dpy = s[1]; // // cp.Cx= c[0] ; // cp.Cy= c[1] ; // cp.sx= 1; // // cc.f= f ; // // image_viewport[0] = viewport[0]; // image_viewport[1] = viewport[1]; // // cc.kappa1= k[0] ; // cc.kappa1= k[1] ; // } // // // void Save(FILE * out) // { // fprintf(out,"VIEW_POINT %f %f %f\n", view_p[0],view_p[1],view_p[2]); // fprintf(out,"X_AXIS %f %f %f\n", x_axis[0],x_axis[1],x_axis[2]); // fprintf(out,"Y_AXIS %f %f %f\n", y_axis[0],y_axis[1],y_axis[2]); // fprintf(out,"Z_AXIS %f %f %f\n", z_axis[0],z_axis[1],z_axis[2]); // fprintf(out,"FOCUS_LENGHT %f \n", f); // fprintf(out,"SCALE %f %f \n", s[0], s[1]); // fprintf(out,"VIEWPORT %d %d \n", viewport[0], viewport[1]); // fprintf(out,"VIEWPORTM %f\n", viewportM); // fprintf(out,"RADIAL_DISTORSION %.10g %.10g \n", k[0],k[1]); // fprintf(out,"CENTER %f %f \n", c[0], c[1]); // fprintf(out,"IS_VALID %d\n", IsValid()); // fprintf(out,"END_CAMERA\n"); // } // // void Load(FILE * in) // { // char row[255]; // Standard(); // while(!feof(in)) // { // fscanf(in,"%s",row); // if(strcmp(row,"VIEW_POINT")==0) // fscanf(in,"%lg %lg %lg",&view_p[0],&view_p[1],&view_p[2]); // else // if(strcmp(row,"X_AXIS")==0) // fscanf(in,"%lg %lg %lg",& x_axis[0],&x_axis[1],&x_axis[2]); // else // if(strcmp(row,"Y_AXIS")==0) // fscanf(in,"%lg %lg %lg",& y_axis[0],&y_axis[1],&y_axis[2]); // else // if(strcmp(row,"Z_AXIS")==0) // fscanf(in,"%lg %lg %lg",& z_axis[0],&z_axis[1],&z_axis[2]); // else // if(strcmp(row,"FOCUS_LENGHT")==0) // fscanf(in,"%lg",&f); // else // if(strcmp(row,"SCALE")==0) // fscanf(in,"%lg %lg",&s[0],&s[1]); // else // if(strcmp(row,"VIEWPORT")==0) // fscanf(in,"%d %d", &viewport[0],&viewport[1]); // else // if(strcmp(row,"VIEWPORTM")==0) // fscanf(in,"%f", &viewportM); // else // if(strcmp(row,"CENTER")==0) // fscanf(in,"%lg %lg", &c[0],&c[1]); // else // if(strcmp(row,"RADIAL_DISTORSION")==0) // fscanf(in,"%lg %lg", &k[0],&k[1]); // else // if(strcmp(row,"IS_VALID")==0) // fscanf(in,"%d",&valid); // if(strcmp(row,"END_CAMERA")==0) // break; // } // } // //#ifdef __GL_H__ // //// Prende in ingresso il bounding box dell'oggetto da inquadrare e setta projection e modelmatrix //// in modo da matchare il piu' possibile quelle della camera. Ovviamente (?) si ignora le distorsioni radiali. //// Nota che bb viene utilizzato solo per settare i near e far plane in maniera sensata. //void SetGL(const Box3 &bb,scalar subx0=0, scalar subx1=1,scalar suby0=0,scalar suby1=1) //{ // scalar _,__; // SetGL(_,__,bb,subx0, subx1, suby0, suby1); // //} // //void SetGL(scalar &znear, scalar &zfar,const Box3 &bb,scalar subx0=0, // scalar subx1=1,scalar suby0=0,scalar suby1=1) //{ // glMatrixMode(GL_PROJECTION); // glLoadIdentity(); // scalar left,right; // scalar bottom, top; // scalar w,h; // // // La lunghezza focale e' la distanza del piano immagine dal centro di proiezione. // // il che mappa direttamente nella chiamata glFrustum che prende in ingresso // // le coordinate del piano immagine posto a znear. // // float imleft =-c[0]*s[0]; // float imright =(viewport[0]-c[0])*s[0]; // float imbottom =-c[1]*s[1]; // float imtop =(viewport[1]-c[1])*s[1]; // znear = Distance(view_p, bb.Center())-bb.Diag(); // zfar = Distance(view_p, bb.Center())+bb.Diag(); // // w=imright-imleft; // h=imtop-imbottom; // // // Quindi il frustum giusto sarebbe questo, // // glFrustum(imleft, imright, imbottom, imtop, f, zfar); // // ma per amor di opengl conviene spostare il near plane fino ad essere vicino all'oggetto da inquadrare. // // Cambiare f significa amplificare in maniera proporzionale anche i left right ecc. // // // 8/5/02 Nota che il near plane va spostato verso l'oggetto solo se quello calcolato sopra e' maggiore di 'f' // // nota che potrebbe anche succedere che znear <0 (viewpoint vicino ad un oggetto con il bb allungato); // if(znear c, scalar RadAngle) //{ // Point3 rnd(1.0 - 2.0*scalar(rand())/RAND_MAX, // 1.0 - 2.0*scalar(rand())/RAND_MAX, // 1.0 - 2.0*scalar(rand())/RAND_MAX); // rnd.Normalize(); // Matrix44 m,t0,t1,tr; // Point3 axis = rnd ^ (view_p-c).Normalize(); // scalar RadRandAngle=RadAngle*(1.0 - 2.0*scalar(rand())/RAND_MAX); // t0.Translate(c); // t1.Translate(-c); // m.Rotate(ToDeg(RadRandAngle),axis); // tr=t1*m*t0; // Apply(tr); //} // // // // //void glTexGen(int offx =0, // angolo basso sinistra della // int offy=0, // subtexture per la quale si vogliono settare le coordinate // int sx=1, // Dimensioni in Texel // int sy=1, // int Tx=1, // Dimensioni della texture // int Ty=1) //{ // // prendi la rototraslazione che // // trasforma la coordinata nel // // sistema di coordinate della camera // Matrix44d M; // M[0][0] = x_axis[0]; // M[0][1] = x_axis[1]; // M[0][2] = x_axis[2]; // M[0][3] = -view_p* x_axis ; // // M[1][0] = y_axis[0]; // M[1][1] = y_axis[1]; // M[1][2] = y_axis[2]; // M[1][3] = -view_p* y_axis; // // M[2][0] = z_axis[0]; // M[2][1] = z_axis[1]; // M[2][2] = z_axis[2]; // M[2][3] = -view_p* z_axis; // // M[3][0] = 0.0; // M[3][1] = 0.0; // M[3][2] = 0.0; // M[3][3] = 1.0; // // // prendi la matrice di proiezione // Matrix44d P; // P.Zero(); // // if(!IsOrtho())// prospettica // { // // P[0][0] = sx/(s[0]*viewport[0]*Tx); // P[0][2] = (1/f)*(offx+0.5*sx)/Tx; // // P[1][1] = sy/(s[1]* viewport[1]*Ty); // P[1][2] = (1/f)*(offy+0.5*sy)/Ty; // // P[2][2] = 1; // P[3][2] = 1/f; // } // else // ortogonale // { // P[0][0] = sx/(s[0]*viewport[0]*viewportM*Tx); // P[0][3] = (offx+0.5*sx)/Tx; // l'effetto e' una traslazione di +1/2 // // P[1][1] = sy/(s[1]* viewport[1]*viewportM*Ty); // P[1][3] = (offy+0.5*sy)/Ty; // l'effetto e' una traslazione di +1/2 // // P[2][2] = 1; // P[3][3] = 1; // } // // componi // Matrix44d PM = P*M; // // glTexGend(GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR); // glTexGend(GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR); // glTexGend(GL_Q, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR); // // glTexGendv(GL_S,GL_OBJECT_PLANE,&PM[0][0]); // glTexGendv(GL_T,GL_OBJECT_PLANE,&PM[1][0]); // glTexGendv(GL_Q,GL_OBJECT_PLANE,&PM[3][0]); // // glEnable(GL_TEXTURE_GEN_S); // glEnable(GL_TEXTURE_GEN_T); // glDisable(GL_TEXTURE_GEN_R); // glEnable(GL_TEXTURE_GEN_Q); //} // //// versione per le texture rettangolare NV_TEXTURE_RECTANGLE //// la differenza da glTexGen e' che il mapping e' in [0..sx]X[0..sy] //void glTexGen_NV(int sx, // Texture Size // int sy) //{ // // prendi la rototraslazione che // // trasforma la coordinata nel // // sistema di coordinate della camera // Matrix44d M; // M[0][0] = x_axis[0]; // M[0][1] = x_axis[1]; // M[0][2] = x_axis[2]; // M[0][3] = -view_p* x_axis ; // // M[1][0] = y_axis[0]; // M[1][1] = y_axis[1]; // M[1][2] = y_axis[2]; // M[1][3] = -view_p* y_axis; // // M[2][0] = z_axis[0]; // M[2][1] = z_axis[1]; // M[2][2] = z_axis[2]; // M[2][3] = -view_p* z_axis; // // M[3][0] = 0.0; // M[3][1] = 0.0; // M[3][2] = 0.0; // M[3][3] = 1.0; // // // prendi la matrice di proiezione // Matrix44d P; // P.Zero(); // // if(!IsOrtho())// prospettica // { // // P[0][0] = sx/(s[0]*viewport[0]); // P[0][2] = sx*(1/f)*( 0.5); // // P[1][1] = sy/(s[1]* viewport[1] ); // P[1][2] = sy*(1/f)*( 0.5); // // P[2][2] = 1; // P[3][2] = 1/f; // } // else // ortogonale // { // P[0][0] = sx/(s[0]*viewport[0]*viewportM); // P[0][3] = sx* 0.5 ; // l'effetto e' una traslazione di +1/2 // // P[1][1] = sy/(s[1]* viewport[1]*viewportM); // P[1][3] = sy* 0.5 ; // l'effetto e' una traslazione di +1/2 // // P[2][2] = 1; // P[3][3] = 1; // } // // componi // Matrix44d PM = P*M; // // glTexGend(GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR); // glTexGend(GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR); // glTexGend(GL_Q, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR); // // glTexGendv(GL_S,GL_OBJECT_PLANE,&PM[0][0]); // glTexGendv(GL_T,GL_OBJECT_PLANE,&PM[1][0]); // glTexGendv(GL_Q,GL_OBJECT_PLANE,&PM[3][0]); // // glEnable(GL_TEXTURE_GEN_S); // glEnable(GL_TEXTURE_GEN_T); // glDisable(GL_TEXTURE_GEN_R); // glEnable(GL_TEXTURE_GEN_Q); //// glDisable(GL_TEXTURE_GEN_Q); // //} //#endif // __GL_H__ // //}; //} // End namespace vcg qutemol/vcg/wrap/gl/shaders.h0000444000175000017500000002105310511250045014550 0ustar mbamba#ifndef __SHADERS_H__ #define __SHADERS_H__ #include #include #include #include "gl_object.h" class Shader : public GLObject, public Bindable { public: typedef enum { VERTEX, FRAGMENT } ShaderType; Shader(void) : GLObject(), Bindable() { this->flags = 0; this->flags |= SOURCE_DIRTY; this->compiled = false; } void Gen(void) { this->Del(); GLenum t; switch (this->Type()) { case Shader::VERTEX : t = GL_VERTEX_SHADER; break; case Shader::FRAGMENT : t = GL_FRAGMENT_SHADER; break; default: return; }; this->objectID = glCreateShader(t); } void Del(void) { if (this->objectID == 0) return; glDeleteShader(this->objectID); this->objectID = 0; } virtual ShaderType Type(void) const = 0; void SetSource(const char * src) { this->flags |= SOURCE_DIRTY; this->compiled = false; this->source = src; const char * pSrc = this->source.c_str(); glShaderSource(this->objectID, 1, &pSrc, 0); } bool LoadSource(const char * fileName) { this->flags |= SOURCE_DIRTY; this->compiled = false; FILE * f = fopen(fileName, "rb"); if (f == 0) { this->source = ""; return false; } fseek(f, 0, SEEK_END); const size_t sz = (size_t)ftell(f); rewind(f); char * buff = new char[sz + 1]; fread(buff, sizeof(char), sz, f); fclose(f); buff[sz] = '\0'; this->source = buff; delete [] buff; const char * pSrc = this->source.c_str(); glShaderSource(this->objectID, 1, &pSrc, 0); return true; } bool Compile(void) { glCompileShader(this->objectID); GLint cm = 0; glGetShaderiv(this->objectID, GL_COMPILE_STATUS, &cm); this->compiled = (cm != GL_FALSE); this->flags = 0; return this->compiled; } bool IsCompiled(void) { return this->compiled; } std::string InfoLog(void) { GLint len = 0; glGetShaderiv(this->objectID, GL_INFO_LOG_LENGTH, &len); char * ch = new char[len + 1]; glGetShaderInfoLog(this->objectID, len, &len, ch); std::string infoLog = ch; delete [] ch; return infoLog; } protected: enum { SOURCE_DIRTY }; std::string source; unsigned int flags; bool compiled; void DoBind(void) { } void DoUnbind(void) { } }; class VertexShader : public Shader { public: VertexShader(void) : Shader() { } ShaderType Type(void) const { return Shader::VERTEX; } }; class FragmentShader : public Shader { public: FragmentShader(void) : Shader() { } ShaderType Type(void) const { return Shader::FRAGMENT; } }; #if 0 class Program; class Uniform { friend class Program; public: /* typedef enum { U_BOOL, U_BVEC2, U_BVEC3, U_BVEC4, U_BMAT2, U_BMAT3, U_BMAT4, U_INT, U_IVEC2, U_IVEC3, U_IVEC4, U_IMAT2, U_IMAT3, U_IMAT4, U_FLOAT, U_FVEC2, U_FVEC3, U_FVEC4, U_FMAT2, U_FMAT3, U_FMAT4, U_SAMPLER1D, U_SAMPLER2D, U_SAMPLER3D, U_SAMPLERCUBE, U_SAMPLER1DSHADOW, U_SAMPLER2DSHADOW } UniformType; */ const std::string & Name(void) const { return this->name; } virtual GLenum Type(void) const = 0; protected: Program * prog; GLint location; std::string name; Uniform(Program * prog, GLint location, const std::string & name) { this->prog = prog; this->location = location; this->name = name; } virtual void Apply(void) = 0; }; class Uniform1b : public Uniform; { public: void SetValue(GLboolean x) { this->value[0] = x; } GLboolean GetValue(void) const { return this->value[0]; } protected: Program * prog; GLboolean value[1]; Uniform(Program * prog, GLint location, const std::string & name) : Uniform(prog, location, name) { this->value = GL_FALSE; } }; class Uniform2b : public Uniform; { public: void SetValue(GLboolean x, GLboolean y) { this->value[0] = x; this->value[1] = y; } GLboolean GetValueX(void) const { return this->value[0]; } GLboolean GetValueY(void) const { return this->value[1]; } protected: Program * prog; GLboolean value[2]; Uniform(Program * prog, GLint location, const std::string & name) : Uniform(prog, location, name) { this->value[0] = GL_FALSE; this->value[1] = GL_FALSE; } }; class Uniform3b : public Uniform; { public: void SetValue(GLboolean x, GLboolean y, GLboolean z) { this->value[0] = x; this->value[1] = y; this->value[2] = z; } GLboolean GetValueX(void) const { return this->value[0]; } GLboolean GetValueY(void) const { return this->value[1]; } GLboolean GetValueZ(void) const { return this->value[2]; } protected: Program * prog; GLboolean value[2]; Uniform(Program * prog, GLint location, const std::string & name) : Uniform(prog, location, name) { this->value[0] = GL_FALSE; this->value[1] = GL_FALSE; } }; class Uniform1i : public Uniform; { public: void SetValue(GLint v) { this->value = v; } GLint GetValue(void) const { return this->value; } protected: Program * prog; GLint value; Uniform(Program * prog, GLint location, const std::string & name) : Uniform(prog, location, name) { this->value = 0; } }; #endif class Program : public GLObject, public Bindable { public: Program(void) { this->linked = false; } void Gen(void) { this->Del(); this->objectID = glCreateProgram(); } void Del(void) { if (this->objectID == 0) return; glDeleteProgram(this->objectID); this->objectID = 0; } void Attach(Shader * shd) { this->shaders.insert(shd); this->linked = false; glAttachShader(this->objectID, shd->ObjectID()); } void Detach(Shader * shd) { this->shaders.erase(shd); this->linked = false; glDetachShader(this->objectID, shd->ObjectID()); } GLsizei AttachedShaders(void) const { return ((GLsizei)(this->shaders.size())); } Shader * AttachedShader(int i) { Shader * shd = 0; int cnt = 0; for (std::set::iterator it=this->shaders.begin(); (cnt < i) && (it!=this->shaders.end()); ++it) { shd = (*it); } return shd; } bool Link(void) { for (std::set::iterator it=this->shaders.begin(); it!=this->shaders.end(); ++it) { Shader * shd = (*it); if (!shd->IsCompiled()) { shd->Compile(); } } glLinkProgram(this->objectID); GLint cm = 0; glGetProgramiv(this->objectID, GL_LINK_STATUS, &cm); this->linked = (cm != GL_FALSE); return this->linked; } bool IsLinked(void) const { return this->linked; } std::string InfoLog(void) { GLint len = 0; glGetProgramiv(this->objectID, GL_INFO_LOG_LENGTH, &len); char * ch = new char[len + 1]; glGetProgramInfoLog(this->objectID, len, &len, ch); std::string infoLog = ch; delete [] ch; return infoLog; } void Uniform(const char * name, GLint x) { const GLint loc = glGetUniformLocation(this->objectID, name); glUniform1i(loc, x); } void Uniform(const char * name, GLint x, GLint y) { const GLint loc = glGetUniformLocation(this->objectID, name); glUniform2i(loc, x, y); } void Uniform(const char * name, GLint x, GLint y, GLint z) { const GLint loc = glGetUniformLocation(this->objectID, name); glUniform3i(loc, x, y, z); } void Uniform(const char * name, GLint x, GLint y, GLint z, GLint w) { const GLint loc = glGetUniformLocation(this->objectID, name); glUniform4i(loc, x, y, z, w); } void Uniform(const char * name, GLfloat x) { const GLint loc = glGetUniformLocation(this->objectID, name); glUniform1f(loc, x); } void Uniform(const char * name, GLfloat x, GLfloat y) { const GLint loc = glGetUniformLocation(this->objectID, name); glUniform2f(loc, x, y); } void Uniform(const char * name, GLfloat x, GLfloat y, GLfloat z) { const GLint loc = glGetUniformLocation(this->objectID, name); glUniform3f(loc, x, y, z); } void Uniform(const char * name, GLfloat x, GLfloat y, GLfloat z, GLfloat w) { const GLint loc = glGetUniformLocation(this->objectID, name); glUniform4f(loc, x, y, z, w); } protected: std::set shaders; bool linked; void DoBind(void) { if (!this->IsLinked()) { this->Link(); } glUseProgram(this->objectID); } void DoUnbind(void) { glUseProgram(0); } }; class ProgramVF : public Bindable { public: Program prog; VertexShader vshd; FragmentShader fshd; ProgramVF(void) : Bindable() { } void SetSources(const char * vsrc, const char * fsrc) { this->vshd.SetSource(vsrc); this->fshd.SetSource(fsrc); this->prog.Attach(&(this->vshd)); this->prog.Attach(&(this->fshd)); } void LoadSources(const char * vfile, const char * ffile) { this->vshd.LoadSource(vfile); this->fshd.LoadSource(ffile); this->prog.Attach(&(this->vshd)); this->prog.Attach(&(this->fshd)); } protected: void DoBind(void) { this->prog.Bind(); } void DoUnbind(void) { this->prog.Unbind(); } }; #endif // __SHADERS_H__ qutemol/vcg/wrap/gl/pick.h0000444000175000017500000002317010567257704014073 0ustar mbamba/**************************************************************************** * VCGLib o o * * Visual and Computer Graphics Library o o * * _ O _ * * Copyright(C) 2004 \/)\/ * * Visual Computing Lab /\/| * * ISTI - Italian National Research Council | * * \ * * All rights reserved. * * * * 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. * * * * 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 (http://www.gnu.org/licenses/gpl.txt) * * for more details. * * * ****************************************************************************/ /**************************************************************************** History $Log: pick.h,v $ Revision 1.11 2007/02/22 09:17:56 cignoni Added cast for mac compiling Revision 1.10 2006/12/07 00:39:22 cignoni Added a class prototype for avoiding the inclusion of tetra.h Revision 1.9 2006/12/04 09:27:13 cignoni Removed useless include ****************************************************************************/ #ifndef __PICK______H #define __PICK______H #include #include namespace vcg{ template class GLPickTri { typedef typename MESH_TYPE::FaceIterator FaceIterator; typedef typename MESH_TYPE::FacePointer FacePointer; typedef typename MESH_TYPE::VertexType VertexType; public: static bool PickNearestFace(int x, int y, MESH_TYPE &m, FacePointer &fi,int width=4, int height=4) { std::vector result; int val=PickFace(x,y,m,result,width,height); if(val!=0) { fi=result[0]; return true; } fi=NULL; return false; } static int PickFace(int x, int y, MESH_TYPE &m, std::vector &result, int width=4, int height=4,bool sorted=true) { result.clear(); if(width==0 ||height==0) return 0; long hits; int sz=m.face.size()*5; GLuint *selectBuf =new GLuint[sz]; // static unsigned int selectBuf[16384]; glSelectBuffer(sz, selectBuf); glRenderMode(GL_SELECT); glInitNames(); /* Because LoadName() won't work with no names on the stack */ glPushName(-1); double mp[16]; GLint viewport[4]; glGetIntegerv(GL_VIEWPORT,viewport); glMatrixMode(GL_PROJECTION); glGetDoublev(GL_PROJECTION_MATRIX ,mp); glPushMatrix(); glLoadIdentity(); //gluPickMatrix(x, viewport[3]-y, 4, 4, viewport); gluPickMatrix(x, y, width, height, viewport); glMultMatrixd(mp); glMatrixMode(GL_MODELVIEW); glPushMatrix(); int fcnt=0; FaceIterator fi; for(fi=m.face.begin();fi!=m.face.end();++fi) { if(!(*fi).IsD()) { glLoadName(fcnt); glBegin(GL_TRIANGLES); glVertex( (*fi).V(0)->P() ); glVertex( (*fi).V(1)->P() ); glVertex( (*fi).V(2)->P() ); glEnd(); } fcnt++; // the counter should advance even for deleted faces! } glPopMatrix(); glMatrixMode(GL_PROJECTION); glPopMatrix(); glMatrixMode(GL_MODELVIEW); hits = glRenderMode(GL_RENDER); //xstring buf; //if (hits <= 0) return 0; std::vector< std::pair > H; for(long ii=0;ii(selectBuf[ii*4+1]/4294967295.0,selectBuf[ii*4+3])); } if(sorted) std::sort(H.begin(),H.end()); // if(H.size()>0) TRACE("\n Closest is %i\n",H[0].second); result.resize(H.size()); for(long ii=0;ii class GLPickTetra { typedef typename TETRA_MESH_TYPE::TetraIterator TetraIterator; typedef typename TETRA_MESH_TYPE::TetraPointer TetraPointer; typedef typename TETRA_MESH_TYPE::VertexType VertexType; public: static bool PickNearestTetra(int x, int y,TETRA_MESH_TYPE &m, TetraIterator &ti,int width=4, int height=4) { std::vector result; int val=PickTetra(x,y,m,result,width,height); if(val!=0) { ti=result[0]; return true; } ti=0; return false; } // class prototype needed for avoid the inclusion of tetra.h class Tetra; static int PickTetra(int x, int y, TETRA_MESH_TYPE &m, std::vector &result, int width=4, int height=4) { result.clear(); long hits; int sz=m.tetra.size()*5; unsigned int *selectBuf =new unsigned int[sz]; // static unsigned int selectBuf[16384]; glSelectBuffer(sz, selectBuf); glRenderMode(GL_SELECT); glInitNames(); /* Because LoadName() won't work with no names on the stack */ glPushName(-1); double mp[16]; int viewport[4]; glGetIntegerv(GL_VIEWPORT,viewport); glMatrixMode(GL_PROJECTION); glGetDoublev(GL_PROJECTION_MATRIX ,mp); glPushMatrix(); glLoadIdentity(); //gluPickMatrix(x, viewport[3]-y, 4, 4, viewport); gluPickMatrix(x, y, width, height, viewport); glMultMatrixd(mp); glMatrixMode(GL_MODELVIEW); glPushMatrix(); int tetracnt=0; TetraIterator ti; for(ti=m.tetra.begin();ti!=m.tetra.end();++ti) { if(!(*ti).IsD()) { glLoadName(tetracnt); glBegin(GL_TRIANGLES); for (int face=0;face<4;face++) { //glLoadName(tetracnt); VertexType *v0=ti->V(Tetra::VofF(face,0)); VertexType *v1=ti->V(Tetra::VofF(face,1)); VertexType *v2=ti->V(Tetra::VofF(face,2)); glVertex(v0->P()); glVertex(v1->P()); glVertex(v2->P()); } glEnd(); tetracnt++; } } glPopMatrix(); glMatrixMode(GL_PROJECTION); glPopMatrix(); glMatrixMode(GL_MODELVIEW); hits = glRenderMode(GL_RENDER); //xstring buf; //if (hits <= 0) return 0; std::vector< std::pair > H; int ii; for(ii=0;ii(selectBuf[ii*4+1]/4294967295.0,selectBuf[ii*4+3])); } std::sort(H.begin(),H.end()); // if(H.size()>0) TRACE("\n Closest is %i\n",H[0].second); result.resize(H.size()); for(ii=0;ii > result; int val=PickTetraFace(x,y,m,result,width,height); if(val!=0) { ti=result[0].first; face=result[0].second; return true; } ti=0; face=-1; return false; } static int PickTetraFace(int x, int y, TETRA_MESH_TYPE &m, std::vector > &result, int width=4, int height=4) { result.clear(); long hits; int sz=(m.tetra.size()*4)*5; unsigned int *selectBuf =new unsigned int[sz]; // static unsigned int selectBuf[16384]; glSelectBuffer(sz, selectBuf); glRenderMode(GL_SELECT); glInitNames(); /* Because LoadName() won't work with no names on the stack */ glPushName(-1); double mp[16]; int viewport[4]; glGetIntegerv(GL_VIEWPORT,viewport); glMatrixMode(GL_PROJECTION); glGetDoublev(GL_PROJECTION_MATRIX ,mp); glPushMatrix(); glLoadIdentity(); //gluPickMatrix(x, viewport[3]-y, 4, 4, viewport); gluPickMatrix(x, y, width, height, viewport); glMultMatrixd(mp); glMatrixMode(GL_MODELVIEW); glPushMatrix(); int tetracnt=0; TetraIterator ti; VertexType *v0; VertexType *v1; VertexType *v2; int face; for(ti=m.tetra.begin();ti!=m.tetra.end();++ti) { if(!(*ti).IsD()) { for (face=0;face<4;face++){ v0=ti->V(Tetra::VofF(face,0)); v1=ti->V(Tetra::VofF(face,1)); v2=ti->V(Tetra::VofF(face,2)); glLoadName(tetracnt); glBegin(GL_TRIANGLES); glVertex(v0->P()); glVertex(v1->P()); glVertex(v2->P()); glEnd(); tetracnt++; } } } glPopMatrix(); glMatrixMode(GL_PROJECTION); glPopMatrix(); glMatrixMode(GL_MODELVIEW); hits = glRenderMode(GL_RENDER); //xstring buf; //if (hits <= 0) return 0; std::vector< std::pair > H; int ii; for(ii=0;ii(selectBuf[ii*4+1]/4294967295.0,selectBuf[ii*4+3])); } std::sort(H.begin(),H.end()); // if(H.size()>0) TRACE("\n Closest is %i\n",H[0].second); result.resize(H.size()); for(ii=0;ii(&*ti,index%4); } delete [] selectBuf; return result.size(); } }; } #endif qutemol/vcg/wrap/gl/addons.h0000444000175000017500000003023410452217672014405 0ustar mbamba/**************************************************************************** * VCGLib o o * * Visual and Computer Graphics Library o o * * _ O _ * * Copyright(C) 2004 \/)\/ * * Visual Computing Lab /\/| * * ISTI - Italian National Research Council | * * \ * * All rights reserved. * * * * 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. * * * * 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 (http://www.gnu.org/licenses/gpl.txt) * * for more details. * * * ****************************************************************************/ /**************************************************************************** History $Log: addons.h,v $ Revision 1.13 2006/07/03 13:46:34 spinelli remove warning C4244 Revision 1.12 2006/05/25 09:22:58 cignoni Removed all GLUT dependencies! Revision 1.11 2006/03/29 07:54:03 cignoni Wrong matrix type in cone (thx Maarten) ****************************************************************************/ #ifndef __VCG_GLADDONS #define __VCG_GLADDONS #include #include #include #include namespace vcg { #include "gl_geometry.h" /** Class Add_Ons. This is class draw 3d icons on the screen */ class Add_Ons { public: enum DrawMode {DMUser,DMWire,DMSolid} ; private: ///used to find right trasformation in case of rotation static void XAxis( vcg::Point3f zero, vcg::Point3f uno, Matrix44f & tr){ tr.SetZero(); *((vcg::Point3f*)&tr[0][0]) = uno-zero; GetUV(*((vcg::Point3f*)tr[0]),*((vcg::Point3f*)tr[1]),*((vcg::Point3f*)tr[2])); tr[3][3] = 1.0; *((vcg::Point3f*)&tr[3][0]) = zero; } //set drawingmode parameters static void SetGLParameters(DrawMode DM) { switch(DM) { case DMUser : break; case DMWire : glDisable(GL_CULL_FACE); glDisable(GL_LIGHTING); glDisable(GL_NORMALIZE); glPolygonMode(GL_FRONT_AND_BACK,GL_LINE); break; case DMSolid : glDisable(GL_CULL_FACE); glPolygonMode(GL_FRONT,GL_FILL); break; default : break; } } ///draw a cylinder static void Cylinder(int slices,float lenght,float width,bool useDisplList) { static std::map Disp_listMap; GLint cyl_List=-1; std::map::const_iterator it=Disp_listMap.find(slices); ///if the diplay list is createdtake the Glint that identify it bool to_insert=false; if (useDisplList) { if (it!=Disp_listMap.end())///the list exist cyl_List=it->second; else to_insert=true; } glScaled(lenght,width,width); if (((!glIsList(cyl_List))&&(useDisplList))||(!useDisplList)) { if (useDisplList) { cyl_List = glGenLists(1); glNewList(cyl_List, GL_COMPILE); } int b; vcg::Point3f p0; vcg::Point3f p1; float step=6.28f/(float)slices; float angle=0; glBegin(GL_TRIANGLE_STRIP); for(b = 0; b <= slices-1; ++b){ p0 = vcg::Point3f( 0, sin(angle),cos(angle)); p1 = p0; p1[0] = 1.f; glNormal3f(p0[0],p0[1],p0[2]); glVertex3d(p0[0],p0[1],p0[2]); glVertex3d(p1[0],p1[1],p1[2]); angle+=step; } ///re-conjunction with first point of cylinder glNormal3f(0,0,1); glVertex3d(0,0,1); glVertex3d(1,0,1); glEnd(); ///fill the cylinder down angle=0; p0=vcg::Point3f(0,0,0); glBegin(GL_TRIANGLE_FAN); glNormal3f(-1,0,0); glVertex3d(p0[0],p0[1],p0[2]); for(b = 0; b <= slices-1; ++b){ glNormal3f(-1,0,0); p1 = Point3f( 0, sin(angle),cos(angle)); glVertex3d(p1[0],p1[1],p1[2]); angle+=step; } glNormal3f(-1,0,0); glVertex3d(0,0,1); glEnd(); angle=0; p0=vcg::Point3f(1,0,0); glBegin(GL_TRIANGLE_FAN); glNormal3f(1,0,0); glVertex3d(p0[0],p0[1],p0[2]); for(b = 0; b <= slices-1; ++b){ glNormal3f(1,0,0); p1 = Point3f( 1, sin(angle),cos(angle)); glVertex3d(p1[0],p1[1],p1[2]); angle+=step; } glNormal3f(1,0,0); glVertex3d(1,0,1); glEnd(); if (useDisplList) glEndList(); } if (useDisplList) { glCallList(cyl_List); ///I insert key and value in the map if I need if (to_insert) Disp_listMap.insert(std::pair(slices,cyl_List)); } } public: static void Diamond (float radius,bool useDisplList) { static GLint diam_List=-1; glScaled(radius,radius,radius); if (((!glIsList(diam_List))&&(useDisplList))||(!useDisplList)) { if (useDisplList) { diam_List = glGenLists(1); glNewList(diam_List, GL_COMPILE); } glBegin(GL_TRIANGLE_FAN); glNormal3f( 0.0, 1, 0.0); glVertex3f(0.0,1,0.0); glNormal3f( 1, 0.0, 0.0); glVertex3f( 1, 0.0, 0.0); glNormal3f( 0.0, 0.0, -1); glVertex3f( 0.0, 0.0,-1); glNormal3f(-1, 0.0 , 0.0); glVertex3f(-1, 0.0, 0.0); glNormal3f( 0.0, 0.0, 1); glVertex3f( 0.0, 0.0, 1); glNormal3f( 1, 0.0, 0.0); glVertex3f( 1, 0.0, 0.0); glEnd(); glBegin(GL_TRIANGLE_FAN); glNormal3f( 0.0, 1, 0.0); glVertex3f( 0.0,-1, 0.0); glNormal3f( 1, 0.0, 0.0); glVertex3f( 1, 0.0, 0.0); glNormal3f( 0.0, 0.0, 1); glVertex3f( 0.0, 0.0, 1); glNormal3f(-1,0.0 , 0.0); glVertex3f(-1, 0.0, 0.0); glNormal3f( 0.0,0.0, -1); glVertex3f( 0.0, 0.0,-1); glNormal3f( 1, 0.0, 0.0); glVertex3f( 1, 0.0, 0.0); glEnd(); if (useDisplList) glEndList(); } if (useDisplList) glCallList(diam_List); } ///draw a cone static void Cone(int slices,float lenght,float width,bool useDisplList) { assert(!glGetError()); static std::map Disp_listMap; GLint cone_List=-1; std::map::const_iterator it=Disp_listMap.find(slices); ///if the diplay list is createdtake the Glint that identify it bool to_insert=false; if (useDisplList) { if (it!=Disp_listMap.end())///the list exist cone_List=it->second; else to_insert=true; } glScaled(lenght,width,width); assert(!glGetError()); if (((!glIsList(cone_List))&&(useDisplList))||(!useDisplList)) { int h=1; vcg::Point3f p0; vcg::Point3f P[2]; vcg::Point3f N[2]; assert(!glGetError()); glScaled(lenght,width,width); if (useDisplList) { cone_List = glGenLists(1); glNewList(cone_List, GL_COMPILE); } for(h=0; h < 2; ++h) { assert(!glGetError()); //glBegin(GL_TRIANGLE_FAN); p0 = Point3f(0,0,0); if(h==0) p0[0]+=1.f; //glNormal3f(1,0.0,0.0); //glVertex3d(p0[0],p0[1],p0[2]); N[0]= Point3f( 1.f,sinf(0),cosf(0) ); P[0]= Point3f( 0,sinf(0),cosf(0)); int b; for(b = 1; b <= slices; ++b) { float angle = -6.28f*(float)b/(float)slices; if (b==slices) angle=0; N[1] = Point3f( 1.f, sinf(angle), cosf(angle) ); P[1] = Point3f( 0, sinf(angle), cosf(angle)); assert(!glGetError()); glBegin(GL_TRIANGLES); Point3f n = ( (P[0]-p0) ^ (P[2]-p0) ).Normalize(); glNormal3f(n[0],n[1],n[2]); glVertex3f(p0[0],p0[1],p0[2]); glNormal3f(N[0][0],N[0][1],N[0][2]); glVertex3f(P[0][0],P[0][1],P[0][2]); glNormal3f(N[1][0],N[1][1],N[1][2]); glVertex3f(P[1][0],P[1][1],P[1][2]); glEnd(); assert(!glGetError()); N[0] = N[1]; P[0] = P[1]; } //glEnd(); } if (useDisplList) glEndList(); } if (useDisplList) { glCallList(cone_List); ///I insert key and value in the map if I need if (to_insert) Disp_listMap.insert(std::pair(slices,cone_List)); } } public: /// draw an arrow from tail to head /// body_width = width of the body of arrow /// head_lenght = lenght of the head of arrow /// head_width = width of the head of arrow /// body_slice = number of slices on the body /// head_slice = number of slices on the head template static void glArrow(Point3f tail, Point3f head,float body_width,float head_lenght, float head_width,int body_slice=10,int head_slice=10,bool useDisplList=true) { if (tail!=head) { //assert(!glGetError()); Matrix44f tr; XAxis(tail,head,tr); glPushAttrib(GL_ALL_ATTRIB_BITS); SetGLParameters(dm); glPushMatrix(); glMultMatrixf(&tr[0][0]); vcg::Point3f Direct=(head-tail); float l_body=Direct.Norm()-head_lenght; glPushMatrix(); glTranslate(vcg::Point3f(tail.Norm(),0,0)); Cylinder(body_slice,l_body,body_width,useDisplList); glPopMatrix(); glTranslate(vcg::Point3f(l_body,0,0)); Cone(head_slice,head_lenght,head_width,useDisplList); glPopMatrix(); //assert(!glGetError()); glPopAttrib(); //assert(!glGetError()); } } /// draw a cone from tail to head /// width = width of the base of the cone /// slice = number of slices on the cone template static void glCone(Point3f tail, Point3f head,float width,int slice=10,bool useDisplList=true) { if (tail!=head) { Matrix44f tr; XAxis(tail,head,tr); glPushAttrib(GL_ALL_ATTRIB_BITS); SetGLParameters(dm); glPushMatrix(); glMultMatrixf(&tr[0][0]); vcg::Point3f Direct=(head-tail); float l_body=Direct.Norm(); glTranslate(vcg::Point3f(tail.Norm(),0,0)); Cone(slice,l_body,width,useDisplList); glPopMatrix(); glPopAttrib(); } } /// draw a cylinder from tail to head /// width = width of the base of the cylinder /// slice = number of slices on the cylinder template static void glCylinder(Point3f tail, Point3f head,float width,int slice=10,bool useDisplList=true) { if (tail!=head) { Matrix44f tr; XAxis(tail,head,tr); glPushAttrib(GL_ALL_ATTRIB_BITS); SetGLParameters(dm); glPushMatrix(); glMultMatrixf(&tr[0][0]); vcg::Point3f Direct=(head-tail); float l_body=Direct.Norm(); glTranslate(vcg::Point3f(tail.Norm(),0,0)); Cylinder(slice,l_body,width,useDisplList); glPopMatrix(); glPopAttrib(); } } /// draw a point in Center /// size = Radius of the point /// slices = The number of subdivisions around the Z axis (similar to lines of longitude). /// stacks = The number of subdivisions along the Z axis (similar to lines of latitude). template static void glPoint(vcg::Point3f Center,float size,int slices =16,int stacks =16) { if (size!=0){ glPushMatrix(); glTranslate(Center); if (dm==DMWire) glutWireSphere(size,slices,stacks); else if (dm==DMSolid) glutSolidSphere(size,slices,stacks); else glutSolidSphere(size,slices,stacks); glPopMatrix(); } } /// draw a point in Center /// size = Radius of the point /// slices = The number of subdivisions around the Z axis (similar to lines of longitude). /// stacks = The number of subdivisions along the Z axis (similar to lines of latitude). template static void glDiamond (Point3f Center, float size,bool useDisplList=true) { if (size!=0){ glPushAttrib(GL_ALL_ATTRIB_BITS); SetGLParameters(dm); glPushMatrix(); glTranslated(Center[0],Center[1],Center[2]); Diamond(size,useDisplList); glPopMatrix(); glPopAttrib(); } } }; } #endif qutemol/vcg/wrap/gl/tetramesh.h0000444000175000017500000002132510643216702015125 0ustar mbamba#ifndef __GLWRAPTETRA__ #define __GLWRAPTETRA__ #include #include #include #include #include #include #include namespace vcg { namespace tetra { class GLW { public: enum DrawMode {DMNone, DMSmallTetra,DMFlat,DMWire, DMHidden,DMTransparent,DMFlatWire} ; enum NormalMode{NMFlat,NMSmooth, NMUser, NMPerMesh}; enum ColorMode {CMNone, CMPerMesh,CMUser,CMPerTetraF,CMPerVertexF,CMPerVertex}; enum Hint {HShrinkFactor}; }; template class GlTetramesh:public GLW{ public: typedef typename CONT_TETRA::value_type TetraType; typedef typename TetraType::VertexType VertexType; typedef typename VertexType::ScalarType ScalarType; typedef typename VertexType::CoordType Point3x; //subclass for clipping planes class ClipPlane { private: Point3x D; Point3x D0; GLdouble eqn[4]; vcg::Matrix44 TR; Point3x pp0; Point3x pp1; Point3x pp2; Point3x pp3; public: bool active; Point3x P; ClipPlane (){active=false;} ~ClipPlane (){} ClipPlane(Point3x p0, Point3x p1,Point3x p2) { Point3x N=((p1-p0)^(p2-p0)).Normalize(); N.Normalize(); D=N; D0=D; P=(p0+p1+p2)/3.f; Point3x v0=N; Point3x v1=(P-p0); v1.Normalize(); Point3x v2=(v0^v1); v2.Normalize(); v0=v0*2; v1=v1*2; v2=v2*2; pp0=-v1-v2; pp1=-v1+v2; pp2=v1+v2; pp3=v1-v2; } //set normal of the clipping plane void SetD(Point3x d) { D=d; } //set the point of the clipping plane void SetP(Point3x p) { P=p; } void GlClip() { if (active){ GLdouble d=-(D.V(0)*P.V(0)+D.V(1)*P.V(1)+D.V(2)*P.V(2)); eqn[0]=-D.V(0); eqn[1]=-D.V(1); eqn[2]=-D.V(2); eqn[3]=-d; glClipPlane(GL_CLIP_PLANE0, eqn); glEnable(GL_CLIP_PLANE0); } } void GlDraw() { glPushMatrix(); glPushAttrib(0xffffffff); glDisable(GL_CLIP_PLANE0); glEnable(GL_LIGHTING); glEnable(GL_NORMALIZE); glTranslate(P); glMultMatrix(TR); glLineWidth(0.5); glColor3d(0.7,0,0.7); glBegin(GL_LINE_LOOP); glVertex(pp0); glVertex(pp1); glVertex(pp2); glVertex(pp3); glEnd(); glPopAttrib(); glPopMatrix(); } void Transform(vcg::Matrix44 Tr) { //thath's for casting in case of trackball using //float to double and vice-versa Point3f p=Point3f((float)D0.V(0),(float)D0.V(1),(float)D0.V(2)); TR=Tr; p=TR*p; D=Point3x((ScalarType) p.V(0),(ScalarType) p.V(1),(ScalarType) p.V(2)); } void Translate(float L) { Point3x D1=D*L; P+=D1; } }; GlTetramesh(CONT_TETRA * _t):tetra(_t){} GlTetramesh( ) {} CONT_TETRA * tetra; ClipPlane section; private: ScalarType shrink_factor; public: void SetHint(Hint h, double value){ switch(h){ case HShrinkFactor: shrink_factor = value; break; } } void AddClipSection(Point3x p0,Point3x p1,Point3x p2) { section=ClipPlane(p0,p1,p2); section.active=true; } void ClearClipSection() { section.active=false; } typedef Color4b (*color_func_vertex)(VertexType&v); color_func_vertex color_vertex; typedef Color4b (*color_func_tetra)(TetraType&v); color_func_tetra color_tetra; template void Draw(){ switch (dm){ case DMNone: break; case DMSmallTetra:_DrawSmallTetra();break; case DMFlat:_DrawSurface();break; case DMWire:_DrawSurface();break; case DMHidden:_DrawSurface();break; case DMFlatWire:_DrawFlatWire(); break; case DMTransparent:break; } } private: template void _DrawSmallTetra(){ Point3x p[4],br; typename CONT_TETRA::iterator it; glPushAttrib(0xffffffff); glEnable(GL_COLOR_MATERIAL); glEnable(GL_LIGHT0); glEnable(GL_LIGHTING); glEnable(GL_NORMALIZE); glPolygonMode(GL_FRONT,GL_FILL); if (section.active) { section.GlClip(); section.GlDraw(); } /*glBegin(GL_TRIANGLES);*/ for( it = tetra->begin(); it != tetra->end(); ++it) if((!it->IsD())&&(!(it->IsS()))) //draw as normal { _DrawSmallTetra(*it); } else if((!it->IsD())&&((it->IsS())))//draw in selection mode { _DrawSelectedTetra(*it); } //glEnd(); glPopAttrib(); } template void _DrawFlatWire(){ glPushAttrib(0xffff); glEnable(GL_COLOR_MATERIAL); glEnable(GL_DEPTH); glDepthRange(0.001,1.0); Draw(); glDisable(GL_LIGHTING); glColor3f(0.0,0.0,0.0); glDepthRange(0.0,0.999); Draw(); glPopAttrib(); } template void _DrawSurface(){ typename CONT_TETRA::iterator it; glPushAttrib(0xffff); glEnable(GL_COLOR_MATERIAL); if((dm == DMWire)||(dm ==DMHidden)) { glDisable(GL_LIGHTING); glDisable(GL_NORMALIZE); glPolygonMode(GL_FRONT_AND_BACK,GL_LINE); } else { glEnable(GL_LIGHTING); glEnable(GL_NORMALIZE); glPolygonMode(GL_FRONT,GL_FILL); } //glBegin(GL_TRIANGLES); for( it = tetra->begin(); it != tetra->end(); ++it) _DrawTetra((*it)); //glEnd(); glPopAttrib(); } void _DrawSelectedTetra(TetraType &t) { glPushMatrix(); glPushAttrib(0xffff); glDisable(GL_CLIP_PLANE0); glDisable(GL_BLEND); glDisable(GL_LIGHTING); glDisable(GL_NORMALIZE); glPolygonMode(GL_FRONT_AND_BACK,GL_LINE); glColor3d(1,0,0); glBegin(GL_TRIANGLES); for (int face=0;face<4;face++) { glVertex(t.V(Tetra::VofF(face,0))->P()); glVertex(t.V(Tetra::VofF(face,1))->P()); glVertex(t.V(Tetra::VofF(face,2))->P()); } glEnd(); //end drawing glPopAttrib(); glPopMatrix(); } template void _DrawTetra(TetraType &t) { if((!t.IsD())&&(!t.IsS())) { if ((dm!=DMWire)&&(dm!=DMHidden)) _ChooseColorTetra(t); for(int i = 0; i < 4; ++i){ if (dm == DMWire) _DrawFace(t,i); else { if (t.IsBorderF(i)) { if(nm==NMSmooth) _DrawFaceSmooth(t,i); else if(nm==NMFlat) _DrawFace(t,i); } } } } else if((!t.IsD())&&(t.IsS())) _DrawSelectedTetra(t); } template void _ChooseColorTetra(TetraType &t) { if (cm==CMNone) { if (t.IsS()) glColor3d(1,0,0); else glColor3d(0.8f,0.8f,0.8f); } else if(cm == CMPerTetraF) { Color4b c; c = color_tetra(t); GLint ic[4]; ic[0] = c[0];ic[1] = c[1];ic[2] = c[2];ic[3] = c[3]; glMaterialiv(GL_FRONT,GL_DIFFUSE ,ic); } } template void _ChooseColorVertex(VertexType &v) { if (cm!=CMNone) { if(cm == CMPerVertexF) { Color4b c; c = color_vertex(v); GLint ic[4]; ic[0] = c[0];ic[1] = c[1];ic[2] = c[2];ic[3] = c[3]; glMaterialiv(GL_FRONT,GL_DIFFUSE ,ic); } else if(cm == CMPerVertex) glColor3f(v.C()[0],v.C()[1],v.C()[2]); } } template void _DrawFaceSmooth(TetraType &t,int face) { VertexType *v0=t.V(Tetra::VofF(face,0)); VertexType *v1=t.V(Tetra::VofF(face,1)); VertexType *v2=t.V(Tetra::VofF(face,2)); glBegin(GL_TRIANGLES); _ChooseColorVertex(*v0); glNormal(v0->N()); glVertex(v0->P()); _ChooseColorVertex(*v1); glNormal(v1->N()); glVertex(v1->P()); _ChooseColorVertex(*v2); glNormal(v2->N()); glVertex(v2->P()); glEnd(); } template void _DrawFace(TetraType &t,int face) { glBegin(GL_TRIANGLES); glNormal(t.N(face)); VertexType *v0=t.V(Tetra::VofF(face,0)); VertexType *v1=t.V(Tetra::VofF(face,1)); VertexType *v2=t.V(Tetra::VofF(face,2)); _ChooseColorVertex(*v0); glVertex(v0->P()); _ChooseColorVertex(*v1); glVertex(v1->P()); _ChooseColorVertex(*v2); glVertex(v2->P()); glEnd(); } template void _DrawSmallTetra(TetraType &t) { Tetra3 T=Tetra3(); T.P0(0)=t.V(0)->cP(); T.P1(0)=t.V(1)->cP(); T.P2(0)=t.V(2)->cP(); T.P3(0)=t.V(3)->cP(); Point3x p[4], br; br=T.ComputeBarycenter(); for(int i = 0; i < 4; ++i) p[i] = t.V(i)->P()* shrink_factor + br *(1- shrink_factor); _ChooseColorTetra(t); glBegin(GL_TRIANGLES); for(int i = 0; i < 4; ++i) { glNormal(t.N(i)); VertexType *v0=t.V(Tetra::VofF(i,0)); VertexType *v1=t.V(Tetra::VofF(i,1)); VertexType *v2=t.V(Tetra::VofF(i,2)); _ChooseColorVertex(*v0); glVertex(p[Tetra::VofF(i,0)]); _ChooseColorVertex(*v1); glVertex(p[Tetra::VofF(i,1)]); _ChooseColorVertex(*v2); glVertex(p[Tetra::VofF(i,2)]); } glEnd(); } }; } // end namespace tetra } // end nemaspace tri #endif qutemol/vcg/wrap/gl/math.h0000444000175000017500000001217210512524531014057 0ustar mbamba/**************************************************************************** * VCGLib o o * * Visual and Computer Graphics Library o o * * _ O _ * * Copyright(C) 2004 \/)\/ * * Visual Computing Lab /\/| * * ISTI - Italian National Research Council | * * \ * * All rights reserved. * * * * 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. * * * * 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 (http://www.gnu.org/licenses/gpl.txt) * * for more details. * * * ****************************************************************************/ /**************************************************************************** History $Log: math.h,v $ Revision 1.11 2006/10/09 19:56:09 cignoni Removed the default use of the OpenGL transpose extension. Added two method for direct (non transposed) matrix multiplication and getting Revision 1.10 2006/02/13 13:05:05 cignoni Removed glew inclusion Revision 1.9 2004/09/30 00:48:07 ponchio -> Revision 1.8 2004/09/28 14:04:36 ganovelli glGet added Revision 1.7 2004/07/13 15:55:57 cignoni Added test on presence of glTranspose extension (for old hw support) Revision 1.6 2004/05/26 15:12:39 cignoni Removed inclusion of gl extension stuff Revision 1.5 2004/05/12 20:54:55 ponchio *** empty log message *** Revision 1.4 2004/05/12 13:07:47 ponchio Added #include Revision 1.3 2004/05/04 23:36:23 cignoni remove include of gl and added glextgension exploiting, Revision 1.2 2004/04/07 10:47:03 cignoni inlined functions for avoid multiple linking errors Revision 1.1 2004/03/31 15:27:17 ponchio *** empty log message *** ****************************************************************************/ #ifndef VCG_GL_MATH_H #define VCG_GL_MATH_H // Please note that this file assume that you have already included your // gl-extension wrapping utility, and that therefore all the extension symbol are already defined. #include #include //#include // please do not include it! namespace vcg { inline void glMultMatrixE(const Matrix44f &matrix) { //glMultMatrixf((const GLfloat *)(matrix[0])); if(glMultTransposeMatrixf) glMultTransposeMatrixf((const GLfloat *)(matrix[0])); else { Matrix44f tmp(matrix); Transpose(tmp); glMultMatrixf((const GLfloat *)(tmp[0])); } } inline void glMultMatrix(const Matrix44f &matrix) { Matrix44f tmp(matrix); Transpose(tmp); glMultMatrixf((const GLfloat *)(tmp[0])); } inline void glMultMatrixE(const Matrix44d &matrix) { if(glMultTransposeMatrixd) glMultTransposeMatrixd((const GLdouble *)(matrix[0])); else { Matrix44d tmp(matrix); Transpose(tmp); glMultMatrixd((const GLdouble *)(tmp[0])); } } inline void glMultMatrix(const Matrix44d &matrix) { Matrix44d tmp(matrix); Transpose(tmp); glMultMatrixd((const GLdouble *)(tmp[0])); } inline void glMultMatrixDirect(const Matrix44f &matrix) { glMultMatrixf((const GLfloat *)(matrix[0])); } inline void glMultMatrixDirect(const Matrix44d &matrix) { glMultMatrixd((const GLdouble *)(matrix[0])); } inline void glMultMatrix(const Similarityf &s) { glTranslatef(s.tra[0], s.tra[1], s.tra[2]); glScalef(s.sca, s.sca, s.sca); float alpha; Point3f axis; s.rot.ToAxis(alpha, axis); glRotatef(math::ToDeg(alpha), axis[0], axis[1], axis[2]); } inline void glMultMatrix(const Similarityd &s) { glTranslated(s.tra[0], s.tra[1], s.tra[2]); double alpha; Point3d axis; s.rot.ToAxis(alpha, axis); glRotated(math::ToDeg(alpha), axis[0], axis[1], axis[2]); glScaled(s.sca, s.sca, s.sca); } inline void glGetv(const GLenum pname, Matrix44f & m){ glGetFloatv(pname,&m[0][0]); Transpose(m); } inline void glGetv(const GLenum pname, Matrix44d & m){ glGetDoublev(pname,&m[0][0]); Transpose(m); } inline void glGetDirectv(const GLenum pname, Matrix44f & m){ glGetFloatv(pname,&m[0][0]); } inline void glGetDirecv(const GLenum pname, Matrix44d & m){ glGetDoublev(pname,&m[0][0]); } }//namespace #endif qutemol/vcg/wrap/gl/gl_object.h0000444000175000017500000000140210511250045015043 0ustar mbamba#ifndef __GL_OBJECT_H__ #define __GL_OBJECT_H__ #include class GLObject { public: GLObject(void) { this->objectID = 0; } virtual ~GLObject(void) { } GLuint ObjectID(void) const { return this->objectID; } bool ValidObject(void) const { return (this->objectID != 0); } virtual void Gen(void) = 0; virtual void Del(void) = 0; protected: GLuint objectID; }; class Bindable { public: Bindable(void) { this->bound = false; } void Bind(void) { this->bound = true; this->DoBind(); } void Unbind(void) { this->DoUnbind(); this->bound = false; } bool IsBound(void) const { return this->bound; } protected: bool bound; virtual void DoBind(void) = 0; virtual void DoUnbind(void) = 0; }; #endif __GL_OBJECT_H__ qutemol/vcg/wrap/gl/picking.h0000444000175000017500000001177610626503071014565 0ustar mbamba#pragma once /**************************************************************************** * VCGLib o o * * Visual and Computer Graphics Library o o * * _ O _ * * Copyright(C) 2004 \/)\/ * * Visual Computing Lab /\/| * * ISTI - Italian National Research Council | * * \ * * All rights reserved. * * * * 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. * * * * 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 (http://www.gnu.org/licenses/gpl.txt) * * for more details. * * * ****************************************************************************/ /**************************************************************************** This file contains two function providing the standard way to do picking using opendgl: - using the SELECT mode (first function) - using the depth buffer and gluUnproject (second function) History $Log: picking.h,v $ Revision 1.6 2007/05/28 07:35:21 fiorin Added std:: prefix to advance call Revision 1.5 2007/05/21 13:22:40 cignoni Corrected gcc compiling issues Revision 1.4 2006/10/27 08:55:15 fiorin Added type cast (in order to remove warnings) Revision 1.3 2006/02/28 13:25:48 ponchio for(ii... -> for(int ii Revision 1.2 2006/02/13 13:06:34 cignoni Removed glut. Added ifdef guards and namespace. Added bool return value to the pick function Revision 1.1 2005/12/03 09:36:28 ganovelli *** empty log message *** ****************************************************************************/ #ifndef WRAP_GL_PICKING_H #define WRAP_GL_PICKING_H #include namespace vcg { template int Pick( const int & x, const int &y, TO_PICK_CONT_TYPE &m, std::vector &result, void (draw_func)(typename TO_PICK_CONT_TYPE::value_type &), int width=4, int height=4) { result.clear(); long hits; int sz = int(m.size())*5; GLuint *selectBuf =new GLuint[sz]; glSelectBuffer(sz, selectBuf); glRenderMode(GL_SELECT); glInitNames(); /* Because LoadName() won't work with no names on the stack */ glPushName(-1); double mp[16]; GLint viewport[4]; glGetIntegerv(GL_VIEWPORT,viewport); glMatrixMode(GL_PROJECTION); glGetDoublev(GL_PROJECTION_MATRIX ,mp); glPushMatrix(); glLoadIdentity(); //gluPickMatrix(x, viewport[3]-y, 4, 4, viewport); gluPickMatrix(x, y, width, height, viewport); glMultMatrixd(mp); glMatrixMode(GL_MODELVIEW); glPushMatrix(); int cnt=0; typename TO_PICK_CONT_TYPE::iterator ei; for(ei=m.begin();ei!=m.end();++ei) { glLoadName(cnt); draw_func(*ei); cnt++; } glPopMatrix(); glMatrixMode(GL_PROJECTION); glPopMatrix(); glMatrixMode(GL_MODELVIEW); hits = glRenderMode(GL_RENDER); if (hits <= 0) return 0; std::vector< std::pair > H; for(int ii=0;ii(selectBuf[ii*4+1]/4294967295.0,selectBuf[ii*4+3])); } std::sort(H.begin(),H.end()); result.resize(H.size()); for(int ii=0;ii bool Pick(const int & x, const int &y, PointType &pp){ double res[3]; GLdouble mm[16],pm[16]; GLint vp[4]; glGetDoublev(GL_MODELVIEW_MATRIX,mm); glGetDoublev(GL_PROJECTION_MATRIX,pm); glGetIntegerv(GL_VIEWPORT,vp); float pix; glReadPixels(x,y,1,1,GL_DEPTH_COMPONENT,GL_FLOAT,&pix); GLfloat depthrange[2]={0,0}; glGetFloatv(GL_DEPTH_RANGE,depthrange); if(pix==depthrange[1]) return false; gluUnProject(x,y,pix,mm,pm,vp,&res[0],&res[1],&res[2]); pp=PointType (res[0],res[1],res[2]); return true; } } // end namespace #endif qutemol/vcg/wrap/gl/camera.h0000444000175000017500000010001410627513754014363 0ustar mbamba/**************************************************************************** * VCGLib o o * * Visual and Computer Graphics Library o o * * _ O _ * * Copyright(C) 2004 \/)\/ * * Visual Computing Lab /\/| * * ISTI - Italian National Research Council | * * \ * * All rights reserved. * * * * 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. * * * * 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 (http://www.gnu.org/licenses/gpl.txt) * * for more details. * * * ****************************************************************************/ /**************************************************************************** History $Log: camera.h,v $ Revision 1.15 2007/05/31 09:39:56 cignoni Small gcc compiling issues Revision 1.14 2006/12/18 16:02:57 matteodelle minor eroor correction on variable names Revision 1.13 2006/12/18 14:28:07 matteodelle *** empty log message *** Revision 1.12 2006/12/18 09:46:39 callieri camera+shot revamp: changed field names to something with more sense, cleaning of various functions, correction of minor bugs/incongruences, removal of the infamous reference in shot. Revision 1.11 2006/01/10 12:22:34 spinelli add namespace vcg:: Revision 1.10 2005/10/24 14:42:57 spinelli add namespace vcg:: to GetFrustum(...) Revision 1.9 2005/06/29 15:02:29 spinelli aggiunto: - static void CavalieriProj( .. ) - static void IsometricProj( .. ) modificato: - static void TransformGL( .. ) - static void SetSubView( .. ) Revision 1.8 2005/02/22 10:57:05 tommyfranken corrected some syntax errors in GetFrustum Revision 1.7 2005/02/21 18:11:47 ganovelli GetFrustum moved from gl/camera to math/camera.h Revision 1.6 2004/12/16 14:41:36 ricciodimare *** empty log message *** Revision 1.5 2004/12/16 11:08:35 ricciodimare Cambiato il nome del costruttore era rimasto quello vecchio... e tolti alcune righe di codice commentate Revision 1.4 2004/12/15 18:45:06 tommyfranken *** empty log message *** Revision 1.3 2004/11/03 09:38:21 ganovelli added SetSubView, some comment and put the class back(!) Revision 1.2 2004/10/05 19:04:44 ganovelli changed from classes to functions Revision 1.1 2004/09/15 22:59:13 ganovelli creation ****************************************************************************/ #ifndef __GL_CAMERA #define __GL_CAMERA // VCG #include // opengl #include template struct GlCamera{ typedef typename CameraType::ScalarType ScalarType; typedef typename CameraType::ScalarType S; /// returns the OpenGL 4x4 PROJECTION matrix that describes the camera (intrinsics) static vcg::Matrix44 MatrixGL(vcg::Camera & cam, vcg::Matrix44 &m) { glPushAttrib(GL_TRANSFORM_BIT); glMatrixMode(GL_PROJECTION); glPushMatrix(); glLoadIdentity(); TransformGL(cam); glGetv(GL_PROJECTION_MATRIX,&m[0][0]); glPopMatrix(); glPopAttrib(); return m; } /// set the OpenGL PROJECTION matrix for the Cavalieri projection static void SetGLCavalieriProj(float x1, float x2, float y1, float y2, float z1, float z2) { GLfloat cavalieri[16]; cavalieri[0] = 2.0f/(x2-x1); cavalieri[4] = 0; cavalieri[8] = (0.707106f * -2.0f)/(x2-x1); cavalieri[12] = (x2+x1)/(x2-x1); cavalieri[1] = 0; cavalieri[5] = 2.0/(y2-y1); cavalieri[9] = (0.707106f * -2.0f)/(y2-y1); cavalieri[13] = (y2+y1)/(y2-y1); cavalieri[2] = 0; cavalieri[6] = 0; cavalieri[10] = -2.0f/(z2-z1); cavalieri[14] = (z2+z1)/(z2-z1); cavalieri[3] = 0; cavalieri[7] = 0; cavalieri[11] = 0; cavalieri[15] = 1.0f; glLoadMatrixf(cavalieri); } /// set the OpenGL PROJECTION matrix for the Isometric projection static void SetGLIsometricProj(float x1, float x2, float y1, float y2, float z1, float z2) { GLfloat isometric[16]; isometric[0] = 1.6f/(x2-x1); isometric[4] = 0; isometric[8] = -1.6f/(x2-x1); isometric[12] = (x2+x1)/(x2-x1); isometric[1] = -1.0f/(y2-y1); isometric[5] = 2.0f/(y2-y1); isometric[9] = -1.0f/(y2-y1); isometric[13] = (y2+y1)/(y2-y1); isometric[2] = 0; isometric[6] = 0; isometric[10] = -2.0f/(z2-z1); isometric[14] = (z2+z1)/(z2-z1); isometric[3] = 0; isometric[7] = 0; isometric[11] = 0; isometric[15] = 1.0f; glLoadMatrixf(isometric); } /// get OpenGL-like frustum from a vcg camera (intrinsics) static void GetFrustum(vcg::Camera & intrinsics, S & sx,S & dx,S & bt,S & tp,S & f) { intrinsics.GetFrustum(sx,dx,bt,tp,f); } /// set the OpenGL PROJECTION matrix to match the camera (intrinsics). requires near and far plane static void TransformGL(vcg::Camera & camera, S nearDist, S farDist ) { S sx,dx,bt,tp,nr,fr; camera.GetFrustum(sx,dx,bt,tp,nr); assert(glGetError()==0); switch(camera.cameraType) { case vcg::PERSPECTIVE: glFrustum(sx,dx,bt,tp,nearDist,farDist); break; case vcg::ORTHO: glOrtho(sx,dx,bt,tp,nearDist,farDist); break; case vcg::ISOMETRIC: SetGLIsometricProj(sx,dx,bt,tp,nearDist,farDist); break; case vcg::CAVALIERI: SetGLCavalieriProj(sx,dx,bt,tp,nearDist,farDist); break; } assert(glGetError()==0); }; static void GetViewSize(vcg::Camera & camera, S &width, S &height) { S sx,dx,bt,tp,nr,fr; GetFrustum(camera,sx,dx,bt,tp,nr,fr); width = dx-sx; //right - left = width height = tp-bt; //top - bottom = height }; static void SetSubView(vcg::Camera & camera,vcg::Point2 p0,S nearDist, S farDist,vcg::Point2 p1){ //typedef typename CameraType::ScalarType S; S sx,dx,bt,tp,f; GetFrustum(camera,sx,dx,bt,tp,f); S width = dx-sx; //right - left = width S height = tp-bt; //top - bottom = height /*glFrustum( width* p0[0]+ sx, width* p1[0]+ sx, height* p0[1]+ bt, height* p1[1]+ bt, nr,fr);*/ switch(camera.cameraType) { case vcg::PERSPECTIVE: glFrustum( width* p0[0]+ sx, width* p1[0]+ sx, height* p0[1]+ bt, height* p1[1]+bt,nearDist,farDist); break; case vcg::ORTHO: glOrtho(width* p0[0]+sx, width* p1[0]+sx, height* p0[1]+ bt, height* p1[1]+bt,nearDist,farDist); break; //case vcg::ISOMETRIC: IsometricProj(dx-width* p1[0], dx-width* p0[0], tp-height* p1[1], tp-height* p0[1],nearDist,farDist); break; //case vcg::CAVALIERI: CavalieriProj(dx-width* p1[0], dx-width* p0[0], tp-height* p1[1], tp-height* p0[1],nearDist,farDist); break; } assert(glGetError()==0); }; }; #endif //private: // // static inline S SQRT( S x) { return sqrt(fabs(x)); } // static inline S CBRT ( S x ) // { // if (x == 0) return 0; // else if (x > 0) return pow (x, 1.0 / 3.0); // else return -pow (-x, 1.0 / 3.0); // } // static inline void SINCOS( S x, S & s, S & c) // { // s=sin(x); // c=cos(x); // } // static inline void SINCOSd( double x, double & s, double & c) // { // s=sin(x); // c=cos(x); // } // static inline S CUB( S x ) { return x*x*x; } // static inline S SQR( S x ) { return x*x; } // //public: // void undistorted_to_distorted_sensor_coord (S Xu, S Yu, S & Xd, S & Yd) const // { // const S SQRT3 = S(1.732050807568877293527446341505872366943); // S Ru,Rd,lambda,c,d,Q,R,D,S,T,sinT,cosT; // // if((Xu==0 && Yu==0) || k[0] == 0) // { // Xd = Xu; // Yd = Yu; // return; // } // // Ru = hypot (Xu, Yu); /* SQRT(Xu*Xu+Yu*Yu) */ // c = 1 / k[0]; // d = -c * Ru; // // Q = c / 3; // R = -d / 2; // D = CUB (Q) + SQR (R); // // if (D >= 0) /* one real root */ // { // D = SQRT (D); // S = CBRT (R + D); // T = CBRT (R - D); // Rd = S + T; // // if (Rd < 0) // Rd = SQRT (-1 / (3 * k[0])); // } // else /* three real roots */ // { // D = SQRT (-D); // S = CBRT (hypot (R, D)); // T = atan2 (D, R) / 3; // SINCOS (T, sinT, cosT); // // /* the larger positive root is 2*S*cos(T) */ // /* the smaller positive root is -S*cos(T) + SQRT(3)*S*sin(T) */ // /* the negative root is -S*cos(T) - SQRT(3)*S*sin(T) */ // Rd = -S * cosT + SQRT3 * S * sinT; /* use the smaller positive root */ // } // // lambda = Rd / Ru; // // Xd = Xu * lambda; // Yd = Yu * lambda; // } // // //void correction(double k, float i, float j, float &disi, float &disj) //{ // // (i,j) punto nell'immagine distorta // // (disi,disj) punto nell'immagine corretta (undistorted) // float hyp; // float I,J,ni,nj; // float ratio = 1; // // ni = i-viewport[0]/2; // nj = j-viewport[1]/2; // hyp = ni*ni + nj*nj; // // I = ni * (1+ k * hyp); // J = nj * (1+ k * hyp); // // disi = (I*ratio+viewport[0]/2); // disj = (J*ratio+viewport[1]/2); //} // // // //void distorsion( float k ,float i, float j,double & disi, double &disj) //{ // // (i,j) punto nell'immagine corretta (undistorted) // // (disi,disj) punto nell'immagine distorta // float hyp; // int _I,_J; // float I,J,ni,nj; // I = i-viewport[0]/2; // J = j-viewport[1]/2; // hyp = sqrt(I*I + J*J); // if((k==0.0) || (hyp <0.001)) // { // disi = i; // disj = j; // } // else // { // undistorted_to_distorted_sensor_coord (I, J, disi, disj); // disi += viewport[0]/2; // disj += viewport[1]/2; // // //// hyp = (viewport[0]*viewport[0] + viewport[1]*viewport[1])/4; //// ni = SX/2 + SX/2 * cam.k[0] * hyp; ///// nj = SY/2 + SY/2 * cam.k[0] * hyp; //// float ratio = sqrt(hyp/(ni*ni + nj*nj)); // float ratio=1; // // // // //----------- Maple // // float t0,t1,t2,sol; // // //t0 = 1/k*pow((108.0*hyp+12.0*sqrt(3.0)*sqrt((4.0+27.0*hyp*hyp*k)/k))*k*k,0.3333333333333333)/6.0-2.0/pow((108.0*hyp+12.0*sqrt(3.0)*sqrt((4.0+27.0*hyp*hyp*k)/k))*k*k,0.3333333333333333); // // // //t1 = -1/k*pow((108.0*hyp+12.0*sqrt(3.0)*sqrt((4.0+27.0*hyp*hyp*k)/k))*k*k,0.3333333333333333)/12.0+1/pow((108.0*hyp+12.0*sqrt(3.0)*sqrt((4.0+27.0*hyp* // //hyp*k)/k))*k*k,0.3333333333333333)+sqrt(-1.0)*sqrt(3.0)*(1/k*pow((108.0*hyp+ // //12.0*sqrt(3.0)*sqrt((4.0+27.0*hyp*hyp*k)/k))*k*k,0.3333333333333333)/6.0+2.0/ // //pow((108.0*hyp+12.0*sqrt(3.0)*sqrt((4.0+27.0*hyp*hyp*k)/k))*k*k, // //0.3333333333333333))/2.0; // // //t2 = -1/k*pow((108.0*hyp+12.0*sqrt(3.0)*sqrt((4.0+27.0*hyp*hyp*k)/k))*k*k,0.3333333333333333)/12.0+1/pow((108.0*hyp+12.0*sqrt(3.0)*sqrt((4.0+27.0*hyp* // //hyp*k)/k))*k*k,0.3333333333333333)-sqrt(-1.0)*sqrt(3.0)*(1/k*pow((108.0*hyp+ // //12.0*sqrt(3.0)*sqrt((4.0+27.0*hyp*hyp*k)/k))*k*k,0.3333333333333333)/6.0+2.0/ // //pow((108.0*hyp+12.0*sqrt(3.0)*sqrt((4.0+27.0*hyp*hyp*k)/k))*k*k, // //0.3333333333333333))/2.0; // // //sol = (t0>t1)?t0:t1; // //sol = (sol (i/(double)(si-1),j/(double)(sj-1)); // { // double disi,disj; // distorsion( k[0] ,(i/(double)(si-1))*viewport[0], (j/(double)(sj-1))*viewport[1],disi,disj); // gridMap[i][j] = Point2 (disi/viewport[0],disj/viewport[1]); // } // } // // inline Camera() // { // k[0]=k[1]=k[2]=k[3]=0.0; // valid = false; // ortho = false; // ResizeGridMap(100,100);// da spostare altrove // } // // inline bool IsValid() // { // return valid; // } // // inline bool IsOrtho() const // { // return ortho; // } // // inline void SetInvalid() // { // valid = false; // } // // inline void SetOrtho(bool isOrtho=true) // { // ortho = isOrtho; // } // // // Genera una camera standard // void Standard() // { // valid = true; // ortho = false; // view_p = vectorial(0,0,0); // x_axis = vectorial(1,0,0); // y_axis = vectorial(0,1,0); // z_axis = vectorial(0,0,1); // f = 25.75; // s = Point2(0.0074,0.0074); // c = Point2(320,240); // viewport[0] = 640; // viewport[1] = 480; // k[0] = 0; // k[1] = 0; // k[2] = 0; // k[3] = 0; // } // // // Trasla la camera (world coordinate) // inline void Translate( const vectorial & t ) // { // view_p += t; // } // // // Trasla la camera (camera coordinate) // inline void Move( const vectorial & t ) // { // view_p+= x_axis * t[0]+y_axis * t[1] + z_axis * t[2]; // } // // // scala la camera // inline void Scale(const scalar & sc){ // view_p *=sc; // s[0]*=sc; // s[1]*=sc; // f*=sc; // //printf("sc\n"); // } // // // // // NOTA funziona solo se l'ultima colonna di m e' 0,0,0,1 // void Apply( const Matrix44 & m ) // { // // Passo 1: calcolo pseudo inversa di m // S s11,s12,s13; // S s21,s22,s23; // S s31,s32,s33; // S s41,s42,s43; // // { // S t4 = m[0][0]*m[1][1]; // S t6 = m[0][0]*m[2][1]; // S t8 = m[1][0]*m[0][1]; // S t10 = m[1][0]*m[2][1]; // S t12 = m[2][0]*m[0][1]; // S t14 = m[2][0]*m[1][1]; // S t17 = 1/(t4*m[2][2]-t6*m[1][2]-t8*m[2][2]+t10*m[0][2]+t12*m[1][2]-t14*m[0][2]); // S t27 = m[1][0]*m[2][2]; // S t28 = m[2][0]*m[1][2]; // S t31 = m[0][0]*m[2][2]; // S t32 = m[2][0]*m[0][2]; // S t35 = m[0][0]*m[1][2]; // S t36 = m[1][0]*m[0][2]; // S t49 = m[3][0]*m[1][1]; // S t51 = m[3][0]*m[2][1]; // S t59 = m[3][0]*m[0][1]; // s11 = -(-m[1][1]*m[2][2]+m[2][1]*m[1][2])*t17; // s12 = -( m[0][1]*m[2][2]-m[2][1]*m[0][2])*t17; // s13 = ( m[0][1]*m[1][2]-m[1][1]*m[0][2])*t17; // s21 = (-t27+t28)*t17; // s22 = -(-t31+t32)*t17; // s23 = -( t35-t36)*t17; // s31 = -(-t10+t14)*t17; // s32 = (-t6 +t12)*t17; // s33 = ( t4 -t8 )*t17; // s41 = -(t10*m[3][2]-t27*m[3][1]-t14*m[3][2]+t28*m[3][1]+t49*m[2][2]-t51*m[1][2])*t17; // s42 = -(-t6*m[3][2]+t31*m[3][1]+t12*m[3][2]-t32*m[3][1]-t59*m[2][2]+t51*m[0][2])*t17; // s43 = (-t4*m[3][2]+t35*m[3][1]+t8 *m[3][2]-t36*m[3][1]-t59*m[1][2]+t49*m[0][2])*t17; // 1.0; // } // // //Matrix44 t2 = tt*m; // //print(t2); // // Fase 2: Calcolo nuovo punto di vista // { // S t1 = view_p[2]*s31; // S t3 = view_p[2]*s21; // S t5 = s43*s21; // S t7 = s43*s31; // S t9 = view_p[1]*s31; // S t11 = view_p[1]*s21; // S t13 = s42*s31; // S t15 = s42*s21; // S t17 = view_p[0]*s32; // S t19 = view_p[0]*s22; // S t21 = s41*s32; // S t23 = s41*s22; // S t25 = -t1*s22+t3*s32-t5*s32+t7*s22+t9*s23-t11*s33-t13*s23+t15*s33-t17*s23+t19*s33+t21*s23-t23*s33; // S t39 = 1/(s11*s22*s33-s11*s32*s23-s21*s12*s33+s21*s32*s13+s31*s12*s23-s31*s22*s13); // S t41 = view_p[0]*s12; // S t45 = s41*s12; // S t47 = view_p[2]*s11; // S t50 = s43*s11; // S t53 = view_p[1]*s11; // S t56 = s42*s11; // S t59 = t41*s33-t17*s13+t21*s13-t45*s33+t47*s32-t1*s12-t50*s32+t7*s12-t53*s33+t9*s13+t56*s33-t13*s13; // S t73 = t15*s13-t56*s23+t19*s13-t41*s23-t23*s13+t45*s23-t11*s13+t53*s23+t3*s12-t47*s22-t5*s12+t50*s22; // // view_p[0] = t25*t39; // view_p[1] = -t59*t39; // view_p[2] = -t73*t39; // } // // // Fase 3: Calcol nuovo sistema di riferimento // { // S A00 = s11*x_axis[0]+s12*x_axis[1]+s13*x_axis[2]; // S A01 = s11*y_axis[0]+s12*y_axis[1]+s13*y_axis[2]; // S A02 = s11*z_axis[0]+s12*z_axis[1]+s13*z_axis[2]; // // S A03 = 0.0; // S A10 = s21*x_axis[0]+s22*x_axis[1]+s23*x_axis[2]; // S A11 = s21*y_axis[0]+s22*y_axis[1]+s23*y_axis[2]; // S A12 = s21*z_axis[0]+s22*z_axis[1]+s23*z_axis[2]; // // S A13 = 0.0; // S A20 = s31*x_axis[0]+s32*x_axis[1]+s33*x_axis[2]; // S A21 = s31*y_axis[0]+s32*y_axis[1]+s33*y_axis[2]; // S A22 = s31*z_axis[0]+s32*z_axis[1]+s33*z_axis[2]; // // x_axis[0] = A00; x_axis[1] = A10; x_axis[2] = A20; // y_axis[0] = A01; y_axis[1] = A11; y_axis[2] = A21; // z_axis[0] = A02; z_axis[1] = A12; z_axis[2] = A22; // // S A1[2][3] = 0.0; // // S A1[3][0] = 0.0; // // S A1[3][1] = 0.0; // // S A1[3][2] = 0.0; // // S A1[3][3] = 1.0; // } // } // // /* // // Applica una trasformazione // void Apply( const Matrix44 & m ) // { // Point3 tx = view_p+x_axis; // Point3 ty = view_p+y_axis; // Point3 tz = view_p+z_axis; // // view_p = m.Apply(view_p); // // x_axis = m.Apply(tx) - view_p; // y_axis = m.Apply(ty) - view_p; // z_axis = m.Apply(tz) - view_p; // } // // // Applica una trasformazione ma bene! // void Stable_Apply( const Matrix44 & m ) // { // Point3 tx = view_p+x_axis; // Point3 ty = view_p+y_axis; // Point3 tz = view_p+z_axis; // // view_p = m.Stable_Apply(view_p); // // x_axis = m.Stable_Apply(tx) - view_p; // y_axis = m.Stable_Apply(ty) - view_p; // z_axis = m.Stable_Apply(tz) - view_p; // } // // */ // // void Project( const vectorial & p, Point2 & q ) const // { // vectorial dp = p - view_p; // S dx = dp*x_axis; // S dy = dp*y_axis; // S dz = dp*z_axis; // // S tx = dx; // S ty = -dy; // S qx,qy; // // // nota: per le camere ortogonali viewportM vale 1 // if(!IsOrtho()) // { // tx *= f/dz; // ty *= f/dz; // // undistorted_to_distorted_sensor_coord(tx,ty,qx,qy); // // q[0] = qx/s[0]+c[0]; // q[1] = qy/s[1]+c[1]; // } // else // { // q[0] = tx/(s[0]*viewportM)+c[0]; // q[1] = ty/(s[1]*viewportM)+c[1]; // } // } // //#if 1 // void Show( FILE * fp ) // { // if(valid) // fprintf(fp, // "posiz.: %g %g %g\n" // "x axis: %g %g %g\n" // "y axis: %g %g %g\n" // "z axis: %g %g %g\n" // "focal : %g scale: %g %g center: %g %g\n" // "viewp.: %d %d distorsion: %g %g %g %g\n" // ,view_p[0],view_p[1],view_p[2] // ,x_axis[0],x_axis[1],x_axis[2] // ,y_axis[0],y_axis[1],y_axis[2] // ,z_axis[0],z_axis[1],z_axis[2] // ,f,s[0],s[1],c[0],c[1] // ,viewport[0],viewport[1],k[0],k[1],k[2],k[3] // ); // else // fprintf(fp,"Invalid\n"); // } //#endif // // // Legge una camera in descrizione tsai binario // static void load_tsai_bin (FILE *fp, tsai_camera_parameters *cp, tsai_calibration_constants *cc) // { // double sa, // ca, // sb, // cb, // sg, // cg; // // fread(&(cp->Ncx),sizeof(double),1,fp); // fread(&(cp->Nfx),sizeof(double),1,fp); // fread(&(cp->dx),sizeof(double),1,fp); // fread(&(cp->dy),sizeof(double),1,fp); // fread(&(cp->dpx),sizeof(double),1,fp); // fread(&(cp->dpy),sizeof(double),1,fp); // fread(&(cp->Cx),sizeof(double),1,fp); // fread(&(cp->Cy),sizeof(double),1,fp); // fread(&(cp->sx),sizeof(double),1,fp); // // fread(&(cc->f),sizeof(double),1,fp); // fread(&(cc->kappa1),sizeof(double),1,fp); // fread(&(cc->Tx),sizeof(double),1,fp); // fread(&(cc->Ty),sizeof(double),1,fp); // fread(&(cc->Tz),sizeof(double),1,fp); // fread(&(cc->Rx),sizeof(double),1,fp); // fread(&(cc->Ry),sizeof(double),1,fp); // fread(&(cc->Rz),sizeof(double),1,fp); // // // SINCOSd (cc->Rx, sa, ca); // SINCOSd (cc->Ry, sb, cb); // SINCOSd (cc->Rz, sg, cg); // // cc->r1 = cb * cg; // cc->r2 = cg * sa * sb - ca * sg; // cc->r3 = sa * sg + ca * cg * sb; // cc->r4 = cb * sg; // cc->r5 = sa * sb * sg + ca * cg; // cc->r6 = ca * sb * sg - cg * sa; // cc->r7 = -sb; // cc->r8 = cb * sa; // cc->r9 = ca * cb; // // fread(&(cc->p1),sizeof(double),1,fp); // fread(&(cc->p2),sizeof(double),1,fp); // } // // void load_tsai (FILE *fp, tsai_camera_parameters *cp, tsai_calibration_constants *cc) // { // double sa, // ca, // sb, // cb, // sg, // cg; // // fscanf (fp, "%lf", &(cp->Ncx)); // fscanf (fp, "%lf", &(cp->Nfx)); // fscanf (fp, "%lf", &(cp->dx)); // fscanf (fp, "%lf", &(cp->dy)); // fscanf (fp, "%lf", &(cp->dpx)); // fscanf (fp, "%lf", &(cp->dpy)); // fscanf (fp, "%lf", &(cp->Cx)); // fscanf (fp, "%lf", &(cp->Cy)); // fscanf (fp, "%lf", &(cp->sx)); // // fscanf (fp, "%lf", &(cc->f)); // fscanf (fp, "%lf", &(cc->kappa1)); // fscanf (fp, "%lf", &(cc->Tx)); // fscanf (fp, "%lf", &(cc->Ty)); // fscanf (fp, "%lf", &(cc->Tz)); // fscanf (fp, "%lf", &(cc->Rx)); // fscanf (fp, "%lf", &(cc->Ry)); // fscanf (fp, "%lf", &(cc->Rz)); // // SINCOSd (cc->Rx, sa, ca); // SINCOSd (cc->Ry, sb, cb); // SINCOSd (cc->Rz, sg, cg); // // cc->r1 = cb * cg; // cc->r2 = cg * sa * sb - ca * sg; // cc->r3 = sa * sg + ca * cg * sb; // cc->r4 = cb * sg; // cc->r5 = sa * sb * sg + ca * cg; // cc->r6 = ca * sb * sg - cg * sa; // cc->r7 = -sb; // cc->r8 = cb * sa; // cc->r9 = ca * cb; // // fscanf (fp, "%lf", &(cc->p1)); // fscanf (fp, "%lf", &(cc->p2)); // } // // // Importa una camera dal formato tsai // void import( const tsai_camera_parameters & cp, // const tsai_calibration_constants & cc, // const int image_viewport[2] // ) // { // assert(!IsOrtho()); // valid = true; // x_axis[0] = cc.r1; x_axis[1] = cc.r2; x_axis[2] = cc.r3; // y_axis[0] = cc.r4; y_axis[1] = cc.r5; y_axis[2] = cc.r6; // z_axis[0] = cc.r7; z_axis[1] = cc.r8; z_axis[2] = cc.r9; // // view_p[0] = - (cc.Tx * x_axis[0] + cc.Ty * y_axis[0] + cc.Tz * z_axis[0]); // view_p[1] = - (cc.Tx * x_axis[1] + cc.Ty * y_axis[1] + cc.Tz * z_axis[1]); // view_p[2] = - (cc.Tx * x_axis[2] + cc.Ty * y_axis[2] + cc.Tz * z_axis[2]); // // s[0] = cp.dpx/cp.sx; // s[1] = cp.dpy; // c[0] = cp.Cx; // c[1] = cp.Cy; // // f = cc.f; // viewport[0] = image_viewport[0]; // viewport[1] = image_viewport[1]; // // k[0] = cc.kappa1; // k[1] = cc.kappa1; // k[2] = 0; // k[2] = 0; // } // // // Esporta una camera in formato tsai // void export( tsai_camera_parameters & cp, // tsai_calibration_constants & cc, // int image_viewport[2] // ) // { // assert(!IsOrtho()); // cc.r1 = x_axis[0]; cc.r2 = x_axis[1]; cc.r3= x_axis[2] ; // cc.r4 = y_axis[0]; cc.r5 = y_axis[1]; cc.r6= y_axis[2] ; // cc.r7 = z_axis[0]; cc.r8 = z_axis[1]; cc.r9= z_axis[2] ; // // cc.Tx = - (view_p[0] * x_axis[0] + view_p[1] * x_axis[1] + view_p[2] * x_axis[2]); // cc.Ty = - (view_p[0] * y_axis[0] + view_p[1] * y_axis[1] + view_p[2] * y_axis[2]); // cc.Tz = - (view_p[0] * z_axis[0] + view_p[1] * z_axis[1] + view_p[2] * z_axis[2]); // // cp.dpx = s[0]; // cp.dpy = s[1]; // // cp.Cx= c[0] ; // cp.Cy= c[1] ; // cp.sx= 1; // // cc.f= f ; // // image_viewport[0] = viewport[0]; // image_viewport[1] = viewport[1]; // // cc.kappa1= k[0] ; // cc.kappa1= k[1] ; // } // // // void Save(FILE * out) // { // fprintf(out,"VIEW_POINT %f %f %f\n", view_p[0],view_p[1],view_p[2]); // fprintf(out,"X_AXIS %f %f %f\n", x_axis[0],x_axis[1],x_axis[2]); // fprintf(out,"Y_AXIS %f %f %f\n", y_axis[0],y_axis[1],y_axis[2]); // fprintf(out,"Z_AXIS %f %f %f\n", z_axis[0],z_axis[1],z_axis[2]); // fprintf(out,"FOCUS_LENGHT %f \n", f); // fprintf(out,"SCALE %f %f \n", s[0], s[1]); // fprintf(out,"VIEWPORT %d %d \n", viewport[0], viewport[1]); // fprintf(out,"VIEWPORTM %f\n", viewportM); // fprintf(out,"RADIAL_DISTORSION %.10g %.10g \n", k[0],k[1]); // fprintf(out,"CENTER %f %f \n", c[0], c[1]); // fprintf(out,"IS_VALID %d\n", IsValid()); // fprintf(out,"END_CAMERA\n"); // } // // void Load(FILE * in) // { // char row[255]; // Standard(); // while(!feof(in)) // { // fscanf(in,"%s",row); // if(strcmp(row,"VIEW_POINT")==0) // fscanf(in,"%lg %lg %lg",&view_p[0],&view_p[1],&view_p[2]); // else // if(strcmp(row,"X_AXIS")==0) // fscanf(in,"%lg %lg %lg",& x_axis[0],&x_axis[1],&x_axis[2]); // else // if(strcmp(row,"Y_AXIS")==0) // fscanf(in,"%lg %lg %lg",& y_axis[0],&y_axis[1],&y_axis[2]); // else // if(strcmp(row,"Z_AXIS")==0) // fscanf(in,"%lg %lg %lg",& z_axis[0],&z_axis[1],&z_axis[2]); // else // if(strcmp(row,"FOCUS_LENGHT")==0) // fscanf(in,"%lg",&f); // else // if(strcmp(row,"SCALE")==0) // fscanf(in,"%lg %lg",&s[0],&s[1]); // else // if(strcmp(row,"VIEWPORT")==0) // fscanf(in,"%d %d", &viewport[0],&viewport[1]); // else // if(strcmp(row,"VIEWPORTM")==0) // fscanf(in,"%f", &viewportM); // else // if(strcmp(row,"CENTER")==0) // fscanf(in,"%lg %lg", &c[0],&c[1]); // else // if(strcmp(row,"RADIAL_DISTORSION")==0) // fscanf(in,"%lg %lg", &k[0],&k[1]); // else // if(strcmp(row,"IS_VALID")==0) // fscanf(in,"%d",&valid); // if(strcmp(row,"END_CAMERA")==0) // break; // } // } // //#ifdef __GL_H__ // //// Prende in ingresso il bounding box dell'oggetto da inquadrare e setta projection e modelmatrix //// in modo da matchare il piu' possibile quelle della camera. Ovviamente (?) si ignora le distorsioni radiali. //// Nota che bb viene utilizzato solo per settare i near e far plane in maniera sensata. //void SetGL(const Box3 &bb,scalar subx0=0, scalar subx1=1,scalar suby0=0,scalar suby1=1) //{ // scalar _,__; // SetGL(_,__,bb,subx0, subx1, suby0, suby1); // //} // //void SetGL(scalar &znear, scalar &zfar,const Box3 &bb,scalar subx0=0, // scalar subx1=1,scalar suby0=0,scalar suby1=1) //{ // glMatrixMode(GL_PROJECTION); // glLoadIdentity(); // scalar left,right; // scalar bottom, top; // scalar w,h; // // // La lunghezza focale e' la distanza del piano immagine dal centro di proiezione. // // il che mappa direttamente nella chiamata glFrustum che prende in ingresso // // le coordinate del piano immagine posto a znear. // // float imleft =-c[0]*s[0]; // float imright =(viewport[0]-c[0])*s[0]; // float imbottom =-c[1]*s[1]; // float imtop =(viewport[1]-c[1])*s[1]; // znear = Distance(view_p, bb.Center())-bb.Diag(); // zfar = Distance(view_p, bb.Center())+bb.Diag(); // // w=imright-imleft; // h=imtop-imbottom; // // // Quindi il frustum giusto sarebbe questo, // // glFrustum(imleft, imright, imbottom, imtop, f, zfar); // // ma per amor di opengl conviene spostare il near plane fino ad essere vicino all'oggetto da inquadrare. // // Cambiare f significa amplificare in maniera proporzionale anche i left right ecc. // // // 8/5/02 Nota che il near plane va spostato verso l'oggetto solo se quello calcolato sopra e' maggiore di 'f' // // nota che potrebbe anche succedere che znear <0 (viewpoint vicino ad un oggetto con il bb allungato); // if(znear c, scalar RadAngle) //{ // Point3 rnd(1.0 - 2.0*scalar(rand())/RAND_MAX, // 1.0 - 2.0*scalar(rand())/RAND_MAX, // 1.0 - 2.0*scalar(rand())/RAND_MAX); // rnd.Normalize(); // Matrix44 m,t0,t1,tr; // Point3 axis = rnd ^ (view_p-c).Normalize(); // scalar RadRandAngle=RadAngle*(1.0 - 2.0*scalar(rand())/RAND_MAX); // t0.Translate(c); // t1.Translate(-c); // m.Rotate(ToDeg(RadRandAngle),axis); // tr=t1*m*t0; // Apply(tr); //} // // // // //void glTexGen(int offx =0, // angolo basso sinistra della // int offy=0, // subtexture per la quale si vogliono settare le coordinate // int sx=1, // Dimensioni in Texel // int sy=1, // int Tx=1, // Dimensioni della texture // int Ty=1) //{ // // prendi la rototraslazione che // // trasforma la coordinata nel // // sistema di coordinate della camera // Matrix44d M; // M[0][0] = x_axis[0]; // M[0][1] = x_axis[1]; // M[0][2] = x_axis[2]; // M[0][3] = -view_p* x_axis ; // // M[1][0] = y_axis[0]; // M[1][1] = y_axis[1]; // M[1][2] = y_axis[2]; // M[1][3] = -view_p* y_axis; // // M[2][0] = z_axis[0]; // M[2][1] = z_axis[1]; // M[2][2] = z_axis[2]; // M[2][3] = -view_p* z_axis; // // M[3][0] = 0.0; // M[3][1] = 0.0; // M[3][2] = 0.0; // M[3][3] = 1.0; // // // prendi la matrice di proiezione // Matrix44d P; // P.Zero(); // // if(!IsOrtho())// prospettica // { // // P[0][0] = sx/(s[0]*viewport[0]*Tx); // P[0][2] = (1/f)*(offx+0.5*sx)/Tx; // // P[1][1] = sy/(s[1]* viewport[1]*Ty); // P[1][2] = (1/f)*(offy+0.5*sy)/Ty; // // P[2][2] = 1; // P[3][2] = 1/f; // } // else // ortogonale // { // P[0][0] = sx/(s[0]*viewport[0]*viewportM*Tx); // P[0][3] = (offx+0.5*sx)/Tx; // l'effetto e' una traslazione di +1/2 // // P[1][1] = sy/(s[1]* viewport[1]*viewportM*Ty); // P[1][3] = (offy+0.5*sy)/Ty; // l'effetto e' una traslazione di +1/2 // // P[2][2] = 1; // P[3][3] = 1; // } // // componi // Matrix44d PM = P*M; // // glTexGend(GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR); // glTexGend(GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR); // glTexGend(GL_Q, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR); // // glTexGendv(GL_S,GL_OBJECT_PLANE,&PM[0][0]); // glTexGendv(GL_T,GL_OBJECT_PLANE,&PM[1][0]); // glTexGendv(GL_Q,GL_OBJECT_PLANE,&PM[3][0]); // // glEnable(GL_TEXTURE_GEN_S); // glEnable(GL_TEXTURE_GEN_T); // glDisable(GL_TEXTURE_GEN_R); // glEnable(GL_TEXTURE_GEN_Q); //} // //// versione per le texture rettangolare NV_TEXTURE_RECTANGLE //// la differenza da glTexGen e' che il mapping e' in [0..sx]X[0..sy] //void glTexGen_NV(int sx, // Texture Size // int sy) //{ // // prendi la rototraslazione che // // trasforma la coordinata nel // // sistema di coordinate della camera // Matrix44d M; // M[0][0] = x_axis[0]; // M[0][1] = x_axis[1]; // M[0][2] = x_axis[2]; // M[0][3] = -view_p* x_axis ; // // M[1][0] = y_axis[0]; // M[1][1] = y_axis[1]; // M[1][2] = y_axis[2]; // M[1][3] = -view_p* y_axis; // // M[2][0] = z_axis[0]; // M[2][1] = z_axis[1]; // M[2][2] = z_axis[2]; // M[2][3] = -view_p* z_axis; // // M[3][0] = 0.0; // M[3][1] = 0.0; // M[3][2] = 0.0; // M[3][3] = 1.0; // // // prendi la matrice di proiezione // Matrix44d P; // P.Zero(); // // if(!IsOrtho())// prospettica // { // // P[0][0] = sx/(s[0]*viewport[0]); // P[0][2] = sx*(1/f)*( 0.5); // // P[1][1] = sy/(s[1]* viewport[1] ); // P[1][2] = sy*(1/f)*( 0.5); // // P[2][2] = 1; // P[3][2] = 1/f; // } // else // ortogonale // { // P[0][0] = sx/(s[0]*viewport[0]*viewportM); // P[0][3] = sx* 0.5 ; // l'effetto e' una traslazione di +1/2 // // P[1][1] = sy/(s[1]* viewport[1]*viewportM); // P[1][3] = sy* 0.5 ; // l'effetto e' una traslazione di +1/2 // // P[2][2] = 1; // P[3][3] = 1; // } // // componi // Matrix44d PM = P*M; // // glTexGend(GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR); // glTexGend(GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR); // glTexGend(GL_Q, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR); // // glTexGendv(GL_S,GL_OBJECT_PLANE,&PM[0][0]); // glTexGendv(GL_T,GL_OBJECT_PLANE,&PM[1][0]); // glTexGendv(GL_Q,GL_OBJECT_PLANE,&PM[3][0]); // // glEnable(GL_TEXTURE_GEN_S); // glEnable(GL_TEXTURE_GEN_T); // glDisable(GL_TEXTURE_GEN_R); // glEnable(GL_TEXTURE_GEN_Q); //// glDisable(GL_TEXTURE_GEN_Q); // //} //#endif // __GL_H__ // //}; //} // End namespace vcg qutemol/vcg/wrap/callback.h0000444000175000017500000000540710075461727014276 0ustar mbamba/**************************************************************************** * VCGLib o o * * Visual and Computer Graphics Library o o * * _ O _ * * Copyright(C) 2004 \/)\/ * * Visual Computing Lab /\/| * * ISTI - Italian National Research Council | * * \ * * All rights reserved. * * * * 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. * * * * 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 (http://www.gnu.org/licenses/gpl.txt) * * for more details. * * * ****************************************************************************/ /**************************************************************************** History $Log: callback.h,v $ Revision 1.4 2004/07/15 11:00:39 ganovelli added interruptible callback Revision 1.3 2004/05/12 10:18:55 ganovelli new line added at the end of file Revision 1.2 2004/05/10 14:26:33 ganovelli argument name removed to avoid "unreference variable"warning Revision 1.1 2004/03/03 15:00:51 cignoni Initial commit ****************************************************************************/ #ifndef __VCGLIB_CALLBACK #define __VCGLIB_CALLBACK namespace vcg { // Generic Callback function: // Used to make algorithms interumpable // Return value: true continue, false break // The second callback is to know where we are (useful for progress bar) typedef bool CallBack( const char * str ); typedef bool CallBackPos(const int pos, const char * str ); inline bool DummyCallBack( const char * ) {return true;} inline bool DummyCallBackPos(const int , const char * ) {return true;} /// interruptible function typedef void TaskFunc(int t,void * contest); } // End namespace #endif qutemol/vcg/wrap/io_trimesh/0000755000175000017500000000000011633404241014514 5ustar mbambaqutemol/vcg/wrap/io_trimesh/export_iv.h0000444000175000017500000000612610023433227016705 0ustar mbamba/**************************************************************************** * VCGLib o o * * Visual and Computer Graphics Library o o * * _ O _ * * Copyright(C) 2004 \/)\/ * * Visual Computing Lab /\/| * * ISTI - Italian National Research Council | * * \ * * All rights reserved. * * * * 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. * * * * 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 (http://www.gnu.org/licenses/gpl.txt) * * for more details. * * * ****************************************************************************/ /** Function to save in Inventor format file. @param filename Name of the new inventor file */ void Save_Iv(const char * filename) { FILE *fp; fp = fopen(filename,"wb"); fprintf(fp,"#Inventor V2.1 ascii \n" ); fprintf(fp," \n" ); fprintf(fp,"Separator { \n " ); fprintf(fp,"ShapeHints {\n"); fprintf(fp,"vertexOrdering COUNTERCLOCKWISE\n"); fprintf(fp,"shapeType UNKNOWN_SHAPE_TYPE\n"); fprintf(fp,"}\n"); fprintf(fp,"MaterialBinding {\n"); fprintf(fp," value PER_FACE\n"); fprintf(fp,"}\n"); fprintf(fp,"Material{\n"); fprintf(fp," diffuseColor [\n"); fprintf(fp," ]\n"); fprintf(fp,"}\n"); fprintf(fp,"Coordinate3 { \n " ); fprintf(fp,"point [ " ); face_iterator fi; vertex_iterator vi; map index; int ind; for(ind=0,vi=vert.begin(); vi!=vert.end(); ++vi,++ind) { fprintf(fp,"%f%s",(*vi).P()[0]," " ); fprintf(fp,"%f%s",(*vi).P()[1]," " ); fprintf(fp,"%f%s",(*vi).P()[2],",\n"); index[&*vi] = ind; } fprintf(fp," ] \n" ); fprintf(fp,"} \n" ); fprintf(fp,"IndexedFaceSet { \n" ); fprintf(fp,"coordIndex [ " ); for (fi=face.begin(); fi!=face.end(); ++fi) { for (int j = 0; j < 3; j++) fprintf(fp,"%i%s",index[(*fi).V(j)],", "); fprintf(fp,"%s","-1, \n"); } fprintf(fp," ] \n" ); fprintf(fp," } \n" ); fprintf(fp," } \n" ); fclose(fp); } qutemol/vcg/wrap/io_trimesh/import_ptx.h0000444000175000017500000006036310705165375017113 0ustar mbamba/**************************************************************************** * VCGLib o o * * Visual and Computer Graphics Library o o * * _ O _ * * Copyright(C) 2004 \/)\/ * * Visual Computing Lab /\/| * * ISTI - Italian National Research Council | * * \ * * All rights reserved. * * * * 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. * * * * 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 (http://www.gnu.org/licenses/gpl.txt) * * for more details. * * * ****************************************************************************/ /**************************************************************************** History $Log: import_ptx.h,v $ Revision 1.7 2007/10/16 16:46:53 cignoni Added Allocator::DeleteFace and Allocator::DeleteVertex; Now the use of SetD() should be deprecated. Revision 1.6 2006/11/28 11:36:25 cignoni Removed nonstandard include io.h Revision 1.5 2006/11/21 22:34:58 cignoni small gcc compiling issues Revision 1.4 2006/11/21 19:23:50 e_cerisoli Added comments for documentation ****************************************************************************/ #ifndef __VCGLIB_IMPORT_PTX #define __VCGLIB_IMPORT_PTX #include #include #include #include #include #include namespace vcg { namespace tri { namespace io { /** This class encapsulate a filter for importing ptx meshes. */ template class ImporterPTX { public: enum PTX_OPEN_MASK_ENUM { PTX_ONLY_POINTS = 0x08000000, //BIT_27 no add faces (PTX_FLIPFACES and PTX_SWITCHSIDE are ignored!) PTX_COLOR = 0x10000000, //BIT_28 must be VertexType::HasColor(); PTX_COMPUTE_AABBOX = 0x20000000, //BIT_29 compute axis aligned bbox PTX_FLIPFACES = 0x40000000, //BIT_30 flip all faces ( PTX_ONLY_POINTS must be false ) PTX_SWITCHSIDE = 0x80000000 //BIT_31 inverse triangulation order (swaping row->cols) ( PTX_ONLY_POINTS must be false ) }; typedef typename OpenMeshType::VertexPointer VertexPointer; typedef typename OpenMeshType::ScalarType ScalarType; typedef typename OpenMeshType::VertexType VertexType; typedef typename OpenMeshType::FaceType FaceType; typedef typename OpenMeshType::VertexIterator VertexIterator; typedef typename OpenMeshType::FaceIterator FaceIterator; struct RANGEMAP_INFO { fpos_t pos; int vn; int fn; }; typedef typename std::vector< RANGEMAP_INFO > RANGEMAP_INFO_TABLE; struct PTX_HEAD_INFO { int vn; int fn; RANGEMAP_INFO_TABLE rmapInfo; }; /// Standard call for knowing the meaning of an error code static const char *ErrorMsg(int error) { static const char * ptx_error_msg[] = { "No errors", "Can't open file", "Header not found", "Eof in header", "Format not found", "Syntax error on header", }; if(error>6 || error<0) return "Unknown error"; else return ptx_error_msg[error]; }; static bool skipmesh(FILE* fp, CallBackPos *cb=NULL) { PTX_HEAD_INFO tab; return skipmesh(fp, cb); } static bool skipmesh(FILE* fp, PTX_HEAD_INFO & tab, CallBackPos *cb=NULL) { int colnum; int rownum; int skiplines; char linebuf; if(feof(fp)) return false; RANGEMAP_INFO ptxInfo; fgetpos(fp, &ptxInfo.pos ); // getting mesh size; fscanf(fp,"%i\n",&colnum); fscanf(fp,"%i\n",&rownum); ptxInfo.vn = rownum*colnum; ptxInfo.fn = (rownum-1) * (colnum-1) * 2; char tmp[255]; sprintf(tmp, "PTX Mesh analysis... mesh %i vert %i face %i", (int)tab.rmapInfo.size(), ptxInfo.vn, ptxInfo.fn); if ( ( colnum <=0 ) || ( rownum <=0 ) ) return false; if(feof(fp)) return false; if(cb) cb( rand()%100, tmp); skiplines = (colnum * rownum) + 8; // have to skip (col * row) lines plus 8 lines for the header for(int ii=0; ii0 ) for (int i=0; i!=meshNumber; ++i) skipmesh(fp, ptxHead, cb); if (!readPTX( m, fp, mask, meshNumber, cb)) { m.Clear(); return 1; } clearBadVertex(m, mask, cb); return 0; } static void clearBadVertex(OpenMeshType &m, int mask, CallBackPos *cb=NULL) { if(cb) cb(40,"PTX Mesh Loading - remove bad vertex!"); for(VertexIterator vi = m.vert.begin(); vi != m.vert.end(); vi++) { if((*vi).P() == Point3f(0.0, 0.0, 0.0)) Allocator::DeleteVertex(m,*vi); } if(cb) cb(60,"PTX Mesh Loading - remove bad face!"); bool onlypoints = ((mask & PTX_ONLY_POINTS) != 0); if(! onlypoints) { for(typename OpenMeshType::FaceIterator fi = m.face.begin(); fi != m.face.end(); fi++) { if( ((*fi).V(0)->IsD()) || ((*fi).V(1)->IsD()) || ((*fi).V(2)->IsD()) ) Allocator::DeleteFace(m,*fi); } // eliminate high angle triangles int angle = 88; //printf(" culling by angle \n"); float limit = cos( angle*3.14159265358979323846/180.0 ); Point3f raggio; if(cb) cb(85,"PTX Mesh Loading - remove bad face!"); vcg::tri::UpdateNormals::PerFaceNormalized(m); for(typename OpenMeshType::FaceIterator fi = m.face.begin(); fi != m.face.end(); fi++) if(!(*fi).IsD()) { raggio = -((*fi).V(0)->P() + (*fi).V(1)->P() + (*fi).V(2)->P()) / 3.0; raggio.Normalize(); if((raggio * (*fi).N()) < limit) Allocator::DeleteFace(m,*fi); } } /*if(cb) cb(60,"PTX Mesh Loading RemoveDuplicateVertex"); tri::Clean::RemoveDuplicateVertex(m); if (!onlypoints) { if(cb) cb(60,"PTX Mesh Loading RemoveUnreferencedVertex"); tri::Clean::RemoveUnreferencedVertex(m); }*/ if(cb) cb(100,"PTX Mesh Loading finish!"); } //if numMesh == -1 load all mesh static int Open_( OpenMeshType &m, const char * filename, int mask = PTX_ONLY_POINTS, CallBackPos *cb=NULL) { FILE *fp; fp = fopen(filename, "rb"); if(fp == NULL) return 1; m.Clear(); m.vn=0; m.fn=0; int vn=0; int fn=0; //PTX_HEAD_INFO tab; //tab.clear(); //while ( skipmesh( fp, tab, cb ) ) {} /*if ( (vn<=0) && (fn<=0) ) return false; //VertexIterator vi = Allocator::AddVertices(m,vn); //OpenMeshType::FaceIterator fi= Allocator::AddFaces(m,fn); VertexIterator vi = Allocator::AddVertices(m, tab[20].vn); FaceIterator fi = Allocator::AddFaces(m, tab[20].fn); readPTX( m, fp, vi, fi, tab[20], mask, 20, cb); fclose(fp); /* return true; if ( numMesh>0 ) for (int i=0; i!=numMesh; ++i) if (!skipmesh(fp, vn, fn, tab)) return false; int mn=0; if ( numMesh == -1 ) { bool next = true; while ( next ) { bool r = readPTX(m, fp, mask, mn, cb); mn++; if ((r==false) && (m.vn==0) ) { fclose(fp); return false; } else if (r==false) next = false; } } else { bool r = readPTX(m, fp, mask, numMesh, cb); if ((r==false) && (m.vn==0) ) { fclose(fp); return false; } } fclose(fp); */ // now i delete all points in (0,0,0) that are unsampled points for(VertexIterator vi = m.vert.begin(); vi != m.vert.end(); vi++) { if((*vi).P() == Point3f(0.0, 0.0, 0.0)) Allocator::DeleteVertex(m,*vi); } bool onlypoints = ((mask & PTX_ONLY_POINTS) != 0); if(! onlypoints) { for(typename OpenMeshType::FaceIterator fi = m.face.begin(); fi != m.face.end(); fi++) { if( ((*fi).V(0)->IsD()) || ((*fi).V(1)->IsD()) || ((*fi).V(2)->IsD()) ) Allocator::DeleteFace(m,*fi); } // eliminate high angle triangles int angle = 88; printf(" culling by angle \n"); float limit = cos( angle*3.14159265358979323846/180.0 ); Point3f raggio; vcg::tri::UpdateNormals::PerFaceNormalized(m); for(typename OpenMeshType::FaceIterator fi = m.face.begin(); fi != m.face.end(); fi++) if(!(*fi).IsD()) { raggio = -((*fi).V(0)->P() + (*fi).V(1)->P() + (*fi).V(2)->P()) / 3.0; raggio.Normalize(); if((raggio * (*fi).N()) < limit) Allocator::DeleteFace(m,*fi); } } /*if(cb) cb(60,"PTX Mesh Loading RemoveDuplicateVertex"); tri::Clean::RemoveDuplicateVertex(m); if (!onlypoints) { if(cb) cb(60,"PTX Mesh Loading RemoveUnreferencedVertex"); tri::Clean::RemoveUnreferencedVertex(m); }*/ if(cb) cb(100,"PTX Mesh Loading finish!"); return 0; } static bool readPTX( OpenMeshType &m, FILE *fp, VertexIterator &vi, FaceIterator &fi, const RANGEMAP_INFO &ptxInfo, int mask, int mn, CallBackPos *cb=NULL) { int colnum; int rownum; int numtokens; char linebuf[256]; int ii; float xx,yy,zz; // position float rr,gg,bb; // color float rf; // reflectance Matrix44f currtrasf; bool hascolor; bool savecolor = ((mask & PTX_COLOR) != 0) && VertexType::HasColor(); bool computeBbox = ((mask & PTX_COMPUTE_AABBOX) != 0); bool onlypoints = ((mask & PTX_ONLY_POINTS) != 0); bool switchside = ((mask & PTX_SWITCHSIDE) != 0); bool flipfaces = ((mask & PTX_FLIPFACES) != 0); int total = 50; if ( onlypoints ) total = 100; if (fsetpos(fp, &ptxInfo.pos)!=0) return false; // getting mesh size; fscanf(fp,"%i\n",&colnum); fscanf(fp,"%i\n",&rownum); if ( ( colnum <=0 ) || ( rownum <=0 ) ) return false; // initial 4 lines [still don't know what is this :) :)] if ( !fscanf(fp,"%f %f %f\n", &xx, &yy, &zz) ) return false; if ( !fscanf(fp,"%f %f %f\n", &xx, &yy, &zz) ) return false; if ( !fscanf(fp,"%f %f %f\n", &xx, &yy, &zz) ) return false; if ( !fscanf(fp,"%f %f %f\n", &xx, &yy, &zz) ) return false; // now the transformation matrix if ( !fscanf(fp,"%f %f %f %f\n", &(currtrasf.ElementAt(0,0)), &(currtrasf.ElementAt(0,1)), &(currtrasf.ElementAt(0,2)), &(currtrasf.ElementAt(0,3))) )return false; if ( !fscanf(fp,"%f %f %f %f\n", &(currtrasf.ElementAt(1,0)), &(currtrasf.ElementAt(1,1)), &(currtrasf.ElementAt(1,2)), &(currtrasf.ElementAt(1,3))) )return false; if ( !fscanf(fp,"%f %f %f %f\n", &(currtrasf.ElementAt(2,0)), &(currtrasf.ElementAt(2,1)), &(currtrasf.ElementAt(2,2)), &(currtrasf.ElementAt(2,3))) )return false; if ( !fscanf(fp,"%f %f %f %f\n", &(currtrasf.ElementAt(3,0)), &(currtrasf.ElementAt(3,1)), &(currtrasf.ElementAt(3,2)), &(currtrasf.ElementAt(3,3))) )return false; // now the real data begins // first line, we should know if the format is // XX YY ZZ RF // or it is // XX YY ZZ RF RR GG BB // read the entire first line and then count the spaces. it's rude but it works :) ii=0; fread(&(linebuf[ii++]),1,1,fp); while(linebuf[ii-1] != '\n') if ( fread(&(linebuf[ii++]),1,1,fp)==0 ) return false; linebuf[ii-1] = '\0'; // terminate the string numtokens=1; for(ii=0; ii<(int)strlen(linebuf); ii++) if(linebuf[ii] == ' ') numtokens++; if(numtokens == 4) hascolor = false; else if(numtokens == 7) hascolor = true; else return false; Transpose(currtrasf); int vn = rownum*colnum; //VertexIterator vi = Allocator::AddVertices(m,vn); //m.vn += vn; // parse the first line.... if(hascolor) { printf("\n hascolor "); sscanf(linebuf,"%f %f %f %f %f %f %f", &xx, &yy, &zz, &rf, &rr, &gg, &bb); } else { printf("\n no color "); sscanf(linebuf,"%f %f %f %f", &xx, &yy, &zz, &rf); } //if (computeBbox) m.bbox.SetNull(); //addthefirstpoint (*vi).P()[0]=xx; (*vi).P()[1]=yy; (*vi).P()[2]=zz; (*vi).P() = currtrasf * (*vi).P(); if (computeBbox) m.bbox.Add( (*vi).P() ); if(hascolor && savecolor) { (*vi).C()[0]=rr; (*vi).C()[1]=gg; (*vi).C()[2]=bb; } vi++; // now for each line until end of mesh (row*col)-1 for(ii=0; ii<((rownum*colnum)-1); ii++) { char tmp[255]; sprintf(tmp, "PTX Mesh Loading... mesh %i", mn); if(cb) cb((ii*total)/vn, tmp); // read the stream if(hascolor) fscanf(fp,"%f %f %f %f %f %f %f", &xx, &yy, &zz, &rf, &rr, &gg, &bb); else fscanf(fp,"%f %f %f %f", &xx, &yy, &zz, &rf); // add the point (*vi).P()[0]=xx; (*vi).P()[1]=yy; (*vi).P()[2]=zz; (*vi).P() = currtrasf * (*vi).P(); if (computeBbox) m.bbox.Add( (*vi).P() ); if(hascolor && savecolor) { (*vi).C()[0]=rr; (*vi).C()[1]=gg; (*vi).C()[2]=bb; } vi++; } if(! onlypoints) { // now i can triangulate int trinum = (rownum-1) * (colnum-1) * 2; //OpenMeshType::FaceIterator fi= Allocator::AddFaces(m,trinum); // m.fn += trinum; int v0i,v1i,v2i, t; for(int rit=0; rit::AddVertices(m,vn); m.vn = vn; // parse the first line.... if(hascolor) { printf("\n hascolor "); sscanf(linebuf,"%f %f %f %f %f %f %f", &xx, &yy, &zz, &rf, &rr, &gg, &bb); } else { printf("\n no color "); sscanf(linebuf,"%f %f %f %f", &xx, &yy, &zz, &rf); } if (computeBbox) m.bbox.SetNull(); //addthefirstpoint (*vi).P()[0]=xx; (*vi).P()[1]=yy; (*vi).P()[2]=zz; if (computeBbox) m.bbox.Add( (*vi).P() ); if(hascolor && savecolor) { (*vi).C()[0]=rr; (*vi).C()[1]=gg; (*vi).C()[2]=bb; } vi++; // now for each line until end of mesh (row*col)-1 for(ii=0; ii<((rownum*colnum)-1); ii++) { char tmp[255]; sprintf(tmp, "PTX Mesh Loading..."); if(cb) cb((ii*total)/vn, tmp); // read the stream if(hascolor) fscanf(fp,"%f %f %f %f %f %f %f", &xx, &yy, &zz, &rf, &rr, &gg, &bb); else fscanf(fp,"%f %f %f %f", &xx, &yy, &zz, &rf); // add the point (*vi).P()[0]=xx; (*vi).P()[1]=yy; (*vi).P()[2]=zz; if (computeBbox) m.bbox.Add( (*vi).P() ); if(hascolor && savecolor) { (*vi).C()[0]=rr; (*vi).C()[1]=gg; (*vi).C()[2]=bb; } vi++; } if(! onlypoints) { // now i can triangulate int trinum = (rownum-1) * (colnum-1) * 2; typename OpenMeshType::FaceIterator fi= Allocator::AddFaces(m,trinum); m.fn = trinum; int v0i,v1i,v2i, t; t=0; for(int rit=0; rit::DeleteVertex(m,*vi); } if(cb) cb(60,"PTX Mesh Loading - remove bad face!"); onlypoints = ((mask & PTX_ONLY_POINTS) != 0); if(! onlypoints) { for(typename OpenMeshType::FaceIterator fi = m.face.begin(); fi != m.face.end(); fi++) { if( ((*fi).V(0)->IsD()) || ((*fi).V(1)->IsD()) || ((*fi).V(2)->IsD()) ) Allocator::DeleteFace(m,*fi); } // eliminate high angle triangles int angle = 88; printf(" culling by angle \n"); float limit = cos( angle*3.14159265358979323846/180.0 ); Point3f raggio; vcg::tri::UpdateNormals::PerFaceNormalized(m); for(typename OpenMeshType::FaceIterator fi = m.face.begin(); fi != m.face.end(); fi++) if(!(*fi).IsD()) { raggio = -((*fi).V(0)->P() + (*fi).V(1)->P() + (*fi).V(2)->P()) / 3.0; raggio.Normalize(); if((raggio * (*fi).N()) < limit) Allocator::DeleteFace(m,*fi); } } for(typename OpenMeshType::VertexIterator vi = m.vert.begin(); vi != m.vert.end(); vi++) { if(!(*vi).IsD()) (*vi).P() = currtrasf * (*vi).P(); } vcg::tri::UpdateNormals::PerFaceNormalized(m); vcg::tri::UpdateBounding::Box(m); if(cb) cb(100,"PTX Mesh Loading finish!"); return true; } ///Standard call that reading a mesh static int Open( OpenMeshType &m, const char * filename, int mask = PTX_ONLY_POINTS, CallBackPos *cb=NULL) { FILE *fp; fp = fopen(filename, "rb"); if(fp == NULL) return 1; m.Clear(); m.vn=0; m.fn=0; if (!readPTX( m, fp, mask,cb)) { m.Clear(); return 1; } int endfile,end = 0; fscanf(fp,"%i%i",&endfile,&end); if(end != 0) return 2; return 0; } }; // end class } // end Namespace tri } // end Namespace io } // end Namespace vcg #endifqutemol/vcg/wrap/io_trimesh/export_smf.h0000444000175000017500000000763110610632741017062 0ustar mbamba/**************************************************************************** * VCGLib o o * * Visual and Computer Graphics Library o o * * _ O _ * * Copyright(C) 2004 \/)\/ * * Visual Computing Lab /\/| * * ISTI - Italian National Research Council | * * \ * * All rights reserved. * * * * 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. * * * * 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 (http://www.gnu.org/licenses/gpl.txt) * * for more details. * * * ****************************************************************************/ /**************************************************************************** History $Log: export_smf.h,v $ Revision 1.4 2007/04/16 08:37:53 cignoni Removed garbage chars at the beginning of the file Revision 1.3 2006/11/21 19:23:50 e_cerisoli Added comments for documentation Revision 1.2 2006/11/16 11:24:44 ****************************************************************************/ #ifndef __VCGLIB_EXPORT_SMF #define __VCGLIB_EXPORT_SMF #include namespace vcg { namespace tri { namespace io { template /** This class encapsulate a filter for save smf meshes. */ class ExporterSMF { public: typedef typename SaveMeshType::VertexPointer VertexPointer; typedef typename SaveMeshType::ScalarType ScalarType; typedef typename SaveMeshType::VertexType VertexType; typedef typename SaveMeshType::FaceType FaceType; typedef typename SaveMeshType::VertexIterator VertexIterator; typedef typename SaveMeshType::FaceIterator FaceIterator; ///Standard call for saving a mesh static int Save(SaveMeshType &m, const char * filename, const int &mask, CallBackPos *cb=0) { VertexIterator vi; FaceIterator fi; FILE *fp; fp = fopen(filename,"wb"); fprintf(fp,"#SMF \n" ); std::map index; int ind; for(ind=1,vi=m.vert.begin(); vi!=m.vert.end(); ++vi,++ind) { fprintf(fp,"v " ); fprintf(fp,"%f%s",(*vi).P()[0]," " ); fprintf(fp,"%f%s",(*vi).P()[1]," " ); fprintf(fp,"%f%s",(*vi).P()[2],"\n"); index[&*vi] = ind; } for (fi=m.face.begin(); fi!=m.face.end(); ++fi) { fprintf(fp,"%s","f "); for (int j = 0; j < 3; j++) fprintf(fp,"%i%s",index[(*fi).V(j)]," "); fprintf(fp,"%s","\n"); } fclose(fp); return 0; } /// Standard call for knowing the meaning of an error code static const char *ErrorMsg(int error) { static std::vector smf_error_msg; if(smf_error_msg.empty()) { smf_error_msg.resize(2 ); smf_error_msg[0]="No errors"; smf_error_msg[1]="Can't open file"; } if(error>1 || error<0) return "Unknown error"; else return smf_error_msg[error].c_str(); } }; // end class } // end Namespace tri } // end Namespace io } // end Namespace vcg #endif qutemol/vcg/wrap/io_trimesh/import_dae.h0000444000175000017500000005602410761510237017021 0ustar mbamba#ifndef __VCGLIB_IMPORTERDAE #define __VCGLIB_IMPORTERDAE //importer for collada's files #include namespace vcg { namespace tri { namespace io { template class ImporterDAE : public UtilDAE { private: static int WedgeNormalAttribute(OpenMeshType& m,const QStringList face,const QStringList wn,const QDomNode wnsrc,const int meshfaceind,const int faceind,const int component) { int indnm = -1; if (!wnsrc.isNull()) { indnm = face.at(faceind).toInt(); assert(indnm * 3 < wn.size()); m.face[meshfaceind].WN(component) = vcg::Point3f(wn.at(indnm * 3).toFloat(),wn.at(indnm * 3 + 1).toFloat(),wn.at(indnm * 3 + 2).toFloat()); } return indnm; } static int WedgeTextureAttribute(OpenMeshType& m,const QStringList face,int ind_txt,const QStringList wt,const QDomNode wtsrc,const int meshfaceind,const int faceind,const int component,const int stride = 2) { int indtx = -1; if (!wtsrc.isNull()) { indtx = face.at(faceind).toInt(); int num = wt.size(); assert(indtx * stride < wt.size()); m.face[meshfaceind].WT(component) = vcg::TexCoord2(); m.face[meshfaceind].WT(component).U() = wt.at(indtx * stride).toFloat(); m.face[meshfaceind].WT(component).V() = wt.at(indtx * stride + 1).toFloat(); m.face[meshfaceind].WT(component).N() = ind_txt; } return indtx; } static int WedgeColorAttribute(OpenMeshType& m,const QStringList face,const QStringList wc,const QDomNode wcsrc,const int meshfaceind,const int faceind,const int component) { int indcl; if (!wcsrc.isNull()) { indcl = face.at(faceind).toInt(); assert(indcl * 4 < wc.size()); m.face[meshfaceind].WC(component) = vcg::Color4b(wc.at(indcl * 4).toFloat(),wc.at(indcl * 4 + 1).toFloat(),wc.at(indcl * 4 + 2).toFloat(),wc.at(indcl * 4 + 3).toFloat()); } return indcl; } static void FindStandardWedgeAttributes(WedgeAttribute& wed,const QDomNode nd,const QDomDocument doc) { wed.wnsrc = findNodeBySpecificAttributeValue(nd,"input","semantic","NORMAL"); wed.offnm = findStringListAttribute(wed.wn,wed.wnsrc,nd,doc,"NORMAL"); wed.wtsrc = findNodeBySpecificAttributeValue(nd,"input","semantic","TEXCOORD"); if (!wed.wtsrc.isNull()) { QDomNode src = attributeSourcePerSimplex(nd,doc,"TEXCOORD"); if (isThereTag(src,"accessor")) { QDomNodeList wedatts = src.toElement().elementsByTagName("accessor"); wed.stride = wedatts.at(0).toElement().attribute("stride").toInt(); } else wed.stride = 2; } else wed.stride = 2; wed.offtx = findStringListAttribute(wed.wt,wed.wtsrc,nd,doc,"TEXCOORD"); wed.wcsrc = findNodeBySpecificAttributeValue(nd,"input","semantic","COLOR"); wed.offcl = findStringListAttribute(wed.wc,wed.wcsrc,nd,doc,"COLOR"); } static DAEError LoadPolygonalMesh(QDomNodeList& polypatch,OpenMeshType& m,const size_t offset,AdditionalInfoDAE* info) { return E_NOERROR; } static DAEError LoadPolygonalListMesh(QDomNodeList& polylist,OpenMeshType& m,const size_t offset,AdditionalInfoDAE* info) { typedef PolygonalMesh< MyPolygon > PolyMesh; PolyMesh pm; //copying vertices for(typename OpenMeshType::VertexIterator itv = m.vert.begin();itv != m.vert.end();++itv) { vcg::Point3f p(itv->P().X(),itv->P().Y(),itv->P().Z()); typename PolyMesh::VertexType v; v.P() = p; pm.vert.push_back(v); } int polylist_size = polylist.size(); for(int pl = 0; pl < polylist_size;++pl) { QString mat = polylist.at(pl).toElement().attribute(QString("material")); QDomNode txt_node = textureFinder(mat,*(info->dae->doc)); int ind_txt = -1; if (!txt_node.isNull()) ind_txt = indexTextureByImgNode(*(info->dae->doc),txt_node); //PolyMesh::PERWEDGEATTRIBUTETYPE att = PolyMesh::NONE; WedgeAttribute wa; FindStandardWedgeAttributes(wa,polylist.at(pl),*(info->dae->doc)); QStringList vertcount; valueStringList(vertcount,polylist.at(pl),"vcount"); int indforpol = findOffSetForASingleSimplex(polylist.at(pl)); int offpols = 0; int npolig = vertcount.size(); QStringList polyind; valueStringList(polyind,polylist.at(pl),"p"); for(int ii = 0;ii < npolig;++ii) { int nvert = vertcount.at(ii).toInt(); typename PolyMesh::FaceType p(nvert); for(int iv = 0;iv < nvert;++iv) { int index = offset + polyind.at(offpols + iv * indforpol).toInt(); p._pv[iv] = &(pm.vert[index]); int nmindex = -1; if (!wa.wnsrc.isNull()) nmindex = offset + polyind.at(offpols + iv * indforpol + wa.offnm).toInt(); int txindex = -1; if (!wa.wtsrc.isNull()) { txindex = offset + polyind.at(offpols + iv * indforpol + wa.offtx).toInt(); /*p._txc[iv].U() = wa.wt.at(txindex * 2).toFloat(); p._txc[iv].V() = wa.wt.at(txindex * 2 + 1).toFloat(); p._txc[iv].N() = ind_txt;*/ } } pm._pols.push_back(p); offpols += nvert * indforpol; } } pm.triangulate(m); return E_NOERROR; } static DAEError LoadTriangularMesh(QDomNodeList& tripatch,OpenMeshType& m,const size_t offset,AdditionalInfoDAE* info) { int tripatch_size = tripatch.size(); for(int tript = 0; tript < tripatch_size;++tript) { QString mat = tripatch.at(tript).toElement().attribute(QString("material")); QDomNode txt_node = textureFinder(mat,*(info->dae->doc)); int ind_txt = -1; if (!txt_node.isNull()) ind_txt = indexTextureByImgNode(*(info->dae->doc),txt_node); int nfcatt = tripatch.at(tript).toElement().elementsByTagName("input").size(); QStringList face; valueStringList(face,tripatch.at(tript),"p"); int face_size = face.size(); int offsetface = (int)m.face.size(); if (face_size != 0) { vcg::tri::Allocator::AddFaces(m,face_size / (nfcatt * 3)); WedgeAttribute wa; FindStandardWedgeAttributes(wa,tripatch.at(tript),*(info->dae->doc)); int jj = 0; //int dd = m.face.size(); for(int ff = offsetface;ff < (int) m.face.size();++ff) { for(unsigned int tt = 0;tt < 3;++tt) { int indvt = face.at(jj).toInt(); assert(indvt + offset < m.vert.size()); m.face[ff].V(tt) = &(m.vert[indvt + offset]); if(tri::HasPerWedgeNormal(m)) WedgeNormalAttribute(m,face,wa.wn,wa.wnsrc,ff,jj + wa.offnm,tt); if(tri::HasPerWedgeTexCoord(m) && ind_txt != -1) { WedgeTextureAttribute(m,face,ind_txt,wa.wt,wa.wtsrc,ff,jj + wa.offtx,tt,wa.stride); } if(tri::HasPerWedgeColor(m)) WedgeColorAttribute(m,face,wa.wc,wa.wcsrc,ff,jj + wa.offcl,tt); jj += nfcatt; } } } } return E_NOERROR; } static int LoadMesh(OpenMeshType& m,AdditionalInfoDAE* info,const QDomNode& geo,const vcg::Matrix44f& t, CallBackPos *cb=0) { if (isThereTag(geo,"mesh")) { if ((cb !=NULL) && (((info->numvert + info->numface)%100)==0) && !(*cb)((100*(info->numvert + info->numface))/(info->numvert + info->numface), "Vertex Loading")) return E_CANTOPEN; /*QDomNodeList geosrc = geo.toElement().elementsByTagName("source"); int geosrc_size = geosrc.size(); if (geosrc_size < 1) return E_NOVERTEXPOSITION;*/ QDomNodeList vertices = geo.toElement().elementsByTagName("vertices"); int vertices_size = vertices.size(); if (vertices_size != 1) return E_INCOMPATIBLECOLLADA141FORMAT; QDomNode srcnode = attributeSourcePerSimplex(vertices.at(0),*(info->dae->doc),"POSITION"); if (srcnode.isNull()) return E_NOVERTEXPOSITION; QStringList geosrcposarr; valueStringList(geosrcposarr,srcnode,"float_array"); int geosrcposarr_size = geosrcposarr.size(); if ((geosrcposarr_size % 3) != 0) return E_CANTOPEN; int nvert = geosrcposarr_size / 3; size_t offset = m.vert.size(); if (geosrcposarr_size != 0) { vcg::tri::Allocator::AddVertices(m,nvert); QDomNode srcnodenorm = attributeSourcePerSimplex(vertices.at(0),*(info->dae->doc),"NORMAL"); QStringList geosrcvertnorm; if (!srcnodenorm.isNull()) valueStringList(geosrcvertnorm,srcnodenorm,"float_array"); QDomNode srcnodetext = attributeSourcePerSimplex(vertices.at(0),*(info->dae->doc),"TEXCOORD"); QStringList geosrcverttext; if (!srcnodetext.isNull()) valueStringList(geosrcverttext,srcnodetext,"float_array"); QDomNode srcnodecolor = attributeSourcePerSimplex(vertices.at(0),*(info->dae->doc),"COLOR"); QStringList geosrcvertcol; if (!srcnodecolor.isNull()) valueStringList(geosrcvertcol,srcnodecolor,"float_array"); int ii = 0; for(size_t vv = offset;vv < m.vert.size();++vv) { assert((ii * 3 < geosrcposarr_size) && (ii * 3 + 1 < geosrcposarr_size) && (ii * 3 + 2 < geosrcposarr_size)); vcg::Point4f tmp = t * vcg::Point4f(geosrcposarr[ii * 3].toFloat(),geosrcposarr[ii * 3 + 1].toFloat(),geosrcposarr[ii * 3 + 2].toFloat(),1.0f); m.vert[vv].P() = vcg::Point3f(tmp.X(),tmp.Y(),tmp.Z()); if (!srcnodenorm.isNull()) { assert((ii * 3 < geosrcvertnorm.size()) && (ii * 3 + 1 < geosrcvertnorm.size()) && (ii * 3 + 2 < geosrcvertnorm.size())); vcg::Matrix44f intr44 = vcg::Inverse(t); vcg::Transpose(intr44); Matrix33f intr33; for(unsigned int rr = 0; rr < 2; ++rr) { for(unsigned int cc = 0;cc < 2;++cc) intr33[rr][cc] = intr44[rr][cc]; } m.vert[vv].N() = (intr33 * vcg::Point3f(geosrcvertnorm[ii * 3].toFloat(),geosrcvertnorm[ii * 3 + 1].toFloat(),geosrcvertnorm[ii * 3 + 2].toFloat())).Normalize(); } /*if (!srcnodecolor.isNull()) { assert((ii * 4 < geosrcvertcol.size()) && (ii * 4 + 1 < geosrcvertcol.size()) && (ii * 4 + 2 < geosrcvertcol.size()) && (ii * 4 + 1 < geosrcvertcol.size())); m.vert[vv].C() = vcg::Color4b(geosrcvertcol[ii * 4].toFloat(),geosrcvertcol[ii * 4 + 1].toFloat(),geosrcvertcol[ii * 4 + 2].toFloat(),geosrcvertcol[ii * 4 + 3].toFloat()); }*/ if (!srcnodetext.isNull()) { assert((ii * 2 < geosrcverttext.size()) && (ii * 2 + 1 < geosrcverttext.size())); m.vert[vv].T() = vcg::TexCoord2(); m.vert[vv].T().u() = geosrcverttext[ii * 2].toFloat(); m.vert[vv].T().v() = geosrcverttext[ii * 2 + 1].toFloat(); } ++ii; } QDomNodeList tripatch = geo.toElement().elementsByTagName("triangles"); int tripatch_size = tripatch.size(); QDomNodeList polypatch = geo.toElement().elementsByTagName("polygons"); int polypatch_size = polypatch.size(); QDomNodeList polylist = geo.toElement().elementsByTagName("polylist"); int polylist_size = polylist.size(); if ((tripatch_size == 0) && (polypatch_size == 0) && (polylist_size == 0)) return E_NOPOLYGONALMESH; DAEError err = E_NOERROR; if (tripatch_size != 0) err = LoadTriangularMesh(tripatch,m,offset,info); else if (polypatch_size != 0) err = LoadPolygonalMesh(polypatch,m,offset,info); else if (polylist_size != 0) err = LoadPolygonalListMesh(polylist,m,offset,info); if (err != E_NOERROR) return err; } return E_NOERROR; } else return E_NOMESH; } static void GetTexCoord(const QDomDocument& doc,AdditionalInfoDAE* inf) { QDomNodeList txlst = doc.elementsByTagName("library_images"); for(int img = 0;img < txlst.at(0).childNodes().size();++img) { QDomNodeList nlst = txlst.at(0).childNodes().at(img).toElement().elementsByTagName("init_from"); if (nlst.size() > 0) { inf->texturefile.push_back(nlst.at(0).firstChild().nodeValue()); } } } public: //merge all meshes in the collada's file in the templeted mesh m //I assume the mesh static int Open(OpenMeshType& m,const char* filename,AdditionalInfo*& info, CallBackPos *cb=0) { AdditionalInfoDAE* inf = new AdditionalInfoDAE(); inf->dae = new InfoDAE(); QDomDocument* doc = new QDomDocument(filename); QFile file(filename); if (!file.open(QIODevice::ReadOnly)) return E_CANTOPEN; if (!doc->setContent(&file)) { file.close(); return E_CANTOPEN; } file.close(); inf->dae->doc = doc; //GetTexture(*(info->doc),inf); //scene->instance_visual_scene QDomNodeList scenes = inf->dae->doc->elementsByTagName("scene"); int scn_size = scenes.size(); if (scn_size == 0) return E_NO3DSCENE; int problem = E_NOERROR; bool found_a_mesh = false; //Is there geometry in the file? bool geoinst_found = false; //for each scene in COLLADA FILE for(int scn = 0;scn < scn_size;++scn) { QDomNodeList instscenes = scenes.at(scn).toElement().elementsByTagName("instance_visual_scene"); int instscn_size = instscenes.size(); if (instscn_size == 0) return E_INCOMPATIBLECOLLADA141FORMAT; //for each scene instance in a COLLADA scene for(int instscn = 0;instscn < instscn_size; ++instscn) { QString libscn_url; referenceToANodeAttribute(instscenes.at(instscn),"url",libscn_url); QDomNode nd = QDomNode(*(inf->dae->doc)); QDomNode visscn = findNodeBySpecificAttributeValue(*(inf->dae->doc),"visual_scene","id",libscn_url); if(visscn.isNull()) return E_UNREFERENCEBLEDCOLLADAATTRIBUTE; //for each node in the libscn_url visual scene QDomNodeList visscn_child = visscn.childNodes(); //for each direct child of a libscn_url visual scene find if there is some geometry instance for(int chdind = 0; chdind < visscn_child.size();++chdind) { QDomNodeList geoinst = visscn_child.at(chdind).toElement().elementsByTagName("instance_geometry"); int geoinst_size = geoinst.size(); if (geoinst_size != 0) { geoinst_found |= true; QDomNodeList geolib = inf->dae->doc->elementsByTagName("library_geometries"); assert(geolib.size() == 1); //!!!!!!!!!!!!!!!!!here will be the code for geometry transformations!!!!!!!!!!!!!!!!!!!!!! for(int geoinst_ind = 0;geoinst_ind < geoinst_size;++geoinst_ind) { QString geo_url; referenceToANodeAttribute(geoinst.at(geoinst_ind),"url",geo_url); QDomNode geo = findNodeBySpecificAttributeValue(geolib.at(0),"geometry","id",geo_url); if (geo.isNull()) return E_UNREFERENCEBLEDCOLLADAATTRIBUTE; vcg::Matrix44f tr; tr.SetIdentity(); TransfMatrix(visscn,geoinst.at(geoinst_ind),tr); problem |= LoadMesh(m,inf,geo,tr); if (problem & E_NOMESH) found_a_mesh |= false; else found_a_mesh = true; } } } //if there is at least a mesh I clean the problem status variable from E_NOMESH ERROR if (((problem & E_NOMESH) || (problem & E_NOPOLYGONALMESH)) && (found_a_mesh)) { if (problem & E_NOMESH) problem = problem & ~E_NOMESH; if (problem & E_NOPOLYGONALMESH) problem = problem & ~E_NOPOLYGONALMESH; } } } if (!geoinst_found) { QDomNodeList geolib = inf->dae->doc->elementsByTagName("library_geometries"); assert(geolib.size() == 1); QDomNodeList geochild = geolib.at(0).childNodes(); int geochild_size = geochild.size(); int problem = 0; for(int chd = 0;chd < geochild_size;++chd) { vcg::Matrix44f tmp; tmp.SetIdentity(); problem |= LoadMesh(m,inf,geochild.at(chd),tmp); } } //if there is at least a mesh I clean the problem status variable from E_NOMESH or E_NOPOLYGONALMESH ERROR if (((problem & E_NOMESH) || (problem & E_NOPOLYGONALMESH)) && (found_a_mesh)) { if (problem & E_NOMESH) problem = problem & ~E_NOMESH; if (problem & E_NOPOLYGONALMESH) problem = problem & ~E_NOPOLYGONALMESH; } info = inf; return problem; } static bool LoadMask(const char * filename, AdditionalInfoDAE*& addinfo) { bool bHasPerWedgeTexCoord = false; bool bHasPerWedgeNormal = false; bool bHasPerVertexColor = false; bool bHasPerFaceColor = false; bool bHasPerVertexNormal = false; bool bHasPerVertexText = false; AdditionalInfoDAE* info = new AdditionalInfoDAE(); info->dae = new InfoDAE(); QDomDocument* doc = new QDomDocument(filename); QFile file(filename); if (!file.open(QIODevice::ReadOnly)) return false; if (!doc->setContent(&file)) { file.close(); return false; } file.close(); info->dae->doc = doc; GetTexCoord(*(info->dae->doc),info); QDomNodeList scenes = info->dae->doc->elementsByTagName("scene"); int scn_size = scenes.size(); //Is there geometry in the file? bool geoinst_found = false; //for each scene in COLLADA FILE for(int scn = 0;scn < scn_size;++scn) { QDomNodeList instscenes = scenes.at(scn).toElement().elementsByTagName("instance_visual_scene"); int instscn_size = instscenes.size(); if (instscn_size == 0) return false; //for each scene instance in a COLLADA scene for(int instscn = 0;instscn < instscn_size; ++instscn) { QString libscn_url; referenceToANodeAttribute(instscenes.at(instscn),"url",libscn_url); QDomNode nd = QDomNode(*(info->dae->doc)); QDomNode visscn = findNodeBySpecificAttributeValue(*(info->dae->doc),"visual_scene","id",libscn_url); if(visscn.isNull()) return false; //for each node in the libscn_url visual scene //QDomNodeList& visscn_child = visscn.childNodes(); QDomNodeList visscn_child = visscn.childNodes(); //for each direct child of a libscn_url visual scene find if there is some geometry instance for(int chdind = 0; chdind < visscn_child.size();++chdind) { //QDomNodeList& geoinst = visscn_child.at(chdind).toElement().elementsByTagName("instance_geometry"); QDomNodeList geoinst = visscn_child.at(chdind).toElement().elementsByTagName("instance_geometry"); int geoinst_size = geoinst.size(); if (geoinst_size != 0) { geoinst_found |= true; QDomNodeList geolib = info->dae->doc->elementsByTagName("library_geometries"); assert(geolib.size() == 1); //!!!!!!!!!!!!!!!!!here will be the code for geometry transformations!!!!!!!!!!!!!!!!!!!!!! info->numvert = 0; info->numface = 0; for(int geoinst_ind = 0;geoinst_ind < geoinst_size;++geoinst_ind) { QString geo_url; referenceToANodeAttribute(geoinst.at(geoinst_ind),"url",geo_url); QDomNode geo = findNodeBySpecificAttributeValue(geolib.at(0),"geometry","id",geo_url); if (geo.isNull()) return false; QDomNodeList vertlist = geo.toElement().elementsByTagName("vertices"); for(int vert = 0;vert < vertlist.size();++vert) { QDomNode no; no = findNodeBySpecificAttributeValue(vertlist.at(vert),"input","semantic","POSITION"); QString srcurl; referenceToANodeAttribute(no,"source",srcurl); no = findNodeBySpecificAttributeValue(geo,"source","id",srcurl); QDomNodeList fa = no.toElement().elementsByTagName("float_array"); assert(fa.size() == 1); info->numvert += (fa.at(0).toElement().attribute("count").toInt() / 3); no = findNodeBySpecificAttributeValue(vertlist.at(vert),"input","semantic","COLOR"); if (!no.isNull()) bHasPerVertexColor = true; no = findNodeBySpecificAttributeValue(vertlist.at(vert),"input","semantic","NORMAL"); if (!no.isNull()) bHasPerVertexNormal = true; no = findNodeBySpecificAttributeValue(vertlist.at(vert),"input","semantic","TEXCOORD"); if (!no.isNull()) bHasPerVertexText = true; } const char* arr[] = {"triangles","polylist","polygons"}; for(unsigned int tt= 0;tt < 3;++tt) { QDomNodeList facelist = geo.toElement().elementsByTagName(arr[tt]); for(int face = 0;face < facelist.size();++face) { info->numface += facelist.at(face).toElement().attribute("count").toInt() ; QDomNode no; no = findNodeBySpecificAttributeValue(facelist.at(face),"input","semantic","NORMAL"); if (!no.isNull()) bHasPerWedgeNormal = true; no = findNodeBySpecificAttributeValue(facelist.at(face),"input","semantic","TEXCOORD"); if (!no.isNull()) bHasPerWedgeTexCoord = true; } } } } } } } if (!geoinst_found) { QDomNodeList geolib = info->dae->doc->elementsByTagName("library_geometries"); assert(geolib.size() == 1); QDomNodeList geochild = geolib.at(0).toElement().elementsByTagName("geometry"); //!!!!!!!!!!!!!!!!!here will be the code for geometry transformations!!!!!!!!!!!!!!!!!!!!!! info->numvert = 0; info->numface = 0; for(int geoinst_ind = 0;geoinst_ind < geochild.size();++geoinst_ind) { QDomNodeList vertlist = geochild.at(geoinst_ind).toElement().elementsByTagName("vertices"); for(int vert = 0;vert < vertlist.size();++vert) { QDomNode no; no = findNodeBySpecificAttributeValue(vertlist.at(vert),"input","semantic","POSITION"); QString srcurl; referenceToANodeAttribute(no,"source",srcurl); no = findNodeBySpecificAttributeValue(geochild.at(geoinst_ind),"source","id",srcurl); QDomNodeList fa = no.toElement().elementsByTagName("float_array"); assert(fa.size() == 1); info->numvert += (fa.at(0).toElement().attribute("count").toInt() / 3); no = findNodeBySpecificAttributeValue(vertlist.at(vert),"input","semantic","COLOR"); if (!no.isNull()) bHasPerVertexColor = true; no = findNodeBySpecificAttributeValue(vertlist.at(vert),"input","semantic","NORMAL"); if (!no.isNull()) bHasPerVertexNormal = true; no = findNodeBySpecificAttributeValue(vertlist.at(vert),"input","semantic","TEXCOORD"); if (!no.isNull()) bHasPerVertexText = true; } QDomNodeList facelist = geochild.at(geoinst_ind).toElement().elementsByTagName("triangles"); for(int face = 0;face < facelist.size();++face) { info->numface += facelist.at(face).toElement().attribute("count").toInt() ; QDomNode no; no = findNodeBySpecificAttributeValue(facelist.at(face),"input","semantic","NORMAL"); if (!no.isNull()) bHasPerWedgeNormal = true; no = findNodeBySpecificAttributeValue(facelist.at(face),"input","semantic","TEXCOORD"); if (!no.isNull()) bHasPerWedgeTexCoord = true; } } } info->mask = 0; if (bHasPerWedgeTexCoord) info->mask |= vcg::tri::io::Mask::IOM_WEDGTEXCOORD; if (bHasPerWedgeNormal) info->mask |= vcg::tri::io::Mask::IOM_WEDGNORMAL; if (bHasPerVertexColor) info->mask |= vcg::tri::io::Mask::IOM_VERTCOLOR; if (bHasPerFaceColor) info->mask |= vcg::tri::io::Mask::IOM_FACECOLOR; if (bHasPerVertexNormal) info->mask |= vcg::tri::io::Mask::IOM_VERTNORMAL; if (bHasPerVertexText) info->mask |= vcg::tri::io::Mask::IOM_VERTTEXCOORD; delete (info->dae->doc); info->dae->doc = NULL; addinfo = info; return true; } }; } } } #endif qutemol/vcg/wrap/io_trimesh/additionalinfo.h0000444000175000017500000000035310757633746017674 0ustar mbamba#ifndef __VCGLIB_ADDITIONAL_INFO #define __VCGLIB_ADDITIONAL_INFO class AdditionalInfo { protected: AdditionalInfo() { } public: unsigned int numvert; unsigned int numface; int mask; virtual ~AdditionalInfo() { } }; #endif qutemol/vcg/wrap/io_trimesh/io_material.h0000444000175000017500000001203010761372200017144 0ustar mbamba/**************************************************************************** * VCGLib o o * * Visual and Computer Graphics Library o o * * _ O _ * * Copyright(C) 2004 \/)\/ * * Visual Computing Lab /\/| * * ISTI - Italian National Research Council | * * \ * * All rights reserved. * * * * 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. * * * * 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 (http://www.gnu.org/licenses/gpl.txt) * * for more details. * * * ****************************************************************************/ /**************************************************************************** History $Log: io_material.h,v $ Revision 1.6 2008/02/27 23:38:40 cignoni added materialname field Revision 1.5 2008/02/27 00:34:43 cignoni corrected various bugs in the export of texture coords Revision 1.4 2007/06/20 10:28:04 tarini "newline at end of file" and "endif" warnings fixed Revision 1.3 2006/11/09 07:51:44 cignoni bug due to wrong access to eventually unexistent FaceColor Revision 1.2 2006/10/09 19:58:08 cignoni Added casts to remove warnings Revision 1.1 2006/03/07 13:19:29 cignoni First Release with OBJ import support Revision 1.1 2006/02/16 19:28:36 fmazzant transfer of Export_3ds.h, Export_obj.h, Io_3ds_obj_material.h from Meshlab to vcg Revision 1.1 2006/02/06 11:04:40 fmazzant added file material.h. it include struct Material, CreateNewMaterial(...) and MaterialsCompare(...) ****************************************************************************/ #ifndef __VCGLIB_MATERIAL #define __VCGLIB_MATERIAL namespace vcg { namespace tri { namespace io { /* structures material */ struct Material { unsigned int index;//index of material std::string materialName; Point3f Ka;//ambient Point3f Kd;//diffuse Point3f Ks;//specular float d;//alpha float Tr;//alpha int illum;//specular illumination float Ns; std::string map_Kd; //filename texture }; template class Materials { public: typedef typename SaveMeshType::FaceIterator FaceIterator; typedef typename SaveMeshType::VertexIterator VertexIterator; typedef typename SaveMeshType::VertexType VertexType; /* creates a new meterial */ inline static int CreateNewMaterial(SaveMeshType &m, std::vector &materials, unsigned int index, FaceIterator &fi) { Point3f diffuse(1,1,1); float Tr = 1; if(HasPerFaceColor(m)){ diffuse = Point3f((float)((*fi).C()[0])/255.0f,(float)((*fi).C()[1])/255.0f,(float)((*fi).C()[2])/255.0f);//diffuse (float)((*fi).C()[3])/255.0f;//alpha } int illum = 2; //default not use Ks! float ns = 0.0; //default Material mtl; mtl.index = index;//index of materials mtl.Ka = Point3f(0.2f,0.2f,0.2f);//ambient mtl.Kd = diffuse;//diffuse mtl.Ks = Point3f(1.0f,1.0f,1.0f);//specular mtl.Tr = Tr;//alpha mtl.Ns = ns; mtl.illum = illum;//illumination if(m.textures.size() && (*fi).WT(0).n() >=0 ) mtl.map_Kd = m.textures[(*fi).WT(0).n()]; else mtl.map_Kd = ""; int i = -1; if((i = MaterialsCompare(materials,mtl)) == -1) { materials.push_back(mtl); return materials.size(); } return i; } /* returns the index of the material if it exists inside the list of the materials, otherwise it returns -1. */ inline static int MaterialsCompare(std::vector &materials, Material mtl) { for(unsigned int i=0;i namespace vcg { namespace tri { namespace io { /** This class encapsulate a filter for opening stl (sterolitograpy) meshes. The stl format is quite simple and rather un-flexible. It just stores, in ascii or binary the, unindexed, geometry of the faces. */ template class ExporterSTL { public: static int Save(SaveMeshType &m, const char * filename, const int &mask, CallBackPos *cb=0) { return Save(m,filename,true); } static int Save(SaveMeshType &m, const char * filename , bool binary =true, const char *objectname=0) { typedef typename SaveMeshType::FaceIterator FaceIterator; FILE *fp; fp = fopen(filename,"wb"); if(fp==0) return 1; if(binary) { // Write Header char *header="VCG "; if(objectname) strncpy(header,objectname,80); fwrite(header,80,1,fp); // write number of facets fwrite(&m.fn,1,sizeof(int),fp); Point3f p; unsigned short attributes=0; FaceIterator fi; for(fi=m.face.begin(); fi!=m.face.end(); ++fi) if( !(*fi).IsD() ) { // For each triangle write the normal, the three coords and a short set to zero p.Import(vcg::NormalizedNormal(*fi)); fwrite(p.V(),3,sizeof(float),fp); for(int k=0;k<3;++k){ p.Import((*fi).V(k)->P()); fwrite(p.V(),3,sizeof(float),fp); } fwrite(&attributes,1,sizeof(short),fp); } } else { if(objectname) fprintf(fp,"solid %s\n",objectname); else fprintf(fp,"solid vcg\n"); Point3f p; FaceIterator fi; for(fi=m.face.begin(); fi!=m.face.end(); ++fi) if( !(*fi).IsD() ) { // For each triangle write the normal, the three coords and a short set to zero p.Import(vcg::NormalizedNormal(*fi)); fprintf(fp," facet normal %13e %13e %13e\n",p[0],p[1],p[2]); fprintf(fp," outer loop\n"); for(int k=0;k<3;++k){ p.Import((*fi).V(k)->P()); fprintf(fp," vertex %13e %13e %13e\n",p[0],p[1],p[2]); } fprintf(fp," endloop\n"); fprintf(fp," endfacet\n"); } fprintf(fp,"endsolid vcg\n"); } fclose(fp); return 0; } static const char *ErrorMsg(int error) { static std::vector stl_error_msg; if(stl_error_msg.empty()) { stl_error_msg.resize(2 ); stl_error_msg[0]="No errors"; stl_error_msg[1]="Can't open file"; } if(error>1 || error<0) return "Unknown error"; else return stl_error_msg[error].c_str(); }; /* returns mask of capability one define with what are the saveable information of the format. */ static int GetExportMaskCapability() { int capability = 0; capability |= vcg::tri::io::Mask::IOM_VERTCOORD; capability |= vcg::tri::io::Mask::IOM_FACEINDEX; return capability; } }; // end class } // end Namespace tri } // end Namespace io } // end Namespace vcg #endif qutemol/vcg/wrap/io_trimesh/import_asc.h0000444000175000017500000001110011004010160016775 0ustar mbamba/**************************************************************************** * VCGLib o o * * Visual and Computer Graphics Library o o * * _ O _ * * Copyright(C) 2004 \/)\/ * * Visual Computing Lab /\/| * * ISTI - Italian National Research Council | * * \ * * All rights reserved. * * * * 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. * * * * 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 (http://www.gnu.org/licenses/gpl.txt) * * for more details. * * * ****************************************************************************/ /**************************************************************************** History $Log: import_raw.h,v $ ****************************************************************************/ #ifndef __VCGLIB_IMPORT_ASC #define __VCGLIB_IMPORT_ASC #include #include #include #include #include #include namespace vcg { namespace tri { namespace io { /** This class encapsulate a filter for importing raw format pointcloud. there exists many raw formats. each one with a particular sintax even if they only contains */ template class ImporterASC { public: typedef typename MESH_TYPE::VertexPointer VertexPointer; typedef typename MESH_TYPE::ScalarType ScalarType; typedef typename MESH_TYPE::VertexType VertexType; typedef typename MESH_TYPE::FaceType FaceType; typedef typename MESH_TYPE::VertexIterator VertexIterator; typedef typename MESH_TYPE::FaceIterator FaceIterator; enum RAWError { E_NOERROR, // 0 // Error open E_CANTOPEN, // 1 E_UNESPECTEDEOF, // 2 }; static const char *ErrorMsg(int error) { static const char * raw_error_msg[] = { "No errors", "Can't open file", "Premature End of file", }; if(error>2 || error<0) return "Unknown error"; else return raw_error_msg[error]; }; /*! * Standard call for reading a mesh * \param m the destination mesh * \param filename the name of the file to read from * \param triangulate if true, the mesh will be triangulated, otherwise only points will be stored * \param lineskip number of lines to be skipped at the begin of the file * \return the operation result */ static int Open( MESH_TYPE &m, const char * filename, CallBackPos *cb=0,bool triangulate=false) { FILE *fp; fp = fopen(filename, "r"); if(fp == NULL) { return E_CANTOPEN; } long currentPos = ftell(fp); fseek(fp,0L,SEEK_END); long fileLen = ftell(fp); fseek(fp,currentPos,SEEK_SET); m.Clear(); Point3f pp; int cnt=0; int ret; /* Read a single facet from an ASCII .STL file */ while(!feof(fp)) { if(cb && (++cnt)%1000) cb( (ftell(fp)*100)/fileLen, "ASC Mesh Loading"); if(feof(fp)) break; ret=fscanf(fp, "%f, %f, %f\n", &pp.X(), &pp.Y(), &pp.Z()); if(ret!=3) return E_UNESPECTEDEOF; VertexIterator vi=Allocator::AddVertices(m,1); (*vi).P().Import(pp); } fclose(fp); // now try to triangulate. // search for the first jump float baseY = m.vert[0].P().Y(); int i; for(i=1;i::FlipMesh(m); return E_NOERROR; } }; // end class } // end Namespace tri } // end Namespace io } // end Namespace vcg #endif qutemol/vcg/wrap/io_trimesh/export_vrml.h0000444000175000017500000002325010761371734017261 0ustar mbamba/**************************************************************************** * VCGLib o o * * Visual and Computer Graphics Library o o * * _ O _ * * Copyright(C) 2004 \/)\/ * * Visual Computing Lab /\/| * * ISTI - Italian National Research Council | * * \ * * All rights reserved. * * * * 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. * * * * 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 (http://www.gnu.org/licenses/gpl.txt) * * for more details. * * * ****************************************************************************/ /**************************************************************************** History $Log: export_vrml.h,v $ Revision 1.9 2008/02/27 23:35:56 cignoni removed useless include Revision 1.8 2008/02/21 17:47:29 cignoni corrected texture saving. Still broken the multitexturing Revision 1.7 2008/02/21 17:23:57 cignoni Corrected various bug, involving spurious commas, and pervertex color saved as per wedge color. Revision 1.6 2007/06/12 10:15:35 cignoni Very important change. No more scaling and translation in the saved file! Revision 1.5 2007/03/20 16:47:49 cignoni Update to the new texture syntax Revision 1.4 2006/11/21 19:22:53 e_cerisoli Added Comments for documentation ****************************************************************************/ #ifndef __VCGLIB_EXPORT_WRL #define __VCGLIB_EXPORT_WRL #include #include namespace vcg { namespace tri { namespace io { template /** This class encapsulate a filter for save vrml meshes. */ class ExporterWRL { public: typedef typename SaveMeshType::VertexPointer VertexPointer; typedef typename SaveMeshType::ScalarType ScalarType; typedef typename SaveMeshType::VertexType VertexType; typedef typename SaveMeshType::FaceType FaceType; typedef typename SaveMeshType::VertexIterator VertexIterator; typedef typename SaveMeshType::FaceIterator FaceIterator; ///Standard call for saving a mesh static int Save(SaveMeshType &m, const char * filename, const int &mask, CallBackPos *cb=0) { FILE *fp; fp = fopen(filename,"wb"); if(fp==NULL) return 1; // Header fprintf(fp, "#VRML V2.0 utf8\n" "\n" "# Generated by VCGLIB, (C)Copyright 1999-2001 VCG, IEI-CNR\n" "\n" "NavigationInfo {\n" " type [ \"EXAMINE\", \"ANY\" ]\n" "}\n" ); // Tranche principale double ss = 8.0/m.bbox.Diag(); fprintf(fp, "Transform {\n" " scale %g %g %g\n" " translation %g %g %g\n" " children\n" " [\n" ,1.0,1.0,1.0, 0.0,0.0,0.0); // ,ss,ss,ss // , -m.bbox.Center()[0]*ss, -m.bbox.Center()[1]*ss,-3-m.bbox.Center()[2]*ss ); // Start Shape fprintf(fp, " Shape\n" " {\n" " geometry IndexedFaceSet\n" " {\n" " creaseAngle .5\n" " solid FALSE\n" " coord Coordinate\n" " {\n" " point\n" " [" ); FaceIterator fi; VertexIterator vi; std::map index; int ind; // Vertici for(ind=0,vi=m.vert.begin(); vi!=m.vert.end(); ++vi, ++ind) if(!(*vi).IsD()) { if(vi!=m.vert.begin()) fprintf(fp,", "); if(ind%4==0) fprintf(fp, "\n " ); fprintf(fp, "%g %g %g" ,(*vi).P()[0] ,(*vi).P()[1] ,(*vi).P()[2] ); index[&*vi] = ind; } fprintf(fp,"\n" " ]\n" " }\n" ); if( HasPerVertexColor(m) && (mask & vcg::tri::io::Mask::IOM_VERTCOLOR)) { fprintf(fp, " color Color\n" " {\n" " color\n" " [" ); for(ind=0,vi=m.vert.begin();vi!=m.vert.end();++vi,++ind) if(!(*vi).IsD()) { if(vi!=m.vert.begin()) fprintf(fp,", "); float r = float(vi->C()[0])/255; float g = float(vi->C()[1])/255; float b = float(vi->C()[2])/255; if(ind%4==0) fprintf(fp,"\n "); fprintf(fp,"%g %g %g",r,g,b); } fprintf(fp, "\n" " ]\n" " }\n" ); } else if( HasPerWedgeColor(m) && (mask & vcg::tri::io::Mask::IOM_WEDGCOLOR )) { fprintf(fp, " color Color\n" " {\n" " color\n" " [" ); for(ind=0,fi=m.face.begin();fi!=m.face.end();++fi,++ind) if(!(*fi).IsD()) { if(fi!=m.face.begin()) fprintf(fp,", "); if(ind%4==0) fprintf(fp,"\n "); for(int z=0;z<3;++z) { if(z!=0) fprintf(fp,", "); float r = float(fi->WC(z)[0])/255; float g = float(fi->WC(z)[1])/255; float b = float(fi->WC(z)[2])/255; fprintf(fp,"%g %g %g",r,g,b); } } fprintf(fp, "\n" " ]\n" " }\n" " colorIndex\n" " [" ); int nn = 0; for(ind=0,fi=m.face.begin(); fi!=m.face.end(); ++fi,++ind) if(!(*fi).IsD()) { //if(fi!=m.face.begin()) fprintf(fp,", "); if(ind%4==0) fprintf(fp,"\n "); fprintf(fp,"%i",nn++); fprintf(fp,"%i",nn++); fprintf(fp,"%i",nn++); fprintf(fp,"-1"); } fprintf(fp, "\n" " ]\n" ); } // NOTE MULTITEXTURE WRL SAVING DO NOT WORK! else if (HasPerWedgeTexCoord(m) &&(mask & vcg::tri::io::Mask::IOM_WEDGTEXCOORD)) { fprintf(fp, "\n" " texCoord TextureCoordinate\n" " {\n" " point\n" " [\n" ); for(ind=0,fi=m.face.begin(); fi!=m.face.end(); ++fi,++ind) if(!(*fi).IsD()) { //if(fi!=m.face.begin()) fprintf(fp,", "); if(ind%4==0) fprintf(fp,"\n "); for (int j = 0; j < 3; j++) fprintf(fp,"%g %g ",fi->WT(j).u(),fi->WT(j).v()); } fprintf(fp, "\n" " ]\n" " }\n" " texCoordIndex\n" " [\n" ); int nn = 0; for(ind=0,fi=m.face.begin(); fi!=m.face.end(); ++fi,++ind) if(!(*fi).IsD()) { //if(fi!=m.face.begin()) fprintf(fp,", "); if(ind%4==0) fprintf(fp,"\n "); for (int j = 0; j < 3; j++) fprintf(fp,"%d ",nn++); fprintf(fp,"-1 "); } fprintf(fp, "\n" " ]\n" ); } fprintf(fp, " coordIndex\n" " [" ); // Facce for(ind=0,fi=m.face.begin(); fi!=m.face.end(); ++fi,++ind) if(!(*fi).IsD()) { if(fi!=m.face.begin()) fprintf(fp,", "); if(ind%6==0) fprintf(fp,"\n "); for (int j = 0; j < 3; j++) fprintf(fp,"%i,",index[(*fi).V(j)]); fprintf(fp,"-1"); } fprintf(fp, "\n" " ]\n" " }\n" " appearance Appearance\n" " {\n" " material Material\n" " {\n" " ambientIntensity 0.2\n" " diffuseColor 0.9 0.9 0.9\n" " specularColor .1 .1 .1\n" " shininess .5\n" " }\n" ); if(m.textures.size()) { fprintf(fp, " texture ImageTexture { url \" %s \" }\n" ,m.textures[0].c_str() ); } fprintf(fp, " }\n" " }\n" " ]\n" "}\n" ); fclose(fp); return 0; } ///Returns mask of capability one define with what are the saveable information of the format. static int GetExportMaskCapability() { int capability = 0; //vert capability |= MeshModel::IOM_VERTCOLOR; //wedg capability |= MeshModel::IOM_WEDGTEXCOORD; capability |= MeshModel::IOM_WEDGCOLOR; return capability; } /// Standard call for knowing the meaning of an error code static const char *ErrorMsg(int error) { static std::vector wrl_error_msg; if(wrl_error_msg.empty()) { wrl_error_msg.resize(2 ); wrl_error_msg[0]="No errors"; wrl_error_msg[1]="Can't open file"; } if(error>1 || error<0) return "Unknown error"; else return wrl_error_msg[error].c_str(); } }; // end class } // end Namespace io } // end Namespace tri } // end Namespace vcg #endifqutemol/vcg/wrap/io_trimesh/export.h0000444000175000017500000001227711001102624016202 0ustar mbamba/**************************************************************************** * VCGLib o o * * Visual and Computer Graphics Library o o * * _ O _ * * Copyright(C) 2004 \/)\/ * * Visual Computing Lab /\/| * * ISTI - Italian National Research Council | * * \ * * All rights reserved. * * * * 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. * * * * 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 (http://www.gnu.org/licenses/gpl.txt) * * for more details. * * * ****************************************************************************/ /**************************************************************************** History $Log: export.h,v $ Revision 1.7 2008/04/15 10:38:12 cignoni added suppor of color in OFF format. Revision 1.6 2006/11/04 14:01:00 granzuglia fixed bug: &(*filename.end()) ---> &(*filename.rbegin()) Revision 1.5 2006/07/09 05:32:15 cignoni Uncommented obj export. Now obj saving is enabled by default Revision 1.4 2006/03/29 08:14:20 corsini Add LoadMask to OFF importer Revision 1.3 2006/02/16 19:28:36 fmazzant transfer of Export_3ds.h, Export_obj.h, Io_3ds_obj_material.h from Meshlab to vcg Revision 1.2 2006/01/13 15:47:42 cignoni Uniformed return type to the style of Open. Now every export function returns 0 in case of success. Revision 1.1 2005/11/12 18:34:17 cignoni Initial Commit ****************************************************************************/ #ifndef __VCGLIB_TRIMESH_GENERIC_EXPORT #define __VCGLIB_TRIMESH_GENERIC_EXPORT #include #include #include #include #include #include namespace vcg { namespace tri { namespace io { /** This class encapsulate a filter for automatically importing meshes by guessing the right filter according to the extension */ template class Exporter { private: enum KnownTypes { KT_UNKNOWN, KT_PLY, KT_STL, KT_DXF, KT_OFF, KT_OBJ}; static int &LastType() { static int lastType= KT_UNKNOWN; return lastType; } public: // simple aux function that returns true if a given file has a given extesnion static bool FileExtension(std::string filename, std::string extension) { std::locale loc1 ; std::use_facet > ( loc1 ).tolower(&*filename.begin(),&(*filename.rbegin())); std::use_facet > ( loc1 ).tolower(&*extension.begin(),&(*extension.rbegin())); std::string end=filename.substr(filename.length()-extension.length(),extension.length()); return end==extension; } // Open Mesh static int Save(OpenMeshType &m, const char *filename, CallBackPos *cb=0) { return Save(m,filename,0,cb); } // Open Mesh static int Save(OpenMeshType &m, const char *filename, const int mask, CallBackPos *cb=0) { int err; if(FileExtension(filename,"ply")) { err = ExporterPLY::Save(m,filename,mask); LastType()=KT_PLY; } else if(FileExtension(filename,"stl")) { err = ExporterSTL::Save(m,filename); LastType()=KT_STL; } else if(FileExtension(filename,"off")) { err = ExporterOFF::Save(m,filename,mask); LastType()=KT_OFF; } else if(FileExtension(filename,"dxf")) { err = ExporterDXF::Save(m,filename); LastType()=KT_DXF; } else if(FileExtension(filename,"obj")) { err = ExporterOBJ::Save(m,filename,mask,cb); LastType()=KT_OBJ; } else { err=1; LastType()=KT_UNKNOWN; } return err; } static const char *ErrorMsg(int error) { switch(LastType()) { case KT_PLY : return ExporterPLY::ErrorMsg(error); break; case KT_STL : return ExporterSTL::ErrorMsg(error); break; case KT_OFF : return ExporterOFF::ErrorMsg(error); break; case KT_DXF : return ExporterDXF::ErrorMsg(error); break; case KT_OBJ : return ExporterOBJ::ErrorMsg(error); break; } return "Unknown type"; } }; // end class } // end Namespace tri } // end Namespace io } // end Namespace vcg #endif qutemol/vcg/wrap/io_trimesh/import_vmi.h0000444000175000017500000001532610567016021017057 0ustar mbamba/**************************************************************************** * VCGLib o o * * Visual and Computer Graphics Library o o * * _ O _ * * Copyright(C) 2004 \/)\/ * * Visual Computing Lab /\/| * * ISTI - Italian National Research Council | * * \ * * All rights reserved. * * * * 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. * * * * 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 (http://www.gnu.org/licenses/gpl.txt) * * for more details. * * * ****************************************************************************/ /**************************************************************************** History $Log: import_vmi.h,v $ Revision 1.2 2007/02/21 10:16:49 ganovelli added GetHeader Revision 1.1 2007/02/14 01:20:37 ganovelli working draft of VCG Mesh Image importer and exporter. Does not consider optional attributes. The mesh atributes are only vn and fn (no bbox, texture coordiantes) ****************************************************************************/ #ifndef __VCGLIB_IMPORT_VMI #define __VCGLIB_IMPORT_VMI /* VMI VCG Mesh Image. The vmi image file consists of a header containing the description of the vertex and face type, the length of vectors containing vertices of faces and the memory image of the object mesh as it is when passed to the function Save(SaveMeshType m) */ namespace vcg { namespace tri { namespace io { template class ImporterVMI { public: typedef typename OpenMeshType::FaceIterator FaceIterator; typedef typename OpenMeshType::VertexIterator VertexIterator; typedef typename OpenMeshType::VertexType VertexType; static bool GetHeader(FILE * f,std::vector& fnameV, std::vector& fnameF, int & vertSize, int &faceSize){ char name[100]; char buf[4096]; int nameFsize,nameVsize,i; fgets(buf,4096,f); sscanf(buf,"%s %d",&name[0],&nameFsize); for(i=0; i < nameFsize; ++i) { fgets(buf,4096,f); sscanf(buf,"%s ",&name[0]);fnameF.push_back(std::string(name)); } fgets(buf,4096,f); sscanf(buf,"%s %d",&name[0],&faceSize); fgets(buf,4096,f); sscanf(buf,"%s %d",&name[0],&nameVsize); for(i=0; i < nameVsize; ++i) { fgets(buf,4096,f); sscanf(buf,"%s ",&name[0]);fnameV.push_back(std::string(name));} fgets(buf,4096,f); sscanf(buf,"%s %d",&name[0],&vertSize); fgets(buf,4096,f); assert(strstr(buf,"end_header")!=NULL); return true; } static bool GetHeader(char * filename,std::vector& nameV, std::vector& nameF, int & vertSize, int &faceSize){ FILE * f = fopen(filename,"rb"); return GetHeader(f,nameV, nameF, vertSize, faceSize); fclose(f); } static bool Open(OpenMeshType &m,char * filename){ int i; OpenMeshType::FaceIterator fi; OpenMeshType::VertexIterator vi; FILE * f = fopen(filename,"rb"); std::vector nameF,nameV,fnameF,fnameV; int vertSize,faceSize; /* read the header */ GetHeader(f,fnameV, fnameF, vertSize, faceSize); /* read the mesh type */ OpenMeshType::FaceType::Name(nameF); OpenMeshType::VertexType::Name(nameV); /* check if the type is the very same, otherwise return */ if(fnameV != nameV) return false; if(fnameF != nameF) return false; int offsetV,offsetF; /* read the address of the first vertex */ fread(&offsetV,sizeof( int),1,f); /* read the address of the first face */ fread(&offsetF,sizeof( int),1,f); /* read the object mesh */ fread(&m,sizeof(OpenMeshType),1,f); /* overwrite che container because they could be inconsistent */ OpenMeshType::VertContainer tvc; OpenMeshType::FaceContainer tfc; memcpy(&m.vert,&tvc,sizeof(OpenMeshType::VertContainer)); memcpy(&m.face,&tfc,sizeof(OpenMeshType::FaceContainer)); m.vert.resize(vertSize); int read; /* load the vertices */ read=fread((void*)& m.vert[0],sizeof(OpenMeshType::VertexType),vertSize,f); assert(ferror(f)==0); assert(read==vertSize); m.face.resize(faceSize); /* load the faces */ read = fread((void*)& m.face[0],sizeof(OpenMeshType::FaceType),faceSize,f); assert(ferror(f)==0); assert(!feof(f)); assert(read==faceSize); if(OpenMeshType::FaceType::HasVFAdjacency()) for(vi = m.vert.begin(); vi != m.vert.end(); ++vi){ (*vi).VFp() = (*vi).VFp()-(OpenMeshType::FaceType*)offsetF+ &m.face[0]; (*vi).VFp() = (*vi).VFp()-(OpenMeshType::FaceType*)offsetF+ &m.face[0]; (*vi).VFp() = (*vi).VFp()-(OpenMeshType::FaceType*)offsetF+ &m.face[0]; } if(OpenMeshType::FaceType::HasVertexRef()) for(fi = m.face.begin(); fi != m.face.end(); ++fi){ (*fi).V(0) = (*fi).V(0)-(OpenMeshType::VertexType*)offsetV+ &m.vert[0]; (*fi).V(1) = (*fi).V(1)-(OpenMeshType::VertexType*)offsetV+ &m.vert[0]; (*fi).V(2) = (*fi).V(2)-(OpenMeshType::VertexType*)offsetV+ &m.vert[0]; } if(OpenMeshType::FaceType::HasFFAdjacency()) for(fi = m.face.begin(); fi != m.face.end(); ++fi){ (*fi).FFp(0) = (*fi).FFp(0)-(OpenMeshType::FaceType*)offsetF+ &m.face[0]; (*fi).FFp(1) = (*fi).FFp(1)-(OpenMeshType::FaceType*)offsetF+ &m.face[0]; (*fi).FFp(2) = (*fi).FFp(2)-(OpenMeshType::FaceType*)offsetF+ &m.face[0]; } if(OpenMeshType::FaceType::HasVFAdjacency()) for(fi = m.face.begin(); fi != m.face.end(); ++fi){ (*fi).VFp(0) = (*fi).VFp(0)-(OpenMeshType::FaceType*)offsetF+ &m.face[0]; (*fi).VFp(1) = (*fi).VFp(1)-(OpenMeshType::FaceType*)offsetF+ &m.face[0]; (*fi).VFp(2) = (*fi).VFp(2)-(OpenMeshType::FaceType*)offsetF+ &m.face[0]; } fclose(f); } }; // end class } // end Namespace tri } // end Namespace io } // end Namespace vcg #endif qutemol/vcg/wrap/io_trimesh/export_u3d.h0000444000175000017500000001721710771132315016771 0ustar mbamba#ifndef __VCGLIB_EXPORTERU3D #define __VCGLIB_EXPORTERU3D #include #include #include #include #include #include #include #include "export_idtf.h" #include namespace vcg { namespace tri { namespace io { namespace u3dparametersclasses { struct IDTFConverterParameters { const QString _converter_loc; const QString _input_file; const QString _output_file; int positionQuality; IDTFConverterParameters(const QString& converter_loc,const QString& input_file,const QString& output_file) :_converter_loc(converter_loc),_input_file(input_file),_output_file(output_file) { } }; struct Movie15Parameters { Movie15Parameters() { _campar = NULL; } //WARNING: in movie15 y-axis and z-axis have been inverted!!! class CameraParameters { public: CameraParameters() :_cam_fov_angle(0.0f),_cam_roll_angle(0.0f),_obj_to_cam_dir(vcg::Point3f(0.0f,0.0f,0.0f)),_obj_to_cam_dist(0.0f),_obj_bbox_diag(0.0f),_obj_pos(vcg::Point3f(0.0f,0.0f,0.0f)) { } CameraParameters(const vcg::Point3f& mesh_center,const float mesh_bbox_diag) :_cam_fov_angle(0.0f),_cam_roll_angle(0.0f),_obj_to_cam_dir(vcg::Point3f(0.0f,0.0f,mesh_bbox_diag)),_obj_to_cam_dist(0.0),_obj_pos(mesh_center),_obj_bbox_diag(mesh_bbox_diag) { } CameraParameters(const float cam_fov_angle,const float cam_roll_angle, const vcg::Point3f& obj_to_cam_dir,const float obj_to_cam_dist, const float obj_bbox_diag, const vcg::Point3f& obj_pos = vcg::Point3f(0.0f,0.0f,0.0f)) :_cam_fov_angle(cam_fov_angle),_cam_roll_angle(cam_roll_angle),_obj_to_cam_dir(obj_to_cam_dir),_obj_to_cam_dist(obj_to_cam_dist),_obj_pos(obj_pos),_obj_bbox_diag(obj_bbox_diag) { } float _cam_fov_angle; float _cam_roll_angle; vcg::Point3f _obj_to_cam_dir; float _obj_to_cam_dist; vcg::Point3f _obj_pos; float _obj_bbox_diag; }; CameraParameters* _campar; int positionQuality; }; } template class ExporterU3D { public: enum U3DError { E_NOERROR, // 0 E_ABORTED_CONVERSION //1 }; static const char *ErrorMsg(int error) { static const char * dae_error_msg[] = { "No errors", "Conversion Process From Idtf intermediate file to U3D format aborted" }; if(error>1 || error<0) return "Unknown error"; else return dae_error_msg[error]; }; static void substituteChar(QString& st,const QChar& ch_remove,const QString& sub) { int ii = 0; while ((ii = st.indexOf(ch_remove,ii)) != -1) st = st.replace(ii,1,sub); } private: static int InvokeConverter(const u3dparametersclasses::IDTFConverterParameters& par) { QProcess p; QString convstring = par._converter_loc; #if defined(Q_OS_WIN) convstring = "\""+convstring + "\" -en 1 -rzf 0 -pq "+QString::number(par.positionQuality)+" -input \"" + par._input_file + "\" -output \"" + par._output_file +"\""; #else QString mac_input=par._input_file; QString mac_output=par._output_file; //mac_input.replace(QString(" "),QString("\\ ")); //mac_output.replace(QString(" "),QString("\\ ")); convstring = convstring + " -en 1 -rzf 0 -pq "+ QString::number(par.positionQuality)+" -input \"" + mac_input + "\" -output \"" + mac_output +"\""; #endif //QMessageBox::warning(0, QString("Saving Log"), QString("Started conversion executable '%1'").arg(convstring)); qDebug("Starting converter %s", qPrintable(convstring)); p.setProcessChannelMode(QProcess::MergedChannels); p.start(convstring); //wait until the task has been completed bool t = p.waitForFinished(-1); if(!t) QMessageBox::warning(0, QString("Saving Error"), QString("Failed conversion executable '%1'").arg(convstring)); p.close(); return (int) t; } static void SaveLatex(SaveMeshType& /*m*/,const QString& file,const u3dparametersclasses::Movie15Parameters& mov_par) { Output_File latex(file.toStdString() + ".tex"); QString u3df = file + ".u3d"; QStringList file_trim; QtUtilityFunctions::splitFilePath(u3df,file_trim); std::string u3d_final = QtUtilityFunctions::fileNameFromTrimmedPath(file_trim).toStdString(); latex.write(0,"\\documentclass[a4paper]{article}"); latex.write(0,"\\usepackage[3D]{movie15}"); latex.write(0,"\\usepackage[UKenglish]{babel}"); latex.write(0,"\\begin{document}"); latex.write(0,"\\includemovie["); latex.write(1,"poster,"); latex.write(1,"toolbar, %same as `controls\'"); QString u3d_text = QString::fromStdString(u3d_final); substituteChar(u3d_text,QChar('_'),QString("")); latex.write(1,"label=" + u3d_text.toStdString() + ","); latex.write(1,"text=(" + u3d_text.toStdString() + "),"); std::string cam_string; u3dparametersclasses::Movie15Parameters::CameraParameters* cam = mov_par._campar; if (cam != NULL) { cam_string = cam_string + "3Daac=" + TextUtility::nmbToStr(cam->_cam_fov_angle) + ", 3Droll=" + TextUtility::nmbToStr(cam->_cam_roll_angle) + ", 3Dc2c=" + TextUtility::nmbToStr(cam->_obj_to_cam_dir.X()) + " " + TextUtility::nmbToStr(cam->_obj_to_cam_dir.Z()) + " " + TextUtility::nmbToStr(cam->_obj_to_cam_dir.Y()) + ", 3Droo=" + TextUtility::nmbToStr(cam->_obj_to_cam_dist) + ", 3Dcoo=" + TextUtility::nmbToStr(-cam->_obj_pos.X()) + " " + TextUtility::nmbToStr(cam->_obj_pos.Z()) + " " + TextUtility::nmbToStr(cam->_obj_pos.Y()) + ","; latex.write(1,cam_string); } latex.write(1,"3Dlights=CAD,"); latex.write(0,"]{\\linewidth}{\\linewidth}{" + u3d_final + "}"); latex.write(0,"\\end{document}"); } public: static int Save(SaveMeshType& m,const char* output_file,const char* conv_loc,const u3dparametersclasses::Movie15Parameters& mov_par,const int mask) { QString curr = QDir::currentPath(); QString out(output_file); QStringList out_trim; QtUtilityFunctions::splitFilePath(out,out_trim); QString tmp(QDir::tempPath()); tmp = tmp + "/" + QtUtilityFunctions::fileNameFromTrimmedPath(out_trim) + ".idtf"; QString conv_loc_st(conv_loc); QString output_file_st(output_file); ////if there are textures file that aren't in tga format I have to convert them ////I maintain the converted file name (i.e. file_path + originalname without extension + tga) in mesh.textures but I have to revert to the original ones ////before the function return. //QStringList oldtextname; //for(unsigned int ii = 0; ii < m.textures.size();++ii) // oldtextname.push_back(m.textures[ii].c_str()); ////tmp vector to save the tga created files that should be deleted. //QStringList convfile; //convertTexturesFiles(m,curr,convfile); vcg::tri::io::ExporterIDTF::Save(m,qPrintable(tmp),mask); u3dparametersclasses::IDTFConverterParameters idtfpar(conv_loc_st,tmp,output_file_st); idtfpar.positionQuality = mov_par.positionQuality; qDebug("conv_loc_st '%s'", qPrintable(conv_loc_st)); qDebug("conv_loc '%s'", conv_loc); qDebug("idtfpar._converter_loc '%s'", qPrintable(idtfpar._converter_loc)); int res = InvokeConverter(idtfpar); //m.textures.clear(); //for(QStringList::iterator it = oldtextname.begin(); it != oldtextname.end();++it) // m.textures.push_back(it->toStdString()); ////if some tga files have been created I have to delete them //removeConvertedTexturesFiles(convfile); QDir::setCurrent(curr); QString lat (output_file); QStringList l = lat.split("."); SaveLatex(m,l[0],mov_par); QDir dir(QDir::tempPath()); dir.remove(tmp); if (res) return 0; else return 1; } static int GetExportMaskCapability() { int capability = 0; //vert //capability |= Mask::IOM_VERTNORMAL; //capability |= vcg::tri::io::Mask::IOM_VERTCOLOR; ////wedg capability |= Mask::IOM_WEDGTEXCOORD; //capability |= Mask::IOM_WEDGNORMAL; return capability; } }; } } } #endif qutemol/vcg/wrap/io_trimesh/export_dae.h0000444000175000017500000000243510752120335017021 0ustar mbamba#ifndef EXPORTER_DAE_H #define EXPORTER_DAE_H #include #include #include namespace vcg { namespace tri { namespace io { template class ExporterDAE { public: static int Save(const MESHMODEL& model,const char* filename,const int mask,const QDomDocument* doc = NULL) { XMLDocumentWriter stream(filename); if (stream.isReliable()) { XMLDocument* document = Collada::DocumentManager::createColladaDocument(model,mask); stream.write(*document); Collada::DocumentManager::destroyColladaDocument(document); return UtilDAE::E_NOERROR; } else return UtilDAE::E_CANTSAVE; } static int GetExportMaskCapability() { int capability = 0; //camera //capability |= MeshModel::IOM_CAMERA; //vert capability |= MeshModel::IOM_VERTNORMAL; capability |= MeshModel::IOM_VERTTEXCOORD; capability |= MeshModel::IOM_VERTCOLOR; //capability |= MeshModel:: ////face ////capability |= MeshModel::IOM_FACEFLAGS; ////capability |= MeshModel::IOM_FACECOLOR; //capability |= MeshModel::IOM_FACENORMAL; ////wedg capability |= MeshModel::IOM_WEDGTEXCOORD; capability |= MeshModel::IOM_WEDGNORMAL; return capability; } }; } } } #endif qutemol/vcg/wrap/io_trimesh/io_ply.h0000444000175000017500000001072610066321614016165 0ustar mbamba/**************************************************************************** * VCGLib o o * * Visual and Computer Graphics Library o o * * _ O _ * * Copyright(C) 2004 \/)\/ * * Visual Computing Lab /\/| * * ISTI - Italian National Research Council | * * \ * * All rights reserved. * * * * 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. * * * * 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 (http://www.gnu.org/licenses/gpl.txt) * * for more details. * * * ****************************************************************************/ /**************************************************************************** History $Log: io_ply.h,v $ Revision 1.4 2004/06/23 15:36:44 cignoni Restructured management of error, now the standard open for any mesh type return the error code, the default success value is zero Any import class has a method ErrorMsg that give a verbal description of an error code. Revision 1.3 2004/05/12 10:19:30 ganovelli new line added at the end of file Revision 1.2 2004/03/09 21:26:47 cignoni cr lf mismatch Revision 1.1 2004/03/08 09:21:34 cignoni Initial commit Revision 1.1 2004/03/03 15:00:51 cignoni Initial commit ****************************************************************************/ #ifndef __VCGLIB_IOTRIMESH_IO_PLY #define __VCGLIB_IOTRIMESH_IO_PLY /** @name Load and Save in Ply format */ //@{ #include #include namespace vcg { namespace tri { namespace io { /** Additional data needed or useful for parsing a ply mesh. This class can be passed to the ImporterPLY::Open() function for - retrieving additional per-vertex per-face data - specifying a callback for long ply parsing - knowing what data is contained in a ply file */ class PlyInfo { public: typedef ::vcg::ply::PropDescriptor PropDescriptor ; PlyInfo() { status=0; mask=0; cb=0; vdn=fdn=0; VertexData=FaceData=0; } /// Store the error codes enconutered when parsing a ply int status; /// It returns a bit mask describing the field preesnt in the ply file int mask; /// a Simple callback that can be used for long ply parsing. // it returns the current position, and formats a string with a description of what th efunction is doing (loading vertexes, faces...) CallBackPos *cb; /// the number of per-vertex descriptor (usually 0) int vdn; /// The additional vertex descriptor that a user can specify to load additional per-vertex non-standard data stored in a ply PropDescriptor *VertexData; /// the number of per-face descriptor (usually 0) int fdn; /// The additional vertex descriptor that a user can specify to load additional per-face non-standard data stored in a ply PropDescriptor *FaceData; /// a string containing the current ply header. Useful for showing it to the user. std::string header; enum Error { // Funzioni superiori E_NO_VERTEX = ply::E_MAXPLYERRORS+1, // 14 E_NO_FACE = ply::E_MAXPLYERRORS+2, // 15 E_SHORTFILE = ply::E_MAXPLYERRORS+3, // 16 E_NO_3VERTINFACE = ply::E_MAXPLYERRORS+4, // 17 E_BAD_VERT_INDEX = ply::E_MAXPLYERRORS+5, // 18 E_NO_6TCOORD = ply::E_MAXPLYERRORS+6, // 19 E_DIFFER_COLORS = ply::E_MAXPLYERRORS+7, E_MAXPLYINFOERRORS= ply::E_MAXPLYERRORS+8// 20 }; }; // end class } // end namespace tri } // end namespace io } // end namespace vcg #endif qutemol/vcg/wrap/io_trimesh/export_off.h0000444000175000017500000001427711001102624017036 0ustar mbamba/**************************************************************************** * VCGLib o o * * Visual and Computer Graphics Library o o * * _ O _ * * Copyright(C) 2004 \/)\/ * * Visual Computing Lab /\/| * * ISTI - Italian National Research Council | * * \ * * All rights reserved. * * * * 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. * * * * 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 (http://www.gnu.org/licenses/gpl.txt) * * for more details. * * * ****************************************************************************/ /**************************************************************************** History $Log: export_off.h,v $ Revision 1.14 2008/04/15 10:38:12 cignoni added suppor of color in OFF format. Revision 1.13 2007/11/06 10:58:25 cignoni Changed the return value to the standard 0 in case of success and notzero for failures Revision 1.12 2007/03/12 16:40:17 tarini Texture coord name change! "TCoord" and "Texture" are BAD. "TexCoord" is GOOD. Revision 1.11 2006/12/07 00:37:58 cignoni Corrected bug in the management of deleted vertices ****************************************************************************/ /** @name Save in OFF format */ //@{ #ifndef __VCGLIB_EXPORT_OFF #define __VCGLIB_EXPORT_OFF #include #include namespace vcg { namespace tri { namespace io { template class ExporterOFF { public: typedef typename SaveMeshType::VertexPointer VertexPointer; typedef typename SaveMeshType::ScalarType ScalarType; typedef typename SaveMeshType::VertexType VertexType; typedef typename SaveMeshType::FaceType FaceType; typedef typename SaveMeshType::FacePointer FacePointer; typedef typename SaveMeshType::VertexIterator VertexIterator; typedef typename SaveMeshType::FaceIterator FaceIterator; static int Save(SaveMeshType &m, const char * filename, int mask=0 ) { vcg::face::Pos he; vcg::face::Pos hei; FILE * fpout = fopen(filename,"w"); if(fpout==NULL) return 1; // 1 is the error code for cant'open, see the ErrorMsg function if( m.HasPerVertexNormal() && (mask & io::Mask::IOM_VERTNORMAL)) fprintf(fpout,"N"); if( tri::HasPerVertexColor(m) && (mask & io::Mask::IOM_VERTCOLOR)) fprintf(fpout,"C"); if( tri::HasPerVertexTexCoord(m) && (mask & io::Mask::IOM_VERTTEXCOORD)) fprintf(fpout,"ST"); fprintf(fpout,"OFF\n"); fprintf(fpout,"%d %d 0\n", m.vn, m.fn); // note that as edge number we simply write zero typename SaveMeshType::FaceIterator fi; //vertices int j; std::vector FlagV; VertexPointer vp; VertexIterator vi; for(j=0,vi=m.vert.begin();vi!=m.vert.end();++vi) { vp=&(*vi); FlagV.push_back(vp->UberFlags()); // Salva in ogni caso flag del vertice if( ! vp->IsD() ) { // ***** ASCII ***** fprintf(fpout,"%g %g %g " ,vp->P()[0],vp->P()[1],vp->P()[2]); if( tri::HasPerVertexColor(m) && (mask & io::Mask::IOM_VERTCOLOR) ) fprintf(fpout,"%d %d %d %d ",vp->C()[0],vp->C()[1],vp->C()[2],vp->C()[3] ); if( m.HasPerVertexNormal() && (mask & io::Mask::IOM_VERTNORMAL) ) fprintf(fpout,"%g %g %g ", vp->N()[0],vp->N()[1],vp->N()[2]); if( m.HasPerVertexTexCoord() && (mask & io::Mask::IOM_VERTTEXCOORD) ) fprintf(fpout,"%g %g ",vp->T().u(),vp->T().v()); fprintf(fpout,"\n"); vp->UberFlags()=j; // Trucco! Nascondi nei flags l'indice del vertice non deletato! j++; } } assert(j==m.vn); FacePointer fp; // int vv[3]; int fcnt=0; for(j=0,fi=m.face.begin();fi!=m.face.end();++fi) { fp=&(*fi); if( ! fp->IsD() ) { fcnt++; fprintf(fpout,"3 %d %d %d\n", fp->cV(0)->UberFlags(), fp->cV(1)->UberFlags(), fp->cV(2)->UberFlags() ); } } fclose(fpout); // Recupera i flag originali for(j=0,vi=m.vert.begin();vi!=m.vert.end();++vi) (*vi).UberFlags()=FlagV[j++]; return 0; } static const char *ErrorMsg(int error) { static std::vector off_error_msg; if(off_error_msg.empty()) { off_error_msg.resize(2 ); off_error_msg[0]="No errors"; off_error_msg[1]="Can't open file"; } if(error>1 || error<0) return "Unknown error"; else return off_error_msg[error].c_str(); } /* returns mask of capability one define with what are the saveable information of the format. */ static int GetExportMaskCapability() { int capability = 0; capability |= vcg::tri::io::Mask::IOM_VERTCOORD; capability |= vcg::tri::io::Mask::IOM_VERTCOLOR; capability |= vcg::tri::io::Mask::IOM_FACEINDEX; return capability; } }; // end class } // end namespace tri } // end namespace io } // end namespace vcg //@} #endif qutemol/vcg/wrap/io_trimesh/import_raw.h0000444000175000017500000003034010535007023017043 0ustar mbamba/**************************************************************************** * VCGLib o o * * Visual and Computer Graphics Library o o * * _ O _ * * Copyright(C) 2004 \/)\/ * * Visual Computing Lab /\/| * * ISTI - Italian National Research Council | * * \ * * All rights reserved. * * * * 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. * * * * 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 (http://www.gnu.org/licenses/gpl.txt) * * for more details. * * * ****************************************************************************/ /**************************************************************************** History $Log: import_raw.h,v $ Revision 1.3 2006/12/04 12:01:23 spinelli add method for automatic hole filling.... Revision 1.2 2005/05/09 12:29:55 callieri added line cleaning to eliminate all separators, added a rough triangulation scheme. Revision 1.1 2005/05/06 13:58:26 callieri First working version (callieri) ****************************************************************************/ #ifndef __VCGLIB_IMPORT_RAW #define __VCGLIB_IMPORT_RAW #include #include #include namespace vcg { namespace tri { namespace io { /** This class encapsulate a filter for importing raw format pointcloud. there exists many raw formats. each one with a particular sintax even if they only contains */ template class ImporterRAW { public: typedef typename MESH_TYPE::VertexPointer VertexPointer; typedef typename MESH_TYPE::ScalarType ScalarType; typedef typename MESH_TYPE::VertexType VertexType; typedef typename MESH_TYPE::FaceType FaceType; typedef typename MESH_TYPE::VertexIterator VertexIterator; typedef typename MESH_TYPE::FaceIterator FaceIterator; // max token number #define RAW_MAX_TOKEN_LINE_DESCRIPTOR 32 enum RAWError { E_NOERROR, // 0 // Error open E_CANTOPEN, // 1 E_UNESPECTEDEOF, // 2 // error line descriptor E_INVALIDLINEDESC, // 3 // error line parsing E_LINEERROR, // 4 // wrong number of points E_WRONGPOINTNUM // 5 }; static const char *ErrorMsg(int error) { static const char * raw_error_msg[] = { "No errors", "Can't open file", "Premature End of file", "Invalid line Descriptor", "Error parsing a line", "Point number different from expected" }; if(error>2 || error<0) return "Unknown error"; else return stl_error_msg[error]; }; // line format is a string describing which data is stored for every data line // PX PY PZ posizione // NX NY NZ normale // CR CG CB colore // RF riflettanza (qualita') // // the string is parsed to know how many value are contained in each line // and which is the order. the result is a number (how many) and a vector // describing the order // // // during reading a data structure is used to store intermediate values // it is basically an array of float // // float linebuffer[] //[0][1][2][3][4][5][6][7][8][9] // p p p n n n c c c r // x y z x y z r g b f // // given the number of tokens and the order vector it is possible to scan a line using the command // // for(...n 0->tokennumber...) // fscanf(fp,"%f", &linebuffer[tokenorder[n]]) static int Parselinedescription(const char * linedesc, int &tokennumber, int *order) { int ii; char tok[3]; int index; // controllo lunghezza // se non e' multiplo di 3 allora e' errato int len = strlen(linedesc) + 1; if(len%3 != 0) return E_INVALIDLINEDESC; index=0; tok[2] = '\0'; tokennumber = 0; for(ii=0; ii0) || (ii<(linelen-2))) // if it's at the begin or the end of line, it's not an exponential if(isdigit(rawline[ii-1])) // a number before it if(isdigit(rawline[ii+1]) || (rawline[ii+1]=='+') || (rawline[ii+1]=='-')) // after it a number a plus or a minus change = false; } if(change) rawline[ii++] = ' '; // then change it to ' ' else ii++; } rawline[linelen] = '\0'; // now parsing the line foundtok = 0; ii = 0; while((foundtok(0,0,0)) && (m.vert[indL].P() != vcg::Point3(0,0,0)) && (m.vert[indR].P() != vcg::Point3(0,0,0)) && (m.vert[indT].P() != vcg::Point3(0,0,0)) && (m.vert[indB].P() != vcg::Point3(0,0,0)) ) { m.vert[ind].P() = ( m.vert[indL].P() + m.vert[indR].P() + m.vert[indT].P() + m.vert[indB].P() ) * 0.25; } } //vcg::tri::io::ExporterPLY::Save( hm, "hole.ply" ); return 1; } /*! * Standard call for reading a mesh * \param m the destination mesh * \param filename the name of the file to read from * \param triangulate if true, the mesh will be triangulated, otherwise only points will be stored * \param lineskip number of lines to be skipped at the begin of the file * \return the operation result */ static int Open( MESH_TYPE &m, const char * filename, bool triangulate=false, int lineskip = 0, const char * linedesc = "PX PY PZ") { int ii; int ret; FILE *fp; int rownumber; int colnumber; // line description int tokennumber; int tokenorder[RAW_MAX_TOKEN_LINE_DESCRIPTOR]; // line read from file, to be parsed char rawline[512]; //line data buffer float linebuffer[10]; // fill buffer with standard values linebuffer[0] = linebuffer[1] = linebuffer[2] = 0.0; linebuffer[3] = linebuffer[4] = linebuffer[5] = 1.0; linebuffer[6] = 0.0; linebuffer[7] = 1.0; linebuffer[8] = 0.0; linebuffer[9] = 1.0; fp = fopen(filename, "r"); if(fp == NULL) { return E_CANTOPEN; } // skip initial lines for(ii=0; ii0) // empty line, just skip { ret = Parseline(tokennumber, tokenorder, rawline, linebuffer); if(ret) return ret; /* // old code reading directly fom file stream for(ii=0; ii::AddFaces(m,trinum); m.fn = trinum; for(cc=0; cc namespace vcg { namespace tri { namespace io { /** @name Load and Save in Ply format */ //@{ class Mask { public: /* Bitmask for specifying what data has to be loaded or saved or it is present in a given plyfile; */ enum { IOM_NONE = 0x0000, IOM_VERTCOORD = 0x0001, IOM_VERTFLAGS = 0x0002, IOM_VERTCOLOR = 0x0004, IOM_VERTQUALITY = 0x0008, IOM_VERTNORMAL = 0x0010, IOM_VERTTEXCOORD = 0x0020, IOM_FACEINDEX = 0x0040, IOM_FACEFLAGS = 0x0080, IOM_FACECOLOR = 0x0100, IOM_FACEQUALITY = 0x0200, IOM_FACENORMAL = 0x0400, IOM_WEDGCOLOR = 0x0800, IOM_WEDGTEXCOORD = 0x1000, IOM_WEDGTEXMULTI = 0x2000, // Se ha anche l'indice di texture esplicito IOM_WEDGNORMAL = 0x4000, IOM_CAMERA = 0x8000, IOM_FLAGS = IOM_VERTFLAGS + IOM_FACEFLAGS, IOM_ALL = 0xFFFF }; // // //static void IOMask2String( int mask, char str[] ) //{ // str[0] = 0; // // strcat(str,"V:"); // if( mask & IOM_VERTFLAGS ) strcat(str,"flag,"); // if( mask & IOM_VERTCOLOR ) strcat(str,"color,"); // if( mask & IOM_VERTQUALITY ) strcat(str,"quality,"); // if( mask & IOM_VERTTEXCOORD ) strcat(str,"texcoord,"); // if( mask & IOM_VERTNORMAL ) strcat(str,"normal,"); // // strcat(str," F:"); // if( mask & IOM_FACEFLAGS ) strcat(str,"mask,"); // if( mask & IOM_FACECOLOR ) strcat(str,"color,"); // if( mask & IOM_FACEQUALITY ) strcat(str,"quality,"); // if( mask & IOM_FACENORMAL ) strcat(str,"normal,"); // // strcat(str," W:"); // if( mask & IOM_WEDGCOLOR ) strcat(str,"color,"); // if( mask & IOM_WEDGTEXCOORD ) strcat(str,"texcoord,"); // if( mask & IOM_WEDGNORMAL ) strcat(str,"normal,"); // // if( mask & IOM_CAMERA ) strcat(str," camera"); //} template static void ClampMask(MeshType &m, int &mask) { if( (mask & IOM_FACECOLOR) && !HasPerFaceColor(m) ) mask = mask & (~IOM_FACECOLOR); if( (mask & IOM_WEDGTEXCOORD) && !HasPerWedgeTexCoord(m) ) mask = mask & (~IOM_WEDGTEXCOORD); if( (mask & IOM_WEDGNORMAL) && !m.HasPerWedgeNormal() ) mask = mask & (~IOM_WEDGNORMAL); if( (mask & IOM_VERTCOLOR) && !m.HasPerVertexColor() ) mask = mask & (~IOM_VERTCOLOR); } }; // end class //@} } // end namespace tri } // end namespace io } // end namespace vcg #endif qutemol/vcg/wrap/io_trimesh/export_vmi.h0000444000175000017500000001035510567016160017067 0ustar mbamba/**************************************************************************** * VCGLib o o * * Visual and Computer Graphics Library o o * * _ O _ * * Copyright(C) 2004 \/)\/ * * Visual Computing Lab /\/| * * ISTI - Italian National Research Council | * * \ * * All rights reserved. * * * * 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. * * * * 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 (http://www.gnu.org/licenses/gpl.txt) * * for more details. * * * ****************************************************************************/ /**************************************************************************** History $Log: export_vmi.h,v $ Revision 1.2 2007/02/21 10:18:24 ganovelli moved the vn and fn in the writig of the header Revision 1.1 2007/02/14 01:20:37 ganovelli working draft of VCG Mesh Image importer and exporter. Does not consider optional attributes. The mesh atributes are only vn and fn (no bbox, texture coordiantes) ****************************************************************************/ #ifndef __VCGLIB_EXPORT_VMI #define __VCGLIB_EXPORT_VMI /* VMI VCG Mesh Image. The vmi image file consists of a header containing the description of the vertex and face type, the length of vectors containing vertices of faces and the memory image of the object mesh as it is when passed to the function Save(SaveMeshType m) */ namespace vcg { namespace tri { namespace io { template class ExporterVMI { public: typedef typename SaveMeshType::FaceIterator FaceIterator; typedef typename SaveMeshType::VertexIterator VertexIterator; typedef typename SaveMeshType::VertexType VertexType; static void Save(const SaveMeshType &m,char * filename){ unsigned int i; int vertSize,faceSize; FILE * f = fopen(filename,"wb"); std::vector nameF,nameV; SaveMeshType::FaceType::Name(nameF); SaveMeshType::VertexType::Name(nameV); vertSize = m.vert.size(); faceSize = m.face.size(); /* write header */ fprintf(f,"FACE_TYPE %d\n",nameF.size()); for(i=0; i < nameF.size(); ++i) fprintf(f,"%s\n",nameF[i].c_str()); fprintf(f,"SIZE_VECTOR_FACES %d\n",faceSize); fprintf(f,"VERTEX_TYPE %d\n",nameV.size()); for(i=0; i < nameV.size(); ++i) fprintf(f,"%s\n",nameV[i].c_str()); fprintf(f,"SIZE_VECTOR_VERTS %d\n",vertSize); fprintf(f,"end_header\n"); unsigned int offsetV = (unsigned int) &m.vert[0]; /* write the address of the first vertex */ fwrite(&offsetV,sizeof(unsigned int),1,f); int offsetF= ( int) &m.face[0]; /* write the address of the first face */ fwrite(&offsetF,sizeof( int),1,f); /* save the object mesh */ fwrite(&m,sizeof(SaveMeshType),1,f); int written; /* save the vertices */ written = fwrite((void*)&m.vert[0],sizeof(SaveMeshType::VertexType),m.vert.size(),f); assert(written==m.vert.size()); /* save the faces */ written = fwrite((void*)&m.face[0],sizeof(SaveMeshType::FaceType),m.face.size(),f); assert(written==m.face.size()); // fflush(f); fclose(f); } }; // end class } // end Namespace tri } // end Namespace io } // end Namespace vcg #endif qutemol/vcg/wrap/io_trimesh/export_ply.h0000444000175000017500000005751011013343777017110 0ustar mbamba/**************************************************************************** * VCGLib o o * * Visual and Computer Graphics Library o o * * _ O _ * * Copyright(C) 2004 \/)\/ * * Visual Computing Lab /\/| * * ISTI - Italian National Research Council | * * \ * * All rights reserved. * * * * 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. * * * * 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 (http://www.gnu.org/licenses/gpl.txt) * * for more details. * * * ****************************************************************************/ /**************************************************************************** History $Log: export_ply.h,v $ Revision 1.31 2008/05/16 17:44:31 cignoni updated to the new temporary data structure Revision 1.30 2008/04/29 11:51:28 corsini set defaut callback (in save) to null Revision 1.29 2008/01/24 11:54:23 cignoni passed the callback in the save Revision 1.28 2007/12/13 00:20:34 cignoni removed harmless printf cast warnings Revision 1.27 2007/11/06 10:59:41 ponchio Typo Revision 1.26 2007/11/06 10:51:55 ponchio Fixed wrong 'return false' in Save. Revision 1.25 2007/10/22 14:47:19 cignoni Added saving of per vertex normals Revision 1.24 2007/07/23 13:27:50 tarini fixed bug on saving flags-per-face Revision 1.23 2007/03/12 16:40:17 tarini Texture coord name change! "TCoord" and "Texture" are BAD. "TexCoord" is GOOD. Revision 1.22 2007/02/18 08:01:07 cignoni Added missing typename Revision 1.21 2007/02/14 16:07:41 ganovelli added HasPerFaceFlag Revision 1.20 2007/02/14 15:40:20 ganovelli a wrong "!" corrected Revision 1.19 2007/02/14 15:30:13 ganovelli added treatment of HasPerVertexFlags absent Revision 1.18 2006/12/18 09:46:39 callieri camera+shot revamp: changed field names to something with more sense, cleaning of various functions, correction of minor bugs/incongruences, removal of the infamous reference in shot. Revision 1.17 2006/11/30 22:49:32 cignoni Added save with (unused) callback Revision 1.16 2006/10/14 00:39:22 cignoni Added a comment on an assert Revision 1.15 2006/01/30 13:43:59 cignoni Added GetExportMaskCapability Revision 1.14 2006/01/27 09:11:48 corsini fix signed/unsigned mismatch Revision 1.13 2006/01/13 15:47:43 cignoni Uniformed return type to the style of Open. Now every export function returns 0 in case of success. Revision 1.12 2006/01/10 13:20:42 cignoni Changed ply::PlyMask to io::Mask Revision 1.11 2005/11/23 15:48:25 pietroni changed shot::similarity to shot::Similarity() and shot::camera to shot::Camera() Revision 1.10 2004/10/28 00:52:45 cignoni Better Doxygen documentation Revision 1.9 2004/10/27 09:33:10 ganovelli cast from scalar type to float added Revision 1.8 2004/10/07 14:19:06 ganovelli shot/camera io added Revision 1.7 2004/07/15 10:54:48 ganovelli std added Revision 1.6 2004/05/28 14:11:13 ganovelli changes to comply io_mask moving in vcg::ply namesp Revision 1.5 2004/05/12 14:43:36 cignoni removed warning of unused variables Revision 1.4 2004/05/12 10:19:30 ganovelli new line added at the end of file Revision 1.3 2004/03/18 15:30:46 cignoni Removed float/double warning Revision 1.2 2004/03/09 21:26:47 cignoni cr lf mismatch Revision 1.1 2004/03/08 09:21:33 cignoni Initial commit Revision 1.1 2004/03/03 15:00:51 cignoni Initial commit ****************************************************************************/ /** @name Load and Save in Ply format */ //@{ #ifndef __VCGLIB_EXPORT_PLY #define __VCGLIB_EXPORT_PLY //#include #include #include #include #include namespace vcg { namespace tri { namespace io { template class ExporterPLY { // Si occupa di convertire da un tipo all'altro. // usata nella saveply per matchare i tipi tra stotype e memtype. // Ad es se in memoria c'e' un int e voglio salvare un float // src sara in effetti un puntatore a int il cui valore deve // essere convertito al tipo di ritorno desiderato (stotype) template static void PlyConv(int mem_type, void *src, StoType &dest) { switch (mem_type){ case ply::T_FLOAT : dest = (StoType) (* ((float *) src)); break; case ply::T_DOUBLE: dest = (StoType) (* ((double *) src)); break; case ply::T_INT : dest = (StoType) (* ((int *) src)); break; case ply::T_SHORT : dest = (StoType) (* ((short *) src)); break; case ply::T_CHAR : dest = (StoType) (* ((char *) src)); break; case ply::T_UCHAR : dest = (StoType) (* ((unsigned char *)src)); break; default : assert(0); } } public: typedef ::vcg::ply::PropDescriptor PropDescriptor ; typedef typename SaveMeshType::VertexPointer VertexPointer; typedef typename SaveMeshType::ScalarType ScalarType; typedef typename SaveMeshType::VertexType VertexType; typedef typename SaveMeshType::FaceType FaceType; typedef typename SaveMeshType::FacePointer FacePointer; typedef typename SaveMeshType::VertexIterator VertexIterator; typedef typename SaveMeshType::FaceIterator FaceIterator; static int Save(SaveMeshType &m, const char * filename, bool binary=true) { PlyInfo pi; return Save(m,filename,binary,pi); } static int Save(SaveMeshType &m, const char * filename, int savemask, CallBackPos *cb=0 ) { PlyInfo pi; pi.mask=savemask; return Save(m,filename,true,pi,cb); } static int Save(SaveMeshType &m, const char * filename, bool binary, PlyInfo &pi, CallBackPos *cb=0) // V1.0 { FILE * fpout; int i; const char * hbin = "binary_little_endian"; const char * hasc = "ascii"; const char * h; bool multit = false; if(binary) h=hbin; else h=hasc; fpout = fopen(filename,"wb"); if(fpout==NULL) { pi.status=::vcg::ply::E_CANTOPEN; return ::vcg::ply::E_CANTOPEN; } fprintf(fpout, "ply\n" "format %s 1.0\n" "comment VCGLIB generated\n" ,h ); if( pi.mask & Mask::IOM_WEDGTEXCOORD ) { const char * TFILE = "TextureFile"; for(i=0; i < static_cast(m.textures.size()); ++i) fprintf(fpout,"comment %s %s\n", TFILE, (const char *)(m.textures[i].c_str()) ); if(m.textures.size()>1 && (m.HasPerWedgeTexCoord() || m.HasPerVertexTexCoord())) multit = true; } if((pi.mask & Mask::IOM_CAMERA)) { fprintf(fpout, "element camera 1\n" "property float view_px\n" "property float view_py\n" "property float view_pz\n" "property float x_axisx\n" "property float x_axisy\n" "property float x_axisz\n" "property float y_axisx\n" "property float y_axisy\n" "property float y_axisz\n" "property float z_axisx\n" "property float z_axisy\n" "property float z_axisz\n" "property float focal\n" "property float scalex\n" "property float scaley\n" "property float centerx\n" "property float centery\n" "property int viewportx\n" "property int viewporty\n" "property float k1\n" "property float k2\n" "property float k3\n" "property float k4\n" ); } fprintf(fpout, "element vertex %d\n" "property float x\n" "property float y\n" "property float z\n" ,m.vn ); if( m.HasPerVertexNormal() &&( pi.mask & Mask::IOM_VERTNORMAL) ) { fprintf(fpout, "property float nx\n" "property float ny\n" "property float nz\n" ); } if( m.HasPerVertexFlags() &&( pi.mask & Mask::IOM_VERTFLAGS) ) { fprintf(fpout, "property int flags\n" ); } if( m.HasPerVertexColor() && (pi.mask & Mask::IOM_VERTCOLOR) ) { fprintf(fpout, "property uchar red\n" "property uchar green\n" "property uchar blue\n" "property uchar alpha\n" ); } if( m.HasPerVertexQuality() && (pi.mask & Mask::IOM_VERTQUALITY) ) { fprintf(fpout, "property float quality\n" ); } for(i=0;i FlagV; VertexPointer vp; VertexIterator vi; SimpleTempData indices(m.vert); for(j=0,vi=m.vert.begin();vi!=m.vert.end();++vi){ vp=&(*vi); indices[j] = j; if( !m.HasPerVertexFlags() || !vp->IsD() ) { if(binary) { float t; t = float(vp->UberP()[0]); fwrite(&t,sizeof(float),1,fpout); t = float(vp->UberP()[1]); fwrite(&t,sizeof(float),1,fpout); t = float(vp->UberP()[2]); fwrite(&t,sizeof(float),1,fpout); if( m.HasPerVertexNormal() && (pi.mask & Mask::IOM_VERTNORMAL) ) { t = float(vp->N()[0]); fwrite(&t,sizeof(float),1,fpout); t = float(vp->N()[1]); fwrite(&t,sizeof(float),1,fpout); t = float(vp->N()[2]); fwrite(&t,sizeof(float),1,fpout); } if( m.HasPerVertexFlags() && (pi.mask & Mask::IOM_VERTFLAGS) ) fwrite(&(vp->UberFlags()),sizeof(int),1,fpout); if( m.HasPerVertexColor() && (pi.mask & Mask::IOM_VERTCOLOR) ) fwrite(&( vp->C() ),sizeof(char),4,fpout); if( m.HasPerVertexQuality() && (pi.mask & Mask::IOM_VERTQUALITY) ) fwrite(&( vp->Q() ),sizeof(float),1,fpout); for(i=0;iP()[0],vp->P()[1],vp->P()[2]); if( m.HasPerVertexNormal() && (pi.mask & Mask::IOM_VERTNORMAL) ) fprintf(fpout,"%g %g %g " ,double(vp->N()[0]),double(vp->N()[1]),double(vp->N()[2])); if( m.HasPerVertexFlags() && (pi.mask & Mask::IOM_VERTFLAGS)) fprintf(fpout,"%d ",vp->UberFlags()); if( m.HasPerVertexColor() && (pi.mask & Mask::IOM_VERTCOLOR) ) fprintf(fpout,"%d %d %d %d ",vp->C()[0],vp->C()[1],vp->C()[2],vp->C()[3] ); if( m.HasPerVertexQuality() && (pi.mask & Mask::IOM_VERTQUALITY) ) fprintf(fpout,"%g ",vp->Q()); for(i=0;iIsD() ) { fcnt++; if(binary) { vv[0]=indices[fp->cV(0)]; vv[1]=indices[fp->cV(1)]; vv[2]=indices[fp->cV(2)]; fwrite(&c,1,1,fpout); fwrite(vv,sizeof(int),3,fpout); if(m.HasPerFaceFlags()&&( pi.mask & Mask::IOM_FACEFLAGS) ) fwrite(&(fp->Flags()),sizeof(int),1,fpout); if( m.HasPerVertexTexCoord() && (pi.mask & Mask::IOM_VERTTEXCOORD) ) { fwrite(&b6,sizeof(char),1,fpout); float t[6]; for(int k=0;k<3;++k) { t[k*2+0] = fp->V(k)->T().u(); t[k*2+1] = fp->V(k)->T().v(); } fwrite(t,sizeof(float),6,fpout); } else if( m.HasPerWedgeTexCoord() && (pi.mask & Mask::IOM_WEDGTEXCOORD) ) { fwrite(&b6,sizeof(char),1,fpout); float t[6]; for(int k=0;k<3;++k) { t[k*2+0] = fp->WT(k).u(); t[k*2+1] = fp->WT(k).v(); } fwrite(t,sizeof(float),6,fpout); } if(multit) { int t = fp->WT(0).n(); fwrite(&t,sizeof(int),1,fpout); } if( m.HasPerFaceColor() && (pi.mask & Mask::IOM_FACECOLOR) ) fwrite(&( fp->C() ),sizeof(char),4,fpout); if( m.HasPerWedgeColor() && (pi.mask & Mask::IOM_WEDGCOLOR) ) { fwrite(&b9,sizeof(char),1,fpout); float t[3]; for(int z=0;z<3;++z) { t[0] = float(fp->WC(z)[0])/255; t[1] = float(fp->WC(z)[1])/255; t[2] = float(fp->WC(z)[2])/255; fwrite( t,sizeof(float),3,fpout); } } if( m.HasPerFaceQuality() && (pi.mask & Mask::IOM_FACEQUALITY) ) fwrite( &(fp->Q()),sizeof(float),1,fpout); for(i=0;icV(0)], indices[fp->cV(1)], indices[fp->cV(2)] ); if(m.HasPerFaceFlags()&&( pi.mask & Mask::IOM_FACEFLAGS )) fprintf(fpout,"%d ",fp->Flags()); if( m.HasPerVertexTexCoord() && (pi.mask & Mask::IOM_VERTTEXCOORD) ) { fprintf(fpout,"6 "); for(int k=0;k<3;++k) fprintf(fpout,"%g %g " ,fp->V(k)->T().u() ,fp->V(k)->T().v() ); } else if( m.HasPerWedgeTexCoord() && (pi.mask & Mask::IOM_WEDGTEXCOORD) ) { fprintf(fpout,"6 "); for(int k=0;k<3;++k) fprintf(fpout,"%g %g " ,fp->WT(k).u() ,fp->WT(k).v() ); } if(multit) { fprintf(fpout,"%d ",fp->WT(0).n()); } if( m.HasPerFaceColor() && (pi.mask & Mask::IOM_FACECOLOR) ) { float t[3]; t[0] = float(fp->C()[0])/255; t[1] = float(fp->C()[1])/255; t[2] = float(fp->C()[2])/255; fprintf(fpout,"9 "); fprintf(fpout,"%g %g %g ",t[0],t[1],t[2]); fprintf(fpout,"%g %g %g ",t[0],t[1],t[2]); fprintf(fpout,"%g %g %g ",t[0],t[1],t[2]); } else if( m.HasPerWedgeColor() && (pi.mask & Mask::IOM_WEDGCOLOR) ) { fprintf(fpout,"9 "); for(int z=0;z<3;++z) fprintf(fpout,"%g %g %g " ,double(fp->WC(z)[0])/255 ,double(fp->WC(z)[1])/255 ,double(fp->WC(z)[2])/255 ); } if( m.HasPerFaceQuality() && (pi.mask & Mask::IOM_FACEQUALITY) ) fprintf(fpout,"%g ",fp->Q()); for(i=0;i ply_error_msg; if(ply_error_msg.empty()) { ply_error_msg.resize(PlyInfo::E_MAXPLYINFOERRORS ); ply_error_msg[ply::E_NOERROR ]="No errors"; ply_error_msg[ply::E_CANTOPEN ]="Can't open file"; ply_error_msg[ply::E_NOTHEADER ]="Header not found"; ply_error_msg[ply::E_UNESPECTEDEOF ]="Eof in header"; ply_error_msg[ply::E_NOFORMAT ]="Format not found"; ply_error_msg[ply::E_SYNTAX ]="Syntax error on header"; ply_error_msg[ply::E_PROPOUTOFELEMENT]="Property without element"; ply_error_msg[ply::E_BADTYPENAME ]="Bad type name"; ply_error_msg[ply::E_ELEMNOTFOUND ]="Element not found"; ply_error_msg[ply::E_PROPNOTFOUND ]="Property not found"; ply_error_msg[ply::E_BADTYPE ]="Bad type on addtoread"; ply_error_msg[ply::E_INCOMPATIBLETYPE]="Incompatible type"; ply_error_msg[ply::E_BADCAST ]="Bad cast"; ply_error_msg[PlyInfo::E_NO_VERTEX ]="No vertex field found"; ply_error_msg[PlyInfo::E_NO_FACE ]="No face field found"; ply_error_msg[PlyInfo::E_SHORTFILE ]="Unespected eof"; ply_error_msg[PlyInfo::E_NO_3VERTINFACE ]="Face with more than 3 vertices"; ply_error_msg[PlyInfo::E_BAD_VERT_INDEX ]="Bad vertex index in face"; ply_error_msg[PlyInfo::E_NO_6TCOORD ]="Face with no 6 texture coordinates"; ply_error_msg[PlyInfo::E_DIFFER_COLORS ]="Number of color differ from vertices"; } if(error>PlyInfo::E_MAXPLYINFOERRORS || error<0) return "Unknown error"; else return ply_error_msg[error].c_str(); }; static int GetExportMaskCapability() { int capability = 0; capability |= vcg::tri::io::Mask::IOM_VERTCOORD ; capability |= vcg::tri::io::Mask::IOM_VERTFLAGS ; capability |= vcg::tri::io::Mask::IOM_VERTCOLOR ; capability |= vcg::tri::io::Mask::IOM_VERTQUALITY ; capability |= vcg::tri::io::Mask::IOM_VERTNORMAL ; capability |= vcg::tri::io::Mask::IOM_VERTTEXCOORD ; capability |= vcg::tri::io::Mask::IOM_FACEINDEX ; capability |= vcg::tri::io::Mask::IOM_FACEFLAGS ; capability |= vcg::tri::io::Mask::IOM_FACECOLOR ; capability |= vcg::tri::io::Mask::IOM_FACEQUALITY ; // capability |= vcg::tri::io::Mask::IOM_FACENORMAL ; capability |= vcg::tri::io::Mask::IOM_WEDGCOLOR ; capability |= vcg::tri::io::Mask::IOM_WEDGTEXCOORD ; capability |= vcg::tri::io::Mask::IOM_WEDGTEXMULTI ; capability |= vcg::tri::io::Mask::IOM_WEDGNORMAL ; return capability; } }; // end class } // end namespace tri } // end namespace io } // end namespace vcg //@} #endif qutemol/vcg/wrap/io_trimesh/export_dxf.h0000444000175000017500000001022210530651106017041 0ustar mbamba/**************************************************************************** * VCGLib o o * * Visual and Computer Graphics Library o o * * _ O _ * * Copyright(C) 2004 \/)\/ * * Visual Computing Lab /\/| * * ISTI - Italian National Research Council | * * \ * * All rights reserved. * * * * 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. * * * * 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 (http://www.gnu.org/licenses/gpl.txt) * * for more details. * * * ****************************************************************************/ /**************************************************************************** History $Log: export_dxf.h,v $ Revision 1.8 2006/11/21 19:23:50 e_cerisoli Added comments for documentation ****************************************************************************/ #ifndef __VCGLIB_EXPORT_DXF #define __VCGLIB_EXPORT_DXF namespace vcg { namespace tri { namespace io { template /** This class encapsulate a filter for save dxf meshes. */ class ExporterDXF { public: ///Standard call for saving a mesh static int Save(SaveMeshType &m, const char * filename) { FILE * o = fopen(filename,"w"); if(o==NULL) return 1; fprintf(o,"0\n"); fprintf(o,"SECTION\n"); fprintf(o,"2\n"); fprintf(o,"ENTITIES\n"); typename SaveMeshType::FaceIterator fi; for(fi=m.face.begin(); fi!=m.face.end(); ++fi) { if (!fi->IsD()) { typename SaveMeshType::CoordType v0 = (*fi).V(0)->P(); typename SaveMeshType::CoordType v1 = (*fi).V(1)->P(); typename SaveMeshType::CoordType v2 = (*fi).V(2)->P(); fprintf(o,"0\n"); fprintf(o,"3DFACE\n"); fprintf(o,"8\n"); fprintf(o,"0\n"); fprintf(o,"10\n"); fprintf(o,"%f\n", v0[0]); //X fprintf(o,"20\n"); fprintf(o,"%f\n", v0[1]); //Y fprintf(o,"30\n"); fprintf(o,"%f\n", v0[2]); //Z fprintf(o,"11\n"); fprintf(o,"%f\n", v1[0]); //X fprintf(o,"21\n"); fprintf(o,"%f\n", v1[1]); //Y fprintf(o,"31\n"); fprintf(o,"%f\n", v1[2]); //Z fprintf(o,"12\n"); fprintf(o,"%f\n", v2[0]); //X fprintf(o,"22\n"); fprintf(o,"%f\n", v2[1]); //Y fprintf(o,"32\n"); fprintf(o,"%f\n", v2[2]); //Z fprintf(o,"13\n"); fprintf(o,"%f\n", v2[0]); //X fprintf(o,"23\n"); fprintf(o,"%f\n", v2[1]); //Y fprintf(o,"33\n"); fprintf(o,"%f\n", v2[2]); //Z } } fprintf(o,"0\n"); fprintf(o,"ENDSEC\n"); fprintf(o,"0\n"); fprintf(o,"EOF\n"); fclose(o); return 0; } /// Standard call for knowing the meaning of an error code static const char *ErrorMsg(int error) { static std::vector dxf_error_msg; if(dxf_error_msg.empty()) { dxf_error_msg.resize(2 ); dxf_error_msg[0]="No errors"; dxf_error_msg[1]="Can't open file"; } if(error>1 || error<0) return "Unknown error"; else return dxf_error_msg[error].c_str(); } }; // end class } // end Namespace tri } // end Namespace io } // end Namespace vcg #endif qutemol/vcg/wrap/io_trimesh/export_3ds.h0000444000175000017500000004637511003376001016765 0ustar mbamba/**************************************************************************** * VCGLib o o * * Visual and Computer Graphics Library o o * * _ O _ * * Copyright(C) 2004 \/)\/ * * Visual Computing Lab /\/| * * ISTI - Italian National Research Council | * * \ * * All rights reserved. * * * * 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. * * * * 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 (http://www.gnu.org/licenses/gpl.txt) * * for more details. * * * ****************************************************************************/ /**************************************************************************** History $Log: export_3ds.h,v $ Revision 1.8 2008/04/22 14:53:53 cignoni removed outdated comment Revision 1.7 2007/03/12 16:40:16 tarini Texture coord name change! "TCoord" and "Texture" are BAD. "TexCoord" is GOOD. Revision 1.6 2006/11/30 22:48:06 cignoni Corrected bug in exporting mesh with deleted vertices Revision 1.5 2006/11/08 15:48:50 cignoni Corrected management of capabilities and masks Revision 1.4 2006/03/29 09:25:49 zifnab1974 extra includes necessary for compilation of meshlab on AMD 64 with gcc 3.4.5 Revision 1.3 2006/03/07 13:20:40 cignoni changed include of io_material Revision 1.2 2006/02/17 23:53:36 fmazzant added relative Path of the Lib3ds library Revision 1.1 2006/02/16 19:28:36 fmazzant transfer of Export_3ds.h, Export_obj.h, Io_3ds_obj_material.h from Meshlab to vcg Revision 1.14 2006/02/06 11:26:26 fmazzant bug-fix comment Revision 1.13 2006/02/06 11:04:39 fmazzant added file material.h. it include struct Material, CreateNewMaterial(...) and MaterialsCompare(...) Revision 1.12 2006/02/04 10:18:46 fmazzant clean code Revision 1.11 2006/02/03 12:36:53 fmazzant not significant updating Revision 1.10 2006/02/03 10:04:41 fmazzant no significant updated Revision 1.9 2006/02/02 16:08:27 fmazzant updated comment code Revision 1.8 2006/02/02 16:05:18 fmazzant deleted bug when saving mesh without textures. Revision 1.7 2006/02/02 15:35:15 fmazzant updated comment code Revision 1.6 2006/02/02 13:08:10 fmazzant cleaned & commented[italian] code Revision 1.5 2006/02/02 10:50:46 fmazzant deleted a big bug of exporter 3ds Revision 1.4 2006/01/31 09:34:30 fmazzant bug-fix on savemaskexporter, when press cancel returns -1. Revision 1.3 2006/01/29 23:52:43 fmazzant correct a small bug Revision 1.2 2006/01/29 18:33:42 fmazzant added some comment to the code Revision 1.1 2006/01/29 16:33:03 fmazzant moved export_obj and export_3ds from test/io into meshio/ Revision 1.30 2006/01/26 15:57:20 fmazzant deleted a small bug Revision 1.29 2006/01/26 15:48:49 fmazzant added control on the maximum number of vertices allowed by the 3DS file format Revision 1.28 2006/01/23 14:07:39 fmazzant deleted bug when saving a face color. Revision 1.27 2006/01/22 23:59:01 fmazzant changed default value of diffuse. 1.0 -> 0.8 Revision 1.26 2006/01/22 10:42:18 fmazzant cleaned code & optimized code of material's name 3ds Revision 1.25 2006/01/22 01:26:52 fmazzant deleted bug on saving name material 3ds Revision 1.24 2006/01/21 15:19:51 fmazzant changed: inserting coord texture in to map from key = index, value=coord to key=coord, value=index_of_vertix. Revision 1.23 2006/01/20 14:15:52 fmazzant added texture filename on material 3ds and coordtexture on face Revision 1.22 2006/01/19 09:36:29 fmazzant cleaned up history log Revision 1.21 2006/01/18 16:14:52 fmazzant update small error Revision 1.20 2006/01/18 16:12:58 fmazzant updated material Revision 1.19 2006/01/18 15:09:45 fmazzant added texture base Revision 1.18 2006/01/18 14:57:26 fmazzant added Lib3dsNode in export_3ds ****************************************************************************/ #ifndef __VCGLIB_EXPORT_3DS #define __VCGLIB_EXPORT_3DS #include #include #include #include #include "io_material.h" /* 3DS export needs the Lib3ds library. lib3ds is a free ANSI-C library for working with the popular "3ds" 3D model format. Supported platforms include GNU (autoconf, automake, libtool, make, GCC) on Unix and Cygwin, and MS Visual C++ 6.0. lib3ds loads and saves Atmosphere settings, Background settings, Shadow map settings, Viewport setting, Materials, Cameras, Lights, Meshes, Hierarchy, Animation keyframes. It also contains useful matrix, vector and quaternion mathematics tools. lib3ds usually integrates well with OpenGL. In addition, some diagnostic and conversion tools are included. lib3ds is distributed under the terms of the GNU Lesser General Public License. this information has been taken by the official site. runable from http://lib3ds.sourceforge.net/ */ #include #include #include #include #include #include #include #include #include #include #define MAX_POLYGONS 65535 namespace vcg { namespace tri { namespace io { template class Exporter3DS { public: typedef typename SaveMeshType::FaceIterator FaceIterator; typedef typename SaveMeshType::VertexIterator VertexIterator; typedef typename SaveMeshType::VertexType VertexType; //int: old index vertex //TexCoord2: tex coord with vertex's index i typedef std::pair > Key; /* enum of all the types of error */ enum SaveError { E_NOERROR, // 0 E_CANTOPENFILE, // 1 E_CANTCLOSEFILE, // 2 E_UNESPECTEDEOF, // 3 E_ABORTED, // 4 E_NOTDEFINITION, // 5 E_NOTVEXTEXVALID, // 6 E_NOTFACESVALID, // 7 E_NOTEXCOORDVALID, // 8 E_NOTNUMBERVERTVALID // 9 }; /* this function takes an index and the relative error message gets back */ static const char* ErrorMsg(int error) { static const char* obj_error_msg[] = { "No errors", // 0 "Can't open file", // 1 "can't close file", // 2 "Premature End of file", // 3 "File saving aborted", // 4 "Function not defined", // 5 "Vertices not valid", // 6 "Faces not valid", // 7 "Texture Coord not valid", // 8 "You cannot save more than 65535 vertices for the 3DS format" // 9 }; if(error>9 || error<0) return "Unknown error"; else return obj_error_msg[error]; }; /* returns mask of capability one define with what are the saveable information of the format. */ static int GetExportMaskCapability() { int capability = 0; //camera //capability |= MeshModel::IOM_CAMERA; //vert //capability |= MeshModel::IOM_VERTTEXCOORD; //face //capability |= MeshModel::IOM_FACEFLAGS; capability |= MeshModel::IOM_FACECOLOR; capability |= MeshModel::IOM_FACENORMAL; //wedg capability |= MeshModel::IOM_WEDGTEXCOORD; capability |= MeshModel::IOM_WEDGNORMAL; return capability; } /* function which saves in 3DS file format */ static int SaveBinary(SaveMeshType &m, const char * filename, const int &mask, CallBackPos *cb=0) { if(m.vn > MAX_POLYGONS)//check max polygons return E_NOTNUMBERVERTVALID; if(m.vn == 0) return E_NOTVEXTEXVALID; if(m.fn == 0) return E_NOTFACESVALID; /* <> si tiene in considerazione una mappa ListOfDuplexVert, alla quale gli viene associato il seguente significato: Key: una coppia (int,TexCoord) formata da un int che rappresenta l'indice del vettore nella mesh originale e la sua coordinata di texture. tale coppia rappresenta una chiave, essendo univoca in tutta la mesh. Non possibile che si incontrino due vertici che hanno solito indice di vertice e solite coordinate di texture, se un vertice di questo tipo esistesse allora i due vertici rappresenterebbero lo stesso vertice. int: l'indice del vertice inserito all'interno del vettore VectorOfVertexType Nel vertice VectorOfVertexType vengono inseriti tutti i vertici appartenenti alla mesh + i k vertici dublicati. la scelta di tali vertici va in base alla seguente regola: se un vertice con indice x(originale) ha pi di una coordinata di texture allora tale vertice viene duplicato e inserito in ListOfDuplexVert e in VectorOfVertexType(in VectorOfVertexType, l'inserimento del doppio vertice non sarebbe necessario, per viene fatto per comodit, in caso contrario dovremmo cercare il vertice dentro il vettore). rappresentazione grafica: ListOfDuplexVert VectorOfVertexType ------ --------- |key1| -> index1 --------- |vertex1| ------ | --------- |key2| -> index2 ---- -------------> |vertex2| ------ | --------- |key3| | |vertex3| ------ | --------- |key4| ------------------> |vertex4| ------ --------- |key5| --------------> |vertex5| ------ | --------- . | . . | . . | . ------ | --------- |keyn| -> indexn -------- |vertexn| ------ --------- questo tipo di struttura permette di selezionare l'indice del vertice in VectorOfVertexType con costo O(1). <> questo pezzo di codice itera su tutte le facce della mesh per riempire la mappa e il vettore. per ogni faccia e per ogni vertice di faccia costruisce la coppia (indice,texture), controlla se all'interno di ListOfDuplexVert esiste gi in tal caso non fa niente, in caso contrario aggiunte la coppia in ListOfDuplexVert e l'oggetto VertexType in VectorOfVertexType associando al valore della chiave (indice,texture) l'indice del vertice a cui punta. alla fine vengono duplicati solamente quei vertici che hanno pi coordinate di texture. c'e' da tenere presente che il codice appena descritto viene eseguito SOLAMENTE se la mesh contiene texture e se dalla dialog di exporter viene spuntato il salvataggio delle texture. In caso contrario non esegue niente e tratta solamente i vertici che sono presenti nella mesh senza creare duplicati. Le informazioni presenti in assenza di texture sono piu' che sufficienti. Federico Mazzanti */ std::map ListOfDuplexVert; std::vector VectorOfVertexType; std::vector VertRemap; // VertRemap[i] keep the final position of m.vert[i] inside the 3ds vertex list. used for remapping the pointers to vertex in the faces int count = 1; int nface = 0; if(HasPerWedgeTexCoord(m) && (mask & vcg::tri::io::Mask::IOM_WEDGTEXCOORD) ) { FaceIterator fi; for(fi=m.face.begin(); fi!=m.face.end(); ++fi) if( !(*fi).IsD() ) { for(unsigned int k=0;k<3;k++) { int i = GetIndexVertex(m, (*fi).V(k)); vcg::TexCoord2 t = (*fi).WT(k); if(!m.vert[i].IsD()) { if(AddDuplexVertexCoord(ListOfDuplexVert,Key(i,t))) { VectorOfVertexType.push_back((*(*fi).V(k))); ListOfDuplexVert[Key(i,t)] = VectorOfVertexType.size()-1; count++; } } } if (cb !=NULL) (*cb)(100.0 * (float)++nface/(float)m.face.size(), "calc duplex vertex ..."); else return E_ABORTED; } } int number_vertex_to_duplicate = 0; if(HasPerWedgeTexCoord(m) && (mask & MeshModel::IOM_WEDGTEXCOORD )) number_vertex_to_duplicate = (count-1) - m.vn; Lib3dsFile *file = lib3ds_file_new();//creates new file Lib3dsMesh *mesh = lib3ds_mesh_new("mesh");//creates a new mesh with mesh's name "mesh" QString qnamematerial = "Material - %1"; std::vector materials; int current = 0; int max = m.vn+m.fn+number_vertex_to_duplicate; lib3ds_mesh_new_point_list(mesh, m.vn + number_vertex_to_duplicate);// set number of vertexs if(HasPerWedgeTexCoord(m) && (mask & vcg::tri::io::Mask::IOM_WEDGTEXCOORD )) lib3ds_mesh_new_texel_list(mesh,m.vn + number_vertex_to_duplicate); //set number of textures int v_index = 0; VertexIterator vi; //saves vert if(HasPerWedgeTexCoord(m) && (mask & MeshModel::IOM_WEDGTEXCOORD )) { for(unsigned int i=0; i< VectorOfVertexType.size();i++) { Lib3dsPoint point; point.pos[0] = VectorOfVertexType[i].P()[0]; point.pos[1] = VectorOfVertexType[i].P()[1]; point.pos[2] = VectorOfVertexType[i].P()[2]; mesh->pointL[i] = point; if (cb !=NULL) (*cb)(100.0 * (float)++current/(float)max, "writing vertices "); else return E_ABORTED; } } else { VertRemap.resize(m.vert.size(),-1); for(vi=m.vert.begin(); vi!=m.vert.end(); ++vi) if( !(*vi).IsD() ) { Lib3dsPoint point; point.pos[0] = (*vi).P()[0]; point.pos[1] = (*vi).P()[1]; point.pos[2] = (*vi).P()[2]; mesh->pointL[v_index] = point; VertRemap[vi-m.vert.begin()]=v_index; if (cb !=NULL) (*cb)(100.0 * (float)++current/(float)max, "writing vertices "); else return E_ABORTED; v_index++; } } lib3ds_mesh_new_face_list (mesh, m.face.size());//set number of faces int f_index = 0;//face index int t_index = 0;//texture index FaceIterator fi; for(fi=m.face.begin(); fi!=m.face.end(); ++fi) if( !(*fi).IsD() ) { vcg::TexCoord2 t0,t1,t2; int i0 = GetIndexVertex(m, (*fi).V(0)); int i1 = GetIndexVertex(m, (*fi).V(1)); int i2 = GetIndexVertex(m, (*fi).V(2)); if(HasPerWedgeTexCoord(m) && (mask & MeshModel::IOM_WEDGTEXCOORD ) ) { t0 = (*fi).WT(0); t1 = (*fi).WT(1); t2 = (*fi).WT(2); } Lib3dsFace face; if(HasPerWedgeTexCoord(m) && (mask & MeshModel::IOM_WEDGTEXCOORD )) { face.points[0] = GetIndexDuplexVertex(ListOfDuplexVert,Key(i0,t0)); face.points[1] = GetIndexDuplexVertex(ListOfDuplexVert,Key(i1,t1)); face.points[2] = GetIndexDuplexVertex(ListOfDuplexVert,Key(i2,t2)); } else { face.points[0] = VertRemap[i0]; face.points[1] = VertRemap[i1]; face.points[2] = VertRemap[i2]; } //saves coord textures if(HasPerWedgeTexCoord(m) && (mask & MeshModel::IOM_WEDGTEXCOORD ) ) { mesh->texelL[face.points[0]][0] = t0.u(); mesh->texelL[face.points[0]][1] = t0.v(); mesh->texelL[face.points[1]][0] = t1.u(); mesh->texelL[face.points[1]][1] = t1.v(); mesh->texelL[face.points[2]][0] = t2.u(); mesh->texelL[face.points[2]][1] = t2.v(); } if(mask & MeshModel::IOM_FACEFLAGS) face.flags = 0; face.smoothing = 10; if((mask & MeshModel::IOM_FACENORMAL) | (mask & MeshModel::IOM_WEDGNORMAL) ) { face.normal[0] = (*fi).N()[0]; face.normal[1] = (*fi).N()[1]; face.normal[2] = (*fi).N()[2]; } if((mask & MeshModel::IOM_FACECOLOR) | (mask & MeshModel::IOM_WEDGTEXCOORD)) { int material_index = vcg::tri::io::Materials::CreateNewMaterial(m, materials, 0, fi); if(material_index == materials.size()) { Lib3dsMaterial *material = lib3ds_material_new();//creates a new material std::string name = qnamematerial.arg(material_index-1).toStdString(); strcpy(material->name,name.c_str());//copy new name of material if(mask & MeshModel::IOM_FACECOLOR) { //ambient material->ambient[0] = materials[materials.size()-1].Ka[0]; material->ambient[1] = materials[materials.size()-1].Ka[1]; material->ambient[2] = materials[materials.size()-1].Ka[2]; material->ambient[3] = materials[materials.size()-1].Tr; //diffuse material->diffuse[0] = materials[materials.size()-1].Kd[0]; material->diffuse[1] = materials[materials.size()-1].Kd[1]; material->diffuse[2] = materials[materials.size()-1].Kd[2]; material->diffuse[3] = materials[materials.size()-1].Tr; //specular material->specular[0] = materials[materials.size()-1].Ks[0]; material->specular[1] = materials[materials.size()-1].Ks[1]; material->specular[2] = materials[materials.size()-1].Ks[2]; material->specular[3] = materials[materials.size()-1].Tr; //shininess material->shininess = materials[materials.size()-1].Ns; } //texture if(HasPerWedgeTexCoord(m) && (mask & MeshModel::IOM_WEDGTEXCOORD ) ) strcpy(material->texture1_map.name,materials[materials.size()-1].map_Kd.c_str()); lib3ds_file_insert_material(file,material);//inserts the material inside the file strcpy(face.material,name.c_str()); } else { std::string name = qnamematerial.arg(material_index).toStdString(); strcpy(face.material,name.c_str());//set name of material } } mesh->faceL[f_index]=face; if (cb !=NULL) (*cb)(100.0 * (float)++current/(float)max, "writing faces "); else return E_ABORTED; f_index++; } lib3ds_file_insert_mesh(file, mesh);//inserts the Mesh into file Lib3dsNode *node = lib3ds_node_new_object();//creates a new node strcpy(node->name,mesh->name); node->parent_id = LIB3DS_NO_PARENT; lib3ds_file_insert_node(file,node);//inserts the node into file bool result = lib3ds_file_save(file, filename); //saves the file if(result) return E_NOERROR; else return E_ABORTED; } /* function which saves in 3DS format */ static int Save(SaveMeshType &m, const char * filename, const int &mask, CallBackPos *cb=0) { return SaveBinary(m,filename,mask,cb); } /* returns index of the vertex */ inline static int GetIndexVertex(SaveMeshType &m, VertexType *p) { return p-&*(m.vert.begin()); } /* added pair Key,int into map */ inline static bool AddDuplexVertexCoord(std::map &m,Key key) { int index = m[key]; if(index==0) return true; return false; } /* returns value of key key into map. this value is vertex's index into list all duplicate vertex */ inline static int GetIndexDuplexVertex(std::map &m,Key key) { return m[key]; } }; // end class } // end Namespace tri } // end Namespace io } // end Namespace vcg #endif qutemol/vcg/wrap/io_trimesh/import.h0000444000175000017500000001420710573777706016226 0ustar mbamba/**************************************************************************** * VCGLib o o * * Visual and Computer Graphics Library o o * * _ O _ * * Copyright(C) 2004 \/)\/ * * Visual Computing Lab /\/| * * ISTI - Italian National Research Council | * * \ * * All rights reserved. * * * * 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. * * * * 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 (http://www.gnu.org/licenses/gpl.txt) * * for more details. * * * ****************************************************************************/ /**************************************************************************** History $Log: import.h,v $ Revision 1.12 2007/03/08 12:21:26 granzuglia fixed bug about string iterator Revision 1.11 2006/03/29 09:27:07 cignoni Added managemnt of non critical errors Revision 1.10 2006/03/29 08:16:31 corsini Minor change in LoadMask Revision 1.9 2006/03/27 07:17:49 cignoni Added generic LoadMask Revision 1.8 2006/03/07 13:19:29 cignoni First Release with OBJ import support Revision 1.7 2006/02/28 14:50:00 corsini Fix comments Revision 1.6 2006/02/10 16:14:53 corsini Fix typo Revision 1.5 2006/02/10 08:14:32 cignoni Refactored import. No more duplicated code Revision 1.4 2006/02/09 16:04:45 corsini Expose load mask Revision 1.3 2006/01/11 10:37:45 cignoni Added use of Callback Revision 1.2 2005/01/26 22:43:19 cignoni Add std:: to stl containers Revision 1.1 2004/11/29 08:12:10 cignoni Initial Update ****************************************************************************/ #ifndef __VCGLIB_IMPORT #define __VCGLIB_IMPORT #include #include #include #include #include namespace vcg { namespace tri { namespace io { /** This class encapsulate a filter for automatically importing meshes by guessing the right filter according to the extension */ template class Importer { private: enum KnownTypes { KT_UNKNOWN, KT_PLY, KT_STL, KT_OFF, KT_OBJ }; static int &LastType() { static int lastType= KT_UNKNOWN; return lastType; } public: // simple aux function that returns true if a given file has a given extesnion static bool FileExtension(std::string filename, std::string extension) { std::locale loc1 ; std::use_facet > ( loc1 ).tolower(&*filename.begin(),&*filename.rbegin()); std::use_facet > ( loc1 ).tolower(&*extension.begin(),&*extension.rbegin()); std::string end=filename.substr(filename.length()-extension.length(),extension.length()); return end==extension; } // Open Mesh static int Open(OpenMeshType &m, const char *filename, CallBackPos *cb=0) { int dummymask = 0; return Open(m,filename,dummymask,cb); } // Open Mesh and return the load mask (the load mask must be initialized first) static int Open(OpenMeshType &m, const char *filename, int &loadmask, CallBackPos *cb=0) { int err; if(FileExtension(filename,"ply")) { err = ImporterPLY::Open(m, filename, loadmask, cb); LastType()=KT_PLY; } else if(FileExtension(filename,"stl")) { err = ImporterSTL::Open(m, filename, loadmask, cb); LastType()=KT_STL; } else if(FileExtension(filename,"off")) { err = ImporterOFF::Open(m, filename, loadmask, cb); LastType()=KT_OFF; } else if(FileExtension(filename,"obj")) { err = ImporterOBJ::Open(m, filename, loadmask, cb); LastType()=KT_OBJ; } else { err=1; LastType()=KT_UNKNOWN; } return err; } static bool ErrorCritical(int error) { switch(LastType()) { case KT_PLY : return (error>0); break; case KT_STL : return (error>0); break; case KT_OFF : return (error>0); break; case KT_OBJ : return ImporterOBJ::ErrorCritical(error); break; } return true; } static const char *ErrorMsg(int error) { switch(LastType()) { case KT_PLY : return ImporterPLY::ErrorMsg(error); break; case KT_STL : return ImporterSTL::ErrorMsg(error); break; case KT_OFF : return ImporterOFF::ErrorMsg(error); break; case KT_OBJ : return ImporterOBJ::ErrorMsg(error); break; } return "Unknown type"; } static bool LoadMask(const char * filename, int &mask) { bool err; if(FileExtension(filename,"ply")) { err = ImporterPLY::LoadMask(filename, mask); LastType()=KT_PLY; } else if(FileExtension(filename,"stl")) { mask = Mask::IOM_VERTCOORD | Mask::IOM_FACEINDEX; err = true; LastType()=KT_STL; } else if(FileExtension(filename,"off")) { mask = Mask::IOM_VERTCOORD | Mask::IOM_FACEINDEX; err = ImporterOFF::LoadMask(filename, mask); LastType()=KT_OFF; } else if(FileExtension(filename,"obj")) { err = ImporterOBJ::LoadMask(filename, mask); LastType()=KT_OBJ; } else { err = false; LastType()=KT_UNKNOWN; } return err; } }; // end class } // end Namespace tri } // end Namespace io } // end Namespace vcg #endif qutemol/vcg/wrap/io_trimesh/import_obj.h0000444000175000017500000006612010761373266017051 0ustar mbamba/**************************************************************************** * VCGLib o o * * Visual and Computer Graphics Library o o * * _ O _ * * Copyright(C) 2004 \/)\/ * * Visual Computing Lab /\/| * * ISTI - Italian National Research Council | * * \ * * All rights reserved. * * * * 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. * * * * 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 (http://www.gnu.org/licenses/gpl.txt) * * for more details. * * * ****************************************************************************/ /**************************************************************************** History $Log: import_obj.h,v $ Revision 1.20 2008/02/27 23:48:06 cignoni removed duplicated material class Revision 1.19 2008/01/17 18:02:02 cignoni added missing cast for normal assignments Revision 1.18 2007/12/13 17:57:33 cignoni removed harmless gcc warnings Revision 1.17 2007/10/17 09:49:50 cignoni correct management of point only files Revision 1.16 2007/07/20 14:49:46 cignoni Added in load mask the face color bit when there is a generic material used Revision 1.15 2007/07/05 14:47:04 cignoni Added face coloring when there is a texture (and therefore a material) Revision 1.14 2007/04/18 13:33:11 cignoni resolved issue related to the parsing of CR LF under *nixes Revision 1.13 2007/04/18 07:01:26 cignoni Added managment of map_Ka textures (and not only map_Kd) Revision 1.12 2006/12/21 00:36:17 cignoni Removed a bug in the managment of non triangular faces Revision 1.11 2006/12/12 02:47:12 cignoni Removed use of tellg that is broken in current version of mingw Revision 1.10 2006/11/21 10:56:41 cignoni ReWrote loadMask. Now shorter and faster. Revision 1.9 2006/10/09 19:58:08 cignoni Added casts to remove warnings Revision 1.8 2006/07/09 05:41:17 cignoni Major rewrite. Now shorter and more robust. Revision 1.7 2006/06/21 04:26:26 cignoni added initial test on end of file in the tokenize Revision 1.6 2006/05/21 07:01:04 cignoni Added mask clamping to the effective capabilities of the mesh Revision 1.5 2006/04/11 09:48:00 zifnab1974 changes needed for compilation on linux 64b with gcc 3.4.5 Revision 1.4 2006/03/29 09:27:07 cignoni Added managemnt of non critical errors Revision 1.3 2006/03/29 08:51:16 corsini reset to zero warnings Revision 1.2 2006/03/27 07:18:22 cignoni added missing std:: Revision 1.1 2006/03/07 13:19:29 cignoni First Release with OBJ import support Initial Working version coded by Buzzelli. ****************************************************************************/ #ifndef __VCGLIB_IMPORT_OBJ #define __VCGLIB_IMPORT_OBJ #include #include #include #include #include #include #include namespace vcg { namespace tri { namespace io { /** This class encapsulate a filter for importing obj (Alias Wavefront) meshes. Warning: this code assume little endian (PC) architecture!!! */ template class ImporterOBJ { public: typedef typename OpenMeshType::VertexPointer VertexPointer; typedef typename OpenMeshType::ScalarType ScalarType; typedef typename OpenMeshType::VertexType VertexType; typedef typename OpenMeshType::FaceType FaceType; typedef typename OpenMeshType::VertexIterator VertexIterator; typedef typename OpenMeshType::FaceIterator FaceIterator; typedef typename OpenMeshType::CoordType CoordType; class Info { public: Info() { mask = 0; cb = 0; numTexCoords=0; } /// It returns a bit mask describing the field preesnt in the ply file int mask; /// a Simple callback that can be used for long obj parsing. // it returns the current position, and formats a string with a description of what th efunction is doing (loading vertexes, faces...) CallBackPos *cb; /// number of vertices int numVertices; /// number of faces (the number of triangles could be /// larger in presence of polygonal faces int numFaces; /// number of texture coords indexes int numTexCoords; }; // end class //struct OBJFacet //{ // CoordType n; // CoordType t; // CoordType v[3]; // // short attr; // material index //}; struct ObjIndexedFace { int v[3]; int n[3]; int t[3]; int tInd; Color4b c; }; struct ObjTexCoord { float u; float v; }; enum OBJError { // Successfull opening E_NOERROR = 0x000, // 0 (position of correspondig string in the array) // Non Critical Errors (only odd numbers) E_NON_CRITICAL_ERROR = 0x001, E_MATERIAL_FILE_NOT_FOUND = 0x003, // 1 E_MATERIAL_NOT_FOUND = 0x005, // 2 E_TEXTURE_NOT_FOUND = 0x007, // 3 E_VERTICES_WITH_SAME_IDX_IN_FACE = 0x009, // 4 // Critical Opening Errors (only even numbers) E_CANTOPEN = 0x00A, // 5 E_UNESPECTEDEOF = 0x00C, // 6 E_ABORTED = 0x00E, // 7 E_NO_VERTEX = 0x010, // 8 E_NO_FACE = 0x012, // 9 E_BAD_VERTEX_STATEMENT = 0x014, // 10 E_BAD_VERT_TEX_STATEMENT = 0x016, // 11 E_BAD_VERT_NORMAL_STATEMENT = 0x018, // 12 E_LESS_THAN_3VERTINFACE = 0x01A, // 13 E_BAD_VERT_INDEX = 0x01C, // 14 E_BAD_VERT_TEX_INDEX = 0x01E, // 15 E_BAD_VERT_NORMAL_INDEX = 0x020 // 16 }; // to check if a given error is critical or not. static bool ErrorCritical(int err) { if(err<0x00A && err>=0) return false; return true; } static const char* ErrorMsg(int error) { static const char* obj_error_msg[] = { "No errors", // 0 "Material library file not found, a default white material is used", // 1 "Some materials definitions were not found, a default white material is used where no material was available", // 2 "Texture file not found", // 3 "Identical index vertices found in the same face", // 4 "Can't open file", // 5 "Premature End of file", // 6 "File opening aborted", // 7 "No vertex field found", // 8 "No face field found", // 9 "Vertex statement with less than 3 coords", // 10 "Texture coords statement with less than 2 coords", // 11 "Vertex normal statement with less than 3 coords", // 12 "Face with less than 3 vertices", // 13 "Bad vertex index in face", // 14 "Bad texture coords index in face", // 15 "Bad vertex normal index in face" // 16 }; // due to approximation, following line works well for either even (critical err codes) // or odd (non critical ones) numbers error = (int) error/2; if(error>15 || error<0) return "Unknown error"; else return obj_error_msg[error]; }; // Helper functions that checks the range of indexes // putting them in the correct range if less than zero (as in the obj style) static bool GoodObjIndex(int &index, const int maxVal) { if (index > maxVal) return false; if (index < 0) { index += maxVal+1; if (index<0 || index > maxVal) return false; } return true; } static int Open(OpenMeshType &mesh, const char *filename, int &loadmask, CallBackPos *cb=0) { Info oi; oi.mask=-1; oi.cb=cb; int ret=Open(mesh,filename,oi); loadmask=oi.mask; return ret; } /*! * Opens an object file (in ascii format) and populates the mesh passed as first * accordingly to read data * \param m The mesh model to be populated with data stored into the file * \param filename The name of the file to be opened * \param oi A structure containing infos about the object to be opened */ static int Open( OpenMeshType &m, const char * filename, Info &oi) { int result = E_NOERROR; m.Clear(); CallBackPos *cb = oi.cb; // if LoadMask has not been called yet, we call it here if (oi.mask == -1) LoadMask(filename, oi); Mask::ClampMask(m,oi.mask); if (oi.numVertices == 0) return E_NO_VERTEX; // Commented out this test. You should be allowed to load point clouds. //if (oi.numFaces == 0) // return E_NO_FACE; std::ifstream stream(filename); if (stream.fail()) return E_CANTOPEN; std::vector materials; // materials vector std::vector texCoords; // texture coordinates std::vector normals; // vertex normals std::vector indexedFaces; std::vector< std::string > tokens; std::string header; short currentMaterialIdx = 0; // index of current material into materials vector Color4b currentColor=Color4b::LightGray; // we declare this outside code block since other // triangles of this face will share the same color Material defaultMaterial; // default material: white materials.push_back(defaultMaterial); int numVertices = 0; // stores the number of vertices been read till now int numTriangles = 0; // stores the number of faces been read till now int numTexCoords = 0; // stores the number of texture coordinates been read till now int numVNormals = 0; // stores the number of vertex normals been read till now int numVerticesPlusFaces = oi.numVertices + oi.numFaces; int extraTriangles=0; // vertices and faces allocatetion VertexIterator vi = Allocator::AddVertices(m,oi.numVertices); //FaceIterator fi = Allocator::AddFaces(m,oi.numFaces); ObjIndexedFace ff; while (!stream.eof()) { tokens.clear(); TokenizeNextLine(stream, tokens); unsigned int numTokens = static_cast(tokens.size()); if (numTokens > 0) { header.clear(); header = tokens[0]; if (header.compare("v")==0) // vertex { if (numTokens < 4) return E_BAD_VERTEX_STATEMENT; (*vi).P()[0] = (ScalarType) atof(tokens[1].c_str()); (*vi).P()[1] = (ScalarType) atof(tokens[2].c_str()); (*vi).P()[2] = (ScalarType) atof(tokens[3].c_str()); ++numVertices; // assigning vertex color // ---------------------- if( oi.mask & vcg::tri::io::Mask::IOM_VERTCOLOR) (*vi).C() = currentColor; ++vi; // move to next vertex iterator // callback invocation, abort loading process if the call returns false if ((cb !=NULL) && (((numTriangles + numVertices)%100)==0) && !(*cb)((100*(numTriangles + numVertices))/numVerticesPlusFaces, "Vertex Loading")) return E_ABORTED; } else if (header.compare("vt")==0) // vertex texture coords { if (numTokens < 3) return E_BAD_VERT_TEX_STATEMENT; ObjTexCoord t; t.u = static_cast(atof(tokens[1].c_str())); t.v = static_cast(atof(tokens[2].c_str())); texCoords.push_back(t); numTexCoords++; } else if (header.compare("vn")==0) // vertex normal { if (numTokens != 4) return E_BAD_VERT_NORMAL_STATEMENT; CoordType n; n[0] = (ScalarType) atof(tokens[1].c_str()); n[1] = (ScalarType) atof(tokens[2].c_str()); n[2] = (ScalarType) atof(tokens[3].c_str()); normals.push_back(n); numVNormals++; } else if (header.compare("f")==0) // face { if (numTokens < 4) return E_LESS_THAN_3VERTINFACE; std::string vertex; std::string texcoord; std::string normal; for(int i=0;i<3;++i) // remember index starts from 1 instead of 0 SplitToken(tokens[i+1], ff.v[i], ff.n[i], ff.t[i], oi.mask); if ( oi.mask & vcg::tri::io::Mask::IOM_WEDGTEXCOORD ) { // verifying validity of texture coords indices for(int i=0;i<3;i++) if(!GoodObjIndex(ff.t[i],oi.numTexCoords)) return E_BAD_VERT_TEX_INDEX; ff.tInd=materials[currentMaterialIdx].index; } // verifying validity of vertex indices if ((ff.v[0] == ff.v[1]) || (ff.v[0] == ff.v[2]) || (ff.v[1] == ff.v[2])) result = E_VERTICES_WITH_SAME_IDX_IN_FACE; for(int i=0;i<3;i++) if(!GoodObjIndex(ff.v[i],numVertices)) return E_BAD_VERT_INDEX; // assigning face normal // --------------------- if ( oi.mask & vcg::tri::io::Mask::IOM_WEDGNORMAL ) { // verifying validity of vertex normal indices // ------------------------------------------- for(int i=0;i<3;i++) if(!GoodObjIndex(ff.n[i],numVNormals)) return E_BAD_VERT_NORMAL_INDEX; } // assigning face color // -------------------- if( oi.mask & vcg::tri::io::Mask::IOM_FACECOLOR) ff.c = currentColor; ++numTriangles; indexedFaces.push_back(ff); /* // A face polygon composed of more than three vertices is triangulated // according to the following schema: // v5 // / \ // / \ // / \ // v1------v4 // |\ / // | \ / // | \ / // v2---v3 // // As shown above, the 5 vertices polygon (v1,v2,v3,v4,v5) // has been split into the triangles (v1,v2,v3), (v1,v3,v4) e (v1,v4,v5). // This way vertex v1 becomes the common vertex of all newly generated // triangles, and this may lead to the creation of very thin triangles. */ int vertexesPerFace = static_cast(tokens.size()-1); int iVertex = 3; while (iVertex < vertexesPerFace) // add other triangles { ObjIndexedFace ffNew=ff; int v4_index; int vt4_index; int vn4_index; SplitToken(tokens[++iVertex], v4_index, vn4_index, vt4_index, oi.mask); // assigning wedge texture coordinates // ----------------------------------- if( oi.mask & vcg::tri::io::Mask::IOM_WEDGTEXCOORD ) { // verifying validity of texture coords index // ------------------------------------------ if(!GoodObjIndex(v4_index, numVertices)) return E_BAD_VERT_INDEX; if(!GoodObjIndex(vt4_index,oi.numTexCoords)) return E_BAD_VERT_TEX_INDEX; if ( oi.mask & vcg::tri::io::Mask::IOM_WEDGNORMAL ) if(!GoodObjIndex(vn4_index,numVNormals)) return E_BAD_VERT_NORMAL_INDEX; ffNew.t[1]=ff.t[2]; ffNew.t[2]=vt4_index; } if ((ff.v[0] == v4_index) || (ff.v[2] == v4_index)) result = E_VERTICES_WITH_SAME_IDX_IN_FACE; ffNew.v[1]=ff.v[2]; ffNew.v[2]=v4_index; // assigning face normal // --------------------- if ( oi.mask & vcg::tri::io::Mask::IOM_WEDGNORMAL ) { ffNew.n[1]=ff.n[2]; ffNew.n[2]=vn4_index; } ++numTriangles; ++extraTriangles; indexedFaces.push_back(ffNew); ff.v[2] = v4_index; } // callback invocation, abort loading process if the call returns false if ((cb !=NULL)&& (((numTriangles + numVertices)%100)==0) ) { if (!(*cb)( (100*(numTriangles +numVertices))/ numVerticesPlusFaces, "Face Loading")) return E_ABORTED; } } else if (header.compare("mtllib")==0) // material library { // obtain the name of the file containing materials library std::string materialFileName = tokens[1]; if (!LoadMaterials( materialFileName.c_str(), materials, m.textures)) result = E_MATERIAL_FILE_NOT_FOUND; } else if (header.compare("usemtl")==0) // material usage { std::string materialName = tokens[1]; bool found = false; unsigned i = 0; while (!found && (i < materials.size())) { std::string currentMaterialName = materials[i].materialName; if (currentMaterialName == materialName) { currentMaterialIdx = i; Material &material = materials[currentMaterialIdx]; Point3f diffuseColor = material.Kd; unsigned char r = (unsigned char) (diffuseColor[0] * 255.0); unsigned char g = (unsigned char) (diffuseColor[1] * 255.0); unsigned char b = (unsigned char) (diffuseColor[2] * 255.0); unsigned char alpha = (unsigned char) (material.Tr * 255.0); currentColor= Color4b(r, g, b, alpha); found = true; } ++i; } if (!found) { currentMaterialIdx = 0; result = E_MATERIAL_NOT_FOUND; } } // we simply ignore other situations } // end for each line... } // end while stream not eof assert((numTriangles +numVertices) == numVerticesPlusFaces+extraTriangles); FaceIterator fi = Allocator::AddFaces(m,numTriangles); //------------------------------------------------------------------------------- // Now the final pass to convert indexes into pointers for face to vert/norm/tex references for(int i=0;i &tokens) { if(stream.eof()) return; std::string line; do std::getline(stream, line); while ((line[0] == '#' || line.length()==0) && !stream.eof()); // skip comments and empty lines if ((line[0] == '#') || (line.length() == 0)) // can be true only on last line of file return; size_t from = 0; size_t to = 0; size_t length = line.size(); tokens.clear(); do { while (from!=length && (line[from]==' ' || line[from]=='\t' || line[from]=='\r') ) from++; if(from!=length) { to = from+1; while (to!=length && line[to]!=' ' && line[to]!='\r') to++; tokens.push_back(line.substr(from, to-from).c_str()); from = to; } } while (from2) { if(line[0]=='v') { if(line[1]==' ') oi.numVertices++; if(line[1]=='t') oi.numTexCoords++; } else if(line[0]=='f') oi.numFaces++; else if(line[0]=='u' && line[1]=='s') bHasPerFaceColor = true; // there is a usematerial so add per face color } } oi.mask = 0; if (oi.numTexCoords) { oi.mask |= vcg::tri::io::Mask::IOM_WEDGTEXCOORD; // Usually if you have tex coords you also have materials oi.mask |= vcg::tri::io::Mask::IOM_FACECOLOR; } if(bHasPerFaceColor) oi.mask |= vcg::tri::io::Mask::IOM_FACECOLOR; return true; } static bool LoadMask(const char * filename, int &mask) { Info oi; bool ret=LoadMask(filename, oi); mask= oi.mask; return ret; } static bool LoadMaterials(const char * filename, std::vector &materials, std::vector &textures) { // assumes we are in the right directory std::ifstream stream(filename); if (stream.fail()) return false; std::vector< std::string > tokens; std::string header; materials.clear(); Material currentMaterial; bool first = true; while (!stream.eof()) { tokens.clear(); TokenizeNextLine(stream, tokens); if (tokens.size() > 0) { header.clear(); header = tokens[0]; if (header.compare("newmtl")==0) { if (!first) { materials.push_back(currentMaterial); currentMaterial = Material(); } else first = false; //strcpy(currentMaterial.name, tokens[1].c_str()); currentMaterial.materialName=tokens[1]; } else if (header.compare("Ka")==0) { float r = (float) atof(tokens[1].c_str()); float g = (float) atof(tokens[2].c_str()); float b = (float) atof(tokens[3].c_str()); currentMaterial.Ka = Point3f(r, g, b); } else if (header.compare("Kd")==0) { float r = (float) atof(tokens[1].c_str()); float g = (float) atof(tokens[2].c_str()); float b = (float) atof(tokens[3].c_str()); currentMaterial.Kd = Point3f(r, g, b); } else if (header.compare("Ks")==0) { float r = (float) atof(tokens[1].c_str()); float g = (float) atof(tokens[2].c_str()); float b = (float) atof(tokens[3].c_str()); currentMaterial.Ks = Point3f(r, g, b); } else if ( (header.compare("d")==0) || (header.compare("Tr")==0) ) // alpha { currentMaterial.Tr = (float) atof(tokens[1].c_str()); } else if (header.compare("Ns")==0) // shininess { currentMaterial.Ns = atoi(tokens[1].c_str()); } else if (header.compare("illum")==0) // specular illumination on/off { int illumination = atoi(tokens[1].c_str()); //currentMaterial.bSpecular = (illumination == 2); currentMaterial.illum = illumination; } else if( (header.compare("map_Kd")==0) || (header.compare("map_Ka")==0) ) // texture name { std::string textureName = tokens[1]; //strcpy(currentMaterial.textureFileName, textureName.c_str()); currentMaterial.map_Kd=textureName; // adding texture name into textures vector (if not already present) // avoid adding the same name twice bool found = false; unsigned int size = static_cast(textures.size()); unsigned j = 0; while (!found && (j < size)) { if (textureName.compare(textures[j])==0) { currentMaterial.index = (int)j; found = true; } ++j; } if (!found) { textures.push_back(textureName); currentMaterial.index = (int)size; } } // we simply ignore other situations } } materials.push_back(currentMaterial); // add last read material stream.close(); return true; } }; // end class } // end Namespace tri } // end Namespace io } // end Namespace vcg #endif // ndef __VCGLIB_IMPORT_OBJ qutemol/vcg/wrap/io_trimesh/util_dae.h0000444000175000017500000003400310731724706016462 0ustar mbamba#ifndef __VCGLIB_UTILDAE #define __VCGLIB_UTILDAE #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace vcg { namespace tri { namespace io { class InfoDAE { public: InfoDAE() { doc = NULL; } ~InfoDAE() { delete doc; } QDomDocument* doc; }; class AdditionalInfoDAE : public AdditionalInfo { public: vcg::tri::io::InfoDAE* dae; std::vector texturefile; AdditionalInfoDAE() :AdditionalInfo() { mask = 0; numvert = 0; numface = 0; } ~AdditionalInfoDAE() { delete dae; texturefile.clear(); } }; class UtilDAE { public: enum DAEError { E_NOERROR, // 0 E_CANTOPEN, // 1 E_NOGEOMETRYLIBRARY, // 2 E_NOMESH, // 3 E_NOVERTEXPOSITION, // 4 E_NO3DVERTEXPOSITION, // 5 E_NO3DSCENE, // 6 E_INCOMPATIBLECOLLADA141FORMAT, //7 E_UNREFERENCEBLEDCOLLADAATTRIBUTE, // 8 E_NOPOLYGONALMESH }; template class MyPolygon { public: typedef VERTEX_TYPE BaseVertexType; int _nvert; std::vector _pv; std::vector< vcg::TexCoord2 > _txc; MyPolygon(int n) :_nvert(n),_pv(_nvert),_txc(_nvert) { } }; template class PolygonalMesh { public: typedef POLYGONAL_TYPE FaceType; enum PERWEDGEATTRIBUTETYPE {NONE = 0,NORMAL = 1,MULTITEXTURECOORD = 2,MULTICOLOR = 4}; typedef typename FaceType::BaseVertexType VertexType; typedef VertexType* VertexPointer; typedef typename std::vector::iterator VertexIterator; typedef typename std::vector::iterator PolygonIterator; vcg::Box3 bbox; std::vector vert; std::vector _pols; void generatePointsVector(std::vector >& v) { for(typename PolygonalMesh::PolygonIterator itp = _pols.begin();itp != _pols.end();++itp) { v.push_back(std::vector()); for(typename std::vector::iterator itv = itp->_pv.begin();itv != itp->_pv.end();++itv) { v[v.size() - 1].push_back((*itv)->P()); } } } void usePerWedgeAttributes(PERWEDGEATTRIBUTETYPE att,const unsigned int multitexture = 1,const unsigned int multicolor = 1) { if (att != NONE) { for(PolygonIterator itp = _pols.begin();itp != _pols.end();++itp) { if (att & MULTICOLOR) itp->usePerWedgeColor(multicolor); if (att & MULTITEXTURECOORD) itp->usePerWedgeMultiTexture(multitexture); if (att & NORMAL) itp->usePerWedgeNormal(); } } } template void triangulate(TRIMESH& mesh) { std::vector > pl; mesh.vert.resize(vert.size()); int multicoor = 0; //PolygonalMesh's points has been copied in TriangularMesh for(size_t jj = 0;jj < mesh.vert.size();++jj) mesh.vert[jj].P() = vert[jj].P(); bool texen = mesh.face.IsWedgeTexEnabled(); unsigned int totaltri = 0; for(size_t ii = 0;ii < _pols.size();++ii) totaltri += _pols[ii]._nvert - 2; mesh.face.resize(totaltri); //transform the polygonal mesh in a vector> generatePointsVector(pl); int trioff = 0; //foreach Polygon for(size_t ii = 0;ii < pl.size();++ii) { std::vector tx; std::vector > pl2(1); pl2[0] = pl[ii]; vcg::glu_tesselator::tesselate(pl2,tx); size_t ntri = tx.size() / 3; assert(tx.size() % 3 == 0); int polvert = 0; //foreach triangle for(size_t tr = 0;tr < ntri;++tr) { //typename TRIMESH::FaceType& f = mesh.face[tr]; //typename TRIMESH::FaceType& f = mesh.face[tr]; for(unsigned int tt = 0;tt < 3; ++tt) { mesh.face[trioff + tr].V(tt) = &(mesh.vert[_pols[ii]._pv[tx[3 * tr + tt]] - &(vert[0])]); //vcg::Point3f ppp = mesh.face[tr].V(tt)->P(); if (texen) { /* f.WT(multicoor).U() = _pols[ii]._txc[polvert].U(); f.WT(multicoor).V() = _pols[ii]._txc[polvert].V(); f.WT(multicoor).N() = _pols[ii]._txc[polvert].N();*/ } polvert = (polvert + 1) % _pols[ii]._nvert; } //mesh.face.push_back(f); } trioff += ntri; } assert(trioff == totaltri); } }; static const char *ErrorMsg(int error) { static const char * dae_error_msg[] = { "No errors", "Can't open file", "File without a geometry library", "There isn't mesh in file", "The meshes in file haven't the vertex position attribute", "The importer assumes that the OpenMeshType uses a 3D point for the vertex position", "There isn't any scene in Collada file", "The input file is not compatible with COLLADA 1.41 standard format", "Collada file is trying to referece an attribute that is not in the file", "This version of Collada Importer support only triangular and polygonal mesh file" }; if(error>9 || error<0) return "Unknown error"; else return dae_error_msg[error]; }; protected: inline static void referenceToANodeAttribute(const QDomNode n,const QString& attr,QString& url_st) { url_st = n.toElement().attribute(attr); int sz = url_st.size() - 1; url_st = url_st.right(sz); assert(url_st.size() != 0); } inline static QDomNode findNodeBySpecificAttributeValue(const QDomNodeList& ndl,const QString& attrname,const QString& attrvalue) { int ndl_size = ndl.size(); assert(ndl_size != 0); int ind = 0; while(ind < ndl_size) { QString st = ndl.at(ind).toElement().attribute(attrname); if (st == attrvalue) return ndl.at(ind); ++ind; } return QDomNode(); } inline static QDomNode findNodeBySpecificAttributeValue(const QDomNode n,const QString& tag,const QString& attrname,const QString& attrvalue) { return findNodeBySpecificAttributeValue(n.toElement().elementsByTagName(tag),attrname,attrvalue); } inline static QDomNode findNodeBySpecificAttributeValue(const QDomDocument n,const QString& tag,const QString& attrname,const QString& attrvalue) { return findNodeBySpecificAttributeValue(n.elementsByTagName(tag),attrname,attrvalue); } inline static bool isThereTag(const QDomNodeList& list) { return ((list.size() > 0) ? true : false); } inline static bool isThereTag(const QDomNode n,const QString& tagname) { return isThereTag(n.toElement().elementsByTagName(tagname)); } inline static bool isThereTag(const QDomDocument n,const QString& tagname) { return isThereTag(n.elementsByTagName(tagname)); } inline static QDomNode attributeSourcePerSimplex(const QDomNode n,const QDomDocument startpoint,const QString& sem) { QDomNodeList vertattr = n.toElement().elementsByTagName("input"); for(int ind = 0;ind < vertattr.size();++ind) { if (vertattr.at(ind).toElement().attribute("semantic") == sem) { QString url; referenceToANodeAttribute(vertattr.at(ind),"source",url); return findNodeBySpecificAttributeValue(startpoint,"source","id",url); } } return QDomNode(); } inline static void valueStringList(QStringList& res,const QDomNode srcnode,const QString& tag) { QDomNodeList list = srcnode.toElement().elementsByTagName(tag); assert(list.size() == 1); QString nd = list.at(0).firstChild().nodeValue(); res = nd.split(" "); if (res.last() == "") res.removeLast(); } /*inline static bool removeChildNode(QDomNodeList*/ inline static bool removeChildNodeList(QDomNodeList& nodelst,const QString& tag = "", const QString& attribname = "", const QString& attribvalue = "") { for(int jj = 0;jj < nodelst.size();++jj) { removeChildNode(nodelst.at(jj),tag,attribname,attribvalue); } return true; } inline static bool removeChildNode(QDomNode node,const QString& tag = "", const QString& attribname = "", const QString& attribvalue = "") { QDomNodeList clst = node.childNodes(); for(int ii = 0;ii < clst.size();++ii) { QDomNode oldchild = node.childNodes().at(ii); if (tag != "") { if ((attribname != "") && (attribvalue != "")) { if (clst.at(ii).toElement().attribute(attribname) == attribvalue) node.removeChild(oldchild); } else { QString nm = clst.at(ii).nodeName(); if (clst.at(ii).nodeName() == tag) { node.removeChild(oldchild); } } } else node.removeChild(oldchild); } return true; } static void ParseRotationMatrix(vcg::Matrix44f& m,const std::vector& t) { vcg::Matrix44f tmp; tmp.SetIdentity(); for(unsigned int ii = 0;ii < t.size();++ii) { QString rt = t[ii].firstChild().nodeValue(); QStringList rtl = rt.split(" "); if (rtl.last() == "") rtl.removeLast(); assert(rtl.size() == 4); tmp.SetRotate(rtl.at(3).toFloat(),vcg::Point3f(rtl.at(0).toFloat(),rtl.at(1).toFloat(),rtl.at(2).toFloat())); tmp *= tmp; } m = m * tmp; } static void AddTranslation(vcg::Matrix44f& m,const QDomNode t) { QDomNode tr = t.firstChild(); QString coord = tr.nodeValue(); QStringList coordlist = coord.split(" "); if (coordlist.last() == "") coordlist.removeLast(); assert(coordlist.size() == 3); m[0][0] = 1.0f; m[1][1] = 1.0f; m[2][2] = 1.0f; m[3][3] = 1.0f; m[0][3] = coordlist.at(0).toFloat(); m[1][3] = coordlist.at(1).toFloat(); m[2][3] = coordlist.at(2).toFloat(); } static void TransfMatrix(const QDomNode parentnode,const QDomNode presentnode,vcg::Matrix44f& m) { if (presentnode == parentnode) return; else { QDomNode par = presentnode.parentNode(); std::vector rotlist; QDomNode trans; for(int ch = 0;ch < par.childNodes().size();++ch) { if (par.childNodes().at(ch).nodeName() == "rotate") rotlist.push_back(par.childNodes().at(ch)); else if (par.childNodes().at(ch).nodeName() == "translate") { trans = par.childNodes().at(ch); } } vcg::Matrix44f tmp; tmp.SetIdentity(); if (!trans.isNull()) AddTranslation(tmp,trans); ParseRotationMatrix(tmp,rotlist); m = m * tmp; TransfMatrix(parentnode,par,m); } } inline static int findOffSetForASingleSimplex(QDomNode node) { QDomNodeList wedatts = node.toElement().elementsByTagName("input"); int max = 0; if (wedatts.size() == 0) return -1; else { for(int ii = 0;ii < wedatts.size();++ii) { int tmp = wedatts.at(ii).toElement().attribute("offset").toInt(); if (tmp > max) max = tmp; } } return max + 1; } inline static int findStringListAttribute(QStringList& list,const QDomNode node,const QDomNode poly,const QDomDocument startpoint,const char* token) { int offset; if (!node.isNull()) { offset = node.toElement().attribute("offset").toInt(); QDomNode st = attributeSourcePerSimplex(poly,startpoint,token); valueStringList(list,st,"float_array"); } return offset; } inline static QDomNode textureFinder(const QString& textname,const QDomDocument doc) { //visual_scene -> instance_material QDomNodeList vis_scn = doc.elementsByTagName("library_visual_scenes"); if (vis_scn.size() != 1) return QDomNode(); QDomNode symb = findNodeBySpecificAttributeValue(vis_scn.at(0),QString("instance_material"),QString("symbol"),textname); if (symb.isNull()) return QDomNode(); QString tar = symb.toElement().attribute("target"); if (tar.isNull()) return QDomNode(); tar = tar.remove('#'); //library_material -> material -> instance_effect QDomNodeList lib_mat = doc.elementsByTagName("library_materials"); if (lib_mat.size() != 1) return QDomNode(); QDomNode material = findNodeBySpecificAttributeValue(lib_mat.at(0),QString("material"),QString("id"),tar); if (material.isNull()) return QDomNode(); QDomNodeList in_eff = material.toElement().elementsByTagName("instance_effect"); if (vis_scn.size() == 0) return QDomNode(); QString url = in_eff.at(0).toElement().attribute("url"); if ((url.isNull()) || (url == "")) return QDomNode(); url = url.remove('#'); //library_effects -> effect -> instance_effect QDomNodeList lib_eff = doc.elementsByTagName("library_effects"); if (lib_eff.size() != 1) return QDomNode(); QDomNode effect = findNodeBySpecificAttributeValue(lib_eff.at(0),QString("effect"),QString("id"),url); if (effect.isNull()) return QDomNode(); QDomNodeList init_from = effect.toElement().elementsByTagName("init_from"); if (init_from.size() == 0) return QDomNode(); QString img_id = init_from.at(0).toElement().text(); if ((img_id.isNull()) || (img_id == "")) return QDomNode(); //library_images -> image QDomNodeList lib_img = doc.elementsByTagName("library_images"); if (lib_img.size() != 1) return QDomNode(); QDomNode img = findNodeBySpecificAttributeValue(lib_img.at(0),QString("image"),QString("id"),img_id); if (img.isNull()) return QDomNode(); return img; } static int indexTextureByImgNode(const QDomDocument doc,const QDomNode node) { QDomNodeList libim = doc.elementsByTagName(QString("library_images")); if (libim.size() != 1) return -1; QDomNodeList imgs = libim.at(0).toElement().elementsByTagName("image"); int ii = 0; bool found = false; while((ii < imgs.size()) && (!found)) { if (imgs.at(ii) == node) found = true; else ++ii; } if (found) return ii; else return -1; } struct WedgeAttribute { QDomNode wnsrc; QStringList wn; int offnm; QDomNode wtsrc; QStringList wt; int stride; int offtx; QDomNode wcsrc; QStringList wc; int offcl; }; }; } } } #endif qutemol/vcg/wrap/io_trimesh/import_stl.h0000444000175000017500000002121410755260250017063 0ustar mbamba/**************************************************************************** * VCGLib o o * * Visual and Computer Graphics Library o o * * _ O _ * * Copyright(C) 2004 \/)\/ * * Visual Computing Lab /\/| * * ISTI - Italian National Research Council | * * \ * * All rights reserved. * * * * 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. * * * * 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 (http://www.gnu.org/licenses/gpl.txt) * * for more details. * * * ****************************************************************************/ /**************************************************************************** History $Log: import_stl.h,v $ Revision 1.16 2008/02/15 09:51:36 cignoni corrected bug in the management of of multiple solid ascii stl files Revision 1.15 2007/05/24 06:56:54 cignoni Corrected gcc warning Revision 1.14 2006/06/10 12:49:05 mariolatronico file length is now computed using fseek and ftell Revision 1.13 2006/06/06 14:35:32 zifnab1974 Changes for compilation on linux AMD64. Some remarks: Linux filenames are case-sensitive. _fileno and _filelength do not exist on linux Revision 1.12 2006/05/03 21:19:34 cignoni Added support for progress callback Revision 1.11 2006/01/30 15:02:50 cignoni Added mask filling in open Revision 1.10 2006/01/04 16:14:43 cignoni Added callback managment on loading of binary stl Revision 1.9 2005/09/15 09:29:45 m_di_benedetto #included missing and Revision 1.8 2004/10/28 00:52:45 cignoni Better Doxygen documentation Revision 1.7 2004/08/25 15:27:51 ponchio Comma at end of enum. Revision 1.6 2004/08/25 15:15:27 ganovelli minor changes to comply gcc compiler (typename's and stuff) Revision 1.5 2004/06/23 15:36:44 cignoni Restructured management of error, now the standard open for any mesh type return the error code, the default success value is zero Any import class has a method ErrorMsg that give a verbal description of an error code. Revision 1.4 2004/03/18 15:30:57 cignoni Removed float/double warning Revision 1.3 2004/03/12 21:42:52 cignoni First working version! ****************************************************************************/ #ifndef __VCGLIB_IMPORT_STL #define __VCGLIB_IMPORT_STL #include #include #include namespace vcg { namespace tri { namespace io { /** This class encapsulate a filter for importing stl (stereolitograpy) meshes. The stl format is quite simple and rather un-flexible. It just stores, in ascii or binary the, unindexed, geometry of the faces. Warning: this code assume little endian (PC) architecture!!! */ template class ImporterSTL { public: typedef typename OpenMeshType::VertexPointer VertexPointer; typedef typename OpenMeshType::ScalarType ScalarType; typedef typename OpenMeshType::VertexType VertexType; typedef typename OpenMeshType::FaceType FaceType; typedef typename OpenMeshType::VertexIterator VertexIterator; typedef typename OpenMeshType::FaceIterator FaceIterator; // if it is binary there are 80 char of comment, the number fn of faces and then exactly fn*4*3 bytes. enum {STL_LABEL_SIZE=80}; class STLFacet { public: Point3f n; Point3f v[3]; // short attr; }; enum STLError { E_NOERROR, // 0 // Errori di open E_CANTOPEN, // 1 E_UNESPECTEDEOF // 2 }; static const char *ErrorMsg(int error) { static const char * stl_error_msg[] = { "No errors", "Can't open file", "Premature End of file", }; if(error>2 || error<0) return "Unknown error"; else return stl_error_msg[error]; }; static int Open(OpenMeshType &mesh, const char *filename, int &loadmask, CallBackPos *cb=0) { loadmask = Mask::IOM_VERTCOORD | Mask::IOM_FACEINDEX; return Open(mesh,filename,cb); } static int Open( OpenMeshType &m, const char * filename, CallBackPos *cb=0) { FILE *fp; bool binary=false; fp = fopen(filename, "r"); if(fp == NULL) { return E_CANTOPEN; } /* Find size of file */ fseek(fp, 0, SEEK_END); int file_size = ftell(fp); int facenum; /* Check for binary or ASCII file */ fseek(fp, STL_LABEL_SIZE, SEEK_SET); fread(&facenum, sizeof(int), 1, fp); int expected_file_size=STL_LABEL_SIZE + 4 + (sizeof(short)+sizeof(STLFacet) )*facenum ; if(file_size == expected_file_size) binary = true; unsigned char tmpbuf[128]; fread(tmpbuf,sizeof(tmpbuf),1,fp); for(unsigned int i = 0; i < sizeof(tmpbuf); i++) { if(tmpbuf[i] > 127) { binary=true; break; } } // Now we know if the stl file is ascii or binary. fclose(fp); if(binary) return OpenBinary(m,filename,cb); else return OpenAscii(m,filename,cb); } static int OpenBinary( OpenMeshType &m, const char * filename, CallBackPos *cb=0) { FILE *fp; fp = fopen(filename, "rb"); if(fp == NULL) { return E_CANTOPEN; } int facenum; fseek(fp, STL_LABEL_SIZE, SEEK_SET); fread(&facenum, sizeof(int), 1, fp); m.Clear(); FaceIterator fi=Allocator::AddFaces(m,facenum); VertexIterator vi=Allocator::AddVertices(m,facenum*3); // For each triangle read the normal, the three coords and a short set to zero for(int i=0;i::AddFaces(m,1); VertexIterator vi=Allocator::AddVertices(m,3); for(int k=0;k<3;++k) { (*vi).P().Import(f.v[k]); (*fi).V(k)=&*vi; ++vi; } } fclose(fp); return E_NOERROR; } }; // end class } // end Namespace tri } // end Namespace io } // end Namespace vcg #endif qutemol/vcg/wrap/io_trimesh/export_obj.h0000444000175000017500000003311510761130043017036 0ustar mbamba/**************************************************************************** * VCGLib o o * * Visual and Computer Graphics Library o o * * _ O _ * * Copyright(C) 2004 \/)\/ * * Visual Computing Lab /\/| * * ISTI - Italian National Research Council | * * \ * * All rights reserved. * * * * 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. * * * * 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 (http://www.gnu.org/licenses/gpl.txt) * * for more details. * * * ****************************************************************************/ /**************************************************************************** History $Log: export_obj.h,v $ Revision 1.11 2008/02/27 00:34:43 cignoni corrected various bugs in the export of texture coords Revision 1.10 2007/10/17 09:49:50 cignoni correct management of point only files Revision 1.9 2007/03/12 16:40:16 tarini Texture coord name change! "TCoord" and "Texture" are BAD. "TexCoord" is GOOD. Revision 1.8 2007/03/08 11:27:52 ganovelli added include to tcoord2 Revision 1.7 2007/02/16 21:12:13 m_di_benedetto Commented out strange abort in WriteMaterials() Revision 1.6 2006/12/07 00:37:58 cignoni Corrected bug in the management of deleted vertices Revision 1.5 2006/10/09 19:58:08 cignoni Added casts to remove warnings Revision 1.4 2006/09/18 12:14:38 cignoni Removed bug in the creation of the material filename Revision 1.3 2006/03/07 13:19:29 cignoni First Release with OBJ import support Revision 1.2 2006/02/28 14:38:09 corsini remove qt include Revision 1.1 2006/02/16 19:28:36 fmazzant transfer of Export_3ds.h, Export_obj.h, Io_3ds_obj_material.h from Meshlab to vcg Revision 1.7 2006/02/06 11:04:40 fmazzant added file material.h. it include struct Material, CreateNewMaterial(...) and MaterialsCompare(...) Revision 1.6 2006/02/04 10:18:46 fmazzant clean code Revision 1.5 2006/02/03 10:04:41 fmazzant no significant updated Revision 1.4 2006/01/30 14:02:05 fmazzant bug-fix Revision 1.3 2006/01/29 23:52:43 fmazzant correct a small bug Revision 1.2 2006/01/29 18:33:42 fmazzant added some comment to the code Revision 1.1 2006/01/29 16:33:03 fmazzant moved export_obj and export_3ds from test/io into meshio/ Revision 1.34 2006/01/22 23:59:01 fmazzant changed default value of diffuse. 1.0 -> 0.8 Revision 1.33 2006/01/19 09:36:29 fmazzant cleaned up history log Revision 1.32 2006/01/18 00:45:56 fmazzant added control on face's diffuse Revision 1.31 2006/01/17 13:48:54 fmazzant added capability mask on export file format Revision 1.30 2006/01/15 00:45:40 fmazzant extend mask exporter for all type file format + Revision 1.29 2006/01/14 00:03:26 fmazzant added more controls ****************************************************************************/ #ifndef __VCGLIB_EXPORT_OBJ #define __VCGLIB_EXPORT_OBJ #include #include #include #include #include "io_material.h" #include #include #include namespace vcg { namespace tri { namespace io { template class ExporterOBJ { public: typedef typename SaveMeshType::FaceIterator FaceIterator; typedef typename SaveMeshType::VertexIterator VertexIterator; typedef typename SaveMeshType::VertexType VertexType; /* enum of all the types of error */ enum SaveError { E_NOERROR, // 0 E_CANTOPENFILE, // 1 E_CANTCLOSEFILE, // 2 E_UNESPECTEDEOF, // 3 E_ABORTED, // 4 E_NOTDEFINITION, // 5 E_NOTVEXTEXVALID, // 6 E_NOTFACESVALID // 7 }; /* this function takes an index and the relative error message gets back */ static const char* ErrorMsg(int error) { static const char* obj_error_msg[] = { "No errors", // 0 "Can't open file", // 1 "can't close file", // 2 "Premature End of file", // 3 "File saving aborted", // 4 "Function not defined", // 5 "Vertices not valid", // 6 "Faces not valid" // 7 }; if(error>7 || error<0) return "Unknown error"; else return obj_error_msg[error]; }; /* returns mask of capability one define with what are the saveable information of the format. */ static int GetExportMaskCapability() { int capability = 0; //vert capability |= vcg::tri::io::Mask::IOM_VERTNORMAL; //face capability |= vcg::tri::io::Mask::IOM_FACECOLOR; //wedg capability |= vcg::tri::io::Mask::IOM_WEDGTEXCOORD; capability |= vcg::tri::io::Mask::IOM_WEDGNORMAL; return capability; } /* function which saves in OBJ file format */ static int Save(SaveMeshType &m, const char * filename, int mask, CallBackPos *cb=0) { if(m.vn == 0) return E_NOTVEXTEXVALID; // Commented out this control. You should be allowed to save a point cloud. // if(m.fn == 0) return E_NOTFACESVALID; int current = 0; int totalPrimitives = m.vn+m.fn; std::vector materialVec; std::string fn(filename); int LastSlash=fn.size()-1; while(LastSlash>=0 && fn[LastSlash]!='/') --LastSlash; FILE *fp; fp = fopen(filename,"w"); if(fp == NULL) return E_CANTOPENFILE; fprintf(fp,"####\n#\n# OBJ File Generated by Meshlab\n#\n####\n"); fprintf(fp,"# Object %s\n#\n# Vertices: %d\n# Faces: %d\n#\n####\n",fn.substr(LastSlash+1).c_str(),m.vn,m.fn); //library materialVec if( (mask & vcg::tri::io::Mask::IOM_FACECOLOR) || (mask & Mask::IOM_WEDGTEXCOORD) ) fprintf(fp,"mtllib ./%s.mtl\n\n",fn.substr(LastSlash+1).c_str()); //vertexs + normal VertexIterator vi; std::map NormalVertex; std::vector VertexId(m.vert.size()); int numvert = 0; int curNormalIndex = 1; for(vi=m.vert.begin(); vi!=m.vert.end(); ++vi) if( !(*vi).IsD() ) { VertexId[vi-m.vert.begin()]=numvert; //saves normal per vertex if((mask & Mask::IOM_VERTNORMAL) || (mask & vcg::tri::io::Mask::IOM_WEDGTEXCOORD) ) { if(AddNewNormalVertex(NormalVertex,(*vi).N(),curNormalIndex)) { fprintf(fp,"vn %f %f %f\n",(*vi).N()[0],(*vi).N()[1],(*vi).N()[2]); curNormalIndex++; } } //saves vertex fprintf(fp,"v %f %f %f\n",(*vi).P()[0],(*vi).P()[1],(*vi).P()[2]); if (cb !=NULL) { if(!(*cb)((100*++current)/totalPrimitives, "writing vertices ")) { fclose(fp); return E_ABORTED;} } numvert++; } assert(numvert == m.vn); fprintf(fp,"# %d vertices, %d vertices normals\n\n",m.vn,NormalVertex.size()); //faces + texture coords FaceIterator fi; std::map,int> CoordIndexTexture; unsigned int material_num = 0; int mem_index = 0; //var temporany int curTexCoordIndex = 1; for(fi=m.face.begin(); fi!=m.face.end(); ++fi) if( !(*fi).IsD() ) { if((mask & Mask::IOM_FACECOLOR) || (mask & Mask::IOM_WEDGTEXCOORD) ) { int index = Materials::CreateNewMaterial(m,materialVec,material_num,fi); if(index == materialVec.size())//inserts a new element material { material_num++; fprintf(fp,"\nusemtl material_%d\n",materialVec[index-1].index); mem_index = index-1; } else { if(index != mem_index)//inserts old name elemente material { fprintf(fp,"\nusemtl material_%d\n",materialVec[index].index); mem_index=index; } } } //saves texture coord for(unsigned int k=0;k<3;k++) { if(HasPerWedgeTexCoord(m) && (mask & Mask::IOM_WEDGTEXCOORD)) { if(AddNewTextureCoord(CoordIndexTexture,(*fi).WT(k),curTexCoordIndex)) { fprintf(fp,"vt %f %f\n",(*fi).WT(k).u(),(*fi).WT(k).v()); curTexCoordIndex++; //ncreases the value number to be associated to the Texture } } } fprintf(fp,"f "); for(unsigned int k=0;k<3;k++) { if(k!=0) fprintf(fp," "); int vInd = -1; // +1 because Obj file format begins from index = 1 but not from index = 0. vInd = VertexId[GetIndexVertex(m, (*fi).V(k))] + 1;//index of vertex per face int vt = -1; if(mask & Mask::IOM_WEDGTEXCOORD) vt = GetIndexVertexTexture(CoordIndexTexture,(*fi).WT(k));//index of vertex texture per face int vn = -1; if((mask & Mask::IOM_VERTNORMAL) || (mask & Mask::IOM_WEDGNORMAL) ) vn = GetIndexVertexNormal(m, NormalVertex, (*fi).V(k)->cN());//index of vertex normal per face. //writes elements on file obj WriteFacesElement(fp,vInd,vt,vn); } fprintf(fp,"\n"); if (cb !=NULL) { if(!(*cb)((100*++current)/totalPrimitives, "writing vertices ")) { fclose(fp); return E_ABORTED;} } }//for fprintf(fp,"# %d faces, %d coords texture\n\n",m.face.size(),CoordIndexTexture.size()); fprintf(fp,"# End of File"); fclose(fp); int r = 0; if((mask & Mask::IOM_WEDGTEXCOORD) || (mask & Mask::IOM_FACECOLOR) ) r = WriteMaterials(materialVec, filename,cb);//write material if(r!= E_NOERROR) return r; return E_NOERROR; } /* returns index of the vertex */ inline static int GetIndexVertex(SaveMeshType &m, VertexType *p) { return p-&*(m.vert.begin()); } /* returns index of the texture coord */ inline static int GetIndexVertexTexture(std::map,int> &mapTexToInt, const vcg::TexCoord2 &wt) { std::map,int>::iterator iter= mapTexToInt.find(wt); if(iter != mapTexToInt.end()) return (*iter).second; else return -1; // Old wrong version. // int index = mapTexToInt[wt]; // if(index!=0){return index;} } /* returns index of the vertex normal */ inline static int GetIndexVertexNormal(SaveMeshType &m, std::map &mapNormToInt, const Point3f &norm ) { std::map::iterator iter= mapNormToInt.find(norm); if(iter != mapNormToInt.end()) return (*iter).second; else return -1; // Old wrong version. // int index = mapNormToInt[m.vert[iv].N()]; // if(index!=0){return index;} } /* write elements on file f v/tc/vn v/tc/vn v/tc/vn ... f v/tc v/tc v/tc ... f v//vn v//vn v//vn ... f v v v ... */ inline static void WriteFacesElement(FILE *fp,int v,int vt, int vn) { fprintf(fp,"%d",v); if(vt!=-1) { fprintf(fp,"/%d",vt); if(vn!=-1) fprintf(fp,"/%d",vn); } else if(vn!=-1) fprintf(fp,"//%d",vn); } /* adds a new index to the coordinate of Texture if it is the first time which is otherwise met not execute anything */ inline static bool AddNewTextureCoord(std::map,int> &m, const vcg::TexCoord2 &wt,int value) { int index = m[wt]; if(index==0){m[wt]=value;return true;} return false; } /* adds a new index to the normal per vertex if it is the first time which is otherwise met does not execute anything */ inline static bool AddNewNormalVertex(std::map &m, Point3f &n ,int value) { int index = m[n]; if(index==0){m[n]=value;return true;} return false; } /* writes material into file */ inline static int WriteMaterials(std::vector &materialVec, const char * filename, CallBackPos *cb=0) { std::string fileName = std::string(filename); fileName+=".mtl"; if(materialVec.size() > 0) { FILE *fp; fp = fopen(fileName.c_str(),"w"); if(fp==NULL)return E_ABORTED; fprintf(fp,"#\n# Wavefront material file\n# Converted by Meshlab Group\n#\n\n"); int current = 0; for(unsigned int i=0;i0) fprintf(fp,"map_Kd %s\n",materialVec[i].map_Kd.c_str()); fprintf(fp,"\n"); } fclose(fp); } return E_NOERROR; } }; // end class } // end Namespace tri } // end Namespace io } // end Namespace vcg #endif qutemol/vcg/wrap/io_trimesh/import_smf.h0000444000175000017500000001056510530651106017050 0ustar mbamba/**************************************************************************** * VCGLib o o * * Visual and Computer Graphics Library o o * * _ O _ * * Copyright(C) 2004 \/)\/ * * Visual Computing Lab /\/| * * ISTI - Italian National Research Council | * * \ * * All rights reserved. * * * * 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. * * * * 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 (http://www.gnu.org/licenses/gpl.txt) * * for more details. * * * ****************************************************************************/ /**************************************************************************** History $Log: import_smf.h,v $ Revision 1.5 2006/11/21 19:23:50 e_cerisoli Added comments for documentation ****************************************************************************/ #ifndef __VCGLIB_IMPORTER_SMF #define __VCGLIB_IMPORTER_SMF #include #include namespace vcg { namespace tri { namespace io { template /** This class encapsulate a filter for opening smf meshes. */ class ImporterSMF { public: typedef typename OpenMeshType::VertexPointer VertexPointer; typedef typename OpenMeshType::ScalarType ScalarType; typedef typename OpenMeshType::VertexType VertexType; typedef typename OpenMeshType::FaceType FaceType; typedef typename OpenMeshType::VertexIterator VertexIterator; typedef typename OpenMeshType::FaceIterator FaceIterator; // if it is binary there are 80 char of comment, the number fn of faces and then exactly fn*4*3 bytes. enum {SMF_LABEL_SIZE=80}; class SMFFacet { public: vcg::Point3f n; vcg::Point3f v[3]; }; enum SMFError { E_NOERROR, // 0 // Errori di open E_CANTOPEN, // 1 E_UNESPECTEDEOF // 2 }; /// Standard call for knowing the meaning of an error code static const char *ErrorMsg(int error) { static const char * smf_error_msg[] = { "No errors", "Can't open file", "Premature End of file", }; if(error>2 || error<0) return "Unknown error"; else return smf_error_msg[error]; }; ///Standard call for reading a mesh static int Open(OpenMeshType &m, const char * filename ) { VertexType v; FaceType f; FILE *fp; float x,y,z; bool one = true; std::map mv; fp = fopen(filename,"r"); if(!fp) return -1; char buf[1024]; while( fgets(buf,1024,fp) ) { char *vf, *comm_pt; if((comm_pt = strstr(buf,"#")) != NULL) *comm_pt = '\0'; if( (vf = strstr(buf,"v")) != NULL ) { sscanf(vf+1,"%f %f %f", &x, &y, &z); v.P()[0] = x; v.P()[1] = y; v.P()[2] = z; m.vert.push_back(v); } else if( (vf = strstr(buf,"f")) != NULL) { if(one) { VertexIterator vi; int ind; for(ind=1,vi=m.vert.begin(); vi!=m.vert.end(); ++vi,++ind) mv[ind]=&*vi; one = false; } int v1,v2,v3; sscanf(vf+1,"%d %d %d", &v1, &v2, &v3); f.V(0) = mv[v1]; f.V(1) = mv[v2]; f.V(2) = mv[v3]; m.face.push_back(f); } } m.vn = m.vert.size(); m.fn = m.face.size(); return 0; } }; }// end of io }// end of tri }// end of vcg #endif qutemol/vcg/wrap/io_trimesh/import_off.h0000444000175000017500000006146711001102624017032 0ustar mbamba/**************************************************************************** * VCGLib o o * * Visual and Computer Graphics Library o o * * _ O _ * * Copyright(C) 2004 \/)\/ * * Visual Computing Lab /\/| * * ISTI - Italian National Research Council | * * \ * * All rights reserved. * * * * 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. * * * * 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 (http://www.gnu.org/licenses/gpl.txt) * * for more details. * * * ****************************************************************************/ /**************************************************************************** History $Log: import_off.h,v $ Revision 1.23 2008/04/15 10:38:12 cignoni added suppor of color in OFF format. Revision 1.22 2008/03/13 08:48:10 granzuglia added two missing include files: 1) #include 2) #include Revision 1.21 2007/12/13 17:57:33 cignoni removed harmless gcc warnings Revision 1.20 2007/03/12 16:40:17 tarini Texture coord name change! "TCoord" and "Texture" are BAD. "TexCoord" is GOOD. Revision 1.19 2006/03/29 08:50:10 corsini Fix bug in texture coordinates reading Revision 1.18 2006/03/29 08:15:46 corsini Fix several bugs Add LoadMask Improve parsing capabilities (account for unexpected newline) Revision 1.17 2006/03/01 08:25:30 cignoni Corrected bug in wrong counting the parsed tokens during the reading of color components Revision 1.16 2006/02/28 15:18:10 corsini Fix loading mask update Revision 1.15 2006/02/09 15:56:34 corsini Update load mask Revision 1.14 2006/02/09 15:18:32 corsini *** empty log message *** Revision 1.12 2006/02/06 13:11:01 corsini Renamed UnexpectedEOF as InvalidFile and added UnsupportedFormat and ErrorNotTriangularFace (by Laurent Saboret) Revision 1.11 2006/01/30 15:02:50 cignoni Added mask filling in open Revision 1.10 2006/01/10 13:20:42 cignoni Changed ply::PlyMask to io::Mask Revision 1.9 2005/12/01 00:58:56 cignoni Added and removed typenames for gcc compiling... Revision 1.8 2005/11/12 18:12:16 cignoni Added casts and changed integral types to remove warnings Revision 1.7 2005/09/28 10:30:14 rita_borgo *** empty log message *** Revision 1.6 2005/01/26 22:44:51 cignoni Resolved scoping of constant of OFF codes Revision 1.5 2005/01/18 12:35:18 rita_borgo Added #include it was giving problems with Allocator:: Revision 1.4 2005/01/03 11:18:24 cignoni changed a .. rfind('OFF') .. in rfind("OFF") and added some casts Revision 1.3 2004/11/23 11:56:50 cignoni Corrected small bug in the tokenizer (it would add a fake token for lines ending with a space before /n) ****************************************************************************/ #ifndef __VCGLIB_IMPORT_OFF #define __VCGLIB_IMPORT_OFF #include #include #include #include #include #include #include #include namespace vcg { namespace tri { namespace io { // /** \addtogroup */ // /* @{ */ /** This class encapsulate a filter for importing OFF meshes. A basic description of the OFF file format can be found at http://www.geomview.org/docs/html/geomview_41.html */ template class ImporterOFF { public: typedef typename MESH_TYPE::VertexType VertexType; typedef typename MESH_TYPE::VertexIterator VertexIterator; typedef typename MESH_TYPE::VertexPointer VertexPointer; typedef typename MESH_TYPE::FaceType FaceType; typedef typename MESH_TYPE::FaceIterator FaceIterator; typedef typename MESH_TYPE::FacePointer FacePointer; typedef typename MESH_TYPE::CoordType CoordType; typedef typename MESH_TYPE::ScalarType ScalarType; // OFF codes enum OFFCodes {NoError=0, CantOpen, InvalidFile, UnsupportedFormat, ErrorNotTriangularFace}; /*! * Standard call for knowing the meaning of an error code * \param message_code The code returned by Open * \return The string describing the error code */ static const char* ErrorMsg(int message_code) { static const char* error_msg[] = { "No errors", "Can't open file", "Invalid file", "Unsupported format", "Face with more than 3 vertices" }; if(message_code>4 || message_code<0) return "Unknown error"; else return error_msg[message_code]; }; /** * Load only the properties of the 3D objects. * * \param filename the name of the file to read from * \param loadmask the mask which encodes the properties * \return the operation result */ static bool LoadMask(const char *filename, int &loadmask) { // To obtain the loading mask all the file must be parsed // to distinguish between per-vertex and per-face color attribute. loadmask=0; MESH_TYPE dummyMesh; return (Open(dummyMesh, filename, loadmask,0,true)==NoError); } static int Open(MESH_TYPE &mesh, const char *filename,CallBackPos *cb=0) { int loadmask; return Open(mesh,filename,loadmask,cb); } /*! * Standard call for reading a mesh. * * \param mesh the destination mesh * \param filename the name of the file to read from * \return the operation result */ static int Open(MESH_TYPE &mesh, const char *filename, int &loadmask, CallBackPos *cb=0, bool onlyMaskFlag=false ) { std::ifstream stream(filename); if (stream.fail()) return CantOpen; std::vector< std::string > tokens; TokenizeNextLine(stream, tokens); bool isNormalDefined = false; bool isColorDefined = false; bool isTexCoordDefined = false; int dimension = 3; bool homogeneousComponents = false; // The "[ST][C][N][4][n]OFF" keyword is optional. Default is "OFF". std::string header = tokens[tokens.size()-1]; if (header.rfind("OFF") != std::basic_string::npos) { for (int u = static_cast(header.rfind("OFF")-1); u>=0; u--) { if (header[u] == 'C') isColorDefined = true; else if (header[u] == 'N') isNormalDefined = true; else if (u>0 && header[u-1] == 'S' && header[u] == 'T') isTexCoordDefined = true; else if (header[u] == '4') homogeneousComponents = true; else if (header[u] == 'n') { TokenizeNextLine(stream, tokens); dimension = atoi(tokens[0].c_str()); } } TokenizeNextLine(stream, tokens); } // Update loading mask /////////////////////////////////////// loadmask = Mask::IOM_VERTCOORD | Mask::IOM_FACEINDEX; if (isNormalDefined) loadmask |= Mask::IOM_VERTNORMAL; if (isTexCoordDefined) loadmask |= Mask::IOM_VERTTEXCOORD; if (isColorDefined) { loadmask |= Mask::IOM_VERTCOLOR;loadmask |= Mask::IOM_FACECOLOR;} if(onlyMaskFlag) return NoError; mesh.Clear(); // check on next 2 lines to detect corrupted files if(tokens.size() < 3) return InvalidFile; unsigned int nVertices, nFaces, nEdges; nVertices = atoi(tokens[0].c_str()); nFaces = atoi(tokens[1].c_str()); nEdges = atoi(tokens[2].c_str()); // dimension is the space dimension of vertices => it must be three(!) if (dimension != 3) return UnsupportedFormat; if (homogeneousComponents) return UnsupportedFormat; // READ VERTICES ////////////////////////////////////////////////////// VertexIterator v_iter = Allocator::AddVertices(mesh, nVertices); TokenizeNextLine(stream, tokens); size_t k = 0; // next token to read for (unsigned int i=0; i(tokens.size()) - static_cast(k) /* tokens already parsed */ - 2 * (isTexCoordDefined ? 1 : 0); if (nb_color_components < 0 || nb_color_components > 4) return InvalidFile; // set per-vertex color attribute if (nb_color_components > 0) loadmask |= Mask::IOM_VERTCOLOR; // Store color components if (tri::HasPerVertexColor(mesh)) { // Read color components if (nb_color_components == 1) { // read color index (*v_iter).C().Import(ColorMap(atoi(tokens[k].c_str()))); } else if (nb_color_components == 3) { // read RGB color if (tokens[k].find(".") == size_t(-1))// if it is a float there is a dot { // integers unsigned char r = static_cast(atoi(tokens[k].c_str())); unsigned char g = static_cast(atoi(tokens[k+1].c_str())); unsigned char b = static_cast(atoi(tokens[k+2].c_str())); vcg::Color4b color(r, g, b, 255); (*v_iter).C().Import(color); } else { // floats float r = static_cast(atof(tokens[k].c_str())); float g = static_cast(atof(tokens[k+1].c_str())); float b = static_cast(atof(tokens[k+2].c_str())); vcg::Color4f color(r, g, b, 1.0); (*v_iter).C().Import(color); } } else if (nb_color_components == 4) { // read RGBA color if (tokens[k].find(".") == size_t(-1)) { // integers unsigned char r = static_cast(atoi(tokens[k].c_str())); unsigned char g = static_cast(atoi(tokens[k+1].c_str())); unsigned char b = static_cast(atoi(tokens[k+2].c_str())); unsigned char a = static_cast(atoi(tokens[k+3].c_str())); Color4b color(r, g, b, a); (*v_iter).C().Import(color); } else { // floats float r = static_cast(atof(tokens[k].c_str())); float g = static_cast(atof(tokens[k+1].c_str())); float b = static_cast(atof(tokens[k+2].c_str())); float a = static_cast(atof(tokens[k+3].c_str())); vcg::Color4f color(r, g, b, a); (*v_iter).C().Import(color); } } } k += nb_color_components; } if (isTexCoordDefined) { for (unsigned int j=0; j<2; j++) { // Go to next line when needed if (k == tokens.size()) // if EOL { TokenizeNextLine(stream, tokens); if (tokens.size() == 0) // if EOF return InvalidFile; k = 0; } std::string str = tokens[k]; k++; // Store texture coordinates if (tri::HasPerWedgeTexCoord(mesh)) { //...TODO... } } } } // for i=... // READ FACES ////////////////////////////////////////////////////// Allocator::AddFaces(mesh, nFaces); unsigned int f0=0; for (unsigned int f=0; f < nFaces; f++) { f0 = f; if (stream.fail()) return InvalidFile; if(cb && (f%1000)==0) cb(50+f*50/nFaces,"Face Loading"); TokenizeNextLine(stream, tokens); int vert_per_face = atoi(tokens[0].c_str()); k = 1; if (vert_per_face == 3) { for (int j = 0; j < 3; j++) { // Go to next line when needed if (k == tokens.size()) // if EOL { TokenizeNextLine(stream, tokens); if (tokens.size() == 0) // if EOF return InvalidFile; k = 0; } mesh.face[f].V(j) = &(mesh.vert[ atoi(tokens[k].c_str()) ]); k++; } } else { // The face must be triangulate unsigned int trigs = vert_per_face-3; // number of extra faces to add nFaces += trigs; Allocator::AddFaces(mesh, trigs); int *vertIndices = new int[vert_per_face]; for (int j=0; j < vert_per_face; j++) { // Go to next line when needed if (k == tokens.size()) // if EOL { TokenizeNextLine(stream, tokens); if (tokens.size() == 0) // if EOF return InvalidFile; k = 0; } vertIndices[j] = atoi(tokens[k].c_str()); k++; } for (int j=0; j<=vert_per_face-3; j++) { mesh.face[f+j].V(0) = &(mesh.vert[ vertIndices[0 ] ]); mesh.face[f+j].V(1) = &(mesh.vert[ vertIndices[1+j] ]); mesh.face[f+j].V(2) = &(mesh.vert[ vertIndices[2+j] ]); } f+=trigs; delete [] vertIndices; } // NOTE: It is assumed that colored face takes exactly one text line // (otherwise it is impossible to parse color information since // color components can vary) if (isColorDefined && tri::HasPerFaceColor(mesh)) { size_t color_elements = tokens.size() - vert_per_face-1; // set per-face color attribute if (color_elements > 0) loadmask |= Mask::IOM_FACECOLOR; switch (color_elements) { case 0: { for ( ; f0<=f; f0++) mesh.face[f0].C().Import(vcg::Color4f(.666f, .666f, .666f, .666f)); break; } case 1: { for ( ; f0<=f; f0++) mesh.face[f0].C().Import( ColorMap( atoi(tokens[vert_per_face+1].c_str()) ) ); break; } case 3: { if (tokens[vert_per_face+1].find('.')==size_t(-1)) { int rgb[3]; rgb[0] = atoi( tokens[vert_per_face+1].c_str() ); rgb[1] = atoi( tokens[vert_per_face+2].c_str() ); rgb[2] = atoi( tokens[vert_per_face+3].c_str() ); for ( ; f0<=f; f0++) mesh.face[f0].C().SetRGB(rgb[0], rgb[1], rgb[2]); } else { float color[3]; color[0] = (float) atof( tokens[vert_per_face+1].c_str() ); color[1] = (float) atof( tokens[vert_per_face+2].c_str() ); color[2] = (float) atof( tokens[vert_per_face+3].c_str() ); for ( ; f0<=f; f0++) mesh.face[f0].C().Import(vcg::Color4f(color[0], color[1], color[2], 1.0f)); } break; } case 4: { if (tokens[vert_per_face+1].find('.')==0) // if it is a float there is a dot { unsigned char color[4]; color[0] = (unsigned char) atoi(tokens[vert_per_face+1].c_str()); color[1] = (unsigned char) atoi(tokens[vert_per_face+2].c_str()); color[2] = (unsigned char) atoi(tokens[vert_per_face+3].c_str()); color[3] = (unsigned char) atoi(tokens[vert_per_face+4].c_str()); for ( ; f0<=f; f0++) mesh.face[f0].C().Import(vcg::Color4f(color[0], color[1], color[2], color[3])); } else { float color[4]; color[0] = float( atof(tokens[vert_per_face+1].c_str()) ); color[1] = float( atof(tokens[vert_per_face+2].c_str()) ); color[2] = float( atof(tokens[vert_per_face+3].c_str()) ); color[3] = float( atof(tokens[vert_per_face+4].c_str()) ); for ( ; f0<=f; f0++) mesh.face[f0].C().Import(vcg::Color4f(color[0], color[1], color[2], color[3])); } break; } } //end switch } // end if (isColorDefined) } // end of for f=... return NoError; } // end Open protected: /*! * Read the next valid line and parses it into "tokens", allowing the tokens to be read one at a time. * \param stream The object providing the input stream * \param tokens The "tokens" in the next line */ inline static const void TokenizeNextLine(std::ifstream &stream, std::vector< std::string > &tokens) { std::string line; do std::getline(stream, line, '\n'); while (line[0] == '#' || line.length()==0); size_t from = 0; size_t to = 0; size_t length = line.size(); tokens.clear(); do { while ( (line[from]==' ' || line[from] == '\t') && from!=length) from++; if(from!=length) { to = from+1; while ( (line[to]!=' ' && line[to] != '\t') && to!=length) to++; tokens.push_back(line.substr(from, to-from).c_str()); from = to; } } while (fromcolor mapping, according to the Geomview's `cmap.fmap' file. * \param i the color index * \return the corresponding vcg::Color4f color */ static const vcg::Color4f ColorMap(int i) { static const float colorMap[148][4] = { { 1.0f, 1.0f, 1.0f, 1.0f }, { 1.0f, 1.0f, 1.0f, 1.0f }, { 1.0f, 1.0f, 1.0f, 1.0f }, { 1.0f, 1.0f, 1.0f, 1.0f }, { 1.0f, 1.0f, 1.0f, 1.0f }, { 1.0f, 1.0f, 1.0f, 1.0f }, { 0.7f, 0.7f, 0.7f, 0.7f }, { 0.2f, 0.2f, 0.2f, 0.2f }, { 0.9f, 0.9f, 0.9f, 0.9f }, { 0.1f, 0.1f, 0.1f, 0.1f }, { 0.1f, 0.1f, 0.1f, 0.1f }, { 0.8f, 0.8f, 0.8f, 0.8f }, { 0.7f, 0.7f, 0.7f, 0.7f }, { 0.7f, 0.7f, 0.7f, 0.7f }, { 0.0f, 0.0f, 0.0f, 0.0f }, { 0.9f, 0.9f, 0.9f, 0.9f }, { 0.2f, 0.2f, 0.2f, 0.2f }, { 0.0f, 0.0f, 0.0f, 0.0f }, { 0.75f, 0.75f, 0.75f, 0.75f }, { 0.8f, 0.8f, 0.8f, 0.8f }, { 0.8f, 0.8f, 0.8f, 0.8f }, { 0.0f, 0.0f, 0.0f, 0.0f }, { 0.0f, 0.0f, 0.0f, 0.0f }, { 0.0f, 0.0f, 0.0f, 0.0f }, { 0.0f, 0.0f, 0.0f, 0.0f }, { 0.4f, 0.4f, 0.4f, 0.4f }, { 0.4f, 0.4f, 0.4f, 0.4f }, { 0.8f, 0.8f, 0.8f, 0.8f }, { 0.8f, 0.8f, 0.8f, 0.8f }, { 0.7f, 0.7f, 0.7f, 0.7f }, { 0.7f, 0.7f, 0.7f, 0.7f }, { 0.7f, 0.7f, 0.7f, 0.7f }, { 0.7f, 0.7f, 0.7f, 0.7f }, { 0.0f, 0.0f, 0.0f, 0.0f }, { 0.9f, 0.9f, 0.9f, 0.9f }, { 0.0f, 0.0f, 0.0f, 0.0f }, { 0.0f, 0.0f, 0.0f, 0.0f }, { 0.75f, 0.75f, 0.75f, 0.75f }, { 0.8f, 0.8f, 0.8f, 0.8f }, { 0.4f, 0.4f, 0.4f, 0.4f }, { 0.0f, 0.0f, 0.0f, 0.0f }, { 0.0f, 0.0f, 0.0f, 0.0f }, { 0.4f, 0.4f, 0.4f, 0.4f }, { 0.8f, 0.8f, 0.8f, 0.8f }, { 0.7f, 0.7f, 0.7f, 0.7f }, { 0.7f, 0.7f, 0.7f, 0.7f }, { 0.0f, 0.0f, 0.0f, 0.0f }, { 0.9f, 0.9f, 0.9f, 0.9f }, { 0.0f, 0.0f, 0.0f, 0.0f }, { 0.0f, 0.0f, 0.0f, 0.0f }, { 0.75f, 0.75f, 0.75f, 0.75f }, { 0.8f, 0.8f, 0.8f, 0.8f }, { 0.4f, 0.4f, 0.4f, 0.4f }, { 0.0f, 0.0f, 0.0f, 0.0f }, { 0.0f, 0.0f, 0.0f, 0.0f }, { 0.4f, 0.4f, 0.4f, 0.4f }, { 0.8f, 0.8f, 0.8f, 0.8f }, { 0.7f, 0.7f, 0.7f, 0.7f }, { 0.7f, 0.7f, 0.7f, 0.7f }, { 0.0f, 0.0f, 0.0f, 0.0f }, { 0.9f, 0.9f, 0.9f, 0.9f }, { 0.0f, 0.0f, 0.0f, 0.0f }, { 0.0f, 0.0f, 0.0f, 0.0f }, { 0.75f, 0.75f, 0.75f, 0.75f }, { 0.8f, 0.8f, 0.8f, 0.8f }, { 0.4f, 0.4f, 0.4f, 0.4f }, { 0.0f, 0.0f, 0.0f, 0.0f }, { 0.0f, 0.0f, 0.0f, 0.0f }, { 0.4f, 0.4f, 0.4f, 0.4f }, { 0.8f, 0.8f, 0.8f, 0.8f }, { 1.0f, 1.0f, 1.0f, 1.0f }, { 1.0f, 1.0f, 1.0f, 1.0f }, { 1.0f, 1.0f, 1.0f, 1.0f }, { 1.0f, 1.0f, 1.0f, 1.0f }, { 1.0f, 1.0f, 1.0f, 1.0f }, { 1.0f, 1.0f, 1.0f, 1.0f }, { 0.05f, 0.05f, 0.05f, 0.05f }, { 0.7f, 0.7f, 0.7f, 0.7f }, { 0.2f, 0.2f, 0.2f, 0.2f }, { 0.9f, 0.9f, 0.9f, 0.9f }, { 0.0f, 0.0f, 0.0f, 0.0f }, { 0.1f, 0.1f, 0.1f, 0.1f }, { 0.8f, 0.8f, 0.8f, 0.8f }, { 0.7f, 0.7f, 0.7f, 0.7f }, { 0.7f, 0.7f, 0.7f, 0.7f }, { 0.7f, 0.7f, 0.7f, 0.7f }, { 0.7f, 0.7f, 0.7f, 0.7f }, { 0.0f, 0.0f, 0.0f, 0.0f }, { 0.0f, 0.0f, 0.0f, 0.0f }, { 0.9f, 0.9f, 0.9f, 0.9f }, { 0.9f, 0.9f, 0.9f, 0.9f }, { 0.0f, 0.0f, 0.0f, 0.0f }, { 0.0f, 0.0f, 0.0f, 0.0f }, { 0.0f, 0.0f, 0.0f, 0.0f }, { 0.0f, 0.0f, 0.0f, 0.0f }, { 0.75f, 0.75f, 0.75f, 0.75f }, { 0.75f, 0.75f, 0.75f, 0.75f }, { 0.8f, 0.8f, 0.8f, 0.8f }, { 0.8f, 0.8f, 0.8f, 0.8f }, { 0.0f, 0.0f, 0.0f, 0.0f }, { 0.0f, 0.0f, 0.0f, 0.0f }, { 0.0f, 0.0f, 0.0f, 0.0f }, { 0.0f, 0.0f, 0.0f, 0.0f }, { 0.4f, 0.4f, 0.4f, 0.4f }, { 0.4f, 0.4f, 0.4f, 0.4f }, { 0.8f, 0.8f, 0.8f, 0.8f }, { 0.8f, 0.8f, 0.8f, 0.8f }, { 0.7f, 0.7f, 0.7f, 0.7f }, { 0.7f, 0.7f, 0.7f, 0.7f }, { 0.7f, 0.7f, 0.7f, 0.7f }, { 0.7f, 0.7f, 0.7f, 0.7f }, { 0.0f, 0.0f, 0.0f, 0.0f }, { 0.9f, 0.9f, 0.9f, 0.9f }, { 0.0f, 0.0f, 0.0f, 0.0f }, { 0.0f, 0.0f, 0.0f, 0.0f }, { 0.75f, 0.75f, 0.75f, 0.75f }, { 0.8f, 0.8f, 0.8f, 0.8f }, { 0.4f, 0.4f, 0.4f, 0.4f }, { 0.0f, 0.0f, 0.0f, 0.0f }, { 0.0f, 0.0f, 0.0f, 0.0f }, { 0.4f, 0.4f, 0.4f, 0.4f }, { 0.8f, 0.8f, 0.8f, 0.8f }, { 0.7f, 0.7f, 0.7f, 0.7f }, { 0.7f, 0.7f, 0.7f, 0.7f }, { 0.0f, 0.0f, 0.0f, 0.0f }, { 0.9f, 0.9f, 0.9f, 0.9f }, { 0.0f, 0.0f, 0.0f, 0.0f }, { 0.0f, 0.0f, 0.0f, 0.0f }, { 0.75f, 0.75f, 0.75f, 0.75f }, { 0.8f, 0.8f, 0.8f, 0.8f }, { 0.4f, 0.4f, 0.4f, 0.4f }, { 0.0f, 0.0f, 0.0f, 0.0f }, { 0.0f, 0.0f, 0.0f, 0.0f }, { 0.4f, 0.4f, 0.4f, 0.4f }, { 0.8f, 0.8f, 0.8f, 0.8f }, { 0.7f, 0.7f, 0.7f, 0.7f }, { 0.7f, 0.7f, 0.7f, 0.7f }, { 0.0f, 0.0f, 0.0f, 0.0f }, { 0.9f, 0.9f, 0.9f, 0.9f }, { 0.0f, 0.0f, 0.0f, 0.0f }, { 0.0f, 0.0f, 0.0f, 0.0f }, { 0.75f, 0.75f, 0.75f, 0.75f }, { 0.8f, 0.8f, 0.8f, 0.8f }, { 0.4f, 0.4f, 0.4f, 0.4f }, { 0.0f, 0.0f, 0.0f, 0.0f }, { 0.0f, 0.0f, 0.0f, 0.0f }, { 0.4f, 0.4f, 0.4f, 0.4f }, { 0.8f, 0.8f, 0.8f, 0.8f } }; return Color4f(colorMap[i][0], colorMap[i][1], colorMap[i][2], colorMap[i][3]); } }; // /*! @} */ } //namespace io }//namespace tri } // namespace vcg #endif //__VCGLIB_IMPORT_OFF qutemol/vcg/wrap/io_trimesh/export_idtf.h0000444000175000017500000004020110753543324017217 0ustar mbamba#ifndef __VCGLIB_EXPORTERIDTF #define __VCGLIB_EXPORTERIDTF #include #include #include #include #include class TextUtility { public: template static std::string nmbToStr(NUMERICTYPE n) { std::stringstream ss; ss << n; return ss.str(); } }; class Output_File { public: Output_File(const std::string& file) :_file() { _file.open(file.c_str(),std::ios::out); } void write(unsigned int tabl,const std::string& st) { std::string tmp; for(unsigned int ii = 0;ii < tabl;++ii) tmp += '\t'; _file << tmp << st << std::endl; } ~Output_File() { _file.close(); } private: std::ofstream _file; std::string _tab; }; #include #include #include #include namespace vcg { namespace tri { namespace io { namespace QtUtilityFunctions { static void splitFilePath(const QString& filepath,QStringList& trim_path) { QString file_uniformed = filepath; file_uniformed.replace(QString("\\"),QString("/")); trim_path = file_uniformed.split("/"); } static QString fileNameFromTrimmedPath(const QStringList& file_path) { if (file_path.size() > 0) return file_path.at(file_path.size() - 1); else return QString(); } static QString fileNameFromPath(const QString& filepath) { QStringList list; splitFilePath(filepath,list); return fileNameFromTrimmedPath(list); } static QString pathWithoutFileName(const QString& filepath) { QString tmp(filepath); tmp.remove(fileNameFromPath(filepath)); return tmp; } static QString fileExtension(const QString& filepath) { QStringList trim_list; splitFilePath(filepath,trim_list); QString file = fileNameFromTrimmedPath(trim_list); trim_list = file.split("."); return trim_list.at(trim_list.size() - 1); } } class TGA_Exporter { public: struct TGAHeader { unsigned char identsize; unsigned char colourmaptype; unsigned char imagetype; unsigned char colormapspecs[5]; short xstart; short ystart; short width; short height; unsigned char bits; unsigned char descriptor; }; static void convert(const QString& outfile,const QImage& im) { TGAHeader tga; tga.identsize = 0; tga.colourmaptype = 0; tga.imagetype = 2; memset(tga.colormapspecs,0,5); tga.xstart = (short) im.offset().x(); tga.ystart = (short) im.offset().y(); tga.height = (short) im.height(); tga.width = (short) im.width(); std::ofstream file(qPrintable(outfile),std::ofstream::binary); unsigned char* tmpchan; int totbyte; if (im.hasAlphaChannel()) { //is a 8-digits binary number code // always 0 0 | mirroring | bits //(future uses)| image | for alpha-channel //-------------------------------------------- // 7 6 | 5 4 | 3 2 1 0 //-------------------------------------------- // 0 0 | 1 0 | 1 0 0 0 tga.descriptor = (char) 40; tga.bits = (char) 32; } else { //is a 8-digits binary number code // always 0 0 | mirroring | bits //(future uses)| image | for alpha-channel //-------------------------------------------- // 7 6 | 5 4 | 3 2 1 0 //-------------------------------------------- // 0 0 | 1 0 | 0 0 0 0 tga.descriptor = (char) 32; tga.bits = (char) 24; } totbyte = tga.height * tga.width * (tga.bits / 8); if (im.hasAlphaChannel()) tmpchan = const_cast(im.bits()); else { tmpchan = new unsigned char[totbyte]; int ii = 0; while(ii < totbyte) { tmpchan[ii] = const_cast(im.bits())[ii + (ii/3)]; ++ii; } } file.write((char *) &tga,sizeof(tga)); file.write(reinterpret_cast(tmpchan),totbyte); file.close(); } template static void convertTexturesFiles(SaveMeshType& m,const QString& file_path,QStringList& conv_file) { for(unsigned int ii = 0; ii < m.textures.size(); ++ii) { QString qtmp(m.textures[ii].c_str()); QString ext = QtUtilityFunctions::fileExtension(qtmp); if (ext.toLower() != "tga") { QImage img(qtmp); QString stmp; if ((file_path.at(file_path.length() - 1) != '/') || (file_path.at(file_path.length() - 1) != '\\')) stmp = file_path + QString("/"); else stmp = file_path; qtmp = stmp + qtmp.remove(ext) + "tga"; m.textures[ii] = qtmp.toStdString(); TGA_Exporter::convert(qtmp,img); conv_file.push_back(qtmp); } } } static void removeConvertedTexturesFiles(const QStringList& conv_file) { for(unsigned int ii = 0;ii < conv_file.size();++ii) { QDir dir(QtUtilityFunctions::pathWithoutFileName(conv_file[ii])); dir.remove(QtUtilityFunctions::fileNameFromPath(conv_file[ii])); } } }; template class ExporterIDTF { public: typedef typename SaveMeshType::VertexPointer VertexPointer; typedef typename SaveMeshType::ScalarType ScalarType; typedef typename SaveMeshType::VertexType VertexType; typedef typename SaveMeshType::FaceType FaceType; typedef typename SaveMeshType::ConstVertexIterator ConstVertexIterator; typedef typename SaveMeshType::VertexIterator VertexIterator; typedef typename SaveMeshType::FaceIterator FaceIterator; typedef typename SaveMeshType::ConstFaceIterator ConstFaceIterator; typedef typename SaveMeshType::CoordType CoordType; enum IDTFError { E_NOERROR // 0 }; static const char *ErrorMsg(int error) { static const char * dae_error_msg[] = { "No errors" }; if(error>0 || error<0) return "Unknown error"; else return dae_error_msg[error]; }; static QStringList convertInTGATextures(SaveMeshType& m,const QString& path,QStringList& textures_to_be_restored) { //if there are textures file that aren't in tga format I have to convert them //I maintain the converted file name (i.e. file_path + originalname without extension + tga) in mesh.textures but I have to revert to the original ones //before the function return. for(unsigned int ii = 0; ii < m.textures.size();++ii) textures_to_be_restored.push_back(m.textures[ii].c_str()); //tmp vector to save the tga created files that should be deleted. QStringList convfile; vcg::tri::io::TGA_Exporter::convertTexturesFiles(m,path,convfile); return convfile; } static void removeConvertedTGATextures(const QStringList& convfile) { //if some tga files have been created I have to delete them vcg::tri::io::TGA_Exporter::removeConvertedTexturesFiles(convfile); } static void restoreConvertedTextures(SaveMeshType& mesh_with_textures_to_be_restored,const QStringList& textures_to_be_restored) { mesh_with_textures_to_be_restored.textures.clear(); for(QStringList::ConstIterator it = textures_to_be_restored.begin();it != textures_to_be_restored.end();++it) mesh_with_textures_to_be_restored.textures.push_back(it->toStdString()); } static int Save(SaveMeshType& m,const char* file,const int mask) { Output_File idtf(file); idtf.write(0,"FILE_FORMAT \"IDTF\""); idtf.write(0,"FORMAT_VERSION 100\n"); idtf.write(0,"NODE \"MODEL\" {"); idtf.write(1,"NODE_NAME \"VcgMesh01\""); idtf.write(1,"PARENT_LIST {"); idtf.write(2,"PARENT_COUNT 1"); idtf.write(2,"PARENT 0 {"); idtf.write(3,"PARENT_NAME \"\""); idtf.write(3,"PARENT_TM {"); idtf.write(4,"1.000000 0.000000 0.000000 0.000000"); idtf.write(4,"0.000000 1.000000 0.000000 0.000000"); idtf.write(4,"0.000000 0.000000 1.000000 0.000000"); idtf.write(4,"0.000000 0.000000 0.000000 1.000000"); idtf.write(3,"}"); idtf.write(2,"}"); idtf.write(1,"}"); idtf.write(1,"RESOURCE_NAME \"MyVcgMesh01\""); idtf.write(0,"}"); if (mask & Mask::IOM_WEDGTEXCOORD) { idtf.write(0,""); idtf.write(0,"RESOURCE_LIST \"SHADER\" {"); idtf.write(1,"RESOURCE_COUNT " + TextUtility::nmbToStr(m.textures.size())); for(unsigned int ii = 0; ii < m.textures.size(); ++ii) { idtf.write(1,"RESOURCE " + TextUtility::nmbToStr(ii) + " {"); idtf.write(2,"RESOURCE_NAME \"ModelShader" + TextUtility::nmbToStr(ii) +"\""); idtf.write(2,"SHADER_MATERIAL_NAME \"Material1\""); idtf.write(2,"SHADER_ACTIVE_TEXTURE_COUNT 1"); idtf.write(2,"SHADER_TEXTURE_LAYER_LIST {"); idtf.write(3,"TEXTURE_LAYER 0 {"); idtf.write(4,"TEXTURE_NAME \"Texture" + TextUtility::nmbToStr(ii) +"\""); idtf.write(3,"}"); idtf.write(2,"}"); } idtf.write(1,"}"); idtf.write(0,"}"); idtf.write(0,""); idtf.write(0,"RESOURCE_LIST \"MATERIAL\" {"); idtf.write(1,"RESOURCE_COUNT 1"); idtf.write(1,"RESOURCE 0 {"); idtf.write(2,"RESOURCE_NAME \"Material1\""); idtf.write(2,"MATERIAL_AMBIENT 0.2 0.2 0.2"); idtf.write(2,"MATERIAL_DIFFUSE 0.8 0.8 0.8"); idtf.write(2,"MATERIAL_SPECULAR 0.0 0.0 0.0"); idtf.write(2,"MATERIAL_EMISSIVE 0.0 0.0 0.0"); idtf.write(2,"MATERIAL_REFLECTIVITY 0.100000"); idtf.write(2,"MATERIAL_OPACITY 1.000000"); idtf.write(1,"}"); idtf.write(0,"}"); idtf.write(0,""); idtf.write(0,"RESOURCE_LIST \"TEXTURE\" {"); idtf.write(1,"RESOURCE_COUNT " + TextUtility::nmbToStr(m.textures.size())); for(unsigned int ii = 0; ii < m.textures.size();++ii) { idtf.write(1,"RESOURCE " + TextUtility::nmbToStr(ii) + " {"); idtf.write(2,"RESOURCE_NAME \"Texture" + TextUtility::nmbToStr(ii) + "\""); idtf.write(2,"TEXTURE_PATH \"" + m.textures[ii] + "\""); idtf.write(1,"}"); } idtf.write(0,"}"); } idtf.write(0,""); idtf.write(0,"RESOURCE_LIST \"MODEL\" {"); idtf.write(1,"RESOURCE_COUNT 1"); idtf.write(1,"RESOURCE 0 {"); idtf.write(2,"RESOURCE_NAME \"MyVcgMesh01\""); idtf.write(2,"MODEL_TYPE \"MESH\""); idtf.write(2,"MESH {"); idtf.write(3,"FACE_COUNT " + TextUtility::nmbToStr(m.face.size())); idtf.write(3,"MODEL_POSITION_COUNT " + TextUtility::nmbToStr(m.vert.size())); idtf.write(3,"MODEL_NORMAL_COUNT " + TextUtility::nmbToStr(m.face.size() * 3)); if (mask & vcg::tri::io::Mask::IOM_VERTCOLOR) idtf.write(3,"MODEL_DIFFUSE_COLOR_COUNT " + TextUtility::nmbToStr(m.face.size() * 3)); else idtf.write(3,"MODEL_DIFFUSE_COLOR_COUNT 0"); idtf.write(3,"MODEL_SPECULAR_COLOR_COUNT 0"); if (mask & vcg::tri::io::Mask::IOM_WEDGTEXCOORD) idtf.write(3,"MODEL_TEXTURE_COORD_COUNT " + TextUtility::nmbToStr(m.face.size() * 3)); else idtf.write(3,"MODEL_TEXTURE_COORD_COUNT 0"); idtf.write(3,"MODEL_BONE_COUNT 0"); unsigned int mod_sha; if (m.textures.size() == 0) mod_sha = 1; else mod_sha = m.textures.size(); idtf.write(3,"MODEL_SHADING_COUNT " + TextUtility::nmbToStr(mod_sha)); idtf.write(3,"MODEL_SHADING_DESCRIPTION_LIST {"); unsigned int hh = 0; do { idtf.write(4,"SHADING_DESCRIPTION " + TextUtility::nmbToStr(hh) + " {"); if (mask & vcg::tri::io::Mask::IOM_WEDGTEXCOORD) { idtf.write(5,"TEXTURE_LAYER_COUNT 1"); idtf.write(5,"TEXTURE_COORD_DIMENSION_LIST {"); idtf.write(6,"TEXTURE_LAYER 0 DIMENSION: 2"); idtf.write(5,"}"); idtf.write(5,"SHADER_ID 0"); } else { idtf.write(5,"TEXTURE_LAYER_COUNT 0"); idtf.write(5,"SHADER_ID 0"); } idtf.write(4,"}"); ++hh; } while(hh < m.textures.size()); idtf.write(3,"}"); idtf.write(3,"MESH_FACE_POSITION_LIST {"); for(ConstFaceIterator fit = m.face.begin();fit != m.face.end();++fit) { idtf.write(4,TextUtility::nmbToStr(fit->V(0) - &(*m.vert.begin())) + " " + TextUtility::nmbToStr(fit->V(1) - &(*m.vert.begin())) + " " + TextUtility::nmbToStr(fit->V(2) - &(*m.vert.begin()))); } idtf.write(3,"}"); idtf.write(3,"MESH_FACE_NORMAL_LIST {"); unsigned int nn = 0; for(ConstFaceIterator fit = m.face.begin();fit != m.face.end();++fit) { idtf.write(4,TextUtility::nmbToStr(nn) + " " + TextUtility::nmbToStr(nn + 1) + " " + TextUtility::nmbToStr(nn + 2)); nn += 3; } idtf.write(3,"}"); idtf.write(3,"MESH_FACE_SHADING_LIST {"); for(FaceIterator fit = m.face.begin();fit != m.face.end();++fit) { unsigned int texind = 0; if (mask & vcg::tri::io::Mask::IOM_WEDGTEXCOORD) texind = fit->WT(0).N(); idtf.write(4,TextUtility::nmbToStr(texind)); } idtf.write(3,"}"); if (mask & vcg::tri::io::Mask::IOM_VERTCOLOR) { idtf.write(3,"MESH_FACE_DIFFUSE_COLOR_LIST {"); nn = 0; for(FaceIterator fit = m.face.begin();fit != m.face.end();++fit) { idtf.write(4,TextUtility::nmbToStr(nn) + " " + TextUtility::nmbToStr(nn + 2) + " " + TextUtility::nmbToStr(nn + 1)); nn += 3; } idtf.write(3,"}"); } if (mask & vcg::tri::io::Mask::IOM_WEDGTEXCOORD) { idtf.write(3,"MESH_FACE_TEXTURE_COORD_LIST {"); for(unsigned int ii = 0; ii < m.face.size();++ii) { idtf.write(4,"FACE " + TextUtility::nmbToStr(ii) + " {"); idtf.write(5,"TEXTURE_LAYER 0 TEX_COORD: " + TextUtility::nmbToStr(ii * 3) + " " + TextUtility::nmbToStr(ii * 3 + 1) + " " + TextUtility::nmbToStr(ii * 3 + 2)); idtf.write(4,"}"); } idtf.write(3,"}"); } idtf.write(3,"MODEL_POSITION_LIST {"); //vcg::tri::UpdateBounding::Box(m); //ScalarType diag = m.bbox.Diag(); //CoordType center = m.bbox.Center(); for(ConstVertexIterator vit = m.vert.begin();vit != m.vert.end();++vit) { CoordType tmp = vit->P();// - center);// /diag; idtf.write(4,TextUtility::nmbToStr(-tmp.X()) + " " + TextUtility::nmbToStr(tmp.Z()) + " " + TextUtility::nmbToStr(tmp.Y())); } idtf.write(3,"}"); idtf.write(3,"MODEL_NORMAL_LIST {"); for(FaceIterator fitn = m.face.begin();fitn != m.face.end();++fitn) { for(unsigned int ii = 0;ii < 3;++ii) { fitn->N().Normalize(); idtf.write(4,TextUtility::nmbToStr(-fitn->N().X()) + " " + TextUtility::nmbToStr(fitn->N().Z()) + " " + TextUtility::nmbToStr(fitn->N().Y())); } } idtf.write(3,"}"); if (mask & vcg::tri::io::Mask::IOM_WEDGTEXCOORD) { idtf.write(3,"MODEL_TEXTURE_COORD_LIST {"); for(FaceIterator fitn = m.face.begin();fitn != m.face.end();++fitn) { for(unsigned int ii = 0;ii < 3;++ii) { idtf.write(4,TextUtility::nmbToStr(fitn->WT(ii).U()) + " " + TextUtility::nmbToStr(-fitn->WT(ii).V()) + " " + TextUtility::nmbToStr(0.0f) + " " + TextUtility::nmbToStr(0.0f)); } } idtf.write(3,"}"); } if (mask & vcg::tri::io::Mask::IOM_VERTCOLOR) { idtf.write(3,"MODEL_DIFFUSE_COLOR_LIST {"); //ScalarType diag = m.bbox.Diag(); //CoordType center = m.bbox.Center(); for(FaceIterator vit = m.face.begin();vit != m.face.end();++vit) { for (unsigned int ii =0; ii <3;++ii) idtf.write(4,TextUtility::nmbToStr((int) vit->V(ii)->C().X()) + " " + TextUtility::nmbToStr((int) vit->V(ii)->C().Y()) + " " + TextUtility::nmbToStr((int) vit->V(ii)->C().Z()) + " 0"); } idtf.write(3,"}"); } idtf.write(2,"}"); idtf.write(1,"}"); idtf.write(0,"}"); if (mask & vcg::tri::io::Mask::IOM_VERTCOLOR) { idtf.write(0,"RESOURCE_LIST \"SHADER\" {"); idtf.write(1,"RESOURCE_COUNT 1"); idtf.write(1,"RESOURCE 0 {"); idtf.write(2,"RESOURCE_NAME \"VcgMesh010\""); idtf.write(2,"ATTRIBUTE_USE_VERTEX_COLOR \"TRUE\""); idtf.write(2,"SHADER_ACTIVE_TEXTURE_COUNT 0"); idtf.write(1,"}"); idtf.write(0,"}"); } if (mask & vcg::tri::io::Mask::IOM_WEDGTEXCOORD) { idtf.write(0,""); idtf.write(0,"MODIFIER \"SHADING\" {"); idtf.write(1,"MODIFIER_NAME \"VcgMesh01\""); idtf.write(1,"PARAMETERS {"); idtf.write(2,"SHADER_LIST_COUNT " + TextUtility::nmbToStr(m.textures.size())); idtf.write(2,"SHADING_GROUP {"); for(unsigned int ii = 0; ii < m.textures.size();++ii) { idtf.write(3,"SHADER_LIST " + TextUtility::nmbToStr(ii) + "{"); idtf.write(4,"SHADER_COUNT 1"); idtf.write(4,"SHADER_NAME_LIST {"); idtf.write(5,"SHADER 0 NAME: \"ModelShader" + TextUtility::nmbToStr(ii) + "\""); idtf.write(4,"}"); idtf.write(3,"}"); } idtf.write(2,"}"); idtf.write(1,"}"); idtf.write(0,"}"); } return E_NOERROR; } static int GetExportMaskCapability() { int capability = 0; //vert capability |= vcg::tri::io::Mask::IOM_VERTNORMAL; capability |= vcg::tri::io::Mask::IOM_VERTCOLOR; ////wedg capability |= vcg::tri::io::Mask::IOM_WEDGTEXCOORD; capability |= vcg::tri::io::Mask::IOM_WEDGNORMAL; return capability; } }; } } } #endifqutemol/vcg/wrap/io_trimesh/how_to_write_an_io_filter.txt0000444000175000017500000000363110527031403022476 0ustar mbamba---- How to write an IMPORT filter ---- For writing an import filter for a XXX 3D mesh file type you must: create a class templated on the mesh type and named: vcg::tri::io::ImporterXXX The class must have at least the following methods static int Open(MESH_TYPE &mesh, const char *filename, CallBackPos *cb=0) static int Open(MESH_TYPE &mesh, const char *filename, int & loadmask, CallBackPos *cb =0) static const char *ErrorMsg(int error) where loadmask is an writeonly bitmask that, after the successful loading, will contain what kind of data have been found inside the loaded file (per vert color, tex coords etc). Please note that you can NOT use loadmask to selectively loading attribute from files. Note also that the returned mask should always match with the capability mask of your mesh, so if your mesh has no texture coords, that bit will be always zero even if the original file has texture coords. To know the original content of a given file use the LoadMask function. The last function is used to translate the numerical error code in a more meaningful message. The callback function should be used to back communicate the loading status in a 1..100 range. It should be called approximatively no more than some hundreds of time, so do not call it for every loaded face. Typical callback line in a j-based loop during vertex loading: if(cb && (j%1000)==0) cb(j*50/vertex_number,"Vertex Loading"); ---- How to write an EXPORT filter ---- create a class templated on the mesh type and named: vcg::tri::io::ExporterDOH The class must have at least the following methods static int Save(MESH_TYPE &mesh, const char *filename, CallBackPos *cb=0) static int Save(MESH_TYPE &mesh, const char *filename, int & savemask, CallBackPos *cb =0) static const char *ErrorMsg(int error) static int GetExportMaskCapability() function return 0 in case of success and a code in any other case... qutemol/vcg/wrap/io_trimesh/import_ply.h0000444000175000017500000010731711001133705017063 0ustar mbamba/**************************************************************************** * VCGLib o o * * Visual and Computer Graphics Library o o * * _ O _ * * Copyright(C) 2004 \/)\/ * * Visual Computing Lab /\/| * * ISTI - Italian National Research Council | * * \ * * All rights reserved. * * * * 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. * * * * 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 (http://www.gnu.org/licenses/gpl.txt) * * for more details. * * * ****************************************************************************/ /**************************************************************************** History $Log: import_ply.h,v $ Revision 1.40 2008/04/15 14:12:21 cignoni added yet another type of face indexes (now 8 different ways!) Revision 1.39 2008/03/22 10:24:44 cignoni added yet another combination of unsigned/signed elements in faces specification to comply to mathematica ply's Revision 1.38 2007/11/19 16:31:55 ponchio loadmask in Open is now written. Revision 1.37 2007/10/19 22:13:37 cignoni added support for per-vertex normal for reading ply point clouds Revision 1.36 2007/07/02 12:33:34 cignoni wedge colors now are loaded into face color if they are available. Revision 1.35 2007/03/12 16:40:17 tarini Texture coord name change! "TCoord" and "Texture" are BAD. "TexCoord" is GOOD. Revision 1.34 2007/03/03 02:28:59 cignoni Removed initialization of a single face in the main parsing loop. Single face cannot exist anymore with OCF. Moved into the tristrip parsing section. Revision 1.33 2007/02/14 15:30:13 ganovelli added treatment of HasPerVertexFlags absent Revision 1.32 2007/02/02 00:29:33 tarini added a few typecasts to QualityTypefor vertices and faces (avoids warinings when short int or int is used for Quality). Revision 1.31 2006/12/18 09:46:39 callieri camera+shot revamp: changed field names to something with more sense, cleaning of various functions, correction of minor bugs/incongruences, removal of the infamous reference in shot. Revision 1.30 2006/11/27 10:36:13 cignoni Removed flags initialization. no more necessary Revision 1.29 2006/10/14 00:18:42 cignoni Allowed the correct loading of meshes with 0 faces Revision 1.28 2006/05/16 15:01:30 cignoni Wedge colors are loaded into facecolor only if specified in the incoming pi.mask Revision 1.27 2006/05/03 21:21:21 cignoni Corrected bug: mismatch in the index of confidence vertex property (8 instead of 11) Changed HasPerFaceColor to the new syntax (HasPerFaceColor(m) instead of FaceType::HasFaceColor() ) Revision 1.26 2006/02/03 09:46:24 corsini Remove signed/unsigned warning Revision 1.25 2006/01/11 10:37:12 cignoni Removed warning for unused vars Revision 1.24 2006/01/10 13:20:42 cignoni Changed ply::PlyMask to io::Mask Revision 1.23 2006/01/04 16:17:03 cignoni Corrected use of mask and callback in function Open(m,filename,mask,callback); Revision 1.22 2005/12/30 22:30:43 cignoni Added support for per vertex color stored as 'diffuse_xxx' property Revision 1.21 2005/12/02 10:04:18 cignoni forgotten a couple of std:: Revision 1.20 2005/12/02 00:01:30 cignoni Added loading of texturenames (normalmap still to do) Revision 1.19 2005/11/25 10:23:27 cignoni Added safe zero initialization of index of wedge texture Revision 1.18 2005/11/23 16:59:55 callieri corrected protected access methods (camera, similarity) of shot Revision 1.17 2005/11/12 18:13:30 cignoni Added support for non triangular faces (simple fan triangulation) and removed flags intiailization. Revision 1.16 2005/10/14 15:09:56 cignoni Added LoadMask without plyinfo and some comment on the mask usage Revision 1.15 2005/06/10 15:05:00 cignoni Made inline PlyType specializations Revision 1.14 2005/04/14 15:09:38 ponchio New gcc 3.3.3 (with bugs and features) now compiles. Revision 1.13 2005/03/18 00:14:39 cignoni removed small gcc compiling issues Revision 1.12 2005/02/08 17:28:22 tarini changed 120 "const static" to "static const", and added missing "format" fields to all PropDescriptor literals, to keep Mingw compiler happy Revision 1.11 2005/01/03 10:35:47 cignoni Improved the compatibility for ply format for faces having the list size (e.g. number of vertexes of a face) as a char instead of a uchar. Added a couple of new face descriptors, corrected a bug in error reporting function (and restructured) and translated a few comments. Thanks to Patrick Min for the careful bug reporting Revision 1.10 2004/10/07 14:51:10 ganovelli added setidentity della camera Revision 1.9 2004/10/07 14:19:06 ganovelli shot/camera io added Revision 1.8 2004/06/23 15:36:43 cignoni Restructured management of error, now the standard open for any mesh type return the error code, the default success value is zero Any import class has a method ErrorMsg that give a verbal description of an error code. Revision 1.7 2004/06/11 17:09:41 ganovelli inclusion of vector..minorchanges Revision 1.6 2004/05/28 14:11:13 ganovelli changes to comply io_mask moving in vcg::ply namesp Revision 1.5 2004/05/12 10:19:30 ganovelli new line added at the end of file Revision 1.4 2004/05/04 02:36:07 ganovelli #ifndef __VCGLIB_IMPORTERPLY added Revision 1.3 2004/04/03 13:30:01 cignoni missing include allocate.h Revision 1.2 2004/03/09 21:26:47 cignoni cr lf mismatch Revision 1.1 2004/03/03 15:00:51 cignoni Initial commit ****************************************************************************/ #ifndef __VCGLIB_IMPORTERPLY #define __VCGLIB_IMPORTERPLY #include #include #include #include #include #include #include namespace vcg { namespace tri { namespace io { template int PlyType () { return 0;} // 10/6/05 Cignoni this specialization must be inlined becouse otherwise if we include this // .h in two different cpp we should get a double definition error during linking template <> inline int PlyType () { return ply::T_FLOAT; } template <> inline int PlyType () { return ply::T_DOUBLE; } template <> inline int PlyType () { return ply::T_INT; } template <> inline int PlyType () { return ply::T_SHORT; } template <> inline int PlyType () { return ply::T_UCHAR; } /** This class encapsulate a filter for opening ply meshes. The ply file format is quite extensible... */ template class ImporterPLY { public: typedef ::vcg::ply::PropDescriptor PropDescriptor ; typedef typename OpenMeshType::VertexPointer VertexPointer; typedef typename OpenMeshType::ScalarType ScalarType; typedef typename OpenMeshType::VertexType VertexType; typedef typename OpenMeshType::FaceType FaceType; typedef typename OpenMeshType::VertexIterator VertexIterator; typedef typename OpenMeshType::FaceIterator FaceIterator; //template int PlyType () { assert(0); return 0;} #define MAX_USER_DATA 256 // Struttura ausiliaria per la lettura del file ply struct LoadPly_FaceAux { unsigned char size; int v[512]; int flags; float q; float texcoord[32]; unsigned char ntexcoord; int texcoordind; float colors[32]; unsigned char ncolors; unsigned char r; unsigned char g; unsigned char b; unsigned char data[MAX_USER_DATA]; }; struct LoadPly_TristripAux { int size; int *v; unsigned char data[MAX_USER_DATA]; }; // Struttura ausiliaria per la lettura del file ply template struct LoadPly_VertAux { S p[3]; S n[3]; int flags; float q; unsigned char r; unsigned char g; unsigned char b; unsigned char data[MAX_USER_DATA]; }; // Struttura ausiliaria caricamento camera struct LoadPly_Camera { float view_px; float view_py; float view_pz; float x_axisx; float x_axisy; float x_axisz; float y_axisx; float y_axisy; float y_axisz; float z_axisx; float z_axisy; float z_axisz; float focal; float scalex; float scaley; float centerx; float centery; int viewportx; int viewporty; float k1; float k2; float k3; float k4; }; static const PropDescriptor &VertDesc(int i) { static const PropDescriptor pv[15]={ /*00*/ {"vertex", "x", ply::T_FLOAT, PlyType(),offsetof(LoadPly_VertAux,p),0,0,0,0,0 ,0}, /*01*/ {"vertex", "y", ply::T_FLOAT, PlyType(),offsetof(LoadPly_VertAux,p) + sizeof(ScalarType),0,0,0,0,0 ,0}, /*02*/ {"vertex", "z", ply::T_FLOAT, PlyType(),offsetof(LoadPly_VertAux,p) + 2*sizeof(ScalarType),0,0,0,0,0 ,0}, /*03*/ {"vertex", "flags", ply::T_INT, ply::T_INT, offsetof(LoadPly_VertAux,flags),0,0,0,0,0 ,0}, /*04*/ {"vertex", "quality", ply::T_FLOAT, ply::T_FLOAT, offsetof(LoadPly_VertAux,q),0,0,0,0,0 ,0}, /*05*/ {"vertex", "red" , ply::T_UCHAR, ply::T_UCHAR, offsetof(LoadPly_VertAux,r),0,0,0,0,0 ,0}, /*06*/ {"vertex", "green", ply::T_UCHAR, ply::T_UCHAR, offsetof(LoadPly_VertAux,g),0,0,0,0,0 ,0}, /*07*/ {"vertex", "blue" , ply::T_UCHAR, ply::T_UCHAR, offsetof(LoadPly_VertAux,b),0,0,0,0,0 ,0}, /*08*/ {"vertex", "diffuse_red" , ply::T_UCHAR, ply::T_UCHAR, offsetof(LoadPly_VertAux,r),0,0,0,0,0 ,0}, /*09*/ {"vertex", "diffuse_green", ply::T_UCHAR, ply::T_UCHAR, offsetof(LoadPly_VertAux,g),0,0,0,0,0 ,0}, /*10*/ {"vertex", "diffuse_blue" , ply::T_UCHAR, ply::T_UCHAR, offsetof(LoadPly_VertAux,b),0,0,0,0,0 ,0}, /*11*/ {"vertex", "confidence",ply::T_FLOAT, ply::T_FLOAT, offsetof(LoadPly_VertAux,q),0,0,0,0,0 ,0}, /*12*/ {"vertex", "nx", ply::T_FLOAT, PlyType(),offsetof(LoadPly_VertAux,n),0,0,0,0,0 ,0}, /*13*/ {"vertex", "ny", ply::T_FLOAT, PlyType(),offsetof(LoadPly_VertAux,n) + sizeof(ScalarType),0,0,0,0,0 ,0}, /*14*/ {"vertex", "nz", ply::T_FLOAT, PlyType(),offsetof(LoadPly_VertAux,n) + 2*sizeof(ScalarType),0,0,0,0,0 ,0}, }; return pv[i]; } static const PropDescriptor &FaceDesc(int i) { static const PropDescriptor qf[16]= { /* 0 */ {"face", "vertex_indices", ply::T_INT, ply::T_INT, offsetof(LoadPly_FaceAux,v), 1,0,ply::T_UCHAR,ply::T_UCHAR,offsetof(LoadPly_FaceAux,size) ,0}, /* 1 */ {"face", "flags", ply::T_INT, ply::T_INT, offsetof(LoadPly_FaceAux,flags), 0,0,0,0,0 ,0}, /* 2 */ {"face", "quality", ply::T_FLOAT, ply::T_FLOAT, offsetof(LoadPly_FaceAux,q), 0,0,0,0,0 ,0}, /* 3 */ {"face", "texcoord", ply::T_FLOAT, ply::T_FLOAT, offsetof(LoadPly_FaceAux,texcoord), 1,0,ply::T_UCHAR,ply::T_UCHAR,offsetof(LoadPly_FaceAux,ntexcoord) ,0}, /* 4 */ {"face", "color", ply::T_FLOAT, ply::T_FLOAT, offsetof(LoadPly_FaceAux,colors), 1,0,ply::T_UCHAR,ply::T_UCHAR,offsetof(LoadPly_FaceAux,ncolors) ,0}, /* 5 */ {"face", "texnumber", ply::T_INT, ply::T_INT, offsetof(LoadPly_FaceAux,texcoordind), 0,0,0,0,0 ,0}, /* 6 */ {"face", "red" , ply::T_UCHAR, ply::T_UCHAR, offsetof(LoadPly_FaceAux,r), 0,0,0,0,0 ,0}, /* 7 */ {"face", "green", ply::T_UCHAR, ply::T_UCHAR, offsetof(LoadPly_FaceAux,g), 0,0,0,0,0 ,0}, /* 8 */ {"face", "blue" , ply::T_UCHAR, ply::T_UCHAR, offsetof(LoadPly_FaceAux,b), 0,0,0,0,0 ,0}, /* 9 */ {"face", "vertex_index", ply::T_INT, ply::T_INT, offsetof(LoadPly_FaceAux,v), 1,0,ply::T_UCHAR,ply::T_CHAR,offsetof(LoadPly_FaceAux,size) ,0}, /* 10 */ {"face", "vertex_index", ply::T_INT, ply::T_INT, offsetof(LoadPly_FaceAux,v), 1,0,ply::T_CHAR, ply::T_CHAR,offsetof(LoadPly_FaceAux,size) ,0}, /* 11 */ {"face", "vertex_index", ply::T_INT, ply::T_INT, offsetof(LoadPly_FaceAux,v), 1,0,ply::T_INT, ply::T_CHAR,offsetof(LoadPly_FaceAux,size) ,0}, /* 12 */ {"face", "vertex_indices", ply::T_INT, ply::T_INT, offsetof(LoadPly_FaceAux,v), 1,0,ply::T_CHAR, ply::T_CHAR,offsetof(LoadPly_FaceAux,size) ,0}, /* 13 */ {"face", "vertex_indices", ply::T_UINT, ply::T_INT, offsetof(LoadPly_FaceAux,v), 1,0,ply::T_UCHAR,ply::T_CHAR,offsetof(LoadPly_FaceAux,size) ,0}, /* 14 */ {"face", "vertex_indices", ply::T_UINT, ply::T_INT, offsetof(LoadPly_FaceAux,v), 1,0,ply::T_INT, ply::T_CHAR,offsetof(LoadPly_FaceAux,size) ,0}, /* 15 */ {"face", "vertex_indices", ply::T_INT, ply::T_INT, offsetof(LoadPly_FaceAux,v), 1,0,ply::T_INT, ply::T_CHAR,offsetof(LoadPly_FaceAux,size) ,0}, }; return qf[i]; } static const PropDescriptor &TristripDesc(int i) { static const PropDescriptor qf[1]= { {"tristrips","vertex_indices", ply::T_INT, ply::T_INT, offsetof(LoadPly_TristripAux,v), 1,1,ply::T_INT,ply::T_INT,offsetof(LoadPly_TristripAux,size) ,0}, }; return qf[i]; } static const PropDescriptor &CameraDesc(int i) { static const PropDescriptor cad[23] = { {"camera","view_px",ply::T_FLOAT,ply::T_FLOAT,offsetof(LoadPly_Camera,view_px),0,0,0,0,0 ,0}, {"camera","view_py",ply::T_FLOAT,ply::T_FLOAT,offsetof(LoadPly_Camera,view_py),0,0,0,0,0 ,0}, {"camera","view_pz",ply::T_FLOAT,ply::T_FLOAT,offsetof(LoadPly_Camera,view_pz),0,0,0,0,0 ,0}, {"camera","x_axisx",ply::T_FLOAT,ply::T_FLOAT,offsetof(LoadPly_Camera,x_axisx),0,0,0,0,0 ,0}, {"camera","x_axisy",ply::T_FLOAT,ply::T_FLOAT,offsetof(LoadPly_Camera,x_axisy),0,0,0,0,0 ,0}, {"camera","x_axisz",ply::T_FLOAT,ply::T_FLOAT,offsetof(LoadPly_Camera,x_axisz),0,0,0,0,0 ,0}, {"camera","y_axisx",ply::T_FLOAT,ply::T_FLOAT,offsetof(LoadPly_Camera,y_axisx),0,0,0,0,0 ,0}, {"camera","y_axisy",ply::T_FLOAT,ply::T_FLOAT,offsetof(LoadPly_Camera,y_axisy),0,0,0,0,0 ,0}, {"camera","y_axisz",ply::T_FLOAT,ply::T_FLOAT,offsetof(LoadPly_Camera,y_axisz),0,0,0,0,0 ,0}, {"camera","z_axisx",ply::T_FLOAT,ply::T_FLOAT,offsetof(LoadPly_Camera,z_axisx),0,0,0,0,0 ,0}, {"camera","z_axisy",ply::T_FLOAT,ply::T_FLOAT,offsetof(LoadPly_Camera,z_axisy),0,0,0,0,0 ,0}, {"camera","z_axisz",ply::T_FLOAT,ply::T_FLOAT,offsetof(LoadPly_Camera,z_axisz),0,0,0,0,0 ,0}, {"camera","focal" ,ply::T_FLOAT,ply::T_FLOAT,offsetof(LoadPly_Camera,focal ),0,0,0,0,0 ,0}, {"camera","scalex" ,ply::T_FLOAT,ply::T_FLOAT,offsetof(LoadPly_Camera,scalex ),0,0,0,0,0 ,0}, {"camera","scaley" ,ply::T_FLOAT,ply::T_FLOAT,offsetof(LoadPly_Camera,scaley ),0,0,0,0,0 ,0}, {"camera","centerx",ply::T_FLOAT,ply::T_FLOAT,offsetof(LoadPly_Camera,centerx),0,0,0,0,0 ,0}, {"camera","centery",ply::T_FLOAT,ply::T_FLOAT,offsetof(LoadPly_Camera,centery),0,0,0,0,0 ,0}, {"camera","viewportx",ply::T_INT,ply::T_INT ,offsetof(LoadPly_Camera,viewportx),0,0,0,0,0 ,0}, {"camera","viewporty",ply::T_INT,ply::T_INT ,offsetof(LoadPly_Camera,viewporty),0,0,0,0,0 ,0}, {"camera","k1" ,ply::T_FLOAT,ply::T_FLOAT,offsetof(LoadPly_Camera,k1 ),0,0,0,0,0 ,0}, {"camera","k2" ,ply::T_FLOAT,ply::T_FLOAT,offsetof(LoadPly_Camera,k2 ),0,0,0,0,0 ,0}, {"camera","k3" ,ply::T_FLOAT,ply::T_FLOAT,offsetof(LoadPly_Camera,k3 ),0,0,0,0,0 ,0}, {"camera","k4" ,ply::T_FLOAT,ply::T_FLOAT,offsetof(LoadPly_Camera,k4 ),0,0,0,0,0 ,0} }; return cad[i]; } /// Standard call for knowing the meaning of an error code static const char *ErrorMsg(int error) { static std::vector ply_error_msg; if(ply_error_msg.empty()) { ply_error_msg.resize(PlyInfo::E_MAXPLYINFOERRORS ); ply_error_msg[ply::E_NOERROR ]="No errors"; ply_error_msg[ply::E_CANTOPEN ]="Can't open file"; ply_error_msg[ply::E_NOTHEADER ]="Header not found"; ply_error_msg[ply::E_UNESPECTEDEOF ]="Eof in header"; ply_error_msg[ply::E_NOFORMAT ]="Format not found"; ply_error_msg[ply::E_SYNTAX ]="Syntax error on header"; ply_error_msg[ply::E_PROPOUTOFELEMENT]="Property without element"; ply_error_msg[ply::E_BADTYPENAME ]="Bad type name"; ply_error_msg[ply::E_ELEMNOTFOUND ]="Element not found"; ply_error_msg[ply::E_PROPNOTFOUND ]="Property not found"; ply_error_msg[ply::E_BADTYPE ]="Bad type on addtoread"; ply_error_msg[ply::E_INCOMPATIBLETYPE]="Incompatible type"; ply_error_msg[ply::E_BADCAST ]="Bad cast"; ply_error_msg[PlyInfo::E_NO_VERTEX ]="No vertex field found"; ply_error_msg[PlyInfo::E_NO_FACE ]="No face field found"; ply_error_msg[PlyInfo::E_SHORTFILE ]="Unespected eof"; ply_error_msg[PlyInfo::E_NO_3VERTINFACE ]="Face with more than 3 vertices"; ply_error_msg[PlyInfo::E_BAD_VERT_INDEX ]="Bad vertex index in face"; ply_error_msg[PlyInfo::E_NO_6TCOORD ]="Face with no 6 texture coordinates"; ply_error_msg[PlyInfo::E_DIFFER_COLORS ]="Number of color differ from vertices"; } if(error>PlyInfo::E_MAXPLYINFOERRORS || error<0) return "Unknown error"; else return ply_error_msg[error].c_str(); }; /// Standard call for reading a mesh static int Open( OpenMeshType &m, const char * filename, CallBackPos *cb=0) { PlyInfo pi; pi.cb=cb; return Open(m, filename, pi); } /// Read a mesh and store in loadmask the loaded field /// Note that loadmask is not read! just modified. You cannot specify what fields /// have to be read. ALL the data for which your mesh HasSomething and are present /// in the file are read in. static int Open( OpenMeshType &m, const char * filename, int & loadmask, CallBackPos *cb =0) { PlyInfo pi; pi.cb=cb; int r = Open(m, filename,pi); loadmask=pi.mask; return r; } /// read a mesh with all the possible option specified in the PlyInfo obj. static int Open( OpenMeshType &m, const char * filename, PlyInfo &pi ) { assert(filename!=0); std::vector index; LoadPly_FaceAux fa; LoadPly_TristripAux tsa; LoadPly_VertAux va; pi.mask = 0; bool multit = false; // true if texture has a per face int spec the texture index va.flags = 42; pi.status = ::vcg::ply::E_NOERROR; // init defaults VertexType tv; //tv.ClearFlags(); if( VertexType::HasQuality() ) tv.Q()=(typename OpenMeshType::VertexType::QualityType)1.0; if( VertexType::HasColor() ) tv.C()=Color4b(Color4b::White); // Descrittori delle strutture //bool isvflags = false; // Il file contiene i flags // The main descriptor of the ply file vcg::ply::PlyFile pf; // Open the file and parse the header if( pf.Open(filename,vcg::ply::PlyFile::MODE_READ)==-1 ) { pi.status = pf.GetError(); return pi.status; } pi.header = pf.GetHeader(); // Descrittori della camera { // Check that all the camera properties are present. bool found = true; for(int i=0;i<23;++i) { if( pf.AddToRead(CameraDesc(i))==-1 ) { found = false; break; } } if(found) pi.mask |= Mask::IOM_CAMERA; } // Descrittori dati standard (vertex coord e faces) if( pf.AddToRead(VertDesc(0))==-1 ) { pi.status = PlyInfo::E_NO_VERTEX; return pi.status; } if( pf.AddToRead(VertDesc(1))==-1 ) { pi.status = PlyInfo::E_NO_VERTEX; return pi.status; } if( pf.AddToRead(VertDesc(2))==-1 ) { pi.status = PlyInfo::E_NO_VERTEX; return pi.status; } if( pf.AddToRead(FaceDesc(0))==-1 ) // Se fallisce si prova anche la sintassi di rapidform con index al posto di indices { int ii; const int FaceVariantNum = 7; for(ii=0;ii< FaceVariantNum;++ii) if( pf.AddToRead(FaceDesc(9+ii))!=-1 ) break; if(ii==FaceVariantNum) if(pf.AddToRead(TristripDesc(0))==-1) // Se fallisce tutto si prova a vedere se ci sono tristrip alla levoy. { pi.status = PlyInfo::E_NO_FACE; return pi.status; } } // Descrittori facoltativi dei flags if(VertexType::HasFlags() && pf.AddToRead(VertDesc(3))!=-1 ) pi.mask |= Mask::IOM_VERTFLAGS; if( VertexType::HasNormal() ) { if( pf.AddToRead(VertDesc(12))!=-1 && pf.AddToRead(VertDesc(13))!=-1 && pf.AddToRead(VertDesc(14))!=-1 ) pi.mask |= Mask::IOM_VERTNORMAL; } if( VertexType::HasQuality() ) { if( pf.AddToRead(VertDesc(4))!=-1 || pf.AddToRead(VertDesc(11))!=-1 ) pi.mask |= Mask::IOM_VERTQUALITY; } if( VertexType::HasColor() ) { if( pf.AddToRead(VertDesc(5))!=-1 ) { pf.AddToRead(VertDesc(6)); pf.AddToRead(VertDesc(7)); pi.mask |= Mask::IOM_VERTCOLOR; } if( pf.AddToRead(VertDesc(8))!=-1 ) { pf.AddToRead(VertDesc(9)); pf.AddToRead(VertDesc(10)); pi.mask |= Mask::IOM_VERTCOLOR; } } // se ci sono i flag per vertice ci devono essere anche i flag per faccia if( pf.AddToRead(FaceDesc(1))!=-1 ) pi.mask |= Mask::IOM_FACEFLAGS; if( FaceType::HasFaceQuality()) { if( pf.AddToRead(FaceDesc(2))!=-1 ) pi.mask |= Mask::IOM_FACEQUALITY; } if( FaceType::HasFaceColor() ) { if( pf.AddToRead(FaceDesc(6))!=-1 ) { pf.AddToRead(FaceDesc(7)); pf.AddToRead(FaceDesc(8)); pi.mask |= Mask::IOM_FACECOLOR; } } if( FaceType::HasWedgeTexCoord() ) { if( pf.AddToRead(FaceDesc(3))!=-1 ) { if(pf.AddToRead(FaceDesc(5))==0) { multit=true; // try to read also the multi texture indicies pi.mask |= Mask::IOM_WEDGTEXMULTI; } pi.mask |= Mask::IOM_WEDGTEXCOORD; } } if( FaceType::HasWedgeColor() || FaceType::HasFaceColor() || VertexType::HasColor()) { if( pf.AddToRead(FaceDesc(4))!=-1 ) { pi.mask |= Mask::IOM_WEDGCOLOR; } } // Descrittori definiti dall'utente, std::vector VPV(pi.vdn); // property descriptor relative al tipo LoadPly_VertexAux std::vector FPV(pi.fdn); // property descriptor relative al tipo LoadPly_FaceAux if(pi.vdn>0){ // Compute the total size needed to load additional per vertex data. size_t totsz=0; for(int i=0;i,data)+totsz; totsz+=pi.VertexData[i].memtypesize(); if( pf.AddToRead(VPV[i])==-1 ) { pi.status = pf.GetError(); return pi.status; } } if(totsz > MAX_USER_DATA) { pi.status = vcg::ply::E_BADTYPE; return pi.status; } } if(pi.fdn>0){ size_t totsz=0; for(int i=0;i MAX_USER_DATA) { pi.status = vcg::ply::E_BADTYPE; return pi.status; } } /**************************************************************/ /* Main Reading Loop */ /**************************************************************/ m.Clear(); for(int i=0;i::AddVertices(m,n); for(j=0;j0) )/************************************************************/ { int j; FaceIterator fi=Allocator::AddFaces(m,n); pf.SetCurElement(i); for(j=0;j=m.vn ) { pi.status = PlyInfo::E_BAD_VERT_INDEX; return pi.status; } (*fi).V(k) = index[ fa.v[k] ]; } for(k=0;k3) { int curpos=int(fi-m.face.begin()); Allocator::AddFaces(m,fa.size-3); fi=m.face.begin()+curpos; } for(int qq=0;qq=m.vn ) { pi.status = PlyInfo::E_BAD_VERT_INDEX; return pi.status; } (*fi).V(k) = index[ fa.v[1+qq+k] ]; } for(k=0;k=numvert_tmp ) { pi.status = PlyInfo::E_BAD_VERT_INDEX; return pi.status; } if(tsa.v[k+2]==-1) { k+=2; if(k%2) remainder=0; else remainder=1; continue; } tf.V(0) = index[ tsa.v[k+0] ]; tf.V(1) = index[ tsa.v[k+1] ]; tf.V(2) = index[ tsa.v[k+2] ]; if((k+remainder)%2) math::Swap (tf.V(0), tf.V(1) ); m.face.push_back( tf ); } } } else { // Skippaggio elementi non gestiti int n = pf.ElemNumber(i); pf.SetCurElement(i); for(int j=0;j(bufstr.length()); for(i=0;i32 && bufstr[i]<125 ) bufclean.push_back(bufstr[i]); char buf2[255]; ply::interpret_texture_name( bufclean.c_str(),filename,buf2 ); m.textures.push_back( std::string(buf2) ); } /*if( !strncmp(c,NFILE,strlen(NFILE)) ) { strcpy(buf,c+strlen(NFILE)+1); n = strlen(buf); for(i=j=0;i32 && buf[i]<125 ) buf[j++] = buf[i]; buf[j] = 0; char buf2[255]; __interpret_texture_name( buf,filename,buf2 ); m.normalmaps.push_back( string(buf2) ); }*/ } // vn and fn should be correct but if someone wrongly saved some deleted elements they can be wrong. m.vn = 0; VertexIterator vi; for(vi=m.vert.begin();vi!=m.vert.end();++vi) if( ! (*vi).IsD() ) ++m.vn; m.fn = 0; FaceIterator fi; for(fi=m.face.begin();fi!=m.face.end();++fi) if( ! (*fi).IsD() ) ++m.fn; return 0; } // Caricamento camera da un ply int LoadCamera(const char * filename) { vcg::ply::PlyFile pf; if( pf.Open(filename,vcg::ply::PlyFile::MODE_READ)==-1 ) { this->pi.status = pf.GetError(); return this->pi.status; } bool found = true; int i; for(i=0;i<23;++i) { if( pf.AddToRead(CameraDesc(i))==-1 ) { found = false; break; } } if(!found) return this->pi.status; for(i=0;ipi.status = PlyInfo::E_SHORTFILE; return this->pi.status; } this->camera.valid = true; this->camera.view_p[0] = ca.view_px; this->camera.view_p[1] = ca.view_py; this->camera.view_p[2] = ca.view_pz; this->camera.x_axis[0] = ca.x_axisx; this->camera.x_axis[1] = ca.x_axisy; this->camera.x_axis[2] = ca.x_axisz; this->camera.y_axis[0] = ca.y_axisx; this->camera.y_axis[1] = ca.y_axisy; this->camera.y_axis[2] = ca.y_axisz; this->camera.z_axis[0] = ca.z_axisx; this->camera.z_axis[1] = ca.z_axisy; this->camera.z_axis[2] = ca.z_axisz; this->camera.f = ca.focal; this->camera.s[0] = ca.scalex; this->camera.s[1] = ca.scaley; this->camera.c[0] = ca.centerx; this->camera.c[1] = ca.centery; this->camera.viewport[0] = ca.viewportx; this->camera.viewport[1] = ca.viewporty; this->camera.k[0] = ca.k1; this->camera.k[1] = ca.k2; this->camera.k[2] = ca.k3; this->camera.k[3] = ca.k4; } break; } } return 0; } static bool LoadMask(const char * filename, int &mask) { PlyInfo pi; return LoadMask(filename, mask,pi); } static bool LoadMask(const char * filename, int &mask, PlyInfo &pi) { mask=0; vcg::ply::PlyFile pf; if( pf.Open(filename,vcg::ply::PlyFile::MODE_READ)==-1 ) { pi.status = pf.GetError(); return false; } if( pf.AddToRead(VertDesc(0))!=-1 && pf.AddToRead(VertDesc(1))!=-1 && pf.AddToRead(VertDesc(2))!=-1 ) mask |= Mask::IOM_VERTCOORD; if( pf.AddToRead(VertDesc(12))!=-1 && pf.AddToRead(VertDesc(13))!=-1 && pf.AddToRead(VertDesc(14))!=-1 ) mask |= Mask::IOM_VERTNORMAL; if( pf.AddToRead(VertDesc(3))!=-1 ) mask |= Mask::IOM_VERTFLAGS; if( pf.AddToRead(VertDesc(4))!=-1 ) mask |= Mask::IOM_VERTQUALITY; if( pf.AddToRead(VertDesc(11))!=-1 ) mask |= Mask::IOM_VERTQUALITY; if( ( pf.AddToRead(VertDesc(5))!=-1 ) && ( pf.AddToRead(VertDesc(6))!=-1 ) && ( pf.AddToRead(VertDesc(7))!=-1 ) ) mask |= Mask::IOM_VERTCOLOR; if( pf.AddToRead(FaceDesc(0))!=-1 ) mask |= Mask::IOM_FACEINDEX; if( pf.AddToRead(FaceDesc(1))!=-1 ) mask |= Mask::IOM_FACEFLAGS; if( pf.AddToRead(FaceDesc(2))!=-1 ) mask |= Mask::IOM_FACEQUALITY; if( pf.AddToRead(FaceDesc(3))!=-1 ) mask |= Mask::IOM_WEDGTEXCOORD; if( pf.AddToRead(FaceDesc(5))!=-1 ) mask |= Mask::IOM_WEDGTEXMULTI; if( pf.AddToRead(FaceDesc(4))!=-1 ) mask |= Mask::IOM_WEDGCOLOR; if( ( pf.AddToRead(FaceDesc(6))!=-1 ) && ( pf.AddToRead(FaceDesc(7))!=-1 ) && ( pf.AddToRead(FaceDesc(8))!=-1 ) ) mask |= Mask::IOM_FACECOLOR; return true; } }; // end class } // end namespace tri } // end namespace io } // end namespace vcg #endif qutemol/vcg/wrap/opensg/0000755000175000017500000000000011633404241013645 5ustar mbambaqutemol/vcg/wrap/opensg/vertex_component.h0000444000175000017500000002534610622035256017430 0ustar mbamba #ifndef __VCG_OSG_VERTEX_PLUS_COMPONENT #define __VCG_OSG_VERTEX_PLUS_COMPONENT #include #include #include #include #include namespace vcg { namespace vert { /// Some Naming Rules : All the Components that can be added to a vertex should be defined in the namespace vert: /// ------------------------- OPENSGINFO ----------------------------------------- template< class T > class EmptyOSGInfo : public T { public : OSG::GeometryPtr Geo() { assert(0); return NULL; } }; template< class T > class OSGInfo : public T { public : OSG::GeometryPtr & Geo() { return _geop; } int & Index() { return _vertexi; } private : OSG::GeometryPtr _geop; /// Maybe we can use pointers to buffers directly but now we really don't now if these pointers change in time ... !!! int _vertexi; /// OSG vertex index }; /// ------------------------- COORD ----------------------------------------- /// Core for the coordinate component templated with the coordinate type of the component template< class T > class OSGCoordCore { public : typedef T CoordType; typedef typename CoordType::ValueType ScalarType; OSGCoordCore( OSG::GeometryPtr p, int i ) { _geopointer = p; _vertexindex = i; } ~OSGCoordCore() { _vertexindex = -1; } CoordType & operator=( CoordType & p2 ) { /// Set coordinates OSG::GeoPositions3fPtr pos = OSG::GeoPositions3fPtr::dcast( _geopointer->getPositions() ); OSG::beginEditCP( pos, OSG::GeoPositions3f::GeoPropDataFieldMask ); pos->setValue( p2, _vertexindex ); OSG::endEditCP( pos, OSG::GeoPositions3f::GeoPropDataFieldMask ); return p2; /// Warning : instead of returning the left side operand we return the right one !!! } ScalarType X() { /// Get coordinates OSG::GeoPositions3fPtr pos = OSG::GeoPositions3fPtr::dcast( _geopointer->getPositions() ); OSG::beginEditCP( pos, OSG::GeoPositions3f::GeoPropDataFieldMask ); OSG::Pnt3f p; pos->getValue( p, _vertexindex ); OSG::endEditCP( pos, OSG::GeoPositions3f::GeoPropDataFieldMask ); return p.x(); } ScalarType Y() { /// Get coordinates OSG::GeoPositions3fPtr pos = OSG::GeoPositions3fPtr::dcast( _geopointer->getPositions() ); OSG::beginEditCP( pos, OSG::GeoPositions3f::GeoPropDataFieldMask ); OSG::Pnt3f p; pos->getValue( p, _vertexindex ); OSG::endEditCP( pos, OSG::GeoPositions3f::GeoPropDataFieldMask ); return p.y(); } ScalarType Z() { /// Get coordinates OSG::GeoPositions3fPtr pos = OSG::GeoPositions3fPtr::dcast( _geopointer->getPositions() ); OSG::beginEditCP( pos, OSG::GeoPositions3f::GeoPropDataFieldMask ); OSG::Pnt3f p; pos->getValue( p, _vertexindex ); OSG::endEditCP( pos, OSG::GeoPositions3f::GeoPropDataFieldMask ); return p.z(); } private : OSG::GeometryPtr _geopointer; int _vertexindex; }; template< class T > class EmptyOSGCoord : public T { public : typedef OSG::Pnt3f CoordType; typedef OSG::Real32 ScalarType; CoordType & P() { assert(0); return CoordType(); } const CoordType & P() const { assert(0); return CoordType(); } const CoordType & cP() const { assert(0); return CoordType(); } CoordType & UberP() { assert(0); return CoordType(); } static bool HasCoord() { return false; } static void Name( std::vector< std::string > & name ) { T::Name(name); } }; template< class A, class T > class OSGCoord : public T { public : typedef A CoordType; /// Must be a OSG::Pnt3 type as : OSG::Pnt3s, OSG:Pnt3f, OSG::Pnt3d etc... typedef typename CoordType::ValueType ScalarType; /// Can be a OSG basic type as : OSG::Int16, OSG::Real32, OSG::Real64 etc... typedef typename OSGCoordCore< CoordType > CoreType; OSGCoord() { _corep = NULL; } ~OSGCoord() { if( _corep != NULL ) delete _corep; } CoreType & P() { CoreType * tmpcorep = _corep; _corep = new CoreType( Geo(), Index() ); if( tmpcorep != NULL ) delete tmpcorep; return *_corep; } static bool HasCoord() { return true; } static void Name( std::vector< std::string > & name ) { name.push_back( std::string("OSGCoord") ); T::Name(name); } private : CoreType * _corep; }; class OSGCoordCore3f : public OSGCoordCore< OSG::Pnt3f > {}; template< class T > class OSGCoord3f : public OSGCoord< OSG::Pnt3f, T > { public : static void Name( std::vector< std::string > & name ) { name.push_back( std::string( "OSGCoord3f" ) ); T::Name(name); } }; /// -------------------------- NORMAL ---------------------------------------- template< class T > class OSGNormalCore { public : typedef T NormalType; typedef typename NormalType::ValueType ScalarType; OSGNormalCore( OSG::GeometryPtr p, int i ) { _geopointer = p; _vertexindex = i; } ~OSGNormalCore() { _vertexindex = -1; } NormalType & operator=( NormalType & n2 ) { /// Set coordinates OSG::GeoNormals3fPtr norm = OSG::GeoNormals3fPtr::dcast( _geopointer->getNormals() ); OSG::beginEditCP( norm, OSG::GeoNormals3f::GeoPropDataFieldMask ); norm->setValue( n2, _vertexindex ); OSG::endEditCP( norm, OSG::GeoNormals3f::GeoPropDataFieldMask ); return n2; /// Warning : instead of returning the left side operand we return the right one !!! } ScalarType X() { /// Get coordinates OSG::GeoNormals3fPtr norm = OSG::GeoNormals3fPtr::dcast( _geopointer->getNormals() ); OSG::beginEditCP( norm, OSG::GeoNormals3f::GeoPropDataFieldMask ); OSG::Vec3f n; norm->getValue( n, _vertexindex ); OSG::endEditCP( norm, OSG::GeoNormals3f::GeoPropDataFieldMask ); return n.x(); } ScalarType Y() { /// Get coordinates OSG::GeoNormals3fPtr norm = OSG::GeoNormals3fPtr::dcast( _geopointer->getNormals() ); OSG::beginEditCP( norm, OSG::GeoNormals3f::GeoPropDataFieldMask ); OSG::Vec3f n; norm->getValue( n, _vertexindex ); OSG::endEditCP( norm, OSG::GeoNormals3f::GeoPropDataFieldMask ); return n.y(); } ScalarType Z() { /// Get coordinates OSG::GeoNormals3fPtr norm = OSG::GeoNormals3fPtr::dcast( _geopointer->getNormals() ); OSG::beginEditCP( norm, OSG::GeoNormals3f::GeoPropDataFieldMask ); OSG::Vec3f n; norm->getValue( n, _vertexindex ); OSG::endEditCP( norm, OSG::GeoNormals3f::GeoPropDataFieldMask ); return n.z(); } private : OSG::GeometryPtr _geopointer; int _vertexindex; }; template< class T > class EmptyOSGNormal : public T { public : typedef OSG::Vec3f NormalType; typedef OSG::Real32 ScalarType; NormalType & N() { assert(0); return NormalType(); } const NormalType cN()const { assert(0); return NormalType(); } static bool HasNormal() { return false; } static bool HasNormalOcc() { return false; } static void Name( std::vector< std::string > & name ) { T::Name(name); } }; template< class A, class T > class OSGNormal : public T { public : typedef A NormalType; /// Must be a OSG::Vec3 type as : OSG::Vec3s, OSG:Vec3f, OSG::Vec3d etc... typedef typename NormalType::ValueType ScalarType; /// Can be a OSG basic type as : OSG::Int16, OSG::Real32, OSG::Real64 etc... typedef typename OSGNormalCore< NormalType > CoreType; OSGNormal() { _corep = NULL; } ~OSGNormal() { if( _corep == NULL ) delete _corep; } CoreType & N() { CoreType * tmpcorep = _corep; _corep = new CoreType( Geo(), Index() ); if( tmpcorep == NULL ) delete tmpcorep; return *_corep; } static bool HasNormal() { return true; } static void Name( std::vector< std::string > & name ) { name.push_back( std::string( "OSGNormal" ) );T::Name(name); } private : CoreType * _corep; }; class OSGNormalCore3f : public OSGNormalCore< OSG::Vec3f > {}; template< class T > class OSGNormal3f : public OSGNormal< OSG::Vec3f, T > { public : static void Name( std::vector< std::string > & name ) { name.push_back( std::string( "OSGNormal3f" ) ); T::Name(name); } }; /// -------------------------- COLOR ---------------------------------- template< class T > class OSGColorCore { public : typedef T ColorType; typedef typename ColorType::ValueType ScalarType; OSGColorCore( OSG::GeometryPtr p, int i ) { _geopointer = p; _vertexindex = i; } ~OSGColorCore() { _vertexindex = -1; } ColorType & operator=( ColorType & c2 ) { /// Set color OSG::GeoColors3fPtr colp = OSG::GeoColors3fPtr::dcast( _geopointer->getColors() ); OSG::beginEditCP( colp, OSG::GeoColors3f::GeoPropDataFieldMask ); colp->setValue( c2, _vertexindex ); OSG::endEditCP( colp, OSG::GeoColors3f::GeoPropDataFieldMask ); return c2; /// Warning : instead of returning the left side operand we return the right one !!! } ScalarType R() { /// Get coordinates OSG::GeoColors3fPtr colp = OSG::GeoColors3fPtr::dcast( _geopointer->getColors() ); OSG::beginEditCP( colp, OSG::GeoColors3f::GeoPropDataFieldMask ); OSG::Color3f c; colp->getValue( c, _vertexindex ); OSG::endEditCP( colp, OSG::GeoColors3f::GeoPropDataFieldMask ); return c.red(); } ScalarType G() { /// Get coordinates OSG::GeoColors3fPtr colp = OSG::GeoColors3fPtr::dcast( _geopointer->getColors() ); OSG::beginEditCP( colp, OSG::GeoColors3f::GeoPropDataFieldMask ); OSG::Color3f c; colp->getValue( c, _vertexindex ); OSG::endEditCP( colp, OSG::GeoColors3f::GeoPropDataFieldMask ); return c.green(); } ScalarType B() { /// Get coordinates OSG::GeoColors3fPtr colp = OSG::GeoColors3fPtr::dcast( _geopointer->getColors() ); OSG::beginEditCP( colp, OSG::GeoColors3f::GeoPropDataFieldMask ); OSG::Color3f c; colp->getValue( c, _vertexindex ); OSG::endEditCP( colp, OSG::GeoColors3f::GeoPropDataFieldMask ); return c.blue(); } private : OSG::GeometryPtr _geopointer; int _vertexindex; }; template< class T > class EmptyOSGColor : public T { public : typedef OSG::Color3f ColorType; typedef OSG::Real32 ScalarType; ColorType & C() { assert(0); return ColorType(); } static bool HasColor() { return false; } static void Name( std::vector< std::string > & name ) { T::Name(name); } }; template< class A, class T > class OSGColor : public T { public : typedef A ColorType; /// Must be a OSG::Color3 type as : OSG::Color3ub, OSG:Color3f etc... typedef typename ColorType::ValueType ScalarType; /// Can be a OSG basic type as : OSG::UInt8, OSG::Real32 etc... typedef typename OSGColorCore< ColorType > CoreType; OSGColor() { _corep = NULL; } ~OSGColor() { if( _corep != NULL ) delete _corep; } CoreType & C() { CoreType * tmpcorep = _corep; _corep = new CoreType( Geo(), Index() ); if( tmpcorep != NULL ) delete tmpcorep; return *_corep; } static bool HasColor() { return true; } static void Name( std::vector< std::string > & name ) { name.push_back( std::string( "OSGColor" ) ); T::Name(name); } private : CoreType * _corep; }; class OSGColorCore3f : public OSGColorCore< OSG::Color3f > {}; template< class T > class OSGColor3f : public OSGColor< OSG::Color3f, T > { static void Name( std::vector< std::string > & name ) { name.push_back( std::string( "OSGColor3f" ) ); T::Name(name); } }; } /// end namespace vert } /// end namespace vcg #endif qutemol/src/0000755000175000017500000000000011633404241011411 5ustar mbambaqutemol/src/gen_normal.h0000444000175000017500000001416710467254320013717 0ustar mbamba/**************************************************************************** * VCGLib o o * * Visual and Computer Graphics Library o o * * _ O _ * * Copyright(C) 2004 \/)\/ * * Visual Computing Lab /\/| * * ISTI - Italian National Research Council | * * \ * * All rights reserved. * * * * 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. * * * * 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 (http://www.gnu.org/licenses/gpl.txt) * * for more details. * * * ****************************************************************************/ /**************************************************************************** History $Log: gen_normal.h,v $ Revision 1.2 2006/08/12 04:28:00 tarini Better AO prediction. New icon. Revision 1.1 2006/07/27 07:05:25 cignoni *** empty log message *** Revision 1.1 2006/06/07 15:15:46 tarini *** empty log message *** Revision 1.4 2006/03/23 07:55:54 cignoni *** empty log message *** Revision 1.3 2006/03/21 12:05:35 cignoni *** empty log message *** Revision 1.2 2006/03/21 11:47:16 cignoni *** empty log message *** Revision 1.1 2006/03/21 10:39:45 cignoni *** empty log message *** Revision 1.4 2004/09/28 09:43:46 cignoni minor changes Revision 1.3 2004/09/16 14:23:57 ponchio fixed gcc template compatibility issues. Revision 1.2 2004/09/10 14:02:20 cignoni Added Cone directions Revision 1.1 2004/09/09 22:38:57 cignoni Initial Update ****************************************************************************/ #ifndef __VCG_GEN_NORMAL #define __VCG_GEN_NORMAL #include #include namespace vcg { template class GenNormal { public: typedef Point3 Point3x; static void Random(int vn, std::vector > &NN) { NN.clear(); while(NN.size() > &NN, ScalarType AngleRad, Point3x dir=Point3x(0,1,0)) { std::vector > NNT; NN.clear(); // per prima cosa si calcola il volume della spherical cap di angolo AngleRad ScalarType Height= 1.0 - cos(AngleRad); // height is measured from top... // Surface is the one of the tangent cylinder ScalarType CapArea = 2.0*M_PI*Height; ScalarType Ratio = CapArea / (4.0*M_PI ); printf("----------AngleRad %f Angledeg %f ratio %f vn %i vn2 %i \n",AngleRad,math::ToDeg(AngleRad),Ratio,vn,int(vn/Ratio)); Uniform(vn/Ratio,NNT); printf("asked %i got %i (expecting %i instead of %i)\n", int(vn/Ratio), NNT.size(), int(NNT.size()*Ratio), vn); typename std::vector >::iterator vi; ScalarType DotProd = cos(AngleRad); for(vi=NNT.begin();vi!=NNT.end();++vi) { if(dir*(*vi) >= DotProd) NN.push_back(*vi); } } static void Uniform(int vn, std::vector > &NN) { OctaLevel pp; int ll=10; while(pow(4.0f,ll)+2>vn) ll--; pp.Init(ll); sort(pp.v.begin(),pp.v.end()); int newsize = unique(pp.v.begin(),pp.v.end())-pp.v.begin(); pp.v.resize(newsize); NN=pp.v; Perturb(NN); } static void Perturb(std::vector > &NN) { float width=0.25f/sqrt(float(NN.size())); typename std::vector >::iterator vi; for(vi=NN.begin(); vi!=NN.end();++vi) { Point3x pp(((float)rand())/RAND_MAX, ((float)rand())/RAND_MAX, ((float)rand())/RAND_MAX); pp=pp*2.0-Point3x(1,1,1); pp*=width; (*vi)+=pp; (*vi).Normalize(); } } private : class OctaLevel { public: std::vector v; int level; int sz; Point3f &Val(int i, int j) { assert(i>=0 && i=0 && j >::iterator vi; for(vi=v.begin(); vi!=v.end();++vi) (*vi).Normalize(); } } }; }; } #endif qutemol/src/AOgpu.h0000444000175000017500000000101610515764030012574 0ustar mbamba class AOgpu{ //private: Point3f dir; // direction void CheckAtom(QAtom &a); static vector fakeTexture; static vector snap; static vector sum; static unsigned int div; static float areas; // expected area coverage of a 1 radius sphere int snapx, snapy; void OpenGLSnap(); bool SavePPM( const char * filename ); static unsigned int mask; public: static void Reset(Mol &m); AOgpu( Point3f _dir, Mol &m); static void GetFinalTexture(vector &text, Mol &m); }; qutemol/src/AOgpu.cpp0000444000175000017500000001223710633257033013137 0ustar mbambatypedef unsigned char Byte; #include #include "CgUtil.h" //#include #include //#include #include #include #include using namespace vcg; using namespace std; #include "CubeMapSamp.h" #include "OctaMapSamp.h" #include "Mol.h" #include "AOgpu.h" #include "HardSettings.h" extern int CSIZE; extern int used_mapping; bool SaveImagePPM( const char * filename , const Byte *im, int sizex, int sizey); void ReloadTexture(vector t, bool bilinear); float extractCurrentScaleFactor(); CgUtil mySettings; vector AOgpu::fakeTexture; vector AOgpu::snap; vector AOgpu::sum; unsigned int AOgpu::div; float AOgpu::areas; unsigned int AOgpu::mask=0; void swapbuffers(); void AOgpu::OpenGLSnap() { GLint vp[4]; glGetIntegerv( GL_VIEWPORT,vp ); // Lettura viewport glPixelStorei( GL_PACK_ROW_LENGTH, 0); glPixelStorei( GL_PACK_ALIGNMENT, 1); snapx = vp[2]; snapy = vp[3]; //Create(tx,ty); if (snap.size()!=snapx*snapy+1) snap.resize(snapx*snapy+1); GLenum mtype = 0; int format=0; if(format==0) { format = GL_RGBA; mtype = GL_UNSIGNED_BYTE; } if(format==GL_DEPTH_COMPONENT) { format = GL_DEPTH_COMPONENT; mtype = GL_FLOAT; } glReadPixels(vp[0],vp[1],vp[2],vp[3],format,mtype,(GLvoid *)&snap[0]); //SaveImagePPM("test.ppm" ,(Byte*)(&snap[0]), vp[2],vp[3]); //swapbuffers(); } AOgpu::AOgpu( Point3f _dir, Mol &m) { int out=hardSettings.TSIZE*hardSettings.TSIZE; glClearColor((out&&255)/255.0 , ((out>>8)&&255)/255.0, (out>>16)/255.0, 0 ); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); dir=_dir.Normalize(); // orthonormal basis Point3f ax,ay,az=dir; ax=az^Point3f(1,0,0); if (ax.SquaredNorm()<0.1) ax=az^Point3f(0,1,0); ax=ax.Normalize(); ay=(az^ax).Normalize(); //CubeMapSamp::Transform(ax,ay,az); // make a snapshot! glMatrixMode(GL_PROJECTION); glPushMatrix(); glLoadIdentity(); GLfloat nearPlane = 0.1; GLfloat farPlane = 200; glOrtho(-1,+1,-1,+1, nearPlane, farPlane); glMatrixMode(GL_MODELVIEW); glPushMatrix(); glLoadIdentity(); gluLookAt( az[0],az[1],az[2], 0,0,0, ay[0], ay[1], ay[2] ); if (areas<0) { // only once: compute areas GLint vp[4]; glGetIntegerv( GL_VIEWPORT,vp ); float sc=extractCurrentScaleFactor()*(1/m.r); areas=vp[2]*vp[3]*sc*sc; } mySettings.BindShaders(); m.Draw(); OpenGLSnap(); // interpret spanshot int k=0,h=0; //int* snapi=(int*)(&snap[0]); int max=snapy*snapx; int maxt=sum.size(); /*static*/ // vector found(sum.size(), false ); for (int i=0; i>24; printf("[%d]",snap[i]>>24); }*/ if (sum[ snap[i]&0x00ffffff ]>>24 !=div) { sum[ snap[i]&0x00ffffff ] = (sum[ snap[i]&0x00ffffff ]+(snap[i]>>24))&0x00ffffff | (div<<24); //printf("[%d]",snap[i]>>24); } /* sum[ snap[i]&0x00ffffff ] = ( ( (sum[ snap[i]&0x00ffffff ] + ((sum[ snap[i]&0x00ffffff ]>>24)!=div)*(snap[i]>>24) )&0x00ffffff ) | (div<<24) ); */ } /* static Point3f sumv=Point3f(0,0,0); sumv+=az; printf("%d (%f %f %f) (%f %f %f)\n", div, az[0],az[1],az[2], sumv[0],sumv[1],sumv[2]); */ mask<<=1; div++; glMatrixMode(GL_PROJECTION); glPopMatrix(); glMatrixMode(GL_MODELVIEW); glPopMatrix(); } void AOgpu::Reset(Mol &m){ mySettings.SetForOffLine(); if (fakeTexture.size()==0) { // Prepare And Load fake texture fakeTexture.resize(hardSettings.TSIZE*hardSettings.TSIZE*3); int k=0, i=0; for (int x=0; x>8)&255; fakeTexture[i++]=(k>>16)&255; k++; } m.DuplicateTexels(fakeTexture, hardSettings.TSIZE); } glActiveTextureARB(GL_TEXTURE0_ARB); //glBindTexture(GL_TEXTURE_2D, molTexture); //ReloadTexture(fakeTexture, false); div=0; if (sum.size()!=hardSettings.TSIZE*hardSettings.TSIZE) { sum.resize(hardSettings.TSIZE*hardSettings.TSIZE,0); } else { sum.clear(); sum.resize(hardSettings.TSIZE*hardSettings.TSIZE,0); } mask=1; areas=-1; mySettings.BindShaders(); } inline unsigned int BitCount(unsigned int x){ x=(((x>>1)&x)&(0x88888888)) + ((x<<1)^x)&(0xAAAAAAAA) ; x = ((x>>2)&(0x33333333)) + ( x &(0x33333333)); x = ((x>>4)&(0x0F0F0F0F)) + ( x &(0x0F0F0F0F)); x = ((x>>8)&(0x00FF00FF)) + ( x &(0x00FF00FF)); return (x&0x0000FFFF)+(x>>16); } void AOgpu::GetFinalTexture(vector &text,Mol &m){ int k=0,i=0; //m.SmoothTexture( sum, hardSettings.TSIZE ); int maxt=sum.size(); /*for (int i=0; i #if defined(_WIN32) #include #else #include // for strcmp #endif #include "HardSettings.h" void HardSettings::SetDefaults(){ TSIZE=1024; // total texture size MAX_TSIZE=2048; /// MAX texture size N_VIEW_DIR=128; SHADOWMAP_SIZE=1024; // texture size for shadowmap AOSM_SIZE=256; // texture size for shadowmmaps for AO comp[utation // if true, use double ShadomMap optimization doubleSM=1; NVIDIA_PATCH = 0; MOVING_QUALITY=100; STILL_QUALITY=200; SNAP_SIZE=1024; // snapshots size SNAP_ANTIALIAS=1; PNG_TRANSPARENT=0; // GIF animation settings GIF_SNAP_SIZE=256; GIF_INITIAL_PAUSE=0; GIF_ANIMATION_MODE=0; GIF_ROT_N_FRAMES=60; GIF_ROT_MSEC=3000; GIF_ROT_SIDEVIEW_ANGLE=10; GIF_INSP_N_FRAMES=60; GIF_INSP_MSEC=3000; GIF_INSP_ANGLE=10; GIF_6SIDES_N_FRAMES=10; GIF_6SIDES_MSEC=400; GIF_6SIDES_PAUSE=1000; }; static char* names[NNAMES]={ "TSIZE", "MAX_TSIZE", "N_VIEW_DIR", "SHADOWMAP_SIZE", "AOSM_SIZE", "MOVING_QUALITY", "STILL_QUALITY", "doubleSM", "NVIDIA_PATCH", "SNAP_SIZE", "SNAP_ANTIALIAS", "PNG_TRANSPARENT", "GIF_SNAP_SIZE", "GIF_INITIAL_PAUSE", "GIF_ANIMATION_MODE", "GIF_ROT_N_FRAMES", "GIF_GIF_ROT_MSEC", "GIF_GIF_ROT_SIDEVIEW_ANGLE", "GIF_INSP_N_FRAMES", "GIF_INSP_MSEC", "GIF_INSP_ANGLE", "GIF_6SIDES_N_FRAMES", "GIF_6SIDES_MSEC", "GIF_6SIDES_PAUSE", }; HardSettings::HardSettings(){ int i=0; data[i++]=&TSIZE; data[i++]=&MAX_TSIZE; data[i++]=&N_VIEW_DIR; data[i++]=&SHADOWMAP_SIZE; data[i++]=&AOSM_SIZE; data[i++]=&MOVING_QUALITY; data[i++]=&STILL_QUALITY; data[i++]=&doubleSM; data[i++]=&NVIDIA_PATCH; data[i++]=&SNAP_SIZE; data[i++]=&SNAP_ANTIALIAS; data[i++]=&PNG_TRANSPARENT; data[i++]=&GIF_SNAP_SIZE; data[i++]=&GIF_INITIAL_PAUSE; data[i++]=&GIF_ANIMATION_MODE; data[i++]=&GIF_ROT_N_FRAMES; data[i++]=&GIF_ROT_MSEC; data[i++]=&GIF_ROT_SIDEVIEW_ANGLE; data[i++]=&GIF_INSP_N_FRAMES; data[i++]=&GIF_INSP_MSEC; data[i++]=&GIF_INSP_ANGLE; data[i++]=&GIF_6SIDES_N_FRAMES; data[i++]=&GIF_6SIDES_MSEC; data[i++]=&GIF_6SIDES_PAUSE; } static char* comments[NNAMES]={ "favoured texture size for molecule", "maximal texture size (used when molecule too large for TSIZE)", "number of view directions ussed in AO computation", "texture size for shadowmap", "texture size for shadowmmaps for AO computation", "Quality of image on screen when molecole moves (between 50..200)", "Quality of image on screen when molecole is still (between 50..200)", "if 1, use double ShadomMap optimization (two way lights)", "use 1 - *AND* disable doubleSM - to patch a bug reported on some Nvidia cards (warning: lowers visual quality!)", "snapshots resolution (per side)", "if 1, antialias exported snapshots", "if 1, save PNG images with tranparent background", "resolution of exported GIF animations", "initial pause in msec before each animation loop", "if 0: full rotation. If 1: inspection mode (rotation around current viewpoint). If 2: six-views show.", "number of frames of exported GIF animations (for full rotation)", "total duration in msec of GIF animations loop (for full rotation)", "angle (in -45 +45). If 0, perfect side rotation; if >0, look from above; if <0, look from below (for full rotation)", "number of frames of exported GIF animations (for inspections)", "total duration in msec of GIF animations loop (for inspections)", "in (10..45). Animation is an inspection around current view point (for inspections)", "number of frames of exported GIF animations (for six-views show)", "duration in msec of each face shift (for six-views show)", "pause in msec after each face shift (for six-views show)", }; bool HardSettings::Load(char *fn){ FILE *f=fopen(fn,"rt"); bool present[NNAMES]; for (int i=0; i #include using namespace std; static std::map E2RC; // covalent radius static std::map E2R; // radius static std::map E2C; // colors static void InitTables(){ if(E2RC.size()==0) { /// according to http://www.umass.edu/microbio/rasmol/rasbonds.htm E2RC[" H"]= 0.320f; E2RC[" C"]= 0.720f; E2RC[" N"]= 0.680f; E2RC[" O"]= 0.680f; E2RC[" P"]= 1.036f; E2RC[" S"]= 1.020f; E2RC["CA"]= 0.992f; E2RC["FE"]= 1.420f; E2RC["ZN"]= 1.448f; E2RC["CD"]= 1.688f; // What is CD anyway? E2RC[" I"]= 1.400f; } if(E2R.size()==0) { // according to http://www.imb-jena.de/ImgLibDoc/glossary/IMAGE_VDWR.html //E2R["H"]= 1.20f; //E2R["C"]= 1.70f; //E2R["N"]= 1.55f; //E2R["O"]= 1.52f; E2R[" F"]= 1.47f; //E2R["P"]= 1.80f; //E2R["S"]= 1.80f; E2R["CL"]= 1.89f; /// according to http://www.umass.edu/microbio/rasmol/rasbonds.htm E2R[" H"]= 1.100f; E2R[" C"]= 1.548f; // was changed to 1.400 for some reason 1.548 is the reported value E2R[" N"]= 1.400f; E2R[" O"]= 1.348f; E2R[" P"]= 1.880f; E2R[" S"]= 1.808f; E2R["CA"]= 1.948f; E2R["FE"]= 1.948f; E2R["ZN"]= 1.148f; E2R["CD"]= 1.748f; E2R[" I"]= 1.748f; } if(E2C.size()==0) { E2C[" H"] = /*[255,255,255]*/ 0xFFFFFF /* 0xFFFFFF */ ; E2C["HE"]= /*[217,255,255]*/ 0xFFC0CB /* 0xD9FFFF */ ; E2C["LI"]= /*[204,128,255]*/ 0xB22222 /* 0xCC80FF */ ; E2C["BE"]= /*[194,255, 0]*/ 0xFF1493 /* 0xC2FF00 */ ; E2C[" B"] = /*[255,181,181]*/ 0x00FF00 /* 0xFFB5B5 */ ; E2C[" C"] = /*[144,144,144]*/ 0x808080 /* 0x909090 */ ; E2C[" N"] = /*[ 48, 80,248]*/ 0x8F8FFF /* 0x3050F8 */ ; E2C[" O"] = /*[255, 13, 13]*/ 0xF00000 /* 0xFF0D0D */ ; E2C[" F"] = /*[144,224, 80]*/ 0xDAA520 /* 0x90E050 */ ; E2C["NE"]= /*[179,227,245]*/ 0xFF1493 /* 0xB3E3F5 */ ; E2C["NA"]= /*[171, 92,242]*/ 0x0000FF /* 0xAB5CF2 */ ; E2C["MG"]= /*[138,255, 0]*/ 0x228B22 /* 0x8AFF00 */ ; E2C["AL"]= /*[191,166,166]*/ 0x808090 /* 0xBFA6A6 */ ; E2C["SI"]= /*[240,200,160]*/ 0xDAA520 /* 0xF0C8A0 */ ; E2C[" P"] = /*[255,128, 0]*/ 0xFFA500 /* 0xFF8000 */ ; E2C[" S"] = /*[255,255, 48]*/ 0xFFC832 /* 0xFFFF30 */ ; E2C["CL"]= /*[ 31,240, 31]*/ 0x00FF00 /* 0x1FF01F */ ; E2C["AR"]= /*[128,209,227]*/ 0xFF1493 /* 0x80D1E3 */ ; E2C["K"] = /*[143, 64,212]*/ 0xFF1493 /* 0x8F40D4 */ ; E2C["CA"]= /*[ 61,255, 0]*/ 0x808090 /* 0x3DFF00 */ ; E2C["SC"]= /*[230,230,230]*/ 0xFF1493 /* 0xE6E6E6 */ ; E2C["TI"]= /*[191,194,199]*/ 0x808090 /* 0xBFC2C7 */ ; E2C[" V"] = /*[166,166,171]*/ 0xFF1493 /* 0xA6A6AB */ ; E2C["CR"]= /*[138,153,199]*/ 0x808090 /* 0x8A99C7 */ ; E2C["MN"]= /*[156,122,199]*/ 0x808090 /* 0x9C7AC7 */ ; E2C["FE"]= /*[224,102, 51]*/ 0xFFA500 /* 0xE06633 */ ; E2C["CO"]= /*[240,144,160]*/ 0xFF1493 /* 0xF090A0 */ ; E2C["NI"]= /*[ 80,208, 80]*/ 0xA52A2A /* 0x50D050 */ ; E2C["CU"]= /*[200,128, 51]*/ 0xA52A2A /* 0xC88033 */ ; E2C["ZN"]= /*[125,128,176]*/ 0xA52A2A /* 0x7D80B0 */ ; E2C["GA"]= /*[194,143,143]*/ 0xFF1493 /* 0xC28F8F */ ; E2C["GE"]= /*[102,143,143]*/ 0xFF1493 /* 0x668F8F */ ; E2C["AS"]= /*[189,128,227]*/ 0xFF1493 /* 0xBD80E3 */ ; E2C["SE"]= /*[255,161, 0]*/ 0xFF1493 /* 0xFFA100 */ ; E2C["BR"]= /*[166, 41, 41]*/ 0xA52A2A /* 0xA62929 */ ; E2C["KR"]= /*[ 92,184,209]*/ 0xFF1493 /* 0x5CB8D1 */ ; E2C["RB"]= /*[112, 46,176]*/ 0xFF1493 /* 0x702EB0 */ ; E2C["SR"]= /*[ 0,255, 0]*/ 0xFF1493 /* 0x00FF00 */ ; E2C[" Y"] = /*[148,255,255]*/ 0xFF1493 /* 0x94FFFF */ ; E2C["ZR"]= /*[148,224,224]*/ 0xFF1493 /* 0x94E0E0 */ ; E2C["NB"]= /*[115,194,201]*/ 0xFF1493 /* 0x73C2C9 */ ; E2C["MO"]= /*[ 84,181,181]*/ 0xFF1493 /* 0x54B5B5 */ ; E2C["TC"]= /*[ 59,158,158]*/ 0xFF1493 /* 0x3B9E9E */ ; E2C["RU"]= /*[ 36,143,143]*/ 0xFF1493 /* 0x248F8F */ ; E2C["RH"]= /*[ 10,125,140]*/ 0xFF1493 /* 0x0A7D8C */ ; E2C["PD"]= /*[ 0,105,133]*/ 0xFF1493 /* 0x006985 */ ; E2C["AG"]= /*[192,192,192]*/ 0x808090 /* 0xC0C0C0 */ ; E2C["CD"]= /*[255,217,143]*/ 0xFF1493 /* 0xFFD98F */ ; E2C["IN"]= /*[166,117,115]*/ 0xFF1493 /* 0xA67573 */ ; E2C["SN"]= /*[102,128,128]*/ 0xFF1493 /* 0x668080 */ ; E2C["SB"]= /*[158, 99,181]*/ 0xFF1493 /* 0x9E63B5 */ ; E2C["TE"]= /*[212,122, 0]*/ 0xFF1493 /* 0xD47A00 */ ; E2C[" I"] = /*[148, 0,148]*/ 0xA020F0 /* 0x940094 */ ; E2C["XE"]= /*[ 66,158,176]*/ 0xFF1493 /* 0x429EB0 */ ; E2C["CS"]= /*[ 87, 23,143]*/ 0xFF1493 /* 0x57178F */ ; E2C["BA"]= /*[ 0,201, 0]*/ 0xFFA500 /* 0x00C900 */ ; E2C["LA"]= /*[112,212,255]*/ 0xFF1493 /* 0x70D4FF */ ; E2C["CE"]= /*[255,255,199]*/ 0xFF1493 /* 0xFFFFC7 */ ; E2C["PR"]= /*[217,255,199]*/ 0xFF1493 /* 0xD9FFC7 */ ; E2C["ND"]= /*[199,255,199]*/ 0xFF1493 /* 0xC7FFC7 */ ; E2C["PM"]= /*[163,255,199]*/ 0xFF1493 /* 0xA3FFC7 */ ; E2C["SM"]= /*[143,255,199]*/ 0xFF1493 /* 0x8FFFC7 */ ; E2C["EU"]= /*[ 97,255,199]*/ 0xFF1493 /* 0x61FFC7 */ ; E2C["GD"]= /*[ 69,255,199]*/ 0xFF1493 /* 0x45FFC7 */ ; E2C["TB"]= /*[ 48,255,199]*/ 0xFF1493 /* 0x30FFC7 */ ; E2C["DY"]= /*[ 31,255,199]*/ 0xFF1493 /* 0x1FFFC7 */ ; E2C["HO"]= /*[ 0,255,156]*/ 0xFF1493 /* 0x00FF9C */ ; E2C["ER"]= /*[ 0,230,117]*/ 0xFF1493 /* 0x00E675 */ ; E2C["TM"]= /*[ 0,212, 82]*/ 0xFF1493 /* 0x00D452 */ ; E2C["YB"]= /*[ 0,191, 56]*/ 0xFF1493 /* 0x00BF38 */ ; E2C["LU"]= /*[ 0,171, 36]*/ 0xFF1493 /* 0x00AB24 */ ; E2C["HF"]= /*[ 77,194,255]*/ 0xFF1493 /* 0x4DC2FF */ ; E2C["TA"]= /*[ 77,166,255]*/ 0xFF1493 /* 0x4DA6FF */ ; E2C[" W"] = /*[ 33,148,214]*/ 0xFF1493 /* 0x2194D6 */ ; E2C["RE"]= /*[ 38,125,171]*/ 0xFF1493 /* 0x267DAB */ ; E2C["OS"]= /*[ 38,102,150]*/ 0xFF1493 /* 0x266696 */ ; E2C["IR"]= /*[ 23, 84,135]*/ 0xFF1493 /* 0x175487 */ ; E2C["PT"]= /*[208,208,224]*/ 0xFF1493 /* 0xD0D0E0 */ ; E2C["AU"]= /*[255,209, 35]*/ 0xDAA520 /* 0xFFD123 */ ; E2C["HG"]= /*[184,184,208]*/ 0xFF1493 /* 0xB8B8D0 */ ; E2C["TL"]= /*[166, 84, 77]*/ 0xFF1493 /* 0xA6544D */ ; E2C["PB"]= /*[ 87, 89, 97]*/ 0xFF1493 /* 0x575961 */ ; E2C["BI"]= /*[158, 79,181]*/ 0xFF1493 /* 0x9E4FB5 */ ; E2C["PO"]= /*[171, 92, 0]*/ 0xFF1493 /* 0xAB5C00 */ ; E2C["AT"]= /*[117, 79, 69]*/ 0xFF1493 /* 0x754F45 */ ; E2C["RN"]= /*[ 66,130,150]*/ 0xFF1493 /* 0x428296 */ ; E2C["FR"]= /*[ 66, 0,102]*/ 0xFF1493 /* 0x420066 */ ; E2C["RA"]= /*[ 0,125, 0]*/ 0xFF1493 /* 0x007D00 */ ; E2C["AC"]= /*[112,171,250]*/ 0xFF1493 /* 0x70ABFA */ ; E2C["TH"]= /*[ 0,186,255]*/ 0xFF1493 /* 0x00BAFF */ ; E2C["PA"]= /*[ 0,161,255]*/ 0xFF1493 /* 0x00A1FF */ ; E2C[" U"] = /*[ 0,143,255]*/ 0xFF1493 /* 0x008FFF */ ; E2C["NP"]= /*[ 0,128,255]*/ 0xFF1493 /* 0x0080FF */ ; E2C["PU"]= /*[ 0,107,255]*/ 0xFF1493 /* 0x006BFF */ ; E2C["AM"]= /*[ 84, 92,242]*/ 0xFF1493 /* 0x545CF2 */ ; E2C["CM"]= /*[120, 92,227]*/ 0xFF1493 /* 0x785CE3 */ ; E2C["BK"]= /*[138, 79,227]*/ 0xFF1493 /* 0x8A4FE3 */ ; E2C["CF"]= /*[161, 54,212]*/ 0xFF1493 /* 0xA136D4 */ ; E2C["ES"]= /*[179, 31,212]*/ 0xFF1493 /* 0xB31FD4 */ ; E2C["FM"]= /*[179, 31,186]*/ 0xFF1493 /* 0xB31FBA */ ; E2C["MD"]= /*[179, 13,166]*/ 0xFF1493 /* 0xB30DA6 */ ; E2C["NO"]= /*[189, 13,135]*/ 0xFF1493 /* 0xBD0D87 */ ; E2C["LR"]= /*[199, 0,102]*/ 0xFF1493 /* 0xC70066 */ ; E2C["RF"]= /*[204, 0, 89]*/ 0xFF1493 /* 0xCC0059 */ ; E2C["DB"]= /*[209, 0, 79]*/ 0xFF1493 /* 0xD1004F */ ; E2C["SG"]= /*[217, 0, 69]*/ 0xFF1493 /* 0xD90045 */ ; E2C["BH"]= /*[224, 0, 56]*/ 0xFF1493 /* 0xE00038 */ ; E2C["HS"]= /*[230, 0, 46]*/ 0xFF1493 /* 0xE6002E */ ; E2C["MT"]= /*[235, 0, 38]*/ 0xFF1493 /* 0xEB0026 */ ; } } static bool addAtomType(char* namei, int unused, float radius, float radiusC, int r, int g, int b){ InitTables(); // upperCase(name); std::string name(namei); int i=0; while (name[i]) { if ((name[i]>='a') && (name[i]<='z')) name[i]=name[i]-'a'+'A'; //else name[i]=namei[i]; i++; } if (radius<0.01) radius=0.01; E2R[name]=radius; E2C[name]=(r<<16)+(g<<8)+b; if (radiusC<0.01) radiusC=0.01; E2RC[name]=radiusC; // note: covalent radius does not get updated. If needed, #if 0 // write a log of added atom types static FILE* f=NULL; if (f==NULL) { f=fopen("AddedAtomsLog.txt","wt"); }; fprintf(f,"Added '%s' %d %f %f (%d %d %d)\n",name,unused,radius,radiusR, r,g,b); fflush(f); #endif return true; } // Adds Pseudo Atoms types used by NanoDex! static void AddPseudoAtoms(){ addAtomType("Ax", 200 , 5.0 , 4.0, 102 ,102 , 204 ); // Axis addAtomType("Ae", 204 , 3.5 , 2.5, 102 ,102 , 204 ); // Axis-end addAtomType("Ss", 201 , 4.0 , 3.0, 102 ,204 , 102 ); // Strand sugar addAtomType("Sj", 203 , 4.0 , 3.0, 102 ,204 , 204 ); // Strand junction addAtomType("Pl", 202 , 3.2 , 2.2, 102 ,26 , 128 ); // Phosphorous link addAtomType("Pe", 205 , 3.0 , 2.0, 102 ,26 , 128 ); // Phosphorous end addAtomType("Sh", 206 , 2.5 , 1.5, 102 ,204 , 102 ); // Sugar hydroxyl addAtomType("Hp", 207 , 4.0 , 3.0, 77 ,179 , 77 ); // Hairpin addAtomType(" X", 0 , 1.1 , 0.1, 255*8/10 ,0 ,0 ); // Bondpoint } // quick and dirty: reads a line, returns it first 80 chars, skips initial spaces and empty lines static char* getLine(FILE* f){ static char res[80]; int i=0; while (1) { char c=fgetc(f); if (c==EOF) { if (i==0) return NULL; else break;} if (c==13 ) { if (i==0) continue; else break; } if ((i<80) && (c!=10) && ((i!=0) ||(c!=' ')) ) res[i++]=c; } res[i]=0; return res; } // reads a NanoDex "art" file, describing custom atom types bool readArtFile(const char* filename){ InitTables(); AddPseudoAtoms(); FILE* f=fopen(filename,"rb"); if (!f) return false; while (1) { char* line=getLine(f); if (!line) break; if (line[0]!='#') { char a[100]; int b; float c1,c2; int d,e,f; sscanf(line,"%s %d %f %f %d %d %d",a,&b,&c1,&c2,&d,&e,&f); addAtomType(a,b,c1,c2,d,e,f); } } fclose(f); return true; } float getMaxCovelentRadius(){ return 1.688f; } float getAtomRadius(const char* atomicElementCharP) { InitTables(); //std::string ss0,ss1; string atomicElement(atomicElementCharP); //ss0=atomicElement.substr(0,1); //ss1=atomicElement.substr(0,2); float rad=E2R[atomicElement]; //if(rad==0) rad = E2R[ss0]; if(rad==0) rad=1.5; return rad; } float getAtomCovalentRadius(const char* atomicElementCharP){ InitTables(); //std::string ss0,ss1; string atomicElement(atomicElementCharP); //ss0=atomicElement.substr(0,1); //ss1=atomicElement.substr(0,2); float rad=E2RC[atomicElement]; //if(rad==0) rad = E2RC[ss0]; // HACK: covalent (B&S) radius of undefined atoms is defined as half the SpaceFill rad if (rad==0) rad=getAtomRadius(atomicElementCharP)/2.0; return rad; } int getAtomColor(const char* atomicElementCharP){ InitTables(); string atomicElement(atomicElementCharP); //std::string ss0,ss1,ss2; //size_t last=std::min(atomicElement.length(),atomicElement.find_first_of(' ')); //ss0=atomicElement.substr(0,1); int color=E2C[atomicElement]; if(color==0) { // printf("color 0 for %s\n",ss0.c_str()); //ss1=atomicElement.substr(0,2); //color = 0x000000; } return color+0xff000000; } // VERY QUICK AND DIRTY random color schema computation: // ----------------------------------------------------- static int basecol=1; void ChangeColorSchema(int i){ static int index=3; if (i==-1) i=index++; basecol=i*1231123; } bool tooDark(int c){ return (c&255)+ ((c>>8)&255) + ((c>>16)&255) < 200; } int getChainColor(int index){ int res=basecol*index*35634379; int antiloop=0; while (tooDark(res) && (antiloop++<10) ) { res=(res+1231)*645633737; } return res; } qutemol/src/MyCanvas.h0000444000175000017500000000165110507300202013273 0ustar mbamba class MyCanvas{ public: bool ratio2x1; typedef enum{ COLOR, DEPTH, COLOR_AND_DEPTH } Kind; Kind kind; bool SetAsOutput(); bool SetAsTexture(); bool Test(){return SetAsOutput();} MyCanvas(Kind k, int size); MyCanvas(Kind k); void SetRes( int res ); void SetResPow2( int pow ); int GetSoftRes(); int GetHardRes(); int GetResPow2( ) {return currentRes; } int GetVideoSize( ) {return videoSize; } void SetSameRes( const MyCanvas &c ); void RedirectToVideo(); void RedirectToMemory(); void SetVideoSize(int v); // when redirectig to video private: int currentRes; // just an index enum {MAX_RES=15}; unsigned int frameID[MAX_RES]; unsigned int textureID[MAX_RES]; bool InitRes(); bool onVideo; int videoSize; int softRes; // subset image, not a power of 2 }; extern MyCanvas mainCanvas, haloCanvas, moltextureCanvas, shadowmapCanvas, shadowAOCanvas; qutemol/src/HardSettings.h0000444000175000017500000000212510542044036014157 0ustar mbamba// HARD SETTINGS: // Settings affecting performance / quality ratio const int NNAMES=24; class HardSettings{ public: int TSIZE; // total texture size int MAX_TSIZE; // max texture size int N_VIEW_DIR; int SHADOWMAP_SIZE; // texture size for shadowmap int AOSM_SIZE; // texture size for shadowmmaps for AO computation int NVIDIA_PATCH; int MOVING_QUALITY; int STILL_QUALITY; // if true, use double ShadomMap optimization int doubleSM; int SNAP_SIZE; int SNAP_ANTIALIAS; int PNG_TRANSPARENT; // GIF animation settings int GIF_SNAP_SIZE; int GIF_INITIAL_PAUSE; int GIF_ANIMATION_MODE; int GIF_ROT_N_FRAMES; int GIF_ROT_MSEC; int GIF_ROT_SIDEVIEW_ANGLE; int GIF_INSP_N_FRAMES; int GIF_INSP_MSEC; int GIF_INSP_ANGLE; int GIF_6SIDES_N_FRAMES; int GIF_6SIDES_MSEC; int GIF_6SIDES_PAUSE; void SetDefaults(); bool Load(char *fn); bool Save(char *fn); bool OnStart(); // tries to load, on faliure setdefaults and saves HardSettings(); private: int* data[NNAMES]; }; extern HardSettings hardSettings; // SINGLETON qutemol/src/Sampling.cpp0000444000175000017500000000303310633257153013673 0ustar mbambatypedef unsigned char Byte; #include #include "CgUtil.h" //#include #include //#include #include #include #include using namespace vcg; using namespace std; #include "CubeMapSamp.h" #include "OctaMapSamp.h" int CubeMapSamp::size; int OctaMapSamp::size; vector CubeMapSamp::dir; vector CubeMapSamp::dirrot; vector CubeMapSamp::map; // mappa 2d di indici a dir //vector CubeMapSamp::weight; vector OctaMapSamp::dir; vector OctaMapSamp::dirrot; vector OctaMapSamp::weight; void OctaMapSamp::FillTexture(vector &texture, const vector &sumtable, int texsize, float div, int tx, int ty ) { for (int y=0,k=0; y255) res=255; texture[h*3+0]= res; texture[h*3+1]= res; texture[h*3+2]= res; /* if (res<512-275) { texture[h*3+0]= 0; texture[h*3+1]= res; texture[h*3+2]= res; } else if (res<254) { texture[h*3+0]= 0; texture[h*3+1]= 255; texture[h*3+2]= 0; } else if (res>275) { texture[h*3+0]= 255; texture[h*3+1]= res-255; texture[h*3+2]= res/2-255; } else { texture[h*3+0]= res; if (res>255) res=255; texture[h*3+1]= res; texture[h*3+2]= res; }*/ } } qutemol/src/main.cpp0000444000175000017500000007025110634273663013060 0ustar mbamba// // qutemol on wxWidgets MAIN // // (on DevCpp, download and install "wxWidgets 2.6.1 unicode" DevPak) // //////////////////////////////////////////////////////////////////// #define SnapButton 1 #define OpenButton 2 #define QuitButton 3 #include #ifdef __GNUG__ #pragma implementation #pragma interface #endif // For compilers that support precompilation, includes "wx.h". #include "wx/wxprec.h" #include "wx/image.h" #include "wx/stdpaths.h" //#include #include #include #ifdef __BORLANDC__ #pragma hdrstop #endif #ifndef WX_PRECOMP #include "wx/wx.h" #endif #if !wxUSE_GLCANVAS #error "OpenGL required: set wxUSE_GLCANVAS to 1 and rebuild the library" #endif #include "main.h" #ifdef __WXMAC__ # ifdef __DARWIN__ # include # else # include # endif #else # include #endif //#include "sample.xpm" typedef unsigned char Byte; typedef unsigned int uint; #include "CgUtil.h" #include #include #include #include #include "gen_normal.h" #include using namespace vcg; using namespace std; #include "CubeMapSamp.h" #include "OctaMapSamp.h" #include "Mol.h" //#include "AOgpu.h" #include "MyCanvas.h" #include "ShadowMap.h" #include "HardSettings.h" #include "Common.h" #include "MyTab.h" #include "saveSnapDialog.h" #include "progress.h" #include "AtomColor.h" extern vcg::Trackball track; extern vcg::Trackball lightTrack; extern Mol mol; bool mustDoHQ=false; #include #include wxStopWatch sw; #include "gifSave.h" // defined in pngSave bool PNGSaveWithAlpha( const char * filename, const Byte * data, int sx, int sy, int reverse = 0); void downsample2x2(Byte * data, int sx, int sy); void downsample2x2NoAlpha(Byte * data, int sx, int sy); wxBitmap *LoadPngImage(wxString st){ #ifdef __DARWIN__ wxString basePath = wxStandardPaths::Get().GetResourcesDir(); wxBitmap* res=new wxBitmap(basePath+_T("/image/")+st+_T(".png"),wxBITMAP_TYPE_PNG); #else wxBitmap* res=new wxBitmap(_T("image/")+st+_T(".png"),wxBITMAP_TYPE_PNG); #endif //wxBitmap* res=new wxBitmap(st,wxBITMAP_TYPE_PNG_RESOURCE); // Marke all black pixels as transparent (useful for Windows NT only) //res->SetMask(new wxMask(*res, wxColor(0,0,0))); return res; } void MyTab::SceneChanged(){ ((TestGLCanvas*)frame2redraw)->SceneChanged(); } void TestGLCanvas::SceneChanged(){ mustDoHQ=false; Refresh(false); } void StartTime(){ sw.Start(); } long int TakeTime(FILE *f , char *st){ long int delta=sw.Time(); fprintf(f,"%5ldmsec: %s\n",delta,st); //globaltime=timen; return delta; } /*long int TakeTotalTime(){ long int timen=getTicks(), delta=timen-startingtime; printf("------------------\nTotal time: %5dmsec\n",delta); globaltime=timen; return delta; }*/ long int getTicks(){ return 0; } void MyToolbar::SetTitleText(wxString s){ #ifndef __DARWIN__ titleText->SetLabel(s); titleTextSizer->Layout(); #endif } class MyDropTarget : public wxFileDropTarget { public: MyDropTarget(MyFrame *_parent) { parent = _parent; } virtual bool OnDropFiles(wxCoord x, wxCoord y, const wxArrayString& filenames){ parent->OnReadFile(filenames[0]); }; private: MyFrame *parent; }; void MyToolbar::OnDrag(wxMouseEvent &event){ if ( event.LeftDClick()) { parent->Maximize( !(parent->IsMaximized()) ); } static int omx, omy; int mx, my; mx = event.GetX(); my = event.GetY(); if ( event.Dragging() ){ if (!(parent->IsMaximized())) { CaptureMouse(); wxPoint cur=parent->GetPosition(); int dx=mx-omx; int dy=my-omy; cur.x+=dx; cur.y+=dy; omx=mx-dx; omy=my-dy; parent->SetPosition( cur ); } } else { omx=mx; omy=my; ReleaseMouse(); } } wxNotebook *notebook; void MyToolbar::UpdateGearsIcon(){ UpdateGearsIcon( mol.DoingAO() ); } void MyToolbar::UpdateGearsIcon(bool b){ if (gearPresent==b) return; if (!b) gearS->Detach(gear); else gearS->Add(gear); gear->Show(b); gearS->Layout(); gearPresent=b; /* if (b) gear->Raise(); else gear->Lower();*/ } MyToolbar::MyToolbar(wxTopLevelWindow *_parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style, const wxString& name): wxPanel(_parent, id, pos, size, style, name){ parent=_parent; // let's build notebook /*wxNotebook **/notebook = new wxNotebook( this, id, pos, size, 0,/*style/*|wxNO_FULL_REPAINT_ON_RESIZE|wxNB_TOP,*/ name); for (int i=0; iAddPage(new MyTab(notebook,i), MyTab::Title(i), i==0 ); parent->SetBackgroundColour(notebook->GetBackgroundColour()); } #ifndef __DARWIN__ wxBitmapButton *snapButton = new wxBitmapButton(this, SnapButton, *LoadPngImage(_T("snap_off2")), wxDefaultPosition, wxSize(48,48),0); snapButton->SetBitmapSelected(*LoadPngImage(_T("snap_on"))); wxBitmapButton *openButton = new wxBitmapButton(this, OpenButton, *LoadPngImage(_T("open_off2")),wxDefaultPosition, wxSize(48,48),0); openButton->SetBitmapSelected(*LoadPngImage(_T("open_on"))); #else wxBitmapButton *snapButton = new wxBitmapButton(this, SnapButton, *LoadPngImage(_T("snap_noborder")), wxDefaultPosition, wxSize(48,48),0); wxBitmapButton *openButton = new wxBitmapButton(this, OpenButton, *LoadPngImage(_T("open_noborder")),wxDefaultPosition, wxSize(48,48),0); #endif wxBitmapButton *quitButton = new wxBitmapButton(this, QuitButton, *LoadPngImage(_T("quitoff")), wxDefaultPosition, wxSize(15,16) , 0); quitButton->SetBitmapSelected(*LoadPngImage(_T("quiton"))); wxStaticBitmap *logo = new wxStaticBitmap(this, wxID_ANY, *LoadPngImage(_T("qutemolsm")), wxDefaultPosition ); gear = new wxStaticBitmap(this, wxID_ANY, *LoadPngImage(_T("gear2")), wxDefaultPosition ); wxSizer *sizerButtons = new wxBoxSizer( wxVERTICAL ); sizerButtons->Add(openButton, 0, wxALL, 1); sizerButtons->Add(snapButton, 0, wxALL, 1); titleText = new wxStaticText(this, wxID_ANY, wxT("")); titleText->Disable(); #ifndef __DARWIN__ wxSizer *linesizer1 = new wxBoxSizer(wxVERTICAL); linesizer1->Add(new wxStaticLine(this),0,wxALL| wxEXPAND, 1); linesizer1->Add(new wxStaticLine(this),0,wxALL| wxEXPAND, 1); linesizer1->Add(new wxStaticLine(this),0,wxALL| wxEXPAND, 1); wxSizer *linesizer2 = new wxBoxSizer(wxVERTICAL); linesizer2->Add(new wxStaticLine(this),0,wxALL| wxEXPAND, 1); linesizer2->Add(new wxStaticLine(this),0,wxALL| wxEXPAND, 1); linesizer2->Add(new wxStaticLine(this),0,wxALL| wxEXPAND, 1); titleTextSizer = new wxBoxSizer(wxHORIZONTAL); titleTextSizer->Add(3,3, 0, wxALL, 3); titleTextSizer->Add(linesizer1, 1, wxALL|wxALIGN_CENTER_VERTICAL, 0); titleTextSizer->Add(titleText, 0, wxALL|wxALIGN_CENTER_VERTICAL, 0); titleTextSizer->Add(linesizer2, 20, wxALL|wxALIGN_CENTER_VERTICAL, 0); titleTextSizer->Add(3,3, 0, wxALL, 3); // spacer titleTextSizer->Add(quitButton, 0, wxALL|wxALIGN_CENTER_VERTICAL, 2); #else quitButton->Hide(); titleText->Hide(); #endif wxSizer *imgsizer = new wxBoxSizer(wxHORIZONTAL); imgsizer->Add(22,22, 0); //imgsizer->Add(1,1, 10); imgsizer->Add(logo, 1, wxALL|wxALIGN_CENTER_VERTICAL|wxALIGN_CENTER_HORIZONTAL, 0); // LOGO //imgsizer->Add(1,1, 9); gearS = new wxBoxSizer(wxVERTICAL); gearS->Add(22,22,1); gearS->Add(gear); gearPresent=true; imgsizer->Add(gearS, 0, wxALL|wxALIGN_BOTTOM|wxALIGN_CENTER_HORIZONTAL, 2); // LOGO wxSizer *topRsizer = new wxBoxSizer(wxVERTICAL); #ifndef __DARWIN__ topRsizer->Add(titleTextSizer,0, wxALL| wxEXPAND, 0); #endif topRsizer->Add(imgsizer,1, wxALL| wxEXPAND, 0); topsizer = new wxBoxSizer(wxHORIZONTAL); topsizer->Add(sizerButtons, 0, wxALL, 5); topsizer->Add(topRsizer, 1, wxALIGN_TOP| wxALL| wxEXPAND, 0); wxSizer *globalsizer = new wxBoxSizer(wxVERTICAL); globalsizer->Add(topsizer, 0, wxALL| wxEXPAND, 0); //globalsizer->Add(5, 5, 0, wxALL, 0); // spacer globalsizer->Add(notebook, 1, wxALL|wxEXPAND, 0); SetSizer(globalsizer); UpdateGearsIcon(false); } // `Main program' equivalent, creating windows and returning main app frame bool MyApp::OnInit() { hardSettings.OnStart(); cgSettings.SetDefaults(); // <-- quick hack (solves wrong constructor order): //if (!wxApp::OnInit()) return false; // questo per caricare salvare PNG... wxImage::AddHandler(new wxPNGHandler); wxImage::AddHandler(new wxJPEGHandler); // Create the main frame window MyFrame *frame = new MyFrame(NULL, wxT("QuteMol"), // wxDefaultPosition, wxDefaultSize, wxDEFAULT_FRAME_STYLE //wxRESIZE_BORDER #ifdef __DARWIN__ wxDefaultPosition, wxDefaultSize,wxDEFAULT_FRAME_STYLE| wxRESIZE_BORDER #else wxDefaultPosition, wxDefaultSize,wxRESIZE_BORDER #endif ); /* Make a menubar */ /* // ...or, maybe NOT wxMenu *fileMenu = new wxMenu; fileMenu->Append(wxID_EXIT, wxT("E&xit")); fileMenu->Append(wxID_ABOUT, wxT("A&bout")); fileMenu->Append(wxID_OPEN, wxT("O&pen")); wxMenuBar *menuBar = new wxMenuBar; menuBar->Append(fileMenu, wxT("&File")); frame->SetMenuBar(menuBar); */ frame->SetCanvas( new TestGLCanvas( frame, wxID_ANY, wxPoint(0,0), wxSize( winx, winy ), wxNO_BORDER //wxSUNKEN_BORDER ) ); // onle TestGLCanvas to process idles... wxIdleEvent::SetMode(wxIDLE_PROCESS_SPECIFIED); frame->SetExtraStyle(wxWS_EX_PROCESS_IDLE ); MyTab::frame2redraw=frame->GetCanvas(); frame->SetToolbar( new MyToolbar( frame, wxID_ANY, wxPoint(winx,0), wxDefaultSize, // wxNO_BORDER //wxSUNKEN_BORDER wxDEFAULT_FRAME_STYLE | // wxNO_FULL_REPAINT_ON_RESIZE | wxCLIP_CHILDREN | wxTAB_TRAVERSAL ) ); wxSizer *sizer = new wxBoxSizer(wxHORIZONTAL); sizer->Add(frame->GetCanvas(), 1, wxGROW|wxSHAPED); sizer->Add(frame->GetToolbar(), 0, wxGROW); frame->SetSizer(sizer); int tbsize=frame->GetToolbar()->GetBestFittingSize().x; frame->GetToolbar()->SetSize(tbsize,winy); frame->GetToolbar()->Layout(); //frame->SetMinSize(wxSize(tbsize+200,200)); frame->SetClientSize(wxSize(winx+tbsize,winy)); static const wxCmdLineEntryDesc cmdLineDesc[] = { { wxCMD_LINE_PARAM,_T(""),_T(""),_T("filename.pdb:(molecule to be drawn)"), wxCMD_LINE_VAL_STRING, wxCMD_LINE_PARAM_OPTIONAL }, { wxCMD_LINE_OPTION,_T("a"),_T(""),_T("filename.art: optional Atom Render Table"), wxCMD_LINE_VAL_STRING, wxCMD_LINE_PARAM_OPTIONAL }, { wxCMD_LINE_SWITCH,_T("v"),_T(""),_T("don't start, show version name"), wxCMD_LINE_VAL_STRING, wxCMD_LINE_PARAM_OPTIONAL }, { wxCMD_LINE_NONE } }; wxCmdLineParser parser(cmdLineDesc, argc, argv); parser.Parse(); InitQuteMol( NULL ); wxString artFilename; if (parser.Found(_T("v"))>0) { FILE *f=fopen("output.txt", "wt"); if (f) { fprintf(f,"ver 0.4.1"); fclose(f); } exit(0); } if (parser.Found(_T("a"),&artFilename)>0) { if (!readArtFile(artFilename.ToAscii())) { wxMessageBox( wxString(_T("Error reading art file \"") + artFilename +"\""), _T("Error reading art file"), wxOK | wxICON_EXCLAMATION, frame); exit(0); return false; } } if (parser.GetParamCount()>0) frame->OnReadFile(parser.GetParam(0)); /* InitQuteMol( parser.GetParam(0).mb_str(wxConvUTF8) ); } else { InitQuteMol( NULL ); }*/ /* Show the frame */ frame->Center(); frame->SetDropTarget( new MyDropTarget(frame) ); frame->Show(true); return true; } void MyFrame::ResetAO(){ mol.ResetAO(); } IMPLEMENT_APP(MyApp) BEGIN_EVENT_TABLE(MyFrame, wxFrame) //EVT_PAINT(MyFrame::OnPaint) #if defined(_WIN32) EVT_ERASE_BACKGROUND(MyFrame::OnEraseBackground) #endif EVT_SIZE(MyFrame::OnSize) EVT_BUTTON(OpenButton, MyFrame::OnOpenFile) EVT_BUTTON(SnapButton, MyFrame::OnSaveSnap) EVT_BUTTON(QuitButton, MyFrame::OnExit) EVT_KEY_DOWN(MyFrame::OnKeyDown) EVT_KEY_UP(MyFrame::OnKeyUp) EVT_IDLE(MyFrame::OnIdle) END_EVENT_TABLE() BEGIN_EVENT_TABLE(MyToolbar, wxPanel) EVT_MOUSE_EVENTS(MyToolbar::OnDrag) END_EVENT_TABLE() void MyFrame::OnKeyUp( wxKeyEvent& event ){ m_canvas->OnKeyUp(event); } void MyFrame::OnKeyDown( wxKeyEvent& event ){ m_canvas->OnKeyDown(event); } /* My frame constructor */ MyFrame::MyFrame(wxFrame *frame, const wxString& title, const wxPoint& pos, const wxSize& size, long style) : wxFrame(frame, wxID_ANY, title, pos, size, style) { m_canvas = NULL; m_tb= NULL; #ifndef __DARWIN__ SetIcon(wxIcon(_T("sample"),wxBITMAP_TYPE_ICO_RESOURCE,32,32)); #endif resize_mode=NATURAL; } //void MyFrame::OnPaint( wxPaintEvent& event ) //{ // wxFrame::OnPaint(event); //} void MyFrame::OnSize(wxSizeEvent& event){ int w,h; GetClientSize(&w,&h); int hlogo = m_tb->topsizer->GetMinSize().y + 40; if (MyTab::Redispose(h - hlogo )) { GetToolbar()->SetSize(200,winy); } if (resize_mode==FORCED ) { // TODO: fullscreen resize //m_canvas->; //m_tb->; resize_mode=NATURAL; wxFrame::OnSize(event); //m_tb->Fit(); //m_tb->GetSizer()->RecalcSizes(); //GetSizer()->RecalcSizes(); //notebook->Layout(); //notebook->SetSize(100,100); //m_tb->SetSize(100,100); //notebook->GetSizer()->RecalcSizes();; //m_tb->Layout(); //Layout(); // Fit(); } else if (resize_mode==NATURAL ) { wxFrame::OnSize(event); /* GetClientSize(&w,&h); int tbsize=GetToolbar()->GetBestFittingSize().x; winx=w-tbsize; winy=h; GetToolbar()->SetPosition( wxPoint(winx,0) ); GetToolbar()->SetSize(tbsize,winy); GetCanvas()->SetSize(winx,winy); */ resize_mode=CUSTOM; } else { static int oldw=0,oldh=0; int w1=m_tb->GetBestFittingSize().x; // int sx=w-w1, sy=h , s; if ((oldw==w) && (oldh!=h)) s=sy; else if ((oldh==h) && (oldw!=w)) s=sx; else s=(sx+sy)/2; wxSize size=wxSize(s+w1, s); resize_mode=NATURAL; SetClientSize(size); //wxFrame::OnSize( event ); //wxSizeEvent event2=wxSizeEvent(size); //wxFrame::OnSize(event2); //oldw=w;oldh=h; } } void MyFrame::Maximize(bool max){ //if (custom_resizing) { resize_mode=FORCED; wxFrame::Maximize(max); //} } /* Intercept menu commands */ void MyFrame::OnExit( wxCommandEvent& WXUNUSED(event) ) { Close(); } BEGIN_EVENT_TABLE(TestGLCanvas, wxGLCanvas) EVT_SIZE(TestGLCanvas::OnSize) EVT_PAINT(TestGLCanvas::OnPaint) EVT_ERASE_BACKGROUND(TestGLCanvas::OnEraseBackground) EVT_MOUSE_EVENTS(TestGLCanvas::OnMouse) EVT_KEY_DOWN(TestGLCanvas::OnKeyDown) EVT_KEY_UP(TestGLCanvas::OnKeyUp) END_EVENT_TABLE() TestGLCanvas::TestGLCanvas(wxWindow *_parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style, const wxString& name) : wxGLCanvas(_parent, id, pos, size, style|wxFULL_REPAINT_ON_RESIZE, name) { initdone=false; shownHQ=false; } TestGLCanvas::~TestGLCanvas() { } wxString errorMSG(int errcode){ wxString res; res=_T("OpenGL problems:\n\n"); if (errcode&ERRGL_NO_GLEW) { res+=_T(" - cannot initialize GLEW:\n "); res+= wxString::FromAscii(CgUtil::lasterr); res+=_T("\n"); } if (errcode&ERRGL_NO_FS) res+=_T(" - no Programmable Fragment Shader found\n"); if (errcode&ERRGL_NO_VS) res+=_T(" - no Programmable Vertex Shader found\n"); if (errcode&ERRGL_NO_FBO_SHADOWMAP) res+=_T(" - cannot initialize FrameBufferObject for shadowmaps\n"); if (errcode&ERRGL_NO_FBO_HALO) res+=_T(" - cannot initialize FrameBufferObject for halos\n"); if (errcode&ERRGL_NO_FBO_HALO) res+=_T(" - cannot initialize FrameBufferObject for A.O. computation\n"); res+=_T("\n(Hint: update graphic card drivers)"); return res; } void TestGLCanvas::OnPaint( wxPaintEvent& event ) { /* must always be here */ wxPaintDC dc(this); #ifndef __WXMOTIF__ if (!GetContext()) return; #endif SetCurrent(); if (!initdone) { static bool once=false; if (!once) { once=true; int errcode=initGl(); if (errcode!=ERRGL_OK){ wxMessageBox(errorMSG(errcode), _T("Unrecoverable error: Problems initializing graphics"), wxOK | wxICON_EXCLAMATION, this); exit(0); } else initdone=true; } } if (!initdone) wxGLCanvas::OnPaint(event); else if (mol.IsReady()) { if (mustDoHQ) { drawFrame( hardSettings.STILL_QUALITY ); shownHQ=true; mustDoHQ=false; } else { drawFrame( hardSettings.MOVING_QUALITY ); shownHQ=false; } SwapBuffers(); } else { clearFrame(); SwapBuffers(); } } void TestGLCanvas::OnSize(wxSizeEvent& event) { // this is also necessary to update the context on some platforms wxGLCanvas::OnSize(event); // set GL viewport (not called by wxGLCanvas::OnSize on all platforms...) GetClientSize(&winx, &winy); mainCanvas.SetVideoSize(winx); #ifndef __WXMOTIF__ if ( GetContext() ) #endif { SetCurrent(); glViewport(0, 0, (GLint) winx, (GLint) winy); } } void MyFrame::OnEraseBackground(wxEraseEvent& event) { wxFrame::OnEraseBackground(event); /* Do nothing, to avoid flashing on MSW */ } void TestGLCanvas::OnEraseBackground(wxEraseEvent& event) { if (!initdone) wxGLCanvas::OnEraseBackground(event); /* Do else do nothing, to avoid flashing on MSW */ } bool wxConsumeTrackBallEvent(wxMouseEvent& event, Trackball &track); bool wxConsumeTrackBallEvent(wxKeyEvent& event, bool down, Trackball &track); void TestGLCanvas::OnKeyUp( wxKeyEvent& event ){ wxConsumeTrackBallEvent(event,false,track); } extern int CSIZE; // number of texels for a patch of an aotm void TestGLCanvas::OnKeyDown( wxKeyEvent& event ){ wxConsumeTrackBallEvent(event,true,track); #ifdef __DARWIN__ wxString path = wxStandardPaths::Get().GetResourcesDir() + "/presets/new.preset"; #else wxString path = "presets\\new.preset"; #endif if (event.GetKeyCode() == WXK_F7 ) { cgSettings.Save(path.c_str()); } if (event.GetKeyCode() == WXK_F6 ) { if (cgSettings.Load(path.c_str())) { MyTab::UpdateAll(); cgSettings.ResetHalo(); cgSettings.UpdateShaders(); SceneChanged(); } } if (event.GetKeyCode() == WXK_F5 ) { mol.PrepareAOSingleView(); SceneChanged(); } if (event.GetKeyCode() == WXK_F2 ) { static int status=0; status=(status+1) % 5; draw_balls = (status==0) || (status==1) || (status==2) ; draw_sticks = (status==0) || (status==1) || (status==3) || (status==4) ; draw_wireframe_balls= (status==1) ; draw_wireframe_sticks= (status==1) || (status==3) ; SceneChanged(); } if (event.GetKeyCode() == WXK_F1 ) { wxString text; if (!mol.IsReady() ) text=wxT("(no molecule)"); else { text=wxString( mol.GetMolName(), wxConvUTF8 ).BeforeLast('.') + wxT("\n (file: \"")+wxString( mol.filename, wxConvUTF8 ) +wxT("\")\n\n"); text=text+wxString::Format(wxT("%d atoms\n"),mol.atom.size()); if (mol.sticks) { text=text+wxString::Format(wxT("%d bonds\n"),mol.bond.size()); } text=text+wxString::Format( _T("\nUsing:\n Texture size = %dx%d\n Patch size=%dx%d"), moltextureCanvas.GetHardRes(), moltextureCanvas.GetHardRes(), CSIZE,CSIZE ); } wxMessageBox(text, _T("QuteMol - file info"), wxOK | wxICON_INFORMATION, this); } if (event.GetKeyCode() == WXK_F6 ) { use_accurate_halo=!use_accurate_halo; SceneChanged(); } // temp, should e set auto depending on dist if (event.GetKeyCode() == WXK_F2 ) { cgSettings.P_capping=!cgSettings.P_capping; cgSettings.UpdateShaders(); SceneChanged(); } } void MyFrame::OnAbout(wxCommandEvent& WXUNUSED(event)) { } void MyFrame::OnSaveSnap (wxCommandEvent & event) { int sx,sy; static const wxString FILETYPES = _T( "PNG (lossless)|*.png|" "JPEG (lossy)|*.jpg|" "GIF animation|*.gif" ); wxFileDialog * saveSnapDialog = new wxFileDialog ( this, wxString (_T("Save a snapshot")), wxString(), // def path wxString(), FILETYPES, wxSAVE | /*wxCHANGE_DIR |*/ wxOVERWRITE_PROMPT ); static int lastFilterIndex=-1; if (lastFilterIndex==-1) lastFilterIndex=saveSnapDialog->GetFilterIndex(); saveSnapDialog->SetFilterIndex( lastFilterIndex ); wxString ext; if (lastFilterIndex==1) ext=_T(".jpg"); else if (lastFilterIndex==2) ext=_T(".gif"); else ext=_T(".png"); saveSnapDialog->SetFilename( wxString( mol.GetFilenameSnap(), wxConvUTF8 )+ ext ); static wxString CANNOT_SAVE = _T("Could not save snap!\n\nYou might try setting\na lower resolution\nor removing AntiAliasing..."); if (saveSnapDialog->ShowModal() == wxID_OK) if ((new savesnapDialog(this,saveSnapDialog->GetFilterIndex()))->ShowModal() == wxID_OK ) { int jj=saveSnapDialog->GetFilterIndex(); lastFilterIndex=jj; Byte* snap; int AAMult=(hardSettings.SNAP_ANTIALIAS)?2:1; bool useTransp=(hardSettings.PNG_TRANSPARENT==1) && (jj==0); if (jj!=2) { sx=sy=hardSettings.SNAP_SIZE*AAMult; if ((useTransp) && (cgSettings.UseHalo()>0)) { cgSettings.doingAlphaSnapshot=true; cgSettings.ResetHalo(); cgSettings.UpdateShaders(); } snap= GetSnapshot(sx,sy, useTransp ); if (cgSettings.doingAlphaSnapshot) { cgSettings.doingAlphaSnapshot=false; cgSettings.ResetHalo(); cgSettings.UpdateShaders(); } if (!snap) { wxMessageBox(CANNOT_SAVE, _T("OpenGL problems?"), wxOK | wxICON_EXCLAMATION, this); return; } } else sx=sy=hardSettings.GIF_SNAP_SIZE*AAMult; { wxString fn=saveSnapDialog->GetPath(); // fix filename Extension ////////////////////////// //wxString ext[3]={ _T("png"), _T("jpg") , _T("png") }; //wxString cext=fn.AfterLast('.'); //if (cext.CmpNoCase(ext[0])||cext.CmpNoCase(ext[1])) fn=fn.BeforeLast('.'); //fn=fn+_T('.')+ext[ jj ]; switch (jj) { case 0: case 1: if (!useTransp) { StartProgress("Saving snap!", 2); wxImage snapi(sx,sy,snap); if (AAMult!=1) snapi=snapi.Scale(sx/AAMult,sy/AAMult); UpdateProgress(1); wxBitmap(snapi.Mirror(false)).SaveFile( fn, (jj==0)?wxBITMAP_TYPE_PNG:wxBITMAP_TYPE_JPEG ); UpdateProgress(2); EndProgress(); } else { if (AAMult!=1) downsample2x2(snap, sx, sy); PNGSaveWithAlpha((const char*)fn.mb_str(wxConvUTF8),snap,sx/AAMult,sy/AAMult,1); }; break; case 2: { GifWrapper gifw; int N; double totalTime; double subStepTime=0; double startTime;startTime=hardSettings.GIF_INITIAL_PAUSE/1000.0; if (hardSettings.GIF_ANIMATION_MODE==0) { N=hardSettings.GIF_ROT_N_FRAMES; totalTime=hardSettings.GIF_ROT_MSEC/1000.0; } if (hardSettings.GIF_ANIMATION_MODE==1) { N=hardSettings.GIF_INSP_N_FRAMES; totalTime=hardSettings.GIF_INSP_MSEC/1000.0; } if (hardSettings.GIF_ANIMATION_MODE==2) { N=hardSettings.GIF_6SIDES_N_FRAMES*6; totalTime=hardSettings.GIF_6SIDES_MSEC*6.0/1000.0; subStepTime=hardSettings.GIF_6SIDES_PAUSE/1000.0; } StartProgress("Saving GIF", N); for (int i=0; iSetTitleText(name); geoSettings.Apply(); // redo shaders, as texture size could have changed cgSettings.UpdateShaders(); } else { wxMessageBox(wxString::FromAscii(QAtom::lastReadError), _T(":-("), wxOK | wxICON_EXCLAMATION, this); m_tb->SetTitleText(); } // remake shaders cos texture size could have changed... //theText->LoadFile(openFileDialog->GetFilename()); //SetStatusText(GetCurrentFilename(), 0); } void MyFrame::OnOpenFile (wxCommandEvent & event) { static const wxString FILETYPES = _T( "Protein Data Bank molecule (pdb, vdb)|*.pdb;*.vdb|" "All files|*.*" ); wxFileDialog * openFileDialog = new wxFileDialog ( this, wxString(_T("Open file")), wxString(), // def path wxString(), FILETYPES, wxOPEN | wxFILE_MUST_EXIST/*| wxCHANGE_DIR*/, wxDefaultPosition); if (openFileDialog->ShowModal() == wxID_OK) { OnReadFile( openFileDialog->GetPath() ); } /* wxString filename=openFileDialog->GetFilename(); wxString dir=openFileDialog->GetDirectory();*/ } void MyFrame::OnIdle(wxIdleEvent& event){ if (mol.DoingAO()) { m_tb->UpdateGearsIcon(true); if (mol.PrepareAOstep()) { m_canvas->SceneChanged(); event.RequestMore(false); m_tb->UpdateGearsIcon(false); return; } else event.RequestMore(true); } else { event.RequestMore(false); if (hardSettings.STILL_QUALITY!=hardSettings.MOVING_QUALITY) if (!m_canvas->shownHQ) { m_canvas->shownHQ=true; mustDoHQ=true; m_canvas->Refresh(false); } m_tb->UpdateGearsIcon(false); } } void TestGLCanvas::OnMouse( wxMouseEvent& event ) { static bool useLightTrack=false; if ( event.m_rightDown || event.m_leftDown || event.m_middleDown ) { if (!HasCapture()) CaptureMouse(); } else if (HasCapture()) ReleaseMouse(); useLightTrack=event.m_rightDown; bool consumed=false; if (useLightTrack) { MovingLightMode=true; if (wxConsumeTrackBallEvent( event, lightTrack)) { SetFocus(); consumed=true; } } else { MovingLightMode=false; if (wxConsumeTrackBallEvent( event, track)) { SetFocus(); consumed=true; } } if ((consumed) && (!event.ButtonUp()) && (!event.ButtonDown())) SceneChanged(); /* if ( event.m_rightUp ) { useLightTrack=false; }*/ } void TestGLCanvas::InitGL() { initGl(); } qutemol/src/main.h0000444000175000017500000000642710633746237012532 0ustar mbamba #ifndef _WX_MAIN_H_ #define _WX_MAIN_H_ #include #include #include #include #include extern "C" { //#include "lw.h" //#include "trackball.h" } /* information needed to display lightwave mesh */ //typedef struct //{ // gint do_init; /* true if initgl not yet called */ // bool do_init; // //lwObject *lwobject; /* lightwave object mesh */ // float beginx,beginy; /* position of mouse */ // float quat[4]; /* orientation of object */ // float zoom; /* field of view in degrees */ //} mesh_info; /* Define a new application type */ class MyApp: public wxApp { public: bool OnInit(); }; class MyToolbar: public wxPanel { public: MyToolbar(wxTopLevelWindow *parent, wxWindowID id = wxID_ANY, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = 0, const wxString& name = wxT("ToolBar")); void OnDrag(wxMouseEvent &event); wxSizer *topsizer; void UpdateGearsIcon(bool b); void UpdateGearsIcon(); void SetTitleText( wxString = wxEmptyString ); private: wxTopLevelWindow *parent; wxStaticText *titleText; wxSizer *titleTextSizer; bool gearPresent; wxStaticBitmap *gear; wxBoxSizer *gearS; DECLARE_EVENT_TABLE() }; /* Define a new frame type */ class TestGLCanvas; class MyFrame: public wxFrame { public: MyFrame(wxFrame *frame, const wxString& title, const wxPoint& pos, const wxSize& size, long style = wxDEFAULT_FRAME_STYLE); void OnExit(wxCommandEvent& event); void OnOpenFile (wxCommandEvent & event); // open the open-file dialogs void OnReadFile (wxString filename); // reads the file void OnSaveSnap (wxCommandEvent & event); void OnAbout (wxCommandEvent & event); void OnSize(wxSizeEvent& event); void Maximize(bool max); //#if defined(_WIN32) void OnEraseBackground(wxEraseEvent& event); //#endif void SetToolbar( MyToolbar *tb ) { m_tb = tb; } MyToolbar *GetToolbar() { return m_tb; } void OnPaint( wxPaintEvent& WXUNUSED(event) ); #if wxUSE_GLCANVAS void SetCanvas( TestGLCanvas *canvas ) { m_canvas = canvas; } TestGLCanvas *GetCanvas() { return m_canvas; } void OnKeyUp( wxKeyEvent& event ); void OnKeyDown( wxKeyEvent& event ); void ResetAO(); void OnIdle(wxIdleEvent& event); private: enum {NATURAL, CUSTOM, FORCED} resize_mode; TestGLCanvas *m_canvas; #endif MyToolbar *m_tb; DECLARE_EVENT_TABLE() }; #if wxUSE_GLCANVAS class TestGLCanvas: public wxGLCanvas { public: TestGLCanvas(wxWindow *parent, wxWindowID id = wxID_ANY, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = 0, const wxString& name = wxT("GLCanvas")); ~TestGLCanvas(); void OnPaint(wxPaintEvent& event); void OnSize(wxSizeEvent& event); void OnEraseBackground(wxEraseEvent& event); void OnMouse( wxMouseEvent& event ); void OnKeyUp( wxKeyEvent& event ); void OnKeyDown( wxKeyEvent& event ); void InitGL(); void SceneChanged(); // redraw! bool initdone; bool shownHQ; private: //wxWindow *parent; DECLARE_EVENT_TABLE() }; #endif // #if wxUSE_GLCANVAS #endif // #ifndef _WX_MAIN_H_ qutemol/src/AO.cpp0000444000175000017500000000444710633256265012435 0ustar mbamba typedef unsigned char Byte; #include #include #include using namespace vcg; using namespace std; #include "CubeMapSamp.h" #include "OctaMapSamp.h" #include "Mol.h" #include "AO.h" const float infty=1000; vector tmpbool(32*32,false); void AO::PrintBuffer(){ int target=32; int k=0; for (int y=0; y0) { tmp=sqrt(tmp)+cz; int i=index(x+cxi,y+cyi); if (buf[i]>tmp) buf[i]=tmp; //buf[i]=0; } } } void AO::CheckAtom(QAtom &a){ int n=a.s.nsamp(); for (int i=0; i0) { int bx=(int) (a.trp[0]+f[0]); int by=(int) (a.trp[1]+f[1]); tmpbool[index(bx,by)]=true;; if (buf[index(bx,by)] == infty ) { a.s.sum[i]+=f[2]; }; a.s.div[i]+=f[2]; } } } AO::AO( Point3f _dir, Mol &m) { dir=_dir.Normalize(); // orthonormal basis Point3f ax,ay,az=dir; ax=az^Point3f(1,0,0); if (ax.SquaredNorm()<0.1) ax=az^Point3f(0,1,0); ax=ax.Normalize(); ay=(az^ax).Normalize(); // project... m.Transform(ax,ay,az); int target=32; // bufx=bufy=target; float bufscalex=target/(m.tx1-m.tx0); float bufscaley=target/(m.ty1-m.ty0); bufscale=(bufscalex #include "CgUtil.h" #if defined(_WIN32) #include #else #include // for strlen #endif //#include #include #include "HardSettings.h" #include "MyCanvas.h" extern int CSIZE; extern int BSIZE; //extern GeoSettings geoSettings; void CgUtil::Set(){ } bool CgUtil::UseHalo(){ return P_halo_size * P_halo_str >0; } bool CgUtil::can_use_doubleshadow(){ return ((P_light_base==0.0) && (hardSettings.doubleSM) ); } bool CgUtil::do_use_doubleshadow(){ return ((P_double_shadows) && (can_use_doubleshadow())); } static char* FORMAT="void CgUtil::Set(int K){\nif (K==0){\n P_light_base = %f ;\n P_lighting = %f ;\n P_phong = %f ;\n P_phong_size = %f ;\n P_col_atoms_sat = %f ;\n P_col_atoms_bri = %f ;\n P_texture = %f ;\n P_border_inside = %f ;\n P_border_outside = %f ;\n P_depth_full = %f ;\n P_sem_effect = %d ;\n P_halo_size = %f ;\n P_halo_col = %f ;\n P_halo_str = %f ;\n P_halo_aware = %f ;\n P_fog = %f ;\n P_capping = %d ;\n P_shadowstrenght = %f ;\n P_bg_color_R = %f ;\n P_bg_color_G = %f ;\n P_bg_color_B = %f ;\n auto_normalize = %d ;\n P_double_shadows = %d ;\n P_border_fixed = %d ;\n}\n}"; bool CgUtil::Load(const char* filename){ FILE *f=fopen(filename, "rt"); if (!f) return false; fscanf(f,FORMAT ,&P_light_base,&P_lighting,&P_phong,&P_phong_size,&P_col_atoms_sat,&P_col_atoms_bri,&P_texture,&P_border_inside,&P_border_outside,&P_depth_full,&P_sem_effect,&P_halo_size,&P_halo_col,&P_halo_str,&P_halo_aware,&P_fog,&P_capping,&P_shadowstrenght,&P_bg_color_R,&P_bg_color_G,&P_bg_color_B,&auto_normalize,&P_double_shadows,&P_border_fixed); fclose(f); return true; } bool CgUtil::Save(const char* filename){ FILE *f=fopen(filename, "wt"); if (!f) return false; fprintf(f,FORMAT ,P_light_base,P_lighting,P_phong,P_phong_size,P_col_atoms_sat,P_col_atoms_bri,P_texture,P_border_inside,P_border_outside,P_depth_full,P_sem_effect,P_halo_size,P_halo_col,P_halo_str,P_halo_aware,P_fog,P_capping,P_shadowstrenght,P_bg_color_R,P_bg_color_G,P_bg_color_B,auto_normalize,P_double_shadows,P_border_fixed); fclose(f); return true; } float CgUtil::_border_outside(){ return P_border_outside*0.075; } float CgUtil::_border_inside(){ return P_border_inside*0.5; } void CgUtil::setGeoSettings(const GeoSettings &gs){ if (gs.mode==GeoSettings::BALL_N_STICKS) { P_cyl_const_color=gs.use_stick_const_color; P_cyl_smooth_color=gs.stick_smooth_color; P_cyl_const_color_R = gs.stick_const_color_R; P_cyl_const_color_G = gs.stick_const_color_G; P_cyl_const_color_B = gs.stick_const_color_B; } if (gs.mode==GeoSettings::LICORICE) { P_cyl_const_color=false; P_cyl_smooth_color=false; } } CgUtil::CgUtil() { loaded=false; idf=666; idv=666; auto_normalize=false; norm=1; loadedVertexHalo=false; ResetHalo(); proj_figa=false; idfStick=idvStick=666; loadedStick=false; idvHalo=666; cyl_radius=0.2; shadowmapBuilding=false; accurateShadowmapBuilding=false; doingAlphaSnapshot=false; shadersMade=false; } void CgUtil::ResetHalo(){ for (int i=0; i---------\n%s",vp); //if(!checkProgramError(vp)) return -1; //return true; } bool CgUtil::MakeHaloShader(int pow){ char fp[10096]; sprintf(fp,"\ !!ARBfp1.0\n\ \n\ ATTRIB data = fragment.texcoord; \n\ \n\ TEMP tmp,tmp2,tmp3, t,t0,t1,t2,nor,n,nabs,nsign,disp,res,depth,pos,\n\ lighting; \n\ \n\ MOV nor, data; \n\ MUL tmp, data, data; \n\ ADD tmp2.x, tmp.x, tmp.y;\n\ ADD tmp2.z, -tmp2.x, 1;\n\ KIL tmp2.z;\n\ \n\ MAD tmp2.x, -data.z, tmp2.x, data.z;\n\ \n\ #TEST!\n\ #ADD tmp2.x, tmp2.x, %10.8f;\n\ #CMP result.color, tmp2.x, {1,0,0,1}, {0,0,1,1};\n\ \n\ MUL tmp, fragment.position, {%14.12f, %14.12f, 0, 0};\n\ #MAD tmp, fragment.position, {0.5, 0.5, 0, 0}, {0.5, 0.5, 0, 0};\n\ TEX tmp.z, tmp, texture[1], 2D; # tmp.z = old depth \n\ ADD tmp.z, tmp.z, -fragment.position.z; \n\ MUL_SAT tmp.z, tmp.z, program.env[0].x; \n\ MUL tmp.z, tmp.z, tmp2.x; \n\ MUL tmp.z, tmp.z, tmp2.x; # again for smoother edges\n\ ", +P_halo_str-1, 1.0f/(1<--------\n%s",fp); if(!checkProgramError(fp)) return false; return true; } static void addDrawAOShaderSnippet(char* fp) { sprintf(fp,"%s\n\ # Find shading value \n\ DP3 l.x, nor, -param; \n\ #MUL_SAT l.x, l.x, param.w; \n\ MUL l.x, l.x, param.w; \n\ #KIL l.x; \n\ ",fp); if ( (!hardSettings.doubleSM) && (!hardSettings.NVIDIA_PATCH) ) { sprintf(fp,"%s\n\ KIL l.x; # early KILL of fragments on the dark side...\n\ ",fp); } sprintf(fp,"%s\n\ # Project! \n\ DP4 pos.x, Smat0, origpos; \n\ DP4 pos.y, Smat1, origpos; \n\ DP4 pos.z, Smat2, origpos; \n\ ",fp); if (hardSettings.doubleSM) sprintf(fp,"%s\n\ CMP tmp, l.x, {0.75,0.5,0.5,1}, {0.25,0.5,0.5,1};\n\ MAD pos, pos, {0.25,0.5,0.5,0}, tmp; \n\ \n\ ",fp); else sprintf(fp,"%s\n\ MAD pos, pos, {0.5,0.5,0.5,0}, {0.5,0.5,0.5,1}; \n\ ",fp); sprintf(fp,"%s\n\ # Access shadow map! \n\ TEX tmp.x, pos, texture[1], 2D;\n\ SUB l.z, tmp.x, pos.z; \n\ ",fp); if (hardSettings.doubleSM) sprintf(fp,"%s\n\ CMP l.z, l.x, -l.z, l.z; \n\ CMP l.x, l.x, -l.x, l.x; # DOUBLE SIDE\n\ \n\ ",fp); sprintf(fp,"%s\n\ # NVIDIA BUUUUGUUGUGUGUGUGUUGUUGGUGUUGUG GUUGUGUG GGFUCKFUCKFUCKFUCKFUCKFUCKFUCK!!! \n\ %s\ CMP result.color, l.z, 0, l.x; # <-- (shadow & shading) \n\ #CMP result.color, l.z, 0, 1; # <-- (TEST: only shadow - works) \n\ #CMP result.color, 1, 0, l.x; # <-- (TEST: only shading - works) \n\ # NVIDIA BUUUUGUUGUGUGUGUGUUGUUGGUGUUGUG GUUGUGUG GGFUCKFUCKFUCKFUCKFUCKFUCKFUCK!!! \n\ \n\ # TEST1: MAD result.color, {0.5,0.5,0.5,0},nor, {0.5,0.5,0.5,1};\n\ # TEST2: MAD result.color, {0.5,0.5,0.5,0},origpos, {0.5,0.5,0.5,1};\n\ # TEST3: CMP result.color, l.z, {1,0,0,1}, {0,0,0.5,1};\n\ # TEST4: MOV result.color, tmp.x;\n\ \n\ \n\ END\n\ ", fp, hardSettings.NVIDIA_PATCH? "MUL l.x, 0.5, param.w; # <-- patch! REMOVE ME when N-VIDIA wakes up \n" :"" ); } bool CgUtil::MakeDrawAOShader(){ char fp[10096]; sprintf(fp,"\ !!ARBfp1.0 \n\ PARAM Smat0 = program.env[0];\n\ PARAM Smat1 = program.env[1];\n\ PARAM Smat2 = program.env[2];\n\ PARAM param = program.env[3];\n\ ATTRIB tc = fragment.texcoord; \n\ ATTRIB data = fragment.texcoord[1]; \n\ TEMP tmp,nor, pos,origpos, abs,l;\n\ \n\ # Find shpere normal... \n\ CMP abs, tc, -tc, tc;\n\ MAD nor, -abs, {1,1,0,0}, +1;\n\ CMP tmp.x, tc.x, -nor.y, nor.y; # tmp_i = sign_i*( 1-abs_i) \n\ CMP tmp.y, tc.y, -nor.x, nor.x; # tmp_i = sign_i*( 1-abs_i) \n\ ADD nor.z, abs.x, abs.y; \n\ ADD nor.z, nor.z, -1; \n\ CMP nor.x, -nor.z, tmp.x, tc.x;\n\ CMP nor.y, -nor.z, tmp.y, tc.y;\n\ # Normalize \n\ DP3 tmp.x, nor, nor; \n\ RSQ tmp.x, tmp.x; \n\ MUL nor, nor, tmp.x; \n\ \n\ # Find pos \n\ MAD origpos, data.w, nor, data;\n\ MOV origpos.w, 1;\n"); addDrawAOShaderSnippet(fp); glProgramStringARB(GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB, strlen(fp), fp); // printf("\n---------------\n%s",fp); if(!checkProgramError(fp)) return false; //ShowShaderInfo(GL_FRAGMENT_PROGRAM_ARB); return true; }; bool CgUtil::MakeDrawAOShaderSticks(){ char fp[10096]; sprintf(fp,"\ !!ARBfp1.0 \n\ PARAM Smat0 = program.env[0];\n\ PARAM Smat1 = program.env[1];\n\ PARAM Smat2 = program.env[2];\n\ PARAM param = program.env[3];\n\ PARAM radius = program.env[4];\n\ ATTRIB axispos= fragment.texcoord[1]; \n\ ATTRIB data = fragment.texcoord; \n\ TEMP tmp,n,nor, pos,origpos, abs,l;\n\ \n\ \n\ # find norm in cyl space \n\ MAD n.y, data.y, -2, 0; \n\ CMP n.y, n.y, -n.y, n.y; \n\ ADD n.x, 2, -n.y; \n\ MIN n.x, n.x, n.y; \n\ CMP n.x, data.y, n.x, -n.x; \n\ MAD n, n, {1,1,0,0}, {0,-1,0,0};\n\ \n\ # normalize \n\ DP3 tmp.x, n, n;\n\ RSQ tmp.x, tmp.x;\n\ MUL n, tmp.x, n;\n\ \n\ # rotate \n\ MUL nor, -n.x, fragment.texcoord[2];\n\ MAD nor, n.y, fragment.texcoord[3], nor;\n\ \n\ # find position \n\ MAD origpos, nor, radius.y, axispos; \n\ MOV origpos.w, 1;\n\ "); addDrawAOShaderSnippet(fp); glProgramStringARB(GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB, strlen(fp), fp); // printf("\n---------------\n%s",fp); if(!checkProgramError(fp)) return false; //ShowShaderInfo(GL_FRAGMENT_PROGRAM_ARB); return true; }; void CgUtil::Normalize(){ /* if (!auto_normalize) return; float sum=P_light_base + P_lighting + P_texture; if (sum>1.0) { norm=sum; P_light_base/=norm; P_lighting/=norm; P_texture/=norm; }*/ } void CgUtil::UndoNormalize(){ //P_light_base*=norm; P_lighting*=norm; P_texture*=norm; } void CgUtil::SetDefaults(){ P_light_base=0.0; P_lighting=0.9; P_phong=0.0; P_phong_size=0.75; P_col_atoms_sat=0.5; P_col_atoms_bri=1.0; P_texture=0.0; P_border_inside=0.0; P_border_outside=0.0; P_depth_full=0.5; P_sem_effect=false; //P_use_shadowmap=false; P_shadowstrenght=0.0; P_double_shadows=true; P_fog=0; P_bg_color_R=P_bg_color_G=P_bg_color_B=0.5; // textmode=USE_CUBE; textmode=USE_OCTA; projmode=ORTHO; writeAlpha=false; writeCol=true; gap =0.5; P_capping=false; P_halo_size=0.0; // 1.0; P_halo_col =0.0; // 1.0; P_halo_str =1.0; // 1.0; P_halo_aware=0.5; } void CgUtil::SetForShadowMap(bool accurate){ P_light_base=0.0; P_lighting=0.0; P_phong=0.0; P_col_atoms_sat=0.0; P_col_atoms_bri=0.0; P_texture=0.0; P_border_inside=0.0; P_border_outside=0.0; P_sem_effect=false; //P_use_shadowmap=false; P_shadowstrenght=0.0; P_fog=0; projmode=ORTHO; textmode=USE_OCTA; writeAlpha=false; writeCol=false; P_capping=false; P_halo_size=0.0; shadowmapBuilding=true; accurateShadowmapBuilding=accurate; } void CgUtil::SetForOffLine(){ P_light_base=0.0; P_lighting=0.0; P_phong=0.0; P_col_atoms_sat=0.0; P_col_atoms_bri=0.0; P_lighting=0.0; P_texture=1.0; P_border_inside=0.0; P_border_outside=0.0; P_sem_effect=false; //P_use_shadowmap=false; P_shadowstrenght=0.0; P_fog=0; projmode=ORTHO; textmode=USE_OCTA; writeAlpha=true; writeCol=true; P_capping=false; gap =0.2; P_halo_size=0.0; } void CgUtil::BindShaders(){ if (!loaded) MakeShaders(); glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, idf); glBindProgramARB(GL_VERTEX_PROGRAM_ARB, idv); } void CgUtil::MakeShaders(){ if (shadersMade) return; shadersMade=true; if (idf==666) glGenProgramsARB(1, &idf); glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, idf); setBallFragmentProgram(); if (idv==666) glGenProgramsARB(1, &idv); glBindProgramARB(GL_VERTEX_PROGRAM_ARB, idv); setBallVertexProgram(); loaded=true; MakeStickShaders(); } void CgUtil::BindStickShaders(){ if (!loadedStick) MakeStickShaders(); glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, idfStick); glBindProgramARB(GL_VERTEX_PROGRAM_ARB, idvStick); } void CgUtil::MakeStickShaders(){ if (idfStick==666) glGenProgramsARB(1, &idfStick); glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, idfStick); setStickFragmentProgram(); if (idvStick==666) glGenProgramsARB(1, &idvStick); glBindProgramARB(GL_VERTEX_PROGRAM_ARB, idvStick); setStickVertexProgram(); loadedStick=true; } bool CgUtil::BindDrawAOShader(){ if (idf==666) glGenProgramsARB(1, &idf); glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, idf); if (!loaded) MakeDrawAOShader(); loaded=true; return true; } bool CgUtil::BindDrawAOShaderSticks(){ if (idf==666) glGenProgramsARB(1, &idf); glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, idf); if (!loaded) MakeDrawAOShaderSticks(); loaded=true; return true; } bool CgUtil::setBallVertexProgram(){ char vp[10096]; // ##################### // # # // # VERTEX PROGRAM # // # # // ##################### sprintf(vp,"\ !!ARBvp1.0\n\ \n\ ATTRIB pos = vertex.position;\n\ ATTRIB data = vertex.normal;\n\ \n\ "); // DataOut = ( +- OutradX, +- OutRadY, InRad ) if (P_texture>0) sprintf(vp,"%s\ ATTRIB offset = vertex.texcoord;\n\ ", vp); sprintf(vp,"%s\ \n\ PARAM mat[4] = { state.matrix.mvp };\n\ PARAM matP[4] = { state.matrix.projection };\n\ \n\ TEMP p,po, disp, dataout, tmp;\n\ \n\ # Transform by concatenation of the\n\ # MODELVIEW and PROJECTION matrices.\n\ DP4 p.x, mat[0], pos;\n\ DP4 p.y, mat[1], pos;\n\ DP4 p.z, mat[2], pos;\n\ DP4 p.w, mat[3], pos;\n\ #MOV p.w, 1; \n\ \n\ MOV dataout, data;\n\ MUL dataout.z, dataout.z, program.env[0].x;\n\ ", vp); // Enlarge impostors to include borders if (_border_outside()!=0) // Compute 'almost' radius and scale indep. border sprintf(vp,"%s\ RSQ tmp.y, dataout.z ;\n\ #MUL tmp.y, tmp.y , tmp.y; # Comment to 'almost'\n\ MUL tmp.x, %7.5f , tmp.y;\n\ ADD dataout.w, tmp.x , 1;\n\ MUL dataout.xy, dataout, dataout.w ;\n\ MAD dataout.w, dataout.w, dataout.w, -1;\n\ ", vp, _border_outside() ); sprintf(vp,"%s\ \n\ MUL disp, dataout, dataout.z; \n\ #MUL disp.x, disp.x, matP[0].x;\n\ #MUL disp.y, disp.y, matP[1].y;\n\ MAD p, {1,1,0,0}, disp, p;\n\ ", vp); sprintf(vp,"%s\ \n\ MOV result.position, p;\n\ \n\ #MOV dataout.w, p.w;\n" ,vp); sprintf(vp,"%sMOV result.texcoord, dataout;\n",vp); if ((P_col_atoms_sat>0)&&(P_col_atoms_bri>0)) sprintf(vp,"%sMOV result.color, vertex.color;\n",vp); if (P_texture>0) sprintf(vp,"%sMOV result.texcoord[2], offset;\n",vp); if (P_use_shadowmap() ) sprintf(vp,"%sMOV result.texcoord[3], vertex.position;\n",vp); sprintf(vp,"%s\nEND\n", vp); glProgramStringARB(GL_VERTEX_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB, strlen(vp), vp); //printf("\n-----------------\n%s",vp); if(!checkProgramError(vp)) return -1; return true; } void CgUtil::addShadowMapComputationFP(char* fp) { sprintf(fp,"%s\n\ #SHADOWMAP\n\ \n\ #compute orig pos from attributes... MODE 1\n\ #MUL t0.x, data.z, ratio.x;\n\ #MAD pos, n, t0.x, origpos;\n\ #\n\ # ...or MODE 2!!! \n\ MAD posScreen, fragment.position, {1,1,0,0}, {0,0,0,1} ;\n\ MOV posScreen.z, depth.x;\n\ \n\ DP4 t0.x, Smat0, posScreen; \n\ DP4 t0.y, Smat1, posScreen; \n\ DP4 t0.z, Smat2, posScreen; \n\ ",fp); if (do_use_doubleshadow()) sprintf(fp,"%s\n\ CMP t1, lighting.z, {0.75,0.5,0.5,1}, {0.25,0.5,0.5,1};\n\ MAD t0, t0, {0.25,0.5,0.5,0}, t1; \n\ \n\ ",fp); else { double tmp=(hardSettings.doubleSM)?0.25:0.5; sprintf(fp,"%s\n\ MAD t0, t0, {%4.2f,0.5,0.5,0}, {%4.2f,0.5,0.5,1}; \n\ ",fp,tmp,tmp); } /* sprintf(fp,"%s\n\ MAD t0, t0, {0.5,0.5,0.5,0}, {0.5,0.5,0.4999999,0}; \n\ ",fp); */ sprintf(fp,"%s\n\ # Access shadow map! \n\ TEX t1, t0, texture[1], 2D;\n\ ",fp); sprintf(fp,"%s\n\ ADD t.z, -t1.z, t0.z; \n\ ",fp); if (do_use_doubleshadow()) sprintf(fp,"%s\n\ CMP t.z, lighting.z, -t.z, t.z; \n\ \n\ ",fp); if ((!do_use_doubleshadow())&&(P_light_base>0)) { sprintf(fp,"%s\n\ CMP t.z, lighting.z, 1, t.z; # if light<0, then in shadow \n\ " ,fp,1.0-P_shadowstrenght); } if (P_shadowstrenght<1) { sprintf(fp,"%s\n\ MUL tmp, lighting, %5.4f; # compute attenuated light \n\ CMP lighting, t.z, lighting, tmp; # if in shadow, then use attenuated light \n\ " ,fp,1.0-P_shadowstrenght); } else sprintf(fp,"%s\n\ CMP lighting, t.z, lighting, 0; # if in shadow, then no light \n\ #CMP result.color, t.z, {0,1,0,0}, {1,0,0,0}; \n\ #\n\ #MAD t0, t0, {0.5,0.5, 200.0,0}, {0.5,0.5,196.5,0}; \n\ #TEX t1, t0, texture[1], 2D;\n\ #MAD t1, t1, 400, -3.5;\n\ #MUL t1, t1.z, {1,0,1,0};\n\ ##ADD t.z, -t1.z, t0.z; \n\ #MAD t0, t0.z, {0,1,0,0}, {0,0,0,0};\n\ #CMP result.color, mat0.x, t1, t0; \n\ #MUL result.color, {0.002,0.002,0,0}, posScreen; \n\ ",fp); }; void CgUtil::addTexturingSnippet(char* fp){ if (P_texture>0) { sprintf(fp,"%s%s",fp,"\n\n\ # texture access \n\ MAD t, t, TNORM, offset; \n\ TEX t, t, texture[0], 2D; \n\n"); if (P_capping) { // overwrite ambient occlusion for close fragments sprintf(fp,"%s\n\ \n\ # lighten OC for close frags \n\ MAD tmp.x, depth.x, -250, 0.50; \n\ CMP tmp.x, tmp.x, 0, tmp.x; \n\ # overwrite OC for cut \n\ CMP tmp.x, depth.x, 0.70, tmp.x; \n\ LRP t, tmp.x, 1, t; \n\ ", fp); } // Add "future" AO prediction (AO not computed yet) // Additive prediction: //sprintf(fp,"%sADD t, t, program.env[6].x;\n", fp ); // multiplicative prediction: sprintf(fp,"%sMUL t, t, program.env[6].x;\n", fp ); sprintf(fp,"%sMAD res, %5.2f, t, res;\n", fp, P_texture ); if (P_phong>0.0) { // weigth phong with AO light. sprintf(fp, "%s\nMUL lighting.y,lighting.y, t;\n", fp); } } float lighting = (!P_sem_effect) ? P_lighting : (1- P_lighting); // apply lighting if ( lighting>0 ) { if (P_sem_effect) { sprintf(fp,"%sMAD lighting.x, lighting.x, -1, 1 ;\n",fp ); // sprintf(fp,"%sMUL lighting.x, lighting.x, lighting.x ;\n",fp ); sprintf(fp,"%s\nMAD lighting.x, %10.8f, lighting.x, %10.8f;\n",fp, lighting, 1-lighting); sprintf(fp,"%sMUL res, lighting.x, res;\n",fp ); } else sprintf(fp,"%s\nMAD res, lighting.x, %f, res;\n",fp, lighting); } if (P_col_atoms_sat>0) { if ((P_col_atoms_sat<1)||(P_col_atoms_bri<1)) { sprintf(fp,"%sMAD tmp, %5.3f, basecol,%5.3f;\n",fp ,P_col_atoms_sat*P_col_atoms_bri, (1.0-P_col_atoms_sat)*P_col_atoms_bri ); sprintf(fp,"%s%s",fp,"MUL res, res, tmp;\n"); } else { sprintf(fp,"%s%s",fp,"MUL res, res, basecol;\n"); } } else { if (P_col_atoms_bri<1.0) { sprintf(fp,"%s%s",fp,"MUL res, res, %5.3f;\n", P_col_atoms_bri ); } } if (writeCol) { if (P_phong>0) { sprintf(fp,"%s%s",fp,"LRP res, lighting.y, 1, res;\n"); } if (writeAlpha) sprintf(fp,"%s%s",fp,"MOV res.w, nor.z;\n"); } // UNUSED: if ( _border_inside()>0 ) { sprintf(fp, "%s \n\ MAD tmp2.z, border.x, %f, 1; \n\ LRP tmp3, tmp2.z, 0, res;\n\ CMP res, -tmp2.z, tmp3, res;\n\ \n", fp, (1.0/_border_inside()) ); }; if ( _border_outside()>0 ) { // Blackens borders: #if (1) // no AA: sprintf(fp,"%sCMP res, -border.x, {0,0,0,0}, res;\n",fp); #else // internal AA: //sprintf(fp,"%sMAD_SAT border.y, -border.x , 10, 1 ;\n",fp); //sprintf(fp,"%sMUL res, border.y, res;\n",fp); #endif } if ( P_fog>0 ) { sprintf(fp,"%sMAD_SAT tmp.x, depth.x, 50, 0;\n",fp); sprintf(fp,"%sMUL tmp.x, tmp.x, %5.4f;\n",fp, P_fog); sprintf(fp,"%sLRP res, tmp.x, {%10.9f,%10.9f,%10.9f,1}, res;\n",fp, P_bg_color_R,P_bg_color_G,P_bg_color_B); } } void CgUtil::addDepthAdjustSnippet(char* fp) { float depth_full=P_depth_full*120.0f; // DEPTH AWARE if ( _border_outside()>0 ) { sprintf(fp, "%s \n\ MUL tmp3.z, -border.x, data.z;\n\ MAD tmp3.z, %8.7f , tmp3.z , fragment.position.z;\n\ CMP depth.x, -border.x, tmp3.z, depth.x;\n\ \n",fp, -depth_full/_border_outside() / 20000.0 //-0.001 ); } if (P_capping) { // //sprintf(fp,"%s%s",fp, "MAD tmp.x, depth.x, 0.001, 10;\n"); //sprintf(fp,"%s%s",fp, "CMP result.depth, depth.x, tmp.x, depth.x;\n"); // sprintf(fp,"%s%s",fp, "ADD result.depth, depth.x, 0.001;\n"); } else { // sprintf(fp,"%s%s",fp, "CMP result.depth, depth.x, 0, depth.x;\n"); sprintf(fp,"%s%s",fp, "MOV result.depth, depth.x;\n"); } sprintf(fp,"%s%s",fp,"MUL res, res, t;\n" ); float lighting = (!P_sem_effect) ? P_lighting : (1- P_lighting); if ((P_capping) && ( (lighting>0) || (P_phong>0) ) ) { sprintf(fp,"%s\n\ # Overwrite capped normal \n\ CMP nor, depth.x, {0,0,1,0}, nor;\n", fp ); } } void CgUtil::addDirectLightingSnippet(char* fp) { /* NOTE: lighting.x = lambert direct (halved if opposite side) lighting.y = phong direct (zeroed if opposite side) lighting.z = lamber original (negative if opposite side) */ float lighting = (!P_sem_effect) ? P_lighting : (1- P_lighting); if (lighting>0) { sprintf(fp,"%s%s",fp, " \n\n\ ## LIGHTING of Normal \n\ DP3 lighting.z, nor, LIGHT; \n\ MUL tmp.y, -lighting.z, 0.35; \n\ CMP lighting.x, lighting.z, tmp.y, lighting.z; \n\n" ); } if (P_phong>0.0) { // phong sprintf(fp, "%s\ ## PHONG \n\ #ADD hwv, {0,0,+1,0}, LIGHT;\n\ #DP3 lighting.y, hwv, hwv;\n\ #RSQ lighting.y, lighting.y;\n\ #MUL hwv, hwv, lighting.y;\n\ DP3 lighting.y, nor, hwv;\n", fp); // compute exponent (TODO: use some sort of EXP funtion) for (int i=0; i<(1.0-P_phong_size)*6.0+3; i++) sprintf(fp,"%sMUL lighting.y, lighting.y, lighting.y;\n", fp); if (P_phong<1.0) sprintf(fp,"%s\nMUL lighting.y,%5.4f,lighting.y;\n", fp, P_phong); } if(P_light_base>0) { sprintf(fp,"%s\nLRP lighting.x,%5.4f, 1, lighting.x; # flatten light \n", fp, P_light_base ); } sprintf(fp,"%s\nMOV res, %5.4f;\n", fp, 0.0 ); } bool CgUtil::shaderHasChanged=false; bool CgUtil::setStickFragmentProgram(){ char fp[10096]; if (shadowmapBuilding) { if (!accurateShadowmapBuilding) sprintf(fp,"\ !!ARBfp1.0 \n\ \n\ MOV result.color, 1;\n\ END\n" ); else sprintf(fp,"\ !!ARBfp1.0 \n\ \n\ ATTRIB data = fragment.texcoord; \n\ MOV result.color, 0.8;\n\ MAD_SAT tmp.x, data.x, -data.x, 1; # tmp.z=1-x^2 \n\ RSQ tmp.x, tmp.x;\n\ RCP n.y, tmp.x;\n\ MAD tmp.z, n.y, data.z, 0; \n\ MAD result.depth, -tmp.z, 0.005, fragment.position.z; \n\ END\n"); glProgramStringARB(GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB, strlen(fp), fp); //printf("\n---------------\n%s",fp); if(!checkProgramError(fp)) return false; return true; } sprintf(fp,"\ !!ARBfp1.0\n\ \n\ ATTRIB data = fragment.texcoord; \n\ ATTRIB normcenter = fragment.texcoord[1];\n\ ATTRIB ROT = fragment.texcoord[2];\n\ ATTRIB offset = fragment.texcoord[3];\n\ ATTRIB normside = fragment.texcoord[4];\n"); if (!P_cyl_const_color) { sprintf(fp,"%s\ ATTRIB col1 = fragment.color.primary;\n\ ATTRIB col2 = fragment.color.secondary;\n",fp); } sprintf(fp,"%s\ PARAM TNORM={%10.9f,%10.9f,0,0}; \n\ PARAM mat0 = program.env[0];\n\ PARAM mat1 = program.env[1];\n\ PARAM mat2 = program.env[2];\n",fp, (moltextureCanvas.GetHardRes()==0)?0:1.0f/moltextureCanvas.GetHardRes(), (moltextureCanvas.GetHardRes()==0)?0:1.0f/moltextureCanvas.GetHardRes() ); if (P_use_shadowmap()) sprintf(fp,"%s\ PARAM Smat0 = program.env[3]; \n\ PARAM Smat1 = program.env[4]; \n\ PARAM Smat2 = program.env[5]; \n\ #PARAM ratio = program.env[6]; \n\ ATTRIB origpos = fragment.texcoord[4]; \n",fp); sprintf(fp,"%s\n\ PARAM LIGHT= state.light[0].position ; \n\ PARAM hwv = state.light[0].half;\n\ \n\ TEMP tmp, nor, n, lighting, res, t, t0, t1, abs, posScreen; \n\ TEMP basecol, border, depth, tmp2, tmp3; \n\ \n\ \n\ MAD_SAT tmp.x, data.x, -data.x, 1; # tmp.z=1-x^2 \n\ RSQ tmp.x, tmp.x;\n\ RCP n.y, tmp.x;\n\ MAD tmp.z, n.y, data.z, 0; \n\ MAD depth.x, -tmp.z, 0.005, fragment.position.z; \n\ \n\ ", fp); if ( (_border_outside()>0 ) ) { sprintf(fp,"%s\n\ #CMP border.x, n.y, n.y, -n.y; \n\ MAD border.x, data.x, data.x, -1; \n\ #ADD border.x, 1, -border.x; \n\ ", fp); } addDepthAdjustSnippet(fp); sprintf(fp,"%s\n\ # Compute normal\n\ MUL nor, n.y, normcenter;\n\ MAD nor, data.x, normside, nor;\n\ ", fp); addDirectLightingSnippet(fp); sprintf(fp,"%s\n\ #TEXTURING ON STICKS \n\ \n\ # FIND X (along axis) \n\ MOV t.x, data.y;\n\ MAD t.x, data.w, n.y, t.x;\n\ # FIND Y (project norm) \n\ MOV n.x, data.x; \n\ \n\ \n\ # rotate (n.x, n.y)\n\ MUL tmp, n, {1,1,0,0};\n\ DP3 n.x, tmp, ROT;\n\ MUL n.y, tmp.x, ROT.y;\n\ MAD n.y, tmp.y, -ROT.x , n.y;\n\ \n\ # find x=FindRoll ( n.x, n.y) \n\ ABS abs, n; \n\ ADD abs.z, abs.x, abs.y; \n\ RCP abs.z, abs.z; \n\ MUL n, n, abs.z;\n\ MAD tmp.x, 0.25, n.y, 0.25;\n\ MAD tmp.y, 0.25,-n.y, 0.75;\n\ CMP t.y, n.x, tmp.x, tmp.y;\n\ \n\ \n\ #KILL OUTLIER FRAGMENTS \n\ CMP t.w, t.x, -t.x, t.x;\n\ ADD t.w, t.w, -1; # w = 1-|x|\n\ KIL -t.w;\n\ ",fp); if (P_use_shadowmap()) { addShadowMapComputationFP(fp); }; if ((P_col_atoms_sat>0) && (P_col_atoms_bri>0)) { if (P_cyl_const_color) sprintf(fp,"%sMOV basecol, {%10.9f,%10.9f,%10.9f,1};\n", fp,P_cyl_const_color_R, P_cyl_const_color_G, P_cyl_const_color_B); else if (P_cyl_smooth_color) { sprintf(fp,"%sMAD t.z, t.x, 0.5,0.5;\n",fp); sprintf(fp,"%sLRP basecol, t.z, col1,col2;\n",fp); } else sprintf(fp,"%sCMP basecol, t.x, col2,col1;\n",fp); } if (P_texture>0) { float sidex=BSIZE, sidey=CSIZE; sprintf(fp,"%s\n\ MAD t, t, {%5.2f, %5.2f, 0,0}, \n\ {%5.2f, %5.2f, 0,0}; \n\ #FRC t, t; \n\ ", fp, (sidex-1)/2.0 , sidey-1.0 , (sidex)/2.0, 0.5); } addTexturingSnippet(fp); sprintf(fp,"%s%s",fp,"ADD result.color, res, {0,0,0,1};\n\n"); sprintf(fp,"%s%s",fp,"END\n"); /*#MOV result.color, n.y;\n\ #MUL tmp.y, data.y, 8;\n\ #FRC result.color.y, tmp.y;\n\ #MOV result.color, fragment.color;\n\ END\n\ ");*/ glProgramStringARB(GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB, strlen(fp), fp); // printf("\n---------------\n%s",fp); if(!checkProgramError(fp)) return false; return true; } bool CgUtil::setStickVertexProgram(){ /* RESULT: TC0 = (corner, ... ) TC1 = NORMAL (on central axis) TC2 = ROTATION of basic point TC3 = TEXTURE OFFSET no! -> TC4 = POSITION of proj. over axis (for shadowmap) TC4 = DIRECTION of normal of side point */ char vp[10096]; sprintf(vp,"\ !!ARBvp1.0\n\ \n\ ATTRIB pos = vertex.position;\n\ \n\ ATTRIB data = vertex.normal;\n\ ATTRIB dire = vertex.texcoord;\n\ ATTRIB startp = vertex.texcoord[1];\n\ \n\ PARAM mat[4] = { state.matrix.mvp };\n\ #PARAM matP[4] = { state.matrix.projection };\n\ PARAM matM[4] = { state.matrix.modelview };\n\ \n\ TEMP p,tmp,tmp2, d,dr, dataout, disp, disp2, norm, normside; \n\ \n\ "); if (P_texture>0) sprintf(vp,"%s\ # pass down texture offest \n\ MOV result.texcoord[3], vertex.texcoord[2];\n\ \n\ ", vp); if ((P_col_atoms_sat>0) && (P_col_atoms_bri>0)) sprintf(vp,"%s\ MOV result.color.primary, vertex.color.primary;\n\ MOV result.color.secondary, vertex.color.secondary;\n\ ",vp); sprintf(vp,"%s\ # Project direction View frame.\n\ DP3 d.x, matM[0], dire;\n\ DP3 d.y, matM[1], dire;\n\ DP3 d.z, matM[2], dire;\n\ \n\ ",vp); sprintf(vp,"%s\ # find k = 1/sqrt(d.x^2+d.y^2) (= tmp.w) \n\ MUL tmp.w, d.x, d.x; \n\ MAD norm.z, d.y, d.y, tmp.w; \n\ RSQ tmp.w, norm.z; \n\ # \n\ # Using orthonormal base B: \n\ # Bx= (+dx,+dy, 0)*k \n\ # By= (-dy,+dx, 0)*k \n\ # Bz= ( 0, 0, 1) \n\ \n\ # now dr = d in B = ( (dx^2+dy^2)*k, 0, dz ) \n\ \n\ ",vp); if (!shadowmapBuilding) sprintf(vp,"%s\ # find normal = ( dr.z*Bx - dr.x*Bz ) = k* (-dx*dz, -dy*dz, dx^2+dy^2)\n\ MUL norm.x, -d.x, d.z;\n\ MUL norm.y, -d.y, d.z;\n\ MUL norm, norm, tmp.w;\n\ \n\ DP3 tmp.x, norm, norm; # normalization, TEMP TEST!\n\ RSQ tmp.x, tmp.x;\n\ MUL norm, norm, tmp.x;\n\ \n\ ",vp); sprintf(vp,"%s\ # radius r (=tmp.z) = Raduis*GlobalScaleFactor \n\ MUL tmp.z, program.env[0].y, program.env[0].x; \n\ \n\ SWZ disp, d, y,-x,0,0; \n\ MUL disp, disp, tmp.w; \n\ MUL disp2, disp, tmp.z; \n\ ### postponed MAD p, data.x, disp2, p; \n\ \n\ MOV dataout, data;\n\ \n\ ",vp); if (!shadowmapBuilding) sprintf(vp,"%s\ # pre-compute Z offset \n\ \n\ # dataout.z = R*(sen*sen/cos+cos) = R*(z*z*k+1/k) \n\ # dataout.z is the z-offset for the center of the cyl \n\ RCP tmp.x , tmp.w;\n\ MUL tmp.y, d.z, d.z;\n\ MAD tmp.y, tmp.y, tmp.w, tmp.x;\n\ MUL dataout.z, program.env[0].y, tmp.y;\n\ # dataout.w = dz/dx \n\ # dataout.w is the y-offset for the center of the cyl \n\ MUL dataout.w, d.z, tmp.w;\n\ MUL dataout.w, dataout.w, dire.w;\n\ MUL dataout.w, dataout.w, program.env[0].z; # (i.e. rad*2)\n\ \n\ ",vp); // Further enlarge impostors at sides to include borders if (_border_outside()!=0) // Compute 'almost' radius and scale indep. border sprintf(vp,"%s\ #MUL tmp.z, program.env[0].y, program.env[0].x; \n\ RSQ tmp.x, tmp.z ;\n\ #MUL tmp.x, tmp.x, tmp.x; # Comment to 'almost'\n\ MUL tmp.x, %7.5f , tmp.x;\n\ ADD tmp.x, tmp.x , 1;\n\ MUL dataout.x, dataout.x, tmp.x ;\n\ ", vp, _border_outside() ); if (!shadowmapBuilding) sprintf(vp,"%s\ # extend cylinder on bottom do deal with ends \n\ MUL tmp.x, -data.y, dataout.w;\n\ SGE tmp.x, tmp.x, 0;\n\ MUL tmp.x, -dataout.w, tmp.x; \n\ ADD dataout.y, dataout.y, tmp.x;\n\ RCP tmp2.x, dire.w; \n\ MUL tmp.x, tmp.x, tmp2.x; \n\ MUL tmp.x, 0.5, tmp.x; \n\ MAD tmp, dire, tmp.x, pos; \n\ ",vp); else sprintf(vp,"%s\ MOV tmp, pos; \n\ ",vp); sprintf(vp,"%s\ \n\ # Project point in View frame.\n\ MOV tmp.w, 1; \n\ DP4 p.x, mat[0], tmp;\n\ DP4 p.y, mat[1], tmp;\n\ DP4 p.z, mat[2], tmp;\n\ DP4 p.w, mat[3], tmp; \n\ \n\ MAD result.position, dataout.x, disp2, p; \n\ ",vp); // Compute normal at side points if (!shadowmapBuilding) sprintf(vp,"%s\ MOV result.texcoord[0], dataout;\n\ MOV result.texcoord[1], norm;\n\ XPD normside, d, norm;\n\ \n\ DP3 tmp.x, normside, normside; # normalization, of normside \n\ RSQ tmp.x, tmp.x;\n\ MUL normside, normside, tmp.x;\n\ \n\ MOV result.texcoord[4], normside;\n\ ",vp); if (P_texture>0) sprintf(vp,"%s\ #ROTATE start vector;\n\ DP3 tmp.x, matM[0], startp;\n\ DP3 tmp.y, matM[1], startp;\n\ DP3 tmp.z, matM[2], startp;\n\ DP3 tmp.w, tmp, tmp;\n\ RSQ tmp.w, tmp.w;\n\ MUL tmp, tmp.w, tmp;\n\ MOV tmp.w, tmp.z;\n\ #MOV tmp.z, 0;\n\ DP3 tmp.x, disp, tmp;\n\ \n\ # cheap way: find an offset to add \n\ # tz=2-tz if tw negative \n\ #SGE tmp.w, 0, -tmp.w; \n\ #MAD tmp.z, tmp.w, -2, 1; \n\ #MUL tmp.x, tmp.z, tmp.x; \n\ #MAD tmp.x, tmp.w, -2, tmp.x; \n\ #MUL result.texcoord[2].x, tmp.x, 0.25;\n\ #\n\ # cool way: store 2D rotation via complex numbers \n\ # tmp.y = sign(tw)*sqrt(1-tmp.x^2)\n\ SGE tmp.w, 0, -tmp.w; \n\ MAD tmp.z, tmp.w, -2, 1; \n\ MAD tmp.w, tmp.x, -tmp.x, 1;\n\ RSQ tmp.w, tmp.w;\n\ RCP tmp.w, tmp.w;\n\ MUL tmp.y, tmp.w, -tmp.z;\n\ \n\ MOV result.texcoord[2], tmp;\n\ ", vp); /* // Not needed if (P_use_shadowmap()) sprintf(vp,"\%s\n\ MOV result.texcoord[4], pos;\n\ ",vp); */ sprintf(vp,"\%s\n\ END\n\ ",vp); glProgramStringARB(GL_VERTEX_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB, strlen(vp), vp); //printf("\n-----------------\n%s",vp); if(!checkProgramError(vp)) return -1; return true; }; bool CgUtil::setBallFragmentProgram(){ CgUtil::shaderHasChanged=true; char fp[10096]; if (shadowmapBuilding) { sprintf(fp,"\ !!ARBfp1.0 \n\ \n\ ATTRIB data = fragment.texcoord; \n\ TEMP tmp; \n\ \n\ MAD tmp.x, data.x, data.x, -1; \n\ MAD tmp.x, data.y, data.y, tmp.x; \n\ KIL -tmp.x;"); if (accurateShadowmapBuilding) sprintf(fp,"%s\ RSQ tmp.x, tmp.x; \n\ RCP tmp.x, tmp.x; \n\ MUL tmp.x, tmp.x, data.z; \n\ MAD result.depth, -tmp.x, 0.005, fragment.position.z;\n" ,fp); sprintf(fp,"\ %sMOV result.color, 1;\n\ END\n",fp); glProgramStringARB(GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB, strlen(fp), fp); //printf("\n---------------\n%s",fp); if(!checkProgramError(fp)) return false; return true; } // ############################ // # # // # FRAGMENT PROGRAM BALL # // # # // ############################ sprintf(fp,"\ !!ARBfp1.0 \n\ \n\ ATTRIB data = fragment.texcoord; \n\ ATTRIB offset = fragment.texcoord[2];\n\ ATTRIB basecol = fragment.color; \n\ "); if (P_use_shadowmap()) sprintf(fp,"%s\ PARAM Smat0 = program.env[3]; \n\ PARAM Smat1 = program.env[4]; \n\ PARAM Smat2 = program.env[5]; \n\ #PARAM ratio = program.env[6]; \n\ ATTRIB origpos = fragment.texcoord[3]; \n\ ",fp); sprintf(fp,"%s\ \n\ TEMP tmp,tmp2,tmp3, t,t0,t1,t2,nor,n,nabs,nsign,disp,res,depth,\n\ lighting, border, posScreen; \n\ PARAM TNORM={%10.9f,%10.9f,0,0}; \n\ \n\ PARAM LIGHT= state.light[0].position ; \n\ PARAM hwv = state.light[0].half;\n\ \n\ PARAM mat[4] = { state.matrix.projection }; \n\ PARAM mat0 = program.env[0];\n\ PARAM mat1 = program.env[1];\n\ PARAM mat2 = program.env[2];\n\ \n", fp, (moltextureCanvas.GetHardRes()==0)?0:1.0f/moltextureCanvas.GetHardRes(), (moltextureCanvas.GetHardRes()==0)?0:1.0f/moltextureCanvas.GetHardRes() ); sprintf(fp,"%s\ MOV nor, data; \n" ,fp); // tentativo prospettiva figa if ((projmode==PERSPECTIVE)&&(proj_figa)) { /* sprintf(fp,"%s\ MAD tmp, fragment.position, {0.00390625, 0.00390625, 0,0}, {-1,-1,0,0}; \n\ DP4 tmp.x, tmp, data; \n\ MUL tmp.x, tmp.x, 0.5; \n\ MAD data.xy, data, tmp.x, data; \n\ " ,fp);*/ } sprintf(fp,"%s\ MUL tmp, data, data; \n\ MOV tmp.z, 1; \n\ DP3 border.x, tmp, {1,1,-1,0}; \n" // border.x = ( (x^2+y^2)-1 ) ,fp); // 1.20*.120 -1 = 0.44 if (_border_outside()>0) { sprintf(fp,"%s\n\n\ ADD tmp2.y, -border.x, data.w; # allow for border (part ii) \n\ #MAD tmp2.y, data.z, -border.x, %7.5f;\n\ #MAD tmp2.y, data.z, tmp2.y, %7.5f;\n\ KIL tmp2.y; \n\ ",fp, -2*_border_outside(), _border_outside()*_border_outside()); } else sprintf(fp,"%s\n\nKIL -border.x; \n",fp); sprintf(fp,"%s\ \n\ RSQ tmp2.y, border.x; \n\ RCP tmp2.x, tmp2.y; \n\ MOV nor.z, tmp2.x; \n\ \n\ MAD tmp2.y, tmp2.x, data.z, 0; # note: add an extra range of 0 \n\ \n", fp); // nor = x, y, z=(1- x^2+y^2) /* if (projmode==PERSPECTIVE) // new_z = old_z / (1/W) + sph_z * W sprintf(fp,"%s%s",fp,"\ MUL tmp2.y, tmp2.y, fragment.position.w; \n\ MAD depth.x, fragment.position.z, data.w, -tmp2.y; # prospettiva: new_z = old_z + 0.005*sph_z\n\ MUL depth.x, depth.x, 0.1; \n\ "); else*/ // new_z = old_z + 0.005*sph_z sprintf(fp,"%s%s",fp, "\ MAD depth.x, -tmp2.y, 0.005, fragment.position.z; # ortho \n\ "); addDepthAdjustSnippet(fp); if ((P_texture>0)|| (P_use_shadowmap())) { sprintf(fp,"%s%s",fp," \n\n\ # rotate normal \n\ DP3 n.x, mat0, nor; \n\ DP3 n.y, mat1, nor; \n\ DP3 n.z, mat2, nor; \n\ MOV n.w, 0; \n\n"); } addDirectLightingSnippet(fp); if (P_use_shadowmap()) { addShadowMapComputationFP(fp); }; if (P_texture>0) { if (textmode==USE_CUBE) sprintf(fp, "%s \n\n\ ## TEXTURING CUBEMAP STYLE \n\ # \n\ # project on cube: find face \n\ CMP nabs, n, -n, n; \n\ MOV t, n; \n\ SWZ t0, t, z,x,y,1; \n\ SWZ t1, t0, z,x,y,-1; \n\ # \n\ SUB t2.x, nabs.z, nabs.y; \n\ CMP t, t2.x, t0, t; \n\ # \n\ CMP t2.z, t.z, -t.z, t.z; \n\ SUB t2.x, t2.z, nabs.x; \n\ CMP t, t2.x, t1, t; \n\ # \n\ # find face \n\ ADD disp.x, t.w, 1; \n\ CMP disp.y, t.z, 0, 1; \n\ # \n\ # divide by max coord \n\ RCP t.z, t.z; \n\ MUL t, t, t.z; \n\ # \n\ # find coords on face \n\ MAD t, t, 0.5, 0.5; \n\ MAD t, t, {%5.2f,%5.2f,0,0}, {%5.2f, %5.2f, 0,0}; \n\ MAD t, {%5.2f,%5.2f,0,0}, disp, t; \n\n", fp, CSIZE-gap*2.0, CSIZE-gap*2.0, gap, gap, CSIZE, CSIZE ); else sprintf(fp, "%s\n\n\ ## TEXTURING OCTAMAP STYLE \n\ # \n\ CMP nabs, n, -n, n; \n\ DP3 tmp.y, {1,1,1,0}, nabs; \n\ RCP tmp.z, tmp.y; \n\ MUL t0, n, tmp.z; \n\ MAD t1, nabs, tmp.z, -1; \n\ # t1= -(1-abs(t)) \n\ CMP t2.x, n.x, t1.y, -t1.y; \n\ CMP t2.y, n.y, t1.x, -t1.x; \n\ CMP t0, n.z, t0, t2; \n\ MAD t, t0, {%5.2f, %5.2f, 0,0}, \n\ {%5.2f, %5.2f, 0,0}; \n\n", fp, CSIZE/2.0 - gap, CSIZE/2.0 - gap, CSIZE/2.0, CSIZE/2.0); } addTexturingSnippet(fp); sprintf(fp,"%s%s",fp,"ADD result.color, res, {0,0,0,1};\n\n"); sprintf(fp,"%s%s",fp,"END\n"); glProgramStringARB(GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB, strlen(fp), fp); //printf("\n---------------\n%s",fp); if(!checkProgramError(fp)) return false; return true; } bool CgUtil::init() { GLenum err=glewInit(); if(err!=GLEW_OK) { sprintf(lasterr,"%s\n",glewGetErrorString(err)); return false; } /* if(!GLEW_ARB_vertex_program || !GLEW_ARB_fragment_program ) { printf("Extension: 'ARB_fragment_program' and/or 'ARB_vertex_program' not supported.\n"); return false; } */ return true; } /* int CgUtil::loadVertexProgram(const char *str) { unsigned int program; checkError(); glGenProgramsARB(1, &program); checkError(); glBindProgramARB(GL_VERTEX_PROGRAM_ARB, program); checkError(); char *text = readFile(str); if(!text) { printf("could not find file %s\n", str); exit(0); } glProgramStringARB(GL_VERTEX_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB, strlen(text), text); if(!checkProgramError(text)) { delete []text; return -1; } delete []text; return program; } int CgUtil::loadFragmentProgram(const char *str) { unsigned int program; glGenProgramsARB(1, &program); checkError(); glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, program); checkError(); char *text = readFile(str); if(!text) { printf("could not find file %s\n", str); exit(0); } char *c=text; while ((*c)!=0) { if ((*c == '(') || (*c == ')') ) *c=' '; if ( *c == '/') *c='#'; c++; } glProgramStringARB(GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB, strlen(text), text); if(!checkProgramError(text)) { delete []text; return -1; } return program; } */ bool CgUtil::checkError() { int error = glGetError(); if(error == GL_NO_ERROR) return true; const char *str; switch(error) { case GL_INVALID_ENUM: str = "Invalid Enum"; break; case GL_INVALID_OPERATION: str = "Invalid Operation"; break; case GL_INVALID_VALUE: str = "Invalid Value"; break; case GL_STACK_OVERFLOW: str = "Stack Overflow"; break; case GL_STACK_UNDERFLOW: str = "Stack Underflow"; break; case GL_OUT_OF_MEMORY: str = "Out of memory"; break; default: str = "Unknown error"; break; } printf("Error %s (%d)\n", str, error); return false; } bool CgUtil::checkProgramError(char *st) { bool res=true; while (1) { int error = glGetError(); if(error == GL_NO_ERROR ) return res; res=false; if(error == GL_INVALID_OPERATION) { GLint errPos; glGetIntegerv( GL_PROGRAM_ERROR_POSITION_ARB, &errPos ); const GLubyte *errString = glGetString( GL_PROGRAM_ERROR_STRING_ARB); fprintf( stderr, "error at position: %d\n[%s]\n", errPos, errString ); fprintf(stderr,"\n\"..."); for (int i=errPos-40; i=0) { if (!st[i]) break; if (i==errPos) fprintf(stderr,"(*)"); fprintf(stderr,"%c", (st[i]=='\n')?'\\':st[i] ); } fprintf(stderr,"...\"\n"); } else { const GLubyte *errString = gluErrorString( error ); fprintf( stderr, "error: [%s]\n", errString ); } } } char *CgUtil::readFile(const char *file) { FILE *fp = fopen(file, "r"); if(!fp) return NULL; char *pippo = new char[1<<18]; int tot = 0; while(1) { int nread = fread(pippo + tot, 1, 1024, fp); tot += nread; if(nread < 1024) { pippo[tot] = '\0'; break; } } fclose(fp); return pippo; } void CgUtil::ShowShaderInfo(int fp){ static GLint i[10],j[10],k[10],h[10]; glGetProgramivARB(fp, GL_MAX_PROGRAM_INSTRUCTIONS_ARB, i); glGetProgramivARB(fp, GL_MAX_PROGRAM_ALU_INSTRUCTIONS_ARB, i+1); glGetProgramivARB(fp, GL_MAX_PROGRAM_TEX_INSTRUCTIONS_ARB, i+2); glGetProgramivARB(fp, GL_MAX_PROGRAM_TEX_INDIRECTIONS_ARB, i+3); glGetProgramivARB(fp, GL_MAX_PROGRAM_TEMPORARIES_ARB, i+4); glGetProgramivARB(fp, GL_MAX_PROGRAM_PARAMETERS_ARB, i+5); glGetProgramivARB(fp, GL_MAX_PROGRAM_ATTRIBS_ARB, i+6); glGetProgramivARB(fp, GL_PROGRAM_INSTRUCTIONS_ARB, j); glGetProgramivARB(fp, GL_PROGRAM_ALU_INSTRUCTIONS_ARB, i+1); glGetProgramivARB(fp, GL_PROGRAM_TEX_INSTRUCTIONS_ARB, j+2); glGetProgramivARB(fp, GL_PROGRAM_TEX_INDIRECTIONS_ARB, j+3); glGetProgramivARB(fp, GL_PROGRAM_TEMPORARIES_ARB, j+4); glGetProgramivARB(fp, GL_PROGRAM_PARAMETERS_ARB, j+5); glGetProgramivARB(fp, GL_PROGRAM_ATTRIBS_ARB, j+6); glGetProgramivARB(fp, GL_PROGRAM_NATIVE_INSTRUCTIONS_ARB, k); glGetProgramivARB(fp, GL_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB, k+1); glGetProgramivARB(fp, GL_PROGRAM_NATIVE_TEX_INSTRUCTIONS_ARB, k+2); glGetProgramivARB(fp, GL_PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB, k+3); glGetProgramivARB(fp, GL_PROGRAM_NATIVE_TEMPORARIES_ARB, k+4); glGetProgramivARB(fp, GL_PROGRAM_NATIVE_PARAMETERS_ARB, k+5); glGetProgramivARB(fp, GL_PROGRAM_NATIVE_ATTRIBS_ARB, k+6); glGetProgramivARB(fp, GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB, h); glGetProgramivARB(fp, GL_MAX_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB, h+1); glGetProgramivARB(fp, GL_MAX_PROGRAM_NATIVE_TEX_INSTRUCTIONS_ARB, h+2); glGetProgramivARB(fp, GL_MAX_PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB, h+3); glGetProgramivARB(fp, GL_MAX_PROGRAM_NATIVE_TEMPORARIES_ARB, h+4); glGetProgramivARB(fp, GL_MAX_PROGRAM_NATIVE_PARAMETERS_ARB, h+5); glGetProgramivARB(fp, GL_MAX_PROGRAM_NATIVE_ATTRIBS_ARB, h+6); char st[10][10]={"Instr","Alu Instr","Tex Instr","Tex Indir","Temp","Param","Attr"}; printf(" %s PROGRAM STATS \n", (fp==GL_FRAGMENT_PROGRAM_ARB)?"FRAGMENT":"VERTEX"); printf(" original | native \n"); printf(" MAX current | MAX current\n"); for (int c=0; c<7; c++) { printf( "%10s %5d %5d | %5d %5d\n",st[c],i[c],j[c],h[c],k[c]); } printf("\n\n"); } qutemol/src/main.rc0000444000175000017500000000142310502547172012666 0ustar mbamba// note that the icon used by the Explorer (i.e. the programs icon) is the // first icon in the executable and the icons are sorted both by their order // (Win9x) and by alphabetically (!) (NT), so put this icon first and give it // a name starting with "a" aaaaaaaa ICON "image/qutemol.ico" sample ICON "image/qutemol.ico" //snap_off2 BITMAP "image/snap_off2.png" //logo BITMAP "image/logo.png" // set this to 1 if you don't want to use manifest resource (manifest resource // is needed to enable visual styles on Windows XP - see docs/msw/winxp.txt // for more information) #define wxUSE_NO_MANIFEST 0 // this is not always needed but doesn't hurt (except making the executable // very slightly larger): this file contains the standard icons, cursors, ... #include qutemol/src/gifSave.h0000444000175000017500000000022210513231336013137 0ustar mbamba class GifWrapper{ public: GifWrapper(); bool AddFrame(Byte* data, int sx, int sy, float dt); bool Save(const char* filename); }; qutemol/src/CubeMapSamp.h0000444000175000017500000001356010462062665013733 0ustar mbamba class CubeMapSamp{ public: static int size; // dim lato static vector map; // mappa 2d di indici a dir static vector dir; // direzioni (uniche!) static vector dirrot; // direzioni ruotate (uniche!) vector sum; // somme (uniche!) vector div; // divisioni (uniche!) static void Transform(Point3f ax, Point3f ay, Point3f az){ for (int i=0; i &t, int s, int tx, int ty){ int nUnique=map.size(); vector dupi(nUnique, -1); for (int y=0; y &t, int s, int tx, int ty, float cr,float cg,float cb){ for (int y=0; y0) { col=(Byte)(sum[i]/div[i]*255); colr=128; } t[k++]= colr; t[k++]= col; t[k++]= col;*/ /* Byte shade=(int)(dir[map[ Index( x , y ) ] ][2] * 255.0); t[k++]= shade; t[k++]= shade; t[k++]= shade; */ //t[k++]= t[k++]= t[k++]= 200; Point3f p=dir[map[ Index( x , y ) ] ]; Point3f q=(p+Point3f(1,1,1))/2.0*255.0; t[k++]= (Byte)(q[0]*cr); t[k++]= (Byte)(q[1]*cg); t[k++]= (Byte)(q[2]*cb); /*int shade=(int)(p*Point3d(0.8,0.6,0)*255.0); if (shade<0) shade=-shade/2; if (shade>255) shade=255; t[k++]= shade; t[k++]= shade; t[k++]= shade;*/ /* float i=255.0*float(map[Index( x , y )])/(size*size*size); t[k++]= (int)i; t[k++]= (int)i; t[k++]= (int)i; int r=0, g=0, b=0; if (y=size*2) g=255; k=(x+(y)*s)*3; t[k++]= t[k++]/2+r/2; t[k++]= t[k++]/2+g/2; t[k++]= t[k++]/2+b/2; */ /* int r=0, g=0, b=0; if (y=size*2) g=255; t[k++]= r; t[k++]= g; t[k++]= b;*/ // printf("%4d ",map[Index( x , y )]); //printf("%3d ",shade); } //printf("\n"); } } static inline int Index(int x, int y){ return x+y*size*3; } static inline int Index3(int x, int y, int z){ return x+y*size+z*size*size; } static inline int I(int x){ return size-1-x; } void Zero(){ int n=dir.size(); sum.resize(n,0); div.resize(n,0); } static void initMap(){ map.resize(size*size*6); int dx=0; int nsampl=size*size*size - (size-2)*(size-2)*(size-2); dir.resize(nsampl); dirrot.resize(nsampl); vector tmpmap(size*size*size); int k=0; for (int z=0; z &t, int s, int tx, int ty){ vector oldvalue(size*size*6); // copy old values for (int y=0; yTH) { sum+=oldvalue[i-dy]; div++; } if ((x%size)!=0) if (oldvalue[i-dx]>TH){ sum+=oldvalue[i-dx]; div++; } if (((y+1)%size)!=0) if (oldvalue[i+dy]>TH){ sum+=oldvalue[i+dy]; div++; } if (((x+1)%size)!=0) if (oldvalue[i+dy]>TH){ sum+=oldvalue[i+dx]; div++; } sum/=div; int k=(x+tx+(y+ty)*s)*3; t[k]=t[k+1]=t[k+2]=sum; } // merge texels int nUnique=map.size(); vector dupi(nUnique, -1); for (int y=0; y map; // mappa 2d di indici a dir static vector dir; // direzioni (uniche!) static vector dirrot; // direzioni ruotate (uniche!) vector sum; // somme (uniche!) vector div; // divisioni (uniche!) static int size; void Shade(){ //col.resize(dir.size()); /*for (int i=0; i1) col[i]=1; }*/ } static inline int nsamp(){ return dir.size(); } // duplicates those texels that are already douplicated void DuplicateTexels(vector &t, int s, int tx, int ty){ int e=size-1; // the end // four corners int k0=(tx+ (ty )*s)*3; int k1=(tx+e+(ty )*s)*3; int k2=(tx+e+(ty+e)*s)*3; int k3=(tx+ (ty+e)*s)*3; t[k0 ]=t[k1 ]=t[k2 ]=t[k3 ]; t[k0+1]=t[k1+1]=t[k2+1]=t[k3+1]; t[k0+2]=t[k1+2]=t[k2+2]=t[k3+2]; // sides for (int i=1; i &t, int s, int tx, int ty, float cr,float cg,float cb){ for (int y=0; y255) shade=255; t[k++]= shade; t[k++]= shade; t[k++]= shade;*/ /* float i=255.0*float(map[Index( x , y )])/(size*size*size); t[k++]= (int)i; t[k++]= (int)i; t[k++]= (int)i; int r=0, g=0, b=0; if (y=size*2) g=255; k=(x+(y)*s)*3; t[k++]= t[k++]/2+r/2; t[k++]= t[k++]/2+g/2; t[k++]= t[k++]/2+b/2; */ /* int r=0, g=0, b=0; if (y=size*2) g=255; t[k++]= r; t[k++]= g; t[k++]= b;*/ // printf("%4d ",map[Index( x , y )]); //printf("%3d ",shade); } //printf("\n"); } } inline static int Index(int x, int y){ return x+y*size; } inline static float sign(float x){ return (x<0)?-1:+1; } inline static float Abs(float x){ return (x<0)?-x:+x; } void Zero(){ int n=dir.size(); sum.resize(n,0); div.resize(n,0); } // smoothing of an octamap! void Smooth(vector &t, int s, int tx, int ty){ vector oldvalue(size*size*6); // copy old values for (int y=0; yTH) {sum+=w; ddiv++; } if (x!=0) w=oldvalue[i-dx]; else w=oldvalue[ Index( 1 , e-y ) ]; if(w>TH) {sum+=w; ddiv++; } if (y!=e) w=oldvalue[i+dy]; else w=oldvalue[ Index( e-x ,e-1 ) ]; if(w>TH) {sum+=w; ddiv++; } if (x!=e) w=oldvalue[i+dx]; else w=oldvalue[ Index( e-1 , e-y ) ]; if(w>TH) {sum+=w; ddiv++; } sum=(sum+ddiv/2)/ddiv; int k=(x+tx+(y+ty)*s)*3; t[k]=t[k+1]=t[k+2]=sum; } } // smoothing of an octamap! void Smooth(vector &t, int s, int tx, int ty){ vector oldvalue(size*size*6); // copy old values for (int y=0; yTH) {sum+=w; ddiv++; } if (x!=0) w=oldvalue[i-dx]; else w=oldvalue[ Index( 1 , e-y ) ]; if(w>TH) {sum+=w; ddiv++; } if (y!=e) w=oldvalue[i+dy]; else w=oldvalue[ Index( e-x ,e-1 ) ]; if(w>TH) {sum+=w; ddiv++; } if (x!=e) w=oldvalue[i+dx]; else w=oldvalue[ Index( e-1 , e-y ) ]; if(w>TH) {sum+=w; ddiv++; } sum=(sum+ddiv/2)/ddiv; int k=(x+tx+(y+ty)*s); t[k]=sum; } } static void SetSize(int _size){ size=_size; initMap(); ComputeWeight(); } static Point3f getDir(float x, float y){ float fs=float(size)-1; Point3f p(x*2/fs-1,y*2/fs-1,0); float ax=Abs(p[0]), ay=Abs(p[1]), az=+1; if (ax+ay>1.0) { p=Point3f( sign(p[0])*(1-ay), sign(p[1])*(1-ax), 0); az=-1; } p[2]=(1-ax-ay)*az; p.Normalize(); return p; } static void initMap(){ dir.resize(size*size); for (int y=0; y weight; static float Area(Point3f a, Point3f b, Point3f c){ return Abs( ((b-a)^(c-a)).Norm()*0.5 ); } static void ComputeWeight(){ weight.resize(size*size); for (int y=0,k=0; y &texture, const vector &sumtable, int texsize, float div, int tx, int ty ); OctaMapSamp(){ } }; qutemol/src/saveSnapDialog.h0000444000175000017500000000064210542044036014462 0ustar mbamba class savesnapDialog:public wxDialog{ public: savesnapDialog( wxWindow* parent, int mode // 0 PNG 1 JPG 2 GIF, ); void OnTextCtrl(wxCommandEvent & event); void OnRadioButton(wxCommandEvent & event); void OnButton(wxCommandEvent & event); void OnCheckBox(wxCommandEvent & event); void OnText(wxCommandEvent & event); bool TransferDataFromWindow(); DECLARE_EVENT_TABLE() }; qutemol/src/progress.cpp0000444000175000017500000000107710542044036013764 0ustar mbamba#include "wx/wxprec.h" #include #include "progress.h" wxProgressDialog *globalProgress=NULL; bool UpdateProgress(int i){ bool res=globalProgress->Update(i); if (!res) EndProgress(); return res; } void StartProgress(char* str, int N){ EndProgress(); wxString st; st.Printf("QuteMol: %s...",str); globalProgress= new wxProgressDialog( //_T("QuteMol"), st, st, _T(""), N, NULL, wxPD_AUTO_HIDE|wxPD_APP_MODAL|wxPD_CAN_ABORT); } void EndProgress(){ if (globalProgress) { globalProgress->Destroy(); globalProgress=NULL; } } qutemol/src/saveSnapDialog.cpp0000444000175000017500000002454610634153055015032 0ustar mbamba#ifndef WX_PRECOMP #include #endif #include #include "SaveSnapDialog.h" #include "HardSettings.h" enum{ ID_ResUp=500, ID_ResDown, ID_Res, ID_AntiAlias, ID_Alpha}; static wxString title[]={"PNG snapshot options","JPG snapshot options","GIF animation options"}; static wxTextCtrl * resText; static wxCheckBox *wxCheckAntia, *wxTransp ; class EventTableEntry{ public: int* data; int tmpdata; int idButMore,idButLess, idText, idCheck, idRadio; int max, min; int delta; bool pow2; int valueIfChecked; wxTextCtrl *text; wxCheckBox *chkbox; wxRadioButton *radio; wxSizer* sizer; wxStaticText* label; wxButton* bm; wxButton* bl; wxRadioButton *enableif; EventTableEntry(){ text=NULL; chkbox=NULL; sizer=NULL; label=NULL; bm=bl=NULL; radio=NULL; idButMore=idButLess=idText=idCheck=idRadio=-1; delta=1; enableif=NULL; } void Enable(){ if (enableif) { bool b=enableif->GetValue(); if (chkbox) chkbox->Enable(b); if (text) text->Enable(b); if (radio) radio->Enable(b); if (label) label->Enable(b); if (bm) bm->Enable(b); if (bl) bl->Enable(b); } } void CheckBounds(){ if (tmpdata>max) tmpdata=max; if (tmpdataSetValue(st); } void More(){ if (pow2) tmpdata*=2; else tmpdata=((tmpdata)/delta)*delta+delta; CheckBounds(); } void Less(){ if (pow2) tmpdata/=2; else tmpdata=((tmpdata+delta-1)/delta)*delta-delta; CheckBounds(); } void Transfer(){ if (data) { if (radio) { if (radio->GetValue()) *data=valueIfChecked; } else *data=tmpdata; } } void SetRadioButton(){ tmpdata=valueIfChecked; } void SetCheck(){ tmpdata=chkbox->GetValue(); } void SetFromText(){ wxString st=text->GetValue(); long int tmp; if (st.ToLong(&tmp)) tmpdata=tmp; } void SetValue(){ //tmpdata=text->GetValue().ScanF(); CheckBounds(); } void Init(){ tmpdata=*data; if (chkbox) chkbox->SetValue(tmpdata); if (text){ wxString st;st.Printf(_T("%d"),tmpdata); if (text) text->SetValue(st); }; if (radio) radio->SetValue(tmpdata==valueIfChecked); } }; int newID(int i=-1){ static int k; if (i!=-1) k=i; return k++; } class EventTable { enum {MAX=100}; wxWindowID id[MAX]; wxRadioButton *enableif, *lastRadio; public: std::vector data; static wxSizer * sizer; static wxDialog* parent; EventTable(){} void Clear(){ data.clear(); newID(500); enableif=lastRadio=NULL; } bool EndEnableGroup(){ enableif=NULL; } bool StartEnableGroup(){ enableif=lastRadio; } bool pressButton(wxWindowID x){ for (int i=0; iAdd( e.label, 1, wxALIGN_RIGHT|wxALIGN_BOTTOM); sizer->Add( e.chkbox, 1, wxALIGN_LEFT|wxALIGN_BOTTOM); data.push_back(e); } void AddNewRadio(wxString label, int *dataz, int value){ EventTableEntry e; e.idRadio=newID(); e.label=new wxStaticText(parent, -1, label ); e.radio=new wxRadioButton(parent, e.idRadio, _T("") ); e.data=dataz; e.valueIfChecked=value; e.enableif=enableif; e.Init(); lastRadio=e.radio; sizer->Add( e.label, 1, wxALIGN_RIGHT|wxALIGN_BOTTOM); sizer->Add( e.radio, 1, wxALIGN_LEFT|wxALIGN_BOTTOM); data.push_back(e); //checkButton but=new } void AddNewInt(wxString label, int *dataz, int min, int max, bool pow2=false, int delta){ EventTableEntry e; e.idText=newID(); e.idButLess=newID(); e.idButMore=newID(); e.label=new wxStaticText(parent, -1, label ); e.bl=new wxButton(parent, e.idButLess, _T("-"),wxDefaultPosition, wxSize(32, 16) ); e.bm=new wxButton(parent, e.idButMore, _T("+"),wxDefaultPosition, wxSize(32, 16) ); e.text=new wxTextCtrl(parent, e.idText, _T(""), wxDefaultPosition, wxSize(50,wxDefaultSize.y), (pow2)?wxTE_READONLY:0 ); e.pow2=pow2; e.min=min; e.max=max; e.data=dataz; e.delta=delta; e.enableif=enableif; e.Init(); e.sizer=new wxBoxSizer(wxHORIZONTAL); e.sizer->Add( e.bl,0,wxALIGN_BOTTOM); e.sizer->Add( e.text,0,wxALIGN_BOTTOM); e.sizer->Add( e.bm,0,wxALIGN_BOTTOM); sizer->Add( e.label, 1, wxALIGN_RIGHT|wxALIGN_BOTTOM); sizer->Add( e.sizer, 1, wxALIGN_LEFT|wxALIGN_BOTTOM); data.push_back(e); } }; static EventTable eventt; wxSizer * EventTable::sizer = NULL; wxDialog* EventTable::parent =NULL; void savesnapDialog::OnRadioButton(wxCommandEvent & event){ eventt.pressRadioButton( event.GetId() ); eventt.Enable(); } void savesnapDialog::OnCheckBox(wxCommandEvent & event){ eventt.pressCheck( event.GetId() ); eventt.Enable(); } void savesnapDialog::OnText(wxCommandEvent & event){ eventt.insertText( event.GetId() ); } void savesnapDialog::OnButton(wxCommandEvent & event){ int jj=event.GetId(); if (jj==wxID_CANCEL) { m_returnCode=jj; EndDialog(jj); } else if (jj==wxID_OK) { m_returnCode=jj; AcceptAndClose(); } else { if (!eventt.pressButton( jj )) eventt.Enable(); } //EmulateButtonClickIfPresent(jj); // ARGH! savesnapDialog::OnButton(event) should be protected, NOT private! // redoing it } savesnapDialog::savesnapDialog( wxWindow* parent , int style ):wxDialog(parent,-1,title[style],wxDefaultPosition,wxSize(100,100) ) { wxSizer *top=new wxBoxSizer(wxVERTICAL); wxSizer *upper=new wxGridSizer(0,2,6,6); /* wxSizer *res=new wxBoxSizer(wxHORIZONTAL); res->Add( new wxButton(this, ID_ResDown, _T("-"), wxDefaultPosition, butSize ),0,wxALIGN_BOTTOM); resText=new wxTextCtrl(this, ID_Res, _T("1024"), wxDefaultPosition, textSize, wxTE_READONLY ); res->Add( resText, 1, wxALIGN_BOTTOM ); res->Add( new wxButton(this, ID_ResUp, _T("+"), wxDefaultPosition, butSize ),0,wxALIGN_BOTTOM); upper->Add( new wxStaticText(this, -1, _T("Resolution:") ), 1, wxALIGN_RIGHT|wxALIGN_BOTTOM); upper->Add(res,1,wxALIGN_LEFT|wxALIGN_BOTTOM); */ eventt.Clear(); EventTable::sizer=upper; EventTable::parent=this; eventt.AddNewInt( _T("Resolution:"), ((style!=2))? &hardSettings.SNAP_SIZE : &hardSettings.GIF_SNAP_SIZE, 32, 1<<13, true,1); eventt.AddNewCheck( _T("AntiAlias:"), &hardSettings.SNAP_ANTIALIAS ); if (style==0) // png { eventt.AddNewCheck( _T("Transparent PNG:"), &hardSettings.PNG_TRANSPARENT ); } wxSizer *mid=NULL; if (style==2) // gif { eventt.AddNewInt( _T("Initial Pause (ms):"), &hardSettings.GIF_INITIAL_PAUSE, 000, 10000, false, +1000 ); //upper->Add(0,0);upper->Add(0,0); wxSizer *mode1s=new wxFlexGridSizer(0,2,6,6); EventTable::sizer=mode1s; eventt.AddNewRadio( _T("Full rotation mode:"), &hardSettings.GIF_ANIMATION_MODE, 0); eventt.StartEnableGroup(); eventt.AddNewInt( _T("Rotation Time (ms):"), &hardSettings.GIF_ROT_MSEC, 500, 10000, false, +500 ); eventt.AddNewInt( _T("Frames:"), &hardSettings.GIF_ROT_N_FRAMES, 10, 1000, false, +5 ); eventt.AddNewInt( _T("View angle (deg):"), &hardSettings.GIF_ROT_SIDEVIEW_ANGLE, -45, +45, false, +5 ); eventt.EndEnableGroup(); //upper->Add(0,0);upper->Add(0,0); wxSizer *mode2s=new wxFlexGridSizer(0,2,6,6); EventTable::sizer=mode2s; eventt.AddNewRadio( _T("Inspection mode:"), &hardSettings.GIF_ANIMATION_MODE, 1); eventt.StartEnableGroup(); eventt.AddNewInt( _T("Rotation Time (ms):"), &hardSettings.GIF_INSP_MSEC, 500, 10000, false, +500 ); eventt.AddNewInt( _T("Frames:"), &hardSettings.GIF_INSP_N_FRAMES, 10, 1000, false, +5 ); eventt.AddNewInt( _T("Angle (deg):"), &hardSettings.GIF_INSP_ANGLE, 5, 35, false, +5 ); eventt.EndEnableGroup(); //upper->Add(0,0);upper->Add(0,0); wxSizer *mode3s=new wxFlexGridSizer(0,2,6,6); EventTable::sizer=mode3s; eventt.AddNewRadio( _T("Six-Sides mode:"), &hardSettings.GIF_ANIMATION_MODE, 2); eventt.StartEnableGroup(); eventt.AddNewInt( _T("Time x Side (ms):"), &hardSettings.GIF_6SIDES_MSEC, 200, 2000, false, +100 ); eventt.AddNewInt( _T("Frames x Side:"), &hardSettings.GIF_6SIDES_N_FRAMES, 10, 200, false, +1 ); eventt.AddNewInt( _T("Pause x Side (ms):"), &hardSettings.GIF_6SIDES_PAUSE, 500, 10000, false, +250 ); eventt.EndEnableGroup(); mid=new wxBoxSizer(wxHORIZONTAL); mid->Add(mode1s,1,wxLEFT,10); mid->Add(mode2s,1,wxLEFT,10); mid->Add(mode3s,1,wxLEFT|wxRIGHT,10); //int GIF_SIDEVIEW_ANGLE; //int GIF_INSPECTION_ANGLE; //int GIF_PAUSE; } top->Add( upper, 0, wxALIGN_CENTER|wxALL, 20 ); if (mid) top->Add( mid ); top->Add( CreateSeparatedButtonSizer(wxOK|wxCANCEL), 0, wxALIGN_CENTER |wxALL, 20 ); SetSizerAndFit(top); eventt.Enable(); } bool savesnapDialog::TransferDataFromWindow(){ eventt.transfer(); return true; } BEGIN_EVENT_TABLE(savesnapDialog, wxDialog) EVT_RADIOBUTTON(-1, savesnapDialog::OnRadioButton) EVT_BUTTON(-1, savesnapDialog::OnButton) EVT_CHECKBOX(-1, savesnapDialog::OnCheckBox) EVT_TEXT(-1, savesnapDialog::OnText) //EVT_BUTTON(ID_ChooseBallnstickConstantcolor, MyTab::OnChooseBallnstickConstantcolor) //EVT_COMMAND_SCROLL(ID_SetLicoriceRadius, MyTab::OnSetLicoriceRadius) //EVT_COMMAND_SCROLL(ID_SetBallnstickRadius, MyTab::OnSetBallnstickRadius) END_EVENT_TABLE() qutemol/src/ShadowMap.h0000444000175000017500000000137010506615341013447 0ustar mbamba extern bool validView(Point3f p); class ShadowMap{ //private: public: Mol &m; public: void computeAsTexture(vcg::Point3f L, bool makeboth, MyCanvas &canvas); bool init(); bool initHalo(); // adapt to current PVMatrix static void ShadowMap::GetCurrentPVMatrix(); // feed parametmers to FP static void FeedParameters(); static void Update(); ShadowMap(Mol &_m) : m( _m ){ } }; class AOgpu2{ public: static bool init(); static void Reset(Mol &m); static void Bind(); AOgpu2( Point3f _dir, Mol &m, int nviews); static void UnBind(); }; //extern unsigned int finalFrame; // frame dove metto l'immagine finale! 0 se lo schermo. //bool createOffsetFrame(uint &frameID, uint &textureID, int screensize, int flags); qutemol/src/MyTab.h0000444000175000017500000000244310515434600012577 0ustar mbamba /* Define a new application type */ class MyTab: public wxPanel{ public: MyTab(wxWindow *parent , int i); // constructor for i-th tab static wxWindow *frame2redraw; static void SceneChanged(); static bool Redispose(int wy); static int Count(); // number of tabs static wxString Title(int i); // title of i-th tab static void EnableGeom(); static void EnableCustom(); void emphCurrentPreset(int i); /* Geometry TAB */ /*--------------*/ /* void OnSetBallnstick (wxCommandEvent & event); void OnSetLicorice (wxCommandEvent & event); void OnSetSpacefill (wxCommandEvent & event); void OnSetLicoriceRadius(wxScrollEvent & event); void OnSetBallnstickRadius(wxScrollEvent & event); void OnSetBallnstickSmoothcolor(wxCommandEvent & event); void OnSetBallnstickBicolor(wxCommandEvent & event); void OnSetBallnstickConstantcolor(wxCommandEvent & event);*/ void OnRadioButton(wxCommandEvent & event); //void OnChooseBallnstickConstantcolor(wxCommandEvent & event); static void setSceneBgcolor(wxColor c); void setSceneBgbrightness(float f); // ALL: void OnSlider(wxScrollEvent & event); void OnButton(wxCommandEvent & event); void OnCheckBox(wxCommandEvent & event); static void UpdateAll(); DECLARE_EVENT_TABLE() }; qutemol/src/MyTab.cpp0000444000175000017500000011346510634443333013146 0ustar mbamba#ifndef WX_PRECOMP #include "wx/wx.h" #endif //#include "wx/artprov.h" #include /* #include #include #include #include */ //#include #include #include "MyTab.h" #include "CgUtil.h" #include "Common.h" #include #include #include const float MAX_BLEND = 0.25; // maximal blend factor for colors (when per chain) // GEOM TAB //////////// enum{ ID_SetBallnstick=500, ID_SetSpacefill, ID_SetLicorice, ID_SetLicoriceRadius, ID_SetBallnstickRadius, ID_SetBallnstickSmoothcolor,ID_SetBallnstickBicolor, ID_SetBallnstickConstantcolor, ID_ChooseBallnstickConstantcolor,ID_SetFog, ID_SetHetatm, ID_ChooseBgcolor, ID_ChooseHAcolor, ID_SetBgbrightness, ID_SetBaseColorSat, ID_SetBaseColorBri, ID_SetShine, ID_SetShineSize, ID_SetLight, ID_SetLightBase, ID_SetHalo, ID_SetAO, ID_SetHaloStr, ID_SetHaloAware, ID_SetAutobalance, // atom colors ID_SetColorPerChain, ID_SetColorPerAtom, ID_ChangeColorSchema, ID_SetColorBlend, // ID_SetShadow, ID_SetShadowStr, ID_SetSem, ID_SetDoubleShadows, ID_SetBorderFixed, ID_SetBorderVariable, ID_SetBorderDepthAware, ID_WebButton, ID_FirstPreset, } ID; static wxRadioButton *buttonSetLicorice, *buttonSetSpacefill, *buttonSetBallnstick, *buttonSetColorPerChain, *buttonSetColorPerAtom ; static wxRadioButton *buttonSetBallnstickBicolor, *buttonSetBallnstickConstantcolor, *buttonSetBallnstickSmoothcolor; static wxString qutemolwebsite=_T("http://qutemol.sourceforge.net/"); static wxColor colDisabled, colSticks, colBg(255,255,255); static float bgbrightness=0.5; // why not? :-( //#include //static wxColourPickerCtrl *buttonChooseBallnstickConstantcolor; // fall back: static wxButton *buttonChooseBallnstickConstantcolor; static wxButton *buttonChooseBgcolor; static wxButton *buttonChooseHAcolor; static wxButton *buttonChangeColorSchema; static wxCheckBox *buttonAutobalance; static wxCheckBox *buttonDoubleShadows; static wxCheckBox *buttonSem; static wxCheckBox *buttonSetHetatm; static wxSlider *sliderLicorice, *sliderBallnstick, *sliderSetBaseColor , *sliderShineSize, *sliderAwaren , *sliderSetBgbrightness, *sliderLightBase, *sliderLighting, *sliderAO, *sliderShadowStr,*sliderHaloAware, *sliderHaloSize, *sliderHaloStr,*sliderColorBlend; static wxStaticText *textLicorice, *textBallnstick, *textShadowStr, *textBallnstick2, *textShineSize, *textDoubleShadows, *textAwaren, *textSem, *textLightBase, *textSetHetatm, *textHaloSize, *textHaloStr, *textHaloAware, *textHaloColor, *textColorBlend; static wxColor normalButtonBg; static wxColor currentButtonBg; const int NPreset=15; static wxButton* preset[NPreset]; static char* presetFile[NPreset] = { "presets//real.preset", "presets//real2.preset", "presets//direct.preset", "presets//illustr.preset", "presets//illustr_new.preset", "presets//illustr_motm.preset", "presets//qutemol1.preset", "presets//qutemol2.preset", "presets//qutemol3.preset", "presets//coolb.preset", "presets//coold.preset", "presets//borders_cool.preset", "presets//sem.preset", "presets//sem2.preset", "presets//shape.preset", }; static wxString presetName[NPreset]={ _T("Realistic\n1"), _T("Realistic\n2"), _T("Direct\nLight Only"), _T("Illustr-\native 1"), _T("Illustr-\native 2"), _T("Molecule of\nthe Month"), _T("Mixed 1"), _T("Mixed 2"), _T("Mixed 3"), _T("Cool\n(bright)"), _T("Cool\n(dark)"), _T("Cool\nborders"), _T("Simulated\nS.E.M. 1"), _T("Simulated\nS.E.M. 2"), _T("Shape\nPerception"), }; static bool presetEndOfLine[NPreset] = { false, true, true, false, true, true, false, false, true, false, true, true, false, true, true }; Byte f2b(float x){ return (Byte)(x*255.0); } float b2f(Byte x){ return ((float)x)/255.0; } // quick hack class SliderTable { enum {MAX=100}; int n; wxWindowID id[MAX]; public: float* data[MAX]; wxSlider* slider[MAX]; SliderTable(){n=0;} void Add(wxWindowID x, float* y, wxSlider* w){ if (nSetValue(int( (*data[i]*100.0) ) ); } } } sliderTable; class ButtonTable { enum {MAX=100}; int n; wxWindowID id[MAX]; public: bool* data[MAX]; wxCheckBox* chk[MAX]; ButtonTable(){n=0;} void Add(wxWindowID x, bool* y, wxCheckBox* w){ if (nSetValue(*(data[i])); } } } buttonTable; wxWindow *MyTab::frame2redraw; bool doAutobalance(int lastChanged){ if (buttonAutobalance->GetValue()) { float* a[2]; //a[0]=&cgSettings.P_light_base; a[0]=&cgSettings.P_lighting; a[1]=&cgSettings.P_texture; wxSlider* s[2]; //s[0]=sliderLightBase; s[0]=sliderLighting; s[1]=sliderAO; int fixed=-1; switch (lastChanged){ //case ID_SetLightBase:fixed=0; break; case ID_SetLight:fixed=0; break; case ID_SetAO:fixed=1; break; } float sum=0, sump=0; for (int i=0; i<2; i++) { sum+=*(a[i]); if (i==fixed) sump+=*(a[i]); } if (fixed==-1) { if (sum!=0) for (int i=0; i<2; i++) { *(a[i])/=sum; s[i]->SetValue( (int)((*a[i])*100.0) ); } } else { for (int i=0; i<2; i++) if (i!=fixed) { *(a[i])=1-sump; s[i]->SetValue( (int)((*a[i])*100.0) ); } } } return false; } void MyTab::OnSlider(wxScrollEvent & event){ wxWindowID id=event.GetId(); if ( (id==ID_SetHalo) || (id==ID_SetHaloStr) ) cgSettings.ResetHalo(); switch ( id ) { case ID_SetLicoriceRadius: { geoSettings.SetLicoRadiusPercentage( sliderLicorice->GetValue() ); geoSettings.Apply(); SceneChanged(); break; } case ID_SetBallnstickRadius: { geoSettings.SetStickRadiusPercentage( sliderBallnstick->GetValue() ); geoSettings.Apply(); SceneChanged(); break; } case ID_SetColorBlend: { SetColMode( sliderColorBlend->GetValue()*0.01f* MAX_BLEND ); SceneChanged(); break; } default: int i=sliderTable[id]; if (i!=-1) { float k=(sliderTable.slider[i]->GetValue())/100.0; *sliderTable.data[i]=k; //if ((id==ID_SetAO) && (k>0)) mol.ShowingAO=false; if (id==ID_SetBgbrightness) { setSceneBgbrightness(bgbrightness); } doAutobalance(id); cgSettings.UpdateShaders(); SceneChanged(); //geoSettings.Apply(); EnableCustom(); } //else wxWindow::OnScroll(event); // default actions. } } void MyTab::OnRadioButton(wxCommandEvent & event){ int id=event.GetId(); switch ( id ) { case ID_SetBallnstick: geoSettings.mode=GeoSettings::BALL_N_STICKS; geoSettings.Apply(); break; case ID_SetLicorice: geoSettings.mode=GeoSettings::LICORICE; geoSettings.Apply(); break; case ID_SetSpacefill: geoSettings.mode=GeoSettings::SPACE_FILL; geoSettings.Apply(); break; case ID_SetBallnstickSmoothcolor: geoSettings.use_stick_const_color=false; geoSettings.stick_smooth_color=true; geoSettings.ApplyColor(); break; case ID_SetBallnstickBicolor: geoSettings.use_stick_const_color=false; geoSettings.stick_smooth_color=false; geoSettings.ApplyColor(); break; case ID_SetBallnstickConstantcolor: geoSettings.use_stick_const_color=true; geoSettings.ApplyColor(); break; case ID_SetColorPerChain: SetColMode(sliderColorBlend->GetValue()*0.01f* MAX_BLEND ); SceneChanged(); break; case ID_SetColorPerAtom: SetColMode(1); SceneChanged(); break; } EnableGeom(); } void MyTab::OnCheckBox(wxCommandEvent & event){ int id=event.GetId(); int i=buttonTable[id]; switch ( id ) { case ID_SetAutobalance: if (doAutobalance(ID_SetAutobalance)) { SceneChanged(); cgSettings.UpdateShaders(); } break; case ID_SetHetatm: geoSettings.Apply(); break; case ID_SetDoubleShadows: UpdateShadowmap(); break; } if (i!=-1) { bool k=(buttonTable.chk[i]->GetValue()); *buttonTable.data[i]=k; cgSettings.UpdateShaders(); SceneChanged(); EnableCustom(); } } void MyTab::OnButton(wxCommandEvent & event){ wxColourDialog* dialog; wxColourData data; int id=event.GetId(); switch ( id ) { case ID_ChangeColorSchema: ChangeColorSchema(); ResetColMode(); SceneChanged(); break; case ID_WebButton: if (!wxLaunchDefaultBrowser(qutemolwebsite)) { wxMessageBox(_T("Browser, browser,\nwhere art thou?"), _T(":-("), wxOK | wxICON_EXCLAMATION, this); } break; case ID_ChooseBallnstickConstantcolor: data.SetChooseFull(true); data.SetCustomColour(0, colBg ); data.SetColour(colSticks); dialog=new wxColourDialog(this,&data); dialog->SetTitle(_T("Choose stick color:")); if (dialog->ShowModal() == wxID_OK) { colSticks = dialog->GetColourData().GetColour(); geoSettings.stick_const_color_R=b2f(colSticks.Red()); geoSettings.stick_const_color_G=b2f(colSticks.Green()); geoSettings.stick_const_color_B=b2f(colSticks.Blue()); buttonChooseBallnstickConstantcolor->SetBackgroundColour(colSticks); geoSettings.ApplyColor(); SceneChanged(); } break; case ID_ChooseHAcolor: { cgSettings.P_halo_col=1.0*(cgSettings.P_halo_col!=1); int k=(int)(cgSettings.P_halo_col*255.0); buttonChooseHAcolor->SetBackgroundColour(wxColor(k,k,k)); cgSettings.ResetHalo(); cgSettings.UpdateShaders(); SceneChanged(); } break; case ID_ChooseBgcolor: data.SetChooseFull(true); data.SetCustomColour(0, colBg); data.SetColour(colBg); dialog=new wxColourDialog(this,&data); dialog->SetTitle(_T("Choose background color:")); if (dialog->ShowModal() == wxID_OK) { setSceneBgcolor(dialog->GetColourData().GetColour()); cgSettings.UpdateShaders(); SceneChanged(); } break; default: int pid=id-ID_FirstPreset; if ( (pid>=0) && (pidSetForegroundColour(normalButtonBg); else preset[i]->SetForegroundColour(currentButtonBg); } */ // preset[j]->Press(); } void MyTab::setSceneBgcolor(wxColor c){ float r=b2f(c.Red()), g=b2f(c.Green()), b=b2f(c.Blue()); float max=(rSetBackgroundColour(c); sliderSetBgbrightness->SetValue(int(bgbrightness*100)); } wxColor col(float r, float g, float b){ wxColor c( Byte(r*255.0), Byte(g*255.0), Byte(b*255.0)); return c; } wxColor col(float r){ return col(r,r,r); } void MyTab::setSceneBgbrightness(float br){ bgbrightness=br; float r=colBg.Red()*bgbrightness/255.0, g=colBg.Green()*bgbrightness/255.0, b=colBg.Blue()*bgbrightness/255.0; //if (r+b+g<0.01) r=g=b=bgbrightness/255.0; cgSettings.P_bg_color_R=r; cgSettings.P_bg_color_G=g; cgSettings.P_bg_color_B=b; buttonChooseBgcolor->SetBackgroundColour( col(r,g,b) ); } void MyTab::EnableCustom(){ bool b=(cgSettings.P_phong>0); sliderShineSize->Enable(b); textShineSize->Enable(b); b=(cgSettings.P_border_outside>0); sliderAwaren->Enable(b); textAwaren->Enable(b); b=(cgSettings.P_lighting>0)||(cgSettings.P_phong>0); textShadowStr->Enable(b); sliderShadowStr->Enable(b); b=(cgSettings.P_lighting>0); textLightBase->Enable(b); sliderLightBase->Enable(b); b=( cgSettings.can_use_doubleshadow() ); if (!b) buttonDoubleShadows->SetValue(false); else buttonDoubleShadows->SetValue(cgSettings.P_double_shadows); buttonDoubleShadows->Enable(b); textDoubleShadows->Enable(b); b = cgSettings.P_halo_size>0; sliderHaloStr->Enable(b); sliderHaloAware->Enable(b); textHaloStr->Enable(b); textHaloAware->Enable(b); textHaloColor->Enable(cgSettings.UseHalo()); buttonChooseHAcolor->Enable(cgSettings.UseHalo()); } void MyTab::EnableGeom(){ bool lico=false, bns=false, sf=false; if (geoSettings.mode == GeoSettings::SPACE_FILL) sf=true; if (geoSettings.mode == GeoSettings::LICORICE) lico=true; if (geoSettings.mode == GeoSettings::BALL_N_STICKS) bns=true; buttonSetLicorice->SetValue(lico); buttonSetSpacefill->SetValue(sf); buttonSetBallnstick->SetValue(bns); sliderBallnstick->Enable(bns); textBallnstick->Enable(bns); textBallnstick2->Enable(bns); sliderLicorice->Enable(lico); textLicorice->Enable(lico); float c=GetColMode(); //sliderColorBlend->SetValue(int(c*100*1.0f)); buttonSetColorPerChain->SetValue(c!=1); buttonChangeColorSchema->Enable(c!=1); sliderColorBlend->Enable(c!=1); textColorBlend->Enable(c!=1); buttonSetColorPerAtom->SetValue(c==1); buttonSetBallnstickBicolor->Enable(bns); buttonSetBallnstickConstantcolor->Enable(bns); buttonSetBallnstickSmoothcolor->Enable(bns); //buttonChooseBallnstickConstantcolor->Enable(bns && constant); if (bns) { bool bi, constant, smooth; constant = (geoSettings.use_stick_const_color); smooth = (!constant) & (geoSettings.stick_smooth_color); bi = (!smooth) && (!constant); buttonSetBallnstickBicolor->SetValue(bi); buttonSetBallnstickConstantcolor->SetValue(constant); buttonSetBallnstickSmoothcolor->SetValue(smooth); buttonChooseBallnstickConstantcolor->Enable(constant); if (constant) { colSticks.Set( f2b(geoSettings.stick_const_color_R), f2b(geoSettings.stick_const_color_G), f2b(geoSettings.stick_const_color_B) ); buttonChooseBallnstickConstantcolor->SetBackgroundColour(colSticks); } else buttonChooseBallnstickConstantcolor->SetBackgroundColour(colDisabled); } else { buttonChooseBallnstickConstantcolor->SetBackgroundColour(colDisabled); buttonChooseBallnstickConstantcolor->Enable(false); } /*bool b= sliderColorBlend()->GetValue()*0.01f *0.1f);*/ int h=GetCurrentHetatm(); int a=GetCurrentAtm(); bool e=true, set=geoSettings.showHetatm; if ((h==0) && (a!=0)) {e=false;set=false;} if ((h!=0) && (a==0)) {e=false;set=true;} buttonSetHetatm->Enable(e); textSetHetatm->Enable(e); buttonSetHetatm->SetValue(set); SceneChanged(); } int MyTab::Count(){ return 4; } wxString MyTab::Title(int i) { switch (i) { case 0: return wxString(_T("Presets")); break; case 1: return wxString(_T("Geometry")); break; case 2: return wxString(_T("Customize")); break; case 3: return wxString(_T("Info")); break; } return wxString(_T("")); } BEGIN_EVENT_TABLE(MyTab, wxPanel) EVT_RADIOBUTTON(-1, MyTab::OnRadioButton) /*EVT_RADIOBUTTON(ID_SetLicorice, MyTab::OnSetLicorice) EVT_RADIOBUTTON(ID_SetSpacefill, MyTab::OnSetSpacefill) EVT_RADIOBUTTON(ID_SetBallnstickSmoothcolor, MyTab::OnSetBallnstickSmoothcolor) EVT_RADIOBUTTON(ID_SetBallnstickBicolor, MyTab::OnSetBallnstickBicolor) EVT_RADIOBUTTON(ID_SetBallnstickConstantcolor, MyTab::OnSetBallnstickConstantcolor)*/ EVT_BUTTON(-1, MyTab::OnButton) EVT_COMMAND_SCROLL_THUMBTRACK(-1, MyTab::OnSlider) EVT_CHECKBOX(-1, MyTab::OnCheckBox) //EVT_BUTTON(ID_ChooseBallnstickConstantcolor, MyTab::OnChooseBallnstickConstantcolor) //EVT_COMMAND_SCROLL(ID_SetLicoriceRadius, MyTab::OnSetLicoriceRadius) //EVT_COMMAND_SCROLL(ID_SetBallnstickRadius, MyTab::OnSetBallnstickRadius) END_EVENT_TABLE() wxBitmap *LoadPngImage(wxString st); wxSlider* tmpSlider; wxCheckBox* tmpChk; wxStaticText* tmpStaticText; wxSizer *newLabelledSlider( wxWindow* parent, wxWindowID idSlider, const wxString& labelString, int pos , wxSlider* &slider=tmpSlider, wxStaticText* &label = tmpStaticText) { // wxSizer *res = new wxBoxSizer(wxHORIZONTAL); label=new wxStaticText(parent, wxID_ANY, labelString); slider=new wxSlider(parent,idSlider, pos, 0, 100, wxDefaultPosition, wxDefaultSize/*, wxNO_FULL_REPAINT_ON_RESIZE */ ); res->Add(label, 0); res->Add(slider, 1, wxEXPAND); return res; } static int SLIDERSIZE=80; wxSizer *newAutoSlider( wxWindow* parent, wxWindowID idSlider, const wxString& labelString, float *pos , wxSlider* &slider=tmpSlider, wxStaticText* &label=tmpStaticText) { // wxSizer *res = new wxBoxSizer(wxHORIZONTAL); label=new wxStaticText(parent, wxID_ANY, labelString); slider=new wxSlider(parent,idSlider, int((*pos)*100.0f), 0, 100, wxDefaultPosition, wxSize(SLIDERSIZE,wxDefaultSize.y), wxNO_FULL_REPAINT_ON_RESIZE ); res->Add(label, 0); res->Add(slider, 0); sliderTable.Add(idSlider, pos, slider); return res; } #define AUTO_TEXT_ON_RIGHT 1 wxSizer *newAutoCheckBox(wxWindow* parent, wxWindowID idChk, const wxString& labelString, bool *value, wxCheckBox* &chk=tmpChk, wxStaticText* &label=tmpStaticText, int flags=0) { // wxSizer *res = new wxBoxSizer(wxHORIZONTAL); label=new wxStaticText(parent, wxID_ANY, labelString); chk=new wxCheckBox(parent,idChk, _T("")); chk->SetValue(*value); if (flags&AUTO_TEXT_ON_RIGHT) { //res->Add(SLIDERSIZE - 10 - chk->GetSize().x ,0,1); res->Add(chk, 0, wxBOTTOM | wxTOP, 3); res->Add(10 ,0,0); res->Add(label, 0, wxALIGN_CENTER); } else { res->Add(label, 0, wxALIGN_CENTER); res->Add(10 ,0,0); res->Add(chk, 0, wxBOTTOM | wxTOP, 3); res->Add(SLIDERSIZE - 10 - chk->GetSize().x ,0,1); } buttonTable.Add(idChk, value, chk); return res; } static wxSizer *globalSizerH=NULL; static wxSizer *globalSizerV=NULL; static wxBoxSizer *sizerR, *sizerL; // returns an emphatized version of a given color wxColor emphColor(wxColor c){ unsigned char rgb[3]; rgb[0]=c.Red(); rgb[1]=c.Green(); rgb[2]=c.Blue(); for (int i=0; i<3; i++) { int K=100; if (rgb[i]>255-K) rgb[i]-=K; else if (rgb[i]>128) rgb[i]+=K; else if (rgb[i]>K) rgb[i]-=K; else rgb[i]+=K; } return wxColor(rgb[0],rgb[1],rgb[2]); } int _TH; //wxSizer *obj1, *obj2; // remove newlines from a strings wxString noNewLine(wxString x){ static wxString res; res.Clear(); for (int i=0; iSetMinSize(butSize); if (presetName[i]==wxEmptyString) preset[i]->Show(false); if (thinButtons) { if (!subSizer) subSizer=new wxBoxSizer(wxHORIZONTAL); subSizer->Add( preset[i], 1, wxALIGN_CENTER|wxEXPAND|wxALL,4 ); if (presetEndOfLine[i]) { sizer->Add( subSizer, 1, wxALIGN_CENTER|wxEXPAND); subSizer=NULL; } } else { sizer->Add( preset[i], 1, wxALIGN_CENTER ); } } normalButtonBg=preset[0]->GetForegroundColour(); currentButtonBg=emphColor(normalButtonBg); wxSizer *topLvlSizer = new wxBoxSizer(wxVERTICAL); // topLvlSizer->Add(10,10,0); topLvlSizer->Add(1,1,1); topLvlSizer->Add(sizer,0, wxALIGN_CENTER); //|wxEXPAND); topLvlSizer->Add(1,1,1); SetSizer(topLvlSizer); } if (n==1) { // geometry tab (ball and stick, stick radius, etc) wxStaticBox *box1 = new wxStaticBox(this, wxID_ANY, _T("Space-Fill") ); wxSizer *sizer1 = new wxStaticBoxSizer(box1, wxHORIZONTAL); buttonSetSpacefill = new wxRadioButton(this, ID_SetSpacefill, _T(""), wxDefaultPosition, wxDefaultSize, wxRB_SINGLE ); wxStaticBitmap *bitmap1 = new wxStaticBitmap(this, wxID_ANY, *LoadPngImage(_T("geo1")), wxDefaultPosition ); sizer1->Add(bitmap1); sizer1->Add(5, 5, 1, wxALL, 5); // spacer wxSizer *sizerMode1 = new wxBoxSizer(wxHORIZONTAL); sizerMode1->Add(buttonSetSpacefill, 0, wxRIGHT|wxALIGN_CENTER, 4); sizerMode1->Add(sizer1, 1); wxStaticBox *box2 = new wxStaticBox(this, wxID_ANY, _T("Balls'n'Sticks") ); wxSizer *sizer2 = new wxStaticBoxSizer(box2, wxHORIZONTAL); //sizer2->Enable(false); buttonSetBallnstick= new wxRadioButton(this, ID_SetBallnstick, _T(""), wxDefaultPosition, wxDefaultSize, wxRB_SINGLE ); wxStaticBitmap *bitmap2 = new wxStaticBitmap(this, wxID_ANY, *LoadPngImage(_T("geo2")), wxDefaultPosition ); wxSizer *sizer2r = new wxBoxSizer(wxVERTICAL); sizer2r->Add( newLabelledSlider( this, ID_SetBallnstickRadius, _T("Stick size:"), geoSettings.GetStickRadiusPercentage(), sliderBallnstick, textBallnstick ) ); { wxSizer *sizer2rr = new wxBoxSizer(wxHORIZONTAL); textBallnstick2=new wxStaticText(this, wxID_ANY, _T("Stick color:")); sizer2rr->Add(textBallnstick2, 0); wxSizer *sizerColbox = new wxBoxSizer(wxVERTICAL); buttonSetBallnstickBicolor = new wxRadioButton (this, ID_SetBallnstickBicolor, _T("Split"), wxDefaultPosition, wxDefaultSize, wxRB_SINGLE ); sizerColbox->Add( buttonSetBallnstickBicolor, 1, wxALL, 1); buttonSetBallnstickSmoothcolor = new wxRadioButton (this, ID_SetBallnstickSmoothcolor, _T("Blended"), wxDefaultPosition, wxDefaultSize, wxRB_SINGLE ); sizerColbox->Add( buttonSetBallnstickSmoothcolor, 1, wxALL, 1); buttonSetBallnstickConstantcolor = new wxRadioButton (this, ID_SetBallnstickConstantcolor, _T("Constant:"), wxDefaultPosition, wxDefaultSize, wxRB_SINGLE ); sizerColbox->Add( buttonSetBallnstickConstantcolor, 1, wxALL, 1); buttonChooseBallnstickConstantcolor = new wxButton(this, ID_ChooseBallnstickConstantcolor, wxEmptyString, wxDefaultPosition, wxSize(16,16),wxNO_BORDER); colDisabled = this->GetBackgroundColour(); // wxColor col(255,0,0); // buttonChooseBallnstickConstantcolor ->SetBackgroundColour(col); /* :-( buttonChooseBallnstickConstantcolor = new wxColourPickerCtrl(this, ID_ChooseBallnstickConstantcolor); */ sizer2rr->Add(sizerColbox, 1); sizer2rr->Add( buttonChooseBallnstickConstantcolor, 0, wxALL|wxALIGN_BOTTOM, 1); //sizer2r->Add(5, 5, 0, wxALL, 5); // spacer sizer2r->Add(sizer2rr, 0); } sizer2->Add(bitmap2); sizer2->Add(5, 5, 0, wxALL, 5); // spacer sizer2->Add(sizer2r, 1); wxSizer *sizerMode2 = new wxBoxSizer(wxHORIZONTAL); sizerMode2->Add(buttonSetBallnstick, 0, wxRIGHT|wxALIGN_CENTER, 4); sizerMode2->Add(sizer2, 1); wxStaticBox *box3 = new wxStaticBox(this, wxID_ANY, _T("Licorice") ); wxSizer *sizer3 = new wxStaticBoxSizer(box3, wxHORIZONTAL); buttonSetLicorice = new wxRadioButton(this, ID_SetLicorice, _T(""), wxDefaultPosition, wxDefaultSize, wxRB_SINGLE ); wxStaticBitmap *bitmap3 = new wxStaticBitmap(this, wxID_ANY, *LoadPngImage(_T("geo3")), wxDefaultPosition ); wxSizer *sizer3r = new wxBoxSizer(wxVERTICAL); /*wxSizer *sizer3rr = new wxBoxSizer(wxHORIZONTAL); textLicorice=new wxStaticText(this, wxID_ANY, _T("Thickness:")); sizer3rr->Add(textLicorice, 0); sizer3rr->Add(sliderLicorice, 1); sizer3r->Add(5, 5, 0, wxALL, 5); // spacer*/ sizer3r->Add( newLabelledSlider( this, ID_SetLicoriceRadius, _T("Thickness:"), geoSettings.GetLicoRadiusPercentage(), sliderLicorice, textLicorice ) , 0, wxALIGN_BOTTOM); sizer3->Add(bitmap3, 0); sizer3->Add(5, 5, 0, wxALL, 5); // spacer sizer3->Add(sizer3r, 1, wxALIGN_CENTER); wxStaticBoxSizer *sizerColors = new wxStaticBoxSizer(new wxStaticBox(this, wxID_ANY, _T("Material Color") ) , wxHORIZONTAL ); wxSizer *subsizerColors = new wxBoxSizer(wxVERTICAL); buttonSetColorPerChain = new wxRadioButton(this, ID_SetColorPerChain, _T("Per chain"), wxDefaultPosition, wxDefaultSize, wxRB_SINGLE ); buttonSetColorPerAtom = new wxRadioButton(this, ID_SetColorPerAtom, _T("Per atom"), wxDefaultPosition, wxDefaultSize, wxRB_SINGLE ); buttonChangeColorSchema = new wxButton(this, ID_ChangeColorSchema, _T("Change cols") ); //_T("Change\ncolor\nschema") subsizerColors->Add( buttonSetColorPerAtom ); subsizerColors->Add( buttonSetColorPerChain ); subsizerColors->Add(2,2); subsizerColors->Add( newLabelledSlider( this, ID_SetColorBlend, _T("Diff:"), 0, sliderColorBlend, textColorBlend ), 1, wxLEFT|wxALIGN_RIGHT,30 ); sizerColors->Add( subsizerColors ); sizerColors->Add(2,2); sizerColors->Add( buttonChangeColorSchema, 1, wxRIGHT|wxALIGN_RIGHT|wxALIGN_BOTTOM,5 ); wxSizer *sizerMode3 = new wxBoxSizer(wxHORIZONTAL); sizerMode3->Add(buttonSetLicorice, 0, wxRIGHT|wxALIGN_CENTER, 5); sizerMode3->Add(sizer3, 1); wxSizer *sizer = new wxBoxSizer(wxVERTICAL); sizer->Add(sizerMode1, 0, wxGROW | wxALL , 4); sizer->Add(sizerMode3, 0, wxGROW | wxALL , 4); sizer->Add(sizerMode2, 0, wxGROW | wxALL , 4); wxSizer *sizerG = new wxBoxSizer(wxVERTICAL); sizer->Add(5,5,0); // spacer sizer->Add(newAutoCheckBox( this,ID_SetHetatm, _T("Show 'HET' atmos"), &(geoSettings.showHetatm), buttonSetHetatm, textSetHetatm, AUTO_TEXT_ON_RIGHT ), 0 , wxALIGN_LEFT | wxLEFT,8 ); sizer->Add(5,5,0); // spacer sizer->Add(sizerColors, 0 , wxALIGN_RIGHT); sizerG->Add(sizer,0,wxALIGN_CENTER ); SetSizer(sizerG); EnableGeom(); } if (n==2) { // customize tab (sliders for all graphic fxs) wxStaticText *label1=new wxStaticText(this, wxID_ANY, _T("Color:")); buttonChooseBgcolor=new wxButton(this, ID_ChooseBgcolor, wxEmptyString, wxDefaultPosition, wxSize(16,16),wxNO_BORDER); wxSizer *sizerBgcolor = new wxBoxSizer(wxHORIZONTAL); sizerBgcolor->Add(label1,0,wxALL, 5); sizerBgcolor->Add(buttonChooseBgcolor,0,wxALL, 5); setSceneBgbrightness(bgbrightness); wxStaticBox *boxBG = new wxStaticBox(this, wxID_ANY, _T("Background") ); wxSizer *sizerBG = new wxStaticBoxSizer(boxBG, wxVERTICAL); sizerBG->Add(newAutoSlider( this, ID_SetBgbrightness, _T("Brightn.:"), &(bgbrightness), sliderSetBgbrightness ), 0 , wxALIGN_RIGHT ); sizerBG->Add(sizerBgcolor,0 , wxALIGN_CENTER); wxStaticBox *boxBC = new wxStaticBox(this, wxID_ANY, _T("Base Colors") ); wxSizer *sizerBC = new wxStaticBoxSizer(boxBC, wxVERTICAL); sizerBC->Add(newAutoSlider( this, ID_SetBaseColorSat, _T("Saturation:"), &(cgSettings.P_col_atoms_sat) ), 0 , wxALIGN_RIGHT ); /* // Useless! Redundant with basic light sizerBC->Add(newAutoSlider( this, ID_SetBaseColorBri, _T("Brightness:"), &(cgSettings.P_col_atoms_bri) ), 0 , wxALIGN_RIGHT ); */ wxStaticBox *boxPL = new wxStaticBox(this, wxID_ANY, _T("Point Light")); wxSizer *sizerPL = new wxStaticBoxSizer(boxPL, wxVERTICAL); sizerPL->Add(newAutoSlider( this, ID_SetLight, _T("Intensity*:"), &(cgSettings.P_lighting), sliderLighting ), 0 , wxALIGN_RIGHT ); sizerPL->Add(newAutoSlider( this, ID_SetLightBase, _T("Flatten:"), &(cgSettings.P_light_base), sliderLightBase, textLightBase ), 0 , wxALIGN_RIGHT ); sizerPL->Add(newAutoSlider( this, ID_SetShine, _T("Shininess:"), &(cgSettings.P_phong) ), 0 , wxALIGN_RIGHT ); sizerPL->Add(newAutoSlider( this, ID_SetShineSize, _T("Glossiness:"), &(cgSettings.P_phong_size), sliderShineSize, textShineSize ), 0 , wxALIGN_RIGHT ); /* sizerPL->Add(newAutoCheckBox( this,ID_SetShadow, _T("Cast Shadows:"), &(cgSettings.P_use_shadowmap()), buttonShadow, textShadow ), 0 , wxALIGN_RIGHT );*/ sizerPL->Add(newAutoSlider( this, ID_SetShadowStr, _T("Shadows:"), &(cgSettings.P_shadowstrenght), sliderShadowStr, textShadowStr ), 0 , wxALIGN_RIGHT ); sizerPL->Add(newAutoCheckBox( this,ID_SetDoubleShadows, _T("2way Light:"), &(cgSettings.P_double_shadows ), buttonDoubleShadows, textDoubleShadows ), 0 , wxALIGN_RIGHT ); sizerPL->Add(newAutoCheckBox( this,ID_SetSem, _T("Fake SEM:"), &(cgSettings.P_sem_effect), buttonSem, textSem ), 0 , wxALIGN_RIGHT ); wxStaticBox *boxDB = new wxStaticBox(this, wxID_ANY, _T("Depth Cueing") ); wxSizer *sizerDB = new wxStaticBoxSizer(boxDB, wxVERTICAL); sizerDB->Add(newAutoSlider( this, ID_SetFog, _T("Strenght:"), &(cgSettings.P_fog) ), 0 , wxALIGN_RIGHT ); wxStaticBox *boxHA = new wxStaticBox(this, wxID_ANY, _T("Halos") ); wxSizer *sizerHA = new wxStaticBoxSizer(boxHA, wxVERTICAL); sizerHA->Add(newAutoSlider( this, ID_SetHalo, _T("Size:"), &(cgSettings.P_halo_size), sliderHaloSize, textHaloSize ), 0 , wxALIGN_RIGHT ); sizerHA->Add(newAutoSlider( this, ID_SetHaloStr, _T("Strenght:"), &(cgSettings.P_halo_str), sliderHaloStr, textHaloStr ), 0 , wxALIGN_RIGHT ); sizerHA->Add(newAutoSlider( this, ID_SetHaloAware, _T("Variance:"), &(cgSettings.P_halo_aware), sliderHaloAware, textHaloAware ), 0 , wxALIGN_RIGHT ); textHaloColor=new wxStaticText(this, wxID_ANY, _T("Color:")); buttonChooseHAcolor=new wxButton(this, ID_ChooseHAcolor, wxEmptyString, wxDefaultPosition, wxSize(16,16),wxNO_BORDER); buttonChooseHAcolor->SetBackgroundColour( col(cgSettings.P_halo_col) ); wxSizer *sizerHAcolor = new wxBoxSizer(wxHORIZONTAL); sizerHAcolor->Add(textHaloColor,0,wxALL, 5); sizerHAcolor->Add(buttonChooseHAcolor,0,wxALL, 5); sizerHA->Add(sizerHAcolor, 0 , wxALIGN_CENTER); // borders wxStaticBox *boxBR = new wxStaticBox(this, wxID_ANY, _T("Borders") ); wxSizer *sizerBR = new wxStaticBoxSizer(boxBR, wxVERTICAL); /* sizerBR->Add(newAutoSlider( this, ID_SetBorderFixed, _T("Fixed Size:"), &(cgSettings.P_border_inside) ), 0 , wxALIGN_RIGHT );*/ sizerBR->Add(newAutoSlider( this, ID_SetBorderVariable, _T("Size:"), &(cgSettings.P_border_outside) ), 0 , wxALIGN_RIGHT ); sizerBR->Add(newAutoSlider( this, ID_SetBorderDepthAware, _T("Variance:"), &(cgSettings.P_depth_full), sliderAwaren, textAwaren ), 0 , wxALIGN_RIGHT ); wxStaticBox *boxAO = new wxStaticBox(this, wxID_ANY, _T("Ambient Light") ); wxSizer *sizerAO = new wxStaticBoxSizer(boxAO, wxVERTICAL); sizerAO->Add(newAutoSlider( this, ID_SetAO, _T("Intensity*:"), &(cgSettings.P_texture), sliderAO ), 0 , wxALIGN_RIGHT ); wxSizer *sizerAB = new wxBoxSizer(wxVERTICAL); buttonAutobalance = new wxCheckBox(this, ID_SetAutobalance, _T("* Autobalance") ); buttonAutobalance->SetValue(false); sizerAB->Add(buttonAutobalance, 1, wxALIGN_CENTER ); buttonTable.Add(ID_SetAutobalance, &(cgSettings.auto_normalize), buttonAutobalance); int SPACE=6; sizerL = new wxBoxSizer(wxVERTICAL); sizerL->Add(sizerBC, 0, wxEXPAND); sizerL->Add(SPACE,SPACE, 0); sizerL->Add(sizerPL, 0, wxEXPAND); sizerL->Add(SPACE,SPACE, 0); sizerL->Add(sizerAO, 0, wxEXPAND); sizerL->Add(SPACE,SPACE, 0); sizerL->Add(sizerAB, 0, wxEXPAND|wxALIGN_CENTER ); /*wxBoxSizer */sizerR = new wxBoxSizer(wxVERTICAL); sizerR->Add(sizerBG, 0, wxEXPAND); sizerR->Add(SPACE,SPACE, 0); sizerR->Add(sizerDB, 0, wxEXPAND); sizerR->Add(SPACE,SPACE, 0); sizerR->Add(sizerHA, 0, wxEXPAND); sizerR->Add(SPACE,SPACE, 0); sizerR->Add(sizerBR, 0, wxEXPAND); globalSizerV = new wxBoxSizer(wxVERTICAL); globalSizerV->Add(sizerL, 1, wxEXPAND); globalSizerH = new wxBoxSizer(wxHORIZONTAL); globalSizerH->Add(globalSizerV, 1); globalSizerH->Add(sizerR,1, wxEXPAND|wxLEFT, 5); _TH=sizerL->GetMinSize().y + sizerR->GetMinSize().y; SetSizer(globalSizerH); EnableCustom(); } if (n==3) { // info tab (about, trackball instructions, and a button for advanced properties) wxSizer *sizerA = new wxBoxSizer(wxVERTICAL); sizerA->Add(new wxStaticText(this, wxID_ANY,_T("by")) ,0, wxALIGN_CENTER ); sizerA->Add(new wxStaticText(this, wxID_ANY,_T("Marco Tarini")) ,0, wxALIGN_CENTER ); sizerA->Add(new wxStaticText(this, wxID_ANY,_T("and")) ,0, wxALIGN_CENTER ); sizerA->Add(new wxStaticText(this, wxID_ANY,_T("Paolo Cignoni")) ,0, wxALIGN_CENTER ); wxSizer *sizerB = new wxStaticBoxSizer(new wxStaticBox(this, wxID_ANY, _T("Instructions") ), wxVERTICAL); sizerB->Add(new wxStaticText(this, wxID_ANY,_T("\ Left Mouse Button: rotate molecule\n\ Mouse wheel / Shift+Left: zoom molecule\n\ Middle Mouse / Ctrl+Left Mouse : pan molecule\n\ Right Mouse Button: move Light\n\ "), wxDefaultPosition, wxDefaultSize, wxALIGN_CENTER) ,0, wxALIGN_CENTER ); wxSizer *sizerC = new wxBoxSizer( wxHORIZONTAL); wxStaticBitmap *bitmap = new wxStaticBitmap(this, wxID_ANY, *LoadPngImage(_T("logo")), wxDefaultPosition ); sizerC->Add(bitmap, 0, wxALIGN_BOTTOM); sizerC->Add(1,1,1); sizerC->Add(new wxStaticText(this, wxID_ANY, _T("ver 0.4.1 ("__DATE__")") ),0, wxALIGN_BOTTOM|wxALL,10); wxSizer *sizer = new wxBoxSizer(wxVERTICAL); sizer->Add(1,1,1); sizer->Add(sizerA,0, wxEXPAND|wxLEFT|wxRIGHT,10); sizer->Add(1,1,1); sizer->Add( new wxButton(this, ID_WebButton, /*_T("visit ")+*/qutemolwebsite ) ,0, wxALIGN_CENTER|wxALL/*|wxEXPAND,10*/); sizer->Add(1,1,1); sizer->Add(sizerB,0, wxEXPAND|wxLEFT|wxRIGHT,10); sizer->Add(1,1,1); sizer->Add(sizerC,0, wxEXPAND); SetSizer(sizer); } } bool MyTab::Redispose(int wy){ bool res=false; if (globalSizerH) { if (_THDetach(sizerR)) { globalSizerV->Detach(sizerL); globalSizerV->Add(sizerL,1, wxEXPAND|wxLEFT|wxRIGHT|wxTOP,10); globalSizerV->Add(sizerR,1, wxEXPAND|wxLEFT|wxRIGHT,10); res=true; } } else { if (globalSizerV->Detach(sizerR)) { globalSizerV->Detach(sizerL); globalSizerV->Add(sizerL,1, wxEXPAND); globalSizerH->Add(sizerR,1, wxEXPAND|wxLEFT, 5); res=true; } } globalSizerV->Layout(); globalSizerV->CalcMin(); globalSizerV->RecalcSizes(); globalSizerH->Layout(); globalSizerH->CalcMin(); globalSizerH->RecalcSizes(); } return res; } void MyTab::UpdateAll(){ setSceneBgcolor( col(cgSettings.P_bg_color_R,cgSettings.P_bg_color_G, cgSettings.P_bg_color_B) ); int k=(int)(cgSettings.P_halo_col*255.0); buttonChooseHAcolor->SetBackgroundColour(wxColor(k,k,k)); sliderTable.UpdateAll(); buttonTable.UpdateAll(); //EnableGeom(); EnableCustom(); } qutemol/src/AtomColor.h0000444000175000017500000000144410631106412013456 0ustar mbamba int getAtomColor(const char* atomicElement); float getAtomRadius(const char* atomicElement); float getAtomCovalentRadius(const char* atomicElement); int getChainColor(int chianIndex); #define MAX_COVALENT_RADIUS 1.688f bool readArtFile(const char* filename); qutemol/src/ShadowMap.cpp0000444000175000017500000003035110633257153014007 0ustar mbamba//#include typedef unsigned char Byte; typedef unsigned int uint; #include #include "CgUtil.h" //#include #include //#include #include #include #include using namespace vcg; using namespace std; #include "CubeMapSamp.h" #include "OctaMapSamp.h" #include "Mol.h" #include "HardSettings.h" #include "MyCanvas.h" #include "ShadowMap.h" bool use_accurate_halo=true; bool validView(Point3f p){ if (!hardSettings.doubleSM) return true; if (p[0]>0) return true; if (p[0]<0) return false; if (p[1]<0) return true; if (p[1]>0) return false; if (p[2]<0) return true; return false; } extern int CSIZE; // size for alo patch extern int BSIZE; // size for bonds patches //extern uint shadowFrame, shadowTexture, offsetFrame, haloFrame, haloTexture, finalFrame; //uint finalFrame=0; // frame dove metto l'immagine finale! 0 se lo schermo. CgUtil shadowSettings; CgUtil shadowSettingsAcc; // functions defined later. static void setMatrices(vcg::Point3f L, int screensize, int screensizeHard, bool sx); static void restoreMatrices(); static GLint lastviewport[4]; float matSM[4][4]; // matrix used during shadowmmap drawing float matFinal[4][4];// matrix for FP computation = matSM x (MV)^(-1) float HSratio; // ratio betweenhard and soft shadowbuffer extern Mol mol; extern int winx,winy; // FOR HALOS void prepareDepthTextureForCurrentViewpoint(){ // Draw depth texture from current viewpoint haloCanvas.SetSameRes( mainCanvas ); haloCanvas.SetAsOutput(); if (use_accurate_halo) shadowSettingsAcc.BindShaders(); else shadowSettings.BindShaders(); glClear( GL_DEPTH_BUFFER_BIT ) ; mol.Draw(); mainCanvas.SetAsOutput(); glActiveTextureARB(GL_TEXTURE1_ARB); haloCanvas.SetAsTexture(); glEnable(GL_TEXTURE_2D); } Point3f lastL(0,0,0); // last used light void ShadowMap::Update(){ lastL.Zero(); } void ShadowMap::computeAsTexture(vcg::Point3f L, bool makeboth, MyCanvas &canvas){ if (lastL!=L) { canvas.SetAsOutput(); setMatrices(L, canvas.GetSoftRes(),canvas.GetHardRes(), true); glClearDepth(1); glClear( GL_DEPTH_BUFFER_BIT ); glDisable(GL_SCISSOR_TEST); glDepthFunc(GL_LESS); m.DrawShadowmap(false); restoreMatrices(); if (hardSettings.doubleSM && makeboth) { setMatrices(L, canvas.GetSoftRes(), canvas.GetHardRes(), false); glClearDepth(-10000); glClear( GL_DEPTH_BUFFER_BIT); glDepthFunc(GL_GREATER); glDisable(GL_SCISSOR_TEST); m.DrawShadowmap(false); restoreMatrices(); } glClearDepth(1); glDepthFunc(GL_LESS); mainCanvas.SetAsOutput(); lastL=L; } glActiveTextureARB(GL_TEXTURE1_ARB); canvas.SetAsTexture(); } extern ShadowMap shadowmap; float extractCurrentScaleFactor(float x[4][4]); float extractCurrentScaleFactor(); //float shadowScaleFactor=1; void ShadowMap::FeedParameters(){ for (int i=0; i<3; i++) { glProgramEnvParameter4fARB(GL_FRAGMENT_PROGRAM_ARB, i+3, matFinal[0][i],matFinal[1][i],matFinal[2][i],matFinal[3][i] ); } } extern CgUtil cgSettings; /*void DrawTmp(){ cgSettings.BindShaders(); glEnable(GL_TEXTURE_2D); //glBindTexture(GL_TEXTURE_2D, molTexture); glActiveTextureARB(GL_TEXTURE1_ARB); glBindTexture(GL_TEXTURE_2D, shadowTexture); shadowmap.m.Draw(); // shadowmap.m.DrawShadowmap(false); glDisable(GL_VERTEX_PROGRAM_ARB); glDisable(GL_FRAGMENT_PROGRAM_ARB); glDisable(GL_BLEND); /*glActiveTextureARB(GL_TEXTURE0_ARB); glDisable(GL_TEXTURE_2D); glActiveTextureARB(GL_TEXTURE1_ARB); glEnable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D, shadowTexture);*/ // glBindTexture(GL_TEXTURE_2D, shadowTexture); /* glBegin(GL_QUADS); glColor3f(0,0,1); float h=-0.25, k=-0.25; glTexCoord2f(0,0); glVertex3d( k, h,0.1); glTexCoord2f(1,0); glVertex3d( k,+1,0.1); glTexCoord2f(1,1); glVertex3d(+1,+1,0.1); glTexCoord2f(0,1); glVertex3d(+1, h,0.1); glEnd(); glActiveTextureARB(GL_TEXTURE1_ARB); glDisable(GL_TEXTURE_2D); glActiveTextureARB(GL_TEXTURE0_ARB); glEnable(GL_TEXTURE_2D); glBegin(GL_QUADS); glColor3f(1,1,1); glTexCoord2f(0,0); glVertex3d(k-0.75,h-0.75,0); glTexCoord2f(1,0); glVertex3d(k-0.75,0.25,0); glTexCoord2f(1,1); glVertex3d(0.25,0.25,0); glTexCoord2f(0,1); glVertex3d(0.25,h-0.75,0); glEnd(); */ /*glActiveTextureARB(GL_TEXTURE1_ARB); glDisable(GL_TEXTURE_2D); glActiveTextureARB(GL_TEXTURE0_ARB); glEnable(GL_TEXTURE_2D); */ /*}*/ bool ShadowMap::init(){ shadowSettings.SetForShadowMap(false); shadowSettingsAcc.SetForShadowMap(true); mainCanvas.RedirectToVideo(); mainCanvas.SetVideoSize(winx); // test shadow and shadowAO canvases shadowmapCanvas.SetRes(hardSettings.SHADOWMAP_SIZE); shadowmapCanvas.ratio2x1=(hardSettings.doubleSM==1); if (!shadowmapCanvas.Test() ) return false; shadowAOCanvas.SetRes(hardSettings.AOSM_SIZE); shadowAOCanvas.ratio2x1=(hardSettings.doubleSM==1); //shadowAOCanvas.ratio2x1=(hardSettings.doubleSM==1); if (!shadowAOCanvas.Test() ) return false; mainCanvas.SetAsOutput(); return true; } bool ShadowMap::initHalo(){ // test halo canvases haloCanvas.SetSameRes(mainCanvas); if (!haloCanvas.Test() ) return false; mainCanvas.SetAsOutput(); return true; } bool AOgpu2::init(){ if (!moltextureCanvas.Test()) return false; mainCanvas.SetAsOutput(); } float myrand(); static CgUtil aogpu_settings; static CgUtil aogpustick_settings; void AOgpu2::Reset(Mol &m){ moltextureCanvas.SetAsOutput(); glClearColor(0,0,0,1); glClear( GL_COLOR_BUFFER_BIT); } void AOgpu2::Bind(){ moltextureCanvas.SetAsOutput(); } AOgpu2::AOgpu2( Point3f dir, Mol &m, int ndir){ shadowmap.computeAsTexture(dir, true, shadowAOCanvas ); glFinish(); moltextureCanvas.SetAsOutput(); glDisable(GL_VERTEX_PROGRAM_ARB); glEnable(GL_FRAGMENT_PROGRAM_ARB); aogpu_settings.BindDrawAOShader(); for (int i=0; i<3; i++) { glProgramEnvParameter4fARB(GL_FRAGMENT_PROGRAM_ARB, i, matSM[0][i],matSM[1][i],matSM[2][i],matSM[3][i] ); //printf("Sending %d (%f %f %f %f)\n", i, mat[0][i],mat[1][i],mat[2][i],mat[3][i]); } glProgramEnvParameter4fARB(GL_FRAGMENT_PROGRAM_ARB, 3, dir[0],dir[1],dir[2], 4.0/ndir ); glProgramEnvParameter4fARB(GL_FRAGMENT_PROGRAM_ARB, 4, 0,stick_radius,0,0 ); m.DrawOnTexture(); glDisable(GL_BLEND); glEnable(GL_VERTEX_PROGRAM_ARB); }; void AOgpu2::UnBind(){ mainCanvas.SetAsOutput(); }; float myrand(){ static int k=0; k+=1231543214; return ((k%12421)/12421.0); } void Bond::DrawOnTexture(){ //glColor3f(myrand(),myrand(),myrand()); float h=0.0; float Xm=(-1.0)-1.0/BSIZE; float Xp=+1.0+1.0/BSIZE; float Ym=Xm, Yp=+1.0+1.0/CSIZE/1.0; Point3f tmp=startp^dir; startp.Normalize(); tmp.Normalize(); glMultiTexCoord3fARB(GL_TEXTURE2_ARB, startp[0],startp[1],startp[2]); glMultiTexCoord3fARB(GL_TEXTURE3_ARB, tmp[0],tmp[1],tmp[2] ); glMultiTexCoord3fARB(GL_TEXTURE1_ARB, b[0],b[1],b[2] ); glTexCoord2f(Xm,Yp); glVertex2f(-h+tx, -h+ty+CSIZE); glTexCoord2f(Xm,Ym); glVertex2f(-h+tx, -h+ty); glMultiTexCoord3fARB(GL_TEXTURE1_ARB, a[0],a[1],a[2] ); glTexCoord2f(Xp,Ym); glVertex2f(-h+tx+BSIZE,-h+ty); glTexCoord2f(Xp,Yp); glVertex2f(-h+tx+BSIZE,-h+ty+CSIZE); } void QAtom::DrawOnTexture(){ glColor3f(myrand(),myrand(),myrand()); float h=0.0; float Xm=(-1.0)-1.0/CSIZE/1.0; float Xp=+1.0+1.0/CSIZE/1.0; float Ym=Xm, Yp=Xp; glMultiTexCoord4fARB(GL_TEXTURE1_ARB, px,py,pz,r ); glTexCoord2f(Xm,Ym); glVertex2f(-h+tx, -h+ty); glTexCoord2f(Xp,Ym); glVertex2f(-h+tx+CSIZE,-h+ty); glTexCoord2f(Xp,Yp); glVertex2f(-h+tx+CSIZE,-h+ty+CSIZE); glTexCoord2f(Xm,Yp); glVertex2f(-h+tx, -h+ty+CSIZE); } void Mol::DrawOnTexture(){ glEnable(GL_BLEND); glBlendFunc(GL_ONE, GL_ONE ); glMatrixMode(GL_PROJECTION); glPushMatrix(); glLoadIdentity(); glOrtho(0,moltextureCanvas.GetSoftRes(),0,moltextureCanvas.GetSoftRes(), 0,1); glMatrixMode(GL_MODELVIEW); glPushMatrix(); glLoadIdentity(); glGetIntegerv(GL_VIEWPORT, lastviewport); glViewport(0,0,moltextureCanvas.GetSoftRes(),moltextureCanvas.GetSoftRes()); glActiveTextureARB(GL_TEXTURE1_ARB); glDisable(GL_TEXTURE_2D); glActiveTextureARB(GL_TEXTURE0_ARB); glDisable(GL_TEXTURE_2D); glBegin(GL_QUADS); for (int i=0; i void ShadowMap::GetCurrentPVMatrix(){ float matP[16]; float matMV[16]; glGetFloatv(GL_PROJECTION_MATRIX, matP); glGetFloatv(GL_MODELVIEW_MATRIX, matMV); Matrix44f A(matSM[0]); Matrix44f B(matMV); Matrix44f C(matP); A=vcg::Transpose( A ); B=vcg::Transpose( B ); C=vcg::Transpose( C ); Matrix44f P = C*B; P=vcg::Invert( P ); Matrix44f res = A*P; Matrix44f mul; Matrix44f add; GLint vp[4]; glGetIntegerv(GL_VIEWPORT, vp); mul.SetScale(Point3f(2.0f/vp[2], 2.0f/vp[3], 2)); add.SetTranslate(Point3f(-1,-1,-1)); //Matrix44f mulHS; //mulHS.SetScale(Point3f(HSratio,HSratio,1) ); res=res*add*mul; for (int i=0; i<4; i++) for (int j=0; j<4; j++) matFinal[i][j]=res[j][i]; } /* void ShadowMap::GetCurrentPVMatrix(){ computeAxBm1xCm1( &(res[0][0]) , &(A[0][0]) , &(B[0][0]) , &(C[0][0])); }*/ void test(){ return; float nf[2]; glGetFloatv(GL_DEPTH_RANGE, nf); FILE *f=fopen("test.txt","w"); fprintf(f,"near=%f,far=%f\n\n",nf[0],nf[1]); fclose(f); float mat[16]; float matP[16]; glGetFloatv(GL_MODELVIEW_MATRIX, mat); glGetFloatv(GL_PROJECTION_MATRIX, matP); Matrix44f A(mat); A=vcg::Transpose( A ); Matrix44f B(matP); B=vcg::Transpose( B ); A = B*A; for (int i=0; i<4; i++) for (int j=0; j<4; j++) mat[i*4+j]=A[j][i]; glMatrixMode(GL_PROJECTION); glLoadIdentity( ); glMatrixMode(GL_MODELVIEW); glLoadMatrixf( mat ); } qutemol/src/Common.cpp0000444000175000017500000006210110633257034013350 0ustar mbambatypedef unsigned char Byte; typedef unsigned int uint; #include #include "CgUtil.h" //#include #include //#include #include #include #include #include "gen_normal.h" #include using namespace vcg; using namespace std; #include "CubeMapSamp.h" #include "OctaMapSamp.h" #include "Mol.h" //#include "AOgpu.h" #include "Common.h" #include "HardSettings.h" #include "MyCanvas.h" #include "ShadowMap.h" extern CgUtil shadowSettings; extern CgUtil shadowSettingsAcc; GeoSettings geoSettings; // singleton extern Mol mol; double aniStep=-1; void setAniStep(double step){ aniStep=step; } void stopAni(){ aniStep=-1; } void GeoSettings::Apply(){ if (mol.IsReady()) { if (mode==BALL_N_STICKS) { mol.SetBallAndSticks(stickRadius); } if (mode==LICORICE) { mol.SetLicorice(licoRadius); } if (mode==SPACE_FILL) mol.SetSpaceFill(); } cgSettings.setGeoSettings(*this); cgSettings.UpdateShaders(); UpdateShadowmap(); mol.ResetAO(); } void SetColMode(float mode){ mol.SetColMode(mode); } void ResetColMode(){ float tmp=mol.colMode; mol.colMode=-1; mol.SetColMode(tmp); } float GetColMode(){ return mol.colMode; } void GeoSettings::ApplyColor(){ cgSettings.setGeoSettings(*this); cgSettings.UpdateShaders(); } using namespace vcg; using namespace std; // VIS06 presentaiton modes: bool draw_balls=true; bool draw_sticks=true; bool draw_wireframe_sticks=false; bool draw_wireframe_balls=false; int winx=512,winy=winx; int CSIZE; // size (texels) per atom patches int BSIZE; // size (texels) per pond patches vcg::Trackball track; vcg::Trackball lightTrack; bool MovingLightMode=false; Mol mol; ShadowMap shadowmap(mol); CgUtil cgSettings; int GetCurrentHetatm(){ return mol.nhetatm; } int GetCurrentAtm(){ return mol.natm; } //void DrawTmp(); void UpdateShadowmap(){ ShadowMap::Update(); } void drawFrame(); // def later... Byte* GetSnapshot(int sx, int sy, bool alpha){ static uint textureSnap = 666; static uint frameSnap; // set offline rendering mainCanvas.RedirectToMemory(); mainCanvas.SetRes(sx); //hardsx=mainCanvas.GetHardRes(); if (!mainCanvas.SetAsOutput()) return NULL; drawFrame(); // capture frame sx=sy=mainCanvas.GetHardRes(); Byte* res=new(Byte[sx*sy*4]); glReadPixels(0,0,sx,sy,alpha?GL_RGBA:GL_RGB,GL_UNSIGNED_BYTE,res); mainCanvas.RedirectToVideo(); mainCanvas.SetAsOutput(); return res; } void setProjection(int res){ int winx,winy; winx=winy=res; glMatrixMode(GL_PROJECTION); glLoadIdentity(); GLfloat nearPlane = 0.01; GLfloat farPlane = 10000; float size=1.2f; float ratio=size*(float)winx / winy; if (cgSettings.projmode==CgUtil::PERSPECTIVE) { gluPerspective(60.0, ratio, nearPlane, farPlane); } else // if(winx texture(hardSettigs.TSIZE*hardSettigs.TSIZE*3,128); void QAtom::DrawHalo(){ if ((!geoSettings.showHetatm)&&(hetatomFlag)) return; float s=cgSettings.P_halo_size * 2.5; glMultiTexCoord2fARB(GL_TEXTURE1_ARB, r+s, (r+s)*(r+s) / (s*s+2*r*s)); glTexCoord2f(+1,+1); glVertex3f(px,py,pz); glTexCoord2f(-1,+1); glVertex3f(px,py,pz); glTexCoord2f(-1,-1); glVertex3f(px,py,pz); glTexCoord2f(+1,-1); glVertex3f(px,py,pz); } void QAtom::Draw(){ if ((!geoSettings.showHetatm)&&(hetatomFlag)) return; glColor3f(cr,cg,cb); glTexCoord2f(tx/float(moltextureCanvas.GetHardRes()),ty/float(moltextureCanvas.GetHardRes())); glNormal3f(+1,+1, r); glVertex3f(px,py,pz); glNormal3f(-1,+1, r); glVertex3f(px,py,pz); glNormal3f(-1,-1, r); glVertex3f(px,py,pz); glNormal3f(+1,-1, r); glVertex3f(px,py,pz); } void Bond::DrawHalo(){ if ((!geoSettings.showHetatm)&&(hetatomFlag)) return; glTexCoord4f(dir[0],dir[1],dir[2], 1.0/lenght); glNormal3f(+1,+1,0); glVertex3f(a[0],a[1],a[2]); glNormal3f(-1,+1,0); glVertex3f(a[0],a[1],a[2]); glNormal3f(-1,-1,0); glVertex3f(b[0],b[1],b[2]); glNormal3f(+1,-1,0); glVertex3f(b[0],b[1],b[2]); } void Bond::Draw(){ if ((!geoSettings.showHetatm)&&(hetatomFlag)) return; // glColor3f(cr,cg,cb); // glTexCoord2f(tx/float(TSIZE),ty/float(TSIZE)); glTexCoord4f(dir[0],dir[1],dir[2], 1.0/lenght); //glMultiTexCoord3fARB(GL_TEXTURE3_ARB, col1[0],col1[1],col1[2] ); glColor3fv(&(col1[0])); glSecondaryColor3fv(&col2[0]); //glMultiTexCoord3fARB(GL_TEXTURE4_ARB, col2[0],col2[1],col2[2] ); glMultiTexCoord3fARB(GL_TEXTURE1_ARB, startp[0],startp[1],startp[2] ); glMultiTexCoord2fARB(GL_TEXTURE2_ARB, tx/float(moltextureCanvas.GetHardRes()),ty/float(moltextureCanvas.GetHardRes())); glNormal3f(+1,+1,0); glVertex3f(a[0],a[1],a[2]); glNormal3f(-1,+1,0); glVertex3f(a[0],a[1],a[2]); glNormal3f(-1,-1,0); glVertex3f(b[0],b[1],b[2]); glNormal3f(+1,-1,0); glVertex3f(b[0],b[1],b[2]); } void QAtom::DrawShadowmap(){ if ((!geoSettings.showHetatm)&&(hetatomFlag)) return; glNormal3f(+1,+1, r); glVertex3f(px,py,pz); glNormal3f(-1,+1, r); glVertex3f(px,py,pz); glNormal3f(-1,-1, r); glVertex3f(px,py,pz); glNormal3f(+1,-1, r); glVertex3f(px,py,pz); } void Bond::DrawShadowmap(){ if ((!geoSettings.showHetatm)&&(hetatomFlag)) return; glTexCoord4f(dir[0],dir[1],dir[2], 1.0/lenght); glNormal3f(+1,+1,0); glVertex3f(a[0],a[1],a[2]); glNormal3f(-1,+1,0); glVertex3f(a[0],a[1],a[2]); glNormal3f(-1,-1,0); glVertex3f(b[0],b[1],b[2]); glNormal3f(+1,-1,0); glVertex3f(b[0],b[1],b[2]); } float extractCurrentScaleFactor(float x[4][4]){ float det= x[0][0]*x[1][1]*x[2][2] -x[0][0]*x[1][2]*x[2][1] +x[1][0]*x[2][1]*x[0][2] -x[1][0]*x[0][1]*x[2][2] +x[2][0]*x[0][1]*x[1][2] -x[2][0]*x[1][1]*x[0][2]; return pow(fabs(det), 1.0f/3.0f); } float extractCurrentScaleFactor(){ float x[4][4]; glGetFloatv(GL_MODELVIEW_MATRIX, &(x[0][0])); return extractCurrentScaleFactor(x); } void prepareDepthTextureForCurrentViewpoint(); void Mol::DrawHalos(){ // let's try to aviod THIS! prepareDepthTextureForCurrentViewpoint(); // hum, unavoidable. glPushMatrix(); glScalef(1/r,1/r,1/r); glTranslatef(-px,-py,-pz); float x[4][4], scalef; glGetFloatv(GL_MODELVIEW_MATRIX, &(x[0][0])); glProgramEnvParameter4fARB(GL_VERTEX_PROGRAM_ARB, 0, scalef=extractCurrentScaleFactor(x), 0,0,0 ); glEnable(GL_VERTEX_PROGRAM_ARB); glEnable(GL_FRAGMENT_PROGRAM_ARB); glDepthMask(false); glEnable(GL_BLEND); if (cgSettings.doingAlphaSnapshot) glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); else glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); cgSettings.BindHaloShader( haloCanvas.GetResPow2() ); glProgramEnvParameter4fARB(GL_FRAGMENT_PROGRAM_ARB, 0, (100.0+cgSettings.P_halo_aware*1300.0)/scalef/mol.r, 0,0,0 ); glBegin(GL_QUADS); for (int i=0; i0) { ShadowMap::GetCurrentPVMatrix(); ShadowMap::FeedParameters(); } for (int i=0; i<3; i++) glProgramEnvParameter4fARB(GL_FRAGMENT_PROGRAM_ARB, i, x[i][0],x[i][1],x[i][2],0 ); glProgramEnvParameter4fARB(GL_FRAGMENT_PROGRAM_ARB, 6, mol.PredictAO(),0,0,0 ); if (draw_balls) { if (draw_wireframe_balls) { glDisable(GL_FRAGMENT_PROGRAM_ARB); for (int i=0; i DirV; void Mol::ResetAO(){ AOready=false; AOstarted=false; AOdoneLvl=0; } bool Mol::DoingAO(){ if (!ready) return false; if (cgSettings.P_texture==0) return false; if (DirV.size()==0) return true; return AOdoneLvl=DirV.size()) return true; if (atom.size()<10) return (AOdoneLvl>6*k); if (atom.size()<100) return (AOdoneLvl>4*k); if (atom.size()<1000) return (AOdoneLvl>2*k); if (atom.size()<10000) return (AOdoneLvl>1*k); return true; } float Mol::PredictAO(){ // Additive prediction //return 0.6*(DirV.size()-AOdoneLvl)/float(DirV.size()); // multiplicative prediction if (DirV.size()==0) return 1.0; else { float coeff=0.25+(AOdoneLvl-1)/20.0; if (coeff>1.0f) coeff=1.0f; return coeff*float(DirV.size()*1.0f) / (AOdoneLvl/*+DirV.size()*0.3f*/); } } void Mol::PrepareAOstart(){ AOdoneLvl=0; AOgpu2::Reset(*this); AOstarted=true; if (DirV.size()==0) { // genreate probe views GenNormal::Uniform(hardSettings.N_VIEW_DIR,DirV); // mix them! int N=DirV.size(); for (int k=0; kDirV.size()) i=0; AOgpu2::UnBind(); AOdoneLvl=DirV.size(); } bool Mol::PrepareAOstep(int nsteps){ if (!DoingAO()) return true; if (!AOstarted) PrepareAOstart(); AOgpu2::Bind(); if (validView(DirV[AOdoneLvl])) AOgpu2 ao(DirV[AOdoneLvl], *this, DirV.size()); AOgpu2::UnBind(); AOdoneLvl++; return (AOdoneLvl>=DirV.size()) ; } void Mol::PrepareAOallAtOnce(){ if (AOready) return; StartTime(); while (!PrepareAOstep(1)); //AOgpu2::GetFinalTexture(texture,*this); //refresh(); FILE *f = fopen("res.txt", "w"); long int w=TakeTime(f,"sampled"); fprintf(f," %d views done in %d msec (%.2f views x sec), with %d atoms & %d sticks.\n", DirV.size(), w, DirV.size()*1000.0/w, this->atom.size(), this->sticks?(this->bond.size()):0 ); fclose(f); AOready=true; } void clearFrame() { glClearColor( cgSettings.P_bg_color_R, cgSettings.P_bg_color_G, cgSettings.P_bg_color_B, 0.0f); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); } void setLightDir(Point3f d){ float f[4]; f[0]=d[0]; f[1]=d[1]; f[2]=d[2]; f[3]=0; glLightfv(GL_LIGHT0, GL_POSITION, f ); } Point3f getDirFromTrackball(vcg::Trackball &tb){ glPushMatrix(); gluLookAt(1,-3,-5, 0,0,0, 0,1,0); tb.center=Point3f(0, 0, 0); tb.radius= 1; tb.GetView(); tb.Apply(false); float pos[4]={0.0f,0.0f,-1.0f,0.0f}; float d[16]; glGetFloatv(GL_MODELVIEW_MATRIX,d); glPopMatrix(); Point3f res(-d[8],-d[9],-d[10]); res.Normalize(); return res; } void drawLightDir() { glPushMatrix(); lightTrack.GetView(); lightTrack.Apply(false); #if 0 glPushAttrib(GL_ENABLE_BIT | GL_CURRENT_BIT); glColor3f(1,1,0); glDisable(GL_LIGHTING); const int lineNum=3; glBegin(GL_LINES); for(unsigned int i=0;i<=lineNum;++i) for(unsigned int j=0;j<=lineNum;++j) { glVertex3f(-1.0f+i*2.0/lineNum,-1.0f+j*2.0/lineNum,-2); glVertex3f(-1.0f+i*2.0/lineNum,-1.0f+j*2.0/lineNum, 2); } glEnd(); glPopAttrib(); #endif glPopMatrix(); } void drawFrame() { cgSettings.MakeShaders(); if (mol.DoingAO()) { // do at least one more step per rendering mol.PrepareAOstep(1); // continue until decent while (!mol.DecentAO()) mol.PrepareAOstep(1); } /*if (cgSettings.UseHalo()>0) { // write depth in HaloTexture glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, haloFrame); } else { // write depth in depthbuffer glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); }*/ mainCanvas.SetAsOutput(); if (cgSettings.doingAlphaSnapshot) glClearColor( cgSettings.P_halo_col, cgSettings.P_halo_col, cgSettings.P_halo_col, 0.0f); else glClearColor( cgSettings.P_bg_color_R, cgSettings.P_bg_color_G, cgSettings.P_bg_color_B, 0.0f); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); Point3f lightDir; if ( cgSettings.P_sem_effect // fixed light dir sem effect // || mol.sticks // quick Hack: fixed light dir when bonds ) lightDir= Point3f(0,0,1); else lightDir=getDirFromTrackball(lightTrack); setLightDir( lightDir ); // gluLookAt(0,0,-3, 0,0,0, 0,1,0); original // gluLookAt(0,0,-3, 0,0,0, 0,1,0); ok for tra gluLookAt(0,0,-40, 0,0,0, 0,1,0); if(MovingLightMode) drawLightDir(); glColor3f(1,1,1); if (1) { //track.center=Point3f(0, 0, 0); //track.radius= 1; //setProjection(); if (aniStep>=0) { double extraRot=360.0*aniStep; // set extra rotation for GIF animation: switch (hardSettings.GIF_ANIMATION_MODE) { default: case 0: glRotated(-hardSettings.GIF_ROT_SIDEVIEW_ANGLE,1,0,0); glRotated(extraRot,0,1,0); break; case 1: glRotated(-extraRot,0,0,1); glRotated(hardSettings.GIF_INSP_ANGLE,0,1,0); glRotated(extraRot,0,0,1); break; case 2:{ double substep[6]; for (int i=0; i<6; i++) { substep[i]=(aniStep*6-i)*90.0; if (substep[i]<0) substep[i]=0; if (substep[i]>90.0) substep[i]=90.0; } glRotated(-substep[5], 1,0,0); glRotated(-substep[4], 0,1,0); glRotated(-substep[3], 0,1,0); glRotated(-substep[2], 1,0,0); glRotated(-substep[1], 0,1,0); glRotated(-substep[0], 0,1,0); }break; } } setProjection( mainCanvas.GetVideoSize() ); track.GetView(); track.Apply(false); setProjection( mainCanvas.GetSoftRes() ); if (cgSettings.P_use_shadowmap()) { shadowmap.computeAsTexture( getGlLightPos() , cgSettings.do_use_doubleshadow(), shadowmapCanvas); //shadowmap.computeAsTexture( Point3f(0,1,0) ); } cgSettings.BindShaders(); glEnable(GL_TEXTURE_2D); //glBindTexture(GL_TEXTURE_2D, molTexture); glActiveTextureARB(GL_TEXTURE1_ARB); shadowmapCanvas.SetAsTexture(); mol.Draw(); // shadowmap.m.DrawShadowmap(false); glDisable(GL_VERTEX_PROGRAM_ARB); glDisable(GL_FRAGMENT_PROGRAM_ARB); glDisable(GL_BLEND); if (cgSettings.UseHalo()>0) mol.DrawHalos(); } } void SetTextureAccess(bool bilinear){ glActiveTextureARB(GL_TEXTURE0_ARB); moltextureCanvas.SetAsTexture(); if (bilinear) { glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); } else { glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); } glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); } /* void ReloadTexture(vector t, bool bilinear){ // glEnable(GL_TEXTURE); glEnable(GL_TEXTURE_2D); glActiveTextureARB(GL_TEXTURE0_ARB); glBindTexture(GL_TEXTURE_2D, molTexture); glTexImage2D( GL_TEXTURE_2D, 0, GL_RGB, //TSIZE,TSIZE, 0, GL_RGB, GL_UNSIGNED_BYTE, (void*)&(t[0]) ); SetTextureAccess(bilinear); }*/ int initGl(){ int res=0; glClearDepth(1.0); glDepthFunc(GL_LESS); glEnable(GL_DEPTH_TEST); glShadeModel(GL_SMOOTH); float pos[4]={0.0f,0.8f,0.6f,0.0f}; glLightfv(GL_LIGHT0, GL_POSITION, pos); glEnable(GL_VERTEX_PROGRAM_ARB); glEnable(GL_FRAGMENT_PROGRAM_ARB); if (!CgUtil::init()) res|=ERRGL_NO_GLEW; if(!GLEW_ARB_vertex_program ) res|=ERRGL_NO_VS; if(!GLEW_ARB_fragment_program ) res|=ERRGL_NO_FS; if (!shadowmap.init()) res|=ERRGL_NO_FBO_SHADOWMAP; if (!shadowmap.initHalo()) res|=ERRGL_NO_FBO_HALO; if (! AOgpu2::init()) res|=ERRGL_NO_FBO_AO; cgSettings.UpdateShaders(); //ReloadTexture(texture, true); return res; } Point3f RandomUnitVec(){ Point3f k; do { k=Point3f( (random(200)-100)*0.01, (random(200)-100)*0.01, (random(200)-100)*0.01 ); } while (k.SquaredNorm()>1.0); return k.Normalize(); } long int globaltime,startingtime; void StartTime();/*{ startingtime=globaltime=getTicks(); }*/ long int TakeTime(FILE *f , char *st);/*{ long int timen=getTicks(), delta=timen-globaltime; fprintf(f,"%5dmsec: %s\n",delta,st); globaltime=timen; return delta; }*/ /*long int TakeTotalTime(){ long int timen=getTicks(), delta=timen-startingtime; printf("------------------\nTotal time: %5dmsec\n",delta); globaltime=timen; return delta; }*/ float myfabs(float a){ return (a<0)?-a:a; } void Cycle( float &c, float min, float max, float step){ if (myfabs(c-max)<0.02) c=min; else { c+=step; if (c>max) c=max; } } int InitQuteMol(const char * filename) { CubeMapSamp::SetSize(CSIZE); OctaMapSamp::SetSize(CSIZE); if (filename==NULL) filename="porin.pdb"; mol.ReadPdb(filename); cgSettings.SetDefaults(); // initGl gets called from the GL canvas on startup. It's not // legal to call it before that time because the OpenGL context // does not exist yet. /*if (!initGl()) { printf("failed to initialize! :(\n"); return 0; }*/ //FillRandomTexture(); //mol.DuplicateTexels(texture, TSIZE); //ReloadTexture(texture, bilinear); return 1; } bool SaveImagePPM( const char * filename , const Byte *im, int sizex, int sizey) { FILE * fp = fopen(filename,"wb"); if(fp==0) return false; fprintf(fp,"P6\n%d %d\n255\n",sizex,sizey); int k=0; for(int i=0;i &im, int sizex, int sizey){ return SaveImagePPM( filename , (Byte*)(&im[0]), sizex, sizey); } bool LoadImagePPM( const char * filename , vector &im) { FILE * fp = fopen(filename,"rb"); if(fp==0) return false; int sizex, sizey, res; res=fscanf(fp,"P6\n%d %d\n255\n",&sizex,&sizey); printf("Loading %s (res=%d)...\n",filename, res); if (res!=2) return false; printf(" - size= (%d %d) ...\n",sizex, sizey); int k=0; for(int i=0;i\wxWidgets-2.8.0-msw-static\include;C:\Programmi\Dev-Cpp\wxWidgets-2.8.0-msw-static\include;C:\Programmi\Dev-Cpp\wxWidgets-2.8.0-msw-static\lib\wx\include\msw-ansi-release-static-2.8 Libs=C:\Programmi\Dev-Cpp\wxWidgets-2.8.0-msw-static\lib PrivateResource=qutemol_private.rc ResourceIncludes=C:\Programmi\Dev-Cpp\wxWidgets-2.8.0-msw-static\include;C:\Programmi\Dev-Cpp\wxWidgets-2.8.0-msw-static\include;C:\programmi\Dev-Cpp\include\wx-2.8 MakeIncludes= Compiler=-mthreads_@@_-D__WXMSW__ _@@_-DNO_GCC_PRAGMA _@@_-fno-rtti _@@_-fno-exceptions_@@_-DNO_DEBUG_@@_-DNDEBUG_@@_-DGLEW_STATIC_@@_ CppCompiler=-D__WXMSW__ _@@_-DNO_GCC_PRAGMA _@@_-fno-rtti _@@_-fno-exceptions_@@_-DNO_DEBUG_@@_-DNDEBUG_@@_-DGLEW_STATIC_@@_ Linker=-s _@@_-mwindows _@@_-lwx_msw_core-2.8 _@@_-lwx_base-2.8 _@@_-lwxjpeg-2.8_@@_-lwx_msw_gl-2.8 _@@_-lrpcrt4 _@@_-loleaut32 _@@_-lole32 _@@_-luuid _@@_-lwinspool _@@_-lwinmm _@@_-lshell32 _@@_-lcomctl32 _@@_-lcomdlg32 _@@_-lctl3d32 _@@_-ladvapi32 _@@_-lwsock32 _@@_-lgdi32_@@_-lopengl32_@@_-lglu32_@@_-lgif_@@_C:/programmi/Dev-Cpp/lib/libpng.a_@@_C:/programmi/Dev-Cpp/lib/libz.a_@@_ IsCpp=1 Icon= ExeOutput= ObjectOutput= OverrideOutput=0 OverrideOutputName=qutemol1.exe HostApplication= Folders=extlibs,gui,molview,vcg CommandLine=testosterone.pdb UseCustomMakefile=0 CustomMakefile= IncludeVersionInfo=0 SupportXPThemes=0 CompilerSet=0 CompilerSettings=0001000001001000000100 [Unit1] FileName=qutemol.cfg Folder= Compile=0 Link=0 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit2] FileName=wx_trackball.cpp CompileCpp=1 Folder=gui Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit3] FileName=AOgpu.h CompileCpp=1 Folder=molview Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit4] FileName=AtomColor.h CompileCpp=1 Folder=molview Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit5] FileName=CgUtil.h CompileCpp=1 Folder=molview Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit6] FileName=Common.h CompileCpp=1 Folder=molview Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit7] FileName=CubeMapSamp.h CompileCpp=1 Folder=molview Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit8] FileName=gen_normal.h CompileCpp=1 Folder=molview Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit9] FileName=gifSave.h CompileCpp=1 Folder=gui Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit10] FileName=HardSettings.h CompileCpp=1 Folder=molview Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit11] FileName=main.h CompileCpp=1 Folder=gui Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit12] FileName=Mol.h CompileCpp=1 Folder=molview Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit13] FileName=MyCanvas.h CompileCpp=1 Folder=molview Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit14] FileName=MyTab.h CompileCpp=1 Folder=gui Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit15] FileName=ShadowMap.h CompileCpp=1 Folder=molview Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit16] FileName=AOgpu.cpp CompileCpp=1 Folder=molview Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit17] FileName=AtomColor.cpp CompileCpp=1 Folder=molview Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit18] FileName=CgUtil.cpp CompileCpp=1 Folder=molview Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit19] FileName=Common.cpp CompileCpp=1 Folder=molview Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit20] FileName=gifSave.cpp CompileCpp=1 Folder=gui Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit21] FileName=HardSettings.cpp CompileCpp=1 Folder=molview Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit22] FileName=main.cpp CompileCpp=1 Folder=gui Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit23] FileName=Mol.cpp CompileCpp=1 Folder=molview Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit24] FileName=MyCanvas.cpp CompileCpp=1 Folder=molview Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit25] FileName=MyTab.cpp CompileCpp=1 Folder=gui Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit26] FileName=pngSave.cpp CompileCpp=1 Folder=gui Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit27] FileName=Sampling.cpp CompileCpp=1 Folder=molview Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit28] FileName=ShadowMap.cpp CompileCpp=1 Folder=molview Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [VersionInfo] Major=0 Minor=1 Release=1 Build=1 LanguageID=1033 CharsetID=1252 CompanyName= FileVersion= FileDescription=Developed using the Dev-C++ IDE InternalName= LegalCopyright= LegalTrademarks= OriginalFilename= ProductName= ProductVersion= AutoIncBuildNr=0 [Unit30] FileName=..\..\sf\wrap\gui\trackball.cpp Folder=vcg Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= CompileCpp=1 [Unit31] FileName=..\..\sf\wrap\gui\trackmode.cpp CompileCpp=1 Folder=vcg Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit32] FileName=saveSnapDialog.cpp CompileCpp=1 Folder=gui Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit33] FileName=saveSnapDialog.h CompileCpp=1 Folder=gui Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit34] FileName=progress.cpp CompileCpp=1 Folder=gui Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit29] FileName=main.rc Folder=Resources Compile=1 Link=0 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit35] FileName=progress.h CompileCpp=1 Folder=gui Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit36] FileName=glewsrc\glew.c CompileCpp=1 Folder=extlibs Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= qutemol/src/MyCanvas.cpp0000444000175000017500000001562310633257536013657 0ustar mbamba #include #include "MyCanvas.h" #include "HardSettings.h" MyCanvas mainCanvas(MyCanvas::COLOR_AND_DEPTH); MyCanvas shadowmapCanvas(MyCanvas::DEPTH); MyCanvas shadowAOCanvas(MyCanvas::DEPTH); MyCanvas haloCanvas(MyCanvas::DEPTH); MyCanvas moltextureCanvas(MyCanvas::COLOR,hardSettings.TSIZE); #define INVALID_ID 666 typedef unsigned int uint; bool MyCanvas::SetAsOutput(){ if (onVideo) glBindFramebufferEXT( GL_FRAMEBUFFER_EXT, 0); else { if (frameID[ currentRes ] == INVALID_ID ) { if ( !InitRes() ) return false; } glBindFramebufferEXT( GL_FRAMEBUFFER_EXT, frameID[ currentRes ] ); } return true; } bool MyCanvas::SetAsTexture(){ glBindTexture( GL_TEXTURE_2D, textureID[ currentRes ] ); } MyCanvas::MyCanvas(Kind k, int size){ currentRes=0; onVideo=false; kind=k; for (int i=0; i=MAX_RES) { i=MAX_RES-1; softRes=1< &t, int siz){ /*s.Smooth( t, siz, tx, ty);*/ } void SmoothTexture(vector &t, int siz){ /*s.Smooth( t, siz, tx, ty);*/ } void FillTexture(vector &texture, int textsize) { s.FillTexture(texture, textsize, tx,ty, cr,cg,cb); } Point3f trp; float trr; // transormed pos and radius void Transform(const Point3f &ax,const Point3f &ay,const Point3f &az){ Point3f p(px,py,pz); trp[0]=p*ax; trp[1]=p*ay; trp[2]=p*az; //printf("[r=%f] (%f %f %f) -> (%f %f %f)\n", r, px,py,pz, trp[0],trp[1],trp[2] ); } void ScaleTransl(float dx, float dy, float scale){ trp[0]=(trp[0]+dx)*scale; trp[1]=(trp[1]+dy)*scale; trr=r*scale; //printf("[%f*%f] -> (%f %f %f %f)\n", r, scale, trp[0],trp[1],trp[2],trr ); } // color from atom name void getCol(const char* st); QAtom(string st); static bool readError; static char lastReadError[1024]; void UpdateColors(float mode); // sends impostors on screnbuffer void Draw(); // sends halos on screnbuffer void DrawHalo(); void DrawShadowmap(); // for GPU ao. void DrawOnTexture(); /* bool operator < (const QAtom& a) const { return trp[2]>a.trp[2]; } */ static unsigned int VBOsize(); void VBOfill(float * f); static void VBOsetup(float *f); //inline bool operator <= (QAtom const &a) const { return px<=a.px; }; inline bool operator < (QAtom const &a) const { return px< a.px; }; }; class Bond{ public: Point3f a, b; Point3f dir; Point3f col1, col2; float lenght; Point3f startp; // start of parameterization const QAtom *atmA, *atmB; bool hetatomFlag; //Point3f cola, colb; void Draw(); void DrawHalo(); void DrawShadowmap(); //Bond(Point3f a,Point3f b, float rada, float radb, Point3f col1, Point3f col2); Bond(const QAtom &a,const QAtom &b); void UpdateColors(); // copies color from atoms void DrawOnTexture(); // for GPU ao. bool AssignNextTextPos(int texsize); int tx, ty; }; class Mol{ public: bool sticks; // true if ball_and_stick mode float colMode; // mode = 0 -> per atom // mode = 1 -> per chain void SetColMode(float newColMode); void SetBallAndSticks(float rad=0.3); void SetLicorice(float rad=0.5); void SetSpaceFill(); vector atom; vector bond; float px,py,pz,r; bool textureAssigned; void Draw(); void DrawShadowmap(bool invert); void DrawHalos(); void DrawOnTexture(); void FindBonds(); void ComputeSize(); bool ReadPdb(const char *filename); float tx0,ty0,tx1,ty1; // bounding box transformed void Transform(const Point3f &ax,const Point3f &ay,const Point3f &az); void ScaleTransl(float scale){ for (int i=0; i &t, int siz){ for (int i=0; i &t, int siz){ for (int i=0; i &t, int size); void FillTexture(vector &texture, const vector &sumtable, int texsize, float div ); bool ReassignTexture(int textsize); // for a given texture size void ReassignTextureAutosize(); // autoselect texture size int NTotTexels(){ return atom.size()*atom[0].s.TotTexSizeX()*atom[0].s.TotTexSizeY(); } // vertexbuffer objects unsigned int vboNorm, vboShadow, vboAO; unsigned int vboNormSt, vboShadowSt, vboAOSt; // for the sticks Mol(); char filename[1024]; char* GetFilenameTex(); char* GetFilenameSnap(); char* GetMolName(); bool PrepareAOstep(int nsteps=1); float PredictAO(); void ResetAO(); bool DoingAO(); // true if AO is being computed bool DecentAO(); // true if AO (being computed) is "decent" // for testing purposes bool PrepareAOSingleView(); int natm, nhetatm; // number of atoms of type hetatm and not ... bool IsReady(){return ready;} void UpdateColors(); private: // unsigned int DL_bonds, DL_atoms; // display lists (UNUSED) void AddBond(int i, int j); void PrepareAOallAtOnce(); int AOdoneLvl; void PrepareAOstart(); bool AOready; bool AOstarted; bool ready; }; extern float stick_radius; qutemol/src/gifSave.cpp0000444000175000017500000001014310542044036013476 0ustar mbamba/* GIFWRAPPER! This file is included in QuteMol project as temporary hack waiting for WxWidgets to support saving in GIF format (patent is now expired!) */ #include #include #include using namespace std; typedef unsigned char Byte; typedef vector Frame; #include "gifSave.h" // global vairables static vector frames; static vector delay; static ColorMapObject* outputPalette; GifWrapper::GifWrapper(){ frames.clear(); delay.clear(); } static int gifsx, gifsy; bool GifWrapper::AddFrame(Byte* data, int sx, int sy, float dt){ gifsx=sx; gifsy=sy; unsigned int npix=sx*sy; int paletteSize=256; Frame output(npix);//=(Frame) malloc(npix); if (frames.size()==0) { Frame r(npix),g(npix),b(npix); // de-interlaeve for (int i=0, j=0; iColors) == GIF_ERROR) return false; } else { // maunal assignment of color indices for (int i = 0, j=0; i < npix; i++) { int minIndex = 0, minDist = 3 * 256 * 256; GifColorType *c = outputPalette->Colors; /* Find closest color in first color map to this color. */ for (int k = 0; k < outputPalette->ColorCount; k++) { int dr = (int(c[k].Red) - data[j] ) ; int dg = (int(c[k].Green) - data[j+1] ) ; int db = (int(c[k].Blue) - data[j+2] ) ; int dist=dr*dr+dg*dg+db*db; if (minDist > dist) { minDist = dist; minIndex = k; } } j+=3; output[i] = minIndex; } } frames.push_back(output); delay.push_back(int(dt*100.0)); return true; } bool AddLoop(GifFileType *gf){ /* yes this was another attempt at supporting the loop extension */ int loop_count; loop_count=0; { unsigned char nsle[12] = "NETSCAPE2.0"; unsigned char subblock[3]; //if (EGifPutExtension(gf, 0xFF, 11, nsle) == GIF_ERROR) { if (EGifPutExtensionFirst(gf, APPLICATION_EXT_FUNC_CODE, 11, nsle) == GIF_ERROR) { //gif_push_error(); //i_push_error(0, "writing loop extension"); return false; } subblock[0] = 1; subblock[2] = loop_count % 256; subblock[1] = loop_count / 256; //if (EGifPutExtension(gf, 0, 3, subblock) == GIF_ERROR) { if (EGifPutExtensionLast(gf, APPLICATION_EXT_FUNC_CODE, 3, subblock) == GIF_ERROR) { //gif_push_error(); //i_push_error(0, "writing loop extention sub-block"); return false; } #if 0 if (EGifPutExtension(gf, 0, 0, subblock) == GIF_ERROR) { gif_push_error(); i_push_error(0, "writing loop extension terminator"); return false; } #endif } return true; } bool GifWrapper::Save(const char* filename){ if (frames.size()==0) return false; GifFileType *GifFile = EGifOpenFileName(filename, FALSE); if (!GifFile) return false; if (EGifPutScreenDesc( GifFile, gifsx, gifsy, 8, 0, outputPalette ) == GIF_ERROR) return false; if (!AddLoop(GifFile)) return false; for (int ni=0; nieVBl"#Ya@Ņ VHUĂ H(gAZU\8ܧ}zy&j9R<:OHɽH gyx~t?op.$P&W " R.TSd ly|B" I>ةآ(G$@`UR,@".Y2GvX@`B, 8C L0ҿ_pH˕͗K3w!lBa)f "#HL 8?flŢko">!N_puk[Vh]3 Z zy8@P< %b0>3o~@zq@qanvRB1n#Dž)4\,XP"MyRD!ɕ2 w ONl~Xv@~- g42y@+͗\LD*A aD@ $<B AT:18 \p` Aa!:b""aH4 Q"rBj]H#-r9\@ 2G1Qu@Ơst4]k=Kut}c1fa\E`X&cX5V5cX7va$^lGXLXC%#W 1'"O%zxb:XF&!!%^'_H$ɒN !%2I IkHH-S>iL&m O:ňL $RJ5e?2BQͩ:ZImvP/S4u%͛Cˤ-Кigih/t ݃EЗkw Hb(k{/LӗT02goUX**|:V~TUsU?y TU^V}FUP թU6RwRPQ__c FHTc!2eXBrV,kMb[Lvv/{LSCsfffqƱ9ٜJ! {--?-jf~7zھbrup@,:m:u 6Qu>cy Gm7046l18c̐ckihhI'&g5x>fob4ekVyVV׬I\,mWlPW :˶vm))Sn1 9a%m;t;|rtuvlp4éĩWggs5KvSmnz˕ҵܭm=}M.]=AXq㝧/^v^Y^O&0m[{`:>=e>>z"=#~~~;yN`k5/ >B Yroc3g,Z0&L~oL̶Gli})*2.QStqt,֬Yg񏩌;jrvgjlRlc웸xEt$ =sl3Ttcܢ˞w|/%ҟ3gAMA|Q cHRMz%u0`:o_F?IDATxڼypՙ{43iF$K%ٖT6  x&ln9@a YBpPE +acp[-,htXscنU{;`qiZKKK~~0T.ضĄx_^/v8Z+? [lPQQQ2mK8Rb3 >=Owqa[񚫮jaz__X$2%mT5 UU`@UU/o}Aݺo߾ϴ8N @u9 e!R"4M ],_|ѣGn?YӴ\,\8 1 (ʟm)'JoOTIˮ[*:V,BxGWZ;{-~=X0ʹrƼǕ]{= Q^^-8َoX߿n H]'?9~RZ`7t2>!eQ?]׷! `yHۍa6y }n'>ir`r/|b7_GEm-ښ5(55XǏc|E^xyb:TEQ( eds=ر#׀+vYz=<|8T\\h`Nk?'xոdyWdxֶmҪJχ  E 9|nt;fv:(s03CRi^+lSn CCCCK00 @?d$_W_MQi)ʊ(j 5kBo+ t|,F6BۇFf2(B {zRre34RJ,FJ-%B4M뮫|ꩧz/+`M$tL 8џR>N80>ΛLhͭ49L|k_⇏=^p, ^ 튳B%˙RTYʉ m?c_+|K`Vʪp8EiRI*--_O0ݮ.D2!Rr6}G|{YTڙJ1ОXO@ Dȁ87wnK{~U.iA(>z{{1Mmۮgݺux^֬YC__<%իؿmVɡCscA$"Tl,_:!01Aeq IbEM)(YvQUb$ֶm{`0 PAN~g:⒒ xi"dž(oI)N*%m?aҥH)y'qwBJ 2y"wV 6X_SC~l0&Iԗ^­UmE>uM6L@)9FCTUU~h瓧ow(->6o_<# "pUqRQSDg8GYI[o cLS8NBkqK2_ <"F9Pm Eq R@NR??kph'LiP(`f$Q hcOir2S|^銙Y UӼ:28/\f!mLՃ˷"/|RZxpX&f_lr@>uMZ+Wݱ}bjାr}BrCmiD,3Kt8S$O@+,[ Íp! sOҌR!мFx)8Sc$HLr©rSPƍ8Cy+JicݢH)mEAm !R=0)f$Vxf5z%%%T/fS0H b\.G٫( lСC35Ѱ+1m{@%o3_cT9, O`E555TWWq؜i옃O<;[p>{m{[RBQQFۏ9"r `r~?B>Bv'5]H\"L&W466|ر 8ά1im *B1c MQUoО={~ 4_+7744d ssf{'Q)BR[o=F`0]\\D4bsB;y#### `Jӓ]$KiiO(Q{ U9-qc``i}'vmѮ#dr.Z0^JYSEQテn;ifW00H$/r؝w9p!&E̗7wDGFFRʝt]On}B|>8fp-T\؞/ !.vI oQIENDB`qutemol/src/image/qutemol.ico0000444000175000017500000004220610507313254014661 0ustar mbamba F   00 %v h@(0 `  0HTP=$#VvH0.33( _bbbzzz999c9F"""㲲ggg ;9W* oΡttvMM<<>><<&&qz> ) ~~~~~~vvx@@>>{{EEE< ,444~~~~~~|||wwwQQ{wwws) $ }}}{{{uuu__a999B`zzz~~~{{{uuu```vvvT B)))}}}||||||vvv```~~~W 8]]==;;==FFVVnnxyyywww___UUUJ E=@@AA@@>>==;;99OOqqs^^^ 2W//JJNNMMGGAA==<<99DDZZqhhN_==^^nnnn``NNBB>><<669M" V Y=={{ffMMAA==33d= E$$`튊YYFF@@""hr;+# *^^]]II;;9IUUooTT:: VR+''b%%d6^"?muG 0;<2!  ?( @   &.1,#  4Phw{saH-   !GtlJ726::3( J***___lllQQQ}~jN1  <}䋋\\\qG&  #_ߜeeeHHH &!!c++++ ` !_8  5~ZZZii====>>>>==''u yI" Cج~~~|||``99<Ӧ}}}|||yyyooo[[\PPPz: /u;;;}}}{{{yyyooo]]]FZsss}}}|||zzzppp]]]LGeee||xx~xxxxxx{{{||||||zzzppp]]]JADDJLL::;;;;99??LLaa|ttuyyyzzzqqq[[[ppp@J$$l??????>>==<<;;99??\\}tttrrrXXXj0Z @@DDFFEECC@@>>==<<::77GGoopYY^ww~FFFI $g=HHNNSSTTPPJJCC??==<<::66QQxMM|DD+++^)&lXQQ``kknnhh\\OOEE??==<<::--nBQ- a0 %iM\\xxwwaaPPEE??==<<\sO+^ bbww]]KKBB??==>zcXPB0 KIIhhQQFFAA99n:$ 3w-wwjjTTGGCCHD OJ||bbPPGG!!b^&  *`$GGmmooaaRR997n5/^+.j9)LryU0 /DT]^WH4   ?(0` %       #-49;:5-$  '9JYelomeZK:)  4Mf~hP;*    !;Z{iSE>>BFHHD=4)  ;`@@@PPP@@@yrsw|zqdSA/   4[<<<𞞞>>>qX?) (N}yyyuuukN5"   :hyyymmmKKK111  A""g))z((y!!b:}^C- $LAAA}}}UU`??;;====>>>>>>99 `qT8" .\樨}}}vv{EE::==>>====<<==44 _># 7h%%%~~~}}}{{{nnw::;;<<<<;;]]{{;;>c=  <pSSS~~~~~~~~~~~~}}}{{{tttRR88::EESSS\5 >riii~~~~~~~~~}}}{{{yyytttffl66@@}N* <p[[[}}}~~~|||||||||yyysssiii>>}wwg;# 7i...~~~~~~||||||zzzyyyrrrhhhSS]@@@}L- /]~~~{{{}}}{{{xxxrrrfffYYYZ6 &N]]]|||{{{yyyxxxrrrfff[[[f=  ?p풒~~~~~~}}}|||xxxrrrddd\\\555lA 1_TTT}}}}}}||||||{{{yyysssfff\\\AAAnC 'RKKK|||uuuwwwxxxyyy{{{||||||||||||zzzssseeeZZZ...k@  #L555__AA999999<>??>>>>==<<<<;;9977;;UU}qqrvvvuuuhhhRRRyyy wG* 2a77BBBBCCCCBBAA@@??>>==<<<<::9977??ffpssskkkQQQoooTTT_6! :l*DDEEHHIIJJIIHHEEBB@@>><<==<<;;997777ddnmmmOOeQQyVVVsF%  @u\HHLLOOSSUUTTQQMMIIDDAA>>==<<<<;;9955@@~llm>>66hh!!!}R.  Dz))|LLSS[[cceeeeaaZZTTLLFFAA??>><<<<;;886699]..8822 ^"555AAA,,,|V4  Dz,,RR__kkuuzz{{uummccXXOOGGAA??====<<::00rQ4  Bw''qWWjj~~uuffXXNNFFAA??====<<--t]D-   <oG[[uuwwddVVKKEE@@??==<<$$n{smg^RC2"  4d VVzzoo^^PPHHCC@@>>==;qVF>95/( *T33uuyyddTTJJEEAA@@66tK0!   Ct]]||eeWWKKGGCC@@<W0  0Z?ppyyccVVKKGGDD%%nk>   AmFlloo]]QQKKGG&&r|O* *Lw HHss~~yyll__TTMM??BZ4   0Qx*//yFFNNLLAA//E^:  0Np|Z:!  ,E`{jN4  #5J^o}tdQ<) $1=GNRSPJ@5(    $''%"     xp`~`@@@@@@@@````````@@@``?``p(  @'lE&('!888___J S%%%wwwSS`9988##j }- qlll~~~|||VViiDDD'f[[[~~~zzzddi%%%V?ȗ~~~{{{fffXXXp+OO|IIEEOOccxxyfff:::a< BBGGCC>>;;DD``j3I.[[ssggLL??;;##TI224D;uummHH>> SA"88syyMM&&s)9""IJJ<<PD ,dj2   ??qutemol/src/image/geo2.png0000444000175000017500000000213410515252127014035 0ustar mbambaPNG  IHDR()GksBIT|d pHYss,tEXtSoftwarewww.inkscape.org<IDATX_UULSfaf&:Zd&QY=d& C z!!((("'uB0H!Ѡ40',g{νs`sg﬽o-ƁI p x9m` 4h|~xXި_{kn`ar` ?,6` uvՎ8~cY\a;>Ec>5U[ۇZ82J X\~U +דHa+ۇ[e S'TK<M^$eˌz,nA;Igʨ2u+eeI !wm LQ` PI#F0SwE;ϭ)>pwm225@_Na`TU:K6P-2.NJJȻ_bcm+ Wޛ)W̻>l.f{,Wv3{E)S%!jD;vj}d_F՝$P+y^ !+ 3)fmJsmLz#D+MTKDU-}3 K&I?Yƒ/=(Q*7F gWZ8PC'mez3 ̦ ;H'*Ѥϙ^z뀪qIr?4^9`N^E(+ e-,-x&jx@NG$|J+t?e 7M,E7Z +D,=RGi[i\3&pX=LJI"Eޤkfn;G Kb.CpAҊtA}7ݥgIKKc5 Xf^N\p {ڭ2g?UzF"l%\3"F"wSIENDB`qutemol/src/image/gear2.png0000444000175000017500000000776710464752122014225 0ustar mbambaPNG  IHDRFΨ pHYs   MiCCPPhotoshop ICC profilexڝSwX>eVBl"#Ya@Ņ VHUĂ H(gAZU\8ܧ}zy&j9R<:OHɽH gyx~t?op.$P&W " R.TSd ly|B" I>ةآ(G$@`UR,@".Y2GvX@`B, 8C L0ҿ_pH˕͗K3w!lBa)f "#HL 8?flŢko">!N_puk[Vh]3 Z zy8@P< %b0>3o~@zq@qanvRB1n#Dž)4\,XP"MyRD!ɕ2 w ONl~Xv@~- g42y@+͗\LD*A aD@ $<B AT:18 \p` Aa!:b""aH4 Q"rBj]H#-r9\@ 2G1Qu@Ơst4]k=Kut}c1fa\E`X&cX5V5cX7va$^lGXLXC%#W 1'"O%zxb:XF&!!%^'_H$ɒN !%2I IkHH-S>iL&m O:ňL $RJ5e?2BQͩ:ZImvP/S4u%͛Cˤ-Кigih/t ݃EЗkw Hb(k{/LӗT02goUX**|:V~TUsU?y TU^V}FUP թU6RwRPQ__c FHTc!2eXBrV,kMb[Lvv/{LSCsfffqƱ9ٜJ! {--?-jf~7zھbrup@,:m:u 6Qu>cy Gm7046l18c̐ckihhI'&g5x>fob4ekVyVV׬I\,mWlPW :˶vm))Sn1 9a%m;t;|rtuvlp4éĩWggs5KvSmnz˕ҵܭm=}M.]=AXq㝧/^v^Y^O&0m[{`:>=e>>z"=#~~~;yN`k5/ >B Yroc3g,Z0&L~oL̶Gli})*2.QStqt,֬Yg񏩌;jrvgjlRlc웸xEt$ =sl3Ttcܢ˞w|/%ҟ3gAMA|Q cHRMz%u0`:o_FIDATx|KlUƿ3s9YOS) Dqxk8g AW:c˙LזbLPW hX|ׯm'nM)+~'!%pq0u롹9e\̙Hh6 ;6BL)ɛ]]e١TUA1n_3/2˗pLVKt݀y>sBBz33{``\\RRGG22a==rPPKK??u==SSUULL..[eeooRRFFBBxJJGG==CC|00\ppYYLLFFMMLL}}33n))\QQrr^^DD|NNOO||dd``VVKKGGPPMMjjVVPPEE~IIFFDDFFEE55s??EEFFCC   C)^ 5cY ;S^N z{|}~Y)6^mnop_qrstu4vAwxy"abc4Cdefghi)jklVWXYZ4*[\]^_5+`"KLMN4OPQR*STU<=>?@ABCDEFGHIJ ./0123456789:; #$%&'()*)+,-  !"    ( @  $ *""0%%:**G--Q00X22^33b55d55f66h77k88n99p99q::q;;q;;r<>t>>u??v??v@@w@@wAAxAAxAAxAAyBByBBzBBzBB{CC{CC|CC}DD}DDDDDDDDDDEEEEEEFFFFGGGGGGGGHHHHIIIIIIJJJJJJJJKKKKKKKKLLLLLLMMMMNNNNNNNNOOOOPPPPPPQQQQQQRRRRRRSSTTUUVVWWXXXXYYYYZZ[[]]^^^^^^____````aaccdd}ee{ff}ggiijjkkiiiiiiiikkmmnnpprrttvvwwxxzz{{||}}~~äunH=?Scuv.8?GIK5[үv+6;@GMSVRY\I84)14DGJQRX[KҋY[G=&(-6==JQQX[\Yic]RH4',4;AHMQVX[[K|jkd\QA1(4;ADDQVV[]Kjyjg_YJ;&,4Yã|||zjd]Q?*& &,6;>à~{ykcWJ6(($ $$+.àxj^R=1$$ $?äx_[G4$$ nêݧj_Q?+$-4;;+ GuôߚjcVH4$$4;@G;蜉ݜxk]Q;&$$4;AG?a·yj]XE+$16AD.ўzjc]Q=(16;.vΒzje_UH6&+4-.򒂃{zkd]R@4$mΤzzjg]W?.uџzjfluvѯ(0` 7**S..Y//\00^11`22b33d55g66i66j77k77l88m88m88n88n99n99o99p::p::q::q;;r;;s;;t;;t;;s<>z??{??z??z??z??z??z??{@@|AABBBBCCCCCCBBCCCCDDDDEEEEEEFFFFGGFFFFFFGGGGHHIIIIJJJJKKLLLLLLLLLLMMMMNNNNOOOOPPQQRRRRSSTTWW\\]]\\ZZWWWWXXYYZZ[[\\^^__``aa````__````aabbddeegghhjjmmnnqqssssttttttssrrrrttvvxxzz||~~бx\[[\vxƑ[+'+--69:@DIwЛ] "#'+,48:;BDFGvо/ !"'+-/69;BDFGIQйw:-#"'++-48;@BDFGJNxпwG;,$""##+.69:@BDFGIMPxЏSMD6.'!"#,.448;@BDFJLMPИ`TRG@6," "#+,-.8;@BDFGIMPSиt`VRLD;4$!"#+,-48;@@DFGGMPPgВda`VRJD9-# !"'+,/699;BDFGJMPRлtkc``TPG@6+""'+,-/46;BDDFJMMRgКomdb`XSMD:-'!#'+,/49@@@BFFGNPRйxomkca`WRGB8," "'+,-/8:;;BEFGMPQй[knmkc`_TPF;4$!!"'$,-466:@DFGINPvо: #ppnkd`XSJB8,# !#$+,--6:@BBFJMPYЛ] Mqqpjd_WQG@4+! "#$,-/69;@@DGJPRБE-" `rsshe_VMD9," !"'+,/468:@DGINPБI;,#  h||uje_QG@/'! "##+,-.6:@BDGMPИVJB4,#  z|{hbVPD8,# "#''+-66;BDGJPаeTQG;6+   y|uf_SG@4+  "''+-46:@BGGYz`VRJD:-'  v{hcWMD8,""#'+,-4:;BFGvЛkaXTPGB8,"  Y{ueXQF@4' "'+,.:;BDG{kc`_TPG@6+!  +hh`TIB6,""+,-6:@DGаqnkb`WSLD9-#  @_WME@4# "+,-69@BvГrokc`_VQG@6,"  8GFB6$"'+,49;BЌrpnkc`XTMF:/'   ''"#+,46:v~rrqokc`WSJB8,"  !#$,-6Qй~rrrnjd_VPF@/$    "'+-:а~}rrshc_TMB8,"   "#+/а~||thcXQG@.'   "#8е|uhaVMB6,"   Yƃ|teXQG@/'  @Ј{hbWMD6,""##'+#  [ДۥufXQF;/'!"#++,/' [Тߨ{h`TJB6+!"++,4666,ʇި|hcXPE;.""$,,/68;WП|td_SGB8$"$+,469@л|te`TIE;, "#+,/69XО|qe`WPGB4$ !#$,-48Д}rqkaXSPF;4+! #'+-6xʊ~rpkb`WRG@6,# "#+-\п~rpmd`XTPF@4+""#+vƖ~rqnkc`XSND:-' !+xа~rpmda`TPGB6,#[Ɲrqokd`_TPFE\е{zuvx(0`||ii__^^aannddAAy??z@@}BBBBDDEEFFGGIIMMqqZZ;;r<>x??z@@}AACCEEFFFFHHIIJJKKkkCC~<>x;;r::p;;r==w??y@@{@@}BBCCEEFFGGHHIIJJKKLLMMxxqqKKFFAA~??{==u99n;;r>>w>>y>>x@@|BBDDEEFFGGHHIIJJKKLLMMNNvvPPMMIIDDBB??z;;r;;r<>w>>yAA~BBCCCCEEFFGGHHIIJJLLLLMMNNVVQQOOKKGGDDAA}==v;;r<>y@@|AA~BBBBEEFFGGHHIIJJKKLLMMNNPPffWWRROOLLIIFFCC??{<>x@@{AA~BBCCEEFFGGGGIIJJKKKKMMNNNN``\\YYUURROOLLIIEEBB>>y<>x??z@@|AACCCCEEGGGGGGHHJJJJKKMMNNOOyybb``]][[YYUUSSOOKKHHEEAA~==w<>yccccaa__\\XXTTPPLLHHEEAA>>x<>y??{@@|AA~BBBBDDFFGGHHHHJJLLMMNNUUXX;;r77k77k77j44e11_--XMMeeeeddaa\\WWSSOOKKGGCC@@{<>w>>y??{AA}BBCCDDEEFFGGGGIIKKLLNNOOKKBB==v99p88m77j66h44e11_//[XXkkllhhbb]]WWRRMMIIEEAA==w<>x;;s77k77k88l66i33c//[22affyyuunnee]]VVPPKKGGCC??z<>x>>y@@|AA~BBBBDDFFGGHHIIKKMMNNRRLLHHCCAA>>x::p99n99n88l55h44e00]55ftt||ppddZZRRNNIIEEAA>>x;;r<>x??y??y@@|BBDDDDFFHHIIKKLLNN^^QQOOKKFFDD@@}<>w??y??z@@|BBCCDDFFGGHHKKKKXXzzXXRROOLLIIFFBB??y;;s::p::p99n88l66j33b..Z55doowwee[[SSMMIIEEAA~>>w;;q;;s==v>>x??z@@|AA~BBCCFFFFHHJJKKmm]]YYTTQQNNKKHHEEAA~==w;;r::q99o99o88l66i22a//[33cVV||ll^^UUOOJJGGCC??z;;r::q;;r<>w@@|AA~BBDDFFGGIIKKeeaa]]ZZWWSSPPLLIIEEBB>>x::q;;r;;r::p99o88l55g11`00]44e77jIIVVSSMMJJGGCC>>x::q;;q<>x@@|AA~CCDDFFmmuujjggeebb__[[XXSSPPLLHHEEAA~==w;;r::p::q::p99o88l66i33c//\//Z33c66h66i77j88m99n88m99n99o99p;;r<>y??{AA~BBDDOOpplljjhhffcc``\\VVRRNNJJGGCC??{<>w??z@@|BBFFqqoommllllkkggaa[[VVQQMMHHEEAA~==v;;r;;r::q::q99o99n88m66i33d//[--X22a55f66i77j77j88l99o::p::p<>y@@|CCttqqrruuyyxxssllcc[[UUOOKKGGBB??z<>xEE~vvuuxx؂؉֊҄zznnbbYYRRMMHHDDAA~==w;;r::q::p99o99n77k77j66i55h33c00]..Y11`55f77k88m99o::p;;q::q<>x>>y??z@@|>>x::q77k44f22a00^00]44d<>y@@|@@|AA}CC??z99o55g11_dd{{냃盛纺楥يssccXXQQLLHHDD@@|<>w::q::q;;s;;r==v??{AA~AA~CCDDEEFFSS||뇇螞赵뿿븸奥ݎxxff\\VVPPKKHHEE??{;;s;;q;;s;;s==v??{@@|AA~CCDDEEGGꌌ睝秧妦⚚ۈuuff^^XXQQLLJJFFAA~<>x@@|AA~CCDDEETT{{爈䐐ᑑ݊}}ppee^^XXSSNNKKHHCC??{<>x??{AA~BBCCEEzz{{~~~~{{ttllee__YYTTPPNNJJFFCC@@{<>x??z@@}BBDDyywwvvuussooiidd__ZZVVSSOOKKGGDDAA>>x;;r<>y@@|BBhhuurrppllhhdd__\\XXTTQQNNJJGGCC@@|==u;;s==v>>x@@{llttoolliieeaa^^[[WWTTPPMMIIFFBB??z<>x[[Ækkeebb^^\\XXUUQQNNJJJJhh~~rrnnmmttqutemol/src/image/quiton.png0000444000175000017500000000114510462062666014531 0ustar mbambaPNG  IHDRV%,tEXtCreation TimeMon 24 Jul 2006 16:01:57 +0100GtIME*-p pHYs  ~gAMA aIDATxڥSA}#+"   ~F"F`* b`dx+\-~knd2^+r9aw\.\WmnrO`0@PB!qs (L=r~<pn|>ra2t:n6Ah4v`hDViժԁ64 .V:fαXLKUÁt:-1̈lrD>gِJ$0:01P*bT";38(~JEZ.YN1lgY10:ϪA p:@f%%?@eIENDB`qutemol/src/image/snap_noborder.png0000444000175000017500000001100110634260666016036 0ustar mbambaPNG  IHDR szz pHYs  ~ MiCCPPhotoshop ICC profilexڝSwX>eVBl"#Ya@Ņ VHUĂ H(gAZU\8ܧ}zy&j9R<:OHɽH gyx~t?op.$P&W " R.TSd ly|B" I>ةآ(G$@`UR,@".Y2GvX@`B, 8C L0ҿ_pH˕͗K3w!lBa)f "#HL 8?flŢko">!N_puk[Vh]3 Z zy8@P< %b0>3o~@zq@qanvRB1n#Dž)4\,XP"MyRD!ɕ2 w ONl~Xv@~- g42y@+͗\LD*A aD@ $<B AT:18 \p` Aa!:b""aH4 Q"rBj]H#-r9\@ 2G1Qu@Ơst4]k=Kut}c1fa\E`X&cX5V5cX7va$^lGXLXC%#W 1'"O%zxb:XF&!!%^'_H$ɒN !%2I IkHH-S>iL&m O:ňL $RJ5e?2BQͩ:ZImvP/S4u%͛Cˤ-Кigih/t ݃EЗkw Hb(k{/LӗT02goUX**|:V~TUsU?y TU^V}FUP թU6RwRPQ__c FHTc!2eXBrV,kMb[Lvv/{LSCsfffqƱ9ٜJ! {--?-jf~7zھbrup@,:m:u 6Qu>cy Gm7046l18c̐ckihhI'&g5x>fob4ekVyVV׬I\,mWlPW :˶vm))Sn1 9a%m;t;|rtuvlp4éĩWggs5KvSmnz˕ҵܭm=}M.]=AXq㝧/^v^Y^O&0m[{`:>=e>>z"=#~~~;yN`k5/ >B Yroc3g,Z0&L~oL̶Gli})*2.QStqt,֬Yg񏩌;jrvgjlRlc웸xEt$ =sl3Ttcܢ˞w|/%ҟ3gAMA|Q cHRMz%u0`:o_FIDATx]l3;]޵LM0RRl\Cbu"ڈJQAԪP_OLKTkjڂq7^wgfeRQUFss{%!f>'$I|B'z122"t]8P(AģLJz˲p˲Pp]0ODpku]dioo0 9wq2 I&~r\NtwwNGjq#=.zG(8::*JBpЛضCSS---k0554piǏG}(TOOaDظq#ׯ5$CCC(iyb*Çoض"(hghhcǎ.gΜaΝLLL @52LLLPTH$T*_N&ԩSR5x׈'jIr9,e||gnݻ$IAiU0v,ʥ2pP8L4440==yq,}}}:ujuq?W^uI$ ۶qn^"Kcc#crr50}kP8L3;7cL3"mkWرc'~PW[KX(?ghxQ__i$IdIPX`6?GY7)a!PCK%ҩfdI!BT)Y!@ q|D#eR|-fS,)J, 7Rߘ;B cj9@<\AhؖEMM 1*dY8={شi DT!jXEEu`y1bXSU˶ |2333H$mz4b˲e!@Dy*A"\UW+˩UQ¡0 E'r <#ϓN1 ]v,yX yj.Uݰ8,VCXDjjiL0R)"WHֳP60ʋSidY bxGPnۂn踎iI;Ë6hE;?ĢQbׂ,S1-ޯꢳޥb^Q~ZwzV۱ђoFFw}AHSj u8;GwWٿER{^_5OݢxGSP}sG{̳WM4eVBl"#Ya@Ņ VHUĂ H(gAZU\8ܧ}zy&j9R<:OHɽH gyx~t?op.$P&W " R.TSd ly|B" I>ةآ(G$@`UR,@".Y2GvX@`B, 8C L0ҿ_pH˕͗K3w!lBa)f "#HL 8?flŢko">!N_puk[Vh]3 Z zy8@P< %b0>3o~@zq@qanvRB1n#Dž)4\,XP"MyRD!ɕ2 w ONl~Xv@~- g42y@+͗\LD*A aD@ $<B AT:18 \p` Aa!:b""aH4 Q"rBj]H#-r9\@ 2G1Qu@Ơst4]k=Kut}c1fa\E`X&cX5V5cX7va$^lGXLXC%#W 1'"O%zxb:XF&!!%^'_H$ɒN !%2I IkHH-S>iL&m O:ňL $RJ5e?2BQͩ:ZImvP/S4u%͛Cˤ-Кigih/t ݃EЗkw Hb(k{/LӗT02goUX**|:V~TUsU?y TU^V}FUP թU6RwRPQ__c FHTc!2eXBrV,kMb[Lvv/{LSCsfffqƱ9ٜJ! {--?-jf~7zھbrup@,:m:u 6Qu>cy Gm7046l18c̐ckihhI'&g5x>fob4ekVyVV׬I\,mWlPW :˶vm))Sn1 9a%m;t;|rtuvlp4éĩWggs5KvSmnz˕ҵܭm=}M.]=AXq㝧/^v^Y^O&0m[{`:>=e>>z"=#~~~;yN`k5/ >B Yroc3g,Z0&L~oL̶Gli})*2.QStqt,֬Yg񏩌;jrvgjlRlc웸xEt$ =sl3Ttcܢ˞w|/%ҟ3gAMA|Q cHRMz%u0`:o_FIDATxڼ}l[yK")~>-ɒɲ۩^IhҦtM"m[Y Pt@.qnD8Q"lj%I}P$ŏu%qXqZBx}s(|mhh۶1>< {G\oݻv7l۶#QJY$נ\EQġC~GhGv,kڴ%)}MH\.mk<4;;?~<.bϦM>اim`׺I)B8eQ*p]7޾wAtY8+i8 +)}0gi^C M@\0 J"]>^cǎSr4u˲puqgV3Dl~ى4Rdя^!mw~bDU5 mS)Y^^ɓ^3$xI=66mۋe]O[eض8^N'H7OO1==Suv>hF4$NC;GrvjnTEQpj2lV&}ݧ444ܣE ؎mX&yWjÿ91xO8&f*ŏG$][\CU BxED*2?Owskm6(=MU־(*ǧmr|ؖ58\yu d1w/u (={PPqz{q9;6G]*a&prfYQ]J6uuR*jJX!y mO?k mgV_nق2cX"AIնA0f2'ϣOMQL%ǽ+%bD$>3R;>Mu"/ʚm3g'諽س iMi_ULֆ>>Uŧih9s[?q.wI.Bⓒ0xIv½x L d'䟟wF±!/gPT*D~]+RP/~r>@3*`XsxIϥ,]>mX( RJfΟgvvqٲe @^ΧRL?MM<7^TW\Nv}s1J Ŷ-T:οyⓓΞeqq|>OZ^)c\A/~?HzTUEUU:a&М399Q*&`q ջ¥mC͹96QOKT y44@U\jQX\DGȘe)Wba]ZE%8e%"o/Ȗ9PW! @^* ۶xQ667e" 2ϞE/ a Z`3 ->FR zRoS"L<TN,Ͽׅg} pj,X5&2so4 Ѻ3@ 6(S*b#9-Sh$ Z,2֋fvoLƍB:5fmc۾{> 0f%G#Ԩ >X)JiQ0? $::hog)f,+c혔E~< N$SL4LZ4,dGY&g"U=2ԁqKDs&۳\MQpQɰ05EE/c:6 u: < kgsAHX\Z(b(3˝E} 0r)+s\\q9 ҩbV X̙ Q ܶq&zˡ2,fs8l_ȫi66mtYJ󺙰BӲ0UeLMM 8d !¶Xq#4UE.,7ۯ.DX㔬B08c1B0ڰ`Zݼ`&Ja`_~7M׀׎9rλlzNx֌.EQ6v*KżH$Bk{,aPw~/W+~m躎i䗗 Gu}mOϓgμ"04MCX+ ?lX]c0+rJBZ^iii;tЏ^|lmkۙfS޺:EyDWa0 +iTt00*L}H)? $߸p7ruX5&L8mYXUS#VmÇxgnH$B/\r+h[ΝMOOϴwtԨZwͶml"J3drQ{x)e;{u]_Bk>55#|8<*X|oi_.Jرc'?>7;;[V^عs}6nxPBX". $"0 \:;IENDB`qutemol/src/image/qutelogo.svg0000444000175000017500000070721010507573327015073 0ustar mbamba image/svg+xml QuteMol scritto in Maiandra GD qutemol/src/image/snap_on.png0000444000175000017500000001325310464762371014654 0ustar mbambaPNG  IHDR1- pHYs   MiCCPPhotoshop ICC profilexڝSwX>eVBl"#Ya@Ņ VHUĂ H(gAZU\8ܧ}zy&j9R<:OHɽH gyx~t?op.$P&W " R.TSd ly|B" I>ةآ(G$@`UR,@".Y2GvX@`B, 8C L0ҿ_pH˕͗K3w!lBa)f "#HL 8?flŢko">!N_puk[Vh]3 Z zy8@P< %b0>3o~@zq@qanvRB1n#Dž)4\,XP"MyRD!ɕ2 w ONl~Xv@~- g42y@+͗\LD*A aD@ $<B AT:18 \p` Aa!:b""aH4 Q"rBj]H#-r9\@ 2G1Qu@Ơst4]k=Kut}c1fa\E`X&cX5V5cX7va$^lGXLXC%#W 1'"O%zxb:XF&!!%^'_H$ɒN !%2I IkHH-S>iL&m O:ňL $RJ5e?2BQͩ:ZImvP/S4u%͛Cˤ-Кigih/t ݃EЗkw Hb(k{/LӗT02goUX**|:V~TUsU?y TU^V}FUP թU6RwRPQ__c FHTc!2eXBrV,kMb[Lvv/{LSCsfffqƱ9ٜJ! {--?-jf~7zھbrup@,:m:u 6Qu>cy Gm7046l18c̐ckihhI'&g5x>fob4ekVyVV׬I\,mWlPW :˶vm))Sn1 9a%m;t;|rtuvlp4éĩWggs5KvSmnz˕ҵܭm=}M.]=AXq㝧/^v^Y^O&0m[{`:>=e>>z"=#~~~;yN`k5/ >B Yroc3g,Z0&L~oL̶Gli})*2.QStqt,֬Yg񏩌;jrvgjlRlc웸xEt$ =sl3Ttcܢ˞w|/%ҟ3gAMA|Q cHRMz%u0`:o_F IDATxڼkpTy}u,1 xm -MI$LI);ek<43Ni ۠,lL R$/X~ss?JpciJJJG}Lu˲FznVqmaΝ?U\.cYs>tDuGww7xmݯoػw{A]׵#U۲ YQe!dYV*++*j~Ꮯn>o˻z/]8t]G4) e!m۶1 ]< 8qg?7q(-G|cc=|p4¡h$In+fHP ::[j#rʿP&׬}WB}ﵷ,+xp\h>mt%44q[o͛ԶB| eee-]]]ͣhtxxv:LkP"I$(IHid3{߾}֭[ӥ+R8@UU|>###QA n# @uu5ݖeb >^\nGxIFH$S(eY!oZ#8D$!SWWwS\ LI%S3YFFFݮ,_s  mafRrI&bDF#V,;[l $rml6$J]sx:J\N'*SUYɢ]x嘦EjH2irT oMμӝ$8 !)vB(8xs3NNe0LQ/3t (Ȟ0b1J$- pPWFT//-!KOaYݹ[b1[l,* ɯpHkz{{ ߿X,F<gb| J+9}yAdE11۶g,`_c,e.4L#G ٴik׮eٲe4lFS5(vхBYٿݞ {ids9,$W0I&\x^^/\RbdY$I¶Aw8]w?%<3]ƞ,vBQ1yI?aF&Jf8@00 ˍ1 fz1m"Te!IMe OEuDx< X ^R)R $g4 l;O[kR(* {СC\TA:dU2 BqyL 8/xaXn\{/|i5"K ƎVw^fx"TU0i(S)/-!o[in~7PUUE=ܙy"Gm yx5׫K.u>Q;A~O?af4 l &&$Ri<|+OnݗYd 6nQlvfΞMUmhnppIy9 7=m}=Cg~SSwf|>nwGYD"Jd)UU) }jT$cz29`Zjl\I}_cttKUU555n<]T*(R9s椢(' !ٶmɆN[NuswЦ\Ժ\uS$3yر9IǗ.]\ZZһ$Dqs>}e3FZlǎISM68N$Y.LC}Z^I"IvRQU4Ea4MX=L&Wn?,sӧ_$) /uݑ/=+P[/H$ѣJgϞرc_|(g!71 ̷GņS NCPYkhh PsNhlB@v8)8zE7~?}QٖGIENDB`qutemol/src/image/logo.png0000444000175000017500000002525010542254013014141 0ustar mbambaPNG  IHDRdQ$UJbKGD pHYsAAU*StIME D IDATxyxU?뜓&d<<+8TWɍZm}Zgg uV@e lad=gD#EA jys;Zߵ>—uh4HQHWߣѼz8]"km^{F޽G8PU9t`ƶmMKJw/9看h ض9p w 7w !ZZٽ{OjRDq7%99nX$= v1x*RU2T86QUuP {l~Yrgh)99;}{ljl>$'?jii6F9+pqR+f<ycNp8tz 'm8#,%uu5CvW={}0h#G~yuÇ+W]M cUy4vV*0 v2Ue9Wիeu?K.S 蝘,~ H =w|HgQwo[͇;t~nv=-78oJL m'$zxye}N&޽s'X{EojSJDF Ѽ%$B'=4`m8.llt-B*0KUZDh4oV$RJi۔ADt17U hYi&5ږ.}yՖ-ˣj3=߰}5}R\3 bGs}Ilua7 GyщKKۂ@SSB&G@n!@dҤR^@ ߃o7F8SU+!55_ֻ+r*۲eޛx@C*j7`MU!JUv .p(UIap7pa uE4fY5UEm[]R*M/mi ԉH1ޡݻKTUU!m'RS阊%͍U-yxܚ9ׁu/P`\%"?ElRN;0BUH՛D7z hLfUI,v*#jjTlkYYv(iIOe5~TԊHOI׵rUhn''1uhF,-;ٽ>{ܱ';l7?*,XRe6sOus& 0ᆗצ54Eey @eYe[UmT1k~kڡCtDZ0ŲddӋp8Fo/e%ob3wC@%3&skhiD" ph_xxڣMM 7UFyUm2ƴbq,2jz/BSNwwKDPU]JJ" 55 8PQyϞ5^NN/z}e`ITE4x\ջkgVN;&$11zK͇{"  1fE_"ңǰÆ]۵k* g--/)YԎKWAm xcD dѼ%S:ɲ`1,*RUUm907}" @)V^z3`12rn eO`JC{f B@b0X 0`Y%"1 {8}32WWT\oJ%8%)#;OL mUn8`_:x FU:[DVCHR?EDaY->%XkjeAdȂ3&?kTWEϓ p8&c 㨪j,>)Ҵ)Sf&Xsh4o mת411TDp& iUor ~^MWw&֭ۀ확)#55WrrjO׍u,3Ƴmۉm^YlS6UX8qԩ3-sgN",F0@>-cór'vzҹp))驭X577MMܵb߾/mz}gʎd]IDRSGVASee!U< rsWeD( M?SSJ,X7Teϟ#"9@<*}}_Hm"-U[V)"Znt@O*5":*cĎ;4haμ>'˘Òv23;\ңǠorIf?ٴ1I@ F^`h* E p/~h^0+sc(%?o$0Oϳa-v}-"r-`hT"kcpUcS0/@puk';>Oa禧W0ovnnϓ :;p8_I--C7;);6*@ [T/³bUѿQmQD?[J=ĥvUHۖP-w10?:Y x N Ͳy@1\ 8xD@֯]⍿kkiijy9ң?x荫V{uc|mii:XWv‡>fgV3&;D3Ui~ 1oEZU}LVeI9{DPdY Qq!U]|v\74W|{>%Eƍk„-ر{n}}ucUՁ۶ٻÇ5hȐ3&[W}{'l۶ vLHHuK,=/99O)"a9EEM,-]އS@6lxvIiiYm?[]3|C~H qBBIvZZvnjjFų?>iLRRg& h !|8ҌO ,'bWoɶt̾}G8 @zzNCϼw֬Yxsݘ3p6^5Q"AP\P0{,]J"ȅ"tSeTY9$Kαmye"8 /fq' 2VTuH0F=- E.~cJb޼9x!),p6_ E.PW փ5 tȄ|Tx\AXu2}'S;L"7Y B]_iH3~YCOl4Tm%5I|ۨQ߮Qu7@{"Ƙ}"֎`1]#F\)!U]#"Aj2`rۖqst%l,Z V dGUuMր8_1,,`,(HFD+@J@V^ AEdWWoԎgUb [hYX>"^ݺtvjj陙zfvHM͈ͫ;p`מݟBDDE}HdVPc3&Q)T=,KM6ϑNzf_deu잘7W^PtpʔYeɅ/EحJwoC`Y),ϟlY"ƘHmBIԪ@W`Jm3Y `<E"HЫ-,JCƏ,F 0>}8 xUW=xp׮*ϋb*yʪO',ifkIT5VcA;Te8^$RUCU{̯.7Et?^ ׷$k#/*"bM@' ǴO 73==;u%m?&$$&TW(.~pZr(bRTuee_֭n]ӧϰo&'&VV߳hQ^]꫟.uy 8"X#")"i۔Cm{ g?'"$htB#@2sYlOkE)geuܿGų1q]aAVVR<7)IʴI+V뮛)3Z55'R=)*k˖RR:N0zXVVƺ؂?:n%Wuo1JKKSm;1]7^~JΝkw\#GSбc1zo۷2eU%\XWɎ`i ^Hdv hC_:@vĖX@BBѲ/9zv;6.{W]~,]r޺ϿzSzz99]gdd8.IIvHUo5ƘIr5~-`ԩ'mM~V'?vkf̘LNjvSaeVM:1iV1jX&5CD@T54 Xhc}i陙3?`Ǹ [UO/{hq6G"Ev^DnmG"E Lg!4i̳SRDb(+((y< $46:+ f us[7tBx<G4X˧9x囵m vGOoBn or63@@E+A׫=|I;TwNX,Vn,!!18XqeǂW<a3{#p{hWࠈ"<#B?Z. .q8*|c#ֱėwe >~RCC]݆ ' Lq_1>٭t֯_Ӵ tݽeabߢѼo_Z1c{ <4iF"E}Ѽ~.{SSu?LH=۳i]_|ժlڴlo mUD )(VaEGc E" TeyemN7?pi8{?aDYщՑHQ 0rsJ-U("Dk{8:):ED^^]P0+[UF//;nlok;Kܞʟ;w3жjvNG(+T;kĈs^WWUv]מ{#HuT r?"KL%S7V^8K)uh;UHA[YTO"r_0QFyk̛wy^;p`G⤓F}3NJII?}\yܰ1=O@WUTD?h\;gHlt/?4#dUnf*+EȰ, NI10Vm[댑|@?~n@ >(P`ܹO)0==缄.II)ɩGƺ5UT;XW %~R"BeUe$;uTDo*uͪ2O-|7~媤Te:@XD{Oy xoND#v+òhVy. ۤ* Dt;kȑڂϯXn݌8gi*Ulx }wwY%"OD.`a8>愕uIjO/A\UmYg""_՚-b^VeHTqDd.ȋrmcAIENDB`qutemol/src/image/geo3.svg0000444000175000017500000001647110515252127014062 0ustar mbamba image/svg+xml qutemol/src/image/open_noborder.png0000444000175000017500000000567310634260666016060 0ustar mbambaPNG  IHDR$%*\K=,tEXtCreation Timemer 31 mag 2006 15:55:22 +0100-tIME  pHYs  ~gAMA a IDATxW p~wsڄ+iSd(ZtDuQl+jCgZ*eq(u< zQGL-J@9%\9!ɒc7d읿#1f}}~dC-|@}+h= ~3f##Ê9͛2fϞ30iT ۻl~ ?NYK'lƆ .ՀzksObv X {\XpX7hjj7/GFn.4ӧC&X`.|s'ر~#0h̋/!W$vjLV+l ByP64 _F ^HAm#x8z+v])YàTW=-lj$,ziLĩ#Sߏ]od2$PId ,cs x`LhkY܈D uvb;E%L6. 1~#B<jnErZknF4˜Z-2+*;8ՅB>#Z3 '|>7`}?@#.dAJ׬Aɔ)P]3fK6 @5ىHL%S%S;oŒͥF,}QCo 03@#!N0mɘJ0ǏW( 3@e iƍQס;@1 ݊ ˤ1 - QSOUͬ,DDqqPp˃$ܛ¿[N' M 0[0mJj>(d9Jd!Qo )E0MZoF'\*]۱a"ȌqJ1322Vi\t]> Sf8ntc#̼W::Pގ1sZ|kBFԍُ h1R& );K<$c^ű6'St#JJ@hh @_)K܀s@0DvO-!Bޓ+.y?;n ԅ$R̝Y Ȁc#3 HS PwN`1!!AyW q887?.'NW 瑜WH@ J%u|X|d[MQzgBt8زe jga0a@JK 4o\dPbW{JGj|j$f&bR?%mXN \H"ndz`w}%6'Ȳ H1sR܈;R* }Q[OmܨHgZ4P'1N Y9Z}hEx3,H#0ǃGػӑS3 8TyH)"XVF_#A%:diczyb ~M>P`;-+ 3B ى Шhmg}Uܿ?O͛iC#t!R`ض9jkCDdz q`kKd0N =wƉOOc>ܹbTFc(WMM۶) 'x2ǿ~iT8KC Q  A$Vj-h41I4%/ĺ֩Ӈ&hԱo5JU.1r4k2 RMSMev6Y=5HD Ej5. I##N'qGN*z#_gff=[^A=N"Cέ@O>ԟgTH[h\/ VB1*z`0 DJxXTZ"l3wJ;v-@^˫t2EcZJKѪ%x<UE0D W ۀ0bd>mQ"a(\LI=v*3*)cDܹ.Sʅ.&Ƃ!㷽iӳe(yNa.45PQeQS2e2& e3Uigfw;FmclVZ .ф<f9g9+>L( dOp=~1Q~c) J)qe-] hdE@"\S69l;s[] 2Ô<@_;^Ihd=S/,g(g68*6VL`߼ło_}5X.̶o,lLrqRgʹ";x E,gt}cΜIUtcɓځ@HRv,Zn17T~/y۶׾18Tb]bDh Դ&+XVь!1IENDB`qutemol/src/image/openfile.pspimage0000444000175000017500000003061110462062666016034 0ustar mbambaPaint Shop Pro Image File ~BK..$%R@p>~BK ~FL ~BK8~FLJ}D~FLϥ}D~FL~FL~BK~BK$%~BK$%~BKJFIFHH%$"       }!1AQa"q2#BR$3br %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz w!1AQaq"2B #3Rbr $4%&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz ?+~2F\o|7C>*8.n!eon$C,C+ƪK2~AxMFHtÆ[{$})⍼7 ̮6!H}ߊcߌk),^K[R-HK">`U7/at1h]_h7MLTl>F3_ÿW쨟R' R< ,VR[D9%Ve$`85էQ;n=oG4s>KnWPm&TSK}\uV?TtMkc891@O+^C௎< } Z |u![ Ks@/ 5 z ^*jj=dב7 <.x*7 5uvg><]Km&{a I0%Xg3Xc k~+v?&c㷌̾n?u!-T2+*T}6^U$ o]t#}~x_FJ_i73p 1ni .KmېY18)Ej'jrgRpim+ۺ]l z5%$k5~ǞмKnu4>qu"7bq_> {P~+Ϯ~ ~ ZiK}9ơ[rMPXdxdLox]|;~П([Nۉt"F85BH:qd:O?|4CD5R>inܱ9 e>'N#pSoKV}.ն?:J Ny5w}W;?<|(jW#۬ߵ<3ܴ,1.!UTE4Jvܝ fƥw㧍=໫/𾉩 KfB ΀Hsp|5oƟ G'kS^dw%$tW%yb#ɶ䢓m۵ιqiU&R]z##J4- 4[MT*il(袽ӌ(~BK  ~BK[Kxkk`ǿo_fL|!CDA27tLxaSemV7/]vsul.͚iM4yL)xx][O^XG̼tm^nNʺ+5va 2pj޳m CW岵o1^,Dӧ* 9AVdm UeY߽Cܞ)Jȳa]|mF>[ЃM\)"<1o"ZO/79h^C/~1,b}g fz?EumӖihqMK-(a%"sfQRtmGwX$BB_Wv7 gb.dXƴ8zcu[Y^2a8 7'yb<:AY_:g28ZK^޲e iT%p9ue@YC/I!HRA 0IdP:o+տ2mdZ94^Z8 ec4riޘQe!8NFj:4l#@+eD8vtbޑā).@`|6 E5q~~[Fye ڮZC*M@UGw]J`h]o:&UmUG䩘T?fz##O?pv?U}} d1G\'>z̖MXNzoFxXQ~dw;xw.v\)9:3gJ+ 㻓;~BKxoe `ҦY4H2AEEyK@@5%-] SS.sPf1u2zL1oAh%lԅq 2srbtI18rՉMe0t1GlnTBS6@$/i9츣Š 1Ɉ_C/eνtZ\b`O<;7ҥ@%5D,o"XJ{\H&gAG,0,3 Z{ f-#*=q#34E1c U=guɕCrWqeٻtXZ6!P*xY1pM3Gja3ozO.`)(5n $y]q۷aA)*-̧5ó~lkί"vZz{ ,5*j0 kLɠW ,>߻14WYc B@^cQޕH˭[yTE3U /skĀz0ϱNl2* ۊ߾G=տq|5ME/( h渓^[VC^as=raW|1_ywER w*v8JNc#:Ex*1;ofDb>Q呍5FZ9q{GlL{#;c|l[ޙL>/<{}{{~<]Xt!yP~4hmo|PA'snJ6+k %iu9W]ا bj\oUgJ?7;~BKxOZW5[i~X2dic-v4^.1ZߠfWQJ2nA,"TJ eV+-ꦱZF;= ,9'y~yq0S BQiM/EKN"UyX.٫SZ"Qy #ddgrᘟ 6]JNJ"a-i"5(]bP(pEf9߾C!SJ`_ \wG?OMȤ1` :/Y?M}|toAsa6N8> qr֒4#%_~2LooTyxتs \ak]^OǤzvv .v*,H D?j=mqUYXAElJ L16;`'g` 5ne&@+g9V`F C 祐iGOPB/>`lm Mq8G;^" GX%땕!Mse4%K ]ΧQG'^wLt6&AA&ARI9e<ǔiVU%T=j=] ޼{lT댿۞L[b/߼fot!KM7nY,:%n.hP]-@f{D$$Y'L;*wKdHʓ] %IV1#.ePEq555y}:M 1 ׈Z"O4]IĮoGѫW++xpNnLb``WvɊ>r(b(N%}WIb@TG+~|:V 33ǟG Ֆ7} 9ߞ+v.%Or:C;:vP8ߎP`YļE~BK~BKRaster 1$% $@~BKxlO@T h@11Q/`"7+ h">z%ĠP[ W[---ioٝ1  E"{zPB:C4[6Ejtj22Lؔ^4l&*:gy;BL#ޕB<焬c9/+YDNh _)J yht"]]%,ʺ!+hm {Xs{uâ͚j4i n %wJ[eB-.XآܷVy=SNفdW}#єYk9:8/m_Gˆ4U1>%ڟ}aEu=5 :g1*,tot@ =Awuu1'JA^YYo~GYdK?uQM,{{m4-,m2bK9\^`;}4"UId̚WO8?nijVUePIVZN E' Գbof Po߃ƭ岶1.37v݁FyHA@]8=yn[^MlWĢS\r3YL> go-bzqx_:35}9"*F`drAYEK_[ r~BK*xX@\oAA@&S7^}*3#=~<^2էUvl=w ֓Bt+=;CdWZ3e]:ۗ z 5 ^m~(KMh{dz+f-_s)S =!͋ t3~0K7.aߧAÇ{M;;97׼N ׮]ӏȞk#sf^vko%T>-&aWLAE+8ltb.w*GAϳR6To3(Y|o@R;?SBre$Pf.cyXg2(TuJWA {R^]|-Ml.'mZҳl< 镓ͷRY37I#(wkMb~e~BK| xlKSQkSo>|&x@\Snɐyims\!p"Q)Ѫ^1vA|PCsnZf{9p>/AQN-3&:9)/B`Ns伲2vF&~ē;&s s[VoSsQJ_&*_sۃSb.q\'m.' eL]/ykq$R=vJd2IFwDB6C+rQ'w! 6?ttI, f+ )ZBÏZ:A/, 6X"=?UOE2> q>J!B{X.W C߷R& ^P_ghL 6:;z$XZnhR֑DU{ D7^Zbz ?cff3QJ߹޶&!q\w Ļe!AD\)M-%F.B`\)}_uul n^K?Z'ˣ~BK| xlKZa뱫5L faPkxȠG<} !Wcl^&mn΍ElFE#缧mj{n^x?< 옾ۈ~s#mĖڹ Azy"|hm7t馤knz!/Vy7 -td86}(O^vwҳΞA< 3d‹~5LJ"Ҁq:ǷekSuKyT&S~نK[5UCJY؀6:c鹙Y8|!9veYJb̑QfWQAZ/;LGwY~v3e| ︾ A]}w-17NBc`o[ؕݲέz<`0ͦX@tx$ `D%|E'yfb nHKmJ*ccwRP(v4(*0r*C޺OJ`z)J9nV5g'yR].q>}OPn7Cj˹Tj-t]R)Zf0r^.8aKtkfm&@=`Gs'kgBc7dAۛ;׹4D"3߹`3rsVj2>Ozu?fk . bh0J.(X_4P@Ԩ~BKxM 0L*]uB\yCyWR(Emxidv̢ l'I\WBRYǻ1RXD(B*e$r%0̸`f3-ӥP6ji }ulP{,}QD2Lye?r:ɂRv[s] ~>i~BKtRaster 2$@~BKN>xlKK@ZKы_AQ,AmMC)K]MYM\1&kbJM];̰!<հ_ NcU%E D- (!՟(1U g*:r \i3dsb6٣5"kiޢT&cpdx޵ٻ DĢLH--N)P|xaamT C"7Ld Fx{YQTt=y2HWSct~BKzjxd]K`/iFdE]7QQP| ynV4%9Mm,3M%lns8s?ߑTɔX{OB{W"ݮ@clXP=ۊK@䟮`(*!cVyLV, 1 [q1:M՘AG"g0O[$$r ,lxVnvj霴(I@_ݕ(G䱐nZɶ=.hif\;l "ba͢YwC"HG`]sXiAp0h]^\GYmɼ|}G$+T__~BKxZf&P˺? z 5 ^_JR?o4Lo܌_?}wzNZn^L݌ JJJt}zM;N5鵓6S7}IKv1 9e^ڭ<8ecʷM  &,V.9L hkc.w*GYr~M@TO,VJ%x,:o_Y^9?X.XGn1m.>4Vn jIϲ0( Q HGoY37$a0zȹ;?bl~BKP@Lxb`. 1."$G_m<@pK49Y։~BKdCopia diRaster 2$@~BKN>xlKK@ZKы_AQ,AmMC)K]MYM\1&kbJM];̰!<հ_ NcU%E D- (!՟(1U g*:r \i3dsb6٣5"kiޢT&cpdx޵ٻ DĢLH--N)P|xaamT C"7Ld Fx{YQTt=y2HWSct~BKzjxd]K`/iFdE]7QQP| ynV4%9Mm,3M%lns8s?ߑTɔX{OB{W"ݮ@clXP=ۊK@䟮`(*!cVyLV, 1 [q1:M՘AG"g0O[$$r ,lxVnvj霴(I@_ݕ(G䱐nZɶ=.hif\;l "ba͢YwC"HG`]sXiAp0h]^\GYmɼ|}G$+T__~BKxZf&P˺? z 5 ^_JR?o4Lo܌_?}wzNZn^L݌ JJJt}zM;N5鵓6S7}IKv1 9e^ڭ<8ecʷM  &,V.9L hkc.w*GYr~M@TO,VJ%x,:o_Y^9?X.XGn1m.>4Vn jIϲ0( Q HGoY37$a0zȹ;?bl~BK8(Lxb`. 1 ?u/$9?NT$x p.aPĂ$&L',8YXA2@"Be;3|m_+y؁fĀjFicgcr;{ʆ dFFP^g1Q{`_u?C<3BI_2v*GK ##,?'bض'?g -=xkz[MCa`Oqutemol/src/image/geo1.png0000444000175000017500000000216310515252126014035 0ustar mbambaPNG  IHDR('} sBIT|d pHYs;;Ī6tEXtSoftwarewww.inkscape.org<IDATXKUe:>+Z+X)ET A M2pcAE↖IAӈJ &%у4k5vws^k}koT""J8x'3 zSl,fhb\UE؇r 1܊c] {Y䁜q]poboDfe;BDLƈ<8mqf~!o#"V/ib:=-CՃ~/wZ#z9mmqSq=6.YDl?pWVW4Mik>Ĩ6DDayDA̫ڤ[]'<M" e4%&*_T7^\mq&oW-ڈ1RbVT~-:7W!ՖWiA5cj6V?[hz0kIGmKcò&cc=o6okpE'/JW*I"bXܨ8G_x1yK O7IENDB`qutemol/src/image/snap_off2.png0000444000175000017500000001316410464762371015075 0ustar mbambaPNG  IHDR1- pHYs   MiCCPPhotoshop ICC profilexڝSwX>eVBl"#Ya@Ņ VHUĂ H(gAZU\8ܧ}zy&j9R<:OHɽH gyx~t?op.$P&W " R.TSd ly|B" I>ةآ(G$@`UR,@".Y2GvX@`B, 8C L0ҿ_pH˕͗K3w!lBa)f "#HL 8?flŢko">!N_puk[Vh]3 Z zy8@P< %b0>3o~@zq@qanvRB1n#Dž)4\,XP"MyRD!ɕ2 w ONl~Xv@~- g42y@+͗\LD*A aD@ $<B AT:18 \p` Aa!:b""aH4 Q"rBj]H#-r9\@ 2G1Qu@Ơst4]k=Kut}c1fa\E`X&cX5V5cX7va$^lGXLXC%#W 1'"O%zxb:XF&!!%^'_H$ɒN !%2I IkHH-S>iL&m O:ňL $RJ5e?2BQͩ:ZImvP/S4u%͛Cˤ-Кigih/t ݃EЗkw Hb(k{/LӗT02goUX**|:V~TUsU?y TU^V}FUP թU6RwRPQ__c FHTc!2eXBrV,kMb[Lvv/{LSCsfffqƱ9ٜJ! {--?-jf~7zھbrup@,:m:u 6Qu>cy Gm7046l18c̐ckihhI'&g5x>fob4ekVyVV׬I\,mWlPW :˶vm))Sn1 9a%m;t;|rtuvlp4éĩWggs5KvSmnz˕ҵܭm=}M.]=AXq㝧/^v^Y^O&0m[{`:>=e>>z"=#~~~;yN`k5/ >B Yroc3g,Z0&L~oL̶Gli})*2.QStqt,֬Yg񏩌;jrvgjlRlc웸xEt$ =sl3Ttcܢ˞w|/%ҟ3gAMA|Q cHRMz%u0`:o_F IDATx̙mlTWzxflmmlcX; Y3MԤJVjT(VfRRUj%jajEJDb hM`lccxf8/е>f=r#X\R@ۆ x!,H)}˗/zŞ7}ݻqo꺾ZJiYBC(x^|şnbKMMͷ?޵_fY!k0:::{ןzꩽ=r\mOM"DAxGP k7]pa͛x=uDFGG[]]Q0SA ʢE ۶)LNNڛfmkk{@+?z:׊'ڞA_:DUU ]2[oٱc3Rw@w߽o|߿V4 |K(h(A8dY2(رC|L^} BQ\ ?}4s4| eMRM|𷆮{bq<<-Ow_y6ttތV\B@&att4#P{'iaTcӲzBRk{~uEU ˲g׮]:rARR"!d={>ݹs_heͥq\E-%9Zu!!JIŋgz{IH)eI'NԩS_n) !2 -Re;()oY ,JDhhl<4M#3=3$/ H=sqرV&^˥ "\ݻwcFMM _x2 O?G};w.;?ϯv{<(> F$ªzVד"ؖ9}4--ض?S?z%qWJy}q\CUDinN>O?:tjƐR²"Ln:l!8/_K xSOŘu}GFhi^CssXPJ .]pls0&jaRLbNL--y≥Ӷm۸48{qqe߰kSw47OJ2d֭k iLϤ1tX4kעkBubCCho LT:|w}gFUUaQ 1hZV*T/fXVbH]mB446.ot8˙mq,<פϑΤi_ߎ KB!"u"eaȕ+c* jF#hBmM ' ltz ov%K4קnEp|" Ng kVT,=kzg Py*\v !}N2 l!V76U6b躾|>!e8 C|#B~{H$B`bz ̱cE IuLO2>>s SPJ"8TTD<v9s -|{vRk׭#Y]H$#*|(3R!`E&&$UUUQK% %FFtXzj3O yBQPT]-MH4(Adò,ű J̀H4뷽5n-?x zm ; Q@U\FWF4AMm-iQ(088D<^EִRSTƯ\{˖6oNdo?Ȇ` (w/^AzzzJ&i4 ̦3؎l68E!K o'޲*B b&}_K:Ͽ7յt1wdjjzdu L0ЈՕxA>`m6jkjhޛ5ofY- Dʫu_^ҭU=y2;6G7 6IPĴm><ű,,Tsl4MLĵmf]vmCtvv>p#.}"5MC(8R{% 6eaX8o'MMM}94G}ƚMtz܈D |3}uq]4m۲p=G%|Bdd2PJ_-+b g$N>CLMM[__F3vX,CMM?^r%:22ryu%S bt\<'^Kgbw,KtGFFEq/|4l[[[uUUUJIJ5441ٓݽ{_`wBA8qɓ'V*aoڴ衇ZZZ !]?V|ԯp!>Yl5sO]IENDB`qutemol/src/image/geo2.svg0000444000175000017500000001772510515252127014064 0ustar mbamba image/svg+xml qutemol/src/image/qutemolsm.png0000444000175000017500000002636010462062666015246 0ustar mbambaPNG  IHDR3 GDtIME . pHYsnu>gAMA a,IDATx} tUE琐0 p`DPg|ʯb *4-*BL@L2<Bo>g QzZnr9h:u4gϞٳgϦ?<}KOf=NZ?IrߩQa_KIg E?N9^*gQ L,Gk.7u~իWoصkצ:nݺica*Jf\=v\JJJs[nݦ?$++1c>4hB6C?p`dY h7t _BhBB£>G8KA\[n_}ۀYC\B9g= * 67fbJ6𠘒f]|y.T8İaîꩧm߾}-uȞ ~ø 3f/iӦmH?k`tԌߌ})Zk3߄Ēw(ӟ |"n-S8LRLb5c|?~ѣ{`V8u v `yǗ.]zoR1j|QtiZDJOR4ًDs5 w>3VMઋ qc^{F7nMݺu&*5/ֈ,΀aРAWb:- tM+H~}jjl aÆ͛/ܒ~ K».]TگӠAz"l4jԨՊ+FrJb۱M;=ҢE0)K̚5kϯz<,y!?2=njMay'uwڵOӦMbp+*Nbbaӿ^ƍw Ծ;wjժ|4rmD!aW1*VXr⊫POg-Z4%K2Xzu&W^ye9cÛV]R?\rU꫁-[)$#AN~U!Cׯ#`Pfa*U^Tk%2[J1̞Lӹ$R,!13f %0p:0t(y&syږ(Q"5 ɟLZ9is49@ &,6;^,HGm`'x 1colU=>{?v/# $Uл\dkEgؘDfgM"u5lذ"`PC,G ag̚.^Z}(t7 {ĉ.+M˸kX^‰a۶mǩp| "YDRaT΍sZn?tO *BI?8B̙3ooJ۽{aj*p lvp(|q0ǁz|k2jԨ )Zl>` n_6( ]<+\$1sa˯&KkqhM"k既m=Kk**A[鹚.[⋺2mIc Z{8J*%p 傜6aA%?KJ0UQk KD(m8jo~ 8mpK(]1>lP8B+yIMgF0h ^I@N0[HmI^Uԯ$y&,Ih:j:Jf[rz~<bĭsK_šOZKB~ 5݀ٳgD!t1[E+k!TX{DrAkmA D/L_ "z rZ=1<ASLw#^|KNwkyV8WըRD%Ѕ Vv֭[7%SJ$/Ag yas$tsZO2vk)zy;?O|)]T"h\8ٙ`[n"O g u 3_DJ)p"!mZUl8v04]2b^7g}$. Np]@йsrZ'ȋG-[6o[sz/r_ׅ䷱O kƊԸۛڱco3#]N B=ZJ9+_Ɍb@A^wu%|k8;0~ hxO@k{%{+`noΏ<0);QjD2q=jτ/q L7AD*!RqjF%Z4nܸajjjE%,:s]-Z4r#5gZζc2I?A.Qr. oRp%X Z ,.E@[q׺RkY+HƈD},`DSׯ_˗2C?쳟? 1َ_k&Nki%jIIIA([o߾`{ uve11=!Ck/~u /7m׮~c-`>.ƈQRJ]iӦm#bG<'☘C]&^WbZ-`hEth?ncjyO|gj֬4#-[|g`oj@PsUzTJjĤuʗW&r9\rlC3gڛ.v+ ;$Ab6$rVo߾BfyUe~H.F Gp2Ջ/^ڶmxv~`'WgrH~GCE.]:uذa_njQ4iC 3V>9k׮_6R^?s_}Օ0Zj}c3fLc&W<`i*63 +}ρݻw8?q+(=uJ?cCP0} F :f5<rG a&/ah8lC5nܸ>`Fo*' OXi C idh-[?/r1MNСC)sK16mtc ^Af j^coJ :R1t|?tґrm6i3*`>MQJ:`rt2ۙ s-$ĐߧOϟ>1zC\$4\b]O>RRQ"Acɯt">9/\;سg׿[N#d'hc\dIN Fټy0#Fh(]nr%ٺ襐ecU235GS3TM(}mFFm6?en幮v֙Ъk,S/W?H !oSP#-_0qi8%-:{M2qَ%k?G8e☰G.SKѣ#̃U,q*g&o? t>SR瞫QaXOgg>}=PFobjݺutcg#Y&"cC iOȑ#'c0԰"L` I~DekQAggPqx7 WΚ5k6$I HDRaq8u_KsDҁ n3f*D1cݪ "0.l;y":o>|>y${'~MJ4Y4'(NuxeF}ׂ5 ¹}H >zP? 2dRq; JɁw~ f.y*W OJOF|7 kEGXBJ2N?˦h+z=WgPж0 rAmw ;Sr#xpn #{Ү]p+\s5nnaZ{NCq=W$ФI `5>`%8*![ |ZɄuƁmDDOXZTgO0dqu]w6DbD^8S:HS4 a֭Mj&f ܴSmK}\iK.bS)rW>;\b0UY%]HށA^TGr3BDKNbnM,~wlڴi^_6bĈ;ʼnI}ACX*k\Mk._4j9WIdѫ Yv-|gAi : 3hРw\?@wXt$Gv%yl~Oc3Hʕ$/Cfۡqz<]rNW&FըQ:?_G "4H\3ӁSNNnBѓA}I#׹s紑#G1gh;ȫqwy݅suən^QS6 (]hƋRK4f g0yE(Ǭ.J2ŨkeU RM6OJ # ?"?{Pk} ƅ]ʅ\aMv ^>/_p_ ^hJ9D}$Jc.灩L2W"b|G'ngzͲKP{7\iNVn<\| *ﭷ:gn=&NW/^ߑγ_~z.5p{Y<4NG}WcN JLrM&(R kFn֬Y^zU!OJ lUR'ZD҇VCs OJCLS"3uZ7N!&?$(6h._u7Xke'gG… [_;*6=8_6hР4,.'M5։U >AK͘I-5qCd/y?##c@˖-;lܸɮ]^I z_O'Lg͚u;K,I- MsEab-|rG3Iso@[#+WNJ-hЄADB#qpr7Up!uip#G:vx}[MC3W^jڴiZ|)"UjXR\5=reufmUB/?1/4Vڌ3wԙ6o|tB=%m ,Xqx d =75+y4RtC]rw޽"e& f!%㏃A~N-X'ed|m 30v&n'[@?䓻 qKc p?~qAѠ j2 d{뭷֓1d 5VZ.O?hkvu]Ι`̽ZB,&R#y$h]Hadѫd[ԯ_=*`fxM!0ٰs@ 6J,_/lٲUVkv+qڵj֬T?=z|I^4Pumzd6\o??5;J^ 7}.F`z.x{~~[|n>\ "o t k:K .>uL5ϰa-R0 fqGݿ΢\Z3OO={~ .]:f`!}ym gVG63to߾ #gaw3c1$ԻA*\_mϙ3=wrw3S~+z̙3y7۵kO5giux#4ٿK}1AB})\?|6mڴW9T,D8vrȐ!6tXQ{bfBhѢ 0 f`)|e\{gΜ=k&N M(I6f!0vŸ| { h?L 45d|'%%%9N.?ީS/{]$7C}nIR&I^Ŧذ"t@;o޼0K"ђ!HkHYƁ 02@q9-ZC=E&k֬Y .`m/Q7V1:*5Rpғr"8x$<]tȑS'rVȊ+N|}QQQg*<{ 6+־#GI@8g;fDu5|s=YlO/GyasRS/9<I S8 H07~ndgss`B$RfAxM7U)S}7@:ἰo2j6uĖ*pc{s ۊ^"6̣?BF勩ˑ1]Q $&߷!d+mObh) XZL2RS_کO[ k­gۆziJ~]^O1| :*'ԹPn$! $L0uEɢz ax5fDANerhwvywgtI҄a4:eiJ^Jыj<D"_-E]+nR^"{E ;YƗbPӂTpZ,Rc~X jD^!ZZjAoқ#ԩ0hР0ɚVPzGq:ojڴ 'Ԋ};R!m63l|8秓9S',eDk ;JN&Mj riҤIxt'd35uXЦ[7w qtb=^p ͧD;6( ;a{kbK앸.?A:vĘ%v!R~`ժDf?Ì 9NTޅ8} ;]Q$p]nh=OI& _h{\L,1.Tr+V3Ğ"8v{]?ߜ(FIENDB`qutemol/src/image/geo1.svg0000444000175000017500000001505610515252127014056 0ustar mbamba image/svg+xml qutemol/src/image/geo3.png0000444000175000017500000000237210515252127014042 0ustar mbambaPNG  IHDR()GksBIT|d pHYs#ktEXtSoftwarewww.inkscape.org<wIDATXMlU*R!R 56 Q1DJMn\# q 6ĸ QHl#(XP ȏ-j }]ӏLd2s==s9#L%$:y`0 D3%y f&U`.0 GS%/>u]-t+QN`o{MxIDsG"(I-i lSn9ǰy[~K+ @/ 'q?0k9* c;{JZKXu012N$鄌?\JaIIhtZZed.,0~_NJZ^Nطy+͸C.`al<֋df{^}6CrbL]R}N`^^y=0FöOT$%o{ XCܤ/۾0YX1`ZH#ГIW$5@"!`_5[~HHlv`uK 'ڍl`ec{}$B]bp!RrKZ>ޜornFH˯cŴh;7/X'$e;BwDr3h:HSQvdCR U[}Zӄ,e0hjNK!HR3[{ Go ڇl_Pqy# ^$iepph}l,\LBM @p{܎'QMQWYR4&,'o"͑+& \Lű@ ] "7 XlS'i9YRIݝBGpB\fx-m(). Gh=JZLsPU[ ..+@c+P J^ jE8N^GxdK. nyۡjA"H  Z~?!Eh4tⷐp'^.%PUbZIjZel"f3\.h70%t^p J`0|g|BhgL&a6?| T*[*0eB'vep8DV)A\f0u^ӑ̪6`ٔ}L,9^%x2fǯ5ؓJ~@B iIENDB`qutemol/src/wx_trackball.cpp0000444000175000017500000000755110633257154014610 0ustar mbamba #include #include //#include //#include #include using namespace vcg; using namespace std; bool wxConsumeTrackBallEvent(wxKeyEvent& event, bool down, Trackball &track){ if (event.m_keyCode==WXK_CONTROL) { if (down) track.ButtonDown(vcg::Trackball::KEY_CTRL); else track.ButtonUp(vcg::Trackball::KEY_CTRL); } if (event.m_keyCode==WXK_SHIFT) { if (down) track.ButtonDown(vcg::Trackball::KEY_SHIFT); else track.ButtonUp(vcg::Trackball::KEY_SHIFT); } return false; } bool wxConsumeTrackBallEvent(wxSizeEvent& mevent, Trackball &track){ return false; } bool wxConsumeTrackBallEvent(wxMouseEvent& mevent, Trackball &track) { int width, height; GLint viewport[4]; glGetIntegerv(GL_VIEWPORT,viewport); width=viewport[2]; height=viewport[3]; if ( mevent.Dragging() /*|| mevent.Moving() */) { track.MouseMove(mevent.m_x, (height - mevent.m_y)); return true; } if ( mevent.LeftUp() || mevent.RightUp() ) { track.MouseUp (mevent.m_x, (height - mevent.m_y), vcg::Trackball::BUTTON_LEFT); return true; } if ( mevent.LeftDown() || mevent.RightDown() ) { track.MouseDown(mevent.m_x, (height - mevent.m_y), vcg::Trackball::BUTTON_LEFT); return true; } if ( mevent.MiddleDown() ) { track.MouseDown(mevent.m_x, (height - mevent.m_y), vcg::Trackball::BUTTON_MIDDLE); return true; } if ( mevent.MiddleUp() ) { track.MouseUp (mevent.m_x, (height - mevent.m_y), vcg::Trackball::BUTTON_MIDDLE); return true; } /* if ( mevent.RightUp() ) { track.MouseUp (mevent.m_x, (height - mevent.m_y), vcg::Trackball::BUTTON_RIGHT); return true; } if ( mevent.RightDown() ) { track.MouseDown(mevent.m_x, (height - mevent.m_y), vcg::Trackball::BUTTON_RIGHT); return true; }*/ if ( mevent.m_wheelRotation !=0 ) { if ( mevent.m_wheelRotation>0) track.MouseWheel( 1); if ( mevent.m_wheelRotation<0) track.MouseWheel(-1); return true; } /* switch( event.type ) { case SDL_KEYDOWN: switch(event.key.keysym.sym) { // case SDLK_h: track.Home(); return true; case SDLK_RCTRL: case SDLK_LCTRL: track.ButtonDown(vcg::Trackball::KEY_CTRL); return true; case SDLK_LSHIFT: case SDLK_RSHIFT: track.ButtonDown(vcg::Trackball::KEY_SHIFT); return true; } break; case SDL_KEYUP: switch(event.key.keysym.sym) { case SDLK_RCTRL: case SDLK_LCTRL: track.ButtonUp(vcg::Trackball::KEY_CTRL); return true; case SDLK_LSHIFT: case SDLK_RSHIFT: track.ButtonUp(vcg::Trackball::KEY_SHIFT); return true; } break; case SDL_MOUSEBUTTONDOWN: switch(event.button.button) { case SDL_BUTTON_WHEELUP: track.MouseWheel( 1); return true; case SDL_BUTTON_WHEELDOWN: track.MouseWheel(-1); return true; case SDL_BUTTON_LEFT: track.MouseDown(event.button.x, (height - event.button.y), vcg::Trackball::BUTTON_LEFT); return true; case SDL_BUTTON_RIGHT: track.MouseDown(event.button.x, (height - event.button.y), vcg::Trackball::BUTTON_RIGHT);return true; } break; case SDL_MOUSEBUTTONUP: switch(event.button.button) { case SDL_BUTTON_LEFT: track.MouseUp(event.button.x, (height - event.button.y), vcg::Trackball::BUTTON_LEFT); return true; case SDL_BUTTON_RIGHT: track.MouseUp(event.button.x, (height - event.button.y), vcg::Trackball::BUTTON_RIGHT);return true; } break; case SDL_MOUSEMOTION: track.MouseMove(event.button.x, (height - event.button.y)); while(SDL_PeepEvents(&event, 1, SDL_GETEVENT, SDL_MOUSEMOTIONMASK)) track.MouseMove(event.button.x, (height - event.button.y)); return true; default: break; } */ return false; } qutemol/src/pngSave.cpp0000444000175000017500000000760110633257612013531 0ustar mbamba/* PNGWRAPPER! This file is included in QuteMol project as temporary hack waiting for WxWidgets to support alpha channel in PNG writing. */ #include #include #include #include #include #include using namespace std; #include #include "progress.h" typedef Byte byte; void downsample2x2(byte * data, int sx, int sy){ int j=0; for (int y=0; y PNG_COLOR_TYPE_GRAY (bit depths 1, 2, 4, 8, 16) // 2 -> PNG_COLOR_TYPE_GRAY_ALPHA (bit depths 8, 16) // 3 -> PNG_COLOR_TYPE_RGB (bit_depths 8, 16) // 4 -> PNG_COLOR_TYPE_RGB_ALPHA (bit_depths 8, 16) int pixel_type = 1; switch(type) { case 1: pixel_type = PNG_COLOR_TYPE_GRAY; break; case 2: pixel_type = PNG_COLOR_TYPE_GRAY_ALPHA; break; case 3: pixel_type = PNG_COLOR_TYPE_RGB; break; case 4: pixel_type = PNG_COLOR_TYPE_RGB_ALPHA; break; } //TRACE("sx %d, sy %d, depth %d, pixel_type %d\n", sx, sy, depth, pixel_type); png_set_IHDR(png_ptr, png_info_ptr, sx, sy, depth, pixel_type, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); //TRACE("png_set_IHDR\n"); png_write_info(png_ptr, png_info_ptr); //TRACE("png_write_info\n"); //TRACE("uffa");*/ char **rows = new char *[sy]; for(int i = 0; i < sy; i++) rows[i] = (char *)data + i * type * (depth/8) * sx; if(reverse) { if (sy>200) StartProgress("Saving PNG", sy); for(int r = sy -1; r >= 0; r--) { if (r%100) { if (!UpdateProgress(sy-r)) { fclose(fp); return false; } } png_write_rows(png_ptr, (png_byte **)(&(rows[r])), 1); } EndProgress(); } else { png_write_rows(png_ptr, (png_byte **)(rows), sy); } delete []rows; TRACE("png_write_rows\n"); png_write_end(png_ptr, png_info_ptr); TRACE("png_write_end\n"); png_destroy_write_struct(&png_ptr, &png_info_ptr); TRACE("png_destroy_write\n"); fclose(fp); return true; } qutemol/src/progress.h0000444000175000017500000000013110542044036013417 0ustar mbamba bool UpdateProgress(int i); void StartProgress(char* str, int N); void EndProgress(); qutemol/src/Mol.cpp0000444000175000017500000003454310642664637012673 0ustar mbamba#include typedef unsigned char Byte; #include #include #include #include #include using namespace vcg; using namespace std; #include "CubeMapSamp.h" #include "OctaMapSamp.h" #include "Mol.h" #include "HardSettings.h" #include "Progress.h" #include "AtomColor.h" #include "MyCanvas.h" #include "CgUtil.h" float stick_radius; static int lx=0,ly=0; extern int BSIZE; extern int CSIZE; // number of texels for a patch of an aotm int BSIZEx, BSIZEy; // number of texels for a pach of a bond int SubPatchX, SubPatchY; // an atom size is subdivided in this many subpatches for bonds #define TOO_BIG 0 #define TOO_SMALL 1 #define SIZE_OK 2 Mol::Mol() { vboNorm=vboShadow=vboAO=666; // not ready vboNormSt=vboShadowSt=vboAOSt=666; // not ready filename[0]=0; AOdoneLvl=0; ready=false; natm = nhetatm = 0; //DL_bonds = DL_atoms = 666; colMode=1.0; } // how many texels per patch? int SetCsize(int textsize, int natoms){ // initial guess: int i=(int)ceil(sqrt((double)natoms)); BSIZE=CSIZE= textsize / i; if (CSIZE>250) { BSIZE=CSIZE=250; return TOO_BIG; } if (CSIZE<6) { return TOO_SMALL; } return SIZE_OK; } bool QAtom::AssignNextTextPos(int texsize){ if (texsize<0) { lx=ly=0; return true;}; tx=lx; ty=ly; if ((lx+s.TotTexSizeX()>texsize) || (ly+s.TotTexSizeY()>texsize)) return false; lx+=s.TotTexSizeX(); if (lx+s.TotTexSizeX()>texsize) { ly+=s.TotTexSizeY(); lx=0; } return true; } bool Bond::AssignNextTextPos(int texsize){ if (texsize<0) { lx=ly=0; return true;}; tx=lx; ty=ly; if ((lx+BSIZE>texsize) || (ly+CSIZE>texsize)) return false; lx+=BSIZE; if (lx+BSIZE>texsize) { ly+=CSIZE; lx=0; } return true; } bool Mol::ReassignTexture(int textsize) { // reset texture atom[0].AssignNextTextPos( -1 ); // assign texture positions for (int i=0; i=16)) { shrink=true; guess/=2; continue; } if ((res==TOO_SMALL)&& (guess*2<=hardSettings.MAX_TSIZE)) { enlarge=true; guess*=2; continue; } } CubeMapSamp::SetSize(CSIZE); OctaMapSamp::SetSize(CSIZE); if (!ReassignTexture(guess)) { // should never happen } break; } while (1); } Bond::Bond(const QAtom &_a,const QAtom &_b): atmA(&_a), atmB(&_b) { a=_a.P(); b=_b.P(); dir=(a-b).Normalize(); float rada= _a.covalentr; float radb= _b.covalentr; /*a-=dir*(rada*0.60); b+=dir*(radb*0.60);*/ lenght=(a-b).Norm(); startp=dir^Point3f(0,0,1); if (startp.SquaredNorm()<0.1) startp=dir^Point3f(0,1,0); startp.Normalize(); hetatomFlag=_a.hetatomFlag || _b.hetatomFlag; UpdateColors(); } void Mol::AddBond(int i, int j) { bond.push_back( Bond( atom[i], atom[j] ) ); } void Mol::FindBonds(){ /* // (DRAMATICALLY) QUADRATIC VERSION for (int i=0; i=mind*mind) && (dist<=maxd*maxd) ) { bond.push_back( Bond( atom[i].P(), atom[j].P(), atom[i].covalentr, atom[j].covalentr, Point3f(atom[i].cr,atom[i].cg,atom[i].cb), Point3f(atom[j].cr,atom[j].cg,atom[j].cb) ) ); } } */ // (HOPEFULLY) PSEUDO-LINEAR VERSION // sort, then find bonds const float MIND=0.4; const float MAXD=MAX_COVALENT_RADIUS*2+0.56; bool showprogress=atom.size()>2000; if (showprogress) StartProgress("Locating Bonds",atom.size() ); // Sort atoms per x coordinate std::sort( atom.begin(), atom.end() ); int st=0; // start interval for (int i=0; i px ) break; // no more atoms else { float maxd=atom[i].covalentr+atom[j].covalentr+0.56; float dist=(atom[i].P()-atom[j].P()).SquaredNorm(); if ( (dist>=MIND*MIND) && (dist<=maxd*maxd) ) if ( // one way check /*(atom[j].px != px ) || (atom[j].py < atom[i].py ) || ( (atom[j].py == atom[i].py ) && (atom[j].pz < atom[i].pz ) ) */ i>j ) AddBond(i,j); } } } if (showprogress) EndProgress(); printf("%d bonds detected!\n",bond.size() ); } void Mol::SetSpaceFill(){ if (sticks) textureAssigned=false; sticks=false; ReassignTextureAutosize(); for (int i=0; itx1) tx1=atom[i].trp[0]+atom[i].r; if (atom[i].trp[1]+atom[i].r>ty1) ty1=atom[i].trp[1]+atom[i].r; } sort(atom.begin(), atom.end() ); } void Mol::DuplicateTexels(vector &t, int texsize){ for (int i=0; i &v) { int startAtom=atoi( st.substr(6,5).c_str()); // assert(startAtom >0 && (startAtom-1)6+i*5+4 && isdigit(st[6+i*5+4])) { // printf("'%s' -> '%s' (%c)\n",st.substr(6,5).c_str(),st.substr(6+i*5,5).c_str(),st[6+i*5+4]); int secondAtom=atoi( st.substr(6+i*5,5).c_str()); //printf("(%i) CONECT %i -> %i\n",i,startAtom-1,secondAtom-1); ++i; v.push_back(startAtom-1); v.push_back(secondAtom-1); //AddBond(startAtom-1,secondAtom-1); } // printf("Found %i conect\n",i); } bool Mol::ReadPdb(const char *_filename){ ready=false; sprintf(filename,"%s",_filename); FILE *f=fopen(filename,"r"); if (!f) { sprintf(QAtom::lastReadError,"Error reding %s:\ncould not open file\n",filename); return false; } long size=0; if (fseek(f, 0, SEEK_END)==0) size=ftell (f); fseek (f, 0, SEEK_SET); bool showprogress=(size==0) || (size>1000000); if (showprogress) StartProgress("Reading file", size); char buf[82]; buf[81]=0; atom.clear(); bond.clear(); textureAssigned=false; QAtom::readError=false; int lineN=0; vector tmpBondVec; while (1){ if(! fgets(buf,81,f)) break; lineN++; if ((lineN % 1000) == 0) if (size!=0) if (showprogress) { if (!UpdateProgress((int)ftell(f))) return false; } string st(buf); if ( (strcmp( st.substr(0,6).c_str(), "ATOM ") == 0 ) || (strcmp( st.substr(0,6).c_str(), "HETATM") == 0 ) ){ atom.push_back(QAtom(st)); if (QAtom::readError) { sprintf(QAtom::lastReadError,"Error reading %s!\nLine %d: %s",filename,lineN,&(st[0])); if (showprogress) EndProgress(); return false; } } if(strcmp( st.substr(0,6).c_str(), "CONECT") == 0 ) AddTmpBonds(st, tmpBondVec); } //printf("Found %d atoms!\n", atom.size() ); nhetatm=0; natm=0; for (int i=0; i0) x0=x1=atom[0].px; y0=y1=atom[0].py; z0=z1=atom[0].pz; for (int i=1; iatom[i].px) x1=atom[i].px; if (y1>atom[i].py) y1=atom[i].py; if (z1>atom[i].pz) z1=atom[i].pz; if (x0 &texture, const vector &sumtable, int texsize, float div ) { /* for (int i=0; icr,atmA->cg,atmA->cb); col2=Point3f(atmB->cr,atmB->cg,atmB->cb); } void QAtom::UpdateColors(float mode){ Color4b ca,cc; *((int *)&ca )= atomColor; *((int *)&cc )= getChainColor( chainIndex ); cb=(float(ca[0])/255.0f)*mode+ (float(cc[0])/255.0f) * (1.0f-mode); cg=(float(ca[1])/255.0f)*mode+ (float(cc[1])/255.0f) * (1.0f-mode); cr=(float(ca[2])/255.0f)*mode+ (float(cc[2])/255.0f) * (1.0f-mode); } void Mol::UpdateColors(){ for (int i=0; i='a' && elem[0]<='z') elem[0]=elem[0]-'a'+'A'; if (elem[1]>='a' && elem[1]<='z') elem[1]=elem[1]-'a'+'A'; if (strcmp( st.substr(0,6).c_str(), "ATOM ") == 0 ) { hetatomFlag=false; getCol( elem.c_str() ); mysscanf(st.substr( 30, 8).c_str(),"%f", &px); mysscanf(st.substr( 38, 8).c_str(),"%f", &py); mysscanf(st.substr( 46, 8).c_str(),"%f", &pz); chainIndex = (int) st[21]; r=spacefillr=getAtomRadius(elem.c_str()); // Van der Waals radii covalentr=getAtomCovalentRadius(elem.c_str()); } else if (strcmp( st.substr(0,6).c_str(), "HETATM") == 0 ) { hetatomFlag=true; getCol( elem.c_str() ); mysscanf(st.substr( 30, 8).c_str(),"%f", &px); mysscanf(st.substr( 38, 8).c_str(),"%f", &py); mysscanf(st.substr( 46, 8).c_str(),"%f", &pz); chainIndex = (int) st[22]; r=spacefillr=getAtomRadius(elem.c_str()); // Van der Waals radii covalentr=getAtomCovalentRadius(elem.c_str()); } covalentr*=0.85; // mystical value!!! } qutemol/src/Common.h0000444000175000017500000000310410535543137013016 0ustar mbambaextern int winx, winy; typedef unsigned char Byte; // SDL functions: remiplement these //void swapbuffers(); //void refresh(); long int getTicks(); // drawing & geom settings... extern CgUtil cgSettings; extern GeoSettings geoSettings; // singleton extern bool bilinear; extern bool MovingLightMode; extern bool draw_balls; // just to test extern bool draw_sticks; // just to test extern bool draw_wireframe_sticks; extern bool draw_wireframe_balls; extern bool use_accurate_halo; void setAniStep(double step); void stopAni(); int InitQuteMol(const char * filename); #define ERRGL_OK 0 #define ERRGL_NO_FS 1 #define ERRGL_NO_VS 2 #define ERRGL_NO_FBO_SHADOWMAP 4 #define ERRGL_NO_FBO_HALO 8 #define ERRGL_NO_FBO_AO 16 #define ERRGL_NO_GLEW 32 // returns an ERRGL code int initGl(); void drawFrame(int quality); void clearFrame(); void UpdateShadowmap(); int GetCurrentHetatm(); int GetCurrentAtm(); void SetTextureAccess(bool bilinear); //void ReloadTexture(vector t, bool bilinear); Byte* GetSnapshot(int sx, int sy, bool alpha); //extern Mol mol; //extern ShadowMap shadowmap; extern CgUtil shadowSettings; extern float background; void StartTime(); long int TakeTime(FILE *f, char *st); long int TakeTotalTime(); void Cycle( float &c, float min, float max, float step); void SetColMode(float mode); float GetColMode(); void ResetColMode(); void ChangeColorSchema(int i=-1); //extern vector texture; //bool LoadImagePPM( const char * filename , vector &im); //bool SaveImagePPM( const char * filename , const vector &im, int sizex, int sizey); qutemol/src/CgUtil.h0000444000175000017500000001222710633257033012757 0ustar mbamba class GeoSettings { public: typedef enum{ SPACE_FILL, BALL_N_STICKS, LICORICE } GeoMode; GeoMode mode; float stickRadius; float licoRadius; bool stick_smooth_color; bool use_stick_const_color; float stick_const_color_R,stick_const_color_G,stick_const_color_B; bool showHetatm; void SetDefaults(){ mode=SPACE_FILL; //stickRadius=0.2; SetLicoRadiusPercentage(50); SetStickRadiusPercentage(100); //licoRadius=0.6; stick_smooth_color = false; use_stick_const_color = false; stick_const_color_R=0.75; stick_const_color_G=0.50; stick_const_color_B=0.50; showHetatm = false; } void Rotate(){ mode=(GeoMode)((((int)mode)+1)%3); } GeoSettings() { SetDefaults(); } void Apply(); void ApplyColor(); void SetLicoRadiusPercentage(int percentage){ licoRadius = 0.3 + percentage/100.0*0.65; } int GetLicoRadiusPercentage(){ return int(100.0*((licoRadius - 0.3)/0.65)); } void SetStickRadiusPercentage(int percentage){ const float tmp=0.32 * 0.85-0.16; stickRadius = 0.16 + percentage/100.0*tmp; } int GetStickRadiusPercentage(){ const float tmp=0.32 * 0.85-0.16; return int(100.0*((stickRadius - 0.16)/tmp)); } }; // drawing settings class CgUtil { public: // RENDERING PARAMETERS: // Settarli a piacere e poi chiamare setShaders... ///////////////////////////////////////////// /* SERIALIZE_BEGIN */ float P_light_base; // from 0 (dark) to 1 (bright) float P_lighting; // from 0 (no lighting) to 1 (full lighting) float P_phong; // from 0 (no phong lighting) to 1 (full lighting) float P_phong_size; // from 0 (POW=100) to 1 (POW=1) float P_col_atoms_sat; // base color: saturation float P_col_atoms_bri; // base color: brightness float P_texture; // FOR AO! from 0 (no AO) to 1 full AO float P_border_inside; // size of antialiased borders inside, in % of atom float P_border_outside; // borders outside (pure black), full size float P_depth_full; // size of depth step for a full border bool P_sem_effect; float P_halo_size; float P_halo_col; float P_halo_str; float P_halo_aware; float P_fog; bool P_capping; // capping float P_shadowstrenght; // how much light float P_bg_color_R; float P_bg_color_G; float P_bg_color_B; bool auto_normalize; bool P_double_shadows; bool P_border_fixed; /* SERIALIZE_END */ bool do_use_doubleshadow(); bool can_use_doubleshadow(); bool P_use_shadowmap() {return P_shadowstrenght>0; }; // Save and load the above bool Load(const char* filename); bool Save(const char* filename); // Set void Set(); // coming from GeoSettings bool P_cyl_smooth_color; bool P_cyl_const_color; float P_cyl_const_color_R,P_cyl_const_color_G,P_cyl_const_color_B; void setGeoSettings(const GeoSettings &gs); // Error messages static char lasterr[255]; enum { USE_OCTA, USE_CUBE } textmode; // textmode enum { PERSPECTIVE, ORTHO } projmode; // projmode bool proj_figa; void SetDefaults(); // set defoult params void SetForOffLine(); // set defoult params for an offscreen rendering void SetForShadowMap(bool accurate);// set defoult params for an offscreen rendering void MakeShaders(); // activates params void UpdateShaders() {shadersMade=false;}; // activates params void BindShaders(); // binds, loads if necessary void MakeStickShaders(); void BindStickShaders(); bool BindDrawAOShader(); bool MakeDrawAOShader(); bool BindDrawAOShaderSticks(); bool MakeDrawAOShaderSticks(); bool UseHalo(); bool BindHaloShader(int powres); // 1^pow = size of halo texture bool MakeHaloShader(int powres); // questi sono settati automaticamente ///////////////////////////////////// float gap; // gap, % of border texels to be skipped int textureSideX,textureSideY; bool writeAlpha; // true during probe rendering only bool writeCol; // write a color at all? static bool init(); static void ShowShaderInfo(int i); static bool checkError(); static bool checkProgramError(char *st); static bool shaderHasChanged; float cyl_radius; bool doingAlphaSnapshot; // lots of things change when doing an alpha snapshot CgUtil(); void ResetHalo(); private: enum {MAXPOW=15}; bool shadersMade; float norm; void Normalize(); void UndoNormalize(); bool setBallVertexProgram(); bool setBallFragmentProgram(); bool setStickVertexProgram(); bool setStickFragmentProgram(); /*static int loadVertexProgram(const char *str); static int loadFragmentProgram(const char *str);*/ static char *readFile(const char *file); bool loaded, loadedStick, loadedVertexHalo; GLuint idf, idv, idfStick, idvStick; bool loadedHalo[MAXPOW]; GLuint idfHalo[MAXPOW]; GLuint idvHalo; void LoadVertexHaloShader(); void addDirectLightingSnippet(char* fp); void addTexturingSnippet(char* fp); void addShadowMapComputationFP(char* fp); void addDepthAdjustSnippet(char* fp); float _border_outside(); float _border_inside(); bool shadowmapBuilding; bool accurateShadowmapBuilding; }; qutemol/src/todo.txt0000444000175000017500000000042710464207644013131 0ustar mbambaTODO: - FIX: caricamento Presettings non influenza status Sliders/bottoni - FIX: Screenshot size 1024x1024 -> 512x512. Offscreen rendering 2048x2048 NON FUNIZONA - Make Border sizes dependent with avg atom size on screen!!! - Info panel - AO autoupdate on geom changes!!! .... qutemol/src/AO.h0000444000175000017500000000073310633256265012074 0ustar mbamba // class to compute ambient occlusion class AO{ //private: Point3f dir; // direction vector buf; int bufx, bufy; float bufscale; inline int index(int x, int y){ int res=x+bufx*y; if (res<0) res=0; if (res>=buf.size()) res=buf.size()-1; return res; //return x+bufx*y; } void PrintBuffer(); void RenderSphere(float cx, float cy, float cz, float rad); void CheckAtom(QAtom &a); public: AO( Point3f _dir, Mol &m); };