mesh.cpp 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326
  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_fbx.h"
  22. # include "resource/mesh_resource.h"
  23. # include <bx/error.h>
  24. # include <bx/readerwriter.h>
  25. # include <vertexlayout.h> // bgfx::write, bgfx::read
  26. namespace crown
  27. {
  28. namespace mesh
  29. {
  30. /// Writer interface.
  31. struct BgfxWriter : public bx::WriterI
  32. {
  33. BinaryWriter *_bw;
  34. ///
  35. explicit BgfxWriter(BinaryWriter &bw)
  36. : _bw(&bw)
  37. {
  38. }
  39. ///
  40. virtual ~BgfxWriter()
  41. {
  42. }
  43. ///
  44. virtual int32_t write(const void *_data, int32_t _size, bx::Error *_err)
  45. {
  46. CE_UNUSED(_err);
  47. _bw->write(_data, _size);
  48. return _size; // FIXME: return the actual number of bytes written
  49. }
  50. };
  51. static void reset(Geometry &g)
  52. {
  53. array::clear(g._positions);
  54. array::clear(g._normals);
  55. array::clear(g._uvs);
  56. array::clear(g._tangents);
  57. array::clear(g._bitangents);
  58. array::clear(g._bones);
  59. array::clear(g._weights);
  60. array::clear(g._position_indices);
  61. array::clear(g._normal_indices);
  62. array::clear(g._uv_indices);
  63. array::clear(g._tangent_indices);
  64. array::clear(g._bitangent_indices);
  65. array::clear(g._vertex_buffer);
  66. array::clear(g._index_buffer);
  67. }
  68. bool has_normals(Geometry &g)
  69. {
  70. return array::size(g._normals) != 0;
  71. }
  72. bool has_uvs(Geometry &g)
  73. {
  74. return array::size(g._uvs) != 0;
  75. }
  76. bool has_tangents(Geometry &g)
  77. {
  78. return array::size(g._tangents) != 0;
  79. }
  80. bool has_bitangents(Geometry &g)
  81. {
  82. return array::size(g._bitangents) != 0;
  83. }
  84. bool has_bones(Geometry &g)
  85. {
  86. return array::size(g._bones) != 0;
  87. }
  88. static u32 vertex_stride(Geometry &g)
  89. {
  90. u32 stride = 0;
  91. stride += 3 * sizeof(f32);
  92. stride += (has_normals(g) ? 3 * sizeof(f32) : 0);
  93. stride += (has_uvs(g) ? 2 * sizeof(f32) : 0);
  94. stride += (has_bones(g) ? 8 * sizeof(f32) : 0);
  95. return stride;
  96. }
  97. static bgfx::VertexLayout vertex_layout(Geometry &g)
  98. {
  99. bgfx::VertexLayout layout;
  100. memset((void *)&layout, 0, sizeof(layout));
  101. layout.begin();
  102. layout.add(bgfx::Attrib::Position, 3, bgfx::AttribType::Float);
  103. if (has_normals(g)) {
  104. layout.add(bgfx::Attrib::Normal, 3, bgfx::AttribType::Float, true);
  105. }
  106. if (has_uvs(g)) {
  107. layout.add(bgfx::Attrib::TexCoord0, 2, bgfx::AttribType::Float);
  108. }
  109. if (has_bones(g)) {
  110. layout.add(bgfx::Attrib::Indices, 4, bgfx::AttribType::Float);
  111. layout.add(bgfx::Attrib::Weight, 4, bgfx::AttribType::Float);
  112. }
  113. layout.end();
  114. return layout;
  115. }
  116. static void generate_vertex_and_index_buffers(Geometry &g)
  117. {
  118. array::resize(g._index_buffer, array::size(g._position_indices));
  119. u16 index = 0;
  120. for (u32 i = 0; i < array::size(g._position_indices); ++i) {
  121. g._index_buffer[i] = index++;
  122. const u16 p_idx = g._position_indices[i] * 3;
  123. Vector3 xyz;
  124. xyz.x = g._positions[p_idx + 0];
  125. xyz.y = g._positions[p_idx + 1];
  126. xyz.z = g._positions[p_idx + 2];
  127. array::push(g._vertex_buffer, (char *)&xyz, sizeof(xyz));
  128. if (has_normals(g)) {
  129. const u16 n_idx = g._normal_indices[i] * 3;
  130. Vector3 n;
  131. n.x = g._normals[n_idx + 0];
  132. n.y = g._normals[n_idx + 1];
  133. n.z = g._normals[n_idx + 2];
  134. array::push(g._vertex_buffer, (char *)&n, sizeof(n));
  135. }
  136. if (has_uvs(g)) {
  137. const u16 t_idx = g._uv_indices[i] * 2;
  138. Vector2 uv;
  139. uv.x = g._uvs[t_idx + 0];
  140. uv.y = g._uvs[t_idx + 1];
  141. array::push(g._vertex_buffer, (char *)&uv, sizeof(uv));
  142. }
  143. if (has_bones(g)) {
  144. const u16 b_idx = g._bone_indices[i] * 4;
  145. Vector4 b;
  146. b.x = g._bones[b_idx + 0];
  147. b.y = g._bones[b_idx + 1];
  148. b.z = g._bones[b_idx + 2];
  149. b.w = g._bones[b_idx + 3];
  150. array::push(g._vertex_buffer, (char *)&b, sizeof(b));
  151. Vector4 w;
  152. const u16 w_idx = g._weight_indices[i] * 4;
  153. w.x = g._weights[w_idx + 0];
  154. w.y = g._weights[w_idx + 1];
  155. w.z = g._weights[w_idx + 2];
  156. w.w = g._weights[w_idx + 3];
  157. array::push(g._vertex_buffer, (char *)&w, sizeof(w));
  158. }
  159. }
  160. }
  161. static void geometry_names(Vector<DynamicString> &names, const Mesh &m, const DynamicString &geometry)
  162. {
  163. auto cur = hash_map::begin(m._nodes);
  164. auto end = hash_map::end(m._nodes);
  165. for (; cur != end; ++cur) {
  166. HASH_MAP_SKIP_HOLE(m._nodes, cur);
  167. if (cur->second._geometry == geometry)
  168. vector::push_back(names, cur->first);
  169. }
  170. }
  171. static OBB obb(Geometry &g)
  172. {
  173. AABB aabb;
  174. OBB obb;
  175. aabb::reset(aabb);
  176. memset(&obb, 0, sizeof(obb));
  177. if (array::size(g._positions) != 0) {
  178. aabb::from_points(aabb
  179. , array::size(g._positions) / 3
  180. , sizeof(g._positions[0]) * 3
  181. , array::begin(g._positions)
  182. );
  183. }
  184. obb.tm = from_quaternion_translation(QUATERNION_IDENTITY, aabb::center(aabb));
  185. obb.half_extents = (aabb.max - aabb.min) * 0.5f;
  186. return obb;
  187. }
  188. s32 write(Mesh &m, CompileOptions &opts)
  189. {
  190. opts.write(RESOURCE_HEADER(RESOURCE_VERSION_MESH));
  191. opts.write(hash_map::size(m._geometries));
  192. auto cur = hash_map::begin(m._geometries);
  193. auto end = hash_map::end(m._geometries);
  194. for (; cur != end; ++cur) {
  195. HASH_MAP_SKIP_HOLE(m._geometries, cur);
  196. Vector<DynamicString> geo_names(default_allocator());
  197. geometry_names(geo_names, m, cur->first);
  198. u32 num_geo_names = vector::size(geo_names);
  199. opts.write(num_geo_names);
  200. for (u32 i = 0; i < num_geo_names; ++i)
  201. opts.write(geo_names[i].to_string_id()._id);
  202. Geometry *geo = (Geometry *)&cur->second;
  203. mesh::generate_vertex_and_index_buffers(*geo);
  204. bgfx::VertexLayout layout = mesh::vertex_layout(*geo);
  205. u32 stride = mesh::vertex_stride(*geo);
  206. OBB bbox = mesh::obb(*geo);
  207. BgfxWriter writer(opts._binary_writer);
  208. bgfx::write(&writer, layout);
  209. opts.write(bbox);
  210. opts.write(array::size(geo->_vertex_buffer) / stride);
  211. opts.write(stride);
  212. opts.write(array::size(geo->_index_buffer));
  213. opts.write(geo->_vertex_buffer);
  214. opts.write(array::begin(geo->_index_buffer), array::size(geo->_index_buffer) * sizeof(u16));
  215. }
  216. return 0;
  217. }
  218. static s32 parse_internal(Mesh &m, Buffer &buf, CompileOptions &opts)
  219. {
  220. TempAllocator4096 ta;
  221. JsonObject obj(ta);
  222. RETURN_IF_ERROR(sjson::parse(obj, buf), opts);
  223. DynamicString source(ta);
  224. if (json_object::has(obj, "source")) {
  225. RETURN_IF_ERROR(sjson::parse_string(source, obj["source"]), opts);
  226. RETURN_IF_FILE_MISSING(source.c_str(), opts);
  227. Buffer fbx_buf = opts.read(source.c_str());
  228. return fbx::parse(m, fbx_buf, opts);
  229. } else {
  230. return mesh::parse(m, buf, opts);
  231. }
  232. }
  233. s32 parse(Mesh &m, const char *path, CompileOptions &opts)
  234. {
  235. RETURN_IF_FILE_MISSING(path, opts);
  236. Buffer buf = opts.read(path);
  237. return parse_internal(m, buf, opts);
  238. }
  239. s32 parse(Mesh &m, CompileOptions &opts)
  240. {
  241. Buffer buf = opts.read();
  242. return parse_internal(m, buf, opts);
  243. }
  244. } // namespace mesh
  245. Node::Node(Allocator &a)
  246. : _local_pose(MATRIX4X4_IDENTITY)
  247. , _geometry(a)
  248. {
  249. }
  250. Geometry::Geometry(Allocator &a)
  251. : _positions(a)
  252. , _normals(a)
  253. , _uvs(a)
  254. , _tangents(a)
  255. , _bitangents(a)
  256. , _bones(a)
  257. , _weights(a)
  258. , _position_indices(a)
  259. , _normal_indices(a)
  260. , _uv_indices(a)
  261. , _tangent_indices(a)
  262. , _bitangent_indices(a)
  263. , _bone_indices(a)
  264. , _weight_indices(a)
  265. , _vertex_buffer(a)
  266. , _index_buffer(a)
  267. {
  268. mesh::reset(*this);
  269. }
  270. Mesh::Mesh(Allocator &a)
  271. : _geometries(a)
  272. , _nodes(a)
  273. {
  274. }
  275. } // namespace crown
  276. #endif // if CROWN_CAN_COMPILE