PointLightVisitor.cpp 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191
  1. /***************************************************************************
  2. PointLightVisitor.cpp - description
  3. -------------------
  4. begin : Sun Jan 30 2000
  5. copyright : (C) 2000 by Henrik Enqvist
  6. email : henqvist@excite.com
  7. ***************************************************************************/
  8. #include "Private.h"
  9. #include "PointLightVisitor.h"
  10. #include "Light.h"
  11. #include "Shape3D.h"
  12. #include "Group.h"
  13. #include "EMath.h"
  14. #include "Polygon.h"
  15. #include "Config.h"
  16. PointLightVisitor * PointLightVisitor::p_PointLightVisitor = NULL;
  17. PointLightVisitor::PointLightVisitor(int size) {
  18. m_vLight.reserve(size);
  19. }
  20. PointLightVisitor::~PointLightVisitor() {
  21. p_PointLightVisitor = NULL;
  22. }
  23. PointLightVisitor * PointLightVisitor::getInstance() {
  24. if (p_PointLightVisitor == NULL) {
  25. p_PointLightVisitor = new PointLightVisitor();
  26. }
  27. return p_PointLightVisitor;
  28. }
  29. void PointLightVisitor::add(Light* l) {
  30. if (l == NULL) return;
  31. m_vLight.push_back(l);
  32. }
  33. void PointLightVisitor::clear() {
  34. m_vLight.clear();
  35. }
  36. void PointLightVisitor::visit(Group * g) {
  37. EM_COUT("PointLightVisitor deprecated", 1);
  38. exit(1);
  39. // Check properties before applying light
  40. if (g->m_iProperties & EM_GROUP_NO_LIGHT) return;
  41. if (g->m_iProperties & EM_GROUP_LIGHT_ONCE) {
  42. g->unsetProperty(EM_GROUP_LIGHT_ONCE);
  43. g->setProperty(EM_GROUP_NO_LIGHT);
  44. }
  45. vector<Shape3D*>::iterator iter = g->m_vShape3D.begin();
  46. vector<Shape3D*>::iterator end = g->m_vShape3D.end();
  47. for ( ; iter != end; iter++) {
  48. // if ((*iter)->m_iProperties & EM_SHAPE3D_TRANS) continue;
  49. if ((*iter)->m_iProperties & EM_SHAPE3D_HIDDEN) continue;
  50. this->visit((*iter), g);
  51. }
  52. }
  53. void PointLightVisitor::visit(Shape3D * s, Group *) {
  54. #if 0
  55. if (Config::getInstance()->useLights()) {
  56. vector<Light*>::iterator lightIter = m_vLight.begin();
  57. vector<Light*>::iterator lightEnd = m_vLight.end();
  58. EM_COUT("PointLightVisitor::visit() lights " << m_vLight.size(), 0);
  59. for ( ; lightIter != lightEnd; ++lightIter) {
  60. if (!(*lightIter)->m_bOn) continue;
  61. // TODO check bounds with collision bounds so that we don't
  62. // need to check every vertex.
  63. // TODO ugly optimization: if statements moved outside for loop
  64. vector<Vertex3D>::iterator vtxTransIter = s->m_vVtxTrans.begin();
  65. vector<Vertex3D>::iterator vtxTransEnd = s->m_vVtxTrans.end();
  66. vector<Vertex3D>::iterator vtxAlignIter = s->m_vVtxAlign.begin();
  67. //vector<Vertex3D>::iterator vtxAlignEnd = s->m_vVtxAlign.end();
  68. vector<Vertex3D>::iterator nmlTransIter = s->m_vNmlTrans.begin();
  69. //vector<Vertex3D>::iterator nmlTransEnd = s->m_vNmlTrans.end();
  70. vector<Vertex3D>::iterator nmlAlignIter = s->m_vNmlAlign.begin();
  71. //vector<Vertex3D>::iterator nmlAlignEnd = s->m_vNmlAlign.end();
  72. vector<Color>::iterator diffuseIter = s->m_vLight.begin();
  73. //vector<Color>::iterator diffuseEnd = s->m_vLight.end();
  74. vector<Color>::iterator specularIter = s->m_vSpecular.begin();
  75. //vector<Color>::iterator specularEnd = s->m_vSpecular.end();
  76. for ( ; vtxTransIter != vtxTransEnd;
  77. ++vtxTransIter, ++vtxAlignIter, ++nmlTransIter,
  78. ++nmlAlignIter, ++diffuseIter, ++specularIter) {
  79. Vertex3D vtxLight;
  80. // Get length from vertex to light
  81. vtxLight.x = (*lightIter)->m_vtxTrans.x - (*vtxTransIter).x;
  82. vtxLight.y = (*lightIter)->m_vtxTrans.y - (*vtxTransIter).y;
  83. vtxLight.z = (*lightIter)->m_vtxTrans.z - (*vtxTransIter).z;
  84. float lengthsqr = EMath::vectorLengthSqr(vtxLight);
  85. // Check bounds
  86. if (((*lightIter)->m_iProperties & EM_USE_BOUNDS) &&
  87. lengthsqr > ((*lightIter)->m_fBounds*(*lightIter)->m_fBounds)) {
  88. continue;
  89. }
  90. // TODO Move if statement outside for loop for performance
  91. // Calculate angle between normal and light
  92. float light;
  93. if ((*lightIter)->m_iProperties & EM_IGNORE_ANGLE_FULL) {
  94. light = 1;
  95. } else if ((*lightIter)->m_iProperties & EM_IGNORE_ANGLE_HALF) {
  96. EMath::normalizeVector(vtxLight);
  97. float angle = EMath::dotProduct((*nmlTransIter), vtxLight);
  98. light = angle; // 1.0f - EMath::emAcos(angle)/EM_PI_DIV_2; // ??
  99. if (light > 0.0f) light = 1.0f;
  100. } else {
  101. EMath::normalizeVector(vtxLight);
  102. float angle = EMath::dotProduct((*nmlTransIter), vtxLight);
  103. light = angle;// 1.0f - EMath::emAcos(angle)/EM_PI_DIV_2;
  104. light = EM_MAX(0.0f, light);
  105. }
  106. // Calculate distance
  107. float k;
  108. if ((*lightIter)->m_iProperties & EM_IGNORE_DISTANCE) {
  109. k = light;
  110. } else {
  111. k = light / ((*lightIter)->m_fConstant +
  112. (*lightIter)->m_fLinear * EMath::emSqrt(lengthsqr) +
  113. (*lightIter)->m_fQuadratic * lengthsqr);
  114. }
  115. // specular light
  116. #if EM_USE_SOURCE_SPECULAR
  117. if (s->m_iProperties & EM_SHAPE3D_SPECULAR) {
  118. float specular;
  119. Vertex3D vtxRef = {0.0f ,0.0f , -1.0f};
  120. Vertex3D vtxDir;
  121. vtxDir.x = (*vtxAlignIter).x - (*lightIter)->m_vtxAlign.x;
  122. vtxDir.y = (*vtxAlignIter).y - (*lightIter)->m_vtxAlign.y;
  123. vtxDir.z = (*vtxAlignIter).z - (*lightIter)->m_vtxAlign.z;
  124. EMath::reflection(vtxDir, (*nmlAlignIter), vtxRef, false);
  125. EMath::normalizeVector(vtxRef); // TODO: optimize - remove normalize
  126. //float view = EMath::dotProduct((*nmlAlignIter), vtxView); // TODO: optimize
  127. float spe = EM_MAX(0.0f, vtxRef.z);
  128. float spe2 = spe * spe;
  129. float spe4 = spe2 * spe2;
  130. specular = spe4 * spe4;
  131. (*specularIter).r += specular * (*lightIter)->m_fR;
  132. (*specularIter).g += specular * (*lightIter)->m_fG;
  133. (*specularIter).b += specular * (*lightIter)->m_fB;
  134. }
  135. #endif
  136. EM_COUT_D("PointLightVisitor::visit() factor " << k, 0);
  137. EM_COUT_D("PointLightVisitor::visit() specular " << specular, 0);
  138. (*diffuseIter).r += k * (*lightIter)->m_fR;
  139. (*diffuseIter).g += k * (*lightIter)->m_fG;
  140. (*diffuseIter).b += k * (*lightIter)->m_fB;
  141. }
  142. }
  143. } // if config->useLights
  144. // apply the lights to the color
  145. // TODO textured polygons don't need color if filter != -1
  146. vector<Color>::iterator diffuseIter = s->m_vLight.begin();
  147. vector<Color>::iterator diffuseEnd = s->m_vLight.end();
  148. vector<Color>::iterator specularIter = s->m_vSpecular.begin();
  149. vector<Color>::iterator colorIter = s->m_vColor.begin();
  150. vector<Color>::iterator litColorIter = s->m_vLitColor.begin();
  151. // move if statement outside loop for performance
  152. if (s->m_iProperties & EM_SHAPE3D_SPECULAR) {
  153. for (; diffuseIter != diffuseEnd;
  154. ++diffuseIter, ++specularIter, ++colorIter, ++litColorIter) {
  155. (*litColorIter).r = (*colorIter).r * (*diffuseIter).r + (*specularIter).r;
  156. (*litColorIter).g = (*colorIter).g * (*diffuseIter).g + (*specularIter).g;
  157. (*litColorIter).b = (*colorIter).b * (*diffuseIter).b + (*specularIter).b;
  158. (*litColorIter).a = (*colorIter).a;
  159. }
  160. } else {
  161. for (; diffuseIter != diffuseEnd;
  162. ++diffuseIter, ++specularIter, ++colorIter, ++litColorIter) {
  163. (*litColorIter).r = (*colorIter).r * (*diffuseIter).r;
  164. (*litColorIter).g = (*colorIter).g * (*diffuseIter).g;
  165. (*litColorIter).b = (*colorIter).b * (*diffuseIter).b;
  166. (*litColorIter).a = (*colorIter).a;
  167. }
  168. /*
  169. (*litColorIter).r = EM_MAX((*litColorIter).r, 1.0f);
  170. (*litColorIter).g = EM_MAX((*litColorIter).g, 1.0f);
  171. (*litColorIter).b = EM_MAX((*litColorIter).b, 1.0f);
  172. */
  173. }
  174. #endif
  175. }