Light.cpp 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365
  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. }
  229. float Light::getRangeInverse() const
  230. {
  231. GP_ASSERT(_type != DIRECTIONAL);
  232. switch (_type)
  233. {
  234. case POINT:
  235. GP_ASSERT(_point);
  236. return _point->rangeInverse;
  237. case SPOT:
  238. GP_ASSERT(_spot);
  239. return _spot->rangeInverse;
  240. default:
  241. GP_ERROR("Unsupported light type (%d).", _type);
  242. return 0.0f;
  243. }
  244. }
  245. float Light::getInnerAngle() const
  246. {
  247. GP_ASSERT(_type == SPOT);
  248. return _spot->innerAngle;
  249. }
  250. void Light::setInnerAngle(float innerAngle)
  251. {
  252. GP_ASSERT(_type == SPOT);
  253. _spot->innerAngle = innerAngle;
  254. _spot->innerAngleCos = cos(innerAngle);
  255. }
  256. float Light::getOuterAngle() const
  257. {
  258. GP_ASSERT(_type == SPOT);
  259. return _spot->outerAngle;
  260. }
  261. void Light::setOuterAngle(float outerAngle)
  262. {
  263. GP_ASSERT(_type == SPOT);
  264. _spot->outerAngle = outerAngle;
  265. _spot->outerAngleCos = cos(outerAngle);
  266. }
  267. float Light::getInnerAngleCos() const
  268. {
  269. GP_ASSERT(_type == SPOT);
  270. return _spot->innerAngleCos;
  271. }
  272. float Light::getOuterAngleCos() const
  273. {
  274. GP_ASSERT(_type == SPOT);
  275. return _spot->outerAngleCos;
  276. }
  277. Light* Light::clone(NodeCloneContext &context) const
  278. {
  279. Light* lightClone = NULL;
  280. switch (_type)
  281. {
  282. case DIRECTIONAL:
  283. lightClone = createDirectional(getColor());
  284. break;
  285. case POINT:
  286. lightClone = createPoint(getColor(), getRange());
  287. break;
  288. case SPOT:
  289. lightClone = createSpot(getColor(), getRange(), getInnerAngle(), getOuterAngle());
  290. break;
  291. default:
  292. GP_ERROR("Unsupported light type (%d).", _type);
  293. return NULL;
  294. }
  295. GP_ASSERT(lightClone);
  296. if (Node* node = context.findClonedNode(getNode()))
  297. {
  298. lightClone->setNode(node);
  299. }
  300. return lightClone;
  301. }
  302. Light::Directional::Directional(const Vector3& color)
  303. : color(color)
  304. {
  305. }
  306. Light::Point::Point(const Vector3& color, float range)
  307. : color(color), range(range)
  308. {
  309. rangeInverse = 1.0f / range;
  310. }
  311. Light::Spot::Spot(const Vector3& color, float range, float innerAngle, float outerAngle)
  312. : color(color), range(range), innerAngle(innerAngle), outerAngle(outerAngle)
  313. {
  314. rangeInverse = 1.0f / range;
  315. innerAngleCos = cos(innerAngle);
  316. outerAngleCos = cos(outerAngle);
  317. }
  318. }