2009-05-18 16:10:59 +02:00
|
|
|
/****************************************************************************
|
|
|
|
* MeshLab o o *
|
|
|
|
* An extendible mesh processor o o *
|
|
|
|
* _ O _ *
|
|
|
|
* Copyright(C) 2005, 2009 \/)\/ *
|
|
|
|
* 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. *
|
|
|
|
* *
|
2018-05-14 20:01:43 +02:00
|
|
|
****************************************************************************/
|
|
|
|
|
|
|
|
#ifndef __GLWRAPTETRA__
|
|
|
|
#define __GLWRAPTETRA__
|
|
|
|
#include <GL/glew.h>
|
|
|
|
#include <GL/GL.h>
|
|
|
|
#include <vcg/space/color4.h>
|
|
|
|
#include <vcg/space/tetra3.h>
|
|
|
|
#include <wrap/gui/view.h>
|
|
|
|
#include <wrap/gl/space.h>
|
|
|
|
#include <wrap/gl/math.h>
|
|
|
|
|
|
|
|
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,CMPerTetra,CMPerVertexF,CMPerVertex};
|
|
|
|
enum Hint {HShrinkFactor};
|
|
|
|
};
|
|
|
|
|
2018-05-25 11:25:00 +02:00
|
|
|
template <typename MeshType>
|
2018-05-14 20:01:43 +02:00
|
|
|
class GlTetramesh:public GLW{
|
|
|
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
2018-05-25 11:25:00 +02:00
|
|
|
typedef typename MeshType::TetraType TetraType;
|
|
|
|
typedef typename TetraType::VertexType VertexType;
|
2018-05-14 20:01:43 +02:00
|
|
|
typedef typename VertexType::ScalarType ScalarType;
|
2018-05-25 11:25:00 +02:00
|
|
|
typedef typename VertexType::CoordType CoordType;
|
2018-05-14 20:01:43 +02:00
|
|
|
|
|
|
|
//subclass for clipping planes
|
|
|
|
class ClipPlane
|
|
|
|
{
|
|
|
|
private:
|
2018-05-25 11:25:00 +02:00
|
|
|
|
|
|
|
CoordType D, D0;
|
|
|
|
ScalarType dist;
|
|
|
|
|
2018-05-14 20:01:43 +02:00
|
|
|
GLdouble eqn[4];
|
|
|
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
bool active;
|
|
|
|
|
|
|
|
ClipPlane (){active=false;}
|
|
|
|
|
|
|
|
~ClipPlane (){}
|
|
|
|
|
2018-05-25 11:25:00 +02:00
|
|
|
ClipPlane(CoordType & p0, CoordType & p1, CoordType & p2)
|
2018-05-14 20:01:43 +02:00
|
|
|
{
|
2018-05-25 11:25:00 +02:00
|
|
|
CoordType N = ((p1-p0)^(p2-p0)).Normalize();
|
2018-05-14 20:01:43 +02:00
|
|
|
|
2018-05-25 11:25:00 +02:00
|
|
|
D = N;
|
|
|
|
D0 = D;
|
|
|
|
|
|
|
|
dist = vcg::Norm((p0 + p1 + p2) / 3.f);
|
2018-05-14 20:01:43 +02:00
|
|
|
}
|
2018-05-25 11:25:00 +02:00
|
|
|
|
2018-05-14 20:01:43 +02:00
|
|
|
//set normal of the clipping plane
|
2018-05-25 11:25:00 +02:00
|
|
|
void SetD(CoordType d)
|
2018-05-14 20:01:43 +02:00
|
|
|
{
|
2018-05-25 11:25:00 +02:00
|
|
|
D = d;
|
|
|
|
D0 = d;
|
2018-05-14 20:01:43 +02:00
|
|
|
}
|
|
|
|
//set the point of the clipping plane
|
2018-05-25 11:25:00 +02:00
|
|
|
void SetDist(ScalarType d)
|
2018-05-14 20:01:43 +02:00
|
|
|
{
|
2018-05-25 11:25:00 +02:00
|
|
|
dist = d;
|
2018-05-14 20:01:43 +02:00
|
|
|
}
|
2018-05-25 11:25:00 +02:00
|
|
|
bool IsClipped(CoordType p)
|
2018-05-14 20:01:43 +02:00
|
|
|
{
|
2018-05-25 11:25:00 +02:00
|
|
|
return D.V(0) * p.X() + D.V(1) * p.Y() + D.V(2) * p.Z() - dist > 0;
|
2018-05-14 20:01:43 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
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()
|
|
|
|
{
|
2018-05-25 11:25:00 +02:00
|
|
|
const ScalarType w = 50;
|
|
|
|
glColor4f(1., 1., 0., 0.3);
|
|
|
|
glEnable(GL_BLEND);
|
|
|
|
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
|
|
|
glDisable(GL_LIGHTING);
|
2018-05-14 20:01:43 +02:00
|
|
|
|
2018-05-25 11:25:00 +02:00
|
|
|
glBegin(GL_LINES);
|
|
|
|
glVertex3f(0, 0, 0);
|
|
|
|
glVertex3f(dist, 0, 0);
|
|
|
|
glEnd();
|
|
|
|
glBegin(GL_TRIANGLES);
|
|
|
|
glVertex3f(dist, -w, w);
|
|
|
|
glVertex3f(dist, w, w);
|
|
|
|
glVertex3f(dist, -w, -w);
|
|
|
|
glVertex3f(dist, w, w);
|
|
|
|
glVertex3f(dist, w, -w);
|
|
|
|
glVertex3f(dist, -w, -w);
|
2018-05-14 20:01:43 +02:00
|
|
|
glEnd();
|
|
|
|
|
2018-05-25 11:25:00 +02:00
|
|
|
glDisable(GL_BLEND);
|
|
|
|
glEnable(GL_LIGHTING);
|
2018-05-14 20:01:43 +02:00
|
|
|
}
|
|
|
|
|
2018-05-25 11:25:00 +02:00
|
|
|
void Transform(vcg::Matrix44<float> & tr)
|
2018-05-14 20:01:43 +02:00
|
|
|
{
|
2018-05-25 11:25:00 +02:00
|
|
|
D = (tr * D0).Normalize();
|
2018-05-14 20:01:43 +02:00
|
|
|
}
|
|
|
|
|
2018-05-25 11:25:00 +02:00
|
|
|
void offsetDist(ScalarType off)
|
2018-05-14 20:01:43 +02:00
|
|
|
{
|
2018-05-25 11:25:00 +02:00
|
|
|
dist = (off < -dist) ? 0.001f : dist + off;
|
2018-05-14 20:01:43 +02:00
|
|
|
}
|
|
|
|
|
2018-05-25 11:25:00 +02:00
|
|
|
bool IsActive()
|
|
|
|
{
|
|
|
|
return active;
|
|
|
|
}
|
2018-05-14 20:01:43 +02:00
|
|
|
|
2018-05-25 11:25:00 +02:00
|
|
|
bool switchActive()
|
|
|
|
{
|
|
|
|
return active ^= true;
|
|
|
|
}
|
2018-05-14 20:01:43 +02:00
|
|
|
};
|
|
|
|
|
2018-05-25 11:25:00 +02:00
|
|
|
GlTetramesh(MeshType * m) : _m(m){}
|
2018-05-14 20:01:43 +02:00
|
|
|
GlTetramesh( ) {}
|
|
|
|
|
2018-05-25 11:25:00 +02:00
|
|
|
MeshType * _m;
|
2018-05-14 20:01:43 +02:00
|
|
|
ClipPlane section;
|
|
|
|
|
|
|
|
private:
|
2018-05-25 11:25:00 +02:00
|
|
|
ScalarType shrink_factor = 0.98f;
|
2018-05-14 20:01:43 +02:00
|
|
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
|
|
|
void SetHint(Hint h, double value){
|
|
|
|
switch(h){
|
|
|
|
case HShrinkFactor: shrink_factor = value; break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-05-25 11:25:00 +02:00
|
|
|
void AddClipSection(CoordType p0, CoordType p1, CoordType p2)
|
2018-05-14 20:01:43 +02:00
|
|
|
{
|
|
|
|
section=ClipPlane(p0,p1,p2);
|
|
|
|
section.active=true;
|
|
|
|
}
|
|
|
|
|
|
|
|
void ClearClipSection()
|
|
|
|
{
|
|
|
|
section.active=false;
|
|
|
|
}
|
|
|
|
|
|
|
|
template <DrawMode dm,NormalMode nm,ColorMode cm >
|
|
|
|
void Draw(){
|
|
|
|
switch (dm){
|
|
|
|
case DMNone: break;
|
2018-05-25 11:25:00 +02:00
|
|
|
case DMSmallTetra: _DrawSmallTetra<cm>();break;
|
|
|
|
case DMFlat: _DrawSurface<dm,nm,cm>();break;
|
|
|
|
case DMWire: _DrawSurface<dm,nm,cm>();break;
|
|
|
|
case DMHidden: _DrawSurface<dm,nm,cm>();break;
|
|
|
|
case DMFlatWire: _DrawFlatWire<nm,cm>(); break;
|
|
|
|
case DMTransparent: break;
|
2018-05-14 20:01:43 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
template <ColorMode cm >
|
|
|
|
void _DrawSmallTetra(){
|
2018-05-25 11:25:00 +02:00
|
|
|
|
|
|
|
glEnable(GL_LIGHT0);
|
|
|
|
glEnable(GL_LIGHTING);
|
2018-05-25 11:58:32 +02:00
|
|
|
ForEachTetra(*_m, [&] (TetraType & t) {
|
2018-05-25 11:25:00 +02:00
|
|
|
if (!t.IsD())
|
2018-05-14 20:01:43 +02:00
|
|
|
{
|
2018-05-25 11:25:00 +02:00
|
|
|
if (!t.IsS()) //draw as normal
|
|
|
|
_DrawSmallTetra<cm>(t);
|
|
|
|
else //draw in selected mode
|
|
|
|
_DrawSelectedTetra(t);
|
2018-05-14 20:01:43 +02:00
|
|
|
}
|
2018-05-25 11:25:00 +02:00
|
|
|
});
|
2018-05-14 20:01:43 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
template <NormalMode nm,ColorMode cm >
|
2018-05-25 11:25:00 +02:00
|
|
|
void _DrawFlatWire(){
|
2018-05-14 20:01:43 +02:00
|
|
|
glPushAttrib(0xffff);
|
|
|
|
glEnable(GL_COLOR_MATERIAL);
|
|
|
|
glEnable(GL_DEPTH);
|
|
|
|
glDepthRange(0.001,1.0);
|
|
|
|
Draw<DMFlat,nm,cm>();
|
|
|
|
glDisable(GL_LIGHTING);
|
|
|
|
glColor3f(0.0,0.0,0.0);
|
|
|
|
glDepthRange(0.0,0.999);
|
|
|
|
Draw<DMHidden,nm,cm>();
|
|
|
|
glPopAttrib();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
template <DrawMode dm,NormalMode nm,ColorMode cm >
|
|
|
|
void _DrawSurface(){
|
2018-05-25 11:25:00 +02:00
|
|
|
|
2018-05-14 20:01:43 +02:00
|
|
|
|
|
|
|
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_LIGHT0);
|
|
|
|
glEnable(GL_LIGHTING);
|
|
|
|
glEnable(GL_NORMALIZE);
|
|
|
|
glPolygonMode(GL_FRONT,GL_FILL);
|
|
|
|
}
|
2018-05-25 11:25:00 +02:00
|
|
|
|
2018-05-25 11:58:32 +02:00
|
|
|
ForEachTetra(*_m, [&] (TetraType & t) {
|
2018-05-25 11:25:00 +02:00
|
|
|
_DrawTetra<dm,nm,cm>(t);
|
|
|
|
});
|
|
|
|
|
2018-05-14 20:01:43 +02:00
|
|
|
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 <DrawMode dm,NormalMode nm,ColorMode cm >
|
|
|
|
void _DrawTetra(TetraType &t)
|
|
|
|
{
|
|
|
|
if((!t.IsD())&&(!t.IsS()))
|
|
|
|
{
|
|
|
|
if ((dm!=DMWire)&&(dm!=DMHidden))
|
|
|
|
_ChooseColorTetra<cm>(t);
|
|
|
|
for(int i = 0; i < 4; ++i){
|
|
|
|
if (dm == DMWire)
|
|
|
|
_DrawFace<cm>(t,i);
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (t.IsBorderF(i))
|
|
|
|
{
|
|
|
|
if(nm==NMSmooth)
|
|
|
|
_DrawFaceSmooth<cm>(t,i);
|
|
|
|
else
|
|
|
|
if(nm==NMFlat)
|
|
|
|
_DrawFace<cm>(t,i);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
if((!t.IsD())&&(t.IsS()))
|
|
|
|
_DrawSelectedTetra(t);
|
|
|
|
}
|
|
|
|
|
|
|
|
template <ColorMode cm >
|
|
|
|
void _ChooseColorTetra(TetraType &t)
|
|
|
|
{
|
|
|
|
if (cm==CMNone)
|
|
|
|
{
|
|
|
|
if (t.IsS())
|
|
|
|
glColor3d(1,0,0);
|
|
|
|
else
|
|
|
|
glColor3d(0.8f,0.8f,0.8f);
|
|
|
|
}
|
|
|
|
if (cm == CMPerTetra)
|
|
|
|
vcg::glColor(t.C());
|
2018-05-25 11:25:00 +02:00
|
|
|
// 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);
|
|
|
|
// }
|
2018-05-14 20:01:43 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
template <ColorMode cm >
|
|
|
|
void _ChooseColorVertex(VertexType &v)
|
|
|
|
{
|
|
|
|
if (cm!=CMNone)
|
|
|
|
{
|
2018-05-25 11:25:00 +02:00
|
|
|
// 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)
|
|
|
|
vcg::glColor(v.C());
|
2018-05-14 20:01:43 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
template <ColorMode cm >
|
|
|
|
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<cm>(*v0);
|
|
|
|
glNormal(v0->N());
|
|
|
|
glVertex(v0->P());
|
|
|
|
_ChooseColorVertex<cm>(*v1);
|
|
|
|
glNormal(v1->N());
|
|
|
|
glVertex(v1->P());
|
|
|
|
_ChooseColorVertex<cm>(*v2);
|
|
|
|
glNormal(v2->N());
|
|
|
|
glVertex(v2->P());
|
|
|
|
glEnd();
|
|
|
|
}
|
|
|
|
|
|
|
|
template < ColorMode cm >
|
|
|
|
void _DrawFace(TetraType &t,int face)
|
|
|
|
{
|
|
|
|
glBegin(GL_TRIANGLES);
|
|
|
|
VertexType *v0=t.V(Tetra::VofF(face,0));
|
|
|
|
VertexType *v1=t.V(Tetra::VofF(face,1));
|
|
|
|
VertexType *v2=t.V(Tetra::VofF(face,2));
|
|
|
|
glNormal(vcg::Normal(v0->P(), v1->P(), v2->P()).normalized());
|
|
|
|
_ChooseColorVertex<cm>(*v0);
|
|
|
|
glVertex(v0->P());
|
|
|
|
_ChooseColorVertex<cm>(*v1);
|
|
|
|
glVertex(v1->P());
|
|
|
|
_ChooseColorVertex<cm>(*v2);
|
|
|
|
glVertex(v2->P());
|
|
|
|
glEnd();
|
|
|
|
}
|
|
|
|
|
|
|
|
template < ColorMode cm >
|
|
|
|
void _DrawSmallTetra(TetraType &t)
|
|
|
|
{
|
2018-05-25 11:25:00 +02:00
|
|
|
CoordType p[4], br;
|
2018-05-14 20:01:43 +02:00
|
|
|
br = Tetra::Barycenter(t);
|
2018-05-25 11:25:00 +02:00
|
|
|
|
|
|
|
if (section.active)
|
2018-05-14 20:01:43 +02:00
|
|
|
{
|
2018-05-25 11:25:00 +02:00
|
|
|
if (section.IsClipped(br))
|
|
|
|
return;
|
|
|
|
bool border = false;
|
|
|
|
bool clipBorder = false;
|
|
|
|
for (int i = 0; i < 4; ++i)
|
|
|
|
{
|
|
|
|
border = border || t.IsB(i);
|
2018-05-14 20:01:43 +02:00
|
|
|
|
2018-05-25 11:25:00 +02:00
|
|
|
CoordType br1 = Tetra::Barycenter(*t.TTp(i));
|
|
|
|
clipBorder = clipBorder || section.IsClipped(br1);
|
|
|
|
}
|
2018-05-14 20:01:43 +02:00
|
|
|
|
2018-05-25 11:25:00 +02:00
|
|
|
if (!border && !clipBorder)
|
|
|
|
return;
|
|
|
|
}
|
2018-05-14 20:01:43 +02:00
|
|
|
|
|
|
|
for(int i = 0; i < 4; ++i)
|
2018-05-25 11:25:00 +02:00
|
|
|
// p[i] = t.V(i)->P();
|
2018-05-14 20:01:43 +02:00
|
|
|
p[i] = t.V(i)->P() * shrink_factor + br * (1 - shrink_factor);
|
|
|
|
|
|
|
|
|
|
|
|
_ChooseColorTetra<cm>(t);
|
|
|
|
|
|
|
|
glBegin(GL_TRIANGLES);
|
|
|
|
for(int i = 0; i < 4; ++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));
|
|
|
|
|
|
|
|
|
|
|
|
glNormal(vcg::Normal(v0->P(), v1->P(), v2->P()).normalized());
|
|
|
|
|
|
|
|
_ChooseColorVertex<cm>(*v0);
|
|
|
|
glVertex(p[Tetra::VofF(i,0)]);
|
|
|
|
_ChooseColorVertex<cm>(*v1);
|
|
|
|
glVertex(p[Tetra::VofF(i,1)]);
|
|
|
|
_ChooseColorVertex<cm>(*v2);
|
|
|
|
glVertex(p[Tetra::VofF(i,2)]);
|
|
|
|
}
|
|
|
|
glEnd();
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
} // end namespace tetra
|
|
|
|
} // end nemaspace tri
|
|
|
|
#endif
|