Commit f547dc86 authored by Pierre Kraemer's avatar Pierre Kraemer

Merge cgogn:~cazier/CGoGN

Conflicts:
	include/Topology/map/embeddedMap2.h
	include/Topology/map/map1.hpp
	include/Topology/map/map2.h
	src/Topology/map/embeddedMap2.cpp
	src/Topology/map/embeddedMap3.cpp
	src/Topology/map/map2.cpp
	src/Topology/map/map3.cpp
parents e9112574 f64adf62
......@@ -72,4 +72,3 @@ QT4_WRAP_CPP( clipping_moc ../clipping.h )
add_executable( clippingD ../clipping.cpp ${clipping_ui} ${clipping_moc})
target_link_libraries( clippingD
${CGoGN_LIBS_D} ${CGoGN_EXT_LIBS} )
......@@ -64,4 +64,3 @@ QT4_WRAP_CPP( clipping_moc ../clipping.h )
add_executable( clipping ../clipping.cpp ${clipping_ui} ${clipping_moc})
target_link_libraries( clipping
${CGoGN_LIBS_R} ${CGoGN_EXT_LIBS} )
/*******************************************************************************
* 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 *
* *
*******************************************************************************/
#include "tutoriel.h"
#include "Topology/generic/parameters.h"
#include "Topology/map/embeddedMap2.h"
#include "Geometry/vector_gen.h"
#include "Geometry/matrix.h"
#include "Algo/Render/GL2/mapRender.h"
#include "Algo/Render/GL2/topoRender.h"
#include "Algo/Geometry/normal.h"
#include "Algo/Selection/raySelector.h"
#include "Algo/Import/import.h"
#include "Algo/Geometry/boundingbox.h"
#include "Utils/Shaders/shaderSimpleColor.h"
#include "Utils/Shaders/shaderPhong.h"
#include "Utils/drawer.h"
// pour simplifier l'ecriture du code
using namespace CGoGN;
// déclaration de la classe utilisée pour le TP
class Map2TP;
// definition de la structure qui decrit le type de carte utilise
struct PFP: public PFP_STANDARD
{
// definition of the map
typedef Map2TP MAP;
};
// fonction qui renvoit vrai (pour sélectioner tous les brins)
SelectorTrue allDarts;
// typedef pour le plongement des sommets
typedef PFP::VEC3 Point3D;
// Variables pour la gestion des plongements
// handler d'attribut de position par sommet
AttributeHandler<Point3D> position;
// handler d'attribut de normale par sommet
AttributeHandler<PFP::VEC3> normal;
/// Fonctions a connaitre:
///
/// phi1(d), phi2(d) : les parcours topologiques
///
/// Creer un face: newOrientedFace(nb_cotes); renvoit un Dart
///
/// Creer un plongement de sommet :
/// Point3D P = Point3D(0.0f,0.0f,0.0f);
///
/// Lire le plongement d'un sommet (celui du brin d)
/// P = position[d];
///
/// Assigner un plongement à un sommet (celui du brin d)
/// embedVertex(d,P);
class Map2TP : public Map2
{
private:
// 3 brins de la carte
Dart d_carre;
Dart d_tri;
Dart d_multiFaces;
// Assigne un nouveau plongement au sommet. Les anciens plongements sont libérés.
void newVertex(Dart d) {
embedNewCell(VERTEX,d);
}
public:
// Fonction Carre: construit un carre et renvoit un brin
Dart Carre()
{
Point3D P[4];
P[0] = Point3D(0.0f,0.0f,0.0f);
P[1] = Point3D(1.0f,0.0f,0.0f);
P[2] = Point3D(1.0f,1.0f,0.0f);
P[3] = Point3D(0.0f,1.0f,0.0f);
Dart d0 = newOrientedFace(4);
position[d0] = P[0];
Dart d1 = phi1(d0);
position[d1] = P[1];
Dart d2 = phi1(d1);
position[d2] = P[2];
Dart d3 = phi1(d2);
position[d3] = P[3];
return d0;
}
// Fonction Triangle: construit un triangle et renvoit un brin
Dart Triangle()
{
Point3D P[3];
P[0] = Point3D(0.0f,1.1f,0.0f);
P[1] = Point3D(1.0f,1.1f,0.0f);
P[2] = Point3D(0.5f,2.0f,0.0f);
Dart d0 = newOrientedFace(3);
position[d0] = P[0];
Dart d1 = phi1(d0);
position[d1] = P[1];
Dart d2 = phi1(d1);
position[d2] = P[2];
return d0;
}
// Construit un polygone de taille "size"
Dart Polygone(Point3D* P, unsigned size)
{
Dart d = newOrientedFace(size);
for (unsigned i=0; i<size; i++) {
position[d] = P[i];
d = phi1(d);
}
return d;
}
// appel clavier touche 'c'
void Colle(Dart d, Dart e)
{
Point3D p = position[d];
Point3D q = position[phi1(d)];
phi2sew(d,e);
newVertex(d);
position[d] = p;
newVertex(e);
position[e] = q;
}
// appel clavier touche 'm'
void ColleMilieu(Dart d, Dart e)
{
Point3D p1 = position[d];
Point3D p2 = position[phi1(d)];
Point3D q1 = position[e];
Point3D q2 = position[phi1(e)];
Point3D m1 = (p1+q2)/2;
Point3D m2 = (q1+p2)/2;;
phi2sew(d,e);
newVertex(d);
position[d] = m1;
newVertex(e);
position[e] = m2;
}
// Construit une figure
Dart MultiFaces()
{
Point3D P[6];
P[0] = Point3D(2.0f,0.0f,0.0f);
P[1] = Point3D(3.0f,0.0f,0.0f);
P[2] = Point3D(3.5f,1.0f,0.0f);
P[3] = Point3D(3.0f,1.8f,0.0f);
P[4] = Point3D(2.0f,1.8f,0.0f);
P[5] = Point3D(1.5f,1.0f,0.0f);
Dart hexa = Polygone(P,6);
Point3D Q[3];
Q[0] = Point3D(2.0f,2.0f,0.0f);
Q[1] = Point3D(3.0f,2.0f,0.0f);
Q[2] = Point3D(2.5f,3.0f,0.0f);
Dart triangle = Polygone(Q,3);
Point3D R[4];
R[0] = Point3D(4.0f,0.0f,0.0f);
R[1] = Point3D(5.0f,0.0f,0.0f);
R[2] = Point3D(5.0f,1.0f,0.0f);
R[3] = Point3D(4.0f,1.0f,0.0f);
Dart carre = Polygone(R,4);
Point3D S[3];
S[0] = Point3D(4.0f,1.2f,0.0f);
S[1] = Point3D(5.0f,1.2f,0.0f);
S[2] = Point3D(4.5f,2.2f,0.0f);
Dart triangle2 = Polygone(S,3);
Dart haut_carre = phi1(phi1(carre));
Dart hexa2 = phi1(phi1(phi1(hexa)));
// Test du phi1Sew
// myMap.phi1sew(hexa,hexa2);
// myMap.phi1sew(myMap.phi1(hexa),myMap.phi_1(carre));
// Génére un maillage à la fin
Colle(haut_carre,triangle2);
Colle(hexa2,triangle);
Colle(phi_1(triangle2),phi_1(hexa2));
Colle(phi1(hexa),phi_1(carre));
return hexa;
}
// Fonction de creation de la carte (appelee par le main)
void createMap()
{
d_carre = Carre();
d_tri = Triangle();
d_multiFaces = MultiFaces();
Colle(phi1(phi1(d_carre)),d_tri);
Colle(phi_1(d_multiFaces),phi1(d_carre));
Colle(phi_1(phi_1(d_multiFaces)),phi1(d_tri));
}
// Touche x
void coupeFace(Dart d, Dart e)
{
Point3D p = position[phi1(d)];
Point3D q = position[phi1(e)];
Dart dd = newOrientedFace(2);
Dart ee = phi1(dd);
phi1sew(d,dd);
phi1sew(e,ee);
phi2sew(dd,ee);
newVertex(ee);
position[ee] = p;
newVertex(dd);
position[dd] = q;
}
// Touche y
void coupeArete(Dart d) {
Point3D p = position[d];
Point3D q = position[phi1(d)];
Point3D milieu = (p + q + Point3D(0.2f,0.2f,0.0f) /* decalage pour voir le point */ )/2;
Dart dd = newDart();
phi1sew(d,dd);
Dart e = phi2(d);
if (e != d) {
Dart ee = newDart();
phi1sew(e,ee);
phi2unsew(d);
phi2sew(d,ee);
phi2sew(e,dd);
}
newVertex(dd);
position[dd] = milieu;
}
// Touche z
void arrondi(Dart d) {
Dart e = phi_1(d);
coupeArete(d);
coupeArete(e);
e = phi1(e);
Point3D P = position[d];
Point3D Q = position[e];
Point3D R = position[phi1(d)];
Point3D M = (P + P + Q + R)/4;
position[d] = M;
}
unsigned face_size(Dart d) {
unsigned n = 0;
Dart e = d;
do {
n++;
e = phi1(e);
} while (e != d);
return n;
}
// Touche p
void triangule() {
Dart d;
for (d = begin(); d != end();) {
if (face_size(d) > 3) {
coupeFace(d,phi1(phi1(d)));
}
else {
next(d);
}
}
}
// Touche q
void fusionSommet(Dart d)
{
Point3D P = position[d];
Point3D Q = position[phi1(d)];
Point3D M = (P + Q)/2;
// On attrape des pointeurs sur les brins à manipuler
Dart dd = phi1(d);
Dart ddd = phi1(dd);
Dart e = phi2(d);
Dart ee = phi1(e);
Dart eee = phi1(ee);
Dart dd2 = phi2(dd);
Dart ee2 = phi2(ee);
Dart ddd2 = phi2(ddd);
Dart eee2 = phi2(eee);
// On découd les triangles du centre
phi2unsew(d);
phi2unsew(dd);
phi2unsew(ee);
phi2unsew(ddd);
phi2unsew(eee);
// On détruit les 2 triangles
deleteOrientedFace(d);
deleteOrientedFace(e);
// On recout les brins restants
phi2sew(dd2,ddd2);
phi2sew(ee2,eee2);
// On plonge le sommet central sur le nouveau point calculé
newVertex(ddd2);
position[ddd2] = M;
}
// Longueur d'une arête
double longueur(Dart d)
{
Point3D P = position[d];
Point3D Q = position[phi1(d)];
Point3D V = P-Q;
return V.norm();
}
// Simplification touche k
void simplifie()
{
Dart dmin = begin();
double lmin = longueur(dmin);
Dart d;
for (d = begin(); d != end(); next(d)) {
if (longueur(d) < lmin) {
dmin = d;
lmin = longueur(d);
}
}
fusionSommet(dmin);
}
};
// definition de la carte comme variable globale
PFP::MAP myMap;
// pile des brins selectionnes (6 max)
std::vector<Dart> selected_darts;
// Variables pour le picking (sélection de brins à la souris)
PFP::VEC3 rayA;
PFP::VEC3 rayB;
std::vector<PFP::VEC3> inters;
std::vector<Dart> d_faces;
std::vector<Dart> d_edges;
std::vector<Dart> d_vertices;
void MyQT::drawSelected()
{
typedef Dart Dart;
// FACES
m_ds->newList(GL_COMPILE_AND_EXECUTE);
m_ds->lineWidth(5.0f);
for(unsigned int i=0; i < d_faces.size(); ++i)
{
m_ds->begin(GL_POLYGON);
// fait varier la couleur du plus pres au plus loin
float c = float (i) / float (d_faces.size());
m_ds->color3f(1.0f - c , 0.0f, c);
Dart d = d_faces[i];
do
{
const PFP::VEC3& P = position[d];
m_ds->vertex(P);
d = myMap.phi1(d);
} while (d!=d_faces[i]);
m_ds->end();
}
//edges
m_ds->begin(GL_LINES);
m_ds->lineWidth(5.0f);
for(unsigned int i=0; i < d_edges.size(); ++i)
{
// fait varier la couleur du plus pres au plus loin
float c = float (i) / float (d_edges.size());
m_ds->color3f(1.0f - c , c ,0.);
Dart d = d_edges[i];
const PFP::VEC3& P = position[d];
m_ds->vertex(P);
d = myMap.phi1(d);
const PFP::VEC3& Q = position[d];
m_ds->vertex(Q);
}
m_ds->end();
//VERTICES
//edges
m_ds->pointSize(9.0f);
m_ds->begin(GL_POINTS);
for(unsigned int i=0; i < d_vertices.size(); ++i)
{
// fait varier la couleur du plus pres au plus loin
float c = float (i) / float (d_vertices.size());
m_ds->color3f(1.0f - c , 0., c);
Dart d = d_vertices[i];
const PFP::VEC3& P = position[d];
m_ds->vertex(P);
}
m_ds->end();
m_ds->endList();
for(unsigned int i=0; i < selected_darts.size(); ++i)
{
// fait varier la couleur du plus pres au plus loin
Dart d = selected_darts[i];
switch(i)
{
case 0:
m_render_topo->overdrawDart(d, 5, 1.0f,0.0f,0.0f);
break;
case 1:
m_render_topo->overdrawDart(d, 5, 0.0f,1.0f,0.0f);
break;
case 2:
m_render_topo->overdrawDart(d, 5, 0.0f,0.0f,1.0f);
break;
case 3:
m_render_topo->overdrawDart(d, 5, 1.0f,1.0f,0.0f);
break;
case 4:
m_render_topo->overdrawDart(d, 5, 1.0f,0.0f,1.0f);
break;
case 5:
m_render_topo->overdrawDart(d, 5, 0.0f,1.0f,1.0f);
break;
default:
break;
}
}
}
void MyQT::cb_initGL()
{
// choose to use GL version 2
Utils::GLSLShader::setCurrentOGLVersion(2);
// create the render
m_render = new Algo::Render::GL2::MapRender();
m_render_topo = new Algo::Render::GL2::TopoRenderMapD() ;
m_ds = new Utils::Drawer();
// create VBO for position
m_positionVBO = new Utils::VBO();
m_normalVBO = new Utils::VBO();
m_shader = new Utils::ShaderPhong();
m_shader->setAttributePosition(m_positionVBO);
m_shader->setAttributeNormal(m_normalVBO);
m_shader->setDiffuse(Geom::Vec4f(0.0f,0.6f,0.0f,0.0f));
m_shader->setSpecular(Geom::Vec4f(0.0f,0.0f,0.0f,0.0f)); // no specular
// using simple shader with color
m_shader2 = new Utils::ShaderSimpleColor();
m_shader2->setAttributePosition(m_positionVBO);
m_shader2->setColor(Geom::Vec4f(0.0f,0.1f,0.0f,0.0f));
registerShader(m_shader);
registerShader(m_shader2);
}
void MyQT::cb_redraw()
{
// update des normales aux sommets
Algo::Geometry::computeNormalVertices<PFP>(myMap, position, normal) ;
// update du VBO position (contexte GL necessaire)
m_positionVBO->updateData(position);
m_normalVBO->updateData(normal);
// update des primitives du renderer
m_render->initPrimitives<PFP>(myMap, allDarts, Algo::Render::GL2::TRIANGLES);
m_render->initPrimitives<PFP>(myMap, allDarts, Algo::Render::GL2::LINES);
m_render_topo->updateData<PFP>(myMap, position, 0.9f, 0.9f);
drawSelected();
if (renderTopo)
{
glEnable( GL_POLYGON_OFFSET_FILL );
glPolygonOffset( 1.0f, 1.0f );
m_render_topo->drawTopo();
}
glEnable( GL_POLYGON_OFFSET_FILL );
glPolygonOffset( 1.5f, 1.5f );
glPolygonOffset( 2.0f, 2.0f );
glLineWidth(1.0f);
m_render->draw(m_shader2,Algo::Render::GL2::LINES) ;
/// Rendu faces pleines
glEnable(GL_CULL_FACE);
glFrontFace(GL_CCW);
glPolygonMode(GL_FRONT,GL_FILL);
glPolygonMode(GL_BACK,GL_NONE);
m_render->draw(m_shader,Algo::Render::GL2::TRIANGLES) ;
glDisable( GL_POLYGON_OFFSET_FILL );
}
void MyQT::cb_keyPress(int keycode)
{
// coordonnées du clic et calcul du rayon dans l'espace 3D
int x,y;
glMousePosition(x,y);
float dist = getOrthoScreenRay(x,y,rayA,rayB);
PFP::VEC3 AB = rayB-rayA;
// tableau de brins pour la sélection
std::vector<Dart> darts;
switch(keycode)
{
// Bascule affichage topologie - normal
case 't':
renderTopo = !renderTopo;
break;
// Oublie les brins sélectionnés
case '0':
selected_darts.clear();
break;
// Sélectionne un brin
case 'd':
Algo::Selection::dartsRaySelection<PFP>(myMap, position, rayA, AB, darts, SelectorTrue());
if (!darts.empty() && selected_darts.size() < 6)
{
selected_darts.push_back(darts[0]);
}
break;
// Affiche les informations sur un brin
case 'D':
Algo::Selection::dartsRaySelection<PFP>(myMap, position, rayA, AB, darts, SelectorTrue());
if (!darts.empty())
{
std::stringstream ss;
Dart d1 = myMap.phi1(darts[0]);
Dart d2 = myMap.phi2(darts[0]);
ss << "dart:" << darts[0].index<<" /phi1:"<< d1.index<<" /phi2:"<< d2.index;
const Point3D& P = position[darts[0]];
ss << " /Emb:" << P;
statusMsg(ss.str().c_str());
}
break;
// Sélectionne des faces
case 'f':
d_faces.clear();
Algo::Selection:: facesRaySelection<PFP>(myMap, position, SelectorTrue(), rayA, AB, d_faces);