You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
449 lines
13 KiB
449 lines
13 KiB
/**************************************************************************** |
|
* VCGLib o o * |
|
* Visual and Computer Graphics Library o o * |
|
* _ O _ * |
|
* Copyright(C) 2004-2016 \/)\/ * |
|
* 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. * |
|
* * |
|
****************************************************************************/ |
|
/**************************************************************************** |
|
History |
|
$Log: not supported by cvs2svn $ |
|
Revision 1.12 2006/05/25 09:22:58 cignoni |
|
Removed all GLUT dependencies! |
|
|
|
Revision 1.11 2006/03/29 07:54:03 cignoni |
|
Wrong matrix type in cone (thx Maarten) |
|
|
|
|
|
****************************************************************************/ |
|
#ifndef __VCG_GLADDONS |
|
#define __VCG_GLADDONS |
|
|
|
#include <wrap/gl/math.h> |
|
#include <wrap/gl/space.h> |
|
#include <vcg/space/point3.h> |
|
#include <map> |
|
|
|
namespace vcg |
|
{ |
|
#include "gl_geometry.h" |
|
/** Class Add_Ons. |
|
This is class draw 3d icons on the screen |
|
*/ |
|
class Add_Ons |
|
{ |
|
public: |
|
enum DrawMode {DMUser,DMWire,DMSolid,DMFlat} ; |
|
private: |
|
|
|
///used to find right transformation in case of rotation |
|
static void XAxis(vcg::Point3f zero, vcg::Point3f uno, Matrix44f & tr) |
|
{ |
|
#ifndef VCG_USE_EIGEN |
|
tr.SetZero(); |
|
*((vcg::Point3f*)&tr[0][0]) = uno-zero; |
|
GetUV(*((vcg::Point3f*)tr[0]),*((vcg::Point3f*)tr[1]),*((vcg::Point3f*)tr[2])); |
|
tr[3][3] = 1.0; |
|
*((vcg::Point3f*)&tr[3][0]) = zero; |
|
#else |
|
tr.col(0).start<3>().setZero(); |
|
tr.row(0).start<3>() = (uno-zero).normalized(); // n |
|
tr.row(1).start<3>() = tr.row(0).start<3>().unitOrthogonal(); // u |
|
tr.row(2).start<3>() = tr.row(0).start<3>().cross(tr.row(1).start<3>()).normalized(); // v |
|
tr.row(3) << zero.transpose(), 1.; |
|
#endif |
|
} |
|
|
|
//set drawingmode parameters |
|
static void SetGLParameters(DrawMode DM) |
|
{ |
|
switch(DM) |
|
{ |
|
case DMUser : |
|
break; |
|
case DMFlat : |
|
glEnable(GL_CULL_FACE); |
|
glEnable(GL_LIGHTING); |
|
glEnable(GL_NORMALIZE); |
|
break; |
|
case DMWire : |
|
glDisable(GL_CULL_FACE); |
|
glDisable(GL_LIGHTING); |
|
glDisable(GL_NORMALIZE); |
|
glPolygonMode(GL_FRONT_AND_BACK,GL_LINE); |
|
break; |
|
case DMSolid : |
|
glDisable(GL_CULL_FACE); |
|
glPolygonMode(GL_FRONT,GL_FILL); |
|
break; |
|
default : |
|
break; |
|
} |
|
} |
|
|
|
///draw a cylinder |
|
static void Cylinder(int slices,float lenght,float width,bool useDisplList) |
|
{ |
|
static std::map<int,GLint> Disp_listMap; |
|
GLint cyl_List=-1; |
|
std::map<int,GLint>::const_iterator it=Disp_listMap.find(slices); |
|
///if the diplay list is createdtake the Glint that identify it |
|
bool to_insert=false; |
|
if (useDisplList) |
|
{ |
|
if (it!=Disp_listMap.end())///the list exist |
|
cyl_List=it->second; |
|
else to_insert=true; |
|
} |
|
|
|
glScaled(lenght,width,width); |
|
|
|
if (((!glIsList(cyl_List))&&(useDisplList))||(!useDisplList)) |
|
{ |
|
if (useDisplList) |
|
{ |
|
cyl_List = glGenLists(1); |
|
glNewList(cyl_List, GL_COMPILE); |
|
} |
|
int b; |
|
vcg::Point3f p0; |
|
vcg::Point3f p1; |
|
|
|
float step=6.28f/(float)slices; |
|
float angle=0; |
|
glBegin(GL_TRIANGLE_STRIP); |
|
for(b = 0; b <= slices-1; ++b){ |
|
p0 = vcg::Point3f( 0, sin(angle),cos(angle)); |
|
p1 = p0; p1[0] = 1.f; |
|
glNormal3f(p0[0],p0[1],p0[2]); |
|
glVertex3d(p0[0],p0[1],p0[2]); |
|
glVertex3d(p1[0],p1[1],p1[2]); |
|
angle+=step; |
|
} |
|
///re-conjunction with first point of cylinder |
|
glNormal3f(0,0,1); |
|
glVertex3d(0,0,1); |
|
glVertex3d(1,0,1); |
|
|
|
glEnd(); |
|
|
|
///fill the cylinder down |
|
angle=0; |
|
p0=vcg::Point3f(0,0,0); |
|
glBegin(GL_TRIANGLE_FAN); |
|
glNormal3f(-1,0,0); |
|
glVertex3d(p0[0],p0[1],p0[2]); |
|
for(b = 0; b <= slices-1; ++b){ |
|
glNormal3f(-1,0,0); |
|
p1 = Point3f( 0, sin(angle),cos(angle)); |
|
glVertex3d(p1[0],p1[1],p1[2]); |
|
angle+=step; |
|
} |
|
glNormal3f(-1,0,0); |
|
glVertex3d(0,0,1); |
|
glEnd(); |
|
|
|
angle=0; |
|
p0=vcg::Point3f(1,0,0); |
|
glBegin(GL_TRIANGLE_FAN); |
|
glNormal3f(1,0,0); |
|
glVertex3d(p0[0],p0[1],p0[2]); |
|
for(b = 0; b <= slices-1; ++b){ |
|
glNormal3f(1,0,0); |
|
p1 = Point3f( 1, sin(angle),cos(angle)); |
|
glVertex3d(p1[0],p1[1],p1[2]); |
|
angle+=step; |
|
} |
|
glNormal3f(1,0,0); |
|
glVertex3d(1,0,1); |
|
glEnd(); |
|
|
|
|
|
if (useDisplList) |
|
glEndList(); |
|
} |
|
if (useDisplList) |
|
{ |
|
glCallList(cyl_List); |
|
///I insert key and value in the map if I need |
|
if (to_insert) |
|
Disp_listMap.insert(std::pair<int,GLint>(slices,cyl_List)); |
|
} |
|
} |
|
public: |
|
static void Diamond (float radius,bool useDisplList) |
|
{ |
|
static GLint diam_List=-1; |
|
|
|
glScaled(radius,radius,radius); |
|
if (((!glIsList(diam_List))&&(useDisplList))||(!useDisplList)) |
|
{ |
|
if (useDisplList) |
|
{ |
|
diam_List = glGenLists(1); |
|
glNewList(diam_List, GL_COMPILE); |
|
} |
|
|
|
glBegin(GL_TRIANGLE_FAN); |
|
glNormal3f( 0.0, 1, 0.0); |
|
glVertex3f(0.0,1,0.0); |
|
|
|
glNormal3f( 1, 0.0, 0.0); |
|
glVertex3f( 1, 0.0, 0.0); |
|
|
|
glNormal3f( 0.0, 0.0, -1); |
|
glVertex3f( 0.0, 0.0,-1); |
|
|
|
glNormal3f(-1, 0.0 , 0.0); |
|
glVertex3f(-1, 0.0, 0.0); |
|
|
|
glNormal3f( 0.0, 0.0, 1); |
|
glVertex3f( 0.0, 0.0, 1); |
|
|
|
glNormal3f( 1, 0.0, 0.0); |
|
glVertex3f( 1, 0.0, 0.0); |
|
|
|
glEnd(); |
|
|
|
glBegin(GL_TRIANGLE_FAN); |
|
glNormal3f( 0.0, 1, 0.0); |
|
glVertex3f( 0.0,-1, 0.0); |
|
|
|
glNormal3f( 1, 0.0, 0.0); |
|
glVertex3f( 1, 0.0, 0.0); |
|
|
|
glNormal3f( 0.0, 0.0, 1); |
|
glVertex3f( 0.0, 0.0, 1); |
|
|
|
glNormal3f(-1,0.0 , 0.0); |
|
glVertex3f(-1, 0.0, 0.0); |
|
|
|
glNormal3f( 0.0,0.0, -1); |
|
glVertex3f( 0.0, 0.0,-1); |
|
|
|
glNormal3f( 1, 0.0, 0.0); |
|
glVertex3f( 1, 0.0, 0.0); |
|
glEnd(); |
|
if (useDisplList) |
|
glEndList(); |
|
} |
|
if (useDisplList) |
|
glCallList(diam_List); |
|
} |
|
|
|
///draw a cone |
|
static void Cone(int slices,float lenght,float width,bool useDisplList) |
|
{ |
|
static std::map<int,GLint> Disp_listMap; |
|
GLint cone_List=-1; |
|
std::map<int,GLint>::const_iterator it=Disp_listMap.find(slices); |
|
///if the diplay list is createdtake the Glint that identify it |
|
bool to_insert=false; |
|
|
|
if (useDisplList) |
|
{ |
|
if (it!=Disp_listMap.end())///the list exist |
|
cone_List=it->second; |
|
else to_insert=true; |
|
} |
|
|
|
glScaled(lenght,width,width); |
|
if (((!glIsList(cone_List))&&(useDisplList))||(!useDisplList)) |
|
{ |
|
int h=1; |
|
vcg::Point3f p0; |
|
vcg::Point3f P[2]; |
|
vcg::Point3f N[2]; |
|
glScaled(lenght,width,width); |
|
if (useDisplList) |
|
{ |
|
cone_List = glGenLists(1); |
|
glNewList(cone_List, GL_COMPILE); |
|
} |
|
for(h=0; h < 2; ++h) |
|
{ |
|
// assert(!glGetError()); |
|
//glBegin(GL_TRIANGLE_FAN); |
|
p0 = Point3f(0,0,0); |
|
if(h==0) p0[0]+=1.f; |
|
//glNormal3f(1,0.0,0.0); |
|
//glVertex3d(p0[0],p0[1],p0[2]); |
|
N[0]= Point3f( 1.f,sinf(0),cosf(0) ); |
|
P[0]= Point3f( 0,sinf(0),cosf(0)); |
|
int b; |
|
for(b = 1; b <= slices; ++b) |
|
{ |
|
float angle = -6.28f*(float)b/(float)slices; |
|
if (b==slices) angle=0; |
|
N[1] = Point3f( 1.f, sinf(angle), cosf(angle) ); |
|
P[1] = Point3f( 0, sinf(angle), cosf(angle)); |
|
glBegin(GL_TRIANGLES); |
|
Point3f n = ( (P[0]-p0) ^ (P[1]-p0) ).Normalize(); |
|
// Point3f n = ( (N[0]+N[1]) ).Normalize(); |
|
glNormal(n); |
|
glVertex(p0); |
|
glNormal3f(N[0][0],N[0][1],N[0][2]); |
|
glVertex3f(P[0][0],P[0][1],P[0][2]); |
|
glNormal3f(N[1][0],N[1][1],N[1][2]); |
|
glVertex3f(P[1][0],P[1][1],P[1][2]); |
|
glEnd(); |
|
// assert(!glGetError()); |
|
N[0] = N[1]; |
|
P[0] = P[1]; |
|
} |
|
//glEnd(); |
|
} |
|
if (useDisplList) |
|
glEndList(); |
|
} |
|
if (useDisplList) |
|
{ |
|
glCallList(cone_List); |
|
///I insert key and value in the map if I need |
|
if (to_insert) |
|
Disp_listMap.insert(std::pair<int,GLint>(slices,cone_List)); |
|
} |
|
} |
|
|
|
public: |
|
|
|
/// draw an arrow from tail to head |
|
/// body_width = width of the body of arrow |
|
/// head_lenght = lenght of the head of arrow |
|
/// head_width = width of the head of arrow |
|
/// body_slice = number of slices on the body |
|
/// head_slice = number of slices on the head |
|
template <DrawMode dm> |
|
static void glArrow(Point3f tail, Point3f head,float body_width,float head_lenght, |
|
float head_width,int body_slice=10,int head_slice=10,bool useDisplList=true) |
|
{ |
|
if (tail!=head) |
|
{ |
|
//assert(!glGetError()); |
|
Matrix44f tr; |
|
XAxis(tail,head,tr); |
|
glPushAttrib(GL_ALL_ATTRIB_BITS); |
|
SetGLParameters(dm); |
|
glPushMatrix(); |
|
glMultMatrixf(&tr[0][0]); |
|
vcg::Point3f Direct=(head-tail); |
|
if(body_width == 0) body_width = Direct.Norm()/40.0f; |
|
if(head_lenght == 0) head_lenght = Direct.Norm()/5.0f; |
|
if(head_width == 0) head_width = Direct.Norm()/15.0f; |
|
float l_body=Direct.Norm()-head_lenght; |
|
glPushMatrix(); |
|
//glTranslate(vcg::Point3f(tail.Norm(),0,0)); |
|
Cylinder(body_slice,l_body,body_width,useDisplList); |
|
glPopMatrix(); |
|
glTranslate(vcg::Point3f(l_body,0,0)); |
|
Cone(head_slice,head_lenght,head_width,useDisplList); |
|
glPopMatrix(); |
|
//assert(!glGetError()); |
|
glPopAttrib(); |
|
//assert(!glGetError()); |
|
} |
|
} |
|
|
|
/// draw a cone from tail to head |
|
/// width = width of the base of the cone |
|
/// slice = number of slices on the cone |
|
template <DrawMode dm> |
|
static void glCone(Point3f tail, Point3f head,float width,int slice=10,bool useDisplList=true) |
|
{ |
|
if (tail!=head) |
|
{ |
|
Matrix44f tr; |
|
XAxis(tail,head,tr); |
|
glPushAttrib(GL_ALL_ATTRIB_BITS); |
|
SetGLParameters(dm); |
|
glPushMatrix(); |
|
glMultMatrixf(&tr[0][0]); |
|
vcg::Point3f Direct=(head-tail); |
|
float l_body=Direct.Norm(); |
|
//glTranslate(vcg::Point3f(tail.Norm(),0,0)); |
|
Cone(slice,l_body,width,useDisplList); |
|
glPopMatrix(); |
|
glPopAttrib(); |
|
} |
|
} |
|
|
|
/// draw a cylinder from tail to head |
|
/// width = width of the base of the cylinder |
|
/// slice = number of slices on the cylinder |
|
template <DrawMode dm> |
|
static void glCylinder(Point3f tail, Point3f head,float width,int slice=10,bool useDisplList=true) |
|
{ |
|
if (tail!=head) |
|
{ |
|
Matrix44f tr; |
|
XAxis(tail,head,tr); |
|
glPushAttrib(GL_ALL_ATTRIB_BITS); |
|
SetGLParameters(dm); |
|
glPushMatrix(); |
|
glMultMatrixf(&tr[0][0]); |
|
vcg::Point3f Direct=(head-tail); |
|
float l_body=Direct.Norm(); |
|
//glTranslate(vcg::Point3f(tail.Norm(),0,0)); |
|
Cylinder(slice,l_body,width,useDisplList); |
|
glPopMatrix(); |
|
glPopAttrib(); |
|
} |
|
|
|
} |
|
|
|
/// draw a point in Center |
|
/// size = Radius of the point |
|
/// slices = The number of subdivisions around the Z axis (similar to lines of longitude). |
|
/// stacks = The number of subdivisions along the Z axis (similar to lines of latitude). |
|
template <DrawMode dm> |
|
static void glPoint(vcg::Point3f Center,float size,int slices =16,int stacks =16) |
|
{ |
|
if (size!=0){ |
|
glPushMatrix(); |
|
glTranslate(Center); |
|
if (dm==DMWire) |
|
glutWireSphere(size,slices,stacks); |
|
else |
|
if (dm==DMSolid) |
|
glutSolidSphere(size,slices,stacks); |
|
else |
|
glutSolidSphere(size,slices,stacks); |
|
glPopMatrix(); |
|
} |
|
} |
|
|
|
/// draw a point in Center |
|
/// size = Radius of the point |
|
/// slices = The number of subdivisions around the Z axis (similar to lines of longitude). |
|
/// stacks = The number of subdivisions along the Z axis (similar to lines of latitude). |
|
template <DrawMode dm> |
|
static void glDiamond (Point3f Center, float size,bool useDisplList=true) |
|
{ |
|
if (size!=0){ |
|
glPushAttrib(GL_ALL_ATTRIB_BITS); |
|
SetGLParameters(dm); |
|
glPushMatrix(); |
|
glTranslated(Center[0],Center[1],Center[2]); |
|
Diamond(size,useDisplList); |
|
glPopMatrix(); |
|
glPopAttrib(); |
|
} |
|
} |
|
}; |
|
} |
|
#endif
|
|
|