vcglib/wrap/gl/trimesh.h

906 lines
26 KiB
C++

/****************************************************************************
* VCGLib o o *
* Visual and Computer Graphics Library o o *
* _ O _ *
* Copyright(C) 2004 \/)\/ *
* 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. *
* *
****************************************************************************/
#ifndef __VCG_GLTRIMESH
#define __VCG_GLTRIMESH
#include <queue>
#include <vector>
#include <map>
#include <algorithm>
#include <iostream>
//#include <GL/glew.h>
#include <wrap/gl/space.h>
#include <wrap/gl/math.h>
#include <vcg/space/color4.h>
namespace vcg {
template <typename T>
class GL_TYPE_NM
{public:
static GLenum SCALAR() { assert(0); return 0;}
};
template <> class GL_TYPE_NM<float>
{ public:
typedef GLfloat ScalarType;
static GLenum SCALAR() { return GL_FLOAT; }
};
template <> class GL_TYPE_NM<double>
{public:
typedef GLdouble ScalarType;
static GLenum SCALAR() { return GL_DOUBLE; }
};
//template <> GL_TYPE::SCALAR<double>() { return GL_DOUBLE; }
// classe base di glwrap usata solo per poter usare i vari drawmode, normalmode senza dover
// specificare tutto il tipo (a volte lunghissimo)
// della particolare classe glwrap usata.
class GLW
{
public:
enum DrawMode {DMNone, DMBox, DMPoints, DMWire, DMHidden, DMFlat, DMSmooth, DMFlatWire, DMRadar, DMLast} ;
enum NormalMode {NMNone, NMPerVert, NMPerFace, NMPerWedge, NMLast};
enum ColorMode {CMNone, CMPerMesh, CMPerFace, CMPerVert, CMLast};
enum TextureMode{TMNone, TMPerVert, TMPerWedge, TMPerWedgeMulti};
enum Hint {
HNUseTriStrip = 0x0001, // ha bisogno che ci sia la fftopology gia calcolata!
// HNUseEdgeStrip = 0x0002, //
HNUseDisplayList = 0x0004,
HNCacheDisplayList = 0x0008, // Each mode has its dl;
HNLazyDisplayList = 0x0010, // Display list are generated only when requested
HNIsTwoManifold = 0x0020, // There is no need to make DetachComplex before .
HNUsePerWedgeNormal = 0x0040, //
HNHasFFTopology = 0x0080, // E' l'utente che si preoccupa di tenere aggiornata la topologia ff
HNHasVFTopology = 0x0100, // E' l'utente che si preoccupa di tenere aggiornata la topologia vf
HNHasVertNormal = 0x0200, // E' l'utente che si preoccupa di tenere aggiornata le normali per faccia
HNHasFaceNormal = 0x0400, // E' l'utente che si preoccupa di tenere aggiornata le normali per vertice
HNUseVArray = 0x0800,
HNUseLazyEdgeStrip = 0x1000, // Edge Strip are generated only when requested
HNUseVBO = 0x2000, // Use Vertex Buffer Object
HNIsPolygonal = 0x4000 // In wireframe modes, hide faux edges
};
enum Change {
CHVertex = 0x01,
CHNormal = 0x02,
CHColor = 0x04,
CHFace = 0x08,
CHFaceNormal = 0x10,
CHRender = 0x20,
CHAll = 0xff
};
enum HintParami {
HNPDisplayListSize =0,
HNPPointDistanceAttenuation =1,
HNPPointSmooth = 2
};
enum HintParamf {
HNPCreaseAngle =0, // crease angle in radians
HNPZTwist = 1, // Z offset used in Flatwire and hiddenline modality
HNPPointSize = 2 // the point size used in point rendering
};
template<class MeshType>
class VertToSplit
{
public:
typename MeshType::face_base_pointer f;
char z;
char edge;
bool newp;
typename MeshType::vertex_pointer v;
};
// GL Array Elemet
class GLAElem {
public :
int glmode;
int len;
int start;
};
std::vector<unsigned int> TMId;
};
template <class MeshType, bool partial = false , class FACE_POINTER_CONTAINER = std::vector<typename MeshType::FacePointer> >
class GlTrimesh : public GLW
{
public:
typedef typename MeshType::VertexType VertexType;
typedef typename MeshType::FaceType FaceType;
typedef typename MeshType::VertexType::CoordType CoordType;
typedef typename MeshType::VertexType::ScalarType ScalarType;
typedef typename MeshType::VertexIterator VertexIterator;
typedef typename MeshType::EdgeIterator EdgeIterator;
typedef typename MeshType::FaceIterator FaceIterator;
FACE_POINTER_CONTAINER face_pointers;
MeshType *m;
unsigned int array_buffers[3];
int curr_hints; // the current hints
// The parameters of hints
int HNParami[8];
float HNParamf[8];
DrawMode cdm; // Current DrawMode
NormalMode cnm; // Current NormalMode
ColorMode ccm; // Current ColorMode
static NormalMode convertDrawModeToNormalMode(DrawMode dm)
{
switch(dm)
{
case(DMFlat):
case(DMFlatWire):
case(DMRadar):
return NMPerFace;
case(DMPoints):
case(DMWire):
case(DMSmooth):
return NMPerVert;
default:
return NMNone;
}
return NMNone;
}
GlTrimesh()
{
m=0;
dl=0xffffffff;
curr_hints=HNUseLazyEdgeStrip;
cdm=DMNone;
ccm=CMNone;
cnm=NMNone;
SetHintParamf(HNPCreaseAngle,float(M_PI/5));
SetHintParamf(HNPZTwist,0.00005f);
SetHintParamf(HNPPointSize,1.0f);
SetHintParami(HNPPointDistanceAttenuation, 1);
SetHintParami(HNPPointSmooth, 0);
}
~GlTrimesh()
{
//Delete the VBOs
if(curr_hints&HNUseVBO)
{
for(int i=0;i<3;++i)
if(glIsBuffer(GLuint(array_buffers[i])))
glDeleteBuffersARB(1, (GLuint *)(array_buffers+i));
}
}
unsigned int dl;
std::vector<unsigned int> indices;
void SetHintParami(const HintParami hip, const int value)
{
HNParami[hip]=value;
}
int GetHintParami(const HintParami hip) const
{
return HNParami[hip];
}
void SetHintParamf(const HintParamf hip, const float value)
{
HNParamf[hip]=value;
}
float GetHintParamf(const HintParamf hip) const
{
return HNParamf[hip];
}
void SetHint(Hint hn)
{
curr_hints |= hn;
}
void ClearHint(Hint hn)
{
curr_hints&=(~hn);
}
void Update(/*Change c=CHAll*/)
{
if(m==0) return;
if(curr_hints&HNUseVArray || curr_hints&HNUseVBO)
{
indices.clear();
for(FaceIterator fi = m->face.begin(); fi != m->face.end(); ++fi)
{
indices.push_back((unsigned int)((*fi).V(0) - &(*m->vert.begin())));
indices.push_back((unsigned int)((*fi).V(1) - &(*m->vert.begin())));
indices.push_back((unsigned int)((*fi).V(2) - &(*m->vert.begin())));
}
if(curr_hints&HNUseVBO)
{
if(!glIsBuffer(array_buffers[1]))
glGenBuffers(2,(GLuint*)array_buffers);
glBindBuffer(GL_ARRAY_BUFFER,array_buffers[0]);
glBufferData(GL_ARRAY_BUFFER_ARB, m->vn * sizeof(VertexType),
(char *)&(m->vert[0].P()), GL_STATIC_DRAW_ARB);
glBindBuffer(GL_ARRAY_BUFFER,array_buffers[1]);
glBufferData(GL_ARRAY_BUFFER_ARB, m->vn * sizeof(VertexType),
(char *)&(m->vert[0].N()), GL_STATIC_DRAW_ARB);
}
glVertexPointer(3,GL_TYPE_NM<ScalarType>::SCALAR(),sizeof(VertexType),0);
glNormalPointer(GL_TYPE_NM<ScalarType>::SCALAR(),sizeof(VertexType),0);
}
//int C=c;
//if((C&CHVertex) || (C&CHFace)) {
// ComputeBBox(*m);
// if(!(curr_hints&HNHasFaceNormal)) m->ComputeFaceNormal();
// if(!(curr_hints&HNHasVertNormal)) m->ComputeVertexNormal();
// C= (C | CHFaceNormal);
//}
//if((C&CHFace) && (curr_hints&HNUseEdgeStrip)) ComputeEdges();
//if((C&CHFace) && (curr_hints&HNUseLazyEdgeStrip)) ClearEdges();
//if(MeshType::HasFFTopology())
// if((C&CHFace) && (curr_hints&HNUseTriStrip)) {
// if(!(curr_hints&HNHasFFTopology)) m->FFTopology();
// ComputeTriStrip();
// }
//if((C&CHFaceNormal) && (curr_hints&HNUsePerWedgeNormal)) {
// if(!(curr_hints&HNHasVFTopology)) m->VFTopology();
// CreaseWN(*m,MeshType::scalar_type(GetHintParamf(HNPCreaseAngle)));
//}
//if(C!=0) { // force the recomputation of display list
// cdm=DMNone;
// ccm=CMNone;
// cnm=NMNone;
//}
//if((curr_hints&HNUseVArray) && (curr_hints&HNUseTriStrip))
// {
// ConvertTriStrip<MeshType>(*m,TStrip,TStripF,TStripVED,TStripVEI);
// }
}
void Draw(DrawMode dm ,ColorMode cm, TextureMode tm)
{
switch(dm)
{
case DMNone : Draw<DMNone >(cm,tm); break;
case DMBox : Draw<DMBox >(cm,tm); break;
case DMPoints : Draw<DMPoints >(cm,tm); break;
case DMWire : Draw<DMWire >(cm,tm); break;
case DMHidden : Draw<DMHidden >(cm,tm); break;
case DMFlat : Draw<DMFlat >(cm,tm); break;
case DMSmooth : Draw<DMSmooth >(cm,tm); break;
case DMFlatWire: Draw<DMFlatWire>(cm,tm); break;
default : break;
}
}
template< DrawMode dm >
void Draw(ColorMode cm, TextureMode tm)
{
switch(cm)
{
case CMNone : Draw<dm,CMNone >(tm); break;
case CMPerMesh : Draw<dm,CMPerMesh>(tm); break;
case CMPerFace : Draw<dm,CMPerFace>(tm); break;
case CMPerVert : Draw<dm,CMPerVert>(tm); break;
default : break;
}
}
template< DrawMode dm, ColorMode cm >
void Draw(TextureMode tm)
{
switch(tm)
{
case TMNone : Draw<dm,cm,TMNone >(); break;
case TMPerVert : Draw<dm,cm,TMPerVert >(); break;
case TMPerWedge : Draw<dm,cm,TMPerWedge >(); break;
case TMPerWedgeMulti : Draw<dm,cm,TMPerWedgeMulti >(); break;
default : break;
}
}
template< DrawMode dm, ColorMode cm, TextureMode tm>
void Draw()
{
if(!m) return;
if((curr_hints & HNUseDisplayList)){
if (cdm==dm && ccm==cm){
glCallList(dl);
return;
}
else {
if(dl==0xffffffff) dl=glGenLists(1);
glNewList(dl,GL_COMPILE);
}
}
glPushMatrix();
switch(dm)
{
case DMNone : break;
case DMBox : DrawBBox(cm);break;
case DMPoints : DrawPoints<NMPerVert,cm>();break;
case DMHidden : DrawHidden();break;
case DMFlat : DrawFill<NMPerFace,cm,tm>();break;
case DMFlatWire : DrawFlatWire<NMPerFace,cm,tm>();break;
case DMRadar : DrawRadar<NMPerFace,cm>();break;
case DMWire : DrawWire<NMPerVert,cm>();break;
case DMSmooth : DrawFill<NMPerVert,cm,tm>();break;
default : break;
}
glPopMatrix();
if((curr_hints & HNUseDisplayList)){
cdm=dm;
ccm=cm;
glEndList();
glCallList(dl);
}
}
/*********************************************************************************************/
/*********************************************************************************************/
template <NormalMode nm, ColorMode cm, TextureMode tm>
void DrawFill()
{
if(m->fn==0) return;
if(cm == CMPerMesh)
glColor(m->C());
if(tm == TMPerWedge || tm == TMPerWedgeMulti )
glDisable(GL_TEXTURE_2D);
if(curr_hints&HNUseVBO)
{
if( (cm==CMNone) || (cm==CMPerMesh) )
{
if (nm==NMPerVert)
glEnableClientState (GL_NORMAL_ARRAY);
glEnableClientState (GL_VERTEX_ARRAY);
if (nm==NMPerVert)
{
glBindBuffer(GL_ARRAY_BUFFER,array_buffers[1]);
glNormalPointer(GL_TYPE_NM<ScalarType>::SCALAR(),sizeof(typename MeshType::VertexType),0);
}
glBindBuffer(GL_ARRAY_BUFFER,array_buffers[0]);
glVertexPointer(3,GL_TYPE_NM<ScalarType>::SCALAR(),sizeof(typename MeshType::VertexType),0);
glDrawElements(GL_TRIANGLES ,m->fn*3,GL_UNSIGNED_INT, &(*indices.begin()) );
glDisableClientState (GL_VERTEX_ARRAY);
if (nm==NMPerVert)
glDisableClientState (GL_NORMAL_ARRAY);
glBindBuffer(GL_ARRAY_BUFFER, 0);
return;
}
}
if(curr_hints&HNUseVArray)
{
if( (cm==CMNone) || (cm==CMPerMesh) )
{
if (nm==NMPerVert)
glEnableClientState (GL_NORMAL_ARRAY);
glEnableClientState (GL_VERTEX_ARRAY);
if (nm==NMPerVert)
glNormalPointer(GL_TYPE_NM<ScalarType>::SCALAR(),sizeof(typename MeshType::VertexType),&(m->vert.begin()->N()[0]));
glVertexPointer(3,GL_TYPE_NM<ScalarType>::SCALAR(),sizeof(typename MeshType::VertexType),&(m->vert.begin()->P()[0]));
glDrawElements(GL_TRIANGLES ,m->fn*3,GL_UNSIGNED_INT, &(*indices.begin()) );
glDisableClientState (GL_VERTEX_ARRAY);
if (nm==NMPerVert)
glDisableClientState (GL_NORMAL_ARRAY);
return;
}
}
else
if(curr_hints&HNUseTriStrip)
{
//if( (nm==NMPerVert) && ((cm==CMNone) || (cm==CMPerMesh)))
// if(curr_hints&HNUseVArray){
// glEnableClientState (GL_NORMAL_ARRAY );
// glNormalPointer(GL_FLOAT,sizeof(MeshType::VertexType),&(m->vert[0].cN()));
// glEnableClientState (GL_VERTEX_ARRAY);
// glVertexPointer(3,GL_FLOAT,sizeof(MeshType::VertexType),&(m->vert[0].cP()));
// std::vector<GLAElem>::iterator vi;
// for(vi=TStripVED.begin();vi!=TStripVED.end();++vi)
// glDrawElements(vi->glmode ,vi->len,GL_UNSIGNED_SHORT,&TStripVEI[vi->start] );
//
// glDisableClientState (GL_NORMAL_ARRAY );
// glDisableClientState (GL_VERTEX_ARRAY);
// return;
// }
//std::vector< MeshType::VertexType *>::iterator vi;
//glBegin(GL_TRIANGLE_STRIP);
//if(nm == NMPerFace) fip=TStripF.begin();
//for(vi=TStrip.begin();vi!=TStrip.end(); ++vi){
// if((*vi)){
// if(nm==NMPerVert) glNormal((*vi)->cN());
// if(nm==NMPerFace) glNormal((*fip)->cN());
// glVertex((*vi)->P());
// }
// else
// {
// glEnd();
// glBegin(GL_TRIANGLE_STRIP);
// }
// if(nm == NMPerFace) ++fip;
// }
//glEnd();
}
else
{
typename FACE_POINTER_CONTAINER::iterator fp;
FaceIterator fi;
short curtexname=-1;
if(partial)
fp = face_pointers.begin();
else
fi = m->face.begin();
if(tm==TMPerWedgeMulti)
{
curtexname=(*fi).WT(0).n();
if ((curtexname >= 0) && (curtexname < (int)TMId.size()))
{
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D,TMId[curtexname]);
}
else
{
glDisable(GL_TEXTURE_2D);
}
}
if(tm==TMPerWedge)
glEnable(GL_TEXTURE_2D);
if(tm==TMPerVert && !TMId.empty()) // in the case of per vertex tex coord we assume that we have a SINGLE texture.
{
curtexname = 0;
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D,TMId[curtexname]);
}
glBegin(GL_TRIANGLES);
while( (partial)?(fp!=face_pointers.end()):(fi!=m->face.end()))
{
FaceType & f = (partial)?(*(*fp)): *fi;
if(!f.IsD())
{
if(tm==TMPerWedgeMulti)
if(f.WT(0).n() != curtexname)
{
curtexname=(*fi).WT(0).n();
glEnd();
if (curtexname >= 0)
{
glEnable(GL_TEXTURE_2D);
if(!TMId.empty())
glBindTexture(GL_TEXTURE_2D,TMId[curtexname]);
}
else
{
glDisable(GL_TEXTURE_2D);
}
glBegin(GL_TRIANGLES);
}
if(nm == NMPerFace) glNormal(f.cN());
if(nm == NMPerVert) glNormal(f.V(0)->cN());
if(nm == NMPerWedge)glNormal(f.WN(0));
if(cm == CMPerFace) glColor(f.C());
if(cm == CMPerVert) glColor(f.V(0)->C());
if(tm==TMPerVert) glTexCoord(f.V(0)->T().P());
if( (tm==TMPerWedge)||(tm==TMPerWedgeMulti) )glTexCoord(f.WT(0).t(0));
glVertex(f.V(0)->P());
if(nm == NMPerVert) glNormal(f.V(1)->cN());
if(nm == NMPerWedge)glNormal(f.WN(1));
if(cm == CMPerVert) glColor(f.V(1)->C());
if(tm==TMPerVert) glTexCoord(f.V(1)->T().P());
if( (tm==TMPerWedge)|| (tm==TMPerWedgeMulti)) glTexCoord(f.WT(1).t(0));
glVertex(f.V(1)->P());
if(nm == NMPerVert) glNormal(f.V(2)->cN());
if(nm == NMPerWedge)glNormal(f.WN(2));
if(cm == CMPerVert) glColor(f.V(2)->C());
if(tm==TMPerVert) glTexCoord(f.V(2)->T().P());
if( (tm==TMPerWedge)|| (tm==TMPerWedgeMulti)) glTexCoord(f.WT(2).t(0));
glVertex(f.V(2)->P());
}
if(partial)
++fp;
else
++fi;
}
glEnd();
}
}
// A draw wireframe that hides faux edges
template <NormalMode nm, ColorMode cm>
void DrawWirePolygonal()
{
if(cm == CMPerMesh) glColor(m->C());
FaceIterator fi;
typename FACE_POINTER_CONTAINER::iterator fp;
if(partial)
fp = face_pointers.begin();
else
fi = m->face.begin();
glBegin(GL_LINES);
while( (partial)?(fp!=face_pointers.end()):(fi!=m->face.end()))
{
typename MeshType::FaceType & f = (partial)?(*(*fp)): *fi;
if(!f.IsD())
{
if(nm == NMPerFace) glNormal(f.cN());
if(cm == CMPerFace) glColor(f.C());
if (!f.IsF(0)) {
if(nm == NMPerVert) glNormal(f.V(0)->cN());
if(nm == NMPerWedge)glNormal(f.WN(0));
if(cm == CMPerVert) glColor(f.V(0)->C());
glVertex(f.V(0)->P());
if(nm == NMPerVert) glNormal(f.V(1)->cN());
if(nm == NMPerWedge)glNormal(f.WN(1));
if(cm == CMPerVert) glColor(f.V(1)->C());
glVertex(f.V(1)->P());
}
if (!f.IsF(1)) {
if(nm == NMPerVert) glNormal(f.V(1)->cN());
if(nm == NMPerWedge)glNormal(f.WN(1));
if(cm == CMPerVert) glColor(f.V(1)->C());
glVertex(f.V(1)->P());
if(nm == NMPerVert) glNormal(f.V(2)->cN());
if(nm == NMPerWedge)glNormal(f.WN(2));
if(cm == CMPerVert) glColor(f.V(2)->C());
glVertex(f.V(2)->P());
}
if (!f.IsF(2)) {
if(nm == NMPerVert) glNormal(f.V(2)->cN());
if(nm == NMPerWedge)glNormal(f.WN(2));
if(cm == CMPerVert) glColor(f.V(2)->C());
glVertex(f.V(2)->P());
if(nm == NMPerVert) glNormal(f.V(0)->cN());
if(nm == NMPerWedge)glNormal(f.WN(0));
if(cm == CMPerVert) glColor(f.V(0)->C());
glVertex(f.V(0)->P());
}
}
if(partial)
++fp;
else
++fi;
}
glEnd();
}
/// Basic Point drawing fucntion
// works also for mesh with deleted vertices
template<NormalMode nm, ColorMode cm>
void DrawPointsBase()
{
glBegin(GL_POINTS);
if(cm==CMPerMesh) glColor(m->C());
for(VertexIterator vi=m->vert.begin();vi!=m->vert.end();++vi)if(!(*vi).IsD())
{
if(nm==NMPerVert) glNormal((*vi).cN());
if(cm==CMPerVert) glColor((*vi).C());
glVertex((*vi).P());
}
glEnd();
}
/// Utility function that computes in eyespace the current distance between the camera and the center of the bbox of the mesh
double CameraDistance(){
CoordType res;
Matrix44<ScalarType> mm;
glGetv(GL_MODELVIEW_MATRIX,mm);
CoordType c=m->bbox.Center();
res=mm*c;
return Norm(res);
}
template<NormalMode nm, ColorMode cm>
void DrawPoints()
{
glPushAttrib(GL_ENABLE_BIT | GL_POINT_BIT);
if(GetHintParami(HNPPointSmooth)>0) glEnable(GL_POINT_SMOOTH);
else glDisable(GL_POINT_SMOOTH);
glPointSize(GetHintParamf(HNPPointSize));
if(GetHintParami(HNPPointDistanceAttenuation)>0)
{
float camDist = (float)CameraDistance();
float quadratic[] = { 0.0f, 0.0f, 1.0f/(camDist*camDist) , 0.0f };
glPointParameterfv( GL_POINT_DISTANCE_ATTENUATION, quadratic );
glPointParameterf( GL_POINT_SIZE_MAX, 16.0f );
glPointParameterf( GL_POINT_SIZE_MIN, 1.0f );
}
else
{
float quadratic[] = { 1.0f, 0.0f, 0.0f};
glPointParameterfv( GL_POINT_DISTANCE_ATTENUATION, quadratic );
glPointSize(GetHintParamf(HNPPointSize));
}
if(m->vn!=(int)m->vert.size())
{
DrawPointsBase<nm,cm>();
}
else
{
if(cm==CMPerMesh)
glColor(m->C());
if (m->vert.size() != 0)
{
// Perfect case, no deleted stuff,
// draw the vertices using vertex arrays
if (nm==NMPerVert)
{
glEnableClientState (GL_NORMAL_ARRAY);
glNormalPointer(GL_TYPE_NM<ScalarType>::SCALAR(),sizeof(VertexType),&(m->vert.begin()->N()[0]));
}
if (cm==CMPerVert)
{
glEnableClientState (GL_COLOR_ARRAY);
glColorPointer(4,GL_UNSIGNED_BYTE,sizeof(typename MeshType::VertexType),&(m->vert.begin()->C()[0]));
}
glEnableClientState (GL_VERTEX_ARRAY);
glVertexPointer(3,GL_TYPE_NM<ScalarType>::SCALAR(),sizeof(VertexType),&(m->vert.begin()->P()[0]));
glDrawArrays(GL_POINTS,0,m->vn);
glDisableClientState (GL_VERTEX_ARRAY);
if (nm==NMPerVert) glDisableClientState (GL_NORMAL_ARRAY);
if (cm==CMPerVert) glDisableClientState (GL_COLOR_ARRAY);
}
}
glPopAttrib();
return;
}
void DrawHidden()
{
//const float ZTWIST=HNParamf[HNPZTwist];
glPushAttrib(GL_ENABLE_BIT | GL_CURRENT_BIT | GL_LIGHTING_BIT );
glEnable(GL_POLYGON_OFFSET_FILL);
glPolygonOffset(1.0, 1);
//glDepthRange(ZTWIST,1.0f);
glDisable(GL_LIGHTING);
glColorMask(GL_FALSE,GL_FALSE,GL_FALSE,GL_FALSE);
DrawFill<NMNone,CMNone,TMNone>();
glDisable(GL_POLYGON_OFFSET_FILL);
glEnable(GL_LIGHTING);
glColorMask(GL_TRUE,GL_TRUE,GL_TRUE,GL_TRUE);
//glDepthRange(0.0f,1.0f-ZTWIST);
DrawWire<NMPerVert,CMNone>();
glPopAttrib();
// glDepthRange(0,1.0f);
}
template <NormalMode nm, ColorMode cm, TextureMode tm>
void DrawFlatWire()
{
//const float ZTWIST=HNParamf[HNPZTwist];
//glDepthRange(ZTWIST,1.0f);
glPushAttrib(GL_ENABLE_BIT | GL_CURRENT_BIT | GL_LIGHTING_BIT );
glEnable(GL_POLYGON_OFFSET_FILL);
glPolygonOffset(1.0, 1);
DrawFill<nm,cm,tm>();
glDisable(GL_POLYGON_OFFSET_FILL);
//glDepthRange(0.0f,1.0f-ZTWIST);
glEnable(GL_COLOR_MATERIAL);
glColorMaterial(GL_FRONT_AND_BACK,GL_AMBIENT_AND_DIFFUSE);
//glColorMaterial(GL_FRONT,GL_DIFFUSE);
glColor3f(.3f,.3f,.3f);
DrawWire<nm,CMNone>();
glPopAttrib();
//glDepthRange(0,1.0f);
}
template <NormalMode nm, ColorMode cm>
void DrawRadar()
{
const float ZTWIST=HNParamf[HNPZTwist];
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glDepthMask(0);
glDepthRange(ZTWIST,1.0f);
if (cm == CMNone)
glColor4f(0.2f, 1.0f, 0.4f, 0.2f);
// DrawFill<nm,cm,TMNone>();
Draw<DMFlat,CMNone,TMNone>();
glDepthMask(1);
glColorMask(GL_FALSE,GL_FALSE,GL_FALSE,GL_FALSE);
// DrawFill<nm,cm,TMNone>();
Draw<DMFlat,CMNone,TMNone>();
glDepthRange(0.0f,1.0f-ZTWIST);
glColorMask(GL_TRUE,GL_TRUE,GL_TRUE,GL_TRUE);
glColor4f(0.1f, 1.0f, 0.2f, 0.6f);
Draw<DMWire,CMNone,TMNone>();
glDisable(GL_BLEND);
glDepthRange(0,1.0f);
}
#ifdef GL_TEXTURE0_ARB
// Multitexturing nel caso voglia usare due texture unit.
void DrawTexture_NPV_TPW2()
{
unsigned int texname=(*(m->face.begin())).WT(0).n(0);
glBindTexture(GL_TEXTURE_2D,TMId[texname]);
typename MeshType::FaceIterator fi;
glBegin(GL_TRIANGLES);
for(fi=m->face.begin();fi!=m->face.end();++fi)if(!(*fi).IsD()){
if(texname!=(*fi).WT(0).n(0)) {
texname=(*fi).WT(0).n(0);
glEnd();
glBindTexture(GL_TEXTURE_2D,TMId[texname]);
glBegin(GL_TRIANGLES);
}
glMultiTexCoordARB(GL_TEXTURE0_ARB, (*fi).WT(0).t(0));
glMultiTexCoordARB(GL_TEXTURE1_ARB, (*fi).WT(0).t(0));
glNormal((*fi).V(0)->N());
glVertex((*fi).V(0)->P());
glMultiTexCoordARB(GL_TEXTURE0_ARB, (*fi).WT(1).t(0));
glMultiTexCoordARB(GL_TEXTURE1_ARB, (*fi).WT(1).t(0));
glNormal((*fi).V(1)->N());
glVertex((*fi).V(1)->P());
glMultiTexCoordARB(GL_TEXTURE0_ARB, (*fi).WT(2).t(0));
glMultiTexCoordARB(GL_TEXTURE1_ARB, (*fi).WT(2).t(0));
glNormal((*fi).V(2)->N());
glVertex((*fi).V(2)->P());
}
glEnd();
}
#endif
/*int MemUsed()
{
int tot=sizeof(GlTrimesh);
tot+=sizeof(mesh_type::edge_type)*edge.size();
tot+=sizeof(MeshType::VertexType *) * EStrip.size();
tot+=sizeof(MeshType::VertexType *) * TStrip.size();
tot+=sizeof(MeshType::FaceType *) * TStripF.size();
return tot;
}*/
private:
template <NormalMode nm, ColorMode cm>
void DrawWire()
{
//if(!(curr_hints & (HNUseEdgeStrip | HNUseLazyEdgeStrip) ) )
if ( (curr_hints & HNIsPolygonal) )
{
DrawWirePolygonal<nm,cm>();
}
else
{
glPushAttrib(GL_POLYGON_BIT);
glPolygonMode(GL_FRONT_AND_BACK ,GL_LINE);
DrawFill<nm,cm,TMNone>();
glPopAttrib();
}
if(m->fn==0 && m->en>0)
{
glPushAttrib(GL_ENABLE_BIT);
glDisable(GL_LIGHTING);
glBegin(GL_LINES);
for(EdgeIterator ei=m->edge.begin();ei!=m->edge.end(); ++ei)
{
glVertex((*ei).V(0)->P());
glVertex((*ei).V(1)->P());
}
glEnd();
glPopAttrib();
}
// {
// if(!HasEdges()) ComputeEdges();
//if(cm==CMPerMesh) glColor(m->C());
//std::vector< MeshType::VertexType *>::iterator vi;
//glBegin(GL_LINE_STRIP);
//for(vi=EStrip.begin();vi!=EStrip.end(); ++vi){
// if((*vi)){
// glNormal((*vi)->N());
// glVertex((*vi)->P());
// }
// else
// {
// glEnd();
// glBegin(GL_LINE_STRIP);
// }
//}
//glEnd();
// }
}
void DrawBBox(ColorMode cm)
{
if(cm==CMPerMesh) glColor(m->C());
glBoxWire(m->bbox);
}
};// end class
} // end namespace
#endif