Commit c5958723 authored by Sylvain Thery's avatar Sylvain Thery

ajout rendu face concave par methode des oreilles

parent 85fd18da
......@@ -89,6 +89,129 @@ protected:
typedef std::pair<GLuint*, unsigned int> buffer_array;
class VertexPoly
{
public:
int id;
float value;
VertexPoly* prev;
VertexPoly* next;
VertexPoly* store_link;
VertexPoly(int i, float v, VertexPoly* p=NULL): id(i),value(v), prev(p), next(NULL),store_link(NULL)
{
if (prev!=NULL)
{
prev->next = this;
prev->store_link = this;
}
}
static void close(VertexPoly* first, VertexPoly* last)
{
last->next = first;
last->store_link = first;
first->prev = last;
}
VertexPoly* unlink()
{
this->prev->next = this->next;
this->next->prev = this->prev;
this->value = 20.0f;
return this->prev;
}
static void erasePoly(VertexPoly* vp)
{
VertexPoly* curr = vp;
do
{
VertexPoly* tmp = curr;
curr = curr->store_link;
delete tmp;
}while (curr != vp);
}
};
// struct VertexPoly
// {
// int id;
// float value;
// unsigned int prev;
// unsigned int next;
// VertexPoly(int i, float v): id(i),value(v) {}
// };
//
// class Polygon
// {
// protected:
// std::vector<VertexPoly> m_vertices;
// public:
// Polygon()
// {
// m_vertices.reserve(256);
// }
//
// inline void addVertex(int id, float val)
// {
// m_vertices.push_back(VertexPoly(id,val));
// }
//
// inline void link_all()
// {
// unsigned int sz = m_vertices.size()-1;
// for (unsigned int i = 1; i<sz; ++i)
// {
// m_vertices[i].next = i+1;
// m_vertices[i].prev = i-1;
// }
// m_vertices[0].next = 1;
// m_vertices[0].prev = m_vertices.size();
// m_vertices[sz].next = 0;
// m_vertices[sz].prev = sz-1;
// }
//
// inline void unlink(unsigned int v)
// {
// m_vertices[ m_vertices[v].prev].next = m_vertices[v].next;
// m_vertices[ m_vertices[v].next].prev = m_vertices[v].prev;
// }
//
// inline const VertexPoly& prev(unsigned int v) const
// {
// return m_vertices[m_vertices[v].prev];
// }
//
// inline const VertexPoly& next(unsigned int v) const
// {
// return m_vertices[m_vertices[v].next];
// }
//
// inline unsigned int prevId(unsigned int v) const
// {
// return m_vertices[v].prev;
// }
//
// inline unsigned int nextId(unsigned int v) const
// {
// return m_vertices[v].next;
// }
//
// inline VertexPoly& operator()(unsigned int v)
// {
// return m_vertices[v];
// }
// };
public:
/**
* Constructor
......@@ -109,6 +232,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 +241,19 @@ 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>
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, std::multimap<float, VertexPoly*>& ears, bool convex);
public:
/**
* creation of indices table of triangles (optimized order)
......@@ -162,6 +299,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,11 @@
#include "Topology/generic/cellmarker.h"
#include "Utils/vbo.h"
#include "Topology/generic/attributeHandler.h"
#include "Geometry/intersection.h"
#include "Algo/Geometry/normal.h"
#include <stdlib.h>
namespace CGoGN
{
......@@ -38,6 +43,263 @@ namespace Render
namespace GL2
{
template<typename PFP>
void MapRender::recompute2Ears( AttributeHandler<typename PFP::VEC3>& position, VertexPoly* vp, const typename PFP::VEC3& normalPoly, std::multimap<float, VertexPoly*>& 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();
// from -1 for sharp angle to 1 for flat
float dotpr1 = 1.0f - (v1*v2);
typename PFP::VEC3 nv1 = v1^v2;
float dotpr2 = 1.0f + (v1*v3);
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)
if ((!convex)&&(dotpr1 < 5.0f)&&(dotpr2 < 5.0f))
{
typename PFP::VEC3 inter;
Geom::Intersection res = Geom::intersectionRayTriangle<typename PFP::VEC3>(Td, normalPoly, Ta,Tb,Tc, inter);
if ( res >= Geom::VERTEX_INTERSECTION)
dotpr1 = 5.0f;// not an ears !
VertexPoly* curr = vnext->next;
bool finished = false;
while ((!finished) && (curr!=vprev))
{
if (curr->value >= 5.0f)
{
const typename PFP::VEC3& P = position[curr->id];
if (dotpr1 <5.0f)
{
Geom::Intersection res = Geom::intersectionRayTriangle<typename PFP::VEC3>(P, normalPoly, Ta,Tb,Tc, inter);
if (res > Geom::VERTEX_INTERSECTION)
dotpr1 = 5.0f;
}
if (dotpr2 <5.0f)
{
Geom::Intersection res = Geom::intersectionRayTriangle<typename PFP::VEC3>(P, normalPoly, Tb,Td,Ta, inter);
if (res > Geom::VERTEX_INTERSECTION)
dotpr2 = 5.0f;// not an ears !
}
finished = ((dotpr1 == 5.0f)&&(dotpr2 == 5.0f));
}
curr = curr->next;
}
if (dotpr2 <5.0f)
{
Geom::Intersection res = Geom::intersectionRayTriangle<typename PFP::VEC3>(Tc, normalPoly, Tb,Td,Ta, inter);
if ( res > Geom::VERTEX_INTERSECTION)
dotpr2 = 5.0f;// not an ears !
}
// bool finished = false;
// for (std::multimap<float, VertexPoly*>::reverse_iterator it = ears.rbegin(); (!finished)&&(it != ears.rend()) ; ++it)
// { //&&(it->first > 5.0f
// if (it->first != it ->second->value) // use only valid ears
// {
// int id = it->second->id;
// if ((id != vp->id) && (id != vp2->id))
// {
// const typename PFP::VEC3& P = position[id];
// typename PFP::VEC3 inter;
// if ((id !=vprev->id) && (dotpr1 != 5.0f))
// if (Geom::intersectionRayTriangle<typename PFP::VEC3>(P, normalPoly, Ta,Tb,Tc, inter) != Geom::NO_INTERSECTION)
// dotpr1 = 5.0f;// not an ears !
// if ((id !=vnext->id) && (dotpr2 != 5.0f))
// if (Geom::intersectionRayTriangle<typename PFP::VEC3>(P, normalPoly, Tb,Td,Ta, inter) != Geom::NO_INTERSECTION)
// dotpr2 = 5.0f;// not an ears !
// }
// }
// finished = ((dotpr1 == 5.0f)&&(dotpr2 == 5.0f));
// }
}
vp->value = dotpr1;
ears.insert(std::pair<float,VertexPoly*>(dotpr1,vp));
vp2->value = dotpr2;
ears.insert(std::pair<float,VertexPoly*>(dotpr2,vp2));
}
template<typename PFP>
float MapRender::computeEarAngle(AttributeHandler<typename PFP::VEC3>& position, const typename PFP::VEC3& normalPoly, unsigned int i, unsigned int j, unsigned int k)
{
// compute angle
typename PFP::VEC3 v1= position[i]-position[j];
typename PFP::VEC3 v2= position[k]-position[j];
v1.normalize();
v2.normalize();
float dotpr = 1.0f - (v1*v2);
typename PFP::VEC3 v3 = v1^v2;
if (v3*normalPoly > 0.0)
{
// not an ears (concave, store at the end for optimized use for intersections)
dotpr = 10.0f - dotpr;
}
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::intersectionRayTriangle<typename PFP::VEC3>(position[curr->id], normalPoly, Ta,Tb,Tc, inter);
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)
{
std::multimap< float, VertexPoly* > ears;
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
{
float val = computeEarAngle<PFP>(position,normalPoly,map.getEmbedding(VERTEX,a),map.getEmbedding(VERTEX,b),map.getEmbedding(VERTEX,c));
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;
if (convex)
{
vpp = prem;
for (unsigned int i=0; i< nbv; ++i)
{
ears.insert(std::pair< float, VertexPoly* >(vpp->value,vpp));
vpp = vpp->next;
}
}
else
{
// second pass test intersection with polygons
vpp = prem;
for (unsigned int i=0; i< nbv; ++i)
{
if (vpp->value <5.0f)
{
computeEarIntersection<PFP>(position,vpp,normalPoly);
if (vpp->value != 5.0f)
ears.insert(std::pair< float, VertexPoly* >(vpp->value,vpp));
}
else
ears.insert(std::pair< float, VertexPoly* >(vpp->value,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
std::multimap< float, VertexPoly* >::iterator be_it = ears.begin(); // best ear is big value cos -> last in map
VertexPoly* be = be_it->second;
while (be->value != be_it->first) // test ear validiy (!= means recomputed: to be destroyed)
{
ears.erase( be_it);
be_it = ears.begin();
be = be_it->second;
}
tableIndices.push_back(be->id);
tableIndices.push_back(be->next->id);
tableIndices.push_back(be->prev->id);
//remove ears
ears.erase(be_it); // from map of ears
be = be->unlink(); // and 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);
VertexPoly::erasePoly(be); // release memory of polygon
}
}
}
template<typename PFP>
inline void MapRender::addTri(typename PFP::MAP& map, Dart d, std::vector<GLuint>& tableIndices)
{
......@@ -45,6 +307,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
{
......
......@@ -103,6 +103,40 @@ void MapRender::draw(Utils::GLSLShader* sh, int prim)
sh->disableVertexAttribs();
}
unsigned int MapRender::drawSub(Utils::GLSLShader* sh, int prim, unsigned int nb_elm)
{
sh->enableVertexAttribs();
switch(prim)
{
case POINTS:
if (nb_elm > m_nbIndices[POINT_INDICES])
nb_elm = m_nbIndices[POINT_INDICES];
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_indexBuffers[POINT_INDICES]);
glDrawElements(GL_POINTS, nb_elm, GL_UNSIGNED_INT, 0) ;
break;
case LINES:
if (2*nb_elm > m_nbIndices[LINE_INDICES])
nb_elm = m_nbIndices[LINE_INDICES]/2;
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_indexBuffers[LINE_INDICES]);
glDrawElements(GL_LINES, 2*nb_elm, GL_UNSIGNED_INT, 0);
break;
case TRIANGLES:
if (3*nb_elm > m_nbIndices[TRIANGLE_INDICES])
nb_elm = m_nbIndices[TRIANGLE_INDICES]/3;
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_indexBuffers[TRIANGLE_INDICES]);
glDrawElements(GL_TRIANGLES, 3*nb_elm, GL_UNSIGNED_INT, 0);
break;
default:
break;
}
sh->disableVertexAttribs();
return nb_elm;
}
} // namespace GL2
} // namespace Render
......
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