1
/****************************************************************************
3
* A versatile mesh processing toolbox o o *
5
* Copyright(C) 2008 \/)\/ *
6
* Visual Computing Lab /\/| *
7
* ISTI - Italian National Research Council | *
9
* All rights reserved. *
11
* This program is free software; you can redistribute it and/or modify *
12
* it under the terms of the GNU General Public License as published by *
13
* the Free Software Foundation; either version 2 of the License, or *
14
* (at your option) any later version. *
16
* This program is distributed in the hope that it will be useful, *
17
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
18
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
19
* GNU General Public License (http://www.gnu.org/licenses/gpl.txt) *
22
****************************************************************************/
23
/****************************************************************************
25
$Log: not supported by cvs2svn $
26
Revision 1.8 2008/03/02 16:44:18 benedetti
27
moved ActiveCoordinateFrame to its own files
29
Revision 1.7 2008/02/26 18:22:42 benedetti
30
corrected after quaternion/similarity/trackball changes
32
Revision 1.6 2008/02/22 20:34:35 benedetti
35
Revision 1.5 2008/02/22 20:04:02 benedetti
36
many user interface improvements, cleaned up a little
38
Revision 1.4 2008/02/17 20:52:53 benedetti
39
some generalization made
41
Revision 1.3 2008/02/16 14:12:30 benedetti
45
****************************************************************************/
48
#include <wrap/gl/math.h>
49
#include <wrap/gl/space.h>
50
#include <wrap/gl/addons.h>
52
#include "coordinateframe.h"
56
CoordinateFrame::CoordinateFrame(float s)
57
:basecolor(Color4b::White),xcolor(Color4b::Red)
58
,ycolor(Color4b::Green),zcolor(Color4b::Blue),size(s),linewidth(2.0)
59
,font(),drawaxis(true),drawlabels(true),drawvalues(false)
61
font.setFamily("Helvetica");
64
void CoordinateFrame::Render(QGLWidget* glw)
67
glPushAttrib(GL_ALL_ATTRIB_BITS);
68
glDisable(GL_LIGHTING);
69
glDisable(GL_TEXTURE_2D);
71
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
72
glEnable(GL_LINE_SMOOTH);
73
glEnable(GL_POINT_SMOOTH);
74
glLineWidth(linewidth);
75
glPointSize(linewidth*1.5);
81
// Get gl state values
84
glGetDoublev(GL_MODELVIEW_MATRIX,mm);
85
glGetDoublev(GL_PROJECTION_MATRIX,mp);
86
glGetIntegerv(GL_VIEWPORT,vp);
87
float slope_a=calcSlope(-a,a,2*size,10,mm,mp,vp);
88
float slope_b=calcSlope(-b,b,2*size,10,mm,mp,vp);
89
float slope_c=calcSlope(-c,c,2*size,10,mm,mp,vp);
90
float scalefactor = size*0.02f;
94
glVertex(-a); glVertex(a);
96
glVertex(-b); glVertex(b);
98
glVertex(-c); glVertex(c);
102
drawTickedLine(o,a,size,slope_a,linewidth); // Draws x axis
103
drawTickedLine(o,b,size,slope_b,linewidth); // Draws y axis
104
drawTickedLine(o,c,size,slope_c,linewidth); // Draws z axis
106
drawTickedLine(o,-a,size,slope_a,linewidth); // Draws x axis
107
drawTickedLine(o,-b,size,slope_b,linewidth); // Draws y axis
108
drawTickedLine(o,-c,size,slope_c,linewidth); // Draws z axis
111
glScalef(scalefactor,scalefactor,scalefactor);
112
Add_Ons::Cone(10,linewidth*1.5,linewidth*0.5,true);
117
glScalef(scalefactor,scalefactor,scalefactor);
118
Add_Ons::Cone(10,linewidth*1.5,linewidth*0.5,true);
122
glRotatef(-90,0,1,0);
123
glScalef(scalefactor,scalefactor,scalefactor);
124
Add_Ons::Cone(10,linewidth*1.5,linewidth*0.5,true);
129
font.setPixelSize(12);
130
float d=size+scalefactor*linewidth*1.5;
132
glw->renderText(d,0,0,QString("X"),font);
134
glw->renderText(0,d,0,QString("Y"),font);
136
glw->renderText(0,0,d,QString("Z"),font);
140
font.setPixelSize(8);
142
glColor(Color4b::LightGray);
143
for(i=slope_a;i<size;i+=slope_a){
144
glw->renderText( i,0,0,QString(" %1").arg(i,3,'f',1),font);
145
glw->renderText(-i,0,0,QString("-%1").arg(i,3,'f',1),font);
147
for(i=slope_b;i<size;i+=slope_b){
148
glw->renderText(0, i,0,QString(" %1").arg(i,3,'f',1),font);
149
glw->renderText(0,-i,0,QString("-%1").arg(i,3,'f',1),font);
151
for(i=slope_c;i<size;i+=slope_c){
152
glw->renderText(0,0, i,QString(" %1").arg(i,3,'f',1),font);
153
glw->renderText(0,0,-i,QString("-%1").arg(i,3,'f',1),font);
158
assert(!glGetError());
161
void CoordinateFrame::drawTickedLine(const Point3d &a,const Point3d &b, float dim,float tickDist,float linewidth)
164
v = v /dim; // normalize without computing square roots and powers
168
for(i=tickDist;i<dim;i+=tickDist)
169
glVertex3f(a[0] + i*v[0],a[1] + i*v[1],a[2] + i*v[2]);
172
glPushAttrib(GL_POINT_BIT);
173
glPointSize(linewidth*3);
175
glVertex3f(a[0] + dim*v[0],a[1] + dim*v[1],a[2] + dim*v[2]);
181
float CoordinateFrame::calcSlope(const Point3d &a,const Point3d &b,float dim,int spacing,double *mm,double *mp,GLint *vp)
185
gluProject(a[0],a[1],a[2],mm,mp,vp,&p1[0],&p1[1],&p1[2]);
186
gluProject(b[0],b[1],b[2],mm,mp,vp,&p2[0],&p2[1],&p2[2]);
189
float tickNum = spacing/Distance(p2,p1);// pxl spacing
190
float slope = dim*tickNum;
191
float nslope = math::Min(
192
math::Min(niceRound(slope), 0.5f*niceRound(2.0f*slope)),
193
0.2f*niceRound(5.0f*slope));
194
nslope = math::Max<float>(niceRound(dim*.001f),nslope); // prevent too small slope
198
float CoordinateFrame::niceRound(float val)
200
return powf(10.f,ceil(log10(val)));
203
MovableCoordinateFrame::MovableCoordinateFrame(float size)
204
:CoordinateFrame(size),position(0,0,0),rotation(0,Point3f(1,0,0))
209
void MovableCoordinateFrame::Render(QGLWidget* gla)
213
glTranslate(position);
215
rotation.ToMatrix(mrot);
217
glMultMatrix(Inverse(mrot));
219
CoordinateFrame::Render(gla);
224
void MovableCoordinateFrame::GetTransform(Matrix44f & transform)
226
// build the matrix that moves points in world coordinates
229
transform.SetIdentity();
233
rotation.ToMatrix(rot);
235
transform = Inverse(rot) * transform ;
239
pos.SetTranslate(position);
241
transform = pos * transform;
245
void MovableCoordinateFrame::Reset(bool reset_position,bool reset_alignment)
248
position = Point3f(0,0,0);
250
rotation = Quaternionf(0,Point3f(1,0,0));
253
void MovableCoordinateFrame::SetPosition(const Point3f newpos)
258
void MovableCoordinateFrame::SetRotation(const Quaternionf newrot)
263
Point3f MovableCoordinateFrame::GetPosition()
268
Quaternionf MovableCoordinateFrame::GetRotation()
273
void MovableCoordinateFrame::Rot(float angle_deg,const Point3f axis)
276
s.SetRotate(math::ToRad(angle_deg),(rotation).Rotate(axis));
280
void MovableCoordinateFrame::AlignWith(const Point3f pri,const Point3f secondary,const char c1, const char c2)
282
const float EPSILON=1e-6f;
285
if( primary.Norm() < EPSILON*size )
289
Plane3f plane(0,primary); // projection plane for the second rotation
291
Point3f x(1,0,0),y(0,1,0),z(0,0,1);
292
Point3f first(0,0,0),second(0,0,0),third(0,0,0);
294
if(c1=='X'){ first = x;
295
if((c2=='Y')||(c2==' ')){ second = y; third = z; }
296
else if(c2=='Z'){ second = z; third = y; }
298
} else if(c1=='Y'){ first = y;
299
if((c2=='Z')||(c2==' ')){ second = z; third = x; }
300
else if(c2=='X'){ second = x; third = z; }
302
} else if(c1=='Z'){ first = z;
303
if((c2=='X')||(c2==' ')){ second = x; third = y; }
304
else if(c2=='Y'){ second = y; third = x; }
308
Point3f old_first = Inverse(rotation).Rotate(first); // axis 1
309
Point3f old_second_pro = plane.Projection(Inverse(rotation).Rotate(second)); // axis 2 projection
310
Point3f old_third_pro = plane.Projection(Inverse(rotation).Rotate(third)); // axis 3 projection
312
// align axis 1 to primary
313
RotateToAlign(old_first,primary);
315
Point3f secondary_pro = plane.Projection(secondary); // secondary's projection
316
Point3f new_second_pro = plane.Projection(Inverse(rotation).Rotate(second)); // axis 2 projection after the first rotation
318
if( secondary.Norm() > EPSILON*size && secondary_pro.Norm() > EPSILON ){ // secondary is not null nor parallel to primary
319
// align axis 2 projection after the first rotation to secondary's projection
320
secondary_pro.Normalize();
321
RotateToAlign(new_second_pro,secondary_pro);
325
if ( old_second_pro.Norm() > EPSILON ) { // can realign axis 2
326
// align axis 2 projection after the first rotation to old axis 2 projection
327
old_second_pro.Normalize();
328
RotateToAlign(new_second_pro,old_second_pro);
333
Point3f new_third_pro = plane.Projection(Inverse(rotation).Rotate(third));// axis 3 projection after the first rotation
334
assert(old_third_pro.Norm() > EPSILON ); // old axis 3 projection should not be null
335
// align axis 3 projection after the first rotation to old axis 3 projection
336
old_third_pro.Normalize();
337
RotateToAlign(new_third_pro,old_third_pro);
340
void MovableCoordinateFrame::Move(const Similarityf track)
342
position = position + track.tra;
343
rotation = rotation * Inverse(track.rot);
346
void MovableCoordinateFrame::RotateToAlign(const Point3f source, const Point3f dest)
348
const float EPSILON=1e-6f;
349
// source and dest must be versors
350
assert( math::Abs(source.Norm() - 1) < EPSILON);
351
assert( math::Abs(dest.Norm() - 1) < EPSILON);
353
Point3f axis = dest ^ source;
354
float sinangle = axis.Norm();
355
float cosangle = dest.dot(source);
356
float angle = math::Atan2(sinangle,cosangle);
358
if( math::Abs(angle) < EPSILON )
359
return; // angle ~ 0, aborting
361
if( math::Abs(math::Abs(angle)-M_PI) < EPSILON){
362
// must find a axis to flip on
363
Plane3f plane(0,source);
364
axis=plane.Projection(Point3f(1,0,0)); // project a "random" point on source's normal plane
365
if(axis.Norm() < EPSILON){ // source was ~ [1,0,0]...
366
axis=plane.Projection(Point3f(0,1,0));
367
assert(axis.Norm() > EPSILON); // this point must be good
370
rotation = rotation * Quaternionf(angle,axis);