PolyLightmapPacker.cpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423
  1. /*
  2. * LightmapPacker.cpp
  3. * Poly
  4. *
  5. * Created by Ivan Safrin on 9/24/08.
  6. * Copyright 2008 __MyCompanyName__. All rights reserved.
  7. *
  8. */
  9. #include "PolyLightmapPacker.h"
  10. using namespace Polycode;
  11. LightmapPacker::LightmapPacker(GenericScene *targetScene) {
  12. this->targetScene = targetScene;
  13. currentImageID = -1;
  14. }
  15. LightmapPacker::~LightmapPacker() {
  16. }
  17. void LightmapPacker::unwrapScene() {
  18. for(int i=0; i < targetScene->getNumStaticGeometry(); i++) {
  19. LightmapMesh *newLMesh = new LightmapMesh;
  20. newLMesh->processed = false;
  21. newLMesh->mesh = targetScene->getStaticGeometry(i);
  22. lightmapMeshes.push_back(newLMesh);
  23. for(int j=0; j < targetScene->getStaticGeometry(i)->getMesh()->getPolygonCount(); j++) {
  24. Polygon *poly = targetScene->getStaticGeometry(i)->getMesh()->getPolygon(j);
  25. Vector3 fnormal = poly->getFaceNormal();
  26. Polygon *flatPoly = new Polygon();
  27. Polygon *flatUnscaled = new Polygon();
  28. LightmapFace *newFace = new LightmapFace;
  29. fnormal.x = fabsf(fnormal.x);
  30. fnormal.y = fabsf(fnormal.y);
  31. fnormal.z = fabsf(fnormal.z);
  32. // Logger::log("fnormal: %f %f %f\n", fnormal.x, fnormal.y, fnormal.z);
  33. if(fnormal.x > fnormal.y && fnormal.x > fnormal.z) {
  34. for(int k=0; k < poly->getVertexCount(); k++) {
  35. flatPoly->addVertex((poly->getVertex(k)->y*lightMapQuality)/lightMapRes, (poly->getVertex(k)->z*lightMapQuality)/lightMapRes, 0);
  36. flatUnscaled->addVertex(poly->getVertex(k)->y, poly->getVertex(k)->z, 0);
  37. }
  38. newFace->projectionAxis = LightmapFace::X_PROJECTION;
  39. } else if (fnormal.y > fnormal.x && fnormal.y > fnormal.z) {
  40. for(int k=0; k < poly->getVertexCount(); k++) {
  41. flatPoly->addVertex((poly->getVertex(k)->x*lightMapQuality)/lightMapRes, (poly->getVertex(k)->z*lightMapQuality)/lightMapRes, 0);
  42. flatUnscaled->addVertex(poly->getVertex(k)->x, poly->getVertex(k)->z, 0);
  43. }
  44. newFace->projectionAxis = LightmapFace::Y_PROJECTION;
  45. } else {
  46. for(int k=0; k < poly->getVertexCount(); k++) {
  47. flatPoly->addVertex((poly->getVertex(k)->x*lightMapQuality)/lightMapRes, (poly->getVertex(k)->y*lightMapQuality)/lightMapRes, 0);
  48. flatUnscaled->addVertex(poly->getVertex(k)->x, poly->getVertex(k)->y, 0);
  49. }
  50. newFace->projectionAxis = LightmapFace::Z_PROJECTION;
  51. }
  52. newFace->area = flatPoly->getBounds2D();
  53. float offx = newFace->area.x;
  54. float offy = newFace->area.y;
  55. newFace->area.x = 0;
  56. newFace->area.y = 0;
  57. // now align the flat face to 0,0
  58. for(int k=0; k < flatPoly->getVertexCount(); k++) {
  59. flatPoly->getVertex(k)->x -= offx;
  60. flatPoly->getVertex(k)->y -= offy;
  61. // flatPoly->getVertex(k)->x *= 1.1;
  62. // flatPoly->getVertex(k)->y *= 1.2;
  63. }
  64. newFace->meshPolygon = poly;
  65. newFace->flatPolygon = flatPoly;
  66. newFace->flatUnscaledPolygon = flatUnscaled;
  67. newFace->actualArea.w = (newFace->area.w * lightMapRes) / lightMapQuality;
  68. newFace->actualArea.h = (newFace->area.h * lightMapRes) / lightMapQuality;
  69. float lumelScale = 1.0f;
  70. float maxSize = 0.4f;
  71. if(newFace->area.w > maxSize || newFace->area.h > maxSize) {
  72. // Logger::log("WARNING, NORMALIZING FACE AREA (%f %f)\n", newFace->area.w, newFace->area.h);
  73. float tmp;
  74. if(newFace->area.w > newFace->area.h) {
  75. tmp = newFace->area.w;
  76. newFace->area.w = maxSize;
  77. newFace->area.h = newFace->area.h * (maxSize/tmp);
  78. } else {
  79. tmp = newFace->area.h;
  80. newFace->area.h = maxSize;
  81. newFace->area.w = newFace->area.w * (maxSize/tmp);
  82. }
  83. lumelScale = (1.0f / (maxSize/tmp)) * 100;
  84. for(int v=0; v < newFace->flatPolygon->getVertexCount(); v++) {
  85. newFace->flatPolygon->getVertex(v)->x = newFace->flatPolygon->getVertex(v)->x * (maxSize/tmp);
  86. newFace->flatPolygon->getVertex(v)->y = newFace->flatPolygon->getVertex(v)->y * (maxSize/tmp);
  87. }
  88. }
  89. // newFace->area.w += (4.0f/lightMapRes);
  90. // newFace->area.h += (4.0f/lightMapRes);
  91. newFace->pixelArea.w = (newFace->area.w * lightMapRes)+2;
  92. newFace->pixelArea.h = (newFace->area.h * lightMapRes)+2;
  93. // newFace->area.w = newFace->pixelArea.w / lightMapRes;
  94. // newFace->area.h = newFace->pixelArea.h / lightMapRes;
  95. newFace->numLumels = 0;
  96. for(float pw =-2 ;pw < newFace->pixelArea.w+3; pw++) {
  97. for(float ph =-2 ;ph < newFace->pixelArea.h+3; ph++) {
  98. Lumel *newLumel = new Lumel;
  99. newLumel->face = newFace;
  100. newLumel->lumelScale = lumelScale;
  101. newLumel->u = pw/lightMapRes;
  102. newLumel->v = ph/lightMapRes;
  103. newLumel->normal = newFace->meshPolygon->getFaceNormal();
  104. newFace->lumels.push_back(newLumel);
  105. lumels.push_back(newLumel);
  106. newFace->numLumels++;
  107. }
  108. }
  109. newLMesh->faces.push_back(newFace);
  110. }
  111. }
  112. }
  113. Vector3 LightmapPacker::getLumelPos(Lumel *lumel, LightmapFace *face) {
  114. Vector3 poly_normal = face->meshPolygon->getFaceNormal();
  115. Vector3 pointonplane = *face->meshPolygon->getVertex(0) ;
  116. // Vector3 pointonplane = (*face->meshPolygon->getVertex(0) + *face->meshPolygon->getVertex(1) + *face->meshPolygon->getVertex(2)) / 3.0f;
  117. float Distance = -(poly_normal.x * pointonplane.x + poly_normal.y * pointonplane.y + poly_normal.z * pointonplane.z);
  118. float X,Y,Z;
  119. Vector3 UVVector, Vect1, Vect2;
  120. float Min_U = face->flatUnscaledPolygon->getVertex(0)->x;
  121. float Min_V = face->flatUnscaledPolygon->getVertex(0)->y;
  122. float Max_U = face->flatUnscaledPolygon->getVertex(0)->x;
  123. float Max_V = face->flatUnscaledPolygon->getVertex(0)->y;
  124. for (int i = 0; i < 3; i++)
  125. {
  126. if (face->flatUnscaledPolygon->getVertex(i)->x < Min_U )
  127. Min_U = face->flatUnscaledPolygon->getVertex(i)->x;
  128. if (face->flatUnscaledPolygon->getVertex(i)->y < Min_V )
  129. Min_V = face->flatUnscaledPolygon->getVertex(i)->y;
  130. if (face->flatUnscaledPolygon->getVertex(i)->x > Max_U )
  131. Max_U = face->flatUnscaledPolygon->getVertex(i)->x;
  132. if (face->flatUnscaledPolygon->getVertex(i)->y > Max_V )
  133. Max_V = face->flatUnscaledPolygon->getVertex(i)->y;
  134. }
  135. switch(face->projectionAxis) {
  136. case LightmapFace::X_PROJECTION:
  137. X = - ( (poly_normal.y * Min_U) + (poly_normal.z * Min_V) + Distance )
  138. / poly_normal.x;
  139. UVVector.x = X;
  140. UVVector.y = Min_U;
  141. UVVector.z = Min_V;
  142. X = - ( (poly_normal.y * Max_U) + (poly_normal.z) * Min_V + Distance )
  143. / poly_normal.x;
  144. Vect1.x = X;
  145. Vect1.y = Max_U;
  146. Vect1.z = Min_V;
  147. X = - ( (poly_normal.y * Min_U) + (poly_normal.z * Max_V) + Distance )
  148. / poly_normal.x;
  149. Vect2.x = X;
  150. Vect2.y = Min_U;
  151. Vect2.z = Max_V;
  152. break;
  153. case LightmapFace::Y_PROJECTION:
  154. Y = - ( poly_normal.x * Min_U + poly_normal.z * Min_V + Distance )
  155. / poly_normal.y;
  156. UVVector.x = Min_U;
  157. UVVector.y = Y;
  158. UVVector.z = Min_V;
  159. Y = - ( poly_normal.x * Max_U + poly_normal.z * Min_V + Distance )
  160. / poly_normal.y;
  161. Vect1.x = Max_U;
  162. Vect1.y = Y;
  163. Vect1.z = Min_V;
  164. Y = - ( poly_normal.x * Min_U + poly_normal.z * Max_V + Distance )
  165. / poly_normal.y;
  166. Vect2.x = Min_U;
  167. Vect2.y = Y;
  168. Vect2.z = Max_V;
  169. break;
  170. case LightmapFace::Z_PROJECTION:
  171. Z = - ( poly_normal.x * Min_U + poly_normal.y * Min_V + Distance )
  172. / poly_normal.z;
  173. UVVector.x = Min_U;
  174. UVVector.y = Min_V;
  175. UVVector.z = Z;
  176. Z = - ( poly_normal.x * Max_U + poly_normal.y * Min_V + Distance )
  177. / poly_normal.z;
  178. Vect1.x = Max_U;
  179. Vect1.y = Min_V;
  180. Vect1.z = Z;
  181. Z = - ( poly_normal.x * Min_U + poly_normal.y * Max_V + Distance )
  182. / poly_normal.z;
  183. Vect2.x = Min_U;
  184. Vect2.y = Max_V;
  185. Vect2.z = Z;
  186. break;
  187. }
  188. Vector3 edge1,edge2,newedge1,newedge2;
  189. edge1.x = Vect1.x - UVVector.x;
  190. edge1.y = Vect1.y - UVVector.y;
  191. edge1.z = Vect1.z - UVVector.z;
  192. edge2.x = Vect2.x - UVVector.x;
  193. edge2.y = Vect2.y - UVVector.y;
  194. edge2.z = Vect2.z - UVVector.z;
  195. float ufactor = lumel->u/(face->area.w+(0.0f/lightMapRes));
  196. float vfactor = lumel->v/(face->area.h+(0.0f/lightMapRes));
  197. // Logger::log("edge1: %f %f %f", edge1.x, edge1.y,edge1.z);
  198. newedge1.x = edge1.x * ufactor;
  199. newedge1.y = edge1.y * ufactor;
  200. newedge1.z = edge1.z * ufactor;
  201. newedge2.x = edge2.x * vfactor;
  202. newedge2.y = edge2.y * vfactor;
  203. newedge2.z = edge2.z * vfactor;
  204. Vector3 retVec(UVVector.x + newedge2.x + newedge1.x,
  205. UVVector.y + newedge2.y + newedge1.y,
  206. UVVector.z + newedge2.z + newedge1.z);
  207. return retVec;
  208. }
  209. void LightmapPacker::packMesh(LightmapMesh *mesh) {
  210. Color col;
  211. mesh->imageID = currentImageID;
  212. mesh->mesh->lightmapIndex = currentImageID;
  213. for(int n=0; n < mesh->faces.size(); n++) {
  214. PackNode *pNode = cNode->Insert(mesh->faces[n]);
  215. if(pNode != NULL) {
  216. col.Random();
  217. currentImage->drawRect(pNode->rc.x-1, pNode->rc.y-1, pNode->rc.w+2, pNode->rc.h+2, col);
  218. pNode->face = mesh->faces[n];
  219. for(int i=0; i < mesh->faces[n]->flatPolygon->getVertexCount(); i++) {
  220. Vertex *vert = mesh->faces[n]->flatPolygon->getVertex(i);
  221. vert->x += (pNode->rc.x/lightMapRes);//-(1.0f/lightMapRes);
  222. vert->y += (pNode->rc.y/lightMapRes);//-(1.0f/lightMapRes);
  223. mesh->faces[n]->meshPolygon->addTexCoord2(vert->x,vert->y);
  224. mesh->mesh->getMesh()->numUVs = 2;
  225. }
  226. for(int nl = 0; nl < mesh->faces[n]->numLumels; nl++) {
  227. mesh->faces[n]->lumels[nl]->worldPos = mesh->mesh->getConcatenatedMatrix() * getLumelPos(mesh->faces[n]->lumels[nl], mesh->faces[n]);
  228. mesh->faces[n]->lumels[nl]->u += (pNode->rc.x/lightMapRes);
  229. mesh->faces[n]->lumels[nl]->v += (pNode->rc.y/lightMapRes);
  230. }
  231. mesh->faces[n]->imageID = currentImageID;
  232. mesh->faces[n]->pixelArea.x = pNode->rc.x;
  233. mesh->faces[n]->pixelArea.y = pNode->rc.y;
  234. } else {
  235. Logger::log("WARNING MESH DOES NOT FIT! %d of %d completed \n", n, mesh->faces.size());
  236. return;
  237. //generateNewImage();
  238. }
  239. }
  240. }
  241. void LightmapPacker::generateNewImage() {
  242. cNode = new PackNode();
  243. cNode->createRoot(lightMapRes);
  244. currentImage = new Image(lightMapRes,lightMapRes);
  245. currentImage->fill(0,0,0,1);
  246. images.push_back(currentImage);
  247. currentImageID++;
  248. }
  249. bool LightmapPacker::hasRoomForMesh(LightmapMesh *mesh) {
  250. PackNode *copyNode = cNode->clone();
  251. for(int n=0; n < mesh->faces.size(); n++) {
  252. PackNode *pNode = copyNode->Insert(mesh->faces[n]);
  253. if(pNode != NULL) {
  254. pNode->face = mesh->faces[n];
  255. } else {
  256. delete copyNode;
  257. return false;
  258. }
  259. }
  260. delete copyNode;
  261. return true;
  262. }
  263. void LightmapPacker::buildTextures() {
  264. generateNewImage();
  265. // TODO: sort meshes by size
  266. for(int m=0; m < lightmapMeshes.size(); m++) {
  267. if(hasRoomForMesh(lightmapMeshes[m])) {
  268. Logger::log("packing mesh %d\n", m);
  269. packMesh(lightmapMeshes[m]);
  270. } else {
  271. Logger::log("mesh %d doesnt fit, generating new image and packing\n", m);
  272. generateNewImage();
  273. packMesh(lightmapMeshes[m]);
  274. }
  275. }
  276. }
  277. void LightmapPacker::generateTextures(int resolution, int quality) {
  278. lightMapRes = resolution;
  279. lightMapQuality = quality;
  280. unwrapScene();
  281. buildTextures();
  282. }
  283. void LightmapPacker::bindTextures() {
  284. // create textures and bind them for preview
  285. for(int i=0; i < images.size(); i++) {
  286. images[i]->fastBlur(1);
  287. Texture* newTex = CoreServices::getInstance()->getMaterialManager()->createTextureFromImage(images[i]);
  288. textures.push_back(newTex);
  289. }
  290. for(int i=0; i < targetScene->getNumStaticGeometry(); i++) {
  291. Material *meshMaterial = targetScene->getStaticGeometry(i)->getMaterial();
  292. if(meshMaterial) {
  293. targetScene->getStaticGeometry(i)->getLocalShaderOptions()->addTexture("diffuse2", textures[targetScene->getStaticGeometry(i)->lightmapIndex]);
  294. }
  295. }
  296. /* old way
  297. for(int i=0; i < lightmapMeshes.size(); i++) {
  298. Material *meshMaterial = lightmapMeshes[i]->mesh->getMaterial();
  299. if(meshMaterial) {
  300. lightmapMeshes[i]->mesh->getLocalShaderOptions()->addTexture("diffuse2", textures[lightmapMeshes[i]->imageID]);
  301. }
  302. }
  303. */
  304. }
  305. void LightmapPacker::saveLightmaps(string folder) {
  306. for(int i=0; i < images.size(); i++) {
  307. std::ostringstream fileName;
  308. fileName << folder << "/" << "lm" << i << ".bmp";
  309. images[i]->writeBMP(fileName.str());
  310. }
  311. }
  312. void PackNode::createRoot(int res) {
  313. rc.w = res-4;
  314. rc.h = res-4;
  315. rootRes = res-4;
  316. rc.x = 1;
  317. rc.y = 1;
  318. }
  319. PackNode *PackNode::clone() {
  320. PackNode *cloneNode = new PackNode();
  321. cloneNode->rc.x = rc.x;
  322. cloneNode->rc.y = rc.y;
  323. cloneNode->rc.w = rc.w;
  324. cloneNode->rc.h = rc.h;
  325. cloneNode->face = face;
  326. if(child[0]) {
  327. cloneNode->child[0] = child[0]->clone();
  328. }
  329. if(child[1]) {
  330. cloneNode->child[1] = child[1]->clone();
  331. }
  332. return cloneNode;
  333. }
  334. PackNode *PackNode::Insert(LightmapFace *img) {
  335. PackNode *newNode;
  336. if(child[0]) {
  337. newNode = child[0]->Insert(img);
  338. if(newNode != NULL)
  339. return newNode;
  340. return child[1]->Insert(img);
  341. } else {
  342. if(face != NULL)
  343. return NULL;
  344. //(if we're too small, return)
  345. if(img->pixelArea.w > rc.w || img->pixelArea.h > rc.h)
  346. return NULL;
  347. if(img->pixelArea.w == rc.w && img->pixelArea.h == rc.h)
  348. return this;
  349. child[0] = new PackNode();
  350. child[1] = new PackNode();
  351. float dw = rc.w - img->pixelArea.w;
  352. float dh = rc.h - img->pixelArea.h;
  353. if(dw > dh) {
  354. child[0]->rc = Rectangle(rc.x, rc.y, img->pixelArea.w, rc.h);
  355. child[1]->rc = Rectangle(rc.x+img->pixelArea.w+4, rc.y, rc.w-img->pixelArea.w-3, rc.h);
  356. } else {
  357. child[0]->rc = Rectangle(rc.x, rc.y, rc.w, img->pixelArea.h);
  358. child[1]->rc = Rectangle(rc.x, rc.y+img->pixelArea.h+4, rc.w, rc.h-img->pixelArea.h-3);
  359. }
  360. return child[0]->Insert(img);
  361. }
  362. }