LightNode.cc 23.9 KB
Newer Older
Jan Möbius's avatar
Jan Möbius committed
1
/*===========================================================================*\
Jan Möbius's avatar
Jan Möbius committed
2 3
*                                                                            *
*                              OpenFlipper                                   *
Martin Schultz's avatar
Martin Schultz committed
4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
 *           Copyright (c) 2001-2015, RWTH-Aachen University                 *
 *           Department of Computer Graphics and Multimedia                  *
 *                          All rights reserved.                             *
 *                            www.openflipper.org                            *
 *                                                                           *
 *---------------------------------------------------------------------------*
 * This file is part of OpenFlipper.                                         *
 *---------------------------------------------------------------------------*
 *                                                                           *
 * Redistribution and use in source and binary forms, with or without        *
 * modification, are permitted provided that the following conditions        *
 * are met:                                                                  *
 *                                                                           *
 * 1. Redistributions of source code must retain the above copyright notice, *
 *    this list of conditions and the following disclaimer.                  *
 *                                                                           *
 * 2. Redistributions in binary form must reproduce the above copyright      *
 *    notice, this list of conditions and the following disclaimer in the    *
 *    documentation and/or other materials provided with the distribution.   *
 *                                                                           *
 * 3. Neither the name of the copyright holder nor the names of its          *
 *    contributors may be used to endorse or promote products derived from   *
 *    this software without specific prior written permission.               *
 *                                                                           *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS       *
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *
 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A           *
 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER *
 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,  *
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,       *
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR        *
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF    *
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING      *
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS        *
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.              *
Jan Möbius's avatar
Jan Möbius committed
39
*                                                                            *
Jan Möbius's avatar
Jan Möbius committed
40 41 42
\*===========================================================================*/

/*===========================================================================*\
Jan Möbius's avatar
Jan Möbius committed
43 44 45 46 47
*                                                                            *
*   $Revision$                                                       *
*   $LastChangedBy$                                                *
*   $Date$                     *
*                                                                            *
Jan Möbius's avatar
Jan Möbius committed
48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63
\*===========================================================================*/




//=============================================================================
//
//  CLASS LightNode - IMPLEMENTATION
//
//=============================================================================


//== INCLUDES =================================================================


#include "LightNode.hh"
Jan Möbius's avatar
Jan Möbius committed
64
#include <ACG/GL/IRenderer.hh>
Jan Möbius's avatar
Jan Möbius committed
65

Jan Möbius's avatar
Jan Möbius committed
66
#ifndef M_PI
Mike Kremer's avatar
Mike Kremer committed
67
#define M_PI 3.14159265358979323846
Jan Möbius's avatar
Jan Möbius committed
68
#endif
Jan Möbius's avatar
Jan Möbius committed
69 70 71 72 73 74

//== NAMESPACES ===============================================================

