#ifndef __GLWRAPTETRA__ #define __GLWRAPTETRA__ #include #include #include #include #include #include #include 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,CMPerTetraF,CMPerVertexF,CMPerVertex}; enum Hint {HShrinkFactor}; }; template class GlTetramesh:public GLW{ public: typedef typename CONT_TETRA::value_type TetraType; typedef typename TetraType::VertexType VertexType; typedef typename VertexType::ScalarType ScalarType; typedef typename VertexType::CoordType Point3x; //subclass for clipping planes class ClipPlane { private: Point3x D; Point3x D0; GLdouble eqn[4]; vcg::Matrix44 TR; Point3x pp0; Point3x pp1; Point3x pp2; Point3x pp3; public: bool active; Point3x P; ClipPlane (){active=false;} ~ClipPlane (){} ClipPlane(Point3x p0, Point3x p1,Point3x p2) { Point3x N=((p1-p0)^(p2-p0)).Normalize(); N.Normalize(); D=N; D0=D; P=(p0+p1+p2)/3.f; Point3x v0=N; Point3x v1=(P-p0); v1.Normalize(); Point3x v2=(v0^v1); v2.Normalize(); v0=v0*2; v1=v1*2; v2=v2*2; pp0=-v1-v2; pp1=-v1+v2; pp2=v1+v2; pp3=v1-v2; } //set normal of the clipping plane void SetD(Point3x d) { D=d; } //set the point of the clipping plane void SetP(Point3x p) { P=p; } 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() { glPushMatrix(); glPushAttrib(0xffffffff); glDisable(GL_CLIP_PLANE0); glEnable(GL_LIGHTING); glEnable(GL_NORMALIZE); glTranslate(P); glMultMatrix(TR); glLineWidth(0.5); glColor3d(0.7,0,0.7); glBegin(GL_LINE_LOOP); glVertex(pp0); glVertex(pp1); glVertex(pp2); glVertex(pp3); glEnd(); glPopAttrib(); glPopMatrix(); } void Transform(vcg::Matrix44 Tr) { //thath's for casting in case of trackball using //float to double and vice-versa Point3f p=Point3f((float)D0.V(0),(float)D0.V(1),(float)D0.V(2)); TR=Tr; p=TR*p; D=Point3x((ScalarType) p.V(0),(ScalarType) p.V(1),(ScalarType) p.V(2)); } void Translate(float L) { Point3x D1=D*L; P+=D1; } }; GlTetramesh(CONT_TETRA * _t):tetra(_t){} GlTetramesh( ) {} CONT_TETRA * tetra; ClipPlane section; private: ScalarType shrink_factor; public: void SetHint(Hint h, double value){ switch(h){ case HShrinkFactor: shrink_factor = value; break; } } void AddClipSection(Point3x p0,Point3x p1,Point3x p2) { section=ClipPlane(p0,p1,p2); section.active=true; } void ClearClipSection() { section.active=false; } typedef Color4b (*color_func_vertex)(VertexType&v); color_func_vertex color_vertex; typedef Color4b (*color_func_tetra)(TetraType&v); color_func_tetra color_tetra; template void Draw(){ switch (dm){ case DMNone: break; case DMSmallTetra:_DrawSmallTetra();break; case DMFlat:_DrawSurface();break; case DMWire:_DrawSurface();break; case DMHidden:_DrawSurface();break; case DMFlatWire:_DrawFlatWire(); break; case DMTransparent:break; } } private: template void _DrawSmallTetra(){ Point3x p[4],br; CONT_TETRA::iterator it; glPushAttrib(0xffffffff); glEnable(GL_COLOR_MATERIAL); glEnable(GL_LIGHT0); glEnable(GL_LIGHTING); glEnable(GL_NORMALIZE); glPolygonMode(GL_FRONT,GL_FILL); if (section.active) { section.GlClip(); section.GlDraw(); } /*glBegin(GL_TRIANGLES);*/ for( it = tetra->begin(); it != tetra->end(); ++it) if((!it->IsD())&&(!(it->IsS()))) //draw as normal { _DrawSmallTetra(*it); } else if((!it->IsD())&&((it->IsS())))//draw in selection mode { _DrawSelectedTetra(*it); } //glEnd(); glPopAttrib(); } template void _DrawFlatWire(){ glPushAttrib(0xffff); glEnable(GL_COLOR_MATERIAL); glEnable(GL_DEPTH); glDepthRange(0.001,1.0); Draw(); glDisable(GL_LIGHTING); glColor3f(0.0,0.0,0.0); glDepthRange(0.0,0.999); Draw(); glPopAttrib(); } template void _DrawSurface(){ CONT_TETRA::iterator it; 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_LIGHTING); glEnable(GL_NORMALIZE); glPolygonMode(GL_FRONT,GL_FILL); } //glBegin(GL_TRIANGLES); for( it = tetra->begin(); it != tetra->end(); ++it) _DrawTetra((*it)); //glEnd(); 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 void _DrawTetra(TetraType &t) { if((!t.IsD())&&(!t.IsS())) { if ((dm!=DMWire)&&(dm!=DMHidden)) _ChooseColorTetra(t); for(int i = 0; i < 4; ++i){ if (dm == DMWire) _DrawFace(t,i); else { if (t.IsBorderF(i)) { if(nm==NMSmooth) _DrawFaceSmooth(t,i); else if(nm==NMFlat) _DrawFace(t,i); } } } } else if((!t.IsD())&&(t.IsS())) _DrawSelectedTetra(t); } template void _ChooseColorTetra(TetraType &t) { if (cm==CMNone) { if (t.IsS()) glColor3d(1,0,0); else glColor3d(0.8f,0.8f,0.8f); } 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); } } template void _ChooseColorVertex(VertexType &v) { if (cm!=CMNone) { 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) glColor3f(v.C()[0],v.C()[1],v.C()[2]); } } template 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(*v0); glNormal(v0->N()); glVertex(v0->P()); _ChooseColorVertex(*v1); glNormal(v1->N()); glVertex(v1->P()); _ChooseColorVertex(*v2); glNormal(v2->N()); glVertex(v2->P()); glEnd(); } template void _DrawFace(TetraType &t,int face) { glBegin(GL_TRIANGLES); glNormal(t.N(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)); _ChooseColorVertex(*v0); glVertex(v0->P()); _ChooseColorVertex(*v1); glVertex(v1->P()); _ChooseColorVertex(*v2); glVertex(v2->P()); glEnd(); } template void _DrawSmallTetra(TetraType &t) { Tetra3 T=Tetra3(); T.P0(0)=t.V(0)->cP(); T.P1(0)=t.V(1)->cP(); T.P2(0)=t.V(2)->cP(); T.P3(0)=t.V(3)->cP(); Point3x p[4], br; br=T.ComputeBarycenter(); for(int i = 0; i < 4; ++i) p[i] = t.V(i)->P()* shrink_factor + br *(1- shrink_factor); _ChooseColorTetra(t); glBegin(GL_TRIANGLES); for(int i = 0; i < 4; ++i) { glNormal(t.N(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)); _ChooseColorVertex(*v0); glVertex(p[Tetra::VofF(i,0)]); _ChooseColorVertex(*v1); glVertex(p[Tetra::VofF(i,1)]); _ChooseColorVertex(*v2); glVertex(p[Tetra::VofF(i,2)]); } glEnd(); } }; } // end namespace tetra } // end nemaspace tri #endif