PolyRadTool.cpp 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228
  1. /*
  2. * PolyRadTool.cpp
  3. * Poly
  4. *
  5. * Created by Ivan Safrin on 9/25/08.
  6. * Copyright 2008 __MyCompanyName__. All rights reserved.
  7. *
  8. */
  9. #include "PolyRadTool.h"
  10. using namespace Polycode;
  11. RadTool::RadTool(GenericScene *scene, LightmapPacker *packer) {
  12. this->scene = scene;
  13. this->packer = packer;
  14. }
  15. void RadTool::fiatLux(int radPasses) {
  16. Vector3 baseAmbient(0.033f, 0.033f, 0.033f);
  17. Color col;
  18. for(int i=0; i < packer->lumels.size(); i++) {
  19. packer->lumels[i]->rEnergy.set(baseAmbient.x, baseAmbient.y, baseAmbient.z);
  20. packer->images[packer->lumels[i]->face->imageID]->setPixel(packer->lumels[i]->u*packer->lightMapRes, packer->lumels[i]->v*packer->lightMapRes, Color(baseAmbient.x, baseAmbient.y, baseAmbient.z, 1.0f));
  21. }
  22. // applyLight(scene->getLight(1));
  23. for(int i =0; i < scene->getNumLights(); i++) {
  24. applyLight(scene->getLight(i));
  25. }
  26. for(int i=0; i < radPasses; i++) {
  27. Logger::log("doing radiosity pass %d\n", i);
  28. doRadiosityPass();
  29. }
  30. }
  31. void RadTool::doRadiosityPass() {
  32. for(int i=0; i < packer->lumels.size(); i+=1) {
  33. radLumel(packer->lumels[i], packer->images[packer->lumels[i]->face->imageID]);
  34. }
  35. }
  36. void RadTool::applyLight(SceneLight *light) {
  37. for(int i=0; i < packer->lumels.size(); i++) {
  38. lightLumel(light, packer->images[packer->lumels[i]->face->imageID], packer->lumels[i]);
  39. }
  40. }
  41. bool RadTool::rayTriangleIntersect(Vector3 ray_origin, Vector3 ray_direction, Vector3 vert0, Vector3 vert1, Vector3 vert2, Vector3 *hitPoint)
  42. {
  43. float t,u,v;
  44. t = 0; u = 0; v = 0;
  45. Vector3 edge1 = vert1 - vert0;
  46. Vector3 edge2 = vert2 - vert0;
  47. Vector3 tvec, pvec, qvec;
  48. float det, inv_det;
  49. pvec = ray_direction.crossProduct(edge2);
  50. det = edge1.dot(pvec);
  51. if (det > -0.00001f)
  52. return false;
  53. inv_det = 1.0f / det;
  54. tvec = ray_origin - vert0;
  55. // hitPoint = tvec;
  56. u = tvec.dot(pvec) * inv_det;
  57. if (u < -0.001f || u > 1.001f)
  58. return false;
  59. qvec = tvec.crossProduct(edge1);
  60. v = ray_direction.dot(qvec) * inv_det;
  61. if (v < -0.001f || u + v > 1.001f)
  62. return false;
  63. t = edge2.dot(qvec) * inv_det;
  64. if (t <= 0)
  65. return false;
  66. hitPoint->x = ray_origin.x+t*ray_direction.x;
  67. hitPoint->y = ray_origin.y+t*ray_direction.y;
  68. hitPoint->z = ray_origin.z+t*ray_direction.z;
  69. return true;
  70. }
  71. bool RadTool::worldRayTest(Vector3 origin, Vector3 destination,Poly::Polygon *hitPolygon) {
  72. Vector3 hitPoint,dirVec;
  73. dirVec = destination-origin;
  74. for(int i= 0; i < packer->lightmapMeshes.size(); i++) {
  75. Matrix4 meshMatrix = packer->lightmapMeshes[i]->mesh->getConcatenatedMatrix();
  76. for(int j=0; j < packer->lightmapMeshes[i]->faces.size(); j++) {
  77. if(rayTriangleIntersect(origin, dirVec,
  78. meshMatrix*(*packer->lightmapMeshes[i]->faces[j]->meshPolygon->getVertex(0)),
  79. meshMatrix*(*packer->lightmapMeshes[i]->faces[j]->meshPolygon->getVertex(1)),
  80. meshMatrix*(*packer->lightmapMeshes[i]->faces[j]->meshPolygon->getVertex(2)),
  81. &hitPoint)) {
  82. float dist = hitPoint.distance(origin);
  83. if(dist < destination.distance(origin) && dist > 1.3f) {
  84. hitPolygon = packer->lightmapMeshes[i]->faces[j]->meshPolygon;
  85. return true;
  86. }
  87. }
  88. }
  89. }
  90. return false;
  91. }
  92. void RadTool::radLumel(Lumel *lumel, Image *image) {
  93. Lumel *lumel2;
  94. float numSeen = 0;
  95. float totalVal_r = 0;
  96. float totalVal_g = 0;
  97. float totalVal_b = 0;
  98. for(int i=0; i < packer->lumels.size(); i+=1000) {
  99. lumel2 = packer->lumels[i];
  100. // if(!worldRayTest(lumel->worldPos, lumel2->worldPos, hitPoly)) {
  101. float dist = lumel2->worldPos.distance(lumel->worldPos);
  102. Vector3 lightVector = lumel2->worldPos-lumel->worldPos;
  103. lightVector.Normalize();
  104. float diffuse = lumel->normal.dot(lightVector);
  105. float pwr = 1.3f;
  106. float val = 1.0f - (dist/45.0f);
  107. val = val * pwr * diffuse * lumel2->lumelScale;
  108. totalVal_r += lumel2->rEnergy.x * val;
  109. totalVal_g += lumel2->rEnergy.y * val;
  110. totalVal_b += lumel2->rEnergy.z * val;
  111. numSeen++;
  112. // }
  113. }
  114. totalVal_r = totalVal_r / numSeen;
  115. totalVal_g = totalVal_g / numSeen;
  116. totalVal_b = totalVal_b / numSeen;
  117. if(totalVal_r < 0)
  118. totalVal_r = 0;
  119. if(totalVal_g < 0)
  120. totalVal_g = 0;
  121. if(totalVal_b < 0)
  122. totalVal_b = 0;
  123. Color col;
  124. lumel->rEnergy.x += totalVal_r;
  125. lumel->rEnergy.y += totalVal_g;
  126. lumel->rEnergy.z += totalVal_b;
  127. if(lumel->rEnergy.x > 1.0f)
  128. lumel->rEnergy.x = 1.0f;
  129. if(lumel->rEnergy.y > 1.0f)
  130. lumel->rEnergy.y = 1.0f;
  131. if(lumel->rEnergy.z > 1.0f)
  132. lumel->rEnergy.z = 1.0f;
  133. col.setColor(lumel->rEnergy.x,lumel->rEnergy.y,lumel->rEnergy.z,1.0f);
  134. image->setPixel(lumel->u*packer->lightMapRes, lumel->v*packer->lightMapRes, col);
  135. }
  136. void RadTool::lightLumel(SceneLight *light, Image *image, Lumel *lumel) {
  137. float dist = light->getPosition()->distance(lumel->worldPos);
  138. Vector3 lightVector = (*light->getPosition())-lumel->worldPos;
  139. lightVector.Normalize();
  140. float diffuse = lumel->normal.dot(lightVector);
  141. //float diffuse = 1;
  142. Polygon *hitPoly;
  143. if(worldRayTest(lumel->worldPos, *light->getPosition(), hitPoly))
  144. return;
  145. float val = ((light->getDistance()) /(dist*dist));
  146. if(val > 1.0f)
  147. val = 1.0f;
  148. float pwr = light->getIntensity();
  149. val = val * pwr * diffuse;
  150. if(val < 0)
  151. val = 0;
  152. Color col;
  153. lumel->rEnergy.x += light->lightColor.r*val;
  154. lumel->rEnergy.y += light->lightColor.g*val;
  155. lumel->rEnergy.z += light->lightColor.b*val;
  156. if(lumel->rEnergy.x > 1.0f)
  157. lumel->rEnergy.x = 1.0f;
  158. if(lumel->rEnergy.y > 1.0f)
  159. lumel->rEnergy.y = 1.0f;
  160. if(lumel->rEnergy.z > 1.0f)
  161. lumel->rEnergy.z = 1.0f;
  162. //lumel->rEnergy.Normalize();
  163. col.setColor(lumel->rEnergy.x,lumel->rEnergy.y,lumel->rEnergy.z,1.0f);
  164. image->setPixel(lumel->u*packer->lightMapRes, lumel->v*packer->lightMapRes, col);
  165. }
  166. RadTool::~RadTool() {
  167. }