~ubuntu-branches/ubuntu/natty/meshlab/natty

« back to all changes in this revision

Viewing changes to vcglib/wrap/gui/coordinateframe.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Teemu Ikonen
  • Date: 2009-05-27 18:07:15 UTC
  • Revision ID: james.westby@ubuntu.com-20090527180715-xv4sqfs9skj5y74h
Tags: upstream-1.2.1
ImportĀ upstreamĀ versionĀ 1.2.1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/****************************************************************************
 
2
 * MeshLab                                                           o o     *
 
3
 * A versatile mesh processing toolbox                             o     o   *
 
4
 *                                                                _   O  _   *
 
5
 * Copyright(C) 2008                                                \/)\/    *
 
6
 * Visual Computing Lab                                            /\/|      *
 
7
 * ISTI - Italian National Research Council                           |      *
 
8
 *                                                                    \      *
 
9
 * All rights reserved.                                                      *
 
10
 *                                                                           *
 
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.                                       *
 
15
 *                                                                           *
 
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)          *
 
20
 * for more details.                                                         *
 
21
 *                                                                           *
 
22
 ****************************************************************************/
 
23
/****************************************************************************
 
24
  History
 
25
$Log: not supported by cvs2svn $
 
26
Revision 1.8  2008/03/02 16:44:18  benedetti
 
27
moved ActiveCoordinateFrame to its own files
 
28
 
 
29
Revision 1.7  2008/02/26 18:22:42  benedetti
 
30
corrected after quaternion/similarity/trackball changes
 
31
 
 
32
Revision 1.6  2008/02/22 20:34:35  benedetti
 
33
corrected typo
 
34
 
 
35
Revision 1.5  2008/02/22 20:04:02  benedetti
 
36
many user interface improvements, cleaned up a little
 
37
 
 
38
Revision 1.4  2008/02/17 20:52:53  benedetti
 
39
some generalization made
 
40
 
 
41
Revision 1.3  2008/02/16 14:12:30  benedetti
 
42
first version
 
43
 
 
44
 
 
45
****************************************************************************/
 
46
 
 
47
#include <GL/glew.h>
 
48
#include <wrap/gl/math.h>
 
49
#include <wrap/gl/space.h>
 
50
#include <wrap/gl/addons.h>
 
51
 
 
52
#include "coordinateframe.h"
 
53
 
 
54
using namespace vcg;
 
55
 
 
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)
 
60
{
 
61
  font.setFamily("Helvetica");
 
62
}
 
63
 
 
64
void CoordinateFrame::Render(QGLWidget* glw)
 
65
{
 
66
  assert( glw!= NULL);
 
67
  glPushAttrib(GL_ALL_ATTRIB_BITS);
 
68
  glDisable(GL_LIGHTING);
 
69
  glDisable(GL_TEXTURE_2D);
 
70
  glEnable(GL_BLEND);
 
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);
 
76
 
 
77
  Point3d o(0,0,0);
 
78
  Point3d a(size,0,0);
 
79
  Point3d b(0,size,0);
 
80
  Point3d c(0,0,size);
 
81
  // Get gl state values
 
82
  double mm[16],mp[16];
 
83
  GLint vp[4];
 
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;
 
