AmbientLightVisitor.cpp 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257
  1. /***************************************************************************
  2. AmbientLightVisitor.cpp - description
  3. -------------------
  4. begin : Wed Jan 26 2000
  5. copyright : (C) 2000 by Henrik Enqvist
  6. email : henqvist@excite.com
  7. ***************************************************************************/
  8. #include "Private.h"
  9. #include "AmbientLightVisitor.h"
  10. #include "Group.h"
  11. #include "Shape3D.h"
  12. #include "Polygon.h"
  13. #include "Config.h"
  14. #include "Light.h"
  15. AmbientLightVisitor * AmbientLightVisitor::p_AmbientLightVisitor = NULL;
  16. AmbientLightVisitor::AmbientLightVisitor(int size) {
  17. m_fStrength = (float)0.1;
  18. m_fBackground = (float)0.0;
  19. m_vLight.reserve(size);
  20. }
  21. AmbientLightVisitor::~AmbientLightVisitor() {
  22. p_AmbientLightVisitor = NULL;
  23. }
  24. AmbientLightVisitor * AmbientLightVisitor::getInstance() {
  25. if (p_AmbientLightVisitor == NULL) {
  26. p_AmbientLightVisitor = new AmbientLightVisitor();
  27. }
  28. return p_AmbientLightVisitor;
  29. }
  30. void AmbientLightVisitor::add(Light* l) {
  31. if (l == NULL) return;
  32. m_vLight.push_back(l);
  33. }
  34. void AmbientLightVisitor::clear() {
  35. m_vLight.clear();
  36. }
  37. void AmbientLightVisitor::setLightning(float s, float bg) {
  38. m_fStrength = s;
  39. m_fBackground = bg;
  40. #if OPENGL_LIGHTS
  41. GLfloat amb[] = {bg, bg, bg, 1};
  42. glLightModelfv(GL_LIGHT_MODEL_AMBIENT,amb);
  43. glEnable(GL_LIGHT0);
  44. // create light
  45. GLfloat pos[] = {0.0f, 10000.0f, 0.0f, 0.0f};
  46. GLfloat light[] = {s, s, s, 1.0f};
  47. glLightfv(GL_LIGHT0, GL_POSITION, pos);
  48. glLightfv(GL_LIGHT0, GL_DIFFUSE, light);
  49. glLightfv(GL_LIGHT0, GL_SPECULAR, light);
  50. #endif
  51. }
  52. void AmbientLightVisitor::visit(Group * g) {
  53. // Check properties before applying light
  54. if (g->m_iProperties & EM_GROUP_NO_LIGHT) return;
  55. if (g->m_iProperties & EM_GROUP_LIGHT_ONCE) {
  56. g->unsetProperty(EM_GROUP_LIGHT_ONCE);
  57. g->setProperty(EM_GROUP_NO_LIGHT);
  58. }
  59. vector<Shape3D*>::iterator iter = g->m_vShape3D.begin();
  60. vector<Shape3D*>::iterator end = g->m_vShape3D.end();
  61. for ( ; iter != end; iter++) {
  62. if ((*iter)->m_iProperties & (EM_SHAPE3D_HIDDEN | EM_SHAPE3D_ALWAYSLIT)) continue;
  63. //if ((*iter)->m_iProperties & EM_SHAPE3D_TRANS) continue;
  64. //if ((*iter)->m_iProperties & EM_SHAPE3D_HIDDEN) continue;
  65. this->visitAmbient((*iter));
  66. this->visitPoint((*iter));
  67. }
  68. }
  69. void AmbientLightVisitor::visitAmbient(Shape3D* s) {
  70. EM_COUT("AmbientLightVisitor::visit()" << endl, 0);
  71. //TODO Flat polygons - who cares about flat polygons anyway
  72. EM_COUT_D("AmbientLightVisitor::visit() shape lights " <<
  73. (*shapeIter)->m_vLight.size() << " normal " <<
  74. (*shapeIter)->m_vNmlTrans.size() << endl, 0);
  75. // Count light for all vertices.
  76. vector<Color>::iterator diffuseIter = s->m_vLight.begin();
  77. vector<Color>::iterator diffuseEnd = s->m_vLight.end();
  78. vector<Color>::iterator specularIter = s->m_vSpecular.begin();
  79. vector<Vertex3D>::iterator nmlTransIter = s->m_vNmlTrans.begin();
  80. vector<Vertex3D>::iterator nmlAlignIter = s->m_vNmlAlign.begin();
  81. //vector<Color>::iterator specularEnd = s->m_vSpecular.end();
  82. //vector<Vertex3D>::iterator nmlTransEnd = s->m_vNmlTrans.end();
  83. //vector<Vertex3D>::iterator nmlAlignEnd = s->m_vNmlAlign.end();
  84. for ( ; diffuseIter != diffuseEnd;
  85. ++diffuseIter, ++nmlTransIter, ++nmlAlignIter, ++specularIter) {
  86. // Count angle between normal and y-axis.
  87. float fAngle = (*nmlTransIter).y;
  88. float fLight = fAngle/2 + 0.5;
  89. // float fLight = 0.5;
  90. (*diffuseIter).r = fLight * m_fStrength + m_fBackground;
  91. (*diffuseIter).r = EM_MIN(1.0, (*diffuseIter).r);
  92. (*diffuseIter).g = (*diffuseIter).b = (*diffuseIter).r;
  93. EM_COUT_D("Light " << (*diffuseIter).r << " " << (*diffuseIter).g << " " <<
  94. (*diffuseIter).b << endl, 0);
  95. // TODO: Move if-specular outside for loop
  96. // specular light
  97. #if EM_USE_GLOBAL_SPECULAR
  98. if (s->m_iProperties & EM_SHAPE3D_SPECULAR) {
  99. Vertex3D vtxRef = {0,0,-1};
  100. Vertex3D vtxDir = {0,-1,0};
  101. EMath::reflection(vtxDir, (*nmlAlignIter), vtxRef, false);
  102. EMath::normalizeVector(vtxRef); // TODO: optimize - remove normalize
  103. //float view = EMath::dotProduct((*nmlAlignIter), vtxView); // TODO: optimize
  104. float spe = EM_MAX(0.0f, vtxRef.z);
  105. float spe2 = spe * spe;
  106. float spe4 = spe2 * spe2;
  107. (*specularIter).r = (*specularIter).g = (*specularIter).b = spe4 * spe4 * 0.5;
  108. } else {
  109. (*specularIter).r = (*specularIter).g = (*specularIter).b = 0;
  110. }
  111. #else
  112. (*specularIter).r = (*specularIter).g = (*specularIter).b = 0;
  113. #endif
  114. }
  115. }
  116. void AmbientLightVisitor::visitPoint(Shape3D * s) {
  117. if (Config::getInstance()->useLights()) {
  118. vector<Light*>::iterator lightIter = m_vLight.begin();
  119. vector<Light*>::iterator lightEnd = m_vLight.end();
  120. EM_COUT("PointLightVisitor::visit() lights " << m_vLight.size(), 0);
  121. for ( ; lightIter != lightEnd; ++lightIter) {
  122. if (!(*lightIter)->m_bOn) continue;
  123. // TODO check bounds with collision bounds so that we don't
  124. // need to check every vertex.
  125. // TODO ugly optimization: if statements moved outside for loop
  126. vector<Vertex3D>::iterator vtxTransIter = s->m_vVtxTrans.begin();
  127. vector<Vertex3D>::iterator vtxTransEnd = s->m_vVtxTrans.end();
  128. vector<Vertex3D>::iterator vtxAlignIter = s->m_vVtxAlign.begin();
  129. vector<Vertex3D>::iterator nmlTransIter = s->m_vNmlTrans.begin();
  130. vector<Vertex3D>::iterator nmlAlignIter = s->m_vNmlAlign.begin();
  131. vector<Color>::iterator diffuseIter = s->m_vLight.begin();
  132. vector<Color>::iterator specularIter = s->m_vSpecular.begin();
  133. //vector<Vertex3D>::iterator vtxAlignEnd = s->m_vVtxAlign.end();
  134. //vector<Vertex3D>::iterator nmlTransEnd = s->m_vNmlTrans.end();
  135. //vector<Vertex3D>::iterator nmlAlignEnd = s->m_vNmlAlign.end();
  136. //vector<Color>::iterator diffuseEnd = s->m_vLight.end();
  137. //vector<Color>::iterator specularEnd = s->m_vSpecular.end();
  138. for ( ; vtxTransIter != vtxTransEnd;
  139. ++vtxTransIter, ++vtxAlignIter, ++nmlTransIter,
  140. ++nmlAlignIter, ++diffuseIter, ++specularIter) {
  141. if ((*lightIter)->m_iProperties & EM_USE_DIFFUSE) {
  142. Vertex3D vtxLight;
  143. // Get length from vertex to light
  144. vtxLight.x = (*lightIter)->m_vtxTrans.x - (*vtxTransIter).x;
  145. vtxLight.y = (*lightIter)->m_vtxTrans.y - (*vtxTransIter).y;
  146. vtxLight.z = (*lightIter)->m_vtxTrans.z - (*vtxTransIter).z;
  147. float lengthsqr = EMath::vectorLengthSqr(vtxLight);
  148. // Check bounds
  149. if (((*lightIter)->m_iProperties & EM_USE_BOUNDS) &&
  150. lengthsqr > ((*lightIter)->m_fBounds*(*lightIter)->m_fBounds)) {
  151. continue;
  152. }
  153. // TODO Move if statement outside for loop for performance
  154. // Calculate angle between normal and light
  155. float light;
  156. if ((*lightIter)->m_iProperties & EM_IGNORE_ANGLE_FULL) {
  157. light = 1;
  158. } else if ((*lightIter)->m_iProperties & EM_IGNORE_ANGLE_HALF) {
  159. EMath::normalizeVector(vtxLight);
  160. float angle = EMath::dotProduct((*nmlTransIter), vtxLight);
  161. light = angle; // 1.0f - EMath::emAcos(angle)/EM_PI_DIV_2; // ??
  162. if (light > 0.0f) light = 1.0f;
  163. } else {
  164. EMath::normalizeVector(vtxLight);
  165. float angle = EMath::dotProduct((*nmlTransIter), vtxLight);
  166. light = angle;// 1.0f - EMath::emAcos(angle)/EM_PI_DIV_2;
  167. light = EM_MAX(0.0f, light);
  168. }
  169. // Calculate distance
  170. float k;
  171. if ((*lightIter)->m_iProperties & EM_IGNORE_DISTANCE) {
  172. k = light;
  173. } else {
  174. k = light / ((*lightIter)->m_fConstant +
  175. (*lightIter)->m_fLinear * EMath::emSqrt(lengthsqr) +
  176. (*lightIter)->m_fQuadratic * lengthsqr);
  177. }
  178. (*diffuseIter).r += k * (*lightIter)->m_fR;
  179. (*diffuseIter).g += k * (*lightIter)->m_fG;
  180. (*diffuseIter).b += k * (*lightIter)->m_fB;
  181. }
  182. // specular light
  183. #if EM_USE_SOURCE_SPECULAR
  184. if ((s->m_iProperties & EM_SHAPE3D_SPECULAR) &&
  185. ((*lightIter)->m_iProperties & EM_USE_SPECULAR)) {
  186. float specular;
  187. Vertex3D vtxRef = {0.0f ,0.0f , -1.0f};
  188. Vertex3D vtxDir;
  189. vtxDir.x = (*vtxAlignIter).x - (*lightIter)->m_vtxAlign.x;
  190. vtxDir.y = (*vtxAlignIter).y - (*lightIter)->m_vtxAlign.y;
  191. vtxDir.z = (*vtxAlignIter).z - (*lightIter)->m_vtxAlign.z;
  192. EMath::reflection(vtxDir, (*nmlAlignIter), vtxRef, false);
  193. EMath::normalizeVector(vtxRef); // TODO: optimize - remove normalize
  194. //float view = EMath::dotProduct((*nmlAlignIter), vtxView); // TODO: optimize
  195. float spe = EM_MAX(0.0f, vtxRef.z);
  196. float spe2 = spe * spe;
  197. float spe4 = spe2 * spe2;
  198. specular = spe4 * spe4;
  199. (*specularIter).r += specular * (*lightIter)->m_fR;
  200. (*specularIter).g += specular * (*lightIter)->m_fG;
  201. (*specularIter).b += specular * (*lightIter)->m_fB;
  202. }
  203. #endif
  204. EM_COUT_D("PointLightVisitor::visit() factor " << k, 0);
  205. EM_COUT_D("PointLightVisitor::visit() specular " << specular, 0);
  206. }
  207. }
  208. } // if config->useLights
  209. // apply the lights to the color
  210. // TODO textured polygons don't need color if filter != -1
  211. vector<Color>::iterator diffuseIter = s->m_vLight.begin();
  212. vector<Color>::iterator diffuseEnd = s->m_vLight.end();
  213. vector<Color>::iterator specularIter = s->m_vSpecular.begin();
  214. vector<Color>::iterator colorIter = s->m_vColor.begin();
  215. vector<Color>::iterator litColorIter = s->m_vLitColor.begin();
  216. // move if statement outside loop for performance
  217. //if (s->m_iProperties & EM_SHAPE3D_SPECULAR) {
  218. for (; diffuseIter != diffuseEnd;
  219. ++diffuseIter, ++specularIter, ++colorIter, ++litColorIter) {
  220. (*litColorIter).r = (*colorIter).r * (*diffuseIter).r + (*specularIter).r;
  221. (*litColorIter).g = (*colorIter).g * (*diffuseIter).g + (*specularIter).g;
  222. (*litColorIter).b = (*colorIter).b * (*diffuseIter).b + (*specularIter).b;
  223. (*litColorIter).a = (*colorIter).a;
  224. }
  225. // } else {
  226. // for (; diffuseIter != diffuseEnd;
  227. // ++diffuseIter, ++specularIter, ++colorIter, ++litColorIter) {
  228. // (*litColorIter).r = (*colorIter).r * (*diffuseIter).r;
  229. // (*litColorIter).g = (*colorIter).g * (*diffuseIter).g;
  230. // (*litColorIter).b = (*colorIter).b * (*diffuseIter).b;
  231. // (*litColorIter).a = (*colorIter).a;
  232. // }
  233. /*
  234. (*litColorIter).r = EM_MAX((*litColorIter).r, 1.0f);
  235. (*litColorIter).g = EM_MAX((*litColorIter).g, 1.0f);
  236. (*litColorIter).b = EM_MAX((*litColorIter).b, 1.0f);
  237. */
  238. }