mesh_resource.cpp 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221
  1. /*
  2. * Copyright (c) 2012-2014 Daniele Bartolini and individual contributors.
  3. * License: https://github.com/taylor001/crown/blob/master/LICENSE
  4. */
  5. #include "dynamic_string.h"
  6. #include "filesystem.h"
  7. #include "json_parser.h"
  8. #include "log.h"
  9. #include "mesh_resource.h"
  10. #include "temp_allocator.h"
  11. #include "vector3.h"
  12. #include "resource_manager.h"
  13. #include "compile_options.h"
  14. namespace crown
  15. {
  16. namespace mesh_resource
  17. {
  18. struct MeshVertex
  19. {
  20. Vector3 position;
  21. Vector3 normal;
  22. Vector2 texcoord;
  23. bool operator==(const MeshVertex& other)
  24. {
  25. return position == other.position &&
  26. normal == other.normal &&
  27. texcoord == other.texcoord;
  28. }
  29. };
  30. void compile(const char* path, CompileOptions& opts)
  31. {
  32. static const uint32_t VERSION = 1;
  33. Buffer buf = opts.read(path);
  34. JSONParser json(array::begin(buf));
  35. JSONElement root = json.root();
  36. // Read data arrays
  37. JSONElement position = root.key_or_nil("position");
  38. CE_ASSERT(!position.is_nil(), "Bad mesh: array 'position' not found.");
  39. JSONElement normal = root.key_or_nil("normal");
  40. JSONElement texcoord = root.key_or_nil("texcoord");
  41. Array<float> positions(default_allocator());
  42. Array<float> normals(default_allocator());
  43. Array<float> texcoords(default_allocator());
  44. position.to_array(positions);
  45. bool has_normal = false;
  46. bool has_texcoord = false;
  47. if (!normal.is_nil())
  48. {
  49. has_normal = true;
  50. normal.to_array(normals);
  51. }
  52. if (!texcoord.is_nil())
  53. {
  54. has_texcoord = true;
  55. texcoord.to_array(texcoords);
  56. }
  57. // Read index arrays
  58. JSONElement index = root.key("index");
  59. Array<uint16_t> position_index(default_allocator());
  60. Array<uint16_t> normal_index(default_allocator());
  61. Array<uint16_t> texcoord_index(default_allocator());
  62. int ii = 0;
  63. index[ii].to_array(position_index);
  64. ++ii;
  65. if (has_normal)
  66. {
  67. index[ii].to_array(normal_index);
  68. ++ii;
  69. }
  70. if (has_texcoord)
  71. {
  72. index[ii].to_array(texcoord_index);
  73. ++ii;
  74. }
  75. Array<MeshVertex> vertices(default_allocator());
  76. Array<uint16_t> indices(default_allocator());
  77. // Generate vb/ib
  78. uint32_t idx = 0;
  79. for (uint32_t i = 0; i < array::size(position_index); i++)
  80. {
  81. MeshVertex v;
  82. uint16_t p_idx = position_index[i] * 3;
  83. v.position = Vector3(positions[p_idx], positions[p_idx + 1], positions[p_idx + 2]);
  84. if (has_normal)
  85. {
  86. uint16_t n_idx = normal_index[i] * 3;
  87. v.normal = Vector3(normals[n_idx], normals[n_idx + 1], normals[n_idx + 2]);
  88. }
  89. if (has_texcoord)
  90. {
  91. uint16_t t_idx = texcoord_index[i] * 2;
  92. v.texcoord = Vector2(texcoords[t_idx], texcoords[t_idx + 1]);
  93. }
  94. uint32_t f_idx = 0;
  95. bool found = false;
  96. for (; f_idx < array::size(vertices); f_idx++)
  97. {
  98. if (vertices[f_idx] == v)
  99. {
  100. found = true;
  101. break;
  102. }
  103. }
  104. if (found)
  105. {
  106. array::push_back(indices, (uint16_t) f_idx);
  107. }
  108. else
  109. {
  110. array::push_back(vertices, v);
  111. array::push_back(indices, (uint16_t) idx);
  112. idx++;
  113. }
  114. }
  115. bgfx::VertexDecl decl;
  116. decl.begin();
  117. decl.add(bgfx::Attrib::Position, 3, bgfx::AttribType::Float);
  118. if (has_normal)
  119. decl.add(bgfx::Attrib::Normal, 3, bgfx::AttribType::Float, false);
  120. if (has_texcoord)
  121. decl.add(bgfx::Attrib::TexCoord0, 2, bgfx::AttribType::Float);
  122. decl.end();
  123. // Write
  124. opts.write(VERSION);
  125. opts.write(decl);
  126. opts.write(array::size(vertices));
  127. for (uint32_t i = 0; i < array::size(vertices); ++i)
  128. {
  129. opts.write(vertices[i].position);
  130. if (has_normal)
  131. opts.write(vertices[i].normal);
  132. if (has_texcoord)
  133. opts.write(vertices[i].texcoord);
  134. }
  135. opts.write(array::size(indices));
  136. for (uint32_t i = 0; i < array::size(indices); ++i)
  137. {
  138. opts.write(indices[i]);
  139. }
  140. }
  141. void* load(File& file, Allocator& a)
  142. {
  143. BinaryReader br(file);
  144. uint32_t version;
  145. br.read(version);
  146. bgfx::VertexDecl decl;
  147. br.read(decl);
  148. uint32_t num_verts;
  149. br.read(num_verts);
  150. const bgfx::Memory* vbmem = bgfx::alloc(num_verts * decl.getStride());
  151. br.read(vbmem->data, num_verts * decl.getStride());
  152. uint32_t num_inds;
  153. br.read(num_inds);
  154. const bgfx::Memory* ibmem = bgfx::alloc(num_inds * sizeof(uint16_t));
  155. br.read(ibmem->data, num_inds * sizeof(uint16_t));
  156. MeshResource* mr = (MeshResource*)a.allocate(sizeof(MeshResource));
  157. mr->decl = decl;
  158. mr->vbmem = vbmem;
  159. mr->ibmem = ibmem;
  160. return mr;
  161. }
  162. void online(StringId64 id, ResourceManager& rm)
  163. {
  164. MeshResource* mr = (MeshResource*)rm.get(MESH_TYPE, id);
  165. mr->vb = bgfx::createVertexBuffer(mr->vbmem, mr->decl);
  166. mr->ib = bgfx::createIndexBuffer(mr->ibmem);
  167. }
  168. void offline(StringId64 id, ResourceManager& rm)
  169. {
  170. MeshResource* mr = (MeshResource*)rm.get(MESH_TYPE, id);
  171. bgfx::destroyVertexBuffer(mr->vb);
  172. bgfx::destroyIndexBuffer(mr->ib);
  173. }
  174. void unload(Allocator& a, void* res)
  175. {
  176. a.deallocate(res);
  177. }
  178. } // namespace mesh_resource
  179. } // namespace crown