mesh.cpp 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274
  1. /*
  2. * Copyright (c) 2012-2025 Daniele Bartolini et al.
  3. * SPDX-License-Identifier: MIT
  4. */
  5. #include "config.h"
  6. #if CROWN_CAN_COMPILE
  7. # include "core/containers/array.inl"
  8. # include "core/containers/vector.inl"
  9. # include "core/filesystem/filesystem.h"
  10. # include "core/json/json_object.inl"
  11. # include "core/json/sjson.h"
  12. # include "core/math/aabb.inl"
  13. # include "core/math/constants.h"
  14. # include "core/math/matrix4x4.inl"
  15. # include "core/math/vector2.inl"
  16. # include "core/math/vector3.inl"
  17. # include "core/memory/temp_allocator.inl"
  18. # include "core/strings/dynamic_string.inl"
  19. # include "resource/compile_options.inl"
  20. # include "resource/mesh.h"
  21. # include "resource/mesh_resource.h"
  22. # include <bx/error.h>
  23. # include <bx/readerwriter.h>
  24. # include <vertexlayout.h> // bgfx::write, bgfx::read
  25. namespace crown
  26. {
  27. namespace mesh
  28. {
  29. /// Writer interface.
  30. struct BgfxWriter : public bx::WriterI
  31. {
  32. BinaryWriter *_bw;
  33. ///
  34. explicit BgfxWriter(BinaryWriter &bw)
  35. : _bw(&bw)
  36. {
  37. }
  38. ///
  39. virtual ~BgfxWriter()
  40. {
  41. }
  42. ///
  43. virtual int32_t write(const void *_data, int32_t _size, bx::Error *_err)
  44. {
  45. CE_UNUSED(_err);
  46. _bw->write(_data, _size);
  47. return _size; // FIXME: return the actual number of bytes written
  48. }
  49. };
  50. static void reset(Geometry &g)
  51. {
  52. array::clear(g._positions);
  53. array::clear(g._normals);
  54. array::clear(g._uvs);
  55. array::clear(g._tangents);
  56. array::clear(g._bitangents);
  57. array::clear(g._position_indices);
  58. array::clear(g._normal_indices);
  59. array::clear(g._uv_indices);
  60. array::clear(g._tangent_indices);
  61. array::clear(g._bitangent_indices);
  62. array::clear(g._vertex_buffer);
  63. array::clear(g._index_buffer);
  64. }
  65. bool has_normals(Geometry &g)
  66. {
  67. return array::size(g._normals) != 0;
  68. }
  69. bool has_uvs(Geometry &g)
  70. {
  71. return array::size(g._uvs) != 0;
  72. }
  73. bool has_tangents(Geometry &g)
  74. {
  75. return array::size(g._tangents) != 0;
  76. }
  77. bool has_bitangents(Geometry &g)
  78. {
  79. return array::size(g._bitangents) != 0;
  80. }
  81. static u32 vertex_stride(Geometry &g)
  82. {
  83. u32 stride = 0;
  84. stride += 3 * sizeof(f32);
  85. stride += (has_normals(g) ? 3 * sizeof(f32) : 0);
  86. stride += (has_uvs(g) ? 2 * sizeof(f32) : 0);
  87. return stride;
  88. }
  89. static bgfx::VertexLayout vertex_layout(Geometry &g)
  90. {
  91. bgfx::VertexLayout layout;
  92. memset((void *)&layout, 0, sizeof(layout));
  93. layout.begin();
  94. layout.add(bgfx::Attrib::Position, 3, bgfx::AttribType::Float);
  95. if (has_normals(g)) {
  96. layout.add(bgfx::Attrib::Normal, 3, bgfx::AttribType::Float, true);
  97. }
  98. if (has_uvs(g)) {
  99. layout.add(bgfx::Attrib::TexCoord0, 2, bgfx::AttribType::Float);
  100. }
  101. layout.end();
  102. return layout;
  103. }
  104. static void generate_vertex_and_index_buffers(Geometry &g)
  105. {
  106. array::resize(g._index_buffer, array::size(g._position_indices));
  107. u16 index = 0;
  108. for (u32 i = 0; i < array::size(g._position_indices); ++i) {
  109. g._index_buffer[i] = index++;
  110. const u16 p_idx = g._position_indices[i] * 3;
  111. Vector3 xyz;
  112. xyz.x = g._positions[p_idx + 0];
  113. xyz.y = g._positions[p_idx + 1];
  114. xyz.z = g._positions[p_idx + 2];
  115. array::push(g._vertex_buffer, (char *)&xyz, sizeof(xyz));
  116. if (has_normals(g)) {
  117. const u16 n_idx = g._normal_indices[i] * 3;
  118. Vector3 n;
  119. n.x = g._normals[n_idx + 0];
  120. n.y = g._normals[n_idx + 1];
  121. n.z = g._normals[n_idx + 2];
  122. array::push(g._vertex_buffer, (char *)&n, sizeof(n));
  123. }
  124. if (has_uvs(g)) {
  125. const u16 t_idx = g._uv_indices[i] * 2;
  126. Vector2 uv;
  127. uv.x = g._uvs[t_idx + 0];
  128. uv.y = g._uvs[t_idx + 1];
  129. array::push(g._vertex_buffer, (char *)&uv, sizeof(uv));
  130. }
  131. }
  132. }
  133. static void geometry_names(Vector<DynamicString> &names, const Mesh &m, const DynamicString &geometry)
  134. {
  135. auto cur = hash_map::begin(m._nodes);
  136. auto end = hash_map::end(m._nodes);
  137. for (; cur != end; ++cur) {
  138. HASH_MAP_SKIP_HOLE(m._nodes, cur);
  139. if (cur->second._geometry == geometry)
  140. vector::push_back(names, cur->first);
  141. }
  142. }
  143. static OBB obb(Geometry &g)
  144. {
  145. AABB aabb;
  146. OBB obb;
  147. aabb::reset(aabb);
  148. memset(&obb, 0, sizeof(obb));
  149. aabb::from_points(aabb
  150. , array::size(g._positions) / 3
  151. , sizeof(g._positions[0]) * 3
  152. , array::begin(g._positions)
  153. );
  154. obb.tm = from_quaternion_translation(QUATERNION_IDENTITY, aabb::center(aabb));
  155. obb.half_extents = (aabb.max - aabb.min) * 0.5f;
  156. return obb;
  157. }
  158. s32 write(Mesh &m, CompileOptions &opts)
  159. {
  160. opts.write(RESOURCE_HEADER(RESOURCE_VERSION_MESH));
  161. opts.write(hash_map::size(m._geometries));
  162. auto cur = hash_map::begin(m._geometries);
  163. auto end = hash_map::end(m._geometries);
  164. for (; cur != end; ++cur) {
  165. HASH_MAP_SKIP_HOLE(m._geometries, cur);
  166. Vector<DynamicString> geo_names(default_allocator());
  167. geometry_names(geo_names, m, cur->first);
  168. u32 num_geo_names = vector::size(geo_names);
  169. opts.write(num_geo_names);
  170. for (u32 i = 0; i < num_geo_names; ++i)
  171. opts.write(geo_names[i].to_string_id()._id);
  172. Geometry *geo = (Geometry *)&cur->second;
  173. mesh::generate_vertex_and_index_buffers(*geo);
  174. bgfx::VertexLayout layout = mesh::vertex_layout(*geo);
  175. u32 stride = mesh::vertex_stride(*geo);
  176. OBB bbox = mesh::obb(*geo);
  177. BgfxWriter writer(opts._binary_writer);
  178. bgfx::write(&writer, layout);
  179. opts.write(bbox);
  180. opts.write(array::size(geo->_vertex_buffer) / stride);
  181. opts.write(stride);
  182. opts.write(array::size(geo->_index_buffer));
  183. opts.write(geo->_vertex_buffer);
  184. opts.write(array::begin(geo->_index_buffer), array::size(geo->_index_buffer) * sizeof(u16));
  185. }
  186. return 0;
  187. }
  188. s32 parse(Mesh &m, CompileOptions &opts, const char *path)
  189. {
  190. if (str_has_suffix(path, ".mesh")) {
  191. Buffer buf = opts.read(path);
  192. return mesh::parse(m, buf, opts);
  193. } else {
  194. TempAllocator512 ta;
  195. DynamicString str(ta);
  196. str = path;
  197. str += ".mesh";
  198. Buffer buf = opts.read(str.c_str());
  199. return mesh::parse(m, buf, opts);
  200. }
  201. }
  202. } // namespace mesh
  203. Node::Node(Allocator &a)
  204. : _local_pose(MATRIX4X4_IDENTITY)
  205. , _geometry(a)
  206. {
  207. }
  208. Geometry::Geometry(Allocator &a)
  209. : _positions(a)
  210. , _normals(a)
  211. , _uvs(a)
  212. , _tangents(a)
  213. , _bitangents(a)
  214. , _position_indices(a)
  215. , _normal_indices(a)
  216. , _uv_indices(a)
  217. , _tangent_indices(a)
  218. , _bitangent_indices(a)
  219. , _vertex_buffer(a)
  220. , _index_buffer(a)
  221. {
  222. mesh::reset(*this);
  223. }
  224. Mesh::Mesh(Allocator &a)
  225. : _geometries(a)
  226. , _nodes(a)
  227. {
  228. }
  229. } // namespace crown
  230. #endif // if CROWN_CAN_COMPILE