namespace ACG {
namespace SceneGraph {

75
//== IMPLEMENTATION ==========================================================
Jan Möbius's avatar
Jan Möbius committed
76

77 78
static LightSourceHandle* lightSourceHandle = 0;

Jan Möbius's avatar
Jan Möbius committed
79 80 81 82 83 84 85
//default Constructor
LightSource::LightSource()
{
  // set OpenGL defaults
  enabled_              = false;
  fixedPosition_        = false;

Matthias Möller's avatar
Matthias Möller committed
86 87 88
  ambientColor_         = Vec4f(0.1f,0.1f,0.1f,1.f);
  diffuseColor_         = Vec4f(1.f,1.f,1.f,1.f);
  specularColor_        = Vec4f(1.f,1.f,1.f,1.f);
89

Matthias Möller's avatar
Matthias Möller committed
90 91
  position_             = Vec4f(0.f,0.f,1.f,0.f);
  realPosition_         = Vec4f(0.f,0.f,1.f,0.f);
92

93
  spotDirection_        = Vec3d(0.0,0.0,-1.0);
Mike Kremer's avatar
Mike Kremer committed
94
  realSpotDirection_    = Vec3d(0.0,0.0,-1.0);
95

96 97
  // Holds initial light source position
  // converted to camera coordinates
Matthias Möller's avatar
Matthias Möller committed
98
  initialPosition_      = Vec4f(0.f, 0.f, 0.f, 0.f);
99 100
  initialSpotDirection_ = Vec3d(0.0, 0.0, -1.0);
  initialPositionInit_  = false;
101

Jan Möbius's avatar
Jan Möbius committed
102
  spotExponent_         = 0;
103
  spotCutoff_           = 180;
Jan Möbius's avatar
Jan Möbius committed
104 105 106 107

  constantAttenuation_  = 1;
  linearAttenuation_    = 0;
  quadraticAttenuation_ = 0;
108

109
  brightness_           = 1.0f;
110

111
  radius_               = 0.1f;
Jan Möbius's avatar
Jan Möbius committed
112 113
}

114
void LightSource::position( Vec3d _pos){
Jan Möbius's avatar
Jan Möbius committed
115
  // Set homogeneous coordinte to 1.0 to get a positional light source
116
  position_ = Vec4d( _pos[0],_pos[1],_pos[2],1.0);
Jan Möbius's avatar
Jan Möbius committed
117 118
}

119
Vec3d LightSource::position() const {
120
  return Vec3d( position_[0], position_[1], position_[2]);
Jan Möbius's avatar
Jan Möbius committed
121 122
}

123
void LightSource::direction( Vec3d _pos) {
Jan Möbius's avatar
Jan Möbius committed
124 125
  // Set homogeneous coordinate of position to 0.0 to tell OpenGL
  // that this is a directional light source
126
  position_ = Vec4d( _pos[0],_pos[1],_pos[2],0.0);
Jan Möbius's avatar
Jan Möbius committed
127 128
}

129
Vec3d LightSource::direction() const {
130
    return Vec3d(position_[0], position_[1], position_[2]);
131 132
}

133
bool LightSource::directional() const {
Jan Möbius's avatar
Jan Möbius committed
134 135 136 137 138 139 140 141 142
  return ( position_[3] == 0.0  );
}

void LightSource::enable()
{ enabled_ = true; }

void LightSource::disable()
{ enabled_ = false; }

143
bool LightSource::enabled() const {
Jan Möbius's avatar
Jan Möbius committed
144 145 146
  return enabled_;
}

147
void LightSource::spotDirection( Vec3d _pos)
Jan Möbius's avatar
Jan Möbius committed
148 149
{ spotDirection_ = _pos; }

150 151 152
Vec3d LightSource::spotDirection( ) const {
  return Vec3d(spotDirection_[0],spotDirection_[1],spotDirection_[2]);
}
Jan Möbius's avatar
Jan Möbius committed
153 154 155 156

void LightSource::ambientColor(  Vec4f _color)
{ ambientColor_ = _color; }

157
Vec4f LightSource::ambientColor() const
Jan Möbius's avatar
Jan Möbius committed
158 159 160 161 162
{ return ambientColor_; }

void LightSource::diffuseColor(  Vec4f _color)
{ diffuseColor_ = _color; }

163
Vec4f LightSource::diffuseColor() const
Jan Möbius's avatar
Jan Möbius committed
164 165 166 167 168
{ return diffuseColor_; }

void LightSource::specularColor(  Vec4f _color)
{ specularColor_ = _color; }

169
Vec4f LightSource::specularColor() const
Jan Möbius's avatar
Jan Möbius committed
170 171
{ return specularColor_; }

172 173 174 175 176 177
void LightSource::setColor(const Vec4f& _ambient, const Vec4f& _diffuse, const Vec4f& _specular) {
    ambientColor_ = _ambient;
    diffuseColor_ = _diffuse;
    specularColor_ = _specular;
}

Jan Möbius's avatar
Jan Möbius committed
178 179 180
void LightSource::fixedPosition( bool _state)
{ fixedPosition_ = _state; }

181 182
bool LightSource::fixedPosition() const {
  return fixedPosition_;
Jan Möbius's avatar
Jan Möbius committed
183 184 185 186 187 188
}

void LightSource::spotExponent(float _exponent) {
    spotExponent_ = _exponent;
}

189
float LightSource::spotExponent() const {
Jan Möbius's avatar
Jan Möbius committed
190 191 192 193 194 195 196
    return spotExponent_;
}

void LightSource::spotCutoff(float _cutoff) {
    spotCutoff_ = _cutoff;
}

197
float LightSource::spotCutoff() const {
Jan Möbius's avatar
Jan Möbius committed
198 199 200 201 202 203 204
    return spotCutoff_;
}

void LightSource::constantAttenuation(float _constantAttenuation) {
    constantAttenuation_ = _constantAttenuation;
}

205
float LightSource::constantAttenuation() const {
Jan Möbius's avatar
Jan Möbius committed
206 207 208 209 210 211 212
    return constantAttenuation_;
}

void LightSource::linearAttenuation(float _linearAttenuation) {
    linearAttenuation_ = _linearAttenuation;
}

213
float LightSource::linearAttenuation() const {
Jan Möbius's avatar
Jan Möbius committed
214 215 216 217 218 219 220
    return linearAttenuation_;
}

void LightSource::quadraticAttenuation(float _quadraticAttenuation) {
    quadraticAttenuation_ = _quadraticAttenuation;
}

221
float LightSource::quadraticAttenuation() const {
Jan Möbius's avatar
Jan Möbius committed
222 223 224
    return quadraticAttenuation_;
}

225 226 227
void LightSource::brightness(float _brightness) {
    brightness_ = _brightness;
}
Jan Möbius's avatar
Jan Möbius committed
228

229 230 231
float LightSource::brightness() const {
    return brightness_;
}
Jan Möbius's avatar
Jan Möbius committed
232

233 234
LightNode::LightNode( BaseNode* _parent,
    const std::string&   _name)
Jan Möbius's avatar
Jan Möbius committed
235
  : BaseNode(_parent, _name),
236 237
    visualize_(false),
    lightId_(GL_INVALID_ENUM) {
238

239 240 241
    if(lightSourceHandle == 0) {
        lightSourceHandle = new LightSourceHandle();
    }
242 243 244

    sphere_ = new ACG::GLSphere(10, 10);
    cone_ = new ACG::GLCone(10, 10, 1.0f, 1.0f, false, true);
Jan Möbius's avatar
Jan Möbius committed
245 246
}

247 248 249
//----------------------------------------------------------------------------

LightNode::~LightNode() {
250 251 252 253 254
  if (sphere_)
    delete sphere_;

  if (cone_)
    delete cone_;
255
}
256

Jan Möbius's avatar
Jan Möbius committed
257
//----------------------------------------------------------------------------
Jan Möbius's avatar
Jan Möbius committed
258 259 260 261 262 263 264

void LightNode::getLightSource(LightSource* _light) const
{
  memcpy(_light, &light_, sizeof(LightSource));
}

//----------------------------------------------------------------------------
Jan Möbius's avatar
Jan Möbius committed
265

266 267 268 269 270 271 272
void LightNode::getLightSourceViewSpace( LightSource* _light ) const
{
  memcpy(_light, &transformedLight_, sizeof(LightSource));
}

//----------------------------------------------------------------------------

273
void LightNode::boundingBox(ACG::Vec3d& _bbMin, ACG::Vec3d& _bbMax) {
274

275
    if( visualize_ && !light_.directional() ) {
276 277 278 279 280 281 282
        ACG::Vec3d r;
        if(light_.fixedPosition())
            r = ACG::Vec3d((double)light_.realPosition_[0],
                           (double)light_.realPosition_[1],
                           (double)light_.realPosition_[2]);
        else
            r = light_.position();
283 284
        _bbMin.minimize( r - Vec3d(light_.radius()*3) );
        _bbMax.maximize( r + Vec3d(light_.radius()*3) );
285 286 287 288 289
    }
}

//----------------------------------------------------------------------------

290
void LightNode::draw(GLState& _state, const DrawModes::DrawMode& /*_drawMode*/) {
291

292 293
    // Visualize light node
    if(visualize_ && !light_.directional()) {
294

295 296 297 298 299 300 301
        // Get initial camera coords of light if in fixed
        // mode and if they haven't been computed yet
        if(light_.fixedPosition_ && !light_.initialPositionInit_) {
            light_.initialPosition_ = _state.modelview() * light_.position_;
            light_.initialSpotDirection_ = _state.modelview().transform_vector(light_.spotDirection());
            light_.initialPositionInit_ = true;
        }
302

Mike Kremer's avatar
Mike Kremer committed
303
        if(light_.fixedPosition_) {
304 305
             light_.realPosition_ = _state.inverse_modelview() * light_.initialPosition_;
             light_.realSpotDirection_ = _state.inverse_modelview().transform_vector(light_.initialSpotDirection_);
Mike Kremer's avatar
Mike Kremer committed
306 307 308 309
         } else {
             light_.realPosition_ = light_.position_;
             light_.realSpotDirection_ = light_.spotDirection_;
         }
310

Mike Kremer's avatar
Mike Kremer committed
311 312 313
         ACG::Vec3f p = ACG::Vec3f(light_.realPosition_[0],
                                   light_.realPosition_[1],
                                   light_.realPosition_[2]);
314 315
         ACG::Vec3d spotDir = light_.realSpotDirection_;

316 317 318
         ACG::Vec4f ac = light_.ambientColor();
         ACG::Vec4f dc = light_.diffuseColor();
         ACG::Vec4f sc = light_.specularColor();
319

320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335
         // Make light sources appear as bright as possible
         float max = 0;
         for(int i = 0; i < 3; ++i) {
             if(ac[i] > max) max = ac[i];
         }
         ac += ACG::Vec4f(1.0f - max);
         max = 0;
         for(int i = 0; i < 3; ++i) {
             if(dc[i] > max) max = dc[i];
         }
         dc += ACG::Vec4f(1.0f - max);
         max = 0;
         for(int i = 0; i < 3; ++i) {
             if(sc[i] > max) max = sc[i];
         }
         sc += ACG::Vec4f(1.0f - max);
336

337
         // Backup variables
Mike Kremer's avatar
Mike Kremer committed
338
         GLboolean lighting_backup;
339

Mike Kremer's avatar
Mike Kremer committed
340
         // Origin
341
         _state.push_modelview_matrix();
Mike Kremer's avatar
Mike Kremer committed
342 343
         // Transform to light origin and direction
         _state.translate(p[0], p[1], p[2]);
344

Mike Kremer's avatar
Mike Kremer committed
345 346
         // Set lighting
         glGetBooleanv(GL_LIGHTING, &lighting_backup);
347
         ACG::GLState::enable(GL_LIGHTING);
348

349 350 351 352
         // Make light directional just for the drawing
         // of itself
         bool backup_directional = light_.directional();
         ACG::Vec3d backup_position = light_.position();
353

354 355
         // Get light id
         lightId_ = lightSourceHandle->getLight(this);
356

357 358
         // Return if we don't have a valid light source
         if(lightId_ == GL_INVALID_ENUM) {
359

360
             // Reset all stored attributes before returning
361
             if(!lighting_backup) ACG::GLState::disable(GL_LIGHTING);
362

363
             _state.pop_modelview_matrix();
364

365 366
             return;
         }
367

368
         glLightf(lightId_, GL_SPOT_EXPONENT, 0.0f);
369 370 371 372 373 374
         float pos[4];
         pos [0] = backup_position[0];
         pos [1] = backup_position[1];
         pos [2] = backup_position[2];
         pos [3] = 0.0f;

375
         glLightfv(lightId_, GL_POSITION, pos);
376

377 378 379 380 381 382 383
         // Set colors
         float gl_ac[] = {ac[0], ac[1], ac[2], ac[3]};
         glLightfv(lightId_, GL_AMBIENT, gl_ac);
         float gl_dc[] = {dc[0], dc[1], dc[2], dc[3]};
         glLightfv(lightId_, GL_DIFFUSE, gl_dc);
         float gl_sc[] = {sc[0], sc[1], sc[2], sc[3]};
         glLightfv(lightId_, GL_SPECULAR, gl_sc);
384

385
         ACG::GLState::enable(lightId_);
386

387
         sphere_->draw(_state, light_.radius());
388

Mike Kremer's avatar
Mike Kremer committed
389 390 391 392
         // Visualize spot cone (or direction)
         if(light_.spotCutoff() < 180.0f) {
             // Note: if the cutoff angle is 180, the light source
             // is a point light emitting light into all directions equally
393

Mike Kremer's avatar
Mike Kremer committed
394 395
             // Rotate into light direction
             ACG::Vec3d z = ACG::Vec3d(0.0f, 0.0f, 1.0f);
396
             ACG::Vec3d spot = spotDir;
Mike Kremer's avatar
Mike Kremer committed
397 398 399 400
             float angle = acos((z | spot)/(z.norm()*spot.norm()));
             angle = angle*360/(2*M_PI);
             ACG::Vec3d rA = z % spot;
             _state.rotate(angle, rA[0], rA[1], rA[2]);
401

402
             // Inverse normal orientation
403 404 405 406
             cone_->setNormalOrientation(ACG::GLPrimitive::INSIDE);
             cone_->setBottomRadius(light_.radius()/6.0f);
             cone_->setTopRadius(light_.radius()/6.0f);
             cone_->draw(_state, light_.radius()*2.0f);
Mike Kremer's avatar
Mike Kremer committed
407 408
             _state.translate(0.0, 0.0, light_.radius()*2);
             // Draw arrow tip
409 410 411
             cone_->setBottomRadius(light_.radius()/2.0f);
             cone_->setTopRadius(0.0f);
             cone_->draw(_state, light_.radius());
Mike Kremer's avatar
Mike Kremer committed
412
         }
413

414 415
         // Free light id
         lightSourceHandle->removeLight(this);
416

Mike Kremer's avatar
Mike Kremer committed
417
         // Undo state changes
418

419 420 421
         if(!backup_directional) {
             light_.position(backup_position);
         }
422

Mike Kremer's avatar
Mike Kremer committed
423
         // Lighting
424
         if(!lighting_backup) ACG::GLState::disable(GL_LIGHTING);
425

Mike Kremer's avatar
Mike Kremer committed
426 427
         _state.pop_modelview_matrix();
     }
428

429 430
}

431 432 433
void LightNode::pick(GLState& _state, PickTarget _target) {

    GLenum prev_depth = _state.depthFunc();
434

435 436
    if (_target == PICK_FACE ||
       _target == PICK_ANYTHING) {
437

438 439
        // Visualize light node
        if(visualize_ && !light_.directional()) {
440

441 442 443 444 445 446 447
            // Get initial camera coords of light if in fixed
            // mode and if they haven't been computed yet
            if(light_.fixedPosition_ && !light_.initialPositionInit_) {
                light_.initialPosition_ = _state.modelview() * light_.position_;
                light_.initialSpotDirection_ = _state.modelview().transform_vector(light_.spotDirection());
                light_.initialPositionInit_ = true;
            }
448

449
            if(light_.fixedPosition_) {
450 451
                 light_.realPosition_ = _state.inverse_modelview() * light_.initialPosition_;
                 light_.realSpotDirection_ = _state.inverse_modelview().transform_vector(light_.initialSpotDirection_);
452 453 454 455
             } else {
                 light_.realPosition_ = light_.position_;
                 light_.realSpotDirection_ = light_.spotDirection_;
             }
456

457 458
             // Enable depth test but store original status
             glPushAttrib(GL_DEPTH_BUFFER_BIT);
459 460
             ACG::GLState::enable(GL_DEPTH_TEST);
             ACG::GLState::depthFunc(GL_LEQUAL);
461

462 463
             _state.pick_set_maximum(1);
             _state.pick_set_name(0);
464

465 466 467
             ACG::Vec3f p = ACG::Vec3f(light_.realPosition_[0],
                                       light_.realPosition_[1],
                                       light_.realPosition_[2]);
468 469
             ACG::Vec3d spotDir = light_.realSpotDirection_;

470 471 472 473
             // Origin
             _state.push_modelview_matrix();
             // Transform to light origin and direction
             _state.translate(p[0], p[1], p[2]);
474

475
             sphere_->draw(_state, light_.radius());
476 477 478 479 480

             // Visualize spot cone (or direction)
             if(light_.spotCutoff() < 180.0f) {
                 // Note: if the cutoff angle is 180, the light source
                 // is a point light emitting light into all directions equally
481

482 483 484 485 486 487 488 489
                 // Rotate into light direction
                 ACG::Vec3d z = ACG::Vec3d(0.0f, 0.0f, 1.0f);
                 ACG::Vec3d spot = spotDir;
                 float angle = acos((z | spot)/(z.norm()*spot.norm()));
                 angle = angle*360/(2*M_PI);
                 ACG::Vec3d rA = z % spot;
                 _state.rotate(angle, rA[0], rA[1], rA[2]);

490 491 492 493
                 cone_->setNormalOrientation(ACG::GLPrimitive::OUTSIDE);
                 cone_->setBottomRadius(light_.radius()/6.0f);
                 cone_->setTopRadius(light_.radius()/6.0f);
                 cone_->draw(_state, light_.radius()*2.0f);
494 495
                 _state.translate(0.0, 0.0, light_.radius()*2);
                 // Draw arrow tip
496 497 498
                 cone_->setBottomRadius(light_.radius()/2.0f);
                 cone_->setTopRadius(0.0f);
                 cone_->draw(_state, light_.radius());
499 500 501
             }

             _state.pop_modelview_matrix();
502

503
             ACG::GLState::depthFunc(prev_depth);
504
         }
505 506 507
    }
}

508
void LightNode::enter(GLState& _state, const DrawModes::DrawMode& /* _drawmode */ )
Jan Möbius's avatar
Jan Möbius committed
509
{
510
    if(visualize_) return;
511

512 513 514 515 516 517 518
    // Get initial camera coords of light if in fixed
    // mode and if they haven't been computed yet
    if(light_.fixedPosition_ && !light_.initialPositionInit_) {
        light_.initialPosition_ = _state.modelview() * light_.position_;
        light_.initialSpotDirection_ = _state.modelview().transform_vector(light_.spotDirection());
        light_.initialPositionInit_ = true;
    }
519

520 521
    // Get light id
    lightId_ = lightSourceHandle->getLight(this);
522

523 524
    // Return if we don't have a valid light source
    if(lightId_ == GL_INVALID_ENUM) return;
525

526 527
    /// transfer GL-preferences to lightSave_
    getParameters(lightId_, lightSave_);
528

529 530 531 532 533 534
    // save old light
    lightSave_.enabled_ = glIsEnabled(lightId_);

    if(light_.enabled_ ) {
        // correct Position for fixed Lights
        if(light_.fixedPosition_) {
535 536
            light_.realPosition_ = _state.inverse_modelview() * light_.initialPosition_;
            light_.realSpotDirection_ = _state.inverse_modelview().transform_vector(light_.initialSpotDirection_);
537 538 539
            //std::cerr << "New Light pos :" << _state.inverse_modelview().transform_vector(light_.position) << std::endl;
        } else {
            light_.realPosition_ = light_.position_;
Mike Kremer's avatar
Mike Kremer committed
540
            light_.realSpotDirection_ = light_.spotDirection_;
541 542 543
            //std::cerr << "New Light pos :" << light_.position << std::endl;
        }

544 545 546 547 548
        // transform to view space for shader pipeline
        transformedLight_ = light_;
        transformedLight_.position_ = _state.modelview() * light_.realPosition_;
        transformedLight_.spotDirection_ = _state.modelview().transform_vector(light_.realSpotDirection_);

549
        ACG::GLState::enable(lightId_);
550
        setParameters(lightId_, light_);
Jan Möbius's avatar
Jan Möbius committed
551
    } else {
552
        ACG::GLState::disable(lightId_);
Jan Möbius's avatar
Jan Möbius committed
553 554 555 556 557 558 559
    }
}


//----------------------------------------------------------------------------


560
void LightNode::leave(GLState& /* _state */ , const DrawModes::DrawMode& /* _drawmode*/ )
Jan Möbius's avatar
Jan Möbius committed
561
{
562
    if(visualize_) return;
563

564 565
    // Return if we don't have a valid light source
    if(lightId_ == GL_INVALID_ENUM) return;
566

567 568
    // restore old enabled light
    if(lightSave_.enabled_) {
569
        ACG::GLState::enable(lightId_);
570 571 572
        setParameters(lightId_, lightSave_);
    }
    else {
573
        ACG::GLState::disable(lightId_);
574
    }
575

576 577
    // Free light id
    lightSourceHandle->removeLight(this);
Jan Möbius's avatar
Jan Möbius committed
578 579 580 581 582 583 584
}

//----------------------------------------------------------------------------

void LightNode::setParameters(GLenum _index, LightSource& _light)
{

585 586
  // Multiply colors by brightness
  Vec4f& a = _light.ambientColor_;
587
  GLfloat ambient[4] = {a[0]*_light.brightness_,
588 589 590 591 592 593 594 595 596
                        a[1]*_light.brightness_,
                        a[2]*_light.brightness_,
                        a[3]*_light.brightness_};

  Vec4f& d = _light.diffuseColor_;
  GLfloat diffuse[4] = {d[0]*_light.brightness_,
                        d[1]*_light.brightness_,
                        d[2]*_light.brightness_,
                        d[3]*_light.brightness_};
597

598 599 600 601 602
  Vec4f& s = _light.specularColor_;
  GLfloat specular[4] = {s[0]*_light.brightness_,
                         s[1]*_light.brightness_,
                         s[2]*_light.brightness_,
                         s[3]*_light.brightness_};
603

Jan Möbius's avatar
Jan Möbius committed
604
  // set preferences of _light for GL_LIGHT#_index
605 606 607
  glLightfv(_index, GL_AMBIENT,  ambient);
  glLightfv(_index, GL_DIFFUSE,  diffuse);
  glLightfv(_index, GL_SPECULAR, specular);
Jan Möbius's avatar
Jan Möbius committed
608

609
  Vec3d& sd = _light.realSpotDirection_;
610

611
  bool directional = _light.directional();
612

613 614
  Vec4f& p = _light.realPosition_;
  GLfloat realPos[4] = {(float)p[0], (float)p[1], (float)p[2], (directional ? 0.0f : 1.0f)};
615

616
  glLightfv(_index, GL_POSITION,  realPos);
617

Jan Möbius's avatar
Jan Möbius committed
618 619 620 621 622
  if(!directional) {
    GLfloat dir[3] = {(float)sd[0], (float)sd[1], (float)sd[2]};
    glLightfv(_index, GL_SPOT_DIRECTION,  dir);
  }

623 624
  if(!directional) glLightf(_index, GL_SPOT_EXPONENT,  _light.spotExponent_);
  if(!directional) glLightf(_index, GL_SPOT_CUTOFF,  _light.spotCutoff_);
625

Jan Möbius's avatar
Jan Möbius committed
626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647
  glLightf(_index, GL_CONSTANT_ATTENUATION,  _light.constantAttenuation_);
  glLightf(_index, GL_LINEAR_ATTENUATION,  _light.linearAttenuation_);
  glLightf(_index, GL_QUADRATIC_ATTENUATION,  _light.quadraticAttenuation_);
}

//----------------------------------------------------------------------------

void LightNode::getParameters(GLenum _index, LightSource& _light)
{
  // get preferences of GL_LIGHT#_index and store them in _light
  glGetLightfv(_index, GL_AMBIENT,  (GLfloat *)_light.ambientColor_.data());
  glGetLightfv(_index, GL_DIFFUSE,  (GLfloat *)_light.diffuseColor_.data());
  glGetLightfv(_index, GL_SPECULAR,  (GLfloat *)_light.specularColor_.data());
  glGetLightfv(_index, GL_POSITION,  (GLfloat *)_light.position_.data());
  glGetLightfv(_index, GL_SPOT_DIRECTION,  (GLfloat *)_light.spotDirection_.data());

  glGetLightfv(_index, GL_SPOT_EXPONENT,  &_light.spotExponent_);
  glGetLightfv(_index, GL_SPOT_CUTOFF,  &_light.spotCutoff_);
  glGetLightfv(_index, GL_CONSTANT_ATTENUATION,  &_light.constantAttenuation_);
  glGetLightfv(_index, GL_LINEAR_ATTENUATION,  &_light.linearAttenuation_);
  glGetLightfv(_index, GL_QUADRATIC_ATTENUATION,  &_light.quadraticAttenuation_);
}
Jan Möbius's avatar
Jan Möbius committed
648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667


void LightNode::getRenderObjects( IRenderer* _renderer, GLState& _state , const DrawModes::DrawMode& _drawMode , const Material* _mat )
{

  // fill IRenderer light struct with light data in view-space
  IRenderer::LightData light;

  if (transformedLight_.directional())
    light.ltype = ACG::SG_LIGHT_DIRECTIONAL;
  else if (transformedLight_.spotCutoff() > 179.5f)
    light.ltype = ACG::SG_LIGHT_POINT;
  else
    light.ltype = ACG::SG_LIGHT_SPOT;

#define V4toV3(v) (ACG::Vec3f(v[0], v[1], v[2]))

  light.diffuse = V4toV3(transformedLight_.diffuseColor());
  light.ambient = V4toV3(transformedLight_.ambientColor());
  light.specular = V4toV3(transformedLight_.specularColor());
668

Jan Möbius's avatar
Jan Möbius committed
669 670 671 672 673 674 675 676 677 678 679 680 681 682
  light.pos = V4toV3(transformedLight_.position());
  light.dir = V4toV3(transformedLight_.direction());

  light.atten[0] = transformedLight_.constantAttenuation();
  light.atten[1] = transformedLight_.linearAttenuation();
  light.atten[2] = transformedLight_.quadraticAttenuation();

  light.spotCutoffExponent[0] = transformedLight_.spotCutoff();
  light.spotCutoffExponent[1] = transformedLight_.spotExponent();

  _renderer->addLight(light);

}

Jan Möbius's avatar
Jan Möbius committed
683 684 685 686
//=============================================================================
} // namespace SceneGraph
} // namespace ACG
//=============================================================================