//========= Copyright Valve Corporation, All rights reserved. ============// // // Purpose: // //============================================================================= #include "movieobjects/dmelight.h" #include "tier0/dbg.h" #include "datamodel/dmelementfactoryhelper.h" #include "mathlib/vector.h" #include "movieobjects/dmetransform.h" #include "materialsystem/imaterialsystem.h" #include "movieobjects_interfaces.h" #include "tier2/tier2.h" // memdbgon must be the last include file in a .cpp file!!! #include "tier0/memdbgon.h" //----------------------------------------------------------------------------- // Expose this class to the scene database //----------------------------------------------------------------------------- IMPLEMENT_ELEMENT_FACTORY( DmeLight, CDmeLight ); //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CDmeLight::OnConstruction() { m_Color.InitAndSet( this, "color", Color( 255, 255, 255, 255 ), FATTRIB_HAS_CALLBACK ); m_flIntensity.InitAndSet( this, "intensity", 1.0f, FATTRIB_HAS_CALLBACK ); } void CDmeLight::OnDestruction() { } //----------------------------------------------------------------------------- // Sets the color and intensity // NOTE: Color is specified 0-255 floating point. //----------------------------------------------------------------------------- void CDmeLight::SetColor( const Color &color ) { m_Color.Set( color ); } void CDmeLight::SetIntensity( float flIntensity ) { m_flIntensity = flIntensity; } //----------------------------------------------------------------------------- // Sets up render state in the material system for rendering //----------------------------------------------------------------------------- void CDmeLight::SetupRenderStateInternal( LightDesc_t &desc, float flAtten0, float flAtten1, float flAtten2 ) { desc.m_Color[0] = m_Color.Get().r(); desc.m_Color[1] = m_Color.Get().g(); desc.m_Color[2] = m_Color.Get().b(); desc.m_Color *= m_flIntensity / 255.0f; desc.m_Attenuation0 = flAtten0; desc.m_Attenuation1 = flAtten1; desc.m_Attenuation2 = flAtten2; desc.m_Flags = 0; if ( desc.m_Attenuation0 != 0.0f ) { desc.m_Flags |= LIGHTTYPE_OPTIMIZATIONFLAGS_HAS_ATTENUATION0; } if ( desc.m_Attenuation1 != 0.0f ) { desc.m_Flags |= LIGHTTYPE_OPTIMIZATIONFLAGS_HAS_ATTENUATION1; } if ( desc.m_Attenuation2 != 0.0f ) { desc.m_Flags |= LIGHTTYPE_OPTIMIZATIONFLAGS_HAS_ATTENUATION2; } } //----------------------------------------------------------------------------- // Sets lighting state //----------------------------------------------------------------------------- void CDmeLight::SetupRenderState( int nLightIndex ) { LightDesc_t desc; if ( GetLightDesc( &desc ) ) { // FIXME: Should we pass the light color in? CMatRenderContextPtr pRenderContext( g_pMaterialSystem ); pRenderContext->SetLight( nLightIndex, desc ); } } //----------------------------------------------------------------------------- // // A directional light // //----------------------------------------------------------------------------- IMPLEMENT_ELEMENT_FACTORY( DmeDirectionalLight, CDmeDirectionalLight ); //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CDmeDirectionalLight::OnConstruction() { m_Direction.InitAndSet( this, "direction", Vector( 0.0f, 0.0f, -1.0f ), FATTRIB_HAS_CALLBACK ); } void CDmeDirectionalLight::OnDestruction() { } //----------------------------------------------------------------------------- // Sets the light direction //----------------------------------------------------------------------------- void CDmeDirectionalLight::SetDirection( const Vector &direction ) { m_Direction.Set( direction ); } //----------------------------------------------------------------------------- // Gets a light desc for the light //----------------------------------------------------------------------------- bool CDmeDirectionalLight::GetLightDesc( LightDesc_t *pDesc ) { memset( pDesc, 0, sizeof(LightDesc_t) ); pDesc->m_Type = MATERIAL_LIGHT_DIRECTIONAL; SetupRenderStateInternal( *pDesc, 1.0f, 0.0f, 0.0f ); matrix3x4_t m; GetTransform()->GetTransform( m ); VectorRotate( m_Direction.Get(), m, pDesc->m_Direction ); VectorNormalize( pDesc->m_Direction ); pDesc->m_Theta = 0.0f; pDesc->m_Phi = 0.0f; pDesc->m_Falloff = 1.0f; return true; } //----------------------------------------------------------------------------- // // A point light // //----------------------------------------------------------------------------- IMPLEMENT_ELEMENT_FACTORY( DmePointLight, CDmePointLight ); //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CDmePointLight::OnConstruction() { m_Position.InitAndSet( this, "position", Vector( 0, 0, 0 ), FATTRIB_HAS_CALLBACK ); m_flAttenuation0.InitAndSet( this, "constantAttenuation", 1.0f, FATTRIB_HAS_CALLBACK ); m_flAttenuation1.InitAndSet( this, "linearAttenuation", 0.0f, FATTRIB_HAS_CALLBACK ); m_flAttenuation2.InitAndSet( this, "quadraticAttenuation", 0.0f, FATTRIB_HAS_CALLBACK ); m_flMaxDistance.InitAndSet( this, "maxDistance", 0.0f, FATTRIB_HAS_CALLBACK ); } void CDmePointLight::OnDestruction() { } //----------------------------------------------------------------------------- // Sets the attenuation factors //----------------------------------------------------------------------------- void CDmePointLight::SetAttenuation( float flConstant, float flLinear, float flQuadratic ) { m_flAttenuation0 = flConstant; m_flAttenuation1 = flLinear; m_flAttenuation2 = flQuadratic; } //----------------------------------------------------------------------------- // Sets the maximum range //----------------------------------------------------------------------------- void CDmePointLight::SetMaxDistance( float flMaxDistance ) { m_flMaxDistance = flMaxDistance; } //----------------------------------------------------------------------------- // Sets up render state in the material system for rendering //----------------------------------------------------------------------------- bool CDmePointLight::GetLightDesc( LightDesc_t *pDesc ) { memset( pDesc, 0, sizeof(LightDesc_t) ); pDesc->m_Type = MATERIAL_LIGHT_POINT; SetupRenderStateInternal( *pDesc, m_flAttenuation0, m_flAttenuation1, m_flAttenuation2 ); matrix3x4_t m; GetTransform()->GetTransform( m ); VectorTransform( m_Position, m, pDesc->m_Position ); pDesc->m_Direction.Init( 0, 0, 1 ); pDesc->m_Range = m_flMaxDistance; pDesc->m_Theta = 0.0f; pDesc->m_Phi = 0.0f; pDesc->m_Falloff = 1.0f; return true; } //----------------------------------------------------------------------------- // // A spot light // //----------------------------------------------------------------------------- IMPLEMENT_ELEMENT_FACTORY( DmeSpotLight, CDmeSpotLight ); //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CDmeSpotLight::OnConstruction() { m_Direction.InitAndSet( this, "direction", Vector( 0.0f, 0.0f, -1.0f ) ); m_flSpotInnerAngle.InitAndSet( this, "spotInnerAngle", 60.0f ); m_flSpotOuterAngle.InitAndSet( this, "spotOuterAngle", 90.0f ); m_flSpotAngularFalloff.InitAndSet( this, "spotAngularFalloff", 1.0f ); } void CDmeSpotLight::OnDestruction() { } //----------------------------------------------------------------------------- // Sets the light direction //----------------------------------------------------------------------------- void CDmeSpotLight::SetDirection( const Vector &direction ) { m_Direction = direction; } //----------------------------------------------------------------------------- // Sets the spotlight angle factors // Angles are specified in degrees, as full angles (as opposed to half-angles) //----------------------------------------------------------------------------- void CDmeSpotLight::SetAngles( float flInnerAngle, float flOuterAngle, float flAngularFalloff ) { m_flSpotInnerAngle = flInnerAngle; m_flSpotOuterAngle = flOuterAngle; m_flSpotAngularFalloff = flAngularFalloff; } //----------------------------------------------------------------------------- // Sets up render state in the material system for rendering //----------------------------------------------------------------------------- bool CDmeSpotLight::GetLightDesc( LightDesc_t *pDesc ) { memset( pDesc, 0, sizeof(LightDesc_t) ); pDesc->m_Type = MATERIAL_LIGHT_SPOT; SetupRenderStateInternal( *pDesc, m_flAttenuation0, m_flAttenuation1, m_flAttenuation2 ); matrix3x4_t m; GetTransform()->GetTransform( m ); VectorTransform( m_Position, m, pDesc->m_Position ); VectorRotate( m_Direction.Get(), m, pDesc->m_Direction ); VectorNormalize( pDesc->m_Direction ); pDesc->m_Range = m_flMaxDistance; // Convert to radians pDesc->m_Theta = m_flSpotInnerAngle * M_PI / 180.0f; pDesc->m_Phi = m_flSpotOuterAngle * M_PI / 180.0f; pDesc->m_Falloff = m_flSpotAngularFalloff; return true; } //----------------------------------------------------------------------------- // // An ambient light // //----------------------------------------------------------------------------- IMPLEMENT_ELEMENT_FACTORY( DmeAmbientLight, CDmeAmbientLight ); //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CDmeAmbientLight::OnConstruction() { } void CDmeAmbientLight::OnDestruction() { } //----------------------------------------------------------------------------- // Sets up render state in the material system for rendering //----------------------------------------------------------------------------- void CDmeAmbientLight::SetupRenderState( int nLightIndex ) { CMatRenderContextPtr pRenderContext( g_pMaterialSystem ); Vector4D cube[6]; Vector4D vec4color( m_Color.Get().r(), m_Color.Get().g(), m_Color.Get().b(), m_Color.Get().a() ); Vector4DMultiply( vec4color, m_flIntensity / 255.0f, cube[0] ); cube[1] = cube[0]; cube[2] = cube[0]; cube[3] = cube[0]; cube[4] = cube[0]; cube[5] = cube[0]; pRenderContext->SetAmbientLightCube( cube ); }