Counter Strike : Global Offensive Source Code
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

239 lines
6.7 KiB

  1. //========= Copyright � 1996-2005, Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose: Dynamic light
  4. //
  5. // $Workfile: $
  6. // $Date: $
  7. // $NoKeywords: $
  8. //=============================================================================//
  9. #include "cbase.h"
  10. #include "dlight.h"
  11. #include "iefx.h"
  12. #include "iviewrender.h"
  13. // memdbgon must be the last include file in a .cpp file!!!
  14. #include "tier0/memdbgon.h"
  15. #if HL2_EPISODIC
  16. // In Episodic we unify the NO_WORLD_ILLUMINATION lights to use
  17. // the more efficient elight structure instead. This should theoretically
  18. // be extended to other projects but may have unintended consequences
  19. // and bears more thorough testing.
  20. //
  21. // For an earlier iteration on this technique see changelist 214433,
  22. // which had a specific flag for use of elights.
  23. #define DLIGHT_NO_WORLD_USES_ELIGHT 1
  24. #endif
  25. //-----------------------------------------------------------------------------
  26. // A dynamic light, with the goofy hack needed for spotlights
  27. //-----------------------------------------------------------------------------
  28. class C_DynamicLight : public C_BaseEntity
  29. {
  30. public:
  31. DECLARE_CLASS( C_DynamicLight, C_BaseEntity );
  32. DECLARE_CLIENTCLASS();
  33. C_DynamicLight();
  34. public:
  35. void OnDataChanged(DataUpdateType_t updateType);
  36. bool ShouldDraw();
  37. void ClientThink( void );
  38. void Release( void );
  39. unsigned char m_Flags;
  40. unsigned char m_LightStyle;
  41. float m_Radius;
  42. int m_Exponent;
  43. float m_InnerAngle;
  44. float m_OuterAngle;
  45. float m_SpotRadius;
  46. private:
  47. dlight_t* m_pDynamicLight;
  48. dlight_t* m_pSpotlightEnd;
  49. inline bool ShouldBeElight() { return (m_Flags & DLIGHT_NO_WORLD_ILLUMINATION); }
  50. };
  51. IMPLEMENT_CLIENTCLASS_DT(C_DynamicLight, DT_DynamicLight, CDynamicLight)
  52. RecvPropInt (RECVINFO(m_Flags)),
  53. RecvPropInt (RECVINFO(m_LightStyle)),
  54. RecvPropFloat (RECVINFO(m_Radius)),
  55. RecvPropInt (RECVINFO(m_Exponent)),
  56. RecvPropFloat (RECVINFO(m_InnerAngle)),
  57. RecvPropFloat (RECVINFO(m_OuterAngle)),
  58. RecvPropFloat (RECVINFO(m_SpotRadius)),
  59. END_RECV_TABLE()
  60. //------------------------------------------------------------------------------
  61. // Purpose :
  62. //------------------------------------------------------------------------------
  63. C_DynamicLight::C_DynamicLight(void) : m_pSpotlightEnd(0), m_pDynamicLight(0)
  64. {
  65. }
  66. //------------------------------------------------------------------------------
  67. // Purpose :
  68. //------------------------------------------------------------------------------
  69. void C_DynamicLight::OnDataChanged(DataUpdateType_t updateType)
  70. {
  71. if ( updateType == DATA_UPDATE_CREATED )
  72. {
  73. SetNextClientThink(gpGlobals->curtime + 0.05);
  74. }
  75. BaseClass::OnDataChanged( updateType );
  76. }
  77. //------------------------------------------------------------------------------
  78. // Purpose :
  79. //------------------------------------------------------------------------------
  80. bool C_DynamicLight::ShouldDraw()
  81. {
  82. return false;
  83. }
  84. //------------------------------------------------------------------------------
  85. // Purpose : Disable drawing of this light when entity perishes
  86. //------------------------------------------------------------------------------
  87. void C_DynamicLight::Release()
  88. {
  89. if (m_pDynamicLight)
  90. {
  91. m_pDynamicLight->die = gpGlobals->curtime;
  92. m_pDynamicLight = 0;
  93. }
  94. if (m_pSpotlightEnd)
  95. {
  96. m_pSpotlightEnd->die = gpGlobals->curtime;
  97. m_pSpotlightEnd = 0;
  98. }
  99. BaseClass::Release();
  100. }
  101. //------------------------------------------------------------------------------
  102. // Purpose :
  103. //------------------------------------------------------------------------------
  104. void C_DynamicLight::ClientThink(void)
  105. {
  106. Vector forward;
  107. AngleVectors( GetAbsAngles(), &forward );
  108. if ( (m_Flags & DLIGHT_NO_MODEL_ILLUMINATION) == 0 )
  109. {
  110. // Deal with the model light
  111. if ( !m_pDynamicLight || (m_pDynamicLight->key != index) )
  112. {
  113. #if DLIGHT_NO_WORLD_USES_ELIGHT
  114. m_pDynamicLight = ShouldBeElight() != 0
  115. ? effects->CL_AllocElight( index )
  116. : effects->CL_AllocDlight( index );
  117. #else
  118. m_pDynamicLight = effects->CL_AllocDlight( index );
  119. #endif
  120. Assert (m_pDynamicLight);
  121. m_pDynamicLight->minlight = 0;
  122. }
  123. m_pDynamicLight->style = m_LightStyle;
  124. m_pDynamicLight->radius = m_Radius;
  125. m_pDynamicLight->flags = m_Flags;
  126. if ( m_OuterAngle > 0 )
  127. m_pDynamicLight->flags |= DLIGHT_NO_WORLD_ILLUMINATION;
  128. color24 c = GetRenderColor();
  129. m_pDynamicLight->color.r = c.r;
  130. m_pDynamicLight->color.g = c.g;
  131. m_pDynamicLight->color.b = c.b;
  132. m_pDynamicLight->color.exponent = m_Exponent; // this makes it match the world
  133. m_pDynamicLight->origin = GetAbsOrigin();
  134. m_pDynamicLight->m_InnerAngle = m_InnerAngle;
  135. m_pDynamicLight->m_OuterAngle = m_OuterAngle;
  136. m_pDynamicLight->die = gpGlobals->curtime + 1e6;
  137. m_pDynamicLight->m_Direction = forward;
  138. }
  139. else
  140. {
  141. // In this case, the m_Flags could have changed; which is how we turn the light off
  142. if (m_pDynamicLight)
  143. {
  144. m_pDynamicLight->die = gpGlobals->curtime;
  145. m_pDynamicLight = 0;
  146. }
  147. }
  148. #if DLIGHT_NO_WORLD_USES_ELIGHT
  149. if (( m_OuterAngle > 0 ) && !ShouldBeElight())
  150. #else
  151. if (( m_OuterAngle > 0 ) && ((m_Flags & DLIGHT_NO_WORLD_ILLUMINATION) == 0))
  152. #endif
  153. {
  154. // Raycast to where the endpoint goes
  155. // Deal with the environment light
  156. if ( !m_pSpotlightEnd || (m_pSpotlightEnd->key != -index) )
  157. {
  158. m_pSpotlightEnd = effects->CL_AllocDlight( -index );
  159. Assert (m_pSpotlightEnd);
  160. }
  161. // Trace a line outward, don't use hitboxes (too slow)
  162. Vector end;
  163. VectorMA( GetAbsOrigin(), m_Radius, forward, end );
  164. trace_t pm;
  165. C_BaseEntity::PushEnableAbsRecomputations( false ); // HACK don't recompute positions while doing RayTrace
  166. UTIL_TraceLine( GetAbsOrigin(), end, MASK_NPCWORLDSTATIC, NULL, COLLISION_GROUP_NONE, &pm );
  167. C_BaseEntity::PopEnableAbsRecomputations();
  168. VectorCopy( pm.endpos, m_pSpotlightEnd->origin );
  169. if (pm.fraction == 1.0f)
  170. {
  171. m_pSpotlightEnd->die = gpGlobals->curtime;
  172. m_pSpotlightEnd = 0;
  173. }
  174. else
  175. {
  176. float falloff = 1.0 - pm.fraction;
  177. falloff *= falloff;
  178. m_pSpotlightEnd->style = m_LightStyle;
  179. m_pSpotlightEnd->flags = DLIGHT_NO_MODEL_ILLUMINATION | (m_Flags & DLIGHT_DISPLACEMENT_MASK);
  180. m_pSpotlightEnd->radius = m_SpotRadius; // * falloff;
  181. m_pSpotlightEnd->die = gpGlobals->curtime + 1e6;
  182. color24 c = GetRenderColor();
  183. m_pSpotlightEnd->color.r = c.r * falloff;
  184. m_pSpotlightEnd->color.g = c.g * falloff;
  185. m_pSpotlightEnd->color.b = c.b * falloff;
  186. m_pSpotlightEnd->color.exponent = m_Exponent;
  187. // For bumped lighting
  188. m_pSpotlightEnd->m_Direction = forward;
  189. // Update list of surfaces we influence
  190. render->TouchLight( m_pSpotlightEnd );
  191. }
  192. }
  193. else
  194. {
  195. // In this case, the m_Flags could have changed; which is how we turn the light off
  196. if (m_pSpotlightEnd)
  197. {
  198. m_pSpotlightEnd->die = gpGlobals->curtime;
  199. m_pSpotlightEnd = 0;
  200. }
  201. }
  202. SetNextClientThink(gpGlobals->curtime + 0.001);
  203. }