Light.cpp 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371
  1. #include "Base.h"
  2. #include "Light.h"
  3. #include "Node.h"
  4. namespace gameplay
  5. {
  6. Light::Light(Light::Type type, const Vector3& color) :
  7. _type(type), _node(NULL)
  8. {
  9. _directional = new Directional(color);
  10. }
  11. Light::Light(Light::Type type, const Vector3& color, float range) :
  12. _type(type), _node(NULL)
  13. {
  14. _point = new Point(color, range);
  15. }
  16. Light::Light(Light::Type type, const Vector3& color, float range, float innerAngle, float outerAngle) :
  17. _type(type), _node(NULL)
  18. {
  19. _spot = new Spot(color, range, innerAngle, outerAngle);
  20. }
  21. Light::~Light()
  22. {
  23. switch (_type)
  24. {
  25. case DIRECTIONAL:
  26. SAFE_DELETE(_directional);
  27. break;
  28. case POINT:
  29. SAFE_DELETE(_point);
  30. break;
  31. case SPOT:
  32. SAFE_DELETE(_spot);
  33. break;
  34. default:
  35. GP_ERROR("Invalid light type (%d).", _type);
  36. break;
  37. }
  38. }
  39. Light* Light::createDirectional(const Vector3& color)
  40. {
  41. return new Light(DIRECTIONAL, color);
  42. }
  43. Light* Light::createDirectional(float red, float green, float blue)
  44. {
  45. return new Light(DIRECTIONAL, Vector3(red, green, blue));
  46. }
  47. Light* Light::createPoint(const Vector3& color, float range)
  48. {
  49. return new Light(POINT, color, range);
  50. }
  51. Light* Light::createPoint(float red, float green, float blue, float range)
  52. {
  53. return new Light(POINT, Vector3(red, green, blue), range);
  54. }
  55. Light* Light::createSpot(const Vector3& color, float range, float innerAngle, float outerAngle)
  56. {
  57. return new Light(SPOT, color, range, innerAngle, outerAngle);
  58. }
  59. Light* Light::createSpot(float red, float green, float blue, float range, float innerAngle, float outerAngle)
  60. {
  61. return new Light(SPOT, Vector3(red, green, blue), range, innerAngle, outerAngle);
  62. }
  63. Light* Light::create(Properties* properties)
  64. {
  65. GP_ASSERT(properties);
  66. // Read light type
  67. std::string typeStr;
  68. if (properties->exists("type"))
  69. typeStr = properties->getString("type");
  70. Light::Type type;
  71. if (typeStr == "DIRECTIONAL")
  72. {
  73. type = Light::DIRECTIONAL;
  74. }
  75. else if (typeStr == "POINT")
  76. {
  77. type = Light::POINT;
  78. }
  79. else if (typeStr == "SPOT")
  80. {
  81. type = Light::SPOT;
  82. }
  83. else
  84. {
  85. GP_ERROR("Invalid 'type' parameter for light definition.");
  86. return NULL;
  87. }
  88. // Read common parameters
  89. Vector3 color;
  90. if (!properties->getVector3("color", &color))
  91. {
  92. GP_ERROR("Missing valid 'color' parameter for light definition.");
  93. return NULL;
  94. }
  95. // Read light-specific parameters
  96. Light* light = NULL;
  97. switch (type)
  98. {
  99. case DIRECTIONAL:
  100. light = createDirectional(color);
  101. break;
  102. case POINT:
  103. {
  104. float range = properties->getFloat("range");
  105. if (range == 0.0f)
  106. {
  107. GP_ERROR("Missing valid 'range' parameter for point light definition.");
  108. return NULL;
  109. }
  110. light = createPoint(color, range);
  111. }
  112. break;
  113. case SPOT:
  114. float range = properties->getFloat("range");
  115. if (range == 0.0f)
  116. {
  117. GP_ERROR("Missing valid 'range' parameter for spot light definition.");
  118. return NULL;
  119. }
  120. float innerAngle = properties->getFloat("innerAngle");
  121. if (innerAngle == 0.0f)
  122. {
  123. GP_ERROR("Missing valid 'innerAngle' parameter for spot light definition.");
  124. return NULL;
  125. }
  126. float outerAngle = properties->getFloat("outerAngle");
  127. if (outerAngle == 0.0f)
  128. {
  129. GP_ERROR("Missing valid 'outerAngle' parameter for spot light definition.");
  130. return NULL;
  131. }
  132. light = createSpot(color, range, innerAngle, outerAngle);
  133. break;
  134. }
  135. return light;
  136. }
  137. Light::Type Light::getLightType() const
  138. {
  139. return _type;
  140. }
  141. Node* Light::getNode() const
  142. {
  143. return _node;
  144. }
  145. void Light::setNode(Node* node)
  146. {
  147. // Connect the new node.
  148. _node = node;
  149. }
  150. const Vector3& Light::getColor() const
  151. {
  152. switch (_type)
  153. {
  154. case DIRECTIONAL:
  155. GP_ASSERT(_directional);
  156. return _directional->color;
  157. case POINT:
  158. GP_ASSERT(_point);
  159. return _point->color;
  160. case SPOT:
  161. GP_ASSERT(_spot);
  162. return _spot->color;
  163. default:
  164. GP_ERROR("Unsupported light type (%d).", _type);
  165. return Vector3::zero();
  166. }
  167. }
  168. void Light::setColor(const Vector3& color)
  169. {
  170. switch (_type)
  171. {
  172. case DIRECTIONAL:
  173. GP_ASSERT(_directional);
  174. _directional->color = color;
  175. break;
  176. case POINT:
  177. GP_ASSERT(_point);
  178. _point->color = color;
  179. break;
  180. case SPOT:
  181. GP_ASSERT(_spot);
  182. _spot->color = color;
  183. break;
  184. default:
  185. GP_ERROR("Unsupported light type (%d).", _type);
  186. break;
  187. }
  188. }
  189. void Light::setColor(float red, float green, float blue)
  190. {
  191. setColor(Vector3(red, green, blue));
  192. }
  193. float Light::getRange() const
  194. {
  195. GP_ASSERT(_type != DIRECTIONAL);
  196. switch (_type)
  197. {
  198. case POINT:
  199. GP_ASSERT(_point);
  200. return _point->range;
  201. case SPOT:
  202. GP_ASSERT(_spot);
  203. return _spot->range;
  204. default:
  205. GP_ERROR("Unsupported light type (%d).", _type);
  206. return 0.0f;
  207. }
  208. }
  209. void Light::setRange(float range)
  210. {
  211. GP_ASSERT(_type != DIRECTIONAL);
  212. switch (_type)
  213. {
  214. case POINT:
  215. GP_ASSERT(_point);
  216. _point->range = range;
  217. _point->rangeInverse = 1.0f / range;
  218. break;
  219. case SPOT:
  220. GP_ASSERT(_spot);
  221. _spot->range = range;
  222. _spot->rangeInverse = 1.0f / range;
  223. break;
  224. default:
  225. GP_ERROR("Unsupported light type (%d).", _type);
  226. break;
  227. }
  228. if (_node)
  229. _node->setBoundsDirty();
  230. }
  231. float Light::getRangeInverse() const
  232. {
  233. GP_ASSERT(_type != DIRECTIONAL);
  234. switch (_type)
  235. {
  236. case POINT:
  237. GP_ASSERT(_point);
  238. return _point->rangeInverse;
  239. case SPOT:
  240. GP_ASSERT(_spot);
  241. return _spot->rangeInverse;
  242. default:
  243. GP_ERROR("Unsupported light type (%d).", _type);
  244. return 0.0f;
  245. }
  246. }
  247. float Light::getInnerAngle() const
  248. {
  249. GP_ASSERT(_type == SPOT);
  250. return _spot->innerAngle;
  251. }
  252. void Light::setInnerAngle(float innerAngle)
  253. {
  254. GP_ASSERT(_type == SPOT);
  255. _spot->innerAngle = innerAngle;
  256. _spot->innerAngleCos = cos(innerAngle);
  257. }
  258. float Light::getOuterAngle() const
  259. {
  260. GP_ASSERT(_type == SPOT);
  261. return _spot->outerAngle;
  262. }
  263. void Light::setOuterAngle(float outerAngle)
  264. {
  265. GP_ASSERT(_type == SPOT);
  266. _spot->outerAngle = outerAngle;
  267. _spot->outerAngleCos = cos(outerAngle);
  268. if (_node)
  269. _node->setBoundsDirty();
  270. }
  271. float Light::getInnerAngleCos() const
  272. {
  273. GP_ASSERT(_type == SPOT);
  274. return _spot->innerAngleCos;
  275. }
  276. float Light::getOuterAngleCos() const
  277. {
  278. GP_ASSERT(_type == SPOT);
  279. return _spot->outerAngleCos;
  280. }
  281. Light* Light::clone(NodeCloneContext &context) const
  282. {
  283. Light* lightClone = NULL;
  284. switch (_type)
  285. {
  286. case DIRECTIONAL:
  287. lightClone = createDirectional(getColor());
  288. break;
  289. case POINT:
  290. lightClone = createPoint(getColor(), getRange());
  291. break;
  292. case SPOT:
  293. lightClone = createSpot(getColor(), getRange(), getInnerAngle(), getOuterAngle());
  294. break;
  295. default:
  296. GP_ERROR("Unsupported light type (%d).", _type);
  297. return NULL;
  298. }
  299. GP_ASSERT(lightClone);
  300. if (Node* node = context.findClonedNode(getNode()))
  301. {
  302. lightClone->setNode(node);
  303. }
  304. return lightClone;
  305. }
  306. Light::Directional::Directional(const Vector3& color)
  307. : color(color)
  308. {
  309. }
  310. Light::Point::Point(const Vector3& color, float range)
  311. : color(color), range(range)
  312. {
  313. rangeInverse = 1.0f / range;
  314. }
  315. Light::Spot::Spot(const Vector3& color, float range, float innerAngle, float outerAngle)
  316. : color(color), range(range), innerAngle(innerAngle), outerAngle(outerAngle)
  317. {
  318. rangeInverse = 1.0f / range;
  319. innerAngleCos = cos(innerAngle);
  320. outerAngleCos = cos(outerAngle);
  321. }
  322. }