Commit 3f75f814 authored by untereiner's avatar untereiner
Browse files

Merge cgogn:~vanhoey/CGoGN

parents ff85b800 4769013a
...@@ -166,6 +166,8 @@ void Viewer::cb_Open() ...@@ -166,6 +166,8 @@ void Viewer::cb_Open()
{ {
std::string filters("all (*.*);; trian (*.trian);; ctm (*.ctm);; off (*.off);; ply (*.ply)") ; std::string filters("all (*.*);; trian (*.trian);; ctm (*.ctm);; off (*.off);; ply (*.ply)") ;
std::string filename = selectFile("Open Mesh", "", filters) ; std::string filename = selectFile("Open Mesh", "", filters) ;
if (filename.empty())
return ;
importMesh(filename) ; importMesh(filename) ;
updateGL() ; updateGL() ;
......
Pour utiliser Eclipse (testé avec la version Helios & Galileo) Pour utiliser Eclipse (testé avec la version Helios, Galileo & Indigo)
Faire un nouveau projet C++ * Configurer un projet dans Eclipse :
Choisir Makefile project -> Empty Project - Faire un nouveau projet C++
Choisir Comme "Location": la racine de NewCGoGN - Choisir Makefile project -> Empty Project
Choisir Toolchains: Linux GCC - Choisir Comme "Location": la racine de NewCGoGN
- Choisir Toolchains: Linux GCC
* Compilation avec le petit marteau ;) (l'icone)
Dans les propriétés du projet: Dans les propriétés du projet:
-> C/C++ Build: -> C/C++ Build:
Dans la configuration Default | Active: Dans la configuration Default | Active:
...@@ -12,14 +14,41 @@ Dans les propriétés du projet: ...@@ -12,14 +14,41 @@ Dans les propriétés du projet:
on peut ensuite ajouter des configurations pour compiler ce que l'on veut on peut ensuite ajouter des configurations pour compiler ce que l'on veut
en changeant juste le Build directory: en changeant juste le Build directory:
CGoGNRelease: build/Release (compile la lib en release) CGoGNRelease: build/Release (compile la lib en release)
CGoGNDebug: build/Debug (compile la lib en debug) CGoGNDebug: build/Debug (compile la lib en debug)
Apps: build/Apps (compile les exemples et les tutos) Apps: build/Apps (compile les exemples et les tutos)
Tuto: build/Apps/Tuto (compile les tutos) Tuto: build/Apps/Tuto (compile les tutos)
etc.. etc..
On peut alors compiler avec le petit marteau ;) (l'icone) et choisir avec le bouton droit ce que l'on
veut compiler.
Ceci ajoute dans le repertoire de CGoGN un .project et un .cproject. Ceci ajoute dans le repertoire de CGoGN un .project et un .cproject.
* Dépendances inter-projets et autocomplétion
Si le projet X dépend d'un autre projet, alors :
Projet X -> Properties -> Project references : cocher le projet dont il dépend.
* Dépendances de Qt :
Afin d'éviter qu'Eclipse ne rejette les syntaxes Qt (les includes de Qt, les Q_OBJECT, les callbacks) :
- Télécharger le plugin Qt "eclipse-integration" http://qt.nokia.com/developer/eclipse-integration/
- Décompresser l'archive et copier son contenu dans le répertoire d'installation d'Eclipse (plugins et features)
- Relancer Eclipse au moins une fois avec l'option --clean (relecture des répertoires locaux)
Normalement, dans Window->Preferences de Eclipse, Qt apparait dans le menu.
- Y ajouter le répertoire de Qt (/usr/bin sur Debian/Ubuntu) et le répertoire d'include (/usr/include/qt4).
Ensuite, pour chaque projet, ajouter les includes suivants dans Properties -> C/C++ general -> Paths and Symbols
parmi les includes de C++ :
- /usr/include/qt4
- /usr/include/qt4/Qt
- /usr/include/qt4/QtCore
- /usr/include/qt4/QtGui
- /usr/include/qt4/QtOpenGL
REMARQUE : en bas de cette fenêtre, le bouton "Export Settings" permet d'exporter en XML la configuration afin
de l'importer dans les autres projets.
- Pour finir, un petit clic-droit sur le projet -> Index -> Freshen all files et le tour est joué.
* Coloration syntaxique des shaders
- Télécharger et décompresser EclipseShaders : http://sourceforge.net/projects/glshaders/
- Copier les répertoires plugins et features dans le répertoire d'installation eclipse
- Relancer Eclipse au moins une fois avec l'option --clean (relecture des répertoires locaux)
Eclipse reconnaîtra désormais les fichiers .frag et .vert.
Pour associer d'autres fichiers au programme GLSLeditor :
- Preferences -> General -> Editors -> File Associations
Dans Preferences -> Shaders Preferences, on peut désormais configurer certaines options liées au shaders.
...@@ -674,9 +674,8 @@ bool MeshTablesSurface<PFP>::importPlyPTMgeneric(const std::string& filename, st ...@@ -674,9 +674,8 @@ bool MeshTablesSurface<PFP>::importPlyPTMgeneric(const std::string& filename, st
* @param attrNames : reference that will be filled with the attribute names ; * @param attrNames : reference that will be filled with the attribute names ;
* - 1 attrName for geometric position (VEC3) * - 1 attrName for geometric position (VEC3)
* - 3 attrNames for local frame (3xVEC3) : Tangent, Bitangent and Normal vector * - 3 attrNames for local frame (3xVEC3) : Tangent, Bitangent and Normal vector
* - 6 attrNames for the function coefficients (6xVEC3) : 6 RGB coefficients being successively the constants, the linears (v then u) and the quadratics : a0 + a1*v + a2*u + a3*u*v + a4*v^2 + a5*u^2. * - 6 attrNames for the function coefficients (6xVEC3) : 6 RGB coefficients being successively the quadratic members, the linears and the constants (u then v) : a*u^2 + b*v^2 + c*uv + d*u + e*v +f.
* @return bool : success. * @return bool : success.
* @return bool : success.
*/ */
template <typename PFP> template <typename PFP>
bool MeshTablesSurface<PFP>::importPlyPTM(const std::string& filename, std::vector<std::string>& attrNames) bool MeshTablesSurface<PFP>::importPlyPTM(const std::string& filename, std::vector<std::string>& attrNames)
......
...@@ -114,6 +114,7 @@ bool importMesh(typename PFP::MAP& map, MeshTablesSurface<PFP>& mts) ...@@ -114,6 +114,7 @@ bool importMesh(typename PFP::MAP& map, MeshTablesSurface<PFP>& mts)
} }
else else
{ {
m.unmark(d);
++nbnm; ++nbnm;
} }
} }
......
...@@ -25,19 +25,48 @@ ...@@ -25,19 +25,48 @@
#ifndef LOCALFRAME_H_ #ifndef LOCALFRAME_H_
#define LOCALFRAME_H_ #define LOCALFRAME_H_
#include <cmath>
namespace CGoGN { namespace CGoGN {
namespace Utils { namespace Utils {
/**
* Util for rotation of a 3D point (or vector) around a given line (going through the origin) and of a given angle
* @param axis the rotation axis direction
* @param angle the rotation angle
* @param p the point to rotate
*/
template <typename REAL>
Geom::Vector<3,REAL> rotate (Geom::Vector<3,REAL> axis, REAL angle, Geom::Vector<3,REAL> p) ;
/**
* Util for conversion from spherical to carthesian coordinates.
* The spherical coordinates are in radius-longitude-latitude
* @param sph the spherical coordinates
* @return the carthesian coordinates
*/
template<typename REAL>
Geom::Vector<3,REAL> sphericalToCarth (const Geom::Vector<3,REAL>& sph) ;
/**
* Util for conversion from carthesian to spherical coordinates.
* The spherical coordinates are in radius-longitude-latitude
* @param carth the carthesian coordinates
* @return the spherical coordinates
*/
template<typename REAL>
Geom::Vector<3,REAL> carthToSpherical (const Geom::Vector<3,REAL>& carth) ;
/** /**
* Class for representing a direct local frame composed of 3 orthonormal vectors T (tangent), B (bitangent) and N (normal). * Class for representing a direct local frame composed of 3 orthonormal vectors T (tangent), B (bitangent) and N (normal).
* This class can compress/decompress a local frame, switching from its explicit representation (3 vectors) to its compressed representation (1 vector). * This class can compress/decompress a local frame, switching from its explicit representation (3 vectors) to its compressed representation (1 vector).
* Usage : * Usage :
* VEC3 T,B,N ; // current set of orthonormal vectors composing the direct frame. * VEC3 T,B,N ; // current set of orthonormal vectors composing the direct frame.
* LocalFrame<PFP::VEC3> lf(T,B,N) ; // Constructor from explicit expression. * LocalFrame<PFP> lf(T,B,N) ; // Constructor from explicit expression.
* if (lf.isOrthoNormalDirect()) // test if the frame is Orthogonal, Normalized and Direct * if (lf.isOrthoNormalDirect()) // test if the frame is Orthogonal, Normalized and Direct
* VEC3 compressed = lf.getCompressed() ; // Extract compressed frame * VEC3 compressed = lf.getCompressed() ; // Extract compressed frame
* LocalFrame<PFP::VEC3> decompressed(compressed) ; // Constructor from implicit (compressed) expression. * LocalFrame<PFP> decompressed(compressed) ; // Constructor from implicit (compressed) expression.
* *
* All formulae were provided by "Représentation compacte d'un repère local", june 14th, 2011 by K. Vanhoey * All formulae were provided by "Représentation compacte d'un repère local", june 14th, 2011 by K. Vanhoey
*/ */
...@@ -46,7 +75,7 @@ class LocalFrame ...@@ -46,7 +75,7 @@ class LocalFrame
{ {
typedef typename PFP::REAL REAL ; typedef typename PFP::REAL REAL ;
typedef typename Geom::Vector<2,REAL> VEC2 ; typedef typename Geom::Vector<2,REAL> VEC2 ;
typedef typename PFP::VEC3 VEC3 ; typedef typename Geom::Vector<3,REAL> VEC3 ;
private: // fields private: // fields
/** /**
...@@ -62,17 +91,20 @@ public: // methods ...@@ -62,17 +91,20 @@ public: // methods
* @param N the normal vector * @param N the normal vector
*/ */
LocalFrame(const VEC3& T, const VEC3& B, const VEC3& N) ; LocalFrame(const VEC3& T, const VEC3& B, const VEC3& N) ;
/** /**
* Constructor from implicit (compressed representation) * Constructor from implicit (compressed representation)
* @param compressedFrame an implicit (compressed) version of the local frame * @param compressedFrame an implicit (compressed) version of the local frame (can be produced by localFrame.getCompressed())
*/ */
LocalFrame(const VEC3& compressedFrame) ; LocalFrame(const VEC3& compressedFrame) ;
~LocalFrame() {} ; ~LocalFrame() {} ;
/** /**
* Returns a compressed version of the current local frame * Returns a compressed version of the current local frame
* A VEC3 is not sufficient to completely define a local frame (if phiN=0, the decompression is not unique).
*/ */
VEC3 getCompressed() ; VEC3 getCompressed() const ;
/** /**
* Tests if the frames are identical * Tests if the frames are identical
...@@ -80,7 +112,7 @@ public: // methods ...@@ -80,7 +112,7 @@ public: // methods
* @param epsilon the authorized deviation * @param epsilon the authorized deviation
* @return true if frames are identical (or deviate less than epsilon) * @return true if frames are identical (or deviate less than epsilon)
*/ */
bool equals(const LocalFrame<PFP>& lf, REAL epsilon = 1e-5) const ; bool equals(const LocalFrame<PFP>& lf, REAL epsilon = 1e-6) const ;
/** /**
* Equality of frames * Equality of frames
...@@ -100,25 +132,25 @@ public: // methods ...@@ -100,25 +132,25 @@ public: // methods
* Tests if the frame is direct * Tests if the frame is direct
* @return true if the frame is direct * @return true if the frame is direct
*/ */
bool isDirect() const ; bool isDirect(REAL epsilon = 1e-7) const ;
/** /**
* Tests if the frame is orthogonal * Tests if the frame is orthogonal
* @return true if the frame is orthogonal * @return true if the frame is orthogonal
*/ */
bool isOrthogonal() const ; bool isOrthogonal(REAL epsilon = 1e-5) const ;
/** /**
* Tests if the frame is normalized * Tests if the frame is normalized
* @return true if the frame is normalized * @return true if the frame is normalized
*/ */
bool isNormalized() const ; bool isNormalized(REAL epsilon = 1e-5) const ;
/** /**
* Tests if the frame is direct, normalized and orthogonal * Tests if the frame is direct, normalized and orthogonal
* @return true if the frame is direct, normalized and orthogonal * @return true if the frame is direct, normalized and orthogonal
*/ */
bool isOrthoNormalDirect() const ; bool isOrthoNormalDirect(REAL epsilon = 1e-5) const ;
/** /**
* @return current tangent vector * @return current tangent vector
...@@ -141,13 +173,33 @@ public: // methods ...@@ -141,13 +173,33 @@ public: // methods
friend std::ostream& operator<< (std::ostream &out, const LocalFrame& lf) { friend std::ostream& operator<< (std::ostream &out, const LocalFrame& lf) {
out << "T : " << lf.m_T << std::endl ; out << "T : " << lf.m_T << std::endl ;
out << "B : " << lf.m_B << std::endl ; out << "B : " << lf.m_B << std::endl ;
out << "N : " << lf.m_N << std::endl ; out << "N : " << lf.m_N ;
return out ; return out ;
} ; } ;
private : // methods private : // private constants
VEC2 carthToSpherical(const VEC3& carth) const ; // (T,B,N) can be any orthonormal direct frame
VEC3 sphericalToCarth(const VEC2& sph) const ; // zeros are not recommended since they can
// generate zero vectors after a dot product
// static const REAL Tx = 0.267261 ;
// static const REAL Ty = 0.534522 ;
// static const REAL Tz = 0.801784 ;
// static const REAL Bx = 0.844416 ;
// static const REAL By = -0.530776 ;
// static const REAL Bz = 0.0723785 ;
// static const REAL Nx = 0.464255 ;
// static const REAL Ny = 0.657695 ;
// static const REAL Nz = -0.593215 ;
static const REAL Tx = 0.0766965 ;
static const REAL Ty = 0.383483 ;
static const REAL Tz = 0.920358 ;
static const REAL Bx = -0.760734 ;
static const REAL By = 0.619202 ;
static const REAL Bz = -0.194606 ;
static const REAL Nx = -0.644516 ;
static const REAL Ny = -0.685222 ;
static const REAL Nz = 0.339219 ;
} ; } ;
} // Utils } // Utils
......
...@@ -38,47 +38,39 @@ LocalFrame<PFP>::LocalFrame(const VEC3& T, const VEC3& B, const VEC3& N) ...@@ -38,47 +38,39 @@ LocalFrame<PFP>::LocalFrame(const VEC3& T, const VEC3& B, const VEC3& N)
template<typename PFP> template<typename PFP>
LocalFrame<PFP>::LocalFrame(const VEC3& compressedFrame) LocalFrame<PFP>::LocalFrame(const VEC3& compressedFrame)
{ {
VEC2 Nspher ; const VEC3 T(Tx,Ty,Tz) ;
VEC2 Tspher ; const VEC3 N(Nx,Ny,Nz) ;
REAL& thetaN = Nspher[0] ; // known // get known data
REAL& phiN = Nspher[1] ; // known const REAL& theta1 = compressedFrame[0] ;
REAL& thetaT = Tspher[0] ; // known const REAL& phi = compressedFrame[1] ;
REAL& phiT = Tspher[1] ; // to be decoded const REAL& theta2 = compressedFrame[2] ;
// compute phiT const VEC3 Tprime = rotate<REAL>(N,theta1,T) ;
REAL Den,Nom ; m_N = rotate<REAL>(Tprime,phi,N) ;
Den = sin(phiN)*(cos(thetaN)*cos(thetaT) + sin(thetaN)*sin(thetaT)) ; // Based on orthogonality m_T = rotate<REAL>(m_N,theta2,Tprime) ;
Nom = cos(phiN) ;
phiT = -atan(Nom/Den) ; // if A==0, atan returns Pi/2
if (phiT < 0.0)
phiT = M_PI + phiT ; // = Pi - |phiT|
// convert to carthesian
m_N = sphericalToCarth(Nspher) ;
m_T = sphericalToCarth(Tspher) ;
// compute B
m_B = m_N ^ m_T ; m_B = m_N ^ m_T ;
} }
template<typename PFP> template<typename PFP>
typename PFP::VEC3 LocalFrame<PFP>::getCompressed() typename Geom::Vector<3,typename PFP::REAL> LocalFrame<PFP>::getCompressed() const
{ {
VEC3 res ; VEC3 res ;
REAL& thetaN = res[0] ; const VEC3 T(Tx,Ty,Tz) ;
REAL& phiN = res[1] ; const VEC3 B(Bx,By,Bz) ;
REAL& thetaT = res[2] ; const VEC3 N(Nx,Ny,Nz) ;
// convert to spherical coordinates REAL& theta1 = res[0] ;
VEC2 Nspher = carthToSpherical(m_N) ; REAL& phi = res[1] ;
VEC2 Tspher = carthToSpherical(m_T) ; REAL& theta2 = res[2] ;
// extract the three scalars VEC3 Tprime = N ^ m_N ;
thetaN = Nspher[0] ; Tprime.normalize() ;
phiN = Nspher[1] ;
thetaT = Tspher[0] ; theta1 = (B*Tprime > 0 ? 1 : -1) * std::acos(std::max(std::min(REAL(1.0), T*Tprime ),REAL(-1.0))) ;
phi = std::acos(std::max(std::min(REAL(1.0), N*m_N ),REAL(-1.0))) ; // phi1 is always positive because the direction of vector Tp=N^N1 (around which a rotation of angle phi is done later on) changes depending on the side on which they lay w.r.t eachother.
theta2 = (m_B*Tprime > 0 ? -1 : 1) * std::acos(std::max(std::min(REAL(1.0), m_T*Tprime ),REAL(-1.0))) ;
return res ; return res ;
} }
...@@ -106,77 +98,74 @@ bool LocalFrame<PFP>::operator!=(const LocalFrame<PFP>& lf) const ...@@ -106,77 +98,74 @@ bool LocalFrame<PFP>::operator!=(const LocalFrame<PFP>& lf) const
} }
template<typename PFP> template<typename PFP>
bool LocalFrame<PFP>::isDirect() const bool LocalFrame<PFP>::isDirect(REAL epsilon) const
{ {
VEC3 new_B = m_N ^ m_T ; // direct VEC3 new_B = m_N ^ m_T ; // direct
VEC3 diffs = new_B - m_B ; // differences with existing B VEC3 diffs = new_B - m_B ; // differences with existing B
REAL diffNorm = diffs.norm2() ; // Norm of this differences vector REAL diffNorm = diffs.norm2() ; // Norm of this differences vector
return (diffNorm < 1e-10) ; // Verify that this difference is very small return (diffNorm < epsilon) ; // Verify that this difference is very small
} }
template<typename PFP> template<typename PFP>
bool LocalFrame<PFP>::isOrthogonal() const bool LocalFrame<PFP>::isOrthogonal(REAL epsilon) const
{ {
return (fabs(m_T * m_B) < 1e-5) && (fabs(m_N * m_B) < 1e-5) && (fabs(m_T * m_N) < 1e-5) ; return (fabs(m_T * m_B) < epsilon) && (fabs(m_N * m_B) < epsilon) && (fabs(m_T * m_N) < epsilon) ;
} }
template<typename PFP> template<typename PFP>
bool LocalFrame<PFP>::isNormalized() const bool LocalFrame<PFP>::isNormalized(REAL epsilon) const
{ {
return (1-1e-5 < m_N.norm2() && m_N.norm2() < 1+1e-5) return (1-epsilon < m_N.norm2() && m_N.norm2() < 1+epsilon)
&& (1-1e-5 < m_T.norm2() && m_T.norm2() < 1+1e-5) && (1-epsilon < m_T.norm2() && m_T.norm2() < 1+epsilon)
&& (1-1e-5 < m_B.norm2() && m_B.norm2() < 1+1e-5) ; && (1-epsilon < m_B.norm2() && m_B.norm2() < 1+epsilon) ;
} }
template<typename PFP> template<typename PFP>
bool LocalFrame<PFP>::isOrthoNormalDirect() const bool LocalFrame<PFP>::isOrthoNormalDirect(REAL epsilon) const
{ {
return isOrthogonal() && isNormalized() && isDirect() ; return isOrthogonal(epsilon) && isNormalized(epsilon) && isDirect(epsilon) ;
} }
template<typename PFP>
typename Geom::Vector<2,typename PFP::REAL> LocalFrame<PFP>::carthToSpherical (const VEC3& carth) const template<typename REAL>
Geom::Vector<3,REAL> carthToSpherical (const Geom::Vector<3,REAL>& carth)
{ {
VEC2 res ; Geom::Vector<3,REAL> res ;
const REAL& x = carth[0] ; const REAL& x = carth[0] ;
const REAL& y = carth[1] ; const REAL& y = carth[1] ;
const REAL& z = carth[2] ; const REAL& z = carth[2] ;
REAL& theta = res[0] ; REAL& rho = res[0] ;
REAL& phi = res[1] ; REAL& theta = res[1] ;
REAL& phi = res[2] ;
phi = acos(z) ; rho = carth.norm() ;
const REAL sinphi = sin(phi) ; theta = ((y < 0) ? -1 : 1) * std::acos(x / REAL(sqrt(x*x + y*y)) ) ;
if (sinphi == 0.0) if (isnan(theta))
theta = 0.0 ; theta = 0.0 ;
else phi = std::asin(z) ;
theta = ((y > 0) ? 1 : -1) * acos(std::min(REAL(1.0),std::max(REAL(-1.0),x / sinphi))) ;
assert (-(M_PI+0.000001) <= theta && theta <= M_PI+0.000001) ;
assert (-0.000001 < phi && phi <= M_PI+0.000001) ;
assert (!isnan(theta) || !"carthToSpherical : Theta is NaN !") ;
assert (!isnan(phi) || !"carthToSpherical : Phi is NaN !") ;
return res ; return res ;
} }
template<typename PFP> template<typename REAL>
typename PFP::VEC3 LocalFrame<PFP>::sphericalToCarth (const VEC2& sph) const Geom::Vector<3,REAL> sphericalToCarth (const Geom::Vector<3,REAL>& sph)
{ {
VEC3 res ; Geom::Vector<3,REAL> res ;
const REAL& theta = sph[0] ; const REAL& rho = sph[0] ;
const REAL& phi = sph[1] ; const REAL& theta = sph[1] ;
const REAL& phi = sph[2] ;
REAL& x = res[0] ; REAL& x = res[0] ;
REAL& y = res[1] ; REAL& y = res[1] ;
REAL& z = res[2] ; REAL& z = res[2] ;
x = cos(theta)*sin(phi) ; x = rho*cos(theta)*cos(phi) ;
y = sin(theta)*sin(phi) ; y = rho*sin(theta)*cos(phi) ;
z = cos(phi) ; z = rho*sin(phi) ;
assert(-1.000001 < x && x < 1.000001) ; assert(-1.000001 < x && x < 1.000001) ;
assert(-1.000001 < y && y < 1.000001) ; assert(-1.000001 < y && y < 1.000001) ;
...@@ -185,6 +174,35 @@ typename PFP::VEC3 LocalFrame<PFP>::sphericalToCarth (const VEC2& sph) const ...@@ -185,6 +174,35 @@ typename PFP::VEC3 LocalFrame<PFP>::sphericalToCarth (const VEC2& sph) const
return res ; return res ;
} }
template <typename REAL>
Geom::Vector<3,REAL> rotate (Geom::Vector<3,REAL> axis, REAL angle, Geom::Vector<3,REAL> vector)
{
axis.normalize() ;
const REAL& u = axis[0] ;
const REAL& v = axis[1] ;
const REAL& w = axis[2] ;
const REAL& x = vector[0] ;
const REAL& y = vector[1] ;
const REAL& z = vector[2] ;
Geom::Vector<3,REAL> res ;
REAL& xp = res[0] ;
REAL& yp = res[1] ;
REAL& zp = res[2] ;
const REAL tmp1 = u*x+v*y+w*z ;
const REAL cos = std::cos(angle) ;
const REAL sin = std::sin(angle) ;
xp = u*tmp1*(1-cos) + x*cos+(v*z-w*y)*sin ;
yp = v*tmp1*(1-cos) + y*cos-(u*z-w*x)*sin ;
zp = w*tmp1*(1-cos) + z*cos+(u*y-v*x)*sin ;
return res ;
}
} // Utils } // Utils
} // CGoGN } // CGoGN
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment