MeshLightmapUVGen.cpp 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314
  1. #include <ThirdParty/thekla/thekla_atlas.h>
  2. #include <Atomic/IO/Log.h>
  3. #include "ModelPacker.h"
  4. #include "MeshLightmapUVGen.h"
  5. namespace AtomicGlow
  6. {
  7. MeshLightmapUVGen::MeshLightmapUVGen(Context* context, Model* model, const Settings& settings) : Object(context),
  8. model_(model),
  9. modelPacker_(new ModelPacker(context)),
  10. settings_(settings),
  11. tOutputMesh_(0),
  12. tInputMesh_(0)
  13. {
  14. }
  15. MeshLightmapUVGen::~MeshLightmapUVGen()
  16. {
  17. }
  18. inline void MeshLightmapUVGen::EmitVertex(PODVector<MPVertex>& vertices, unsigned& index, const MPVertex& vertex)
  19. {
  20. index = 0;
  21. for (unsigned i = 0; i < vertices.Size(); i++)
  22. {
  23. if (vertices[i] == vertex)
  24. {
  25. index = i;
  26. return;
  27. }
  28. }
  29. index = vertices.Size();
  30. vertices.Push(vertex);
  31. }
  32. void MeshLightmapUVGen::WriteLightmapUVCoords()
  33. {
  34. //Thekla::atlas_write_debug_textures(tOutputMesh_, tInputMesh_, ToString("/Users/jenge/Desktop/%s_lmWorldSpaceTexture.png", modelName.CString()).CString() ,
  35. // ToString("/Users/jenge/Desktop/%s_lmNormalTexture.png", modelName.CString()).CString() );
  36. Vector<PODVector<MPVertex>> geoVerts;
  37. Vector<PODVector<unsigned>> geoIndices;
  38. geoVerts.Resize(curLOD_->mpGeometry_.Size());
  39. geoIndices.Resize(curLOD_->mpGeometry_.Size());
  40. float uscale = 1.f / tOutputMesh_->atlas_width;
  41. float vscale = 1.f / tOutputMesh_->atlas_height;
  42. for (unsigned i = 0; i < tOutputMesh_->index_count/3; i++)
  43. {
  44. unsigned v0 = (unsigned) tOutputMesh_->index_array[i * 3];
  45. unsigned v1 = (unsigned) tOutputMesh_->index_array[i * 3 + 1];
  46. unsigned v2 = (unsigned) tOutputMesh_->index_array[i * 3 + 2];
  47. Thekla::Atlas_Output_Vertex& tv0 = tOutputMesh_->vertex_array[v0];
  48. Thekla::Atlas_Output_Vertex& tv1 = tOutputMesh_->vertex_array[v1];
  49. Thekla::Atlas_Output_Vertex& tv2 = tOutputMesh_->vertex_array[v2];
  50. LMVertex& lv0 = lmVertices_[tv0.xref];
  51. LMVertex& lv1 = lmVertices_[tv1.xref];
  52. LMVertex& lv2 = lmVertices_[tv2.xref];
  53. unsigned geometryIdx = lv0.geometryIdx_;
  54. // check for mixed geometry in triangle
  55. if (geometryIdx != lv1.geometryIdx_ || geometryIdx != lv2.geometryIdx_)
  56. {
  57. assert(0);
  58. }
  59. MPGeometry* mpGeo = curLOD_->mpGeometry_[geometryIdx];
  60. PODVector<MPVertex>& verts = geoVerts[geometryIdx];
  61. PODVector<unsigned>& indices = geoIndices[geometryIdx];
  62. unsigned ovindices[3];
  63. Vector2 uvs[3];
  64. uvs[0] = Vector2(tv0.uv[0], tv0.uv[1]);
  65. uvs[1] = Vector2(tv1.uv[0], tv1.uv[1]);
  66. uvs[2] = Vector2(tv2.uv[0], tv2.uv[1]);
  67. ovindices[0] = lv0.originalVertex_;
  68. ovindices[1] = lv1.originalVertex_;
  69. ovindices[2] = lv2.originalVertex_;
  70. Vector2 center(uvs[0]);
  71. center += uvs[1];
  72. center += uvs[2];
  73. center /= 3.0f;
  74. unsigned index;
  75. for (unsigned j = 0; j < 3; j++)
  76. {
  77. Vector2 uv = uvs[j];
  78. /*
  79. uv -= center;
  80. uv *= 0.98f;
  81. uv += center;
  82. uv.x_ = Clamp<float>(uv.x_, 2, tOutputMesh_->atlas_width - 2);
  83. uv.y_ = Clamp<float>(uv.y_, 2, tOutputMesh_->atlas_height - 2);
  84. */
  85. uv.x_ *= uscale;
  86. uv.y_ *= vscale;
  87. MPVertex mpv = mpGeo->vertices_[ovindices[j]];
  88. mpv.uv1_ = uv;
  89. EmitVertex(verts, index, mpv);
  90. indices.Push(index);
  91. }
  92. }
  93. for (unsigned i = 0; i < curLOD_->mpGeometry_.Size(); i++)
  94. {
  95. MPGeometry* mpGeo = curLOD_->mpGeometry_[i];
  96. mpGeo->vertices_ = geoVerts[i];
  97. mpGeo->indices_ = new unsigned[geoIndices[i].Size()];
  98. memcpy(&mpGeo->indices_[0], &geoIndices[i][0], sizeof(unsigned) * geoIndices[i].Size());
  99. mpGeo->numIndices_ = geoIndices[i].Size();
  100. // Check whether we need to add UV1 semantic
  101. PODVector<VertexElement> nElements;
  102. unsigned texCoordCount = 0;
  103. for (unsigned j = 0; j < mpGeo->elements_.Size(); j++)
  104. {
  105. VertexElement element = mpGeo->elements_[j];
  106. if (element.type_ == TYPE_VECTOR2 && element.semantic_ == SEM_TEXCOORD)
  107. texCoordCount++;
  108. }
  109. if (texCoordCount == 0)
  110. {
  111. // We don't have a valid UV set in UV0
  112. // FIX ME: This doesn't currently work
  113. mpGeo->elements_.Push(VertexElement(TYPE_VECTOR2, SEM_TEXCOORD, 0));
  114. mpGeo->elements_.Push(VertexElement(TYPE_VECTOR2, SEM_TEXCOORD, 1));
  115. }
  116. else if (texCoordCount == 1)
  117. {
  118. bool added = false;
  119. for (unsigned j = 0; j < mpGeo->elements_.Size(); j++)
  120. {
  121. VertexElement element = mpGeo->elements_[j];
  122. nElements.Push(element);
  123. if ( (element.type_ == TYPE_VECTOR2 && element.semantic_ == SEM_TEXCOORD) || (!added && j == (mpGeo->elements_.Size() - 1) ) )
  124. {
  125. added = true;
  126. VertexElement element(TYPE_VECTOR2, SEM_TEXCOORD, 1);
  127. nElements.Push(element);
  128. }
  129. }
  130. mpGeo->elements_ = nElements;
  131. }
  132. }
  133. }
  134. bool MeshLightmapUVGen::Generate()
  135. {
  136. if (model_.Null())
  137. return false;
  138. if (!modelPacker_->Unpack(model_))
  139. {
  140. return false;
  141. }
  142. for (unsigned i = 0; i < modelPacker_->lodLevels_.Size(); i++)
  143. {
  144. curLOD_ = modelPacker_->lodLevels_[i];
  145. // combine all LOD vertices/indices
  146. unsigned totalVertices = 0;
  147. unsigned totalIndices = 0;
  148. for (unsigned j = 0; j < curLOD_->mpGeometry_.Size(); j++)
  149. {
  150. MPGeometry* geo = curLOD_->mpGeometry_[j];
  151. totalVertices += geo->vertices_.Size();
  152. totalIndices += geo->numIndices_;
  153. }
  154. // Setup thekla input mesh
  155. tInputMesh_ = new Thekla::Atlas_Input_Mesh();
  156. // Allocate vertex arrays
  157. lmVertices_ = new LMVertex[totalVertices];
  158. tInputMesh_->vertex_count = totalVertices;
  159. tInputMesh_->vertex_array = new Thekla::Atlas_Input_Vertex[tInputMesh_->vertex_count];
  160. tInputMesh_->face_count = totalIndices / 3;
  161. tInputMesh_->face_array = new Thekla::Atlas_Input_Face[tInputMesh_->face_count];
  162. unsigned vCount = 0;
  163. unsigned fCount = 0;
  164. for (unsigned j = 0; j < curLOD_->mpGeometry_.Size(); j++)
  165. {
  166. MPGeometry* geo = curLOD_->mpGeometry_[j];
  167. unsigned vertexStart = vCount;
  168. for (unsigned k = 0; k < geo->vertices_.Size(); k++, vCount++)
  169. {
  170. const MPVertex& mpv = geo->vertices_[k];
  171. LMVertex& lmv = lmVertices_[vCount];
  172. Thekla::Atlas_Input_Vertex& tv = tInputMesh_->vertex_array[vCount];
  173. lmv.geometry_ = geo;
  174. lmv.geometryIdx_ = j;
  175. lmv.originalVertex_ = k;
  176. tv.position[0] = mpv.position_.x_;
  177. tv.position[1] = mpv.position_.y_;
  178. tv.position[2] = mpv.position_.z_;
  179. tv.normal[0] = mpv.normal_.x_;
  180. tv.normal[1] = mpv.normal_.y_;
  181. tv.normal[2] = mpv.normal_.z_;
  182. tv.uv[0] = mpv.uv0_.x_;
  183. tv.uv[1] = mpv.uv0_.y_;
  184. // this appears unused in thekla atlas?
  185. tv.first_colocal = vCount;
  186. }
  187. for (unsigned k = 0; k < geo->numIndices_/3; k++, fCount++)
  188. {
  189. Thekla::Atlas_Input_Face& tface = tInputMesh_->face_array[fCount];
  190. tface.vertex_index[0] = (int) (geo->indices_[k * 3] + vertexStart);
  191. tface.vertex_index[1] = (int) (geo->indices_[k * 3 + 1] + vertexStart);
  192. tface.vertex_index[2] = (int) (geo->indices_[k * 3 + 2] + vertexStart);
  193. if (tface.vertex_index[0] > totalVertices || tface.vertex_index[1] > totalVertices || tface.vertex_index[2] > totalVertices)
  194. {
  195. ATOMIC_LOGERROR("Vertex overflow");
  196. return false;
  197. }
  198. tface.material_index = j;
  199. }
  200. }
  201. Thekla::Atlas_Options atlasOptions;
  202. atlas_set_default_options(&atlasOptions);
  203. // disable brute force packing quality, as it has a number of notes about performance
  204. // and it is turned off in Thekla example in repo as well. I am also seeing some meshes
  205. // having problems packing with it and hanging on import
  206. atlasOptions.packer_options.witness.packing_quality = 1;
  207. atlasOptions.packer_options.witness.texel_area = 8;
  208. atlasOptions.packer_options.witness.conservative = true;
  209. Thekla::Atlas_Error error = Thekla::Atlas_Error_Success;
  210. tOutputMesh_ = atlas_generate(tInputMesh_, &atlasOptions, &error);
  211. if (tOutputMesh_)
  212. {
  213. WriteLightmapUVCoords();
  214. }
  215. delete [] tInputMesh_->vertex_array;
  216. delete [] tInputMesh_->face_array;
  217. delete tInputMesh_;
  218. tInputMesh_ = 0;
  219. atlas_free(tOutputMesh_);
  220. tOutputMesh_ = 0;
  221. }
  222. // update model
  223. modelPacker_->Pack();
  224. return true;
  225. }
  226. }