Commit 78e96120 authored by CGoGN GIT Supervisor's avatar CGoGN GIT Supervisor

Merge branch 'master' of /home/thery/CGoGN

parents 602d10c6 1262e060
......@@ -25,6 +25,7 @@ include_directories(
${CGoGN_ROOT_DIR}/ThirdParty/AntTweakBar/include
${CGoGN_ROOT_DIR}/ThirdParty/OpenCTM
${CGoGN_ROOT_DIR}/ThirdParty/Assimp/include
${CGoGN_ROOT_DIR}/ThirdParty/glm
)
# define libs path
......@@ -46,3 +47,9 @@ target_link_libraries( Geom_inclusionD
add_executable( Geom_intersectionD ./Geom_intersection.cpp)
target_link_libraries( Geom_intersectionD
${CGoGN_LIBS_D} ${COMMON_LIBS} )
QT4_WRAP_CPP(concave_rendering_moc concave_rendering.h)
add_executable( concave_renderingD concave_rendering.cpp ${concave_rendering_moc})
target_link_libraries( concave_renderingD
${CGoGN_LIBS_D} ${COMMON_LIBS} ${QT_LIBRARIES} )
This diff is collapsed.
/*******************************************************************************
* CGoGN: Combinatorial and Geometric modeling with Generic N-dimensional Maps *
* version 0.1 *
* Copyright (C) 2009-2011, IGG Team, LSIIT, University of Strasbourg *
* *
* This library is free software; you can redistribute it and/or modify it *
* under the terms of the GNU Lesser General Public License as published by the *
* Free Software Foundation; either version 2.1 of the License, or (at your *
* option) any later version. *
* *
* 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 Lesser General Public License *
* for more details. *
* *
* You should have received a copy of the GNU Lesser General Public License *
* along with this library; if not, write to the Free Software Foundation, *
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *
* *
* Web site: http://cgogn.u-strasbg.fr/ *
* Contact information: cgogn@unistra.fr *
* *
*******************************************************************************/
#ifndef _TUTO1_
#define _TUTO1_
#include <iostream>
#include "Utils/qtSimple.h"
#include "Utils/cgognStream.h"
// forward definitions (minimize includes)
namespace CGoGN { namespace Algo { namespace Render { namespace GL2 { class MapRender; } } } }
namespace CGoGN { namespace Utils { class VBO; } }
namespace CGoGN { namespace Utils { class ShaderSimpleColor; } }
using namespace CGoGN ;
/**
* A class for a little interface and rendering
*/
class MyQT : public Utils::QT::SimpleQT
{
Q_OBJECT
public:
// render
Algo::Render::GL2::MapRender* m_render;
// VBO
Utils::VBO* m_positionVBO;
// shader basic
Utils::ShaderSimpleColor* m_shader;
MyQT() : m_render(NULL), m_positionVBO(NULL), m_shader(NULL)
{}
// callbacks of simpleQT to overdefine:
void cb_initGL();
void cb_redraw();
void cb_keyPress(int code);
void cb_New() { CGoGNout << "New ..." << CGoGNendl; }
void cb_Save() { CGoGNout << "Rien a sauver ..." << CGoGNendl; }
// callbacks (slots) locally defined
public slots:
void menu_slot1() { CGoGNout << "Exemple de menu" << CGoGNendl; }
};
#endif
......@@ -50,6 +50,27 @@ typename PFP::VEC3 triangleNormal(typename PFP::MAP& map, Dart d, const typename
return N ;
}
template<typename PFP>
typename PFP::VEC3 newellNormal(typename PFP::MAP& map, Dart d, const typename PFP::TVEC3& position)
{
Dart e=d;
typename PFP::VEC3 normal(0);
do
{
const typename PFP::VEC3& P = position[e];
e = map.phi1(e);
const typename PFP::VEC3& Q = position[e];
normal[0] += (P[1]-Q[1])*(P[2]+Q[2]);
normal[1] += (P[2]-Q[2])*(P[0]+Q[0]);
normal[2] += (P[0]-Q[0])*(P[1]+Q[1]);
}while (e !=d);
normal.normalize();
return normal;
}
template <typename PFP>
typename PFP::VEC3 faceNormal(typename PFP::MAP& map, Dart d, const typename PFP::TVEC3& position)
{
......
......@@ -28,6 +28,7 @@
#include <GL/glew.h>
#include <vector>
#include <list>
#include <set>
#include <utility>
#include "Topology/generic/dart.h"
......@@ -89,6 +90,50 @@ protected:
typedef std::pair<GLuint*, unsigned int> buffer_array;
// forward declaration
class VertexPoly;
// comparaison function for multiset
static bool cmpVP(VertexPoly* lhs, VertexPoly* rhs);
// multiset typedef for simple writing
typedef std::multiset< VertexPoly*,bool(*)(VertexPoly*,VertexPoly*)> VPMS;
class VertexPoly
{
public:
int id;
float value;
VertexPoly* prev;
VertexPoly* next;
VPMS::iterator ear;
VertexPoly(int i, float v, VertexPoly* p=NULL): id(i),value(v), prev(p), next(NULL)
{
if (prev!=NULL)
prev->next = this;
}
static void close(VertexPoly* first, VertexPoly* last)
{
last->next = first;
first->prev = last;
}
static VertexPoly* erase(VertexPoly* vp)
{
VertexPoly* tmp = vp->prev;
tmp->next = vp->next;
vp->next->prev = tmp;
vp->value = 20.0f; //??
delete vp;
return tmp;
}
};
public:
/**
* Constructor
......@@ -109,6 +154,7 @@ public:
buffer_array get_nb_index_buffer() { return std::make_pair(m_nbIndices, SIZE_BUFFER); }
protected:
/**
* addition of indices table of one triangle
* @param d a dart of the triangle
......@@ -117,6 +163,22 @@ protected:
template <typename PFP>
void addTri(typename PFP::MAP& map, Dart d, std::vector<GLuint>& tableIndices) ;
template<typename PFP>
inline void addEarTri(typename PFP::MAP& map, Dart d, std::vector<GLuint>& tableIndices);
// template<typename PFP>
// float computeEarAngle(AttributeHandler<typename PFP::VEC3>& position, const typename PFP::VEC3& normalPoly, unsigned int i, unsigned int j, unsigned int k);
template<typename PFP>
float computeEarAngle(const typename PFP::VEC3& P1, const typename PFP::VEC3& P2, const typename PFP::VEC3& P3, const typename PFP::VEC3& normalPoly);
template<typename PFP>
bool computeEarIntersection(AttributeHandler<typename PFP::VEC3>& position, VertexPoly* vp, const typename PFP::VEC3& normalPoly);
template<typename PFP>
void recompute2Ears( AttributeHandler<typename PFP::VEC3>& position, VertexPoly* vp, const typename PFP::VEC3& normalPoly, VPMS& ears, bool convex);
public:
/**
* creation of indices table of triangles (optimized order)
......@@ -162,6 +224,8 @@ public:
* draw the VBO (function to call in the drawing callback)
*/
void draw(Utils::GLSLShader* sh, int prim) ;
unsigned int drawSub(Utils::GLSLShader* sh, int prim, unsigned int nb_elm);
} ;
} // namespace GL2
......
......@@ -26,6 +26,10 @@
#include "Topology/generic/cellmarker.h"
#include "Utils/vbo.h"
#include "Topology/generic/attributeHandler.h"
#include "Geometry/intersection.h"
#include "Algo/Geometry/normal.h"
namespace CGoGN
{
......@@ -38,6 +42,230 @@ namespace Render
namespace GL2
{
inline bool MapRender::cmpVP(VertexPoly* lhs, VertexPoly* rhs)
{
return lhs->value < rhs->value;
}
template<typename PFP>
void MapRender::recompute2Ears( AttributeHandler<typename PFP::VEC3>& position, VertexPoly* vp, const typename PFP::VEC3& normalPoly, VPMS& ears, bool convex)
{
VertexPoly* vprev = vp->prev;
VertexPoly* vp2 = vp->next;
VertexPoly* vnext = vp2->next;
const typename PFP::VEC3& Ta = position[vp->id];
const typename PFP::VEC3& Tb = position[vp2->id];
const typename PFP::VEC3& Tc = position[vprev->id];
const typename PFP::VEC3& Td = position[vnext->id];
// compute angle
typename PFP::VEC3 v1= Tb - Ta;
typename PFP::VEC3 v2= Tc - Ta;
typename PFP::VEC3 v3= Td - Tb;
v1.normalize();
v2.normalize();
v3.normalize();
float dotpr1 = 1.0f - (v1*v2);
float dotpr2 = 1.0f + (v1*v3);
if (!convex) // if convex no need to test if vertex is an ear (yes)
{
typename PFP::VEC3 nv1 = v1^v2;
typename PFP::VEC3 nv2 = v1^v3;
if (nv1*normalPoly < 0.0)
dotpr1 = 10.0f - dotpr1;// not an ears (concave)
if (nv2*normalPoly < 0.0)
dotpr2 = 10.0f - dotpr2;// not an ears (concave)
bool finished = false;
for (VPMS::reverse_iterator it = ears.rbegin(); (!finished)&&(it != ears.rend())&&((*it)->value > 5.0f); ++it)
{
int id = (*it)->id;
const typename PFP::VEC3& P = position[id];
// typename PFP::VEC3 inter;
if ((dotpr1 != 5.0f) && (id !=vprev->id))
if (Geom::intersectionRayTriangleOpt<typename PFP::VEC3>(P, normalPoly, Ta,Tb,Tc) > Geom::VERTEX_INTERSECTION)
dotpr1 = 5.0f;// not an ears !
if ((dotpr2 != 5.0f) && (id !=vnext->id) )
if (Geom::intersectionRayTriangleOpt<typename PFP::VEC3>(P, normalPoly, Tb,Td,Ta) > Geom::VERTEX_INTERSECTION)
dotpr2 = 5.0f;// not an ears !
finished = ((dotpr1 == 5.0f)&&(dotpr2 == 5.0f));
}
}
vp->value = dotpr1;
vp->ear = ears.insert(vp);
vp2->value = dotpr2;
vp2->ear = ears.insert(vp2);
}
template<typename PFP>
float MapRender::computeEarAngle(const typename PFP::VEC3& P1, const typename PFP::VEC3& P2, const typename PFP::VEC3& P3, const typename PFP::VEC3& normalPoly)
{
typename PFP::VEC3 v1 = P1-P2;
typename PFP::VEC3 v2 = P3-P2;
v1.normalize();
v2.normalize();
float dotpr = 1.0f - (v1*v2);
typename PFP::VEC3 vn = v1^v2;
if (vn*normalPoly > 0.0f)
dotpr = 10.0f - dotpr; // not an ears (concave, store at the end for optimized use for intersections)
return dotpr;
}
template<typename PFP>
bool MapRender::computeEarIntersection(AttributeHandler<typename PFP::VEC3>& position, VertexPoly* vp, const typename PFP::VEC3& normalPoly)
{
VertexPoly* endV = vp->prev;
VertexPoly* curr = vp->next;
const typename PFP::VEC3& Ta = position[vp->id];
const typename PFP::VEC3& Tb = position[curr->id];
const typename PFP::VEC3& Tc = position[endV->id];
curr = curr->next;
while (curr != endV)
{
// typename PFP::VEC3 inter;
Geom::Intersection res = Geom::intersectionRayTriangleOpt<typename PFP::VEC3>(position[curr->id], normalPoly, Ta,Tb,Tc);
if (res > Geom::VERTEX_INTERSECTION)
{
vp->value = 5.0f;// not an ears !
return false;
}
curr = curr->next;
}
return true;
}
template<typename PFP>
inline void MapRender::addEarTri(typename PFP::MAP& map, Dart d, std::vector<GLuint>& tableIndices)
{
bool(*fn_pt)(VertexPoly*,VertexPoly*) = &(MapRender::cmpVP);
VPMS ears(fn_pt);
AttributeHandler<typename PFP::VEC3> position = map.template getAttribute<typename PFP::VEC3>(VERTEX,"position");
// compute normal to polygon
typename PFP::VEC3 normalPoly = Algo::Geometry::newellNormal<PFP>(map, d, position);
// first pass create polygon in chained list witht angle computation
VertexPoly* vpp=NULL;
VertexPoly* prem=NULL;
unsigned int nbv = 0;
unsigned int nbe = 0;
Dart a = d;
Dart b = map.phi1(a);
Dart c = map.phi1(b);
do
{
// typename PFP::VEC3 v1= position[map.getEmbedding(VERTEX,a)]-position[map.getEmbedding(VERTEX,b)];
// typename PFP::VEC3 v2= position[map.getEmbedding(VERTEX,c)]-position[map.getEmbedding(VERTEX,b)];
// typename PFP::VEC3 v3= position[map.getEmbedding(VERTEX,c)]-position[map.getEmbedding(VERTEX,a)];
typename PFP::VEC3 P1= position[map.getEmbedding(VERTEX,a)];
typename PFP::VEC3 P2= position[map.getEmbedding(VERTEX,b)];
typename PFP::VEC3 P3= position[map.getEmbedding(VERTEX,c)];
float val = computeEarAngle<PFP>(P1,P2,P3,normalPoly);
VertexPoly* vp = new VertexPoly(map.getEmbedding(VERTEX,b),val,vpp);
if (vp->value <5.0f)
nbe++;
if (vpp==NULL)
prem = vp;
vpp = vp;
a = b;
b = c;
c = map.phi1(c);
nbv++;
}while (a!=d);
VertexPoly::close(prem,vpp);
// bool convex = nbe==nbv;
bool convex = false;
if (convex)
{
// second pass with no test of intersections with polygons
vpp = prem;
for (unsigned int i=0; i< nbv; ++i)
{
vpp->ear = ears.insert(vpp);
vpp = vpp->next;
}
}
else
{
// second pass test intersections with polygons
vpp = prem;
for (unsigned int i=0; i< nbv; ++i)
{
if (vpp->value <5.0f)
{
computeEarIntersection<PFP>(position,vpp,normalPoly);
}
vpp->ear = ears.insert(vpp);
vpp = vpp->next;
}
}
// DBG: AFF ears
// for (std::multimap< float, VertexPoly* >::iterator it = ears.begin(); it != ears.end(); ++it )
// std::cout << it->first <<" , "<< it->second->id<<" , "<< it->second->value<< " / ";
// std::cout << std::endl;
// NO WE HAVE THE POLYGON AND EARS
// LET'S REMOVE THEM
while (nbv>3)
{
// take best (and valid!) ear
VPMS::iterator be_it = ears.begin(); // best ear is big value cos -> last in map
VertexPoly* be = *be_it;
tableIndices.push_back(be->id);
tableIndices.push_back(be->next->id);
tableIndices.push_back(be->prev->id);
//remove 3 ears
ears.erase(be_it); // from map of ears
ears.erase(be->next->ear);
ears.erase(be->prev->ear);
be = VertexPoly::erase(be); // and remove ear vertex from polygon
nbv--;
if (nbv>3) // do not recompute if only one triangle left
recompute2Ears<PFP>(position,be,normalPoly,ears,convex);
else // finish
{
tableIndices.push_back(be->id);
tableIndices.push_back(be->next->id); // last triangle
tableIndices.push_back(be->prev->id);
// release memory of last triangle in polygon
delete be->next;
delete be->prev;
delete be;
}
}
}
template<typename PFP>
inline void MapRender::addTri(typename PFP::MAP& map, Dart d, std::vector<GLuint>& tableIndices)
{
......@@ -45,6 +273,12 @@ inline void MapRender::addTri(typename PFP::MAP& map, Dart d, std::vector<GLuint
Dart b = map.phi1(a);
Dart c = map.phi1(b);
if (map.phi1(c) != a)
{
addEarTri<PFP>(map, d, tableIndices); //TODO version optimisee pour 4 cotes ?
return;
}
// loop to cut a polygon in triangle on the fly (works only with convex faces)
do
{
......
......@@ -59,11 +59,59 @@ Intersection intersectionLinePlane(const VEC3& P, const VEC3& Dir, const VEC3& P
/**
* test the intersection between a ray and a triangle
* test the intersection between a ray and a triangle (optimized version with triple product
* @param P a point on the line
* @param Dir line direction
* @param Ta triangle point 1
* @param Tb triangle point 2
* @param Tc triangle point 3
* @param Inter store the intersection point
* @return the intersection ( FACE_INTERSECTION / EDGE_INTERSECTION / VERTEX_INTERSECTION / NO_INTERSECTION)
*/
template <typename VEC3>
Intersection intersectionRayTriangle(const VEC3& P, const VEC3& Dir, const VEC3& Ta, const VEC3& Tb, const VEC3& Tc, VEC3& Inter) ;
/**
* test the intersection between a ray and a triangle (optimized version with triple product
* @param P a point on the line
* @param Dir line direction
* @param Ta triangle point 1
* @param Tb triangle point 2
* @param Tc triangle point 3
* @param Inter store the intersection point
* @return the intersection ( FACE_INTERSECTION / EDGE_INTERSECTION / VERTEX_INTERSECTION / NO_INTERSECTION)
*/
template <typename VEC3>
Intersection intersectionRayTriangleOpt(const VEC3& P, const VEC3& Dir, const VEC3& Ta, const VEC3& Tb, const VEC3& Tc, VEC3& Inter);
/**
* test the intersection between a ray and a triangle (optimized version with triple product
* @param P a point on the line
* @param Dir line direction
* @param Ta triangle point 1
* @param Tb triangle point 2
* @param Tc triangle point 3
* @return the intersection ( FACE_INTERSECTION / EDGE_INTERSECTION / VERTEX_INTERSECTION / NO_INTERSECTION)
*/
template <typename VEC3>
Intersection intersectionRayTriangleOpt(const VEC3& P, const VEC3& Dir, const VEC3& Ta, const VEC3& Tb, const VEC3& Tc);
/**
* test the intersection between a ray and a triangle, but test only face intersection and
* @param P a point on the line
* @param Dir line direction
* @param Ta triangle point 1
* @param Tb triangle point 2
* @param Tc triangle point 3
* @param Inter store the intersection point
* @return the intersection ( FACE_INTERSECTION / EDGE_INTERSECTION / VERTEX_INTERSECTION / NO_INTERSECTION)
*/
//template <typename VEC3>
//Intersection intersectionRayTriangleFaceOnly(const VEC3& P, const VEC3& Dir, const VEC3& Ta, const VEC3& Tb, const VEC3& Tc)
/**
* test the intersection between a line and a triangle
* @param P a point on the line
......
......@@ -52,6 +52,146 @@ Intersection intersectionLinePlane(const VEC3& P, const VEC3& Dir, const VEC3& P
}
//template <typename VEC3>
//Intersection intersectionRayTriangleFaceOnly(const VEC3& P, const VEC3& Dir, const VEC3& Ta, const VEC3& Tb, const VEC3& Tc)
//{
// typedef typename VEC3::DATA_TYPE T ;
//
// VEC3 u = Ta - P ;
// VEC3 v = Tb - P ;
// VEC3 w = Tc - P ;
// T x = tripleProduct(Dir, u, v) ;
// T y = tripleProduct(Dir, v, w) ;
// T z = tripleProduct(Dir, w, u) ;
// if((x < T(0) && y < T(0) && z < T(0)) || (x > T(0) && y > T(0) && z > T(0)))
// return FACE_INTERSECTION ;
// return NO_INTERSECTION ;
//}
template <typename VEC3>
Intersection intersectionRayTriangleOpt(const VEC3& P, const VEC3& Dir, const VEC3& Ta, const VEC3& Tb, const VEC3& Tc, VEC3& Inter)
{
typedef typename VEC3::DATA_TYPE T ;
VEC3 u = Ta - P ;
VEC3 v = Tb - P ;
VEC3 w = Tc - P ;
T x = tripleProduct(Dir, u, v) ;
T y = tripleProduct(Dir, v, w) ;
T z = tripleProduct(Dir, w, u) ;
unsigned int np=0;
unsigned int nn=0;
unsigned int nz=0;
if (x>T(0))
++np;
else
if (x<T(0))
++nn;
else ++nz;
if (y>T(0))
++np;
else
if (y<T(0))
++nn;
else ++nz;
if (z>T(0))
++np;
else
if (z<T(0))
++nn;
else ++nz;
if ((np !=0) && (nn!=0))
return NO_INTERSECTION;
T sum = x + y + z ;
T alpha = y / sum ;
T beta = z / sum ;
T gamma = T(1) - alpha - beta ;
Inter = Ta * alpha + Tb * beta + Tc * gamma ;
return Intersection(FACE_INTERSECTION-nz);
// switch(nz)
// {
// case 0:
// {
// T sum = x + y + z ;
// T alpha = y / sum ;
// T beta = z / sum ;
// T gamma = T(1) - alpha - beta ;
// Inter = Ta * alpha + Tb * beta + Tc * gamma ;
// return FACE_INTERSECTION ;
// }
// break;
// case 1:
// return EDGE_INTERSECTION;
// break;
// case 2:
// return VERTEX_INTERSECTION;
// break;
// default:
// return NO_INTERSECTION;
// break;
// }
// // just for no warning compilation
// return NO_INTERSECTION;
}
template <typename VEC3>
Intersection intersectionRayTriangleOpt(const VEC3& P, const VEC3& Dir, const VEC3& Ta, const VEC3& Tb, const VEC3& Tc)
{
typedef typename VEC3::DATA_TYPE T ;
VEC3 u = Ta - P ;
VEC3 v = Tb - P ;
VEC3 w = Tc - P ;
T x = tripleProduct(Dir, u, v) ;
T y = tripleProduct(Dir, v, w) ;
T z = tripleProduct(Dir, w, u) ;
unsigned int np=0;
unsigned int nn=0;
unsigned int nz=0;
if (x>T(0))
++np;
else
if (x<T(0))
++nn;
else ++nz;
if (y>T(0))
++np;
else
if (y<T(0))
++nn;
else ++nz;
if (z>T(0))
++np;
else
if (z<T(0))