Developer Documentation
TypeLight.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 #include "TypeLight.hh"
45 
46 #define DEF0 "Default Light 0.lgt"
47 #define DEF1 "Default Light 1.lgt"
48 #define DEF2 "Default Light 2.lgt"
49 
50 TypeLightPlugin::TypeLightPlugin() :
51  defaultLights_(true),
52  toolbar_(0),
53  lightOptions_(0),
54  lightAction_(0),
55  moveMode_(0),
56  translateMode_(0),
57  rotateMode_(0),
58  allLightsMode_(0),
59  viewerToolbarAction_(0),
60  onlyTargets_(false),
61  planeDepth_(0.0f),
62  transVec_(0.0),
63  rotation_(true),
64  radius_(0.0),
65  depth_(0.0f),
66  lightCenter_(0.0),
67  lightRadius_(0.0),
68  lightId_(-1),
69  hitLightTrackball_(false),
70  hitTrackball_(false)
71 {
72 
73  // Reset transformation matrix
74  light_matrix_.identity();
75 }
76 
77 bool TypeLightPlugin::registerType() {
78  addDataType("Light",tr("Light"));
79  setTypeIcon( "Light", "LightType.png");
80 
81  return true;
82 }
83 
85 
86  // Add default lights to active scene
87  addDefaultLights();
88 }
89 
90 void TypeLightPlugin::removeDefaultLights() {
91 
92  int light0 = PluginFunctions::getObjectId(DEF0);
93  int light1 = PluginFunctions::getObjectId(DEF1);
94  int light2 = PluginFunctions::getObjectId(DEF2);
95 
96  if(light0 > 0)
97  emit deleteObject(light0);
98  if(light1 > 0)
99  emit deleteObject(light1);
100  if(light2 > 0)
101  emit deleteObject(light2);
102 
103  defaultLights_ = false;
104 }
105 
106 void TypeLightPlugin::addDefaultLights() {
107 
108  // Test if light sources already exist
109  int light0 = PluginFunctions::getObjectId(DEF0);
110  int light1 = PluginFunctions::getObjectId(DEF1);
111  int light2 = PluginFunctions::getObjectId(DEF2);
112 
113  if(light0 == -1) {
114  // Create light 0
115  light0 = addDefaultLight(DEF0);
116 
117  BaseObjectData* obj0(0);
118 
119  if(PluginFunctions::getObject( light0, obj0 )) {
120 
121  LightObject* lightObject0 = PluginFunctions::lightObject(obj0);
122  LightSource* lightSrc0 = PluginFunctions::lightSource(lightObject0);
123 
124  if( lightSrc0 ) {
125  lightSrc0->direction(ACG::Vec3d(0.0,0.0,1.0) );
126  lightSrc0->diffuseColor( ACG::Vec4f(0.55f,0.55f,0.55f,0.0f));
127  lightSrc0->specularColor(ACG::Vec4f(0.55f,0.55f,0.55f,0.0f));
128  lightSrc0->enable();
129  lightSrc0->brightness(1.0);
130  lightSrc0->fixedPosition(true);
131  lightObject0->setName(DEF0);
132  }
133 
134  emit updatedObject(light0, UPDATE_ALL);
135  }
136  }
137 
138  if(light1 == -1) {
139 
140  // Create light 1
141  light1 = addDefaultLight(DEF1);
142 
143  BaseObjectData* obj1(0);
144  if(PluginFunctions::getObject( light1, obj1 )) {
145 
146  LightObject* lightObject1 = PluginFunctions::lightObject(obj1);
147  LightSource* lightSrc1 = PluginFunctions::lightSource(lightObject1);
148 
149  if( lightSrc1 ) {
150  lightSrc1->direction(ACG::Vec3d(-1.0, 1.0, 0.7) );
151  lightSrc1->diffuseColor( ACG::Vec4f(0.55f,0.55f,0.55f,0.0f));
152  lightSrc1->specularColor(ACG::Vec4f(0.55f,0.55f,0.55f,0.0f));
153  lightSrc1->enable();
154  lightSrc1->brightness(1.0);
155  lightSrc1->fixedPosition(true);
156  lightObject1->setName(DEF1);
157  }
158 
159  emit updatedObject(light1, UPDATE_ALL);
160  }
161  }
162 
163  if(light2 == -1) {
164  //Generate the default lights
165  light2 = addDefaultLight(DEF2);
166 
167  BaseObjectData* obj2(0);
168  if(PluginFunctions::getObject( light2, obj2 )) {
169 
170  LightObject* lightObject2 = PluginFunctions::lightObject(obj2);
171  LightSource* lightSrc2 = PluginFunctions::lightSource(lightObject2);
172 
173  if( lightSrc2 ) {
174  lightSrc2->direction(ACG::Vec3d( 1.0, 1.0, 0.7) );
175  lightSrc2->diffuseColor(ACG::Vec4f(0.55f,0.55f,0.55f,0.0f));
176  lightSrc2->specularColor(ACG::Vec4f(0.55f,0.55f,0.55f,0.0f));
177  lightSrc2->enable();
178  lightSrc2->brightness(1.0);
179  lightSrc2->fixedPosition(true);
180  lightObject2->setName(DEF2);
181  }
182 
183  emit updatedObject(light2, UPDATE_ALL);
184  }
185  }
186 
187  defaultLights_ = true;
188 }
189 
190 void TypeLightPlugin::showReducedUi(bool reduced) {
191  viewerToolbarAction_->setVisible(!reduced);
192 }
193 
195 
196  if ( OpenFlipper::Options::gui() ){
197  //PICKMODES
198  emit addPickMode("Separator");
199  emit addHiddenPickMode("MoveLights");
200  emit setPickModeMouseTracking ("MoveLights", true);
201  emit addHiddenPickMode("TranslateLights");
202  emit setPickModeMouseTracking ("TranslateLights", true);
203  emit addHiddenPickMode("RotateLights");
204  emit setPickModeMouseTracking ("RotateLights", true);
205 
206  // Create tool bar
207  toolbar_ = new QToolBar(tr("Transform light sources"));
208 
209  lightAction_ = new QAction(tr("<B>Light mode</B><br>Transform light sources in 3D."), toolbar_);
210  lightAction_->setStatusTip(tr("Transform light sources in 3D."));
211  lightAction_->setIcon(QIcon(OpenFlipper::Options::iconDirStr()+OpenFlipper::Options::dirSeparator()+"light-mode.png") );
212  lightAction_->setCheckable(true);
213  toolbar_->addAction(lightAction_);
214 
215  connect(lightAction_, SIGNAL(triggered(bool)), this, SLOT(slotLightModeRequest(bool)) );
216 
217  // Add toolbar icon with context menu
218  QToolBar* viewerToolbar = 0;
219 
220  emit getToolBar( "Viewer Toolbar", viewerToolbar );
221 
222  if ( viewerToolbar == 0 ) {
223  emit log(LOGERR,"Unable to get Viewer Toolbar!");
224  } else {
225 
226  // Search for picking action...
227  QList< QAction *> toolbarActions = viewerToolbar->actions();
228  QAction* pickAction = 0;
229  for ( int i = 0 ; i < toolbarActions.size() ; ++i ) {
230  if ( toolbarActions[i]->text() == "Pick" )
231  pickAction = toolbarActions[i];
232  }
233 
234  // And append light mode button if found.
235  if (pickAction)
236  viewerToolbarAction_ = viewerToolbar->insertWidget( pickAction, toolbar_ );
237  else
238  viewerToolbarAction_ = viewerToolbar->addWidget( toolbar_ );
239  viewerToolbarAction_->setText(tr("Light"));
240 
241  }
242 
243  lightOptions_ = new QToolBar(tr("Transform light sources"));
244  lightOptions_->setAttribute(Qt::WA_AlwaysShowToolTips, true);
245 
246  QActionGroup* pickGroup = new QActionGroup(lightOptions_);
247  pickGroup->setExclusive (false);
248 
249  moveMode_ = new QAction(tr("Move light source"), pickGroup);
250  moveMode_->setStatusTip(tr("Move light source on virtual trackball around trackball center."));
251  moveMode_->setToolTip(tr("Move light source on virtual trackball around trackball center."));
252  moveMode_->setIcon(QIcon(OpenFlipper::Options::iconDirStr()+OpenFlipper::Options::dirSeparator()+"light-move.png") );
253  moveMode_->setCheckable(true);
254  lightOptions_->addAction(moveMode_);
255 
256  translateMode_ = new QAction(tr("Translate light source"), pickGroup);
257  translateMode_->setStatusTip(tr("Translate light source on plane parallely to viewing plane."));
258  translateMode_->setToolTip(tr("Translate light source on plane parallely to viewing plane."));
259  translateMode_->setIcon(QIcon(OpenFlipper::Options::iconDirStr()+OpenFlipper::Options::dirSeparator()+"light-translate.png") );
260  translateMode_->setCheckable(true);
261  lightOptions_->addAction(translateMode_);
262 
263  rotateMode_ = new QAction(tr("Rotate spotlight direction"), pickGroup);
264  rotateMode_->setStatusTip(tr("Rotate the spotlight direction of a light source."));
265  rotateMode_->setToolTip(tr("Rotate the spotlight direction of a light source."));
266  rotateMode_->setIcon(QIcon(OpenFlipper::Options::iconDirStr()+OpenFlipper::Options::dirSeparator()+"light-rotate.png") );
267  rotateMode_->setCheckable(true);
268  lightOptions_->addAction(rotateMode_);
269 
270  lightOptions_->addSeparator ();
271 
272  allLightsMode_ = new QAction(tr("All lights"), lightOptions_);
273  allLightsMode_->setStatusTip(tr("Transform all light sources if checked. If not, only apply to target light sources."));
274  allLightsMode_->setToolTip(tr("Transform all light sources if checked. If not, only apply to target light sources."));
275  allLightsMode_->setIcon(QIcon(OpenFlipper::Options::iconDirStr()+OpenFlipper::Options::dirSeparator()+"light-alllights.png") );
276  allLightsMode_->setCheckable(true);
277  lightOptions_->addAction(allLightsMode_);
278 
279  connect(pickGroup, SIGNAL(triggered(QAction*)), this, SLOT(slotPickModeRequest(QAction*)) );
280  connect(allLightsMode_, SIGNAL(triggered(bool)), this, SLOT(slotSetAllOrTarget(bool)) );
281 
282  emit setPickModeToolbar ("MoveLights", lightOptions_);
283  emit setPickModeToolbar ("TranslateLights", lightOptions_);
284  emit setPickModeToolbar ("RotateLights", lightOptions_);
285 
286  }
287  // Disable the build in light management and use this plugins light handling
289 
290  // Add default light sources to active scene
291  addDefaultLights();
292 }
293 
294 void TypeLightPlugin::slotPickModeChanged (const std::string& /*_pickMode*/) {
295 
296  if(PluginFunctions::actionMode() != Viewer::LightMode)
297  lightAction_->setChecked(false);
298 }
299 
300 void TypeLightPlugin::slotLightModeRequest(bool /*_checked*/) {
301 
302  PluginFunctions::actionMode(Viewer::LightMode);
303  PluginFunctions::pickMode("MoveLights");
304 
305  lightAction_->setChecked(true);
306 
307  // Chose "MoveLights" pick mode per default
308  moveMode_->setChecked(true);
309  translateMode_->setChecked(false);
310  rotateMode_->setChecked(false);
311 }
312 
313 void TypeLightPlugin::slotPickModeRequest(QAction* _action) {
314 
315  PluginFunctions::actionMode(Viewer::LightMode);
316 
317  if (_action == moveMode_){
318  PluginFunctions::pickMode("MoveLights");
319 
320  lightAction_->setChecked(true);
321  moveMode_->setChecked(true);
322  translateMode_->setChecked(false);
323  rotateMode_->setChecked(false);
324 
325  } else if (_action == translateMode_){
326  PluginFunctions::pickMode("TranslateLights");
327 
328  lightAction_->setChecked(true);
329  moveMode_->setChecked(false);
330  translateMode_->setChecked(true);
331  rotateMode_->setChecked(false);
332 
333  } else if (_action == rotateMode_){
334  PluginFunctions::pickMode("RotateLights");
335 
336  lightAction_->setChecked(true);
337  moveMode_->setChecked(false);
338  translateMode_->setChecked(false);
339  rotateMode_->setChecked(true);
340  }
341 }
342 
343 void TypeLightPlugin::slotSetAllOrTarget(bool _checked) {
344 
345  allLightsMode_->setChecked(_checked);
346  onlyTargets_ = !_checked;
347 }
348 
349 int TypeLightPlugin::addDefaultLight(QString _name) {
350 
351  // new object data struct
352  LightObject* object = new LightObject();
353 
354  // call the local function to update names
355  object->setName( _name );
356 
357  object->defaultLight(true);
358 
359  object->update();
360 
361  object->hide();
362 
363  emit emptyObjectAdded (object->id() );
364 
365  return object->id();
366 }
367 
369 
370  // new object data struct
371  LightObject * object = new LightObject();
372 
373  QString name = QString(tr("New Light %1.lgt").arg( object->id() ));
374 
375  // call the local function to update names
376  QFileInfo f(name);
377  object->setName( f.fileName() );
378 
379  object->defaultLight(false);
380 
381  object->update();
382 
383  object->enablePicking(true);
384 
385  object->hide();
386 
387  emit emptyObjectAdded (object->id() );
388 
389  return object->id();
390 }
391 
393 
394  BaseObject* obj = 0;
395  PluginFunctions::getObject(_id, obj);
396 
397  if(!obj) return;
398 
399  LightObject* light = 0;
400  light = dynamic_cast<LightObject*>(obj);
401 
402  if(!light) return;
403 
404  // Skip default light sources
405  if(light->defaultLight()) return;
406 
407  removeDefaultLights();
408  lightSources_.push_back(_id);
409 }
410 
412 
413  for(uint i = 0; i < lightSources_.size(); ++i) {
414  if(lightSources_[i] == _id) lightSources_.erase(lightSources_.begin() + i);
415  }
416 
417  if(lightSources_.empty() && !defaultLights_) {
418  addDefaultLights();
419  }
420 
421 }
422 
424 
425  // Init depth
426  float d = FLT_MAX;
428 
430  o_it != PluginFunctions::objectsEnd(); ++o_it) {
431 
433  if(lightObject != 0) {
434 
435  LightSource* source = PluginFunctions::lightSource(lightObject);
436  if(source != 0) {
437 
438  ACG::Vec3d z = state.project(source->position());
439 
440  if(!source->directional() && z[2] < d) {
441 
442  // z-value of light source
443  d = z[2];
444  }
445  }
446  }
447  }
448 
449  if(d == FLT_MAX) return 0.0f;
450 
451  return d;
452 }
453 
454 double TypeLightPlugin::getFarthestRadius() {
455 
456  // Init distance
457  double d = 0.0;
459 
461  o_it != PluginFunctions::objectsEnd(); ++o_it) {
462 
464  if(lightObject != 0) {
465 
466  LightSource* source = PluginFunctions::lightSource(lightObject);
467  if(source != 0) {
468 
469  if(!source->directional()) {
470 
471  double tmp_d = fabs((source->position() - c).norm());
472  if(tmp_d > d) d = tmp_d;
473 
474  }
475  }
476  }
477  }
478 
479  return d;
480 }
481 
482 void TypeLightPlugin::slotMouseEventLight(QMouseEvent* _event) {
483 
484  // Only react if in light mode
485  if(PluginFunctions::actionMode() == Viewer::LightMode) {
486  // Get gl state
488 
489  // Invert screen y-axis since the OpenGL y-axis is inverted
490  QPoint pos (_event->x(), state.viewport_height() - _event->y());
491 
492  switch (_event->type())
493  {
494  case QEvent::MouseButtonPress:
495  {
496  // Reset transformation
497  light_matrix_.identity();
498 
499  if(PluginFunctions::pickMode() == "MoveLights" && _event->buttons() & Qt::LeftButton) {
500 
501  radius_ = getFarthestRadius();
502 
503  depth_ = findDepth();
504 
505  // Trackball rotation of light source
506  hitTrackball_ = computeClickOnTrackball(pos, lastPoint3D_, state);
507 
508  rotation_ = true;
509 
510  } else if (PluginFunctions::pickMode() == "TranslateLights" && _event->buttons() & Qt::LeftButton) {
511  // Translation in plane orthogonal to viewing plane
512  lastPoint2D_ = pos;
513 
514  rotation_ = false;
515 
516  } else if(PluginFunctions::pickMode() == "RotateLights" && _event->buttons() & Qt::LeftButton) {
517 
518  QPoint p(_event->x(), _event->y());
519 
520  size_t id = 0;
521  size_t t = 0;
522  ACG::Vec3d v;
524 
525  // Get picked light node
526  if(id != 0) {
527  BaseObjectData* obj = 0;
529 
530  if(obj != 0) {
531  LightObject* light = 0;
532  light = PluginFunctions::lightObject(obj);
533 
534  if(light) {
535 
536  lightCenter_ = light->lightSource()->position();
537 
538  ACG::Vec3d bbMin, bbMax;
539  light->lightNodeVis()->boundingBox(bbMin, bbMax);
540  lightRadius_ = (bbMin - bbMax).length()/4;
541  lightId_ = id;
542 
543  // Set depth
544  depth_ = state.project(light->lightSource()->position())[2];
545  }
546  }
547  }
548 
549  if(lightId_ == -1) break;
550 
551  hitLightTrackball_ = computeClickOnLightTrackball(pos, lastPoint3D_, state);
552  }
553 
554  break;
555  }
556 
557  case QEvent::MouseButtonRelease:
558  {
559  lightId_ = -1;
560  hitLightTrackball_ = false;
561  hitTrackball_ = false;
562  }
563 
564  case QEvent::MouseMove:
565  {
566 
567  if (PluginFunctions::pickMode() == "MoveLights" && _event->buttons() & Qt::LeftButton) {
568 
569  // rotate lights
570  if ((pos.x() < 0) || (pos.x() > (int)state.viewport_width()) ||
571  (pos.y() < 0) || (pos.y() > (int)state.viewport_height()))
572  break;
573 
574  // Compute first intersection if this is the first
575  // hit of the trackball
576  if(hitTrackball_ == false) {
577 
578  hitTrackball_ = computeClickOnTrackball(pos, lastPoint3D_, state);
579 
580  } else {
581 
582  ACG::Vec3d v1 = lastPoint3D_;
583  v1.normalize();
584 
585  hitTrackball_ = computeClickOnTrackball(pos, lastPoint3D_, state);
586 
587  ACG::Vec3d v2 = lastPoint3D_;
588  v2.normalize();
589 
590  ACG::Vec3d axis = v1 % v2;
591 
592  axis = state.inverse_modelview().transform_vector(axis);
593 
594  axis.normalize();
595 
596  double angle = acos(v1 | v2) * 180/M_PI;
597 
598  rotateLights(axis, angle);
599  }
600 
601  } else if (PluginFunctions::pickMode() == "TranslateLights" && _event->buttons() & Qt::LeftButton) {
602 
603  // Get depth of plane along which we want to translate
604  planeDepth_ = findDepth();
605 
606  ACG::Vec3d p0(pos.x(), pos.y(), planeDepth_);
607  p0 = state.unproject(p0);
608 
609  ACG::Vec3d p1(lastPoint2D_.x(), lastPoint2D_.y(), planeDepth_);
610  p1 = state.unproject(p1);
611 
612  // Translation in plane
613  transVec_ = p0 - p1;
614 
615  lastPoint2D_ = pos;
616 
617  updateLights();
618 
619  } else if (PluginFunctions::pickMode() == "RotateLights" && _event->buttons() & Qt::LeftButton) {
620 
621  // rotate spot light direction
622  if ( (pos.x() < 0) || (pos.x() > (int)state.viewport_width()) ||
623  (pos.y() < 0) || (pos.y() > (int)state.viewport_height()) ||
624  (lightId_ == -1)) break;
625 
626  // Compute first intersection if this is the first
627  // hit of the trackball
628  if(hitLightTrackball_ == false) {
629 
630  hitLightTrackball_ = computeClickOnLightTrackball(pos, lastPoint3D_, state);
631 
632  } else {
633 
634  ACG::Vec3d v1 = lastPoint3D_;
635  v1.normalize();
636 
637  hitLightTrackball_ = computeClickOnLightTrackball(pos, lastPoint3D_, state);
638 
639  ACG::Vec3d v2 = lastPoint3D_;
640  v2.normalize();
641 
642  ACG::Vec3d axis = v1 % v2;
643 
644  axis = state.inverse_modelview().transform_vector(axis);
645 
646  axis.normalize();
647 
648  double angle = acos(v1 | v2) * 180/M_PI;
649 
650  rotateLightDirection(axis, angle);
651  }
652  }
653 
654  break;
655  }
656 
657  default: // avoid warning
658  break;
659  }
660  }
661 
662  // interaction
665 }
666 
667 bool TypeLightPlugin::computeClickOnTrackball(const QPoint& _v2D, ACG::Vec3d& _clickOnSphere, ACG::GLState& _state) {
668 
669  bool hit = true;
670 
671  ACG::Vec3d clickInWorld = _state.unproject(ACG::Vec3d(_v2D.x(), _v2D.y(), depth_));
672 
673  clickInWorld = _state.modelview().transform_point(clickInWorld);
674 
676 
677  c = _state.modelview().transform_point(c);
678 
679  ACG::Vec3d clickRelToC = (clickInWorld - c);
680 
681  double x = clickRelToC[0];
682  double y = clickRelToC[1];
683 
684  // radius_ contains the radius of the trackball of the most
685  // distant light source
686  double sq = radius_*radius_ - x*x - y*y;
687 
688  double z = sq > 0.0 ? sqrt(sq) : 0.0;
689 
690  if(sq <= 0.0) hit = false;
691 
692  // Set point on sphere to referenced variable
693  _clickOnSphere = ACG::Vec3d(x, y, z);
694 
695  return hit;
696 }
697 
698 bool TypeLightPlugin::computeClickOnLightTrackball(const QPoint& _v2D, ACG::Vec3d& _clickOnSphere, ACG::GLState& _state) {
699 
700  bool hit = true;
701 
702  ACG::Vec3d clickInWorld = _state.unproject(ACG::Vec3d(_v2D.x(), _v2D.y(), depth_));
703 
704  clickInWorld = _state.modelview().transform_point(clickInWorld);
705 
706  ACG::Vec3d c = lightCenter_;
707 
708  c = _state.modelview().transform_point(c);
709 
710  ACG::Vec3d clickRelToC = (clickInWorld - c);
711 
712  double x = clickRelToC[0];
713  double y = clickRelToC[1];
714 
715  // radius_ contains the radius of the trackball of the most
716  // distant light source
717  double sq = lightRadius_*lightRadius_ - x*x - y*y;
718 
719  double z = sq > 0.0 ? sqrt(sq) : 0.0;
720 
721  if(sq <= 0.0) hit = false;
722 
723  // Set point on sphere to referenced variable
724  _clickOnSphere = ACG::Vec3d(x, y, z);
725 
726  return hit;
727 }
728 
729 void TypeLightPlugin::rotateLights(ACG::Vec3d& _axis, double _angle) {
730 
731  // Rotate lights
732  light_matrix_.rotate(_angle, _axis[0], _axis[1], _axis[2]);
733 
734  // Transform positions
735  updateLights();
736 }
737 
739 
740  ACG::GLMatrixd m;
741 
742  m.identity();
743  m.rotate(_angle, _axis[0], _axis[1], _axis[2]);
744 
745  // Get picked light node
746  if(lightId_ != 0) {
747  BaseObjectData* obj = 0;
748  PluginFunctions::getPickedObject(lightId_, obj);
749 
750  if(obj != 0) {
751  LightObject* light = 0;
752  light = PluginFunctions::lightObject(obj);
753 
754  if(light) {
755 
756  ACG::Vec3d spot = light->lightSource()->spotDirection();
757  spot = m.transform_vector(spot);
758  light->lightSource()->spotDirection(spot);
759 
760  emit updatedObject(light->id(), UPDATE_ALL);
761  }
762  }
763  }
764 }
765 
767 
769 
771  o_it != PluginFunctions::objectsEnd(); ++o_it) {
772 
774  if(lightObject != 0) {
775 
776  LightSource* source = PluginFunctions::lightSource(lightObject);
777  if(source != 0) {
778 
779  // If light source is directional, we only care about rotations not translations!
780  if( source->directional() && rotation_) {
781  std::cerr << "Not implemented yet! rotate directional light sources" << std::endl;
782  }
783 
784 
785  // Skip if light source is directional
786  if(!source->directional() && rotation_) {
787 
788  // Rotate light source relatively to trackball center:
789 
790  // Get light source's position
791  ACG::Vec3d p = source->position();
792  // Vector point from trackball center to light source position
793  ACG::Vec3d r = p - c;
794  // Rotate this vector
795  r = light_matrix_.transform_vector(r);
796  // ... and set new position.
797  source->position(c + r);
798 
799  emit updatedObject(lightObject->id(), UPDATE_ALL);
800 
801  } else if(!source->directional() && !rotation_) {
802 
803  // Translate light on plane
804 
805  // Get light source's position
806  ACG::Vec3d p = source->position();
807  p += transVec_;
808  source->position(p);
809 
810  emit updatedObject(lightObject->id(), UPDATE_ALL);
811  }
812  }
813 
814  }
815  }
816 
817  // Reset light source transformation matrix
818  light_matrix_.identity();
819 
820  // Reset translation vector
821  transVec_ = ACG::Vec3d(0.0);
822 }
823 
const ACG::Vec3d trackBallCenter(int _viewer)
Get the trackball Center.
const UpdateType UPDATE_ALL(UpdateTypeSet(1))
Identifier for all updates.
bool defaultLight() const
Is light default light source?
Definition: LightObject.hh:124
const GLMatrixd & inverse_modelview() const
get inverse modelview matrix
Definition: GLState.hh:811
void slotAllCleared()
Called if the whole scene is cleared.
Definition: TypeLight.cc:84
void addedEmptyObject(int _id)
An empty object has been added.
Definition: TypeLight.cc:392
void rotateLights(ACG::Vec3d &_axis, double _angle)
Rotate light sources.
Definition: TypeLight.cc:729
bool scenegraphPick(ACG::SceneGraph::PickTarget _pickTarget, const QPoint &_mousePos, size_t &_nodeIdx, size_t &_targetIdx, ACG::Vec3d *_hitPointPtr=0)
Execute picking operation on scenegraph.
int getObjectId(const QString &_name)
pick any of the prior targets (should be implemented for all nodes)
Definition: PickTarget.hh:84
LightNode * lightNodeVis()
Get the scenegraph Node.
Definition: LightObject.cc:231
bool directional() const
Check if the light source is a directional light source.
Definition: LightNode.cc:127
void spotDirection(Vec3d _pos)
Set spot direction.
Definition: LightNode.cc:141
LightSource * lightSource()
Definition: LightObject.cc:326
void specularColor(Vec4f _color)
set Specular color for LightSource
Definition: LightNode.cc:160
unsigned int activeExaminer()
Get the id of the examiner which got the last mouse events.
int id() const
Definition: BaseObject.cc:190
bool getPickedObject(const size_t _node_idx, BaseObjectData *&_object)
Get the picked mesh.
bool computeClickOnTrackball(const QPoint &_v2D, ACG::Vec3d &_clickOnSphere, ACG::GLState &_state)
Compute click on trackball containing the light source.
Definition: TypeLight.cc:667
void enable()
enable LightSource
Definition: LightNode.cc:131
int viewport_width() const
get viewport width
Definition: GLState.hh:822
auto normalize() -> decltype(*this/=std::declval< VectorT< S, DIM >>().norm())
Definition: Vector11T.hh:429
void updateLights()
Update light sources&#39; positions.
Definition: TypeLight.cc:766
const QStringList TARGET_OBJECTS("target")
Iterable object range.
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)
void slotPickModeChanged(const std::string &_pickMode)
The pickingMode has changed.
Definition: TypeLight.cc:294
const QStringList ALL_OBJECTS
Iterable object range.
void rotateLightDirection(ACG::Vec3d &_axis, double _angle)
Rotate spot light direction.
Definition: TypeLight.cc:738
LightObject * lightObject(BaseObjectData *_object)
Cast an BaseObject to a LightObject if possible.
void fixedPosition(bool _state)
make LightSource fixed or moveable with ModelViewMatrix
Definition: LightNode.cc:172
bool getObject(const int _identifier, BaseObject *&_object)
Get the object which has the given identifier.
DLLEXPORT void setTypeIcon(DataType _id, QString _icon)
Set an Icon for a given DataType.
Definition: Types.cc:223
Viewer::ViewerProperties & viewerProperties(int _id)
Get the viewer properties Use this functions to get basic viewer properties such as backgroundcolor o...
Vec3d unproject(const Vec3d &_winPoint) const
unproject point in window coordinates _winPoint to world coordinates
Definition: GLState.cc:651
Vec3d project(const Vec3d &_point) const
project point in world coordinates to window coordinates
Definition: GLState.cc:640
void disableExaminerLightHandling()
Disable the core light handling.
VectorT< double, 3 > Vec3d
Definition: VectorT.hh:121
int viewport_height() const
get viewport height
Definition: GLState.hh:824
Structure to hold options for one LightSource.
Definition: LightNode.hh:85
DLLEXPORT DataType addDataType(QString _name, QString _readableName)
Adds a datatype and returns the id for the new type.
Definition: Types.cc:117
void diffuseColor(Vec4f _color)
set Diffuse color for LightSource
Definition: LightNode.cc:154
Vec3d direction() const
Get direction of the light source.
Definition: LightNode.cc:123
const GLMatrixd & modelview() const
get modelview matrix
Definition: GLState.hh:791
DLLEXPORT ObjectIterator objectsEnd()
Return Iterator to Object End.
void position(Vec3d _pos)
Set position for LightSource.
Definition: LightNode.cc:108
void identity()
setup an identity matrix
ACG::GLState & glState()
Get the glState of the Viewer.
Viewer::ActionMode actionMode()
Get the current Action mode.
void objectDeleted(int _id)
An object was deleted.
Definition: TypeLight.cc:411
bool computeClickOnLightTrackball(const QPoint &_v2D, ACG::Vec3d &_clickOnSphere, ACG::GLState &_state)
Compute click on trackball of light source.
Definition: TypeLight.cc:698
void rotate(Scalar angle, Scalar x, Scalar y, Scalar z, MultiplyFrom _mult_from=MULT_FROM_RIGHT)
LightSource * lightSource(BaseObjectData *_object)
Get the lightSource in this Object.
void setName(QString _name)
Set the name of the Object.
Definition: LightObject.cc:213
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)
void boundingBox(ACG::Vec3d &, ACG::Vec3d &)
Get bounding box (for visualization purposes)
Definition: LightNode.cc:267
void pluginsInitialized()
Initialize Plugin step 2.
Definition: TypeLight.cc:194
void traverse(ACG::SceneGraph::MouseEventAction &_action)
void slotMouseEventLight(QMouseEvent *_event)
Mouse Event from main application ( Light Mode )
Definition: TypeLight.cc:482
const std::string pickMode()
Get the current Picking mode.
int addEmpty()
Create an empty object.
Definition: TypeLight.cc:368
float findDepth()
Find depth of nearest light source.
Definition: TypeLight.cc:423