// * This file is part of the COLOBOT source code // * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch // * // * 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 3 of the License, or // * (at your option) any later version. // * // * This program is distributed in the hope that it will be useful, // * but WITHOUT ANY WARRANTY; without even the implied warranty of // * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // * GNU General Public License for more details. // * // * You should have received a copy of the GNU General Public License // * along with this program. If not, see http://www.gnu.org/licenses/. // light.cpp #define STRICT #define D3D_OVERLOADS #include #include #include #include "math/const.h" #include "common/struct.h" #include "graphics/d3d/d3dengine.h" #include "common/event.h" #include "common/misc.h" #include "common/iman.h" #include "math/old/math3d.h" #include "graphics/common/light.h" // Initializes a progression. void ProgInit(LightProg &p, float value) { p.starting = value; p.ending = value; p.current = value; p.progress = 0.0f; p.speed = 100.0f; } // Makes evolve a progression. void ProgFrame(LightProg &p, float rTime) { if ( p.speed < 100.0f ) { if ( p.progress < 1.0f ) { p.progress += p.speed*rTime; if ( p.progress > 1.0f ) { p.progress = 1.0f; } } p.current = (p.ending-p.starting)*p.progress + p.starting; } else { p.current = p.ending; } } // Change the current value. void ProgSet(LightProg &p, float value) { p.starting = p.current; p.ending = value; p.progress = 0.0f; } // Object's constructor. CLight::CLight(CInstanceManager* iMan, CD3DEngine* engine) { m_iMan = iMan; m_iMan->AddInstance(CLASS_LIGHT, this); m_pD3DDevice = 0; m_engine = engine; m_lightUsed = 0; m_lightTable = (Light*)malloc(sizeof(Light)*D3DMAXLIGHT); ZeroMemory(m_lightTable, sizeof(Light)*D3DMAXLIGHT); m_time = 0.0f; } // Object's destructor. CLight::~CLight() { free(m_lightTable); m_iMan->DeleteInstance(CLASS_LIGHT, this); } void CLight::SetD3DDevice(LPDIRECT3DDEVICE7 device) { m_pD3DDevice = device; } // Removes all the lights. void CLight::FlushLight() { int i; for ( i=0 ; iLightEnable(i, FALSE); } m_lightUsed = 0; } // Creates a new light. Returns its rank or -1 on error. int CLight::CreateLight() { int i; for ( i=0 ; i= D3DMAXLIGHT ) return FALSE; m_lightTable[lightRank].bUsed = FALSE; m_pD3DDevice->LightEnable(lightRank, FALSE); m_lightUsed = 0; for ( i=0 ; i= D3DMAXLIGHT ) return FALSE; m_lightTable[lightRank].light = light; ProgInit(m_lightTable[lightRank].colorRed, m_lightTable[lightRank].light.dcvDiffuse.r); ProgInit(m_lightTable[lightRank].colorGreen, m_lightTable[lightRank].light.dcvDiffuse.g); ProgInit(m_lightTable[lightRank].colorBlue, m_lightTable[lightRank].light.dcvDiffuse.b); return TRUE; } // Gives the specifications of a light. BOOL CLight::GetLight(int lightRank, D3DLIGHT7 &light) { if ( lightRank < 0 || lightRank >= D3DMAXLIGHT ) return FALSE; light = m_lightTable[lightRank].light; return TRUE; } // Lights up or put out a light. BOOL CLight::LightEnable(int lightRank, BOOL bEnable) { if ( lightRank < 0 || lightRank >= D3DMAXLIGHT ) return FALSE; m_lightTable[lightRank].bEnable = bEnable; return TRUE; } // Specifies the type (TYPE *) items included in this light. // This light does not light up so that this type of objects. BOOL CLight::SetLightIncluType(int lightRank, D3DTypeObj type) { if ( lightRank < 0 || lightRank >= D3DMAXLIGHT ) return FALSE; m_lightTable[lightRank].incluType = type; return TRUE; } // Specifies the type (TYPE *) items excluded by this light. // This light does not illuminate then ever these objects. BOOL CLight::SetLightExcluType(int lightRank, D3DTypeObj type) { if ( lightRank < 0 || lightRank >= D3DMAXLIGHT ) return FALSE; m_lightTable[lightRank].excluType = type; return TRUE; } // Management of the position of the light. BOOL CLight::SetLightPos(int lightRank, D3DVECTOR pos) { if ( lightRank < 0 || lightRank >= D3DMAXLIGHT ) return FALSE; m_lightTable[lightRank].light.dvPosition = pos; return TRUE; } D3DVECTOR CLight::RetLightPos(int lightRank) { if ( lightRank < 0 || lightRank >= D3DMAXLIGHT ) return D3DVECTOR(0.0f, 0.0f, 0.0f); return m_lightTable[lightRank].light.dvPosition; } // Management direction of the light. BOOL CLight::SetLightDir(int lightRank, D3DVECTOR dir) { if ( lightRank < 0 || lightRank >= D3DMAXLIGHT ) return FALSE; m_lightTable[lightRank].light.dvDirection = dir; return TRUE; } D3DVECTOR CLight::RetLightDir(int lightRank) { if ( lightRank < 0 || lightRank >= D3DMAXLIGHT ) return D3DVECTOR(0.0f, 0.0f, 0.0f); return m_lightTable[lightRank].light.dvDirection; } // Specifies the rate of change. BOOL CLight::SetLightIntensitySpeed(int lightRank, float speed) { if ( lightRank < 0 || lightRank >= D3DMAXLIGHT ) return FALSE; m_lightTable[lightRank].intensity.speed = speed; return TRUE; } // Management of the intensity of light. BOOL CLight::SetLightIntensity(int lightRank, float value) { if ( lightRank < 0 || lightRank >= D3DMAXLIGHT ) return FALSE; ProgSet(m_lightTable[lightRank].intensity, value); return TRUE; } float CLight::RetLightIntensity(int lightRank) { if ( lightRank < 0 || lightRank >= D3DMAXLIGHT ) return 0.0f; return m_lightTable[lightRank].intensity.current; } // Specifies the rate of change. BOOL CLight::SetLightColorSpeed(int lightRank, float speed) { if ( lightRank < 0 || lightRank >= D3DMAXLIGHT ) return FALSE; m_lightTable[lightRank].colorRed.speed = speed; m_lightTable[lightRank].colorGreen.speed = speed; m_lightTable[lightRank].colorBlue.speed = speed; return TRUE; } // Color management for light. BOOL CLight::SetLightColor(int lightRank, D3DCOLORVALUE color) { if ( lightRank < 0 || lightRank >= D3DMAXLIGHT ) return FALSE; ProgSet(m_lightTable[lightRank].colorRed, color.r); ProgSet(m_lightTable[lightRank].colorGreen, color.g); ProgSet(m_lightTable[lightRank].colorBlue, color.b); return TRUE; } D3DCOLORVALUE CLight::RetLightColor(int lightRank) { D3DCOLORVALUE color; if ( lightRank < 0 || lightRank >= D3DMAXLIGHT ) { color.r = 0.5f; color.g = 0.5f; color.b = 0.5f; color.a = 0.5f; return color; } color.r = m_lightTable[lightRank].colorRed.current; color.g = m_lightTable[lightRank].colorGreen.current; color.b = m_lightTable[lightRank].colorBlue.current; return color; } // Adjusts the color of all lights. void CLight::AdaptLightColor(D3DCOLORVALUE color, float factor) { D3DCOLORVALUE value; int i; for ( i=0 ; iRetPause() ) return; m_time += rTime; for ( i=0 ; iRetEyePt()-m_engine->RetLookatPt(); angle = RotateAngle(dir.x, dir.z); angle += PI*0.5f*i; m_lightTable[i].light.dvDirection.x = sinf(angle*2.0f); m_lightTable[i].light.dvDirection.z = cosf(angle*2.0f); } } } // Updates all the lights. void CLight::LightUpdate() { BOOL bEnable; float value; int i; for ( i=0 ; iSetLight(i, &m_lightTable[i].light); m_pD3DDevice->LightEnable(i, bEnable); } else { m_lightTable[i].light.dcvDiffuse.r = 0.0f; m_lightTable[i].light.dcvDiffuse.g = 0.0f; m_lightTable[i].light.dcvDiffuse.b = 0.0f; m_pD3DDevice->LightEnable(i, bEnable); } } } // Updates the lights for a given type. void CLight::LightUpdate(D3DTypeObj type) { BOOL bEnable; int i; for ( i=0 ; iLightEnable(i, bEnable); } if ( m_lightTable[i].excluType != TYPENULL ) { bEnable = (m_lightTable[i].excluType != type); m_pD3DDevice->LightEnable(i, bEnable); } } }