91
  if(drawaxis){
 
92
    glBegin(GL_LINES);
 
93
      glColor(xcolor);
 
94
      glVertex(-a); glVertex(a);
 
95
      glColor(ycolor);
 
96
      glVertex(-b); glVertex(b);
 
97
      glColor(zcolor);
 
98
      glVertex(-c); glVertex(c);
 
99
    glEnd();
 
100
    glColor(basecolor);
 
101
    // positive axes
 
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
 
105
    // negative axes
 
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
 
109
    glPushMatrix();
 
110
      glTranslate(a);
 
111
      glScalef(scalefactor,scalefactor,scalefactor);
 
112
      Add_Ons::Cone(10,linewidth*1.5,linewidth*0.5,true);
 
113
    glPopMatrix();
 
114
    glPushMatrix();
 
115
      glTranslate(b);
 
116
      glRotatef(90,0,0,1);
 
117
      glScalef(scalefactor,scalefactor,scalefactor);
 
118
      Add_Ons::Cone(10,linewidth*1.5,linewidth*0.5,true);
 
119
    glPopMatrix();
 
120
    glPushMatrix();
 
121
      glTranslate(c);
 
122
      glRotatef(-90,0,1,0);
 
123
      glScalef(scalefactor,scalefactor,scalefactor);
 
124
      Add_Ons::Cone(10,linewidth*1.5,linewidth*0.5,true);
 
125
    glPopMatrix();
 
126
  }
 
127
  if(drawlabels){
 
128
        font.setBold(true);
 
129
    font.setPixelSize(12);
 
130
    float d=size+scalefactor*linewidth*1.5;
 
131
    glColor(xcolor);
 
132
    glw->renderText(d,0,0,QString("X"),font);
 
133
    glColor(ycolor);
 
134
    glw->renderText(0,d,0,QString("Y"),font);
 
135
    glColor(zcolor);
 
136
    glw->renderText(0,0,d,QString("Z"),font);
 
137
  }  
 
138
  if(drawvalues){
 
139
        font.setBold(false);    
 
140
    font.setPixelSize(8);
 
141
    float i;
 
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);
 
146
    }
 
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);
 
150
    }
 
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);
 
154
    }
 
155
  }
 
156
  
 
157
  glPopAttrib();
 
158
  assert(!glGetError());  
 
159
}
 
160
 
 
161
void CoordinateFrame::drawTickedLine(const Point3d &a,const Point3d &b, float dim,float tickDist,float linewidth)
 
162
{
 
163
  Point3d v(b-a);
 
164
  v = v /dim; // normalize without computing square roots and powers
 
165
 
 
166
  glBegin(GL_POINTS);
 
167
  float i;
 
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]);
 
170
  glEnd();
 
171
 
 
172
  glPushAttrib(GL_POINT_BIT);
 
173
  glPointSize(linewidth*3);  
 
174
  glBegin(GL_POINTS);
 
175
       glVertex3f(a[0] + dim*v[0],a[1] + dim*v[1],a[2] + dim*v[2]);
 
176
  glEnd();
 
177
 
 
178
  glPopAttrib();
 
179
}
 
180
 
 
181
float CoordinateFrame::calcSlope(const Point3d &a,const Point3d &b,float dim,int spacing,double *mm,double *mp,GLint *vp)
 
182
{
 
183
   Point3d p1,p2;
 
184
 
 
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]);
 
187
  p1[2]=p2[2]=0;
 
188
 
 
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
 
195
  return nslope;
 
196
}
 
197
 
 
198
float CoordinateFrame::niceRound(float val)
 
199
{
 
200
  return powf(10.f,ceil(log10(val)));
 
201
}
 
202
 
 
203
MovableCoordinateFrame::MovableCoordinateFrame(float size)
 
204
:CoordinateFrame(size),position(0,0,0),rotation(0,Point3f(1,0,0))
 
205
{
 
206
  // nothing here
 
207
}
 
208
 
 
209
void MovableCoordinateFrame::Render(QGLWidget* gla)
 
210
{
 
211
  glPushMatrix();
 
212
  
 
213
  glTranslate(position);  
 
214
  Matrix44f mrot; 
 
215
  rotation.ToMatrix(mrot);
 
216
 
 
217
  glMultMatrix(Inverse(mrot));
 
218
  
 
219
  CoordinateFrame::Render(gla);
 
220
  
 
221
  glPopMatrix();
 
222
}
 
223
 
 
224
void MovableCoordinateFrame::GetTransform(Matrix44f & transform)
 
