MLRSpotLight.cpp 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314
  1. //===========================================================================//
  2. // Copyright (C) Microsoft Corporation. All rights reserved. //
  3. //===========================================================================//
  4. #include "MLRHeaders.hpp"
  5. //#############################################################################
  6. //######################### MLRSpotLight ################################
  7. //#############################################################################
  8. MLRSpotLight::ClassData*
  9. MLRSpotLight::DefaultData = NULL;
  10. //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  11. //
  12. void
  13. MLRSpotLight::InitializeClass()
  14. {
  15. Verify(!DefaultData);
  16. Verify(gos_GetCurrentHeap() == StaticHeap);
  17. DefaultData =
  18. new ClassData(
  19. MLRSpotLightClassID,
  20. "MidLevelRenderer::MLRSpotLight",
  21. MLRInfiniteLightWithFalloff::DefaultData
  22. );
  23. Register_Object(DefaultData);
  24. }
  25. //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  26. //
  27. void
  28. MLRSpotLight::TerminateClass()
  29. {
  30. Unregister_Object(DefaultData);
  31. delete DefaultData;
  32. DefaultData = NULL;
  33. }
  34. //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  35. //
  36. MLRSpotLight::MLRSpotLight() :
  37. MLRInfiniteLightWithFalloff(DefaultData)
  38. {
  39. Verify(gos_GetCurrentHeap() == Heap);
  40. lightMap = NULL;
  41. }
  42. //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  43. //
  44. MLRSpotLight::MLRSpotLight(
  45. Stuff::MemoryStream *stream,
  46. int version
  47. ) :
  48. MLRInfiniteLightWithFalloff(DefaultData, stream, version)
  49. {
  50. Check_Object(stream);
  51. Verify(gos_GetCurrentHeap() == Heap);
  52. lightMap = NULL;
  53. if (version > 7)
  54. {
  55. MString name;
  56. *stream >> name;
  57. if (name.GetLength() > 0)
  58. {
  59. Check_Object(MLRTexturePool::Instance);
  60. MLRTexture *texture = (*MLRTexturePool::Instance)(name, 0);
  61. if (!texture)
  62. texture = MLRTexturePool::Instance->Add(name, 0);
  63. Check_Object(texture);
  64. lightMap = new MLRLightMap(texture);
  65. Check_Object(lightMap);
  66. lightMask |= MLRState::LightMapLightingMode;
  67. }
  68. }
  69. Radian angle;
  70. *stream >> angle;
  71. SetSpreadAngle(angle);
  72. }
  73. //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  74. //
  75. MLRSpotLight::MLRSpotLight(Stuff::Page *page):
  76. MLRInfiniteLightWithFalloff(DefaultData, page)
  77. {
  78. Check_Object(page);
  79. Verify(gos_GetCurrentHeap() == Heap);
  80. lightMap = NULL;
  81. const char* lightmap;
  82. if (page->GetEntry("LightMap", &lightmap))
  83. {
  84. Check_Pointer(lightmap);
  85. Check_Object(MLRTexturePool::Instance);
  86. MLRTexture *texture = (*MLRTexturePool::Instance)(lightmap, 0);
  87. if (!texture)
  88. texture = MLRTexturePool::Instance->Add(lightmap, 0);
  89. Check_Object(texture);
  90. lightMap = new MLRLightMap(texture);
  91. Check_Object(lightMap);
  92. lightMask |= MLRState::LightMapLightingMode;
  93. }
  94. Degree angle=45.0;
  95. page->GetEntry("Spread", &angle.angle);
  96. SetSpreadAngle(angle);
  97. }
  98. //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  99. //
  100. MLRSpotLight::~MLRSpotLight()
  101. {
  102. if (lightMap)
  103. {
  104. Check_Object(lightMap);
  105. delete lightMap;
  106. }
  107. }
  108. //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  109. //
  110. void
  111. MLRSpotLight::Save(Stuff::MemoryStream *stream)
  112. {
  113. Check_Object(this);
  114. Check_Object(stream);
  115. MLRInfiniteLightWithFalloff::Save(stream);
  116. if (lightMap)
  117. {
  118. Check_Object(lightMap);
  119. unsigned handle = lightMap->GetState().GetTextureHandle();
  120. MLRTexture *texture = (*MLRTexturePool::Instance)[handle];
  121. Check_Object(texture);
  122. MString name = texture->GetTextureName();
  123. *stream << name;
  124. }
  125. else
  126. *stream << MString("");
  127. *stream << spreadAngle;
  128. }
  129. //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  130. //
  131. void
  132. MLRSpotLight::Write(Stuff::Page *page)
  133. {
  134. Check_Object(this);
  135. Check_Object(page);
  136. MLRInfiniteLightWithFalloff::Write(page);
  137. if (lightMap)
  138. {
  139. Check_Object(lightMap);
  140. unsigned handle = lightMap->GetState().GetTextureHandle();
  141. MLRTexture *texture = (*MLRTexturePool::Instance)[handle];
  142. Check_Object(texture);
  143. page->SetEntry("LightMap", texture->GetTextureName());
  144. }
  145. page->SetEntry("Spread", spreadAngle * Degrees_Per_Radian);
  146. }
  147. //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  148. //
  149. void
  150. MLRSpotLight::TestInstance()
  151. {
  152. Verify(IsDerivedFrom(DefaultData));
  153. }
  154. //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  155. //
  156. void
  157. MLRSpotLight::SetSpreadAngle(const Radian &radian)
  158. {
  159. Check_Object(this);
  160. spreadAngle = radian;
  161. tanSpreadAngle = (Scalar)tan(spreadAngle);
  162. cosSpreadAngle = (Scalar)cos(spreadAngle);
  163. }
  164. //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  165. //
  166. void
  167. MLRSpotLight::SetSpreadAngle(const Degree &degree)
  168. {
  169. Check_Object(this);
  170. spreadAngle = degree;
  171. tanSpreadAngle = (Scalar)tan(spreadAngle);
  172. cosSpreadAngle = (Scalar)cos(spreadAngle);
  173. }
  174. //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  175. //
  176. bool
  177. MLRSpotLight::GetSpreadAngle(Radian *angle)
  178. {
  179. Check_Object(this);
  180. *angle = spreadAngle;
  181. return true;
  182. }
  183. //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  184. //
  185. void
  186. MLRSpotLight::LightVertex(const MLRVertexData& vertexData)
  187. {
  188. UnitVector3D light_z;
  189. RGBColor light_color(color);
  190. Point3D vertex_to_light;
  191. Verify(GetFalloffDistance(vertex_to_light.x, vertex_to_light.y));
  192. GetInShapePosition(vertex_to_light);
  193. vertex_to_light -= *vertexData.point;
  194. //
  195. //--------------------------------------------------------------
  196. // If the distance to the vertex is zero, the light will not
  197. // contribute to the vertex coloration. Otherwise, decrease the
  198. // light level as appropriate to the distance
  199. //--------------------------------------------------------------
  200. //
  201. Scalar length = vertex_to_light.GetApproximateLength();
  202. Scalar falloff = 1.0f;
  203. if(GetFalloff(length, falloff))
  204. {
  205. light_color.red *= falloff;
  206. light_color.green *= falloff;
  207. light_color.blue *= falloff;
  208. }
  209. else
  210. {
  211. return;
  212. }
  213. Scalar cos_spread_angle = GetCosSpreadAngle();
  214. GetInWorldDirection(light_z);
  215. length = -1.0f / length;
  216. vertex_to_light *= length;
  217. Scalar t = vertex_to_light * light_z;
  218. if (t <= cos_spread_angle)
  219. {
  220. return;
  221. }
  222. /* Verify(!Close_Enough(cos_spread_angle, 1.0f));
  223. spread = 1.0f - ((1.0f - t) / (1.0f - cos_spread_angle));
  224. light_color.red *= cos_spread_angle;
  225. light_color.green *= cos_spread_angle;
  226. light_color.blue *= cos_spread_angle;
  227. */
  228. light_z.x = vertex_to_light.x;
  229. light_z.y = vertex_to_light.y;
  230. light_z.z = vertex_to_light.z;
  231. //
  232. //-------------------------------------------------------------------
  233. // Now we reduce the light level falling on the vertex based upon the
  234. // cosine of the angle between light and normal
  235. //-------------------------------------------------------------------
  236. //
  237. Scalar cosine = -(light_z * (*vertexData.normal)) * intensity;
  238. #if COLOR_AS_DWORD
  239. #else
  240. if (cosine > SMALL)
  241. {
  242. light_color.red *= cosine;
  243. light_color.green *= cosine;
  244. light_color.blue *= cosine;
  245. vertexData.color->red += light_color.red;
  246. vertexData.color->green += light_color.green;
  247. vertexData.color->blue += light_color.blue;
  248. }
  249. #endif
  250. }
  251. //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  252. //
  253. void
  254. MLRSpotLight::SetLightMap(MLRLightMap *light_map)
  255. {
  256. Check_Object(this);
  257. if (lightMap)
  258. {
  259. Check_Object(lightMap);
  260. delete lightMap;
  261. }
  262. lightMap = light_map;
  263. if (lightMap == NULL)
  264. {
  265. lightMask &= ~MLRState::LightMapLightingMode;
  266. }
  267. else
  268. {
  269. Check_Object(light_map);
  270. lightMask |= MLRState::LightMapLightingMode;
  271. }
  272. }