/* 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" #include "vector.h" #include "debug.h" #include "tinyxml.h" #include "load_param.h" #include "factory.h" using namespace std; CREATE_FACTORY(Light); //! Definition of the Lights and their Names int lightsV[] = { GL_LIGHT0, GL_LIGHT1, GL_LIGHT2, GL_LIGHT3, GL_LIGHT4, GL_LIGHT5, GL_LIGHT6, GL_LIGHT7 }; /** * \param root The XML-element to load the Light from \todo what to do, if no Light-Slots are open anymore ??? */ Light::Light(const TiXmlElement* root) { PRINTF(4)("initializing Light number %d.\n", this->lightNumber); this->lightNumber = LightManager::getInstance()->registerLight(this); this->setClassID(CL_LIGHT, "Light"); char tmpName[10]; sprintf(tmpName, "Light[%d]", this->lightNumber); this->setName(tmpName); // enable The light glEnable(lightsV[this->lightNumber]); // postSpawn // set values (defaults) this->setDiffuseColor(1.0, 1.0, 1.0); this->setSpecularColor(1.0, 1.0, 1.0); this->loadParams(root); } /** \brief destroys a Light */ Light::~Light(void) { glDisable(lightsV[this->lightNumber]); LightManager::getInstance()->unregisterLight(this); } /** * \param root The XML-element to load the Light from */ void Light::loadParams(const TiXmlElement* root) { static_cast(this)->loadParams(root); LoadParam(root, "diffuse-color", this, &Light::setDiffuseColor) .describe("sets the diffuse color of the Light (red [0-1], green [0-1], blue [0-1])"); LoadParam(root, "specular-color", this, &Light::setSpecularColor) .describe("sets the specular color of the Light (red [0-1], green [0-1], blue [0-1])"); LoadParam(root, "attenuation", this, &Light::setAttenuation) .describe("sets the Attenuation of the LightSource (constant Factor, linear Factor, quadratic Factor)."); LoadParam(root, "spot-direction", this, &Light::setSpotDirection) .describe("sets the Direction of the Spot"); LoadParam(root, "spot-cutoff", this, &Light::setSpotCutoff) .describe("the cuttoff of the Spotlight"); } /** \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(const 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); } /** \brief draws this Light. Being a World-entity the possibility to do this lies at hand. */ void Light::draw(void) const { 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)(" 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->setClassID(CL_LIGHT_MANAGER, "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->setAmbientColor(.0,.0,.0); for (int i = 0; i < NUMBEROFLIGHTS; i++) if (this->lights[i]) delete lights[i]; delete lights; LightManager::singletonRef = NULL; } /** \brief singleton-Reference to the Light-class */ LightManager* LightManager::singletonRef = NULL; /** \param root the XML-element to load the LightManager's settings from */ void LightManager::loadParams(const TiXmlElement* root) { LoadParam(root, "Lights", this, &LightManager::loadLights) .describe("an XML-Element to load lights from."); LoadParam(root, "ambient-color", this, &LightManager::setAmbientColor) .describe("sets the ambient Color of the Environmental Light"); } /** \param root The XML-element to load Lights from */ void LightManager::loadLights(const TiXmlElement* root) { const TiXmlElement* element = root->FirstChildElement(); while (element != NULL) { Factory::getFirst()->fabricate(element); element = element->NextSiblingElement(); } } // 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); } /** \param light the Light to register to the LightManager This is done explicitely by the constructor of a Light */ int LightManager::registerLight(Light* light) { for (int i = 0; i < NUMBEROFLIGHTS; i++) if (!this->lights[i]) { this->lights[i]=light; return i; } PRINTF(1)("no more light slots availiable. All %d already taken\n", NUMBEROFLIGHTS); return -1; } /** \param light The light to unregister from the LightManager This is done every time a Light is destroyed explicitely by the Light-destructor */ void LightManager::unregisterLight(Light* light) { for (int i = 0; i < NUMBEROFLIGHTS; i++) { if (this->lights[i] == light) { this->lights[i] = NULL; return; } } PRINTF(2)("Light %p could not be unloaded (this should not heappen\n)"); return; } /** \brief draws all the Lights in their appropriate position */ void LightManager::draw() const { glMatrixMode(GL_MODELVIEW); glLoadIdentity(); PRINTF(4)("Drawing the Lights\n"); for (int i = 0; i < NUMBEROFLIGHTS; i++) if (this->lights[i]) lights[i]->draw(); } /** \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)("-----------------------------LM-\n"); }