LightObject.cc 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239
  1. #include "graphics/dgl.h"
  2. #include "console/consoleTypes.h"
  3. #include "2d/core/Utility.h"
  4. #include "2d/sceneobject/LightObject.h"
  5. // Script bindings.
  6. #include "LightObject_ScriptBinding.h"
  7. IMPLEMENT_CONOBJECT(LightObject);
  8. LightObject::LightObject():
  9. mLightRadius(10.0f),
  10. mLightSegments(15)
  11. {
  12. mSrcBlendFactor = GL_SRC_ALPHA;
  13. mDstBlendFactor = GL_ONE;
  14. // Use a static body by default.
  15. mBodyDefinition.type = b2_staticBody;
  16. }
  17. LightObject::~LightObject()
  18. {
  19. }
  20. bool LightObject::onAdd()
  21. {
  22. // Call Parent.
  23. if (!Parent::onAdd())
  24. return false;
  25. // Return Okay.
  26. return true;
  27. }
  28. //----------------------------------------------------------------------------
  29. void LightObject::onRemove()
  30. {
  31. // Call Parent.
  32. Parent::onRemove();
  33. }
  34. void LightObject::initPersistFields()
  35. {
  36. Parent::initPersistFields();
  37. /// Light settings.
  38. addProtectedField("LightRadius", TypeF32, Offset(mLightRadius, LightObject), &setLightRadius, &defaultProtectedGetFn, &writeLightRadius, "");
  39. addProtectedField("LightSegments", TypeS32, Offset(mLightSegments, LightObject), &setLightSegments, &defaultProtectedGetFn, &writeLightSegments, "");
  40. }
  41. void LightObject::safeDelete(void)
  42. {
  43. Parent::safeDelete();
  44. }
  45. void LightObject::sceneRender(const SceneRenderState * sceneRenderState, const SceneRenderRequest * sceneRenderRequest, BatchRender * batchRender)
  46. {
  47. Vector2 worldPos = getPosition();
  48. Vector<Vector2> verts;
  49. Vector<RayList> bList;
  50. S32 mSrcLightBlend = getSrcBlendFactor();
  51. S32 mDstLightBlend = getDstBlendFactor();
  52. ColorF mLightColor = getBlendColor();
  53. F32 radius = getLightRadius();
  54. Scene* scene = getScene();
  55. b2World* mWorld = scene->getWorld();
  56. glEnable(GL_BLEND);
  57. glDisable(GL_TEXTURE_2D);
  58. glPushMatrix();
  59. glTranslatef(worldPos.x, worldPos.y, 0);
  60. glPolygonMode(GL_FRONT, GL_FILL);
  61. //additive blending
  62. //glBlendFunc(GL_ONE,GL_ONE);
  63. glBlendFunc(mSrcLightBlend, mDstLightBlend);
  64. // Creates the fading dark region.
  65. glBegin(GL_TRIANGLE_FAN);
  66. glColor4f(mLightColor.red,mLightColor.green,mLightColor.blue,mLightColor.alpha);
  67. glVertex2f(0, 0);
  68. //check scene objects
  69. U32 objCount = scene->getSceneObjectCount();
  70. for (U32 i = 0; i < objCount; i++)
  71. {
  72. SceneObject *tObj = scene->getSceneObject(i);
  73. Vector2 dist = worldPos - tObj->getPosition();
  74. const F32 distSqr = dist.LengthSquared();
  75. const F32 radSqr = radius * radius;
  76. //within radius?
  77. if (distSqr < radSqr || distSqr == radSqr)
  78. {
  79. U32 shapeCount = tObj->getCollisionShapeCount();
  80. for (U32 j = 0; j < shapeCount; j++)
  81. {
  82. //All vertices from polygon collision shape
  83. if (tObj->getCollisionShapeType(j) == b2Shape::e_polygon)
  84. {
  85. U32 pCount = tObj->getPolygonCollisionShapePointCount(j);
  86. for (U32 k = 0; k < pCount; k++)
  87. {
  88. Vector2 locPoint = tObj->getPolygonCollisionShapeLocalPoint(j, k);
  89. Vector2 wPoint = tObj->getWorldPoint(locPoint);
  90. verts.push_back(wPoint);
  91. }
  92. }
  93. }
  94. }
  95. }
  96. /// \ | /
  97. /// - + -
  98. /// / | \
  99. U32 lightSeg = getLightSegments();
  100. F32 segAng = 360.0f / lightSeg;
  101. for (U32 i = 0; i <= lightSeg; i++)
  102. {
  103. b2Vec2 segStrt = worldPos;
  104. b2Vec2 segEnd = segStrt + radius * b2Vec2(mCos(mDegToRad((F32)segAng * i)), mSin(mDegToRad((F32)segAng * i)));
  105. verts.push_back(segEnd);
  106. }
  107. //cast ray to vertices
  108. for (S32 l = 0; l < verts.size(); l++)
  109. {
  110. F32 rayLength = radius;
  111. Vector2 p1 = worldPos;
  112. Vector2 p2 = verts[l];
  113. F32 baseAng = mAtan(p2.x, p2.y);
  114. F32 cAng = 0;
  115. for (int m = 0; m < 2; m++)
  116. {
  117. if (m == 0)cAng = baseAng - 0.0001f;
  118. //if (m == 1)cAng = baseAng;
  119. if (m == 1)cAng = baseAng + 0.0001f;
  120. p2.x = rayLength * mCos(cAng);
  121. p2.y = rayLength * mSin(cAng);
  122. RaysCastCallback callback;
  123. mWorld->RayCast(&callback, p1, p2);
  124. if (callback.m_fixture)
  125. {
  126. F32 ang = mAtan(callback.m_point.x - p1.x, callback.m_point.y - p1.y);
  127. Vector2 intersection = p1 + callback.m_fraction * (p2 - p1);
  128. RayList intersectionPoint;
  129. intersectionPoint.ang = ang;
  130. intersectionPoint.x = intersection.x;
  131. intersectionPoint.y = intersection.y;
  132. intersectionPoint.l = callback.m_fraction;
  133. bList.push_back_unique(intersectionPoint);
  134. }
  135. else
  136. {
  137. F32 ang = mAtan(p2.x - p1.x, p2.y - p1.y);
  138. RayList intersectionPoint;
  139. intersectionPoint.ang = ang;
  140. intersectionPoint.x = p2.x;
  141. intersectionPoint.y = p2.y;
  142. intersectionPoint.l = 1.0;
  143. bList.push_back_unique(intersectionPoint);
  144. }
  145. }
  146. }
  147. //Con::printf("Rays cast: %i", bList.size());
  148. //sort the list
  149. if (bList.size() > 1)
  150. {
  151. dQsort(bList.address(), bList.size(), sizeof(RayList), sortRays);
  152. }
  153. //triangle fan
  154. for (S32 m = 0; m < bList.size(); m++)
  155. {
  156. glColor4f(mLightColor.red - (mLightColor.red * bList[m].l), mLightColor.green - (mLightColor.green * bList[m].l), mLightColor.blue - (mLightColor.blue * bList[m].l), mLightColor.alpha - (mLightColor.alpha * bList[m].l));
  157. glVertex2f(bList[m].x, bList[m].y);
  158. }
  159. //close off the circle
  160. glColor4f(mLightColor.red - (mLightColor.red * bList[0].l), mLightColor.green - (mLightColor.green * bList[0].l), mLightColor.blue - (mLightColor.blue * bList[0].l), mLightColor.alpha - (mLightColor.alpha * bList[0].l));
  161. glVertex2f(bList[0].x, bList[0].y);
  162. glDisable(GL_BLEND);
  163. glEnd();
  164. glPopMatrix();
  165. }
  166. void LightObject::OnRegisterScene(Scene* mScene)
  167. {
  168. Parent::OnRegisterScene(mScene);
  169. mScene->getWorldQuery()->addAlwaysInScope(this);
  170. }
  171. void LightObject::OnUnregisterScene(Scene* mScene)
  172. {
  173. mScene->getWorldQuery()->removeAlwaysInScope(this);
  174. Parent::OnUnregisterScene(mScene);
  175. }
  176. S32 QSORT_CALLBACK sortRays(const void* a, const void* b)
  177. {
  178. RayList* ray_a = (RayList*) a;
  179. RayList* ray_b = (RayList*) b;
  180. if (ray_a->ang < ray_b->ang)
  181. {
  182. return -1;
  183. }
  184. else if (ray_a->ang > ray_b->ang)
  185. {
  186. return 1;
  187. }
  188. return 0;
  189. }