225
{
 
226
  // build the matrix that moves points in world coordinates
 
227
 
 
228
  // clean transform
 
229
  transform.SetIdentity();
 
230
 
 
231
  // apply rotation
 
232
  Matrix44f rot;
 
233
  rotation.ToMatrix(rot);
 
234
 
 
235
  transform = Inverse(rot) * transform ;
 
236
  
 
237
  // apply translation
 
238
  Matrix44f pos;
 
239
  pos.SetTranslate(position);
 
240
  
 
241
  transform = pos * transform;
 
242
  
 
243
}
 
244
 
 
245
void MovableCoordinateFrame::Reset(bool reset_position,bool reset_alignment)
 
246
{
 
247
  if(reset_position)
 
248
    position = Point3f(0,0,0);
 
249
  if(reset_alignment)
 
250
    rotation = Quaternionf(0,Point3f(1,0,0));
 
251
}
 
252
 
 
253
void MovableCoordinateFrame::SetPosition(const Point3f newpos)
 
254
{
 
255
  position = newpos;
 
256
}
 
257
 
 
258
void MovableCoordinateFrame::SetRotation(const Quaternionf newrot)
 
259
{
 
260
  rotation = newrot;
 
261
}
 
262
 
 
263
Point3f MovableCoordinateFrame::GetPosition()
 
264
{
 
265
  return position;
 
266
}
 
267
 
 
268
Quaternionf MovableCoordinateFrame::GetRotation()
 
269
{
 
270
  return rotation;
 
271
}
 
272
 
 
273
void MovableCoordinateFrame::Rot(float angle_deg,const Point3f axis)
 
274
{
 
275
  Similarityf s;
 
276
        s.SetRotate(math::ToRad(angle_deg),(rotation).Rotate(axis));
 
277
  Move(s);
 
278
}
 
279
 
 
280
void MovableCoordinateFrame::AlignWith(const Point3f pri,const Point3f secondary,const char c1, const char c2)
 
281
{
 
282
  const float EPSILON=1e-6f;
 
283
  Point3f primary=pri;
 
284
 
 
285
  if( primary.Norm() < EPSILON*size )
 
286
    return;
 
287
 
 
288
  primary.Normalize();
 
289
  Plane3f plane(0,primary); // projection plane for the second rotation
 
290
   
 
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);
 
293
 
 
294
  if(c1=='X'){ first = x;
 
295
    if((c2=='Y')||(c2==' ')){ second = y; third = z; } 
 
296
    else if(c2=='Z'){ second = z; third = y; } 
 
297
    else assert (0);
 
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; }
 
301
    else assert (0);
 
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; }
 
305
    else assert (0);   
 
306
  } else assert (0);
 
307
 
 
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
 
311
 
 
312
  // align axis 1 to primary
 
313
  RotateToAlign(old_first,primary);
 
314
 
 
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
 
317
 
 
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);
 
322
    return;
 
323
  }
 
324
 
 
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);
 
329
    return;
 
330
  }
 
331
 
 
332
  // realign axis 3
 
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);
 
338
}
 
339
 
 
340
void MovableCoordinateFrame::Move(const Similarityf track)
 
341
{
 
342
  position = position + track.tra;
 
343
  rotation = rotation * Inverse(track.rot);
 
344
}
 
345
 
 
346
void MovableCoordinateFrame::RotateToAlign(const Point3f source, const Point3f dest)
 
347
{
 
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);
 
352
 
 
353
  Point3f axis = dest ^ source;
 
354
  float sinangle = axis.Norm();
 
355
  float cosangle = dest.dot(source);
 
356
  float angle = math::Atan2(sinangle,cosangle);  
 
357
 
 
358
  if( math::Abs(angle) < EPSILON )    
 
359
    return; // angle ~ 0, aborting
 
360
 
 
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
 
368
        }
 
369
  }
 
370
  rotation = rotation * Quaternionf(angle,axis);
 
371
}