Developer Documentation

ManipulatorNode.cc
1 /*===========================================================================*\
2 * *
3 * OpenFlipper *
4 * Copyright (c) 2001-2015, RWTH-Aachen University *
5 * Department of Computer Graphics and Multimedia *
6 * All rights reserved. *
7 * www.openflipper.org *
8 * *
9 *---------------------------------------------------------------------------*
10 * This file is part of OpenFlipper. *
11 *---------------------------------------------------------------------------*
12 * *
13 * Redistribution and use in source and binary forms, with or without *
14 * modification, are permitted provided that the following conditions *
15 * are met: *
16 * *
17 * 1. Redistributions of source code must retain the above copyright notice, *
18 * this list of conditions and the following disclaimer. *
19 * *
20 * 2. Redistributions in binary form must reproduce the above copyright *
21 * notice, this list of conditions and the following disclaimer in the *
22 * documentation and/or other materials provided with the distribution. *
23 * *
24 * 3. Neither the name of the copyright holder nor the names of its *
25 * contributors may be used to endorse or promote products derived from *
26 * this software without specific prior written permission. *
27 * *
28 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *
29 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *
30 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
31 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER *
32 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, *
33 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, *
34 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR *
35 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
36 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING *
37 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS *
38 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
39 * *
40 \*===========================================================================*/
41
42
43
44
45
46
47 //=============================================================================
48 //
49 // CLASS ManipulatorNode - IMPLEMENTATION
50 //
51 //=============================================================================
52
53
54 //== INCLUDES =================================================================
55
56
57 #include "ManipulatorNode.hh"
58
59 //== NAMESPACES ===============================================================
60
61
62 namespace ACG {
63 namespace SceneGraph {
64
65
66 //== IMPLEMENTATION ==========================================================
67
68
69 const Vec4f cylinder_color (0.8f, 0.4f, 0.4f, 1.0f);
70 const Vec4f sphere_color (0.8f, 0.4f, 0.4f, 1.0f);
71 const Vec4f select_color (1.0f, 0.1f, 0.1f, 1.0f);
72 const float SCALE_CONST = 5.0f;
73
74
75 //----------------------------------------------------------------------------
76
77
78 ManipulatorNode::
79 ManipulatorNode( BaseNode* _parent, const std::string& _name )
80 : TransformNode(_parent, _name),
81 draw_cylinder_(false),
82 direction_(1.0,0.0,0.0),
83 cylinder_(0),
84 cylinder_radius_(1),
85 cylinder_height_(10),
86 cylinder_slices_(30),
87 cylinder_stacks_(10),
88 cylinder_clicked_(false),
89 sphere_clicked_(false),
90 touched_(false)
91 {
92 }
93
94
95 //----------------------------------------------------------------------------
96
97
98 ManipulatorNode::
99 ~ManipulatorNode()
100 {
101 if (cylinder_)
102 delete cylinder_;
103 }
104
105
106 //----------------------------------------------------------------------------
107
108
109 void
110 ManipulatorNode::
111 setIdentity()
112 {
113 direction_ = rotation().transform_vector( direction_ );
114 TransformNode::setIdentity();
115 }
116
117
118 //----------------------------------------------------------------------------
119
120
121 void
122 ManipulatorNode::
123 setup_cylinder_system(GLState& _state)
124 {
125 _state.translate(center()[0], center()[1], center()[2]);
126 _state.mult_matrix(inverse_scale (), scale ()); // Adapt scaling
127
128 // rotation axis & angle
129 Vec3d z(0.0, 0.0, 1.0);
130 double scal_prod = (direction_ | z);
131 Vec3d axis = z % direction_;
132 double norm = axis.norm();
133 double angle;
134
135 if (norm > FLT_MIN)
136 {
137 axis /= norm;
138 if (scal_prod > 1.0) scal_prod = 1.0;
139 if (scal_prod < -1.0) scal_prod = -1.0;
140 angle = 180.0 / M_PI * acos(scal_prod);
141 }
142 else
143 {
144 axis = Vec3d(1.0, 0.0, 0.0);
145 angle = (scal_prod > 0.0) ? 0.0 : 180.0;
146 }
147
148 _state.rotate(angle, axis[0], axis[1], axis[2]);
149 }
150
151
152 void
153 ManipulatorNode::
154 setup_sphere_system(GLState& _state)
155 {
156 setup_cylinder_system(_state);
157
158 _state.translate(0, 0, cylinder_height_+ 2*cylinder_radius_);
159 }
160
161
162 //----------------------------------------------------------------------------
163
164
165 void
166 ManipulatorNode::draw(GLState& _state, const DrawModes::DrawMode& /* _drawMode */ )
167 {
168 if (draw_cylinder_)
169 {
170 if(_state.compatibilityProfile())
171 {
172 ACG::GLState::enable(GL_LIGHTING);
173 ACG::GLState::shadeModel(GL_FLAT);
174 }
175
176
177 // backup colors
178 Vec4f backup_diffuse = _state.diffuse_color();
179 Vec4f backup_specular = _state.specular_color();
180
181
182 // draw cylinder
183
184 if (!cylinder_)
185 {
186 cylinder_ = new GLCylinder(cylinder_slices_, cylinder_stacks_, cylinder_radius_, false, false);
187 }
188
189 _state.push_modelview_matrix();
190 setup_cylinder_system(_state);
191
192 if( cylinder_clicked_)
193 {
194 _state.set_diffuse_color(select_color * 0.6f);
195 _state.set_specular_color(select_color * 0.8f);
196 }
197 else
198 {
199 _state.set_diffuse_color(cylinder_color * 0.6f);
200 _state.set_specular_color(cylinder_color * 0.8f);
201 }
202
203 // Zylinder in die X-Achse
204 /*glPushMatrix();
205 glLoadIdentity();
206 glRotatef(-90, 0.0, 1.0, 0.0);*/
207
208 if(_state.compatibilityProfile())
209 ACG::GLState::shadeModel(GL_SMOOTH);
210 cylinder_->setBottomRadius(cylinder_radius_);
211 cylinder_->setTopRadius(cylinder_radius_);
212 cylinder_->draw(_state, cylinder_height_);
213
214 //glPopMatrix();
215
216
217 // BIG wireframe sphere
218 if( sphere_clicked_ )
219 {
220 _state.set_diffuse_color(select_color * 0.6f);
221 _state.set_specular_color(select_color * 0.0f);
222 if(_state.compatibilityProfile())
223 {
224 ACG::GLState::shadeModel(GL_SMOOTH);
225 GLint previous[2];
226 glGetIntegerv(GL_POLYGON_MODE,previous);
227 glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
228 _state.scale(cylinder_height_+4*cylinder_radius_,cylinder_height_+4*cylinder_radius_,cylinder_height_+4*cylinder_radius_);
229 ACG::GLSphere sphere(20, 20);
230 sphere.draw_primitive();
231 glPolygonMode(GL_FRONT,previous[0]);
232 glPolygonMode(GL_BACK,previous[1]);
233 }
234 }
235
236 _state.pop_modelview_matrix();
237
238
239
240
241 // draw sphere
242
243 _state.push_modelview_matrix();
244 setup_sphere_system(_state);
245
246 if( sphere_clicked_)
247 {
248 _state.set_diffuse_color(select_color * 0.6f);
249 _state.set_specular_color(select_color * 0.8f);
250 }
251 else
252 {
253 _state.set_diffuse_color(sphere_color * 0.6f);
254 _state.set_specular_color(sphere_color * 0.8f);
255 }
256
257 if(_state.compatibilityProfile())
258 {
259 ACG::GLState::shadeModel(GL_SMOOTH);
260 _state.scale(2*cylinder_radius_,2*cylinder_radius_,2*cylinder_radius_);
261 ACG::GLSphere sphere(20, 20);
262 sphere.draw_primitive();
263 }
264
265 _state.pop_modelview_matrix();
266
267
268
269
270 // restore
271 _state.set_diffuse_color(backup_diffuse);
272 _state.set_specular_color(backup_specular);
273 }
274 }
275
276
277 //----------------------------------------------------------------------------
278
279
280 void
281 ManipulatorNode::mouseEvent(GLState& _state, QMouseEvent* _event)
282 {
283 Vec3d oldPoint3D;
284 Vec2i newPoint2D(_event->pos().x(), _event->pos().y());
285 Vec3d newPoint3D;
286 double new_axis_hit;
287
288
289 switch (_event->type())
290 {
291 case QEvent::MouseButtonPress:
292 {
293 // hit sphere ?
294 sphere_clicked_ = hitSphere(_state, newPoint2D);
295
296 // hit cylinder ?
297 cylinder_clicked_ = mapToCylinder(_state, newPoint2D, new_axis_hit);
298
299 // If the user clicked on the manipulator, remember it
300 if ( sphere_clicked_ || cylinder_clicked_)
301 touched_ = true;
302
303 // select only sphere or cylinder
304 if(sphere_clicked_ && cylinder_clicked_)
305 cylinder_clicked_ = false;
306
307 oldPoint2D_ = newPoint2D;
308 break;
309 }
310
311
312 case QEvent::MouseButtonRelease:
313 {
314 sphere_clicked_ = false;
315 cylinder_clicked_ = false;
316 break;
317 }
318
319
320 case QEvent::MouseButtonDblClick:
321 {
322 draw_cylinder_ = !draw_cylinder_;
323 break;
324 }
325
326
327 case QEvent::MouseMove:
328 {
329 // IF sphere clicked rotate or change direction
330 if(sphere_clicked_)
331 {
332 bool hit0 = mapToSphere(_state, newPoint2D, newPoint3D);
333 bool hit1 = mapToSphere(_state, oldPoint2D_, oldPoint3D);
334
335
336 if (hit0 && hit1)
337 {
338 // change direction
339 if(_event->modifiers() & Qt::ShiftModifier)
340 {
341
342 // calculate new cylinder direction
343 direction_.normalize();
344 newPoint3D.normalize();
345 oldPoint3D.normalize();
346
347 direction_ += newPoint3D - oldPoint3D;
348
349 }
350 // rotate
351 else
352 {
353 Vec3d axis = oldPoint3D % newPoint3D;
354 double cos_angle = ( oldPoint3D | newPoint3D );
355
356 if (fabs(cos_angle) < 1.0)
357 rotate(acos(cos_angle)*180.0/M_PI, axis);
358 }
359 }
360 else sphere_clicked_ = false;
361 }
362
363
364 // cylinder clicked change scaling or change translation
365 if(cylinder_clicked_)
366 {
367 double old_axis_hit;
368
369 mapToCylinder(_state, oldPoint2D_, old_axis_hit);
370 mapToCylinder(_state, newPoint2D, new_axis_hit);
371
372 // scale
373 if(_event->modifiers() & Qt::ShiftModifier)
374 {
375 scale(1.0 + (new_axis_hit - old_axis_hit) /
376 (cylinder_height_ * SCALE_CONST));
377 }
378
379 // twist
380 else if(_event->modifiers() & (Qt::ControlModifier |
381 Qt::AltModifier))
382 {
383 rotate( 45.0 * (new_axis_hit-old_axis_hit) / cylinder_height_,
384 direction_);
385
386 }
387
388 // translate
389 else
390 {
391 translate(new_axis_hit - old_axis_hit);
392 }
393 }
394
395 break;
396 }
397
398 default: // avoid warning
399 break;
400 }
401
402
403 // save old Point
404 oldPoint2D_ = newPoint2D;
405 }
406
407
408 //----------------------------------------------------------------------------
409
410
411 bool ManipulatorNode::hitSphere( GLState& _state,
412 const Vec2i& _v2)
413 {
414 // Qt -> GL coordinate systems
415 unsigned int x = _v2[0];
416 unsigned int y = _state.context_height() - _v2[1];
417
418
419 // get ray from eye through pixel, in sphere coords
420 Vec3d origin, direction;
421
422 _state.set_updateGL(false);
423 _state.push_modelview_matrix();
424
425 setup_sphere_system(_state);
426 _state.scale(2*cylinder_radius_);
427
428 _state.viewing_ray(x, y, origin, direction);
429
430 _state.pop_modelview_matrix();
431 _state.set_updateGL(true);
432
433
434
435 // calc sphere-ray intersection
436 // (sphere is centered at origin, has radius 1)
437 double a = direction.sqrnorm(),
438 b = 2.0 * (origin | direction),
439 c = origin.sqrnorm() - 1.0,
440 d = b*b - 4.0*a*c;
441
442 return (d >= 0.0);
443 }
444
445
446 //----------------------------------------------------------------------------
447
448
449 bool
450 ManipulatorNode::mapToSphere( GLState& _state,
451 const Vec2i& _v2,
452 Vec3d& _v3 )
453 {
454 // Qt -> GL coordinate systems
455 unsigned int x = _v2[0];
456 unsigned int y = _state.context_height() - _v2[1];
457
458
459
460 // get ray from eye through pixel (trackball coords)
461 // *no* rotation, points have to be in world coords
462 Vec3d origin, direction;
463
464 _state.set_updateGL(false);
465 _state.push_modelview_matrix();
466
467 _state.translate(center()[0], center()[1], center()[2]);
468 _state.mult_matrix(inverse_scale (), scale ());
469 _state.scale(cylinder_height_ + 4*cylinder_radius_);
470
471 _state.viewing_ray(x, y, origin, direction);
472
473 _state.pop_modelview_matrix();
474 _state.set_updateGL(true);
475
476
477
478 // calc sphere-ray intersection
479 // (sphere is centered at origin, has radius 1)
480 double a = direction.sqrnorm(),
481 b = 2.0 * (origin | direction),
482 c = origin.sqrnorm() - 1.0,
483 d = b*b - 4.0*a*c,
484 t;
485
486 if (d < 0.0) return false;
487 else if (d == 0.0) t = -b / (2.0*a);
488 else
489 {
490 a = 1.0 / (2.0*a);
491 d = sqrt(d);
492 double t1 = (-b - d) * a;
493 double t2 = (-b + d) * a;
494 t = (t1 < t2) ? t1 : t2;
495 }
496
497
498
499 // map back to world coords
500 _v3 = origin + direction*t;
501
502 return true;
503 }
504
505
506 //----------------------------------------------------------------------------
507
508
509 bool
510 ManipulatorNode::mapToCylinder(GLState& _state,
511 const Vec2i& _v1,
512 double& _axis_hit)
513 {
514 // Qt -> GL coordinate systems
515 unsigned int x = _v1[0];
516 unsigned int y = _state.context_height() - _v1[1];
517
518
519 // get ray from eye through pixel (cylinder coords)
520 Vec3d origin, direction;
521
522 _state.set_updateGL(false);
523 _state.push_modelview_matrix();
524
525 setup_cylinder_system(_state);
526
527 _state.viewing_ray(x, y, origin, direction);
528
529 _state.pop_modelview_matrix();
530 _state.set_updateGL(true);
531
532
533
534 // get cylinder axis ray: it's in its own coord system!
535 const Vec3d origin2(0,0,0), direction2(0,0,1);
536
537
538 // compute pseude-intersection
539 Vec3d normal = (direction % direction2).normalize();
540 Vec3d vd = ((origin2 - origin) % direction);
541 _axis_hit = (normal | vd);
542
543 double orthodistance = std::abs( ( origin2 - origin ) | normal);
544
545
546 // hit cylinder ?
547 return((orthodistance < cylinder_radius_) &&
548 (_axis_hit >= 0) &&
549 (_axis_hit <= cylinder_height_));
550 }
551
552
553 //----------------------------------------------------------------------------
554
555
556 void ManipulatorNode::pick(GLState& _state, PickTarget _target) {
557 if (_target == PICK_FACE || _target == PICK_ANYTHING) {
558 if (draw_cylinder_) {
559
560 _state.pick_set_maximum(2);
561
562 // cylinder
563 _state.push_modelview_matrix();
564 setup_cylinder_system(_state);
565 _state.pick_set_name(0);
566 cylinder_->setBottomRadius(cylinder_radius_);
567 cylinder_->setTopRadius(cylinder_radius_);
568 cylinder_->draw(_state, cylinder_height_);
569 _state.pop_modelview_matrix();
570
571 // sphere
572 _state.push_modelview_matrix();
573 setup_sphere_system(_state);
574 _state.pick_set_name(1);
575 if(_state.compatibilityProfile()) {
576 _state.scale(2*cylinder_radius_,2*cylinder_radius_,2*cylinder_radius_);
577 ACG::GLSphere sphere(20, 20);
578 sphere.draw_primitive();
579 }
580 _state.pop_modelview_matrix();
581 }
582 }
583 }
584
585
586 //----------------------------------------------------------------------------
587
588
589 void
590 ManipulatorNode::set_direction(Vec3d& _v)
591 {
592 direction_ = inverse_rotation().transform_vector(_v.normalize());
593 }
594
595 //----------------------------------------------------------------------------
596
597 Vec3d
598 ManipulatorNode::direction() const
599 {
600 return rotation().transform_vector(direction_);
601 }
602
603
604
605 //=============================================================================
606 } // namespace SceneGraph
607 } // namespace ACG
608 //=============================================================================
ACG::GLState::specular_color
const Vec4f & specular_color() const
get specular color
Definition: GLState.hh:941
ACG::SceneGraph::ManipulatorNode::set_direction
void set_direction(Vec3d &_v)
Definition: ManipulatorNode.cc:590
ACG
Namespace providing different geometric functions concerning angles.
Definition: BaseObjectData.hh:68
ACG::SceneGraph::TransformNode::inverse_scale
const GLMatrixd & inverse_scale() const
return inverse scale matrix
Definition: TransformNode.hh:185
ACG::SceneGraph::ManipulatorNode::setIdentity
virtual void setIdentity()
Definition: ManipulatorNode.cc:111
ACG::GLState::set_specular_color
void set_specular_color(const Vec4f &_col)
set specular color
Definition: GLState.cc:737
ACG::SceneGraph::PICK_ANYTHING
pick any of the prior targets (should be implemented for all nodes)
Definition: PickTarget.hh:84
OpenMesh::VectorT::norm
auto norm() const -> decltype(std::sqrt(std::declval< VectorT< S, DIM >>().sqrnorm()))
compute euclidean norm
Definition: Vector11T.hh:409
ACG::GLState::set_diffuse_color
void set_diffuse_color(const Vec4f &_col)
set diffuse color
Definition: GLState.cc:722
OpenMesh::VectorT::sqrnorm
decltype(std::declval< S >() *std::declval< S >()) sqrnorm() const
compute squared euclidean norm
Definition: Vector11T.hh:397
ACG::GLState::push_modelview_matrix
void push_modelview_matrix()
push modelview matrix
Definition: GLState.cc:1010
ACG::GLState::set_updateGL
void set_updateGL(bool _b)
should GL matrices be updated after each matrix operation
Definition: GLState.hh:235
ACG::SceneGraph::ACG::GLState::enable
static void enable(GLenum _cap, bool _warnRemoved=true)
replaces glEnable, but supports locking
ACG::GLState::context_height
int context_height() const
get gl context height
Definition: GLState.hh:830
ACG::SceneGraph::ManipulatorNode::~ManipulatorNode
~ManipulatorNode()
Destructor.
Definition: ManipulatorNode.cc:99
ACG::SceneGraph::TransformNode::scale
const GLMatrixd & scale() const
return scale matrix
Definition: TransformNode.hh:181
ACG::GLState::translate
void translate(double _x, double _y, double _z, MultiplyFrom _mult_from=MULT_FROM_RIGHT)
translate by (_x, _y, _z)
Definition: GLState.cc:533
ACG::GLCylinder
Definition: GLPrimitives.hh:218
OpenMesh::VectorT::normalize
auto normalize() -> decltype(*this/=std::declval< VectorT< S, DIM >>().norm())
Definition: Vector11T.hh:429
ACG::SceneGraph::ManipulatorNode::translate
void translate(double _s)
translate in cylinder direction
Definition: ManipulatorNode.hh:133
ACG::SceneGraph::TransformNode::rotate
void rotate(double _angle, const Vec3d &_axis)
Definition: TransformNode.cc:148
ACG::SceneGraph::ManipulatorNode::touched_
bool touched_
if the manipulator is cklicked with a mouse, this flag will be set to true
Definition: ManipulatorNode.hh:186
ACG::GLState
Definition: GLState.hh:213
ACG::SceneGraph::ManipulatorNode::direction
Vec3d direction() const
Definition: ManipulatorNode.cc:598
ACG::SceneGraph::TransformNode::inverse_rotation
const GLMatrixd & inverse_rotation() const
return inverse rotation matrix
Definition: TransformNode.hh:172
ACG::GLState::mult_matrix
void mult_matrix(const GLMatrixd &_m, const GLMatrixd &_inv_m, MultiplyFrom _mult_from=MULT_FROM_RIGHT)
multiply by a given transformation matrix
Definition: GLState.cc:614
ACG::Vec3d
VectorT< double, 3 > Vec3d
Definition: VectorT.hh:121
ACG::SceneGraph::TransformNode::setIdentity
virtual void setIdentity()
Definition: TransformNode.cc:112
ACG::SceneGraph::ACG::GLState::shadeModel
static void shadeModel(GLenum _mode)
replaces glShadeModel, supports locking
ACG::SceneGraph::ManipulatorNode::pick
void pick(GLState &_state, PickTarget _target)
picking
Definition: ManipulatorNode.cc:556
ACG::SceneGraph::ManipulatorNode::ManipulatorNode
ManipulatorNode(BaseNode *_parent=0, const std::string &_name="<ManipulatorNode>")
Default constructor.
Definition: ManipulatorNode.cc:79
ACG::GLSphere
Definition: GLPrimitives.hh:139
ACG::GLState::viewing_ray
void viewing_ray(int _x, int _y, Vec3d &_origin, Vec3d &_direction) const
Definition: GLState.cc:930
ACG::SceneGraph::DrawModes::DrawMode
Specifies a DrawMode.
Definition: DrawModes.hh:288
ACG::SceneGraph::TransformNode::rotation
const GLMatrixd & rotation() const
return rotation matrix
Definition: TransformNode.hh:168
SceneGraph
Definition: QtPrincipalAxisDialog.hh:67
ACG::SceneGraph::PickTarget
PickTarget
What target to use for picking.
Definition: PickTarget.hh:73
ACG::GLState::rotate
void rotate(double _angle, double _x, double _y, double _z, MultiplyFrom _mult_from=MULT_FROM_RIGHT)
rotate around axis (_x, _y, _z) by _angle
Definition: GLState.cc:564
ACG::SceneGraph::BaseNode
Definition: BaseNode.hh:104
ACG::GLState::pop_modelview_matrix
void pop_modelview_matrix()
pop modelview matrix
Definition: GLState.cc:1026
OpenMesh::VectorT< float, 4 >
ACG::GLState::scale
void scale(double _s)
scale by (_s, _s, _s)
Definition: GLState.hh:750
ACG::SceneGraph::ManipulatorNode::mouseEvent
virtual void mouseEvent(GLState &_state, QMouseEvent *_event)
get mouse events
Definition: ManipulatorNode.cc:281
ACG::SceneGraph::PICK_FACE
picks faces (should be implemented for all nodes)
Definition: PickTarget.hh:78
ACG::SceneGraph::ManipulatorNode::draw
void draw(GLState &_state, const DrawModes::DrawMode &_drawMode)
draw the cylinder (if enabled)
Definition: ManipulatorNode.cc:166
ACG::GLState::diffuse_color
const Vec4f & diffuse_color() const
get diffuse color
Definition: GLState.hh:936
ACG::Matrix4x4T::transform_vector
VectorT< T, 3 > transform_vector(const VectorT< T, 3 > &_v) const
transform vector (x&#39;,y&#39;,z&#39;,0) = A * (x,y,z,0)
Definition: Matrix4x4T_impl.hh:219
ACG::SceneGraph::TransformNode::center
const Vec3d & center() const
get center
Definition: TransformNode.hh:115
ACG::GLState::pick_set_maximum
bool pick_set_maximum(size_t _idx)
Set the maximal number of primitives/components of your object.
Definition: GLState.cc:1051
ACG::SceneGraph::TransformNode
Definition: TransformNode.hh:89
ACG::GLState::pick_set_name
void pick_set_name(size_t _idx)
sets the current name/color (like glLoadName(_idx))
Definition: GLState.cc:1061