/* orxonox - the future of 3D-vertical-scrollers Copyright (C) 2004 orx This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. ### File Specific: main-programmer: Benjamin Grauer co-programmer: ... */ #define DEBUG_SPECIAL_MODULE DEBUG_MODULE_LIGHT #include "light.h" #include "glincl.h" using namespace std; //! Definition of the Lights int lightsV[] = {GL_LIGHT0, GL_LIGHT1, GL_LIGHT2, GL_LIGHT3, GL_LIGHT4, GL_LIGHT5, GL_LIGHT6, GL_LIGHT7}; /** \param lightNumber the Light Number to initiate */ Light::Light(int lightNumber) { this->setClassName("Light"); char tmpName[7]; sprintf(tmpName, "Light%d", lightNumber); this->setName(tmpName); PRINTF(4)("initializing Light number %d.\n", lightNumber); // enable The light glEnable(lightsV[lightNumber]); // postSpawn // set values (defaults) this->lightNumber = lightNumber; this->setPosition(0.0, 0.0, 0.0); this->setDiffuseColor(1.0, 1.0, 1.0); this->setSpecularColor(1.0, 1.0, 1.0); } /** \brief destroys a Light */ Light::~Light(void) { glDisable(lightsV[this->lightNumber]); } /** \brief Sets a Position for the Light. \param position The new position of the Light. \todo patrick: is it ok to set a Light Position even if it is derived from p_node?? */ void Light::setPosition(Vector position) { this->lightPosition[0] = position.x; this->lightPosition[1] = position.y; this->lightPosition[2] = position.z; this->lightPosition[3] = 0.0; this->setAbsCoor(&position); glLightfv (lightsV[this->lightNumber], GL_POSITION, this->lightPosition); } /** \brief Sets a Position of this Light. \param x the x-coordinate \param y the y-coordinate \param z the z-coordinate */ void Light::setPosition(GLfloat x, GLfloat y, GLfloat z) { this->setPosition(Vector(x, y, z)); } /** \brief sets an emitting Diffuse color of this Light \param r red \param g green \param b blue */ void Light::setDiffuseColor(GLfloat r, GLfloat g, GLfloat b) { this->diffuseColor[0] = r; this->diffuseColor[1] = g; this->diffuseColor[2] = b; this->diffuseColor[3] = 1.0; glLightfv (lightsV[this->lightNumber], GL_DIFFUSE, this->diffuseColor); } /** \brief sets an emitting Specular color of this Light \param r red \param g green \param b blue */ void Light::setSpecularColor(GLfloat r, GLfloat g, GLfloat b) { this->specularColor[0] = r; this->specularColor[1] = g; this->specularColor[2] = b; this->specularColor[3] = 1.0; glLightfv (lightsV[this->lightNumber], GL_SPECULAR, this->specularColor); } /** \brief Sets the AttenuationType of this Light Source \param constantAttenuation The Constant Attenuation of the Light \param linearAttenuation The Linear Attenuation of the Light \param quadraticAttenuation The Quadratic Attenuation of the Light */ void Light::setAttenuation(float constantAttenuation, float linearAttenuation, float quadraticAttenuation) { this->constantAttenuation = constantAttenuation; this->linearAttenuation = linearAttenuation; this->quadraticAttenuation = quadraticAttenuation; glLightf(lightsV[this->lightNumber], GL_CONSTANT_ATTENUATION, constantAttenuation); glLightf(lightsV[this->lightNumber], GL_LINEAR_ATTENUATION, linearAttenuation); glLightf(lightsV[this->lightNumber], GL_QUADRATIC_ATTENUATION, quadraticAttenuation); } /** \brief stets the direction of the Spot Light. \param direction The direction of the Spot Light. */ void Light::setSpotDirection(Vector direction) { this->spotDirection[0] = direction.x; this->spotDirection[1] = direction.y; this->spotDirection[2] = direction.z; glLightfv(lightsV[this->lightNumber], GL_SPOT_DIRECTION, this->spotDirection); } /** \brief sets the cutoff angle of the Light. \param cutoff The cutoff angle. */ void Light::setSpotCutoff(GLfloat cutoff) { this->spotCutoff = cutoff; glLightf(lightsV[this->lightNumber], GL_SPOT_CUTOFF, cutoff); } /** \returns the Position of the Light */ Vector Light::getPosition() const { return Vector(this->lightPosition[0], this->lightPosition[1], this->lightPosition[2]); } /** \brief draws this Light. Being a World-entity the possibility to do this lies at hand. */ void Light::draw() { float pos[4] = {this->getAbsCoor().x, this->getAbsCoor().y, this->getAbsCoor().z, 1.0}; PRINTF(4)("Drawing The Lights new Position at %f %f %f\n", pos[0], pos[1], pos[2]); glLightfv(lightsV[this->lightNumber], GL_POSITION, pos); } /** \brief Prints out some nice formated debug information about the Light */ void Light::debug(void) const { PRINT(0)(":: %d :: -- reference %p\n", this->lightNumber, this); PRINT(0)(" GL-state: "); GLboolean param; glGetBooleanv(lightsV[this->lightNumber], ¶m); if (param) PRINT(0)("ON\n"); else PRINT(0)("OFF\n"); PRINT(0)(" Position: %f/%f/%f\n", this->lightPosition[0], this->lightPosition[1], this->lightPosition[2]); PRINT(0)(" DiffuseColor: %f/%f/%f\n", this->diffuseColor[0], this->diffuseColor[1], this->diffuseColor[2]); PRINT(0)(" SpecularColor: %f/%f/%f\n", this->specularColor[0], this->specularColor[1], this->specularColor[2]); PRINT(0)(" Attenuation: constant=%f linear=%f quadratic=%f\n", this->constantAttenuation, this->linearAttenuation, this->quadraticAttenuation); } /****************** ** LIGHT-MANAGER ** ******************/ /** \brief standard constructor for a Light */ LightManager::LightManager () { this->setClassName ("LightManager"); glEnable (GL_LIGHTING); this->setAmbientColor(.3, .3, .3); this->lights = new Light*[NUMBEROFLIGHTS]; for (int i = 0; i < NUMBEROFLIGHTS; i++) lights[i] = NULL; this->currentLight = NULL; } /** \brief standard deconstructor first disables Lighting then deletes the rest of the allocated memory and in the end sets the singleton Reference to zero. */ LightManager::~LightManager () { glDisable(GL_LIGHTING); // this will be done either by worldEntity, or by pNode as each light is one of them // for (int i = 0; i < NUMBEROFLIGHTS; i++) // this->deleteLight(i); delete lights; LightManager::singletonRef = NULL; } /** \brief singleton-Reference to the Light-class */ LightManager* LightManager::singletonRef = NULL; /** \returns The Instance of the Lights */ LightManager* LightManager::getInstance(void) { if (!singletonRef) LightManager::singletonRef = new LightManager(); return singletonRef; } /** \brief initializes a new Light with default values, and enables GL_LIGHTING */ void LightManager::initLight(int lightNumber) { lights[lightNumber] = new Light(lightNumber); } /** \brief Adds a new Light, by selecting the First free slot. if no slot is free error */ int LightManager::addLight(void) { for (int i = 0; i < NUMBEROFLIGHTS; i++) if (!this->lights[i]) return addLight(i); PRINTF(1)("no more light slots availiable. All %d already taken\n", NUMBEROFLIGHTS); return -1; } /** \brief Adds a new Light \param lightNumber The number of the light to add. if the Number is not free: warn, automatically choose another slot. */ int LightManager::addLight(int lightNumber) { if (this->lights[lightNumber]) { PRINTF(2)("Lightslot %d is allready taken, trying another one\n", lightNumber); return this->addLight(); } this->initLight(lightNumber); this->currentLight = this->lights[lightNumber]; return lightNumber; } /** \brief select the light to work with \param lightNumber the light to work with */ void LightManager::editLightNumber(int lightNumber) { if (!this->currentLight) { PRINTF(2)("no Light defined yet. Please define at least one light first befor editing.\n"); return; } this->currentLight = lights[lightNumber]; } /** \brief Delete the current Light */ void LightManager::deleteLight(void) { if (!this->currentLight) { PRINTF(1)("no Light defined yet. So you cannot delete any Light right now.\n"); return; } this->deleteLight(this->currentLight->getLightNumber()); } /** \brief delete light. \param lightNumber the number of the light to delete */ void LightManager::deleteLight(int lightNumber) { if (this->lights[lightNumber]) { PRINTF(4)("deleting Light number %d\n", lightNumber); delete this->lights[lightNumber]; this->lights[lightNumber] = NULL; } } /** \brief draws all the Lights in their appropriate position */ void LightManager::draw() { glMatrixMode(GL_MODELVIEW); glLoadIdentity(); PRINTF(4)("Drawing the Lights\n"); for (int i = 0; i < NUMBEROFLIGHTS; i++) if (this->lights[i]) lights[i]->draw(); } // set Attributes /** \brief sets the ambient Color of the Scene \param r red \param g green \param b blue */ void LightManager::setAmbientColor(GLfloat r, GLfloat g, GLfloat b) { this->ambientColor[0] = r; this->ambientColor[1] = g; this->ambientColor[2] = b; this->ambientColor[3] = 1.0; glLightfv (GL_LIGHT0, GL_AMBIENT, this->ambientColor); } /** \brief sets The Position of the currently selected Light \param position the new Position */ void LightManager::setPosition(Vector position) { this->currentLight->setPosition(position); } /** \brief Sets a Position for the currently selected Light. \param x the x-coordinate \param y the y-coordinate \param z the z-coordinate */ void LightManager::setPosition(GLfloat x, GLfloat y, GLfloat z) { if (!this->currentLight) { PRINTF(2)("no Light defined yet. Please define at least one light first befor editing.\n"); return; } this->currentLight->setPosition(x, y, z); } /** \brief sets an emitting Diffuse color of the currently selected Light \param r red \param g green \param b blue */ void LightManager::setDiffuseColor(GLfloat r, GLfloat g, GLfloat b) { if (!this->currentLight) { PRINTF(2)("no Light defined yet. Please define at least one light first befor editing.\n"); return; } this->currentLight->setDiffuseColor(r,g,b); } /** \brief sets an emitting Specular color of the currently selected Light \param r red \param g green \param b blue */ void LightManager::setSpecularColor(GLfloat r, GLfloat g, GLfloat b) { if (!this->currentLight) { PRINTF(2)("no Light defined yet. Please define at least one light first befor editing.\n"); return; } this->currentLight->setSpecularColor(r, g, b); } /** \brief Sets the AttenuationType of th currently selecte LightSource Light Source \param constantAttenuation The Constant Attenuation of the Light \param linearAttenuation The Linear Attenuation of the Light \param quadraticAttenuation The Quadratic Attenuation of the Light */ void LightManager::setAttenuation(float constantAttenuation, float linearAttenuation, float quadraticAttenuation) { if (!this->currentLight) { PRINTF(2)("no Light defined yet. Please define at least one light first befor editing.\n"); return; } this->currentLight->setAttenuation(constantAttenuation, linearAttenuation, quadraticAttenuation); } /** \brief stets the direction of the Spot Light. \param direction The direction of the Spot Light. */ void LightManager::setSpotDirection(Vector direction) { if (!this->currentLight) { PRINTF(2)("no Light defined yet. Please define at least one light first befor editing.\n"); return; } this->currentLight->setSpotDirection(direction); } /** \brief sets the cutoff angle of the Light. \param cutoff The cutoff angle. */ void LightManager::setSpotCutoff(GLfloat cutoff) { if (!this->currentLight) { PRINTF(2)("no Light defined yet. Please define at least one light first befor editing.\n"); return; } this->currentLight->setSpotCutoff(cutoff); } // get Attributes /** \returns the Position of the Light */ Vector LightManager::getPosition(void) const { if (!this->currentLight) { PRINTF(2)("no Light defined yet\n"); return Vector(.0, .0, .0); } else return this->currentLight->getPosition(); } /** \returns the Position of Light \param lightNumber lightnumber */ Vector LightManager::getPosition(int lightNumber) const { if (!this->lights[lightNumber]) { PRINTF(2)("no Light defined yet\n"); return Vector(.0,.0,.0); } else return this->lights[lightNumber]->getPosition(); } /** \returns a pointer to a Light \param lightNumber The light to request the pointer from */ Light* LightManager::getLight(int lightNumber) const { return this->lights[lightNumber]; } /** \brief outputs debug information about the Class and its lights */ void LightManager::debug(void) const { PRINT(0)("=================================\n"); PRINT(0)("= DEBUG INFORMATION CLASS LIGHT =\n"); PRINT(0)("=================================\n"); PRINT(0)("Reference: %p\n", LightManager::singletonRef); if (this->currentLight) PRINT(0)("current Light Nr: %d\n", this->currentLight->getLightNumber()); PRINT(0)("Ambient Color: %f:%f:%f\n", this->ambientColor[0], this->ambientColor[0], this->ambientColor[0]); PRINT(0)("=== Lights ===\n"); for (int i = 0; i < NUMBEROFLIGHTS; i++) if (this->lights[i]) { this->lights[i]->debug(); } PRINT(0)("--------------------------------\n"); }