Developer Documentation

TranslationManipulatorNode.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 TranslationManipulatorNode - IMPLEMENTATION
50 //
51 //=============================================================================
52
53
54 //== INCLUDES =================================================================
55
56
57 #include "TranslationManipulatorNode.hh"
58
59 #include <ACG/GL/IRenderer.hh>
60
61 #include <OpenMesh/Core/Geometry/MathDefs.hh>
62
63 #include <ACG/GL/GLPrimitives.hh>
64
65 //== NAMESPACES ===============================================================
66
67
68 namespace ACG {
69 namespace SceneGraph {
70
71
72 //== IMPLEMENTATION ==========================================================
73
74 // How many pixels should the cursor be away from the dragging center
75 // for the translation operation to affect the geometry's position
76 #define SNAP_PIXEL_TOLERANCE 30
77
78 // Node colors (normal, over, clicked, occluded normal, occluded over, occluded clicked)
79
80 const Vec4f colors[4][6] = {
81 // origin
82 {
83 // normal
84 Vec4f(0.2f,0.2f,0.2f,1.0f), Vec4f(0.5f,0.5f,0.5f,1.0f), Vec4f(0.8f,0.8f,0.8f,1.0f),
85 // occluded
86 Vec4f(0.2f,0.2f,0.2f,0.2f), Vec4f(0.5f,0.5f,0.5f,0.4f), Vec4f(0.8f,0.8f,0.8f,0.6f)
87 },
88 // X
89 {
90 // normal
91 Vec4f(0.2f,0.0f,0.0f,1.0f), Vec4f(0.5f,0.0f,0.0f,1.0f), Vec4f(0.8f,0.0f,0.0f,1.0f),
92 // occluded
93 Vec4f(0.3f,0.1f,0.1f,0.2f), Vec4f(0.5f,0.2f,0.2f,0.4f), Vec4f(0.8f,0.4f,0.4f,0.6f)
94 },
95 // Y
96 {
97 // normal
98 Vec4f(0.0f,0.2f,0.0f,1.0f), Vec4f(0.0f,0.5f,0.0f,1.0f), Vec4f(0.0f,0.8f,0.0f,1.0f),
99 // occluded
100 Vec4f(0.1f,0.3f,0.1f,0.2f), Vec4f(0.2f,0.5f,0.2f,0.4f), Vec4f(0.4f,0.8f,0.4f,0.6f)
101 },
102 // Z
103 {
104 // normal
105 Vec4f(0.0f,0.0f,0.2f,1.0f), Vec4f(0.0f,0.0f,0.5f,1.0f), Vec4f(0.0f,0.0f,0.8f,1.0f),
106 // occluded
107 Vec4f(0.1f,0.1f,0.3f,0.2f), Vec4f(0.2f,0.2f,0.5f,0.4f), Vec4f(0.4f,0.4f,0.8f,0.6f)
108 }
109 };
110
111
112 //----------------------------------------------------------------------------
113
114 TranslationManipulatorNode::Element::Element () :
115 active_target_color_ (0.0, 0.0, 0.0, 1.0),
116 active_current_color_ (0.0, 0.0, 0.0, 1.0),
117 inactive_target_color_ (0.0, 0.0, 0.0, 1.0),
118 inactive_current_color_ (0.0, 0.0, 0.0, 1.0),
119 clicked_ (false),
120 over_ (false)
121 {
122 }
123
124 //----------------------------------------------------------------------------
125
126 TranslationManipulatorNode::
127 TranslationManipulatorNode( BaseNode* _parent, const std::string& _name )
128 : TransformNode(_parent, _name),
129 touched_(false),
130 draw_manipulator_(false),
131 dirX_(1.0,0.0,0.0),
132 dirY_(0.0,1.0,0.0),
133 dirZ_(0.0,0.0,1.0),
134 axisBottom_(0),
135 axisCenter_(0),
136 axisTop_(0),
137 circle_(0),
138 sphere_(0),
139 manipulator_radius_(20.0),
140 manipulator_height_(20),
141 set_manipulator_radius_(1.0),
142 set_manipulator_height_(1.0),
143 manipulator_slices_(10),
144 manipulator_stacks_(10),
145 any_axis_clicked_(false),
146 any_top_clicked_(false),
147 outer_ring_clicked_(false),
148 any_axis_over_(false),
149 any_top_over_(false),
150 outer_ring_over_(false),
151 resize_current_ (0.0),
152 mode_ (TranslationRotation),
153 ignoreTime_ (false),
154 dragging_(false),
155 auto_size_(TranslationManipulatorNode::Never),
156 auto_size_length_(1.0),
157 activeRotations_(ALL_AXIS)
158 {
159 localTransformation_.identity();
160
161 // Create GLPrimitives
162 axisBottom_ = new ACG::GLCone(manipulator_slices_, manipulator_stacks_,
163 (1.0 - resize_current_) * manipulator_radius_,
164 (1.0 + resize_current_) * manipulator_radius_, false, true);
165 axisCenter_ = new ACG::GLCone(manipulator_slices_, manipulator_stacks_,
166 (1.0 - resize_current_) * manipulator_radius_,
167 (1.0 + resize_current_) * manipulator_radius_, false, true);
168 axisTop_ = new ACG::GLCone(manipulator_slices_, manipulator_stacks_,
169 (1.0 - resize_current_) * manipulator_radius_,
170 (1.0 + resize_current_) * manipulator_radius_, false, true);
171
172 sphere_ = new ACG::GLSphere(manipulator_slices_, manipulator_stacks_);
173 circle_ = new ACG::GLDisk(30, 30, 2.0f*manipulator_height_ - manipulator_height_/4.0f, 2.0f*manipulator_height_);
174
175 setTraverseMode( BaseNode::ChildrenFirst );
176
177 updateTargetColors ();
178 for (unsigned int i = 0; i < TranslationManipulatorNode::NumElements; i++)
179 {
180 element_[i].active_current_color_ = element_[i].active_target_color_;
181 element_[i].inactive_current_color_ = element_[i].inactive_target_color_;
182 }
183 /*
184 setMultipassNode(0);
185 multipassNodeSetActive(2,true);
186
187 setMultipassStatus(0);
188 multipassStatusSetActive(1,true);
189 multipassStatusSetActive(2,true);*/
190
191 }
192
193
194 //----------------------------------------------------------------------------
195
196 TranslationManipulatorNode::~TranslationManipulatorNode() {
197
198 delete axisBottom_;
199 delete axisCenter_;
200 delete axisTop_;
201
202 delete sphere_;
203
204 delete circle_;
205 }
206
207
208 //----------------------------------------------------------------------------
209
210
211 void
212 TranslationManipulatorNode::
213 setIdentity()
214 {
215 TransformNode::setIdentity();
216 }
217
218
219 //----------------------------------------------------------------------------
220 void
221 TranslationManipulatorNode::
222 update_manipulator_system(GLState& _state)
223 {
224 _state.translate(center()[0], center()[1], center()[2]); // Follow translation of parent node
225 _state.mult_matrix(inverse_scale (), scale ()); // Adapt scaling
226
227 update_rotation(_state);
228 updateSize (_state);
229 }
230
231 //----------------------------------------------------------------------------
232 // Local rotation of the manipulator
233 void
234 TranslationManipulatorNode::update_rotation(GLState& _state){
235
236 // Get global transformation
237 if(_state.compatibilityProfile())
238 glMatrixMode(GL_MODELVIEW);
239 GLMatrixd model = _state.modelview();
240
241 // revert global transformation as we want to use our own
242 model *= inverse_rotation();
243
244 // apply local transformation to adjust our coordinate system
245 model *= localTransformation_;
246
247 // And update current matrix
248 _state.set_modelview(model);
249
250 }
251
252 //----------------------------------------------------------------------------
253
254 void TranslationManipulatorNode::updateTargetColors ()
255 {
256 // reset all color to default values
257 element_[Origin].active_target_color_ = colors[0][0];
258 element_[XAxis].active_target_color_ = colors[1][0];
259 element_[YAxis].active_target_color_ = colors[2][0];
260 element_[ZAxis].active_target_color_ = colors[3][0];
261 element_[XTop].active_target_color_ = colors[1][0];
262 element_[YTop].active_target_color_ = colors[2][0];
263 element_[ZTop].active_target_color_ = colors[3][0];
264 element_[XRing].active_target_color_ = colors[1][0];
265 element_[YRing].active_target_color_ = colors[2][0];
266 element_[ZRing].active_target_color_ = colors[3][0];
267
268 element_[Origin].inactive_target_color_ = colors[0][3];
269 element_[XAxis].inactive_target_color_ = colors[1][3];
270 element_[YAxis].inactive_target_color_ = colors[2][3];
271 element_[ZAxis].inactive_target_color_ = colors[3][3];
272 element_[XTop].inactive_target_color_ = colors[1][3];
273 element_[YTop].inactive_target_color_ = colors[2][3];
274 element_[ZTop].inactive_target_color_ = colors[3][3];
275 element_[XRing].inactive_target_color_ = colors[1][3];
276 element_[YRing].inactive_target_color_ = colors[2][3];
277 element_[ZRing].inactive_target_color_ = colors[3][3];
278
279
280 // blending is enabled for ring so we have to set alpha correctly
281 element_[XRing].active_target_color_[3] = 1.0;
282 element_[YRing].active_target_color_[3] = 1.0;
283 element_[ZRing].active_target_color_[3] = 1.0;
284
285 // hide rings in resize mode
286 if (mode_ == Resize || mode_ == Place)
287 for (unsigned int i = 0; i < 3; i++)
288 {
289 element_[XRing + i].active_target_color_[3] = 0.0;
290 element_[XRing + i].inactive_target_color_[3] = 0.0;
291 }
292
293 // set colors according to current (clicked/over/none) state
294 if(element_[Origin].clicked_){
295 element_[Origin].active_target_color_ = colors[0][2];
296 element_[Origin].inactive_target_color_ = colors[0][5];
297 for (unsigned int i = 1; i < NumElements - 3; i++)
298 {
299 element_[i].active_target_color_ = (colors[0][2] * static_cast<float>(0.5) ) + (colors[((i-1)%3) + 1][2] * static_cast<float>(0.5));
300 element_[i].inactive_target_color_ = (colors[0][5] * static_cast<float>(0.5)) + (colors[((i-1)%3) + 1][5] * static_cast<float>(0.5) );
301 }
302 return;
303 } else if(element_[Origin].over_){
304 element_[Origin].active_target_color_ = colors[0][1];
305 element_[Origin].inactive_target_color_ = colors[0][4];
306 for (unsigned int i = 1; i < NumElements - 3; i++)
307 {
308 element_[i].active_target_color_ = (colors[0][1] * static_cast<float>(0.5)) + (colors[((i-1)%3) + 1][1] * static_cast<float>(0.5));
309 element_[i].inactive_target_color_ = (colors[0][4] * static_cast<float>(0.5)) + (colors[((i-1)%3) + 1][4] * static_cast<float>(0.5));
310 }
311 return;
312 }
313
314 for (unsigned int i = 0; i < 3; i++)
315 if (element_[i + XTop].clicked_)
316 {
317 element_[i + XTop].active_target_color_ = colors[i+1][2];
318 element_[i + XTop].inactive_target_color_ = colors[i+1][5];
319 if (mode_ != TranslationRotation)
320 {
321 element_[i + XAxis].active_target_color_ = colors[i+1][2];
322 element_[i + XAxis].inactive_target_color_ = colors[i+1][5];
323 }
324 if (mode_ != Resize) {
325 element_[i + XRing].active_target_color_ = colors[i+1][2];
326 element_[i + XRing].inactive_target_color_ = colors[i+1][5];
327 }
328 return;
329 } else if (element_[i + XTop].over_)
330 {
331 element_[i + XTop].active_target_color_ = colors[i+1][1];
332 element_[i + XTop].inactive_target_color_ = colors[i+1][4];
333 if (mode_ != TranslationRotation)
334 {
335 element_[i + XAxis].active_target_color_ = colors[i+1][1];
336 element_[i + XAxis].inactive_target_color_ = colors[i+1][4];
337 }
338 if (mode_ != Resize) {
339 element_[i + XRing].active_target_color_ = colors[i+1][1];
340 element_[i + XRing].inactive_target_color_ = colors[i+1][4];
341 }
342 return;
343 }
344
345 for (unsigned int i = 0; i < 3; i++)
346 if (element_[i + XAxis].clicked_)
347 {
348 element_[i + XTop].active_target_color_ = colors[i+1][2];
349 element_[i + XTop].inactive_target_color_ = colors[i+1][5];
350 element_[i + XAxis].active_target_color_ = colors[i+1][2];
351 element_[i + XAxis].inactive_target_color_ = colors[i+1][5];
352 if (mode_ == LocalRotation) {
353 element_[i + XRing].active_target_color_ = colors[i+1][2];
354 element_[i + XRing].inactive_target_color_ = colors[i+1][5];
355 }
356 return;
357 } else if (element_[i + XAxis].over_)
358 {
359 element_[i + XTop].active_target_color_ = colors[i+1][1];
360 element_[i + XTop].inactive_target_color_ = colors[i+1][4];
361 element_[i + XAxis].active_target_color_ = colors[i+1][1];
362 element_[i + XAxis].inactive_target_color_ = colors[i+1][4];
363 if (mode_ == LocalRotation) {
364 element_[i + XRing].active_target_color_ = colors[i+1][1];
365 element_[i + XRing].inactive_target_color_ = colors[i+1][4];
366 }
367 return;
368 }
369
370 if (mode_ != Resize) {
371 for (unsigned int i = 0; i < 3; i++) {
372 if (element_[i + XRing].clicked_)
373 {
374 element_[i + XRing].active_target_color_ = colors[i+1][2];
375 element_[i + XRing].inactive_target_color_ = colors[i+1][5];
376 return;
377 } else if (element_[i + XRing].over_)
378 {
379 element_[i + XRing].active_target_color_ = colors[i+1][1];
380 element_[i + XRing].inactive_target_color_ = colors[i+1][4];
381 return;
382 }
383 }
384 }
385
386 }
387
388 //----------------------------------------------------------------------------
389
390 bool TranslationManipulatorNode::updateCurrentColors (GLState& _state)
391 {
392 bool rv = false;
393
394 float value = (float)_state.msSinceLastRedraw () / 1000.0;
395
396 if (ignoreTime_)
397 {
398 value = 0;
399 ignoreTime_ = false;
400 }
401
402 for (unsigned int i = 0; i < NumElements; i++)
403 {
404 Vec4f diff = element_[i].active_target_color_ -
405 element_[i].active_current_color_;
406
407 for (unsigned int j = 0; j < 4; j++)
408 if (diff[j] > value)
409 diff[j] = value;
410 else if (diff[j] < -value)
411 diff[j] = -value;
412
413 element_[i].active_current_color_ += diff;
414
415 diff = element_[i].inactive_target_color_ -
416 element_[i].inactive_current_color_;
417
418 for (unsigned int j = 0; j < 4; j++)
419 if (diff[j] > value)
420 diff[j] = value;
421 else if (diff[j] < -value)
422 diff[j] = -value;
423
424 element_[i].inactive_current_color_ += diff;
425
426 rv |= element_[i].active_target_color_ != element_[i].active_current_color_ ||
427 element_[i].inactive_target_color_ != element_[i].inactive_current_color_;
428 }
429
430 float diff = ((mode_ == Resize) ? 1.0 : 0.0) - resize_current_;
431
432 if (diff > value)
433 diff = value;
434 else if (diff < -value)
435 diff = -value;
436
437 resize_current_ += diff;
438 rv |= resize_current_ != ((mode_ == Resize) ? 1.0 : 0.0);
439
440 return rv;
441 }
442
443 //----------------------------------------------------------------------------
444
445 void TranslationManipulatorNode::drawManipulator (GLState& _state, bool _active)
446 {
447 glPushAttrib(GL_ENABLE_BIT );
448 ACG::GLState::disable( GL_CULL_FACE );
449
450 // Save modelview matrix
451 _state.push_modelview_matrix();
452
453 //================================================================================================
454 // Sphere
455 //================================================================================================
456
457 // ACG::GLState::disable(GL_ALPHA_TEST);
458 // ACG::GLState::enable(GL_BLEND);
459 // ACG::GLState::enable(GL_CULL_FACE);
460 // glColorMaterial ( GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE ) ;
461 // ACG::GLState::enable(GL_COLOR_MATERIAL);
462 //
463 // ACG::GLState::blendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_DST_ALPHA);
464 //
465 // glColor4f( 1.0,0.0,0.0,0.3);
466 // gluSphere( axis_, manipulator_height_ * 1.5 , manipulator_slices_ * 2, manipulator_stacks_ * 2);
467 // ACG::GLState::disable(GL_COLOR_MATERIAL);
468 //
469 //
470 // ACG::GLState::enable(GL_ALPHA_TEST);
471 // ACG::GLState::disable(GL_BLEND);
472
473 //================================================================================================
474 // Z-Axis
475 //================================================================================================
476 // gluCylinder draws into z direction so z-Axis first
477
478 if (_active)
479 {
480 _state.set_diffuse_color(element_[ZAxis].active_current_color_);
481 _state.set_specular_color(element_[ZAxis].active_current_color_);
482 } else {
483 _state.set_diffuse_color(element_[ZAxis].inactive_current_color_);
484 _state.set_specular_color(element_[ZAxis].inactive_current_color_);
485 }
486
487 // Draw Bottom of z-axis
488 axisBottom_->setBottomRadius((1.0 - resize_current_) * manipulator_radius_);
489 axisBottom_->setTopRadius((1.0 + resize_current_) * manipulator_radius_);
490 axisBottom_->draw(_state, manipulator_height_/2.0);
491
492 // Draw center of z-axis
493 _state.translate(0.0, 0.0, manipulator_height_/2);
494
495 axisCenter_->setBottomRadius(manipulator_radius_);
496 axisCenter_->setTopRadius(manipulator_radius_);
497 axisCenter_->draw(_state, manipulator_height_/2.0);
498
499
500 // Draw Top of z-axis
501 if (_active)
502 {
503 _state.set_diffuse_color(element_[ZTop].active_current_color_);
504 _state.set_specular_color(element_[ZTop].active_current_color_);
505 } else {
506 _state.set_diffuse_color(element_[ZTop].inactive_current_color_);
507 _state.set_specular_color(element_[ZTop].inactive_current_color_);
508 }
509
510 _state.translate(0.0, 0.0, manipulator_height_/2);
511 axisTop_->setBottomRadius(manipulator_radius_*2.0);
512 axisTop_->setTopRadius(0.0);
513 axisTop_->draw(_state, manipulator_height_/2.0);
514 _state.translate(0.0, 0.0, -manipulator_height_);
515
516 //================================================================================================
517 // Y-Axis
518 //================================================================================================
519 _state.rotate(-90, 1.0, 0.0, 0.0);
520 if (_active)
521 {
522 _state.set_diffuse_color(element_[YAxis].active_current_color_);
523 _state.set_specular_color(element_[YAxis].active_current_color_);
524 } else {
525 _state.set_diffuse_color(element_[YAxis].inactive_current_color_);
526 _state.set_specular_color(element_[YAxis].inactive_current_color_);
527 }
528
529 // Draw Bottom of y-axis
530 axisBottom_->setBottomRadius((1.0 - resize_current_) * manipulator_radius_);
531 axisBottom_->setTopRadius((1.0 + resize_current_) * manipulator_radius_);
532 axisBottom_->draw(_state, manipulator_height_/2.0);
533
534 // Draw center of y-axis
535 _state.translate(0.0, 0.0, manipulator_height_/2);
536
537 axisCenter_->setBottomRadius(manipulator_radius_);
538 axisCenter_->setTopRadius(manipulator_radius_);
539 axisCenter_->draw(_state, manipulator_height_/2.0);
540
541
542 // Draw Top of y-axis
543 if (_active)
544 {
545 _state.set_diffuse_color(element_[YTop].active_current_color_);
546 _state.set_specular_color(element_[YTop].active_current_color_);
547 } else {
548 _state.set_diffuse_color(element_[YTop].inactive_current_color_);
549 _state.set_specular_color(element_[YTop].inactive_current_color_);
550 }
551
552 _state.translate(0.0, 0.0, manipulator_height_/2);
553 axisTop_->setBottomRadius(manipulator_radius_*2.0);
554 axisTop_->setTopRadius(0.0);
555 axisTop_->draw(_state, manipulator_height_/2.0);
556 _state.translate(0.0, 0.0, -manipulator_height_);
557
558
559 //================================================================================================
560 // X-Axis
561 //================================================================================================
562 _state.rotate(90, 0.0, 1.0, 0.0);
563 if (_active)
564 {
565 _state.set_diffuse_color(element_[XAxis].active_current_color_);
566 _state.set_specular_color(element_[XAxis].active_current_color_);
567 } else {
568 _state.set_diffuse_color(element_[XAxis].inactive_current_color_);
569 _state.set_specular_color(element_[XAxis].inactive_current_color_);
570 }
571
572 // Draw Bottom of x-axis
573 axisBottom_->setBottomRadius((1.0 - resize_current_) * manipulator_radius_);
574 axisBottom_->setTopRadius((1.0 + resize_current_) * manipulator_radius_);
575 axisBottom_->draw(_state, manipulator_height_/2.0);
576
577 // Draw center of x-axis
578 _state.translate(0.0, 0.0, manipulator_height_/2);
579
580 axisCenter_->setBottomRadius(manipulator_radius_);
581 axisCenter_->setTopRadius(manipulator_radius_);
582 axisCenter_->draw(_state, manipulator_height_/2.0);
583
584
585 // Draw Top of x-axis
586 if (_active)
587 {
588 _state.set_diffuse_color(element_[XTop].active_current_color_);
589 _state.set_specular_color(element_[XTop].active_current_color_);
590 } else {
591 _state.set_diffuse_color(element_[XTop].inactive_current_color_);
592 _state.set_specular_color(element_[XTop].inactive_current_color_);
593 }
594
595 _state.translate(0.0, 0.0, manipulator_height_/2);
596 axisTop_->setBottomRadius(manipulator_radius_*2.0);
597 axisTop_->setTopRadius(0.0);
598 axisTop_->draw(_state, manipulator_height_/2.0);
599 _state.translate(0.0, 0.0, -manipulator_height_);
600
601 //=================================================================================================
602 // Sphere
603 //=================================================================================================
604 if (_active)
605 {
606 _state.set_diffuse_color(element_[Origin].active_current_color_);
607 _state.set_specular_color(element_[Origin].active_current_color_);
608 } else {
609 _state.set_diffuse_color(element_[Origin].inactive_current_color_);
610 _state.set_specular_color(element_[Origin].inactive_current_color_);
611 }
612
613 sphere_->draw(_state, manipulator_radius_*2);
614
615 //=================================================================================================
616 // Outer-Rings
617 //=================================================================================================
618
619 ACG::GLState::enable (GL_BLEND);
620 glPushAttrib(GL_LIGHTING_BIT);
621 ACG::GLState::disable(GL_LIGHTING);
622
623 // update circle size
624 circle_->setInnerRadius(2.0f*manipulator_height_ - manipulator_height_/4.0f);
625 circle_->setOuterRadius(2.0f*manipulator_height_);
626
627 if ( activeRotations_ & X_AXIS) {
628 if (_active)
629 {
630 _state.set_diffuse_color(element_[XRing].active_current_color_);
631 _state.set_ambient_color(element_[XRing].active_current_color_);
632 _state.set_color(element_[XRing].active_current_color_);
633
634 } else {
635 _state.set_diffuse_color(element_[XRing].inactive_current_color_);
636 _state.set_ambient_color(element_[XRing].inactive_current_color_);
637 _state.set_color(element_[XRing].inactive_current_color_);
638
639 }
640
641 circle_->draw(_state);
642 }
643
644
645 _state.rotate(90, 0.0, 1.0, 0.0);
646 if ( activeRotations_ & Y_AXIS) {
647 if (_active)
648 {
649 _state.set_diffuse_color(element_[YRing].active_current_color_);
650 _state.set_ambient_color(element_[YRing].active_current_color_);
651 _state.set_color(element_[YRing].active_current_color_);
652
653 } else {
654 _state.set_diffuse_color(element_[YRing].inactive_current_color_);
655 _state.set_ambient_color(element_[YRing].inactive_current_color_);
656 _state.set_color(element_[YRing].inactive_current_color_);
657
658 }
659
660 circle_->draw(_state);
661 }
662
663 _state.rotate(90, 1.0, 0.0, 0.0);
664 if ( activeRotations_ & Z_AXIS) {
665 if (_active)
666 {
667 _state.set_diffuse_color(element_[ZRing].active_current_color_);
668 _state.set_ambient_color(element_[ZRing].active_current_color_);
669 _state.set_color(element_[ZRing].active_current_color_);
670
671 } else {
672 _state.set_diffuse_color(element_[ZRing].inactive_current_color_);
673 _state.set_ambient_color(element_[ZRing].inactive_current_color_);
674 _state.set_color(element_[ZRing].inactive_current_color_);
675
676 }
677
678 circle_->draw(_state);
679 }
680
681 glPopAttrib(); // ENABLE_BIT
682 glPopAttrib(); // LIGHTING_BIT
683
684
685 _state.pop_modelview_matrix();
686 }
687
688 //----------------------------------------------------------------------------
689
690
691 void
692 TranslationManipulatorNode::draw(GLState& _state, const DrawModes::DrawMode& /* _drawMode */ )
693 {
694 GLenum prev_depth = _state.depthFunc();
695
696 if (draw_manipulator_) {
697
698 // Store lighting bits and enable lighting
699 glPushAttrib(GL_LIGHTING_BIT);
700 ACG::GLState::enable(GL_LIGHTING);
701 ACG::GLState::shadeModel(GL_SMOOTH);
702
703 // Store original depth status
704 glPushAttrib(GL_DEPTH_BUFFER_BIT);
705
706
707 // Alpha Test things
708 glPushAttrib(GL_COLOR_BUFFER_BIT);
709
710 glPushAttrib(GL_ENABLE_BIT);
711
712 // backup colors
713 Vec4f backup_diffuse = _state.diffuse_color();
714 Vec4f backup_specular = _state.specular_color();
715
716
717 // Correctly align nodes local coordinate system
718 update_manipulator_system(_state);
719
720 updateTargetColors ();
721 if (updateCurrentColors (_state))
722 setDirty ();
723
724 ACG::GLState::enable(GL_DEPTH_TEST);
725 ACG::GLState::depthFunc(GL_GREATER);
726 glDepthMask(GL_FALSE);
727 ACG::GLState::enable (GL_BLEND);
728 ACG::GLState::blendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
729 drawManipulator(_state, false);
730 ACG::GLState::disable (GL_BLEND);
731
732 ACG::GLState::depthFunc(GL_LEQUAL);
733 glDepthMask(GL_TRUE);
734 drawManipulator(_state, true);
735
736 // Restore old attributes and modelview
737 glPopAttrib();
738 glPopAttrib();
739 glPopAttrib();
740 glPopAttrib();
741
742 // restore active colors
743 _state.set_diffuse_color(backup_diffuse);
744 _state.set_specular_color(backup_specular);
745
746 ACG::GLState::depthFunc(prev_depth);
747 }
748 }
749
750 //----------------------------------------------------------------------------
751
752 GLMatrixd TranslationManipulatorNode::computeWorldMatrix()
753 {
754 GLMatrixd world;
755 world.identity();
756
757 world.translate(center()[0], center()[1], center()[2]); // Follow translation of parent node
758 world *= inverse_scale();
759
760 // revert global transformation as we want to use our own
761 world *= inverse_rotation();
762
763 // apply local transformation to adjust our coordinate system
764 world *= localTransformation_;
765
766 return world;
767 }
768
769 //----------------------------------------------------------------------------
770
771 void TranslationManipulatorNode::getRenderObjects(IRenderer* _renderer,
772 GLState& _state,
773 const DrawModes::DrawMode& _drawMode,
774 const Material* _mat)
775 {
776 if (draw_manipulator_)
777 {
778 RenderObject ro;
779 ro.initFromState(&_state);
780
781 // compute model-view matrix for the center of manipulator
782 ro.modelview *= computeWorldMatrix();
783 updateSize(_state);
784
785 updateTargetColors ();
786 if (updateCurrentColors (_state))
787 setDirty ();
788
789
790 // unlit, use emissive color only
791 ro.shaderDesc.shadeMode = SG_SHADE_UNLIT;
792 ro.shaderDesc.vertexColors = false;
793 ro.shaderDesc.clearTextures();
794
795 // we need the scene zbuffer for the transparent overdraw effect
796 // -> defer as long as possible
797 ro.priority = 1000;
798
799 // 1st pass
800 // draw occluded areas on top via alpha blending
801 ro.depthTest = true;
802 ro.depthFunc = GL_GREATER;
803 ro.depthWrite = false;
804
805 ro.blending = true;
806 ro.blendSrc = GL_SRC_ALPHA;
807 ro.blendDest = GL_ONE_MINUS_SRC_ALPHA;
808 ro.alpha = 0.5f;
809
810 addManipulatorToRenderer(_renderer, &ro, false);
811
812 // 2nd pass
813 // draw rest as usual
814 ro.priority = 1001;
815 ro.blending = false;
816 ro.depthFunc = GL_LEQUAL;
817 ro.depthWrite = true;
818 ro.alpha = 1.0f;
819
820 addManipulatorToRenderer(_renderer, &ro, true);
821 }
822 }
823
824 //----------------------------------------------------------------------------
825
826 void TranslationManipulatorNode::addAxisToRenderer (IRenderer* _renderer, RenderObject* _baseRO, bool _active, int _axis)
827 {
828 assert(_axis >= XAxis && _axis - 3 >= 0 && _axis <= ZAxis);
829
830 for (int i = 0; i < 3; ++i)
831 _baseRO->emissive[i] = _active ? element_[_axis].active_current_color_[i] : element_[_axis].inactive_current_color_[i];
832
833 // Draw Bottom
834 axisBottom_->setBottomRadius((1.0 - resize_current_) * manipulator_radius_);
835 axisBottom_->setTopRadius((1.0 + resize_current_) * manipulator_radius_);
836 axisBottom_->addToRenderer(_renderer, _baseRO, manipulator_height_/2.0f);
837
838 // Draw center
839 _baseRO->modelview.translate(0.0, 0.0, manipulator_height_/2);
840
841 axisCenter_->setBottomRadius(manipulator_radius_);
842 axisCenter_->setTopRadius(manipulator_radius_);
843 axisCenter_->addToRenderer(_renderer, _baseRO, manipulator_height_/2.0f);
844
845
846 // Draw top
847
848 // _axis - 3 computes id of axis-top in 'Elements' enum
849 for (int i = 0; i < 3; ++i)
850 _baseRO->emissive[i] = _active ? (element_[_axis-3].active_current_color_[i]) : (element_[_axis-3].inactive_current_color_[i]);
851
852 _baseRO->modelview.translate(0.0, 0.0, manipulator_height_/2);
853 axisTop_->setBottomRadius(manipulator_radius_*2.0);
854 axisTop_->setTopRadius(0.0);
855 axisTop_->addToRenderer(_renderer, _baseRO, manipulator_height_/2.0f);
856 _baseRO->modelview.translate(0.0, 0.0, -manipulator_height_);
857
858 }
859
860 //----------------------------------------------------------------------------
861
862 void TranslationManipulatorNode::addManipulatorToRenderer (IRenderer* _renderer, RenderObject* _baseRO, bool _active)
863 {
864 _baseRO->culling = false;
865
866 GLMatrixd oldModelview = _baseRO->modelview;
867
868 //================================================================================================
869 // Z-Axis
870 //================================================================================================
871 // gluCylinder draws into z direction so z-Axis first
872
873 _baseRO->debugName = "TranslationManipulatorNode.z";
874 addAxisToRenderer(_renderer, _baseRO, _active, ZAxis);
875
876 //================================================================================================
877 // Y-Axis
878 //================================================================================================
879
880 _baseRO->debugName = "TranslationManipulatorNode.y";
881 _baseRO->modelview.rotate(-90, 1.0, 0.0, 0.0);
882 addAxisToRenderer(_renderer, _baseRO, _active, YAxis);
883
884 //================================================================================================
885 // X-Axis
886 //================================================================================================
887
888 _baseRO->debugName = "TranslationManipulatorNode.x";
889 _baseRO->modelview.rotate(90, 0.0, 1.0, 0.0);
890 addAxisToRenderer(_renderer, _baseRO, _active, XAxis);
891
892 //=================================================================================================
893 // Sphere
894 //=================================================================================================
895
896 _baseRO->debugName = "TranslationManipulatorNode.sphere";
897
898 for (int i = 0; i < 3; ++i)
899 _baseRO->emissive[i] = _active ? (element_[Origin].active_current_color_[i]) : (element_[Origin].inactive_current_color_[i]);
900
901 sphere_->addToRenderer(_renderer, _baseRO, manipulator_radius_ * 2.0f);
902
903 //=================================================================================================
904 // Outer-Rings
905 //=================================================================================================
906
907 // _baseRO->blending = true;
908
909 // update circle size
910 circle_->setInnerRadius(2.0f*manipulator_height_ - manipulator_height_/4.0f);
911 circle_->setOuterRadius(2.0f*manipulator_height_);
912
913 if ( activeRotations_ & X_AXIS)
914 {
915 _baseRO->name = "TranslationManipulatorNode.x_ring";
916
917 for (int i = 0; i < 3; ++i)
918 _baseRO->emissive[i] = _active ? (element_[XRing].active_current_color_[i]) : (element_[XRing].inactive_current_color_[i]);
919
920 circle_->addToRenderer_primitive(_renderer, _baseRO);
921 }
922
923
924 _baseRO->modelview.rotate(90, 0.0, 1.0, 0.0);
925 if ( activeRotations_ & Y_AXIS)
926 {
927 _baseRO->debugName = "TranslationManipulatorNode.y_ring";
928
929 for (int i = 0; i < 3; ++i)
930 _baseRO->emissive[i] = _active ? (element_[YRing].active_current_color_[i]) : (element_[YRing].inactive_current_color_[i]);
931 circle_->addToRenderer_primitive(_renderer, _baseRO);
932 }
933
934 _baseRO->modelview.rotate(90, 1.0, 0.0, 0.0);
935 if ( activeRotations_ & Z_AXIS)
936 {
937 _baseRO->debugName = "TranslationManipulatorNode.z_ring";
938
939 for (int i = 0; i < 3; ++i)
940 _baseRO->emissive[i] = _active ? (element_[ZRing].active_current_color_[i]) : (element_[ZRing].inactive_current_color_[i]);
941 circle_->addToRenderer_primitive(_renderer, _baseRO);
942 }
943
944 _baseRO->modelview = oldModelview;
945 }
946
947 //----------------------------------------------------------------------------
948
949 // void
950 // TranslationManipulatorNode::leave(GLState& _state, const DrawModes::DrawMode& /* _drawMode */ )
951 // {
952
953 // }
954
955 //----------------------------------------------------------------------------
956
957 void
958 TranslationManipulatorNode::mouseEvent(GLState& _state, QMouseEvent* _event)
959 {
960 if (!draw_manipulator_)
961 return; // Avoid transformation of object while transformator is invisible
962
963 Vec3d oldPoint3D;
964 Vec2i newPoint2D(_event->pos().x(), _event->pos().y());
965 Vec3d newPoint3D;
966 unsigned int i;
967 bool lockOldPoint = false;
968
969 updateSize(_state);
970
971 switch (_event->type()) {
972
973 // If mouse is pressed check if any part of the manipulator is hit and store that state
974 case QEvent::MouseButtonPress: {
975 for (i = 0; i < NumElements; i++)
976 element_[i].clicked_ = false;
977
978 // Start dragging process
979 if (!dragging_) {
980 draggingOrigin3D_ = center();
981 dragging_ = true;
982 }
983
984 // hit origin ?
985 if ((mode_ != LocalRotation) && (mode_ != Rotation))
986 element_[Origin].clicked_ = hitSphere(_state, newPoint2D);
987 else
988 element_[Origin].clicked_ = false;
989
990 // hit any top ?
991 any_top_clicked_ = mapToCylinderTop(_state, newPoint2D, Click);
992
993 // hit any axis ?
994 any_axis_clicked_ = mapToCylinder(_state, newPoint2D, Click);
995
996 // hit one of the outer rings ?
997 if (mode_ != Resize)
998 outer_ring_clicked_ = mapToSphere(_state, newPoint2D, newPoint3D, Click);
999 else
1000 outer_ring_clicked_ = false;
1001
1002 // origin has been hit, ignore all other parts
1003 if (element_[Origin].clicked_) {
1004 for (i = 1; i < NumElements; i++)
1005 element_[i].clicked_ = false;
1006 any_axis_clicked_ = false;
1007 any_top_clicked_ = false;
1008 outer_ring_clicked_ = false;
1009 } else if (any_top_clicked_) { // tops override the axes
1010 for (i = XAxis; i < NumElements; i++)
1011 element_[i].clicked_ = false;
1012 any_axis_clicked_ = false;
1013 outer_ring_clicked_ = false;
1014 } else if (any_axis_clicked_) { // axes have been hit, disable rest ... should not be required
1015 for (i = XRing; i < NumElements; i++)
1016 element_[i].clicked_ = false;
1017 outer_ring_clicked_ = false;
1018 } else if (outer_ring_clicked_) { // Nothing except the outer ring has been hit
1019 for (i = 0; i < XRing; i++)
1020 element_[i].clicked_ = false;
1021 any_axis_clicked_ = false;
1022 any_top_clicked_ = false;
1023 }
1024
1025 // Reset local transformation:
1026 if ( (_event->modifiers() & Qt::ControlModifier) && (_event->modifiers() & Qt::AltModifier) ) {
1027 localTransformation_.identity();
1028 }
1029
1030 oldPoint2D_ = newPoint2D;
1031 currentScale_ = Vec3d(1.0, 1.0, 1.0);
1032 ignoreTime_ = true;
1033
1034 touched_ = element_[Origin].clicked_
1035 || any_top_clicked_
1036 || any_axis_clicked_
1037 || outer_ring_clicked_;
1038 break;
1039 }
1040
1041 // Reset all states as we stopped manipulating
1042 case QEvent::MouseButtonRelease: {
1043
1044 for (i = 0; i < NumElements; i++) {
1045 if (element_[i].clicked_)
1046 touched_ = true;
1047 element_[i].clicked_ = false;
1048 }
1049
1050 touched_ = touched_
1051 || any_top_clicked_
1052 || any_axis_clicked_
1053 || outer_ring_clicked_;
1054
1055 any_axis_clicked_ = false;
1056 any_top_clicked_ = false;
1057 outer_ring_clicked_ = false;
1058 ignoreTime_ = true;
1059 dragging_ = false;
1060 break;
1061 }
1062
1063 case QEvent::MouseButtonDblClick: {
1064 draw_manipulator_ = !draw_manipulator_;
1065 break;
1066 }
1067
1068 // All real manipulation is done here
1069 case QEvent::MouseMove: {
1070 if (!draw_manipulator_) {
1071 touched_ = false;
1072 return; // Avoid manipulation if manipulator is invisible
1073 }
1074
1075 // Get pressed modifiers
1076 Qt::KeyboardModifiers mods = Qt::ShiftModifier | Qt::ControlModifier;
1077
1078 for (i = 0; i < NumElements; i++)
1079 element_[i].over_ = false;
1080 any_axis_over_ = false;
1081 any_top_over_ = false;
1082 outer_ring_over_ = false;
1083
1084 if (!(element_[Origin].clicked_ || any_top_clicked_ || any_axis_clicked_ || outer_ring_clicked_)) {
1085 // over origin ?
1086 if ((mode_ != LocalRotation) && (mode_ != Rotation))
1087 element_[Origin].over_ = hitSphere(_state, newPoint2D);
1088 else
1089 element_[Origin].over_ = false;
1090
1091
1092 // over any top ?
1093 if (mode_ != Place) {
1094 any_top_over_ = mapToCylinderTop(_state, newPoint2D, Over);
1095 }
1096
1097 // over any axis ?
1098 if (mode_ != Place) {
1099 any_axis_over_ = mapToCylinder(_state, newPoint2D, Over);
1100 }
1101
1102 // over one of the outer rings ?
1103 if (mode_ != Resize) {
1104 outer_ring_over_ = mapToSphere(_state, newPoint2D, newPoint3D, Over);
1105 } else {
1106 outer_ring_over_ = false;
1107 }
1108
1109 // origin has been hit, ignore all other parts
1110 if (element_[Origin].over_) {
1111 for (i = 1; i < NumElements; i++)
1112 element_[i].over_ = false;
1113 any_axis_over_ = false;
1114 any_top_over_ = false;
1115 outer_ring_over_ = false;
1116 } else if (any_top_over_) { // tops override the axes
1117 for (i = XAxis; i < NumElements; i++)
1118 element_[i].over_ = false;
1119 any_axis_over_ = false;
1120 outer_ring_over_ = false;
1121 } else if (any_axis_over_) { // axes have been hit, disable rest ... should not be required
1122 for (i = XRing; i < NumElements; i++)
1123 element_[i].over_ = false;
1124 outer_ring_over_ = false;
1125 } else if (outer_ring_over_) { // Nothing except the outer ring has been hit
1126 for (i = 0; i < XRing; i++)
1127 element_[i].over_ = false;
1128 any_axis_over_ = false;
1129 any_top_over_ = false;
1130 }
1131 }
1132
1133 // set action for the different modes
1134 bool rot[3], trans[3];
1135 switch (mode_) {
1136 case Rotation:
1137 for (i = 0; i < 3; i++) {
1138 rot[i] = element_[XTop + i].clicked_ || element_[XRing + i].clicked_;
1139 trans[i] = false;
1140 }
1141 break;
1142 case TranslationRotation:
1143 for (i = 0; i < 3; i++) {
1144 rot[i] = element_[XTop + i].clicked_ || element_[XRing + i].clicked_;
1145 trans[i] = element_[XAxis + i].clicked_;
1146 }
1147 break;
1148 case LocalRotation:
1149 for (i = 0; i < 3; i++) {
1150 rot[i] = element_[XTop + i].clicked_ || element_[XRing + i].clicked_ || element_[XAxis + i].clicked_;
1151 trans[i] = false;
1152 }
1153 break;
1154 case Place:
1155 break;
1156 case Resize:
1157 for (i = 0; i < 3; i++) {
1158 rot[i] = false;
1159 trans[i] = element_[XTop + i].clicked_ || element_[XAxis + i].clicked_;
1160 }
1161 break;
1162 }
1163
1164 // If origin was clicked on
1165 if (element_[Origin].clicked_) {
1166
1167 // translate along screen plane ( unproject to get world coords for translation and apply them )
1168
1169 Vec3d d = _state.project(center());
1170 Vec3d d_origin = _state.project(draggingOrigin3D_);
1171
1172 // Snap back to origin position if mouse cursor
1173 // is near enough
1174 if (std::abs(d_origin[0] - newPoint2D[0]) < SNAP_PIXEL_TOLERANCE
1175 && std::abs(_state.context_height() - d_origin[1] - newPoint2D[1]) < SNAP_PIXEL_TOLERANCE
1176 && (_event->modifiers() & Qt::AltModifier) ) {
1177 newPoint2D = oldPoint2D_;
1178 Vec3d backtrans = draggingOrigin3D_ - center();
1179 if (mode_ != Resize) {
1180 translate(backtrans);
1181 }
1182 }
1183
1184 // translate along screen plane ( unproject to get world coords for translation and apply them )
1185 Vec3d oldvec = _state.unproject(Vec3d(oldPoint2D_[0], (_state.context_height() - oldPoint2D_[1]), d[2]));
1186 Vec3d newvec = _state.unproject(Vec3d(newPoint2D[0], (_state.context_height() - newPoint2D[1]), d[2]));
1187 Vec3d ntrans = newvec - oldvec;
1188
1189 if (mode_ != Resize)
1190 translate(ntrans);
1191 else {
1192 // revert last scale
1193 scale(Vec3d(1.0 / currentScale_[0], 1.0 / currentScale_[1], 1.0 / currentScale_[2]));
1194 double positive = -1;
1195 if (newPoint2D[0] - oldPoint2D_[0] + oldPoint2D_[1] - newPoint2D[1] > 0)
1196 positive = 1;
1197
1198 Vec2d div = Vec2d(newPoint2D[0], newPoint2D[1]) - Vec2d(oldPoint2D_[0], oldPoint2D_[1]);
1199
1200 double scaleValue = div.norm() * 3.0 / qMin(_state.context_height(), _state.context_width());
1201 scaleValue *= positive;
1202 currentScale_ += Vec3d(scaleValue, scaleValue, scaleValue);
1203
1204 scale(currentScale_);
1205 }
1206
1207 touched_ = true;
1208 }
1209
1210 // x axis clicked apply translation along axis
1211 if (trans[0]) {
1212
1213 mapToCylinder(_state, oldPoint2D_);
1214 mapToCylinder(_state, newPoint2D);
1215
1216 // translate
1217 // Get screen coordinates of current mouse position and unproject them
1218 // into world coordinates. Project onto selected axis and apply resulting
1219 // vector as translation
1220
1221 Vec3d d = _state.project(center());
1222 Vec3d d_origin = _state.project(draggingOrigin3D_);
1223
1224 // Snap back to origin position if mouse cursor
1225 // is near enough
1226 if (std::abs(d_origin[0] - newPoint2D[0]) < SNAP_PIXEL_TOLERANCE
1227 && std::abs(_state.context_height() - d_origin[1] - newPoint2D[1]) < SNAP_PIXEL_TOLERANCE
1228 && (_event->modifiers() & Qt::AltModifier) ) {
1229 newPoint2D = oldPoint2D_;
1230 Vec3d backtrans = draggingOrigin3D_ - center();
1231 if (mode_ != Resize) {
1232 translate(backtrans);
1233 }
1234 }
1235 Vec3d oldvec = _state.unproject(Vec3d(oldPoint2D_[0], (_state.context_height() - oldPoint2D_[1]), d[2]));
1236 Vec3d newvec = _state.unproject(Vec3d(newPoint2D[0], (_state.context_height() - newPoint2D[1]), d[2]));
1237 Vec3d ntrans = newvec - oldvec;
1238
1239 // project to current direction
1240 ntrans = (ntrans | directionX()) * directionX();
1241
1242 if (mode_ == Resize) {
1243 //scaling
1244 double positive = -1;
1245 if ((directionX() | ntrans) > 0)
1246 positive = 1;
1247
1248 if (currentScale_[0] < 0)
1249 positive *= -1;
1250
1251 Vec3d proj = _state.project(ntrans + oldvec);
1252
1253 Vec2d div = Vec2d(proj[0], proj[1]) - Vec2d(oldPoint2D_[0], (_state.context_height() - oldPoint2D_[1]));
1254
1255 double scaleValue = div.norm() * 3.0 / qMin(_state.context_height(), _state.context_width());
1256 scaleValue *= positive;
1257
1258 // revert last scale
1259 GLMatrixd m = localTransformation_;
1260 GLMatrixd mi = localTransformation_;
1261 mi.invert();
1262
1263 m.scale(Vec3d(1.0 / currentScale_[0], 1.0 / currentScale_[1], 1.0 / currentScale_[2]));
1264 m *= mi;
1265
1266 scale(m);
1267
1268 currentScale_ += Vec3d(scaleValue, 0.0, 0.0);
1269
1270 m = localTransformation_;
1271 m.scale(currentScale_);
1272 m *= mi;
1273
1274 scale(m);
1275 } else
1276 //translation
1277 translate(ntrans);
1278
1279 touched_ = true;
1280 }
1281
1282 // y axis clicked change translation along axis
1283 if (trans[1]) {
1284
1285 mapToCylinder(_state, oldPoint2D_);
1286 mapToCylinder(_state, newPoint2D);
1287
1288 // translate
1289 // Get screen coordinates of current mouse position and unproject them
1290 // into world coordinates. Project onto selected axis and apply resulting
1291 // vector as translation
1292
1293 Vec3d d = _state.project(center());
1294 Vec3d d_origin = _state.project(draggingOrigin3D_);
1295
1296 // Snap back to origin position if mouse cursor
1297 // is near enough
1298 if (std::abs(d_origin[0] - newPoint2D[0]) < SNAP_PIXEL_TOLERANCE
1299 && std::abs(_state.context_height() - d_origin[1] - newPoint2D[1]) < SNAP_PIXEL_TOLERANCE
1300 && (_event->modifiers() & Qt::AltModifier) ) {
1301 newPoint2D = oldPoint2D_;
1302 Vec3d backtrans = draggingOrigin3D_ - center();
1303 if (mode_ != Resize) {
1304 translate(backtrans);
1305 }
1306 }
1307 Vec3d oldvec = _state.unproject(Vec3d(oldPoint2D_[0], (_state.context_height() - oldPoint2D_[1]), d[2]));
1308 Vec3d newvec = _state.unproject(Vec3d(newPoint2D[0], (_state.context_height() - newPoint2D[1]), d[2]));
1309 Vec3d ntrans = newvec - oldvec;
1310
1311 // project to current direction
1312 ntrans = (ntrans | directionY()) * directionY();
1313
1314 if (mode_ == Resize) {
1315 //scaling
1316 double positive = -1;
1317 if ((directionY() | ntrans) > 0)
1318 positive = 1;
1319
1320 if (currentScale_[1] < 0)
1321 positive *= -1;
1322
1323 Vec3d proj = _state.project(ntrans + oldvec);
1324
1325 Vec2d div = Vec2d(proj[0], proj[1]) - Vec2d(oldPoint2D_[0], (_state.context_height() - oldPoint2D_[1]));
1326
1327 double scaleValue = div.norm() * 3.0 / qMin(_state.context_height(), _state.context_width());
1328 scaleValue *= positive;
1329
1330 // revert last scale
1331 GLMatrixd m = localTransformation_;
1332 GLMatrixd mi = localTransformation_;
1333 mi.invert();
1334
1335 m.scale(Vec3d(1.0 / currentScale_[0], 1.0 / currentScale_[1], 1.0 / currentScale_[2]));
1336 m *= mi;
1337
1338 scale(m);
1339
1340 currentScale_ += Vec3d(0.0, scaleValue, 0.0);
1341
1342 m = localTransformation_;
1343 m.scale(currentScale_);
1344 m *= mi;
1345
1346 scale(m);
1347
1348 } else
1349 //translation
1350 translate(ntrans);
1351
1352 touched_ = true;
1353 }
1354
1355 // z axis clicked change translation along axis
1356 if (trans[2]) {
1357
1358 mapToCylinder(_state, oldPoint2D_);
1359 mapToCylinder(_state, newPoint2D);
1360
1361 // translate
1362 // Get screen coordinates of current mouse position and unproject them
1363 // into world coordinates. Project onto selected axis and apply resulting
1364 // vector as translation
1365
1366 Vec3d d = _state.project(center());
1367 Vec3d d_origin = _state.project(draggingOrigin3D_);
1368
1369 // Snap back to origin position if mouse cursor
1370 // is near enough
1371 if (std::abs(d_origin[0] - newPoint2D[0]) < SNAP_PIXEL_TOLERANCE
1372 && std::abs(_state.context_height() - d_origin[1] - newPoint2D[1]) < SNAP_PIXEL_TOLERANCE
1373 && (_event->modifiers() & Qt::AltModifier) ) {
1374 newPoint2D = oldPoint2D_;
1375 Vec3d backtrans = draggingOrigin3D_ - center();
1376 if (mode_ != Resize) {
1377 translate(backtrans);
1378 }
1379 }
1380 Vec3d oldvec = _state.unproject(Vec3d(oldPoint2D_[0], (_state.context_height() - oldPoint2D_[1]), d[2]));
1381 Vec3d newvec = _state.unproject(Vec3d(newPoint2D[0], (_state.context_height() - newPoint2D[1]), d[2]));
1382 Vec3d ntrans = newvec - oldvec;
1383
1384 // project to current direction
1385 ntrans = (ntrans | directionZ()) * directionZ();
1386
1387 if (mode_ == Resize) {
1388 //scaling
1389 double positive = -1;
1390 if ((directionZ() | ntrans) > 0)
1391 positive = 1;
1392
1393 if (currentScale_[2] < 0)
1394 positive *= -1;
1395
1396 Vec3d proj = _state.project(ntrans + oldvec);
1397
1398 Vec2d div = Vec2d(proj[0], proj[1]) - Vec2d(oldPoint2D_[0], (_state.context_height() - oldPoint2D_[1]));
1399
1400 double scaleValue = div.norm() * 3.0 / qMin(_state.context_height(), _state.context_width());
1401 scaleValue *= positive;
1402
1403 // revert last scale
1404 GLMatrixd m = localTransformation_;
1405 GLMatrixd mi = localTransformation_;
1406 mi.invert();
1407
1408 m.scale(Vec3d(1.0 / currentScale_[0], 1.0 / currentScale_[1], 1.0 / currentScale_[2]));
1409 m *= mi;
1410
1411 scale(m);
1412
1413 currentScale_ += Vec3d(0.0, 0.0, scaleValue);
1414
1415 m = localTransformation_;
1416 m.scale(currentScale_);
1417 m *= mi;
1418
1419 scale(m);
1420
1421 } else
1422 //translation
1423 translate(ntrans);
1424
1425 touched_ = true;
1426 }
1427
1428 // x top clicked: rotate around x axis
1429 if (rot[0] && (activeRotations_ & X_AXIS)) {
1430
1431 mapToCylinder(_state, oldPoint2D_);
1432 mapToCylinder(_state, newPoint2D);
1433
1434 Vec2i dist = oldPoint2D_ - newPoint2D;
1435 int rotation = 0;
1436
1437 // Rasterize movement if shift is pressed
1438 if (_event->modifiers() == mods) {
1439 if (abs(dist[1]) < (int) (_state.viewport_height() / 16)) {
1440 rotation = 0;
1441 lockOldPoint = true;
1442 } else {
1443 // Rotate exactly 45 degrees
1444 if (dist[1] < 0)
1445 rotation = -45;
1446 else
1447 rotation = 45;
1448 ;
1449 }
1450 } else {
1451 rotation = dist[1];
1452 }
1453
1454 // Shift has been pressed
1455 // Rotate manipulator but not parent node
1456 if (mode_ == LocalRotation) {
1457
1458 // Update only local rotation
1459 localTransformation_.rotate(-rotation, directionX(), ACG::MULT_FROM_LEFT);
1460
1461 } else {
1462 // Rotate parent node but not manipulator
1463 _state.push_modelview_matrix();
1464 _state.translate(center()[0], center()[1], center()[2]);
1465 update_rotation(_state);
1466
1467 rotate(rotation, directionX());
1468
1469 _state.pop_modelview_matrix();
1470 }
1471
1472 touched_ = true;
1473 }
1474
1475 // y top clicked: rotate around y axis
1476 // or outer ring on zx axis has been clicked
1477 if (rot[1] && (activeRotations_ & Y_AXIS)) {
1478
1479 mapToCylinder(_state, oldPoint2D_);
1480 mapToCylinder(_state, newPoint2D);
1481
1482 Vec2i dist = oldPoint2D_ - newPoint2D;
1483 int rotation = 0;
1484
1485 // Rasterize movement if shift is pressed
1486 if (_event->modifiers() == mods) {
1487 if (abs(dist[1]) < (int) (_state.viewport_width() / 16)) {
1488 rotation = 0;
1489 lockOldPoint = true;
1490 } else {
1491 // Rotate exactly 45 degrees
1492 if (dist[1] < 0)
1493 rotation = -45;
1494 else
1495 rotation = 45;
1496 ;
1497 }
1498 } else {
1499 rotation = dist[1];
1500 }
1501
1502 if (mode_ == LocalRotation) {
1503
1504 // Update only local rotation
1505 localTransformation_.rotate(-rotation, directionY(), ACG::MULT_FROM_LEFT);
1506
1507 } else {
1508 _state.push_modelview_matrix();
1509 _state.translate(center()[0], center()[1], center()[2]);
1510
1511 rotate(rotation, directionY());
1512
1513 _state.pop_modelview_matrix();
1514 }
1515
1516 touched_ = true;
1517 }
1518
1519 // z top clicked: rotate around z axis
1520 if (rot[2] && (activeRotations_ & Z_AXIS)) {
1521
1522 mapToCylinder(_state, oldPoint2D_);
1523 mapToCylinder(_state, newPoint2D);
1524
1525 Vec2i dist = oldPoint2D_ - newPoint2D;
1526
1527 int rotation = 0;
1528
1529 // Rasterize movement if shift is pressed
1530 if (_event->modifiers() == mods) {
1531 if (abs(dist[1]) < (int) (_state.viewport_width() / 16)) {
1532 rotation = 0;
1533 lockOldPoint = true;
1534 } else {
1535 // Rotate exactly 45 degrees
1536 if (dist[1] < 0)
1537 rotation = 45;
1538 else
1539 rotation = -45;
1540 ;
1541 }
1542 } else {
1543 rotation = -dist[1];
1544 }
1545
1546 if (mode_ == LocalRotation) {
1547
1548 // Update only local rotation
1549 localTransformation_.rotate(-rotation, directionZ(), ACG::MULT_FROM_LEFT); // (dist[0]+dist[1])/2
1550
1551 } else {
1552 _state.push_modelview_matrix();
1553 _state.translate(center()[0], center()[1], center()[2]);
1554
1555 rotate(rotation, directionZ());
1556
1557 _state.pop_modelview_matrix();
1558 }
1559
1560 touched_ = true;
1561 }
1562
1563 break;
1564 }
1565
1566 default: // avoid warning
1567 break;
1568 }
1569
1570 setDirty();
1571
1572 // save old Point
1573 if (!lockOldPoint)
1574 oldPoint2D_ = newPoint2D;
1575 }
1576
1577
1578 //----------------------------------------------------------------------------
1579
1581 bool TranslationManipulatorNode::hitSphere( GLState& _state,
1582 const Vec2i& _v2)
1583 {
1584 // Qt -> GL coordinate systems
1585 unsigned int x = _v2[0];
1586 unsigned int y = _state.context_height() - _v2[1];
1587
1588
1589 // get ray from eye through pixel, in sphere coords
1590 Vec3d origin, direction;
1591
1592 _state.set_updateGL(false);
1593 _state.push_modelview_matrix();
1594
1595 update_manipulator_system(_state);
1596 _state.scale(2*manipulator_radius_);
1597
1598 _state.viewing_ray(x, y, origin, direction);
1599
1600 _state.pop_modelview_matrix();
1601 _state.set_updateGL(true);
1602
1603
1604
1605 // calc sphere-ray intersection
1606 // (sphere is centered at origin, has radius 1)
1607 double a = direction.sqrnorm(),
1608 b = 2.0 * (origin | direction),
1609 c = origin.sqrnorm() - 1.0,
1610 d = b*b - 4.0*a*c;
1611
1612 return (d >= 0.0);
1613 }
1614
1615
1616 //------------------------------------------------------------------------------------
1617
1618
1620
1621 bool TranslationManipulatorNode::hitOuterSphere( GLState& _state,
1622 const Vec2i& _v2)
1623 {
1624 // Qt -> GL coordinate systems
1625 unsigned int x = _v2[0];
1626 unsigned int y = _state.context_height() - _v2[1];
1627
1628
1629 // get ray from eye through pixel, in sphere coords
1630 Vec3d origin, direction;
1631
1632 _state.set_updateGL(false);
1633 _state.push_modelview_matrix();
1634
1635 update_manipulator_system(_state);
1636 _state.scale(manipulator_height_+4*manipulator_radius_);
1637
1638 _state.viewing_ray(x, y, origin, direction);
1639
1640 _state.pop_modelview_matrix();
1641 _state.set_updateGL(true);
1642
1643
1644 // calc sphere-ray intersection
1645 // (sphere is centered at origin, has radius 1)
1646 double a = direction.sqrnorm(),
1647 b = 2.0 * (origin | direction),
1648 c = origin.sqrnorm() - 1.0,
1649 d = b*b - 4.0*a*c;
1650
1651 return (d >= 0.0);
1652 }
1653
1654
1655 //------------------------------------------------------------------------------------
1656
1657
1660 bool
1661 TranslationManipulatorNode::mapToCylinder( GLState& _state,
1662 const Vec2i& _v1,
1663 StateUpdates _updateStates )
1664 {
1665 // Qt -> GL coordinate systems
1666 unsigned int x = _v1[0];
1667 unsigned int y = _state.context_height() - _v1[1];
1668
1669
1670 // get ray from eye through pixel (cylinder coords)
1671 Vec3d originX, directionX;
1672 Vec3d originY, directionY;
1673 Vec3d originZ, directionZ;
1674
1675 _state.set_updateGL(false);
1676 _state.push_modelview_matrix();
1677
1678 // Now that we have 3 different axes we have to test intersection with each of them
1679 // Z-Axis:
1680 update_manipulator_system(_state);
1681 _state.viewing_ray(x, y, originZ, directionZ);
1682
1683 // Y-Axis:
1684 _state.rotate(-90, 1.0, 0.0, 0.0);
1685 _state.viewing_ray(x, y, originY, directionY);
1686
1687 // X-Axis:
1688 _state.rotate(90, 0.0, 1.0, 0.0);
1689 _state.viewing_ray(x, y, originX, directionX);
1690
1691 _state.pop_modelview_matrix();
1692 _state.set_updateGL(true);
1693
1694
1695 // get cylinder axis ray: it's in its own coord system!
1696 // Viewing ray function unprojects screen coordinates thorugh inverse viewport, projection and modelview
1697 // such that we end in local coordinate system of the manipulator.
1698 // local transformation of the manipulator is included in update_manipulator_system which applies the
1699 // local transformation to the current glstate used by viewing_ray
1700 const Vec3d origin2(0,0,0),
1701 cylinderAxis(0.0, 0.0, 1.0); // Always same but we change the coordinate system for the viewer
1702
1703
1704 // compute pseude-intersection (x axis)
1705 Vec3d normalX = (directionX % cylinderAxis).normalize();
1706 Vec3d vdX = ((origin2 - originX) % directionX);
1707 double axis_hitX = (normalX | vdX);
1708 double orthodistanceX = std::abs( ( origin2 - originX ) | normalX);
1709
1710 // compute pseude-intersection (y axis)
1711 Vec3d normalY = (directionY % cylinderAxis).normalize();
1712 Vec3d vdY = ((origin2 - originY) % directionY);
1713 double axis_hitY = (normalY | vdY);
1714 double orthodistanceY = std::abs( ( origin2 - originY ) | normalY);
1715
1716 // compute pseude-intersection (z axis)
1717 Vec3d normalZ = (directionZ % cylinderAxis).normalize();
1718 Vec3d vdZ = ((origin2 - originZ) % directionZ);
1719 double axis_hitZ = (normalZ | vdZ);
1720 double orthodistanceZ = std::abs( ( origin2 - originZ ) | normalZ);
1721
1722 if ( _updateStates == None )
1723 return false;
1724
1725 if ( ( orthodistanceX < manipulator_radius_ ) &&
1726 ( axis_hitX >= 0 ) &&
1727 ( axis_hitX <= manipulator_height_ ) )
1728 {
1729
1730 // z axis has been hit
1731 if ( _updateStates == Click)
1732 element_[XAxis].clicked_ = true;
1733 else
1734 element_[XAxis].over_ = true;
1735
1736 } else if ( ( orthodistanceY < manipulator_radius_ ) &&
1737 ( axis_hitY >= 0 ) &&
1738 ( axis_hitY <= manipulator_height_))
1739 {
1740
1741 // y axis has been hit
1742 if ( _updateStates == Click)
1743 element_[YAxis].clicked_ = true;
1744 else
1745 element_[YAxis].over_ = true;
1746
1747 } else if ( ( orthodistanceZ < manipulator_radius_ ) &&
1748 ( axis_hitZ >= 0 ) &&
1749 ( axis_hitZ <= manipulator_height_ ) )
1750 {
1751 // x axis has been hit
1752 if ( _updateStates == Click)
1753 element_[ZAxis].clicked_ = true;
1754 else
1755 element_[ZAxis].over_ = true;
1756
1757 }
1758
1759 if ( _updateStates == Click)
1760 return (element_[XAxis].clicked_ || element_[YAxis].clicked_ || element_[ZAxis].clicked_);
1761
1762 return (element_[XAxis].over_ || element_[YAxis].over_ || element_[ZAxis].over_);
1763 }
1764
1765
1766 //----------------------------------------------------------------------------
1769 // This method treats the top as cylinder
1770 // TODO: Adapt intersection test to cone shape
1771 bool
1772 TranslationManipulatorNode::mapToCylinderTop( GLState& _state,
1773 const Vec2i& _v1,
1774 StateUpdates _updateStates )
1775 {
1776 // Qt -> GL coordinate systems
1777 unsigned int x = _v1[0];
1778 unsigned int y = _state.context_height() - _v1[1];
1779
1780
1781 // get ray from eye through pixel (cylinder coords)
1782 Vec3d originX, directionX;
1783 Vec3d originY, directionY;
1784 Vec3d originZ, directionZ;
1785
1786 _state.set_updateGL(false);
1787 _state.push_modelview_matrix();
1788
1789 // Z-Axis:
1790 update_manipulator_system(_state);
1791 _state.translate( 0.0, 0.0, manipulator_height_);
1792 _state.viewing_ray(x, y, originZ, directionZ);
1793 _state.translate( 0.0, 0.0, -manipulator_height_);
1794
1795 // Y-Axis:
1796 _state.rotate(-90, 1.0, 0.0, 0.0);
1797 _state.translate(0.0, 0.0 , manipulator_height_ );
1798 _state.viewing_ray(x, y, originY, directionY);
1799 _state.translate(0.0, 0.0, -manipulator_height_);
1800
1801 // X-Axis:
1802 _state.rotate(90, 0.0, 1.0, 0.0);
1803 _state.translate(0.0, 0.0, manipulator_height_);
1804 _state.viewing_ray(x, y, originX, directionX);
1805 _state.translate(0.0, 0.0, -manipulator_height_);
1806
1807 _state.pop_modelview_matrix();
1808 _state.set_updateGL(true);
1809
1810
1811 // get cylinder axis ray: it's in its own coord system!
1812 // Viewing ray function unprojects screen coordinates thorugh inverse viewport, projection and modelview
1813 // such that we end in local coordinate system of the manipulator.
1814 // local transformation of the manipulator is included in update_manipulator_system which applies the
1815 // local transformation to the current glstate used by viewing_ray
1816 const Vec3d origin2(0,0,0),
1817 cylinderAxis(0.0, 0.0, 1.0);
1818
1819 // compute pseude-intersection (x axis)
1820 Vec3d normalX = (directionX % cylinderAxis).normalize();
1821 Vec3d vdX = ((origin2 - originX) % directionX );
1822 double axis_hitX = (normalX | vdX);
1823 double orthodistanceX = std::abs( ( origin2 - originX ) | normalX);
1824
1825 // compute pseude-intersection (y axis)
1826 Vec3d normalY = (directionY % cylinderAxis).normalize();
1827 Vec3d vdY = ((origin2 - originY) % directionY);
1828 double axis_hitY = (normalY | vdY);
1829 double orthodistanceY = std::abs( ( origin2 - originY ) | normalY);
1830
1831 // compute pseude-intersection (z axis)
1832 Vec3d normalZ = (directionZ % cylinderAxis).normalize();
1833 Vec3d vdZ = ((origin2 - originZ) % directionZ);
1834 double axis_hitZ = (normalZ | vdZ);
1835 double orthodistanceZ = std::abs( ( origin2 - originZ ) | normalZ);
1836
1837 if ( _updateStates == None )
1838 return false;
1839
1840 // TODO: Work with cones :
1841
1842 if ( ( orthodistanceX < manipulator_radius_ * 2.0 ) &&
1843 ( axis_hitX >= 0.0 ) &&
1844 ( axis_hitX <= manipulator_height_ / 2.0 ) )
1845 {
1846
1847 // z top has been hit
1848 if ( _updateStates == Click)
1849 element_[XTop].clicked_ = true;
1850 else
1851 element_[XTop].over_ = true;
1852
1853 } else if ( ( orthodistanceY < manipulator_radius_ * 2.0 ) &&
1854 ( axis_hitY >= 0.0 ) &&
1855 ( axis_hitY <= manipulator_height_ / 2.0 ) )
1856 {
1857
1858 // y top has been hit
1859 if ( _updateStates == Click)
1860 element_[YTop].clicked_ = true;
1861 else
1862 element_[YTop].over_ = true;
1863
1864 } else if ( ( orthodistanceZ < manipulator_radius_ * 2.0 ) &&
1865 ( axis_hitZ >= 0.0 ) &&
1866 ( axis_hitZ <= manipulator_height_ / 2.0 ) )
1867 {
1868
1869 // x top has been hit
1870 if ( _updateStates == Click)
1871 element_[ZTop].clicked_ = true;
1872 else
1873 element_[ZTop].over_ = true;
1874
1875 }
1876
1877 if ( _updateStates == Click)
1878 return (element_[XTop].clicked_ || element_[YTop].clicked_ || element_[ZTop].clicked_);
1879 return (element_[XTop].over_ || element_[YTop].over_ || element_[ZTop].over_);
1880 }
1881
1882 //----------------------------------------------------------------------------
1883
1887 bool
1888 TranslationManipulatorNode::mapToSphere( GLState& _state,
1889 const Vec2i& _v2,
1890 Vec3d& _v3,
1891 StateUpdates _updateStates)
1892 {
1893 // Qt -> GL coordinate systems
1894 unsigned int x = _v2[0];
1895 unsigned int y = _state.context_height() - _v2[1];
1896
1897 // get ray from eye through pixel
1898 Vec3d originXY, directionXY,
1899 originYZ, directionYZ,
1900 originZX, directionZX;
1901
1902 _state.set_updateGL(false);
1903 _state.push_modelview_matrix();
1904
1905 update_manipulator_system(_state);
1906
1907 _state.viewing_ray(x, y, originXY, directionXY);
1908 _state.rotate(90, 0.0, 1.0, 0.0);
1909 _state.viewing_ray(x, y, originYZ, directionYZ);
1910 _state.rotate(90, 1.0, 0.0, 0.0);
1911 _state.viewing_ray(x, y, originZX, directionZX);
1912
1913 _state.pop_modelview_matrix();
1914 _state.set_updateGL(true);
1915
1916 // origin + direction * t = (x, y, 0) <=> t = -origin_z / direction_z
1917 // => Point on xy-plane p = (origin_x + direction_x*t, origin_y + direction_y*t, 0)
1918 double t1 = -originXY[2]/directionXY[2];
1919 Vec3d hitPointXY = originXY + directionXY*t1;
1920
1921 double t2 = -originYZ[2]/directionYZ[2];
1922 Vec3d hitPointYZ = originYZ + directionYZ*t2;
1923
1924 double t3 = -originZX[2]/directionZX[2];
1925 Vec3d hitPointZX = originZX + directionZX*t3;
1926
1927 // Depth test: Take nearest object
1928 bool t1_near = false, t2_near = false, t3_near = false;
1929 if( t1 <= t2 && t1 <= t3)
1930 t1_near = true;
1931 if( t2 <= t1 && t2 <= t3)
1932 t2_near = true;
1933 if( t3 <= t1 && t3 <= t2)
1934 t3_near = true;
1935
1936 bool xy_hit = hitPointXY.length() > 2*manipulator_height_ - manipulator_height_/4.0 &&
1937 hitPointXY.length() < 2*manipulator_height_;
1938
1939 bool yz_hit = hitPointYZ.length() > 2*manipulator_height_ - manipulator_height_/4.0 &&
1940 hitPointYZ.length() < 2*manipulator_height_;
1941
1942 bool zx_hit = hitPointZX.length() > 2*manipulator_height_ - manipulator_height_/4.0 &&
1943 hitPointZX.length() < 2*manipulator_height_;
1944
1945
1946 bool more_than_one_hit = (xy_hit && yz_hit) || (xy_hit && zx_hit) || (yz_hit && zx_hit);
1947 // std::cerr << 2*manipulator_height_ - manipulator_height_/3.0 << " < " <<
1948 // hitPointXY << " < " << 2*manipulator_height_ << std::endl;
1949 //
1950 // std::cerr << 2*manipulator_height_ - manipulator_height_/3.0 << " < " <<
1951 // hitPointYZ << " < " << 2*manipulator_height_ << std::endl;
1952 //
1953 // std::cerr << 2*manipulator_height_ - manipulator_height_/3.0 << " < " <<
1954 // hitPointZX << " < " << 2*manipulator_height_ << std::endl;
1955
1956 // Test if hit point on x-y plane matches length of
1957 // manipulator radius_state
1958 if(xy_hit && (!more_than_one_hit || t1_near))
1959 {
1960 // Outer ring on xy plane has been hit
1961 if ( _updateStates == Click)
1962 element_[ZRing].clicked_ = true;
1963 else if ( _updateStates == Over)
1964 element_[ZRing].over_ = true;
1965 _v3 = hitPointXY;
1966 return true;
1967 }
1968
1969 else if(yz_hit && (!more_than_one_hit || t2_near))
1970 {
1971 // Outer ring on yz plane has been hit
1972 if ( _updateStates == Click)
1973 element_[XRing].clicked_ = true;
1974 else if ( _updateStates == Over)
1975 element_[XRing].over_ = true;
1976 _v3 = hitPointYZ;
1977 return true;
1978 }
1979
1980 else if(zx_hit && (!more_than_one_hit || t3_near))
1981 {
1982 // Outer ring around zx plane has been hit
1983 if ( _updateStates == Click)
1984 element_[YRing].clicked_ = true;
1985 else if ( _updateStates == Over)
1986 element_[YRing].over_ = true;
1987 _v3 = hitPointZX;
1988 return true;
1989 }
1990
1991 return false;
1992 }
1993
1994 //----------------------------------------------------------------------------
1995
1996 void
1997 TranslationManipulatorNode::
1998 pick(GLState& _state, PickTarget _target)
1999 {
2000 GLenum prev_depth = _state.depthFunc();
2001
2002 if (_target == PICK_FACE ||
2003 _target == PICK_ANYTHING) {
2004
2005 if (draw_manipulator_) {
2006
2007 updateSize (_state);
2008
2009 _state.pick_set_maximum(5);
2010
2011 // Enable depth test but store original status
2012 if(_state.compatibilityProfile())
2013 glPushAttrib(GL_DEPTH_BUFFER_BIT);
2014 GLboolean depthTest;
2015 glGetBooleanv(GL_DEPTH_TEST, &depthTest);
2016 ACG::GLState::enable(GL_DEPTH_TEST);
2017 ACG::GLState::depthFunc(GL_LEQUAL);
2018
2019 // Save modelview matrix
2020 _state.push_modelview_matrix();
2021
2022 // Correctly align nodes local coordinate system
2023 update_manipulator_system(_state);
2024
2025 _state.pick_set_name(0);
2026 //================================================================================================
2027 // Z-Axis
2028 //================================================================================================
2029 // gluCylinder draws into z direction so z-Axis first
2030
2031 axisBottom_->setBottomRadius(manipulator_radius_);
2032 axisBottom_->setTopRadius(manipulator_radius_);
2033 axisBottom_->draw(_state, manipulator_height_);
2034
2035 // Draw Top of z-axis
2036 _state.translate(0.0, 0.0, manipulator_height_);
2037 axisTop_->setBottomRadius(manipulator_radius_*2.0);
2038 axisTop_->setTopRadius(manipulator_radius_*2.0);
2039 axisTop_->draw(_state, manipulator_height_/2.0);
2040 _state.translate(0.0, 0.0, -manipulator_height_);
2041
2042 _state.pick_set_name(1);
2043 //================================================================================================
2044 // Y-Axis
2045 //================================================================================================
2046 _state.rotate(-90, 1.0, 0.0, 0.0);
2047 axisBottom_->setBottomRadius(manipulator_radius_);
2048 axisBottom_->setTopRadius(manipulator_radius_);
2049 axisBottom_->draw(_state, manipulator_height_);
2050
2051 // Draw Top of y-axis
2052 _state.translate(0.0, 0.0, manipulator_height_);
2053 axisTop_->setBottomRadius(manipulator_radius_*2.0);
2054 axisTop_->setTopRadius(manipulator_radius_*2.0);
2055 axisTop_->draw(_state, manipulator_height_/2.0);
2056 _state.translate(0.0, 0.0, -manipulator_height_);
2057
2058
2059 _state.pick_set_name(2);
2060 //================================================================================================
2061 // X-Axis
2062 //================================================================================================
2063 _state.rotate(90, 0.0, 1.0, 0.0);
2064
2065 axisBottom_->setBottomRadius(manipulator_radius_);
2066 axisBottom_->setTopRadius(manipulator_radius_);
2067 axisBottom_->draw(_state, manipulator_height_);
2068
2069 // Draw Top of x-axis
2070 _state.translate(0.0, 0.0, manipulator_height_);
2071 axisTop_->setBottomRadius(manipulator_radius_*2.0);
2072 axisTop_->setTopRadius(manipulator_radius_*2.0);
2073 axisTop_->draw(_state, manipulator_height_/2.0);
2074
2075 _state.translate(0.0, 0.0, -manipulator_height_);
2076
2077 _state.pick_set_name(3);
2078 //=================================================================================================
2079 // Sphere
2080 //=================================================================================================
2081
2082 sphere_->draw(_state, manipulator_radius_*2);
2083
2084 //=================================================================================================
2085 // Outer-Spheres
2086 //=================================================================================================
2087
2088 _state.pick_set_name(4);
2089 circle_->setInnerRadius(2.0f*manipulator_height_ - manipulator_height_/4.0f);
2090 circle_->setOuterRadius(2.0f*manipulator_height_);
2091 if ( activeRotations_ & X_AXIS)
2092 circle_->draw(_state);
2093
2094 _state.rotate(90, 0.0, 1.0, 0.0);
2095 if ( activeRotations_ & Y_AXIS)
2096 circle_->draw(_state);
2097
2098 _state.rotate(90, 1.0, 0.0, 0.0);
2099 if ( activeRotations_ & Z_AXIS)
2100 circle_->draw(_state);
2101
2102 // Restore old attributes and modelview
2103 if(_state.compatibilityProfile())
2104 glPopAttrib();
2105 _state.pop_modelview_matrix();
2106
2107 if(depthTest)
2108 ACG::GLState::enable(GL_DEPTH_TEST);
2109 //restore original depth comparison function
2110 ACG::GLState::depthFunc(prev_depth);
2111 }
2112 }
2113 }
2114
2115
2116 //----------------------------------------------------------------------------
2117
2118 void
2119 TranslationManipulatorNode::set_direction(const Vec3d& _directionX, const Vec3d& _directionY)
2120 {
2121
2122 localTransformation_.identity();
2123
2124 const Vec3d cross = _directionX % _directionY;
2125
2126 localTransformation_(0,0) = _directionX[0];
2127 localTransformation_(1,0) = _directionX[1];
2128 localTransformation_(2,0) = _directionX[2];
2129 localTransformation_(3,0) = 0.0;
2130
2131 localTransformation_(0,1) = _directionY[0];
2132 localTransformation_(1,1) = _directionY[1];
2133 localTransformation_(2,1) = _directionY[2];
2134 localTransformation_(3,1) = 0.0;
2135
2136 localTransformation_(0,2) = cross[0];
2137 localTransformation_(1,2) = cross[1];
2138 localTransformation_(2,2) = cross[2];
2139 localTransformation_(3,2) = 0.0;
2140
2141 }
2142
2143 //----------------------------------------------------------------------------
2144
2145
2146
2147
2148 Vec3d
2149 TranslationManipulatorNode::directionX() const
2150 {
2151 Vec3d direction = localTransformation_.transform_vector(dirX_);
2152
2153 if ( ! OpenMesh::is_zero( direction.sqrnorm() ) )
2154 direction.normalize();
2155 else
2156 direction = Vec3d(0.0,0.0,0.0);
2157
2158 return direction;
2159 }
2160
2161 //----------------------------------------------------------------------------
2162
2163
2164 Vec3d
2165 TranslationManipulatorNode::directionY() const
2166 {
2167 Vec3d direction = localTransformation_.transform_vector(dirY_);
2168
2169 if ( ! OpenMesh::is_zero( direction.sqrnorm() ) )
2170 direction.normalize();
2171 else
2172 direction = Vec3d(0.0,0.0,0.0);
2173
2174 return direction;
2175 }
2176
2177 //----------------------------------------------------------------------------
2178
2179
2180 Vec3d
2181 TranslationManipulatorNode::directionZ() const
2182 {
2183 Vec3d direction = localTransformation_.transform_vector(dirZ_);
2184
2185 if ( ! OpenMesh::is_zero( direction.sqrnorm() ) )
2186 direction.normalize();
2187 else
2188 direction = Vec3d(0.0,0.0,0.0);
2189
2190 return direction;
2191 }
2192
2193 //----------------------------------------------------------------------------
2194
2195 double TranslationManipulatorNode::get_screen_length (GLState& _state, Vec3d& _point) const
2196 {
2197 Vec3d proj = _state.project (_point);
2198 proj[0] += 1.0;
2199 Vec3d uproj = _state.unproject (proj);
2200 uproj -= _point;
2201 return uproj.length ();
2202 }
2203
2204 //----------------------------------------------------------------------------
2205
2206 void TranslationManipulatorNode::updateSize (GLState& _state)
2207 {
2208 if (auto_size_ != TranslationManipulatorNode::Never)
2209 {
2210 Vec3d point = localTransformation_.transform_point(Vec3d (0.0, 0.0, 0.0));
2211
2212 int tmp, width, height;
2213
2214 _state.get_viewport (tmp, tmp, width, height);
2215
2216 auto_size_length_ = get_screen_length (_state, point) * (width + height) * 0.02;
2217
2218 if (auto_size_ == TranslationManipulatorNode::Once)
2219 auto_size_ = TranslationManipulatorNode::Never;
2220 }
2221
2222 manipulator_radius_ = set_manipulator_radius_ * auto_size_length_;
2223 manipulator_height_ = set_manipulator_height_ * auto_size_length_;
2224 }
2225
2226 //----------------------------------------------------------------------------
2227
2228
2229 void TranslationManipulatorNode::boundingBox( Vec3d & _bbMin, Vec3d & _bbMax )
2230 {
2231 if (!draw_manipulator_)
2232 return;
2233
2234 float r = 2 * manipulator_height_;
2235
2236 _bbMin.minimize(center()+Vec3d(-r,-r,-r));
2237 _bbMax.maximize(center()+Vec3d(r,r,r));
2238 }
2239
2240 //----------------------------------------------------------------------------
2241
2242 void TranslationManipulatorNode::setMode (ManipulatorMode _mode)
2243 {
2244 if (mode_ != _mode)
2245 ignoreTime_ = true;
2246 mode_ = _mode;
2247 setDirty ();
2248 }
2249
2250 //=============================================================================
2251 } // namespace SceneGraph
2252 } // namespace ACG
2253 //=============================================================================
ACG::SceneGraph::TranslationManipulatorNode::directionY
Vec3d directionY() const
Get current direction of y-Axis in world coordinates.
Definition: TranslationManipulatorNode.cc:2165
ACG::SceneGraph::ACG::SceneGraph::BaseNode::setTraverseMode
void setTraverseMode(unsigned int _mode)
Set traverse mode for node.
Definition: MeshNode2T_impl.hh:452
ACG::SceneGraph::TransformNode::translate
void translate(const Vec3d &_v)
Add a translation to the current Transformation.
Definition: TransformNode.cc:125
ACG::GLMatrixT::rotate
void rotate(Scalar angle, Scalar x, Scalar y, Scalar z, MultiplyFrom _mult_from=MULT_FROM_RIGHT)
Definition: GLMatrixT_impl.hh:155
ACG::RenderObject::initFromState
void initFromState(GLState *_glState)
Initializes a RenderObject instance.
Definition: RenderObject.cc:61
ACG::GLDisk
Definition: GLPrimitives.hh:252
ACG::GLState::pop_modelview_matrix
void pop_modelview_matrix()
pop modelview matrix
Definition: GLState.cc:1026
ACG::GLState::specular_color
const Vec4f & specular_color() const
get specular color
Definition: GLState.hh:941
ACG::SceneGraph::TransformNode
Definition: TransformNode.hh:89
ACG::GLState::set_diffuse_color
void set_diffuse_color(const Vec4f &_col)
set diffuse color
Definition: GLState.cc:722
ACG::GLState
Definition: GLState.hh:213
ACG::SceneGraph::TranslationManipulatorNode::directionZ
Vec3d directionZ() const
Get current direction of z-Axis in world coordinates.
Definition: TranslationManipulatorNode.cc:2181
ACG::SceneGraph::TransformNode::center
const Vec3d & center() const
get center
Definition: TransformNode.hh:115
ACG::SceneGraph::PICK_FACE
picks faces (should be implemented for all nodes)
Definition: PickTarget.hh:78
ACG::GLState::viewport_width
int viewport_width() const
get viewport width
Definition: GLState.hh:822
ACG
Namespace providing different geometric functions concerning angles.
Definition: BaseObjectData.hh:68
ACG::SceneGraph::TranslationManipulatorNode::boundingBox
void boundingBox(Vec3d &_bbMin, Vec3d &_bbMax) override
bounding box of node
Definition: TranslationManipulatorNode.cc:2229
ACG::GLState::project
Vec3d project(const Vec3d &_point) const
project point in world coordinates to window coordinates
Definition: GLState.cc:640
ACG::Vec4f
VectorT< float, 4 > Vec4f
Definition: VectorT.hh:138
ACG::SceneGraph::TranslationManipulatorNode::setIdentity
virtual void setIdentity() override
Definition: TranslationManipulatorNode.cc:213
ACG::RenderObject::depthFunc
GLenum depthFunc
GL_LESS, GL_LEQUAL, GL_GREATER ..
Definition: RenderObject.hh:240
ACG::SceneGraph::ACG::GLState::disable
static void disable(GLenum _cap, bool _warnRemoved=true)
replaces glDisable, but supports locking
ACG::GLCone
Definition: GLPrimitives.hh:169
ACG::GLState::get_viewport
void get_viewport(int &_left, int &_bottom, int &_width, int &_height) const
get viewport
Definition: GLState.hh:816
ACG::RenderObject::shaderDesc
ShaderGenDesc shaderDesc
Drawmode and other shader params.
Definition: RenderObject.hh:225
ACG::GLMatrixT::translate
void translate(Scalar _x, Scalar _y, Scalar _z, MultiplyFrom _mult_from=MULT_FROM_RIGHT)
multiply self with translation matrix (x,y,z)
Definition: GLMatrixT_impl.hh:96
ACG::SceneGraph::TranslationManipulatorNode::hitSphere
bool hitSphere(GLState &_state, const Vec2i &_v2)
Determine whether the origin sphere has been hit.
Definition: TranslationManipulatorNode.cc:1581
ACG::ShaderGenDesc::clearTextures
void clearTextures()
disables texture support and removes all texture types
Definition: ShaderGenerator.hh:223
OpenMesh::VectorT< float, 4 >
ACG::Matrix4x4T::identity
void identity()
setup an identity matrix
Definition: Matrix4x4T_impl.hh:250
ACG::SceneGraph::TransformNode::inverse_scale
const GLMatrixd & inverse_scale() const
return inverse scale matrix
Definition: TransformNode.hh:185
ACG::GLState::scale
void scale(double _s)
scale by (_s, _s, _s)
Definition: GLState.hh:750
OpenMesh::VectorT::maximize
vector_type & maximize(const vector_type &_rhs)
maximize values: same as *this = max(*this, _rhs), but faster
Definition: Vector11T.hh:568
ACG::RenderObject::name
std::string name
Name for logging.
Definition: RenderObject.hh:121
ACG::GLState::depthFunc
const GLenum & depthFunc() const
get glDepthFunc() that is supposed to be active
Definition: GLState.cc:941
ACG::GLState::diffuse_color
const Vec4f & diffuse_color() const
get diffuse color
Definition: GLState.hh:936
ACG::Matrix4x4T::transform_point
VectorT< T, 3 > transform_point(const VectorT< T, 3 > &_v) const
transform point (x&#39;,y&#39;,z&#39;,1) = M * (x,y,z,1)
Definition: Matrix4x4T_impl.hh:196
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::IRenderer
Definition: IRenderer.hh:78
ACG::GLState::set_updateGL
void set_updateGL(bool _b)
should GL matrices be updated after each matrix operation
Definition: GLState.hh:235
SceneGraph
Definition: QtPrincipalAxisDialog.hh:67
ACG::SceneGraph::TranslationManipulatorNode::set_direction
void set_direction(const Vec3d &_directionX, const Vec3d &_directionY)
Set direction in world coordinates.
Definition: TranslationManipulatorNode.cc:2119
ACG::SceneGraph::PickTarget
PickTarget
What target to use for picking.
Definition: PickTarget.hh:73
ACG::GLState::unproject
Vec3d unproject(const Vec3d &_winPoint) const
unproject point in window coordinates _winPoint to world coordinates
Definition: GLState.cc:651
ACG::Matrix4x4T::invert
bool invert()
matrix inversion (returns true on success)
Definition: Matrix4x4T_impl.hh:291
ACG::GLState::push_modelview_matrix
void push_modelview_matrix()
push modelview matrix
Definition: GLState.cc:1010
ACG::GLState::set_modelview
void set_modelview(const GLMatrixd &_m)
set modelview
Definition: GLState.hh:728
ACG::SceneGraph::TranslationManipulatorNode::setMode
void setMode(ManipulatorMode _mode)
set current operation mode
Definition: TranslationManipulatorNode.cc:2242
ACG::SceneGraph::TranslationManipulatorNode
Definition: TranslationManipulatorNode.hh:89
ACG::SceneGraph::TranslationManipulatorNode::computeWorldMatrix
GLMatrixd computeWorldMatrix()
computes world matrix, transforms from model to world space
Definition: TranslationManipulatorNode.cc:752
ACG::GLMatrixT< double >
ACG::SceneGraph::TransformNode::inverse_rotation
const GLMatrixd & inverse_rotation() const
return inverse rotation matrix
Definition: TransformNode.hh:172
ACG::SceneGraph::TranslationManipulatorNode::mapToCylinderTop
bool mapToCylinderTop(GLState &_state, const Vec2i &_v2, StateUpdates _updateStates=None)
Definition: TranslationManipulatorNode.cc:1772
ACG::SceneGraph::PICK_ANYTHING
pick any of the prior targets (should be implemented for all nodes)
Definition: PickTarget.hh:84
ACG::GLState::set_ambient_color
void set_ambient_color(const Vec4f &_col)
set ambient color
Definition: GLState.cc:707
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::TranslationManipulatorNode::pick
void pick(GLState &_state, PickTarget _target) override
leave node
Definition: TranslationManipulatorNode.cc:1998
ACG::GLMatrixT::scale
void scale(Scalar _x, Scalar _y, Scalar _z, MultiplyFrom _mult_from=MULT_FROM_RIGHT)
multiply self with scaling matrix (x,y,z)
Definition: GLMatrixT_impl.hh:75
ACG::GLState::viewport_height
int viewport_height() const
get viewport height
Definition: GLState.hh:824
OpenMesh::VectorT::minimize
vector_type & minimize(const vector_type &_rhs)
minimize values: same as *this = min(*this, _rhs), but faster
Definition: Vector11T.hh:540
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
OpenMesh::VectorT::norm
auto norm() const -> decltype(std::sqrt(std::declval< VectorT< S, DIM >>().sqrnorm()))
compute euclidean norm
Definition: Vector11T.hh:414
ACG::GLSphere
Definition: GLPrimitives.hh:139
ACG::SceneGraph::BaseNode
Definition: BaseNode.hh:104
ACG::GLState::set_specular_color
void set_specular_color(const Vec4f &_col)
set specular color
Definition: GLState.cc:737
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::TranslationManipulatorNode::getRenderObjects
void getRenderObjects(IRenderer *_renderer, GLState &_state, const DrawModes::DrawMode &_drawMode, const Material *_mat) override
create renderobjects for shaderpipeline renderer
Definition: TranslationManipulatorNode.cc:771
ACG::SceneGraph::TranslationManipulatorNode::TranslationManipulatorNode
TranslationManipulatorNode(BaseNode *_parent=0, const std::string &_name="<TranslationTranslationManipulatorNode>")
Default constructor.
Definition: TranslationManipulatorNode.cc:127
ACG::SceneGraph::TranslationManipulatorNode::mapToSphere
bool mapToSphere(GLState &_state, const Vec2i &_v2, Vec3d &_v3, StateUpdates _updateStates=None)
Definition: TranslationManipulatorNode.cc:1888
ACG::GLState::set_color
void set_color(const Vec4f &_col)
set color
Definition: GLState.cc:691
ACG::SceneGraph::ACG::SceneGraph::BaseNode::setDirty
void setDirty(bool _dirty=true)
mark node for redrawn
Definition: MeshNode2T_impl.hh:275
ACG::RenderObject::priority
int priority
Priority to allow sorting of objects.
Definition: RenderObject.hh:116
ACG::SceneGraph::DrawModes::DrawMode
Specifies a DrawMode.
Definition: DrawModes.hh:288
ACG::GLState::viewing_ray
void viewing_ray(int _x, int _y, Vec3d &_origin, Vec3d &_direction) const
Definition: GLState.cc:930
OpenMesh::VectorT::length
auto length() const -> decltype(std::declval< VectorT< S, DIM >>().norm())
compute squared euclidean norm
Definition: Vector11T.hh:423
ACG::SceneGraph::ACG::GLState::blendFunc
static void blendFunc(GLenum _sfactor, GLenum _dfactor)
replaces glBlendFunc, supports locking
Definition: MeshNode2T_impl.hh:307
ACG::SceneGraph::TranslationManipulatorNode::update_rotation
void update_rotation(GLState &_state)
update the internal rotation matrix ( internal rotation may be changed without modifiing children of ...
Definition: TranslationManipulatorNode.cc:234
ACG::SceneGraph::TranslationManipulatorNode::directionX
Vec3d directionX() const
Get current direction of x-Axis in world coordinates.
Definition: TranslationManipulatorNode.cc:2149
ACG::SceneGraph::TranslationManipulatorNode::ManipulatorMode
ManipulatorMode
enum to define the manipulator mode
Definition: TranslationManipulatorNode.hh:107
ACG::GLState::pick_set_name
void pick_set_name(size_t _idx)
sets the current name/color (like glLoadName(_idx))
Definition: GLState.cc:1061
ACG::SceneGraph::TranslationManipulatorNode::mapToCylinder
bool mapToCylinder(GLState &_state, const Vec2i &_v2, StateUpdates _updateStates=None)
Definition: TranslationManipulatorNode.cc:1661
ACG::GLState::modelview
const GLMatrixd & modelview() const
get modelview matrix
Definition: GLState.hh:791
OpenMesh::VectorT::sqrnorm
decltype(std::declval< S >() *std::declval< S >()) sqrnorm() const
compute squared euclidean norm
Definition: Vector11T.hh:402
ACG::SceneGraph::ACG::GLState::enable
static void enable(GLenum _cap, bool _warnRemoved=true)
replaces glEnable, but supports locking
ACG::SceneGraph::TranslationManipulatorNode::mouseEvent
virtual void mouseEvent(GLState &_state, QMouseEvent *_event) override
get mouse events
Definition: TranslationManipulatorNode.cc:958
ACG::SceneGraph::TransformNode::setIdentity
virtual void setIdentity()
Definition: TransformNode.cc:112
ACG::SceneGraph::BaseNode::ChildrenFirst
Execute action the children first and then on this node.
Definition: BaseNode.hh:443
ACG::GLState::context_height
int context_height() const
get gl context height
Definition: GLState.hh:830
ACG::GLState::msSinceLastRedraw
unsigned int msSinceLastRedraw() const
time passed since last redraw in milliseconds
Definition: GLState.hh:238
ACG::SceneGraph::TranslationManipulatorNode::update_manipulator_system
void update_manipulator_system(GLState &_state)
set the current state to follow manipulator transformation
Definition: TranslationManipulatorNode.cc:222
ACG::SceneGraph::TranslationManipulatorNode::touched_
bool touched_
stores if this manipulator was used in order to avoid emitting manipulatorMoved unnecessarily ...
Definition: TranslationManipulatorNode.hh:230
ACG::SceneGraph::TranslationManipulatorNode::~TranslationManipulatorNode
~TranslationManipulatorNode()
Destructor.
Definition: TranslationManipulatorNode.cc:196
ACG::RenderObject::blendDest
GLenum blendDest
glBlendFunc: GL_SRC_ALPHA, GL_ZERO, GL_ONE, GL_ONE_MINUS_SRC_ALPHA ...
Definition: RenderObject.hh:247
ACG::SceneGraph::TransformNode::rotation
const GLMatrixd & rotation() const
return rotation matrix
Definition: TransformNode.hh:168
ACG::Vec2d
VectorT< double, 2 > Vec2d
Definition: VectorT.hh:104
ACG::SceneGraph::TranslationManipulatorNode::draw
void draw(GLState &_state, const DrawModes::DrawMode &_drawMode) override
draw the cylinder (if enabled)
Definition: TranslationManipulatorNode.cc:692
OpenMesh::VectorT::normalize
auto normalize() -> decltype(*this/=std::declval< VectorT< S, DIM >>().norm())
Definition: Vector11T.hh:434
ACG::RenderObject
Interface class between scenegraph and renderer.
Definition: RenderObject.hh:98
OpenMesh::is_zero
bool is_zero(const T &_a, Real _eps)
Definition: MathDefs.hh:61
ACG::SceneGraph::ACG::GLState::shadeModel
static void shadeModel(GLenum _mode)
replaces glShadeModel, supports locking
ACG::SceneGraph::Material
Definition: MaterialNode.hh:79
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::SceneGraph::ACG::GLState::depthFunc
const GLenum & depthFunc() const
get glDepthFunc() that is supposed to be active
ACG::Vec3d
VectorT< double, 3 > Vec3d
Definition: VectorT.hh:121
ACG::GLState::context_width
int context_width() const
get gl context width
Definition: GLState.hh:827
ACG::RenderObject::modelview
GLMatrixd modelview
Modelview transform.
Definition: RenderObject.hh:138
ACG::SceneGraph::TranslationManipulatorNode::hitOuterSphere
bool hitOuterSphere(GLState &_state, const Vec2i &_v2)
Determine whether the outer sphere has been hit by the cursor.
Definition: TranslationManipulatorNode.cc:1621