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