scene_graph.cpp 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481
  1. /*
  2. * Copyright (c) 2012-2026 Daniele Bartolini et al.
  3. * SPDX-License-Identifier: MIT
  4. */
  5. #include "core/containers/array.inl"
  6. #include "core/containers/hash_map.inl"
  7. #include "core/math/constants.h"
  8. #include "core/math/matrix3x3.inl"
  9. #include "core/math/matrix4x4.inl"
  10. #include "core/math/quaternion.inl"
  11. #include "core/math/vector3.inl"
  12. #include "core/memory/allocator.h"
  13. #include "core/strings/string_id.inl"
  14. #include "world/debug_line.h"
  15. #include "world/scene_graph.h"
  16. #include "world/unit_manager.h"
  17. #include <stdint.h> // UINT_MAX
  18. #include <string.h> // memcpy
  19. namespace crown
  20. {
  21. static void unit_destroyed_callback_bridge(UnitId unit, void *user_ptr)
  22. {
  23. ((SceneGraph *)user_ptr)->unit_destroyed_callback(unit);
  24. }
  25. SceneGraph::Pose &SceneGraph::Pose::operator=(const Matrix4x4 &m)
  26. {
  27. Matrix3x3 rotm = to_matrix3x3(m);
  28. normalize(rotm.x);
  29. normalize(rotm.y);
  30. normalize(rotm.z);
  31. position = translation(m);
  32. rotation = rotm;
  33. scale = crown::scale(m);
  34. return *this;
  35. }
  36. SceneGraph::SceneGraph(Allocator &a, UnitManager &um)
  37. : _marker(SCENE_GRAPH_MARKER)
  38. , _allocator(&a)
  39. , _unit_manager(&um)
  40. , _map(a)
  41. {
  42. _unit_destroy_callback.destroy = unit_destroyed_callback_bridge;
  43. _unit_destroy_callback.user_data = this;
  44. _unit_destroy_callback.node.next = NULL;
  45. _unit_destroy_callback.node.prev = NULL;
  46. um.register_destroy_callback(&_unit_destroy_callback);
  47. }
  48. SceneGraph::~SceneGraph()
  49. {
  50. _unit_manager->unregister_destroy_callback(&_unit_destroy_callback);
  51. _allocator->deallocate(_data.buffer);
  52. _marker = 0;
  53. }
  54. TransformInstance SceneGraph::make_instance(u32 i)
  55. {
  56. TransformInstance inst = { i }; return inst;
  57. }
  58. void SceneGraph::allocate(u32 num)
  59. {
  60. CE_ASSERT(num > _data.size, "num > _data.size");
  61. const u32 bytes = 0
  62. + num*sizeof(UnitId) + alignof(UnitId)
  63. + num*sizeof(Matrix4x4) + alignof(Matrix4x4)
  64. + num*sizeof(Pose) + alignof(Pose)
  65. + num*sizeof(TransformInstance) * 4 + alignof(TransformInstance)
  66. + num*sizeof(bool) + alignof(bool)
  67. ;
  68. InstanceData new_data;
  69. new_data.size = _data.size;
  70. new_data.capacity = num;
  71. new_data.buffer = _allocator->allocate(bytes);
  72. new_data.unit = (UnitId * )memory::align_top(new_data.buffer, alignof(UnitId));
  73. new_data.world = (Matrix4x4 * )memory::align_top(new_data.unit + num, alignof(Matrix4x4));
  74. new_data.local = (Pose * )memory::align_top(new_data.world + num, alignof(Pose));
  75. new_data.parent = (TransformInstance *)memory::align_top(new_data.local + num, alignof(TransformInstance));
  76. new_data.first_child = (TransformInstance *)memory::align_top(new_data.parent + num, alignof(TransformInstance));
  77. new_data.next_sibling = (TransformInstance *)memory::align_top(new_data.first_child + num, alignof(TransformInstance));
  78. new_data.prev_sibling = (TransformInstance *)memory::align_top(new_data.next_sibling + num, alignof(TransformInstance));
  79. new_data.changed = (bool * )memory::align_top(new_data.prev_sibling + num, alignof(bool));
  80. memcpy(new_data.unit, _data.unit, _data.size * sizeof(UnitId));
  81. memcpy(new_data.world, _data.world, _data.size * sizeof(Matrix4x4));
  82. memcpy(new_data.local, _data.local, _data.size * sizeof(Pose));
  83. memcpy(new_data.parent, _data.parent, _data.size * sizeof(TransformInstance));
  84. memcpy(new_data.first_child, _data.first_child, _data.size * sizeof(TransformInstance));
  85. memcpy(new_data.next_sibling, _data.next_sibling, _data.size * sizeof(TransformInstance));
  86. memcpy(new_data.prev_sibling, _data.prev_sibling, _data.size * sizeof(TransformInstance));
  87. memcpy(new_data.changed, _data.changed, _data.size * sizeof(bool));
  88. _allocator->deallocate(_data.buffer);
  89. _data = new_data;
  90. }
  91. void SceneGraph::unit_destroyed_callback(UnitId unit)
  92. {
  93. TransformInstance inst = instance(unit);
  94. if (is_valid(inst))
  95. destroy(inst);
  96. }
  97. void SceneGraph::create_instances(const void *components_data
  98. , u32 num
  99. , const UnitId *unit_lookup
  100. , const u32 *unit_index
  101. , const u32 *unit_parents
  102. , u32 spawn_flags
  103. , const Vector3 &pos
  104. , const Quaternion &rot
  105. , const Vector3 &scl
  106. )
  107. {
  108. const TransformDesc *transforms = (TransformDesc *)components_data;
  109. for (u32 i = 0; i < num; ++i) {
  110. UnitId unit = unit_lookup[unit_index[i]];
  111. CE_ASSERT(!hash_map::has(_map, unit), "Unit already has a transform component");
  112. if (_data.capacity == 0 || _data.capacity - 1 == _data.size)
  113. grow();
  114. const u32 last = _data.size;
  115. Matrix4x4 pose;
  116. set_identity(pose);
  117. set_translation(pose, spawn_flags & SpawnFlags::OVERRIDE_POSITION ? pos : transforms[i].position);
  118. set_rotation(pose, spawn_flags & SpawnFlags::OVERRIDE_ROTATION ? rot : transforms[i].rotation);
  119. set_scale(pose, spawn_flags & SpawnFlags::OVERRIDE_SCALE ? scl : transforms[i].scale);
  120. _data.unit[last] = unit;
  121. _data.world[last] = pose;
  122. _data.local[last] = pose;
  123. _data.parent[last].i = UINT32_MAX;
  124. _data.first_child[last].i = UINT32_MAX;
  125. _data.next_sibling[last].i = UINT32_MAX;
  126. _data.prev_sibling[last].i = UINT32_MAX;
  127. _data.changed[last] = false;
  128. ++_data.size;
  129. hash_map::set(_map, unit, last);
  130. if (unit_parents[unit_index[i]] != UINT32_MAX) {
  131. TransformInstance parent_ti = instance(unit_lookup[unit_parents[unit_index[i]]]);
  132. link(parent_ti, make_instance(last), transforms[i].position, transforms[i].rotation, transforms[i].scale);
  133. }
  134. }
  135. }
  136. TransformInstance SceneGraph::create(UnitId unit, const Vector3 &pos, const Quaternion &rot, const Vector3 &scale)
  137. {
  138. TransformDesc td;
  139. td.position = pos;
  140. td.rotation = rot;
  141. td.scale = scale;
  142. u32 unit_lookup = 0;
  143. u32 unit_parents = UINT32_MAX;
  144. create_instances(&td, 1, &unit, &unit_lookup, &unit_parents);
  145. return instance(unit);
  146. }
  147. /// Moves the node data from index @a src to index @a dst, while preserving
  148. /// internal links between nodes.
  149. static void scene_graph_move_data(const SceneGraph &sg, u32 dst, u32 src)
  150. {
  151. // Any node can be referenced by its children.
  152. TransformInstance cur = sg._data.first_child[src];
  153. while (is_valid(cur)) {
  154. sg._data.parent[cur.i].i = dst;
  155. cur = sg._data.next_sibling[cur.i];
  156. }
  157. if (sg._data.parent[src].i != UINT32_MAX) {
  158. // Child node can also be referenced by its parent (if it is the parent's
  159. // first child)...
  160. if (sg._data.first_child[sg._data.parent[src].i].i == src)
  161. sg._data.first_child[sg._data.parent[src].i].i = dst;
  162. // ... and (at most) by its two closest siblings.
  163. if (sg._data.next_sibling[src].i != UINT32_MAX)
  164. sg._data.prev_sibling[sg._data.next_sibling[src].i].i = dst;
  165. if (sg._data.prev_sibling[src].i != UINT32_MAX)
  166. sg._data.next_sibling[sg._data.prev_sibling[src].i].i = dst;
  167. }
  168. sg._data.unit[dst] = sg._data.unit[src];
  169. sg._data.world[dst] = sg._data.world[src];
  170. sg._data.local[dst] = sg._data.local[src];
  171. sg._data.parent[dst] = sg._data.parent[src];
  172. sg._data.first_child[dst] = sg._data.first_child[src];
  173. sg._data.next_sibling[dst] = sg._data.next_sibling[src];
  174. sg._data.prev_sibling[dst] = sg._data.prev_sibling[src];
  175. sg._data.changed[dst] = sg._data.changed[src];
  176. }
  177. /// Swaps the transforms @a aa and @a bb.
  178. static void scene_graph_swap(const SceneGraph &sg, TransformInstance aa, TransformInstance bb)
  179. {
  180. // Index of the temporary storage slot. Memory access past size-1 is allowed
  181. // because we allocate one extra slot in SceneGraph::grow().
  182. const u32 tt = sg._data.size;
  183. scene_graph_move_data(sg, tt, aa.i);
  184. scene_graph_move_data(sg, aa.i, bb.i);
  185. scene_graph_move_data(sg, bb.i, tt);
  186. }
  187. void SceneGraph::destroy(TransformInstance transform)
  188. {
  189. CE_ASSERT(transform.i < _data.size, "Index out of bounds");
  190. // Unlink all children.
  191. TransformInstance cur = _data.first_child[transform.i];
  192. while (is_valid(cur)) {
  193. TransformInstance next_sibling = _data.next_sibling[cur.i];
  194. unlink(cur);
  195. cur = next_sibling;
  196. }
  197. unlink(transform);
  198. const u32 last = _data.size - 1;
  199. const UnitId u = _data.unit[transform.i];
  200. const UnitId last_u = _data.unit[last];
  201. if (last != transform.i) {
  202. scene_graph_swap(*this, transform, make_instance(last));
  203. hash_map::set(_map, last_u, transform.i);
  204. }
  205. hash_map::remove(_map, u);
  206. --_data.size;
  207. }
  208. TransformInstance SceneGraph::instance(UnitId unit)
  209. {
  210. return make_instance(hash_map::get(_map, unit, UINT32_MAX));
  211. }
  212. UnitId SceneGraph::owner(TransformInstance transform)
  213. {
  214. CE_ASSERT(transform.i < _data.size, "Index out of bounds");
  215. return _data.unit[transform.i];
  216. }
  217. bool SceneGraph::has(UnitId unit)
  218. {
  219. return hash_map::has(_map, unit);
  220. }
  221. void SceneGraph::set_local_position(TransformInstance transform, const Vector3 &pos)
  222. {
  223. CE_ASSERT(transform.i < _data.size, "Index out of bounds");
  224. _data.local[transform.i].position = pos;
  225. set_local(transform);
  226. }
  227. void SceneGraph::set_local_rotation(TransformInstance transform, const Quaternion &rot)
  228. {
  229. CE_ASSERT(transform.i < _data.size, "Index out of bounds");
  230. _data.local[transform.i].rotation = from_quaternion(rot);
  231. set_local(transform);
  232. }
  233. void SceneGraph::set_local_scale(TransformInstance transform, const Vector3 &scale)
  234. {
  235. CE_ASSERT(transform.i < _data.size, "Index out of bounds");
  236. _data.local[transform.i].scale = scale;
  237. set_local(transform);
  238. }
  239. void SceneGraph::set_local_pose(TransformInstance transform, const Matrix4x4 &pose)
  240. {
  241. CE_ASSERT(transform.i < _data.size, "Index out of bounds");
  242. _data.local[transform.i] = pose;
  243. set_local(transform);
  244. }
  245. Vector3 SceneGraph::local_position(TransformInstance transform)
  246. {
  247. CE_ASSERT(transform.i < _data.size, "Index out of bounds");
  248. return _data.local[transform.i].position;
  249. }
  250. Quaternion SceneGraph::local_rotation(TransformInstance transform)
  251. {
  252. CE_ASSERT(transform.i < _data.size, "Index out of bounds");
  253. return rotation(_data.local[transform.i].rotation);
  254. }
  255. Vector3 SceneGraph::local_scale(TransformInstance transform)
  256. {
  257. CE_ASSERT(transform.i < _data.size, "Index out of bounds");
  258. return _data.local[transform.i].scale;
  259. }
  260. Matrix4x4 SceneGraph::local_pose(TransformInstance transform)
  261. {
  262. CE_ASSERT(transform.i < _data.size, "Index out of bounds");
  263. Matrix4x4 tr = from_quaternion_translation(quaternion(_data.local[transform.i].rotation), _data.local[transform.i].position);
  264. set_scale(tr, _data.local[transform.i].scale);
  265. return tr;
  266. }
  267. Vector3 SceneGraph::world_position(TransformInstance transform)
  268. {
  269. CE_ASSERT(transform.i < _data.size, "Index out of bounds");
  270. return translation(_data.world[transform.i]);
  271. }
  272. Quaternion SceneGraph::world_rotation(TransformInstance transform)
  273. {
  274. CE_ASSERT(transform.i < _data.size, "Index out of bounds");
  275. return rotation(_data.world[transform.i]);
  276. }
  277. Matrix4x4 SceneGraph::world_pose(TransformInstance transform)
  278. {
  279. CE_ASSERT(transform.i < _data.size, "Index out of bounds");
  280. return _data.world[transform.i];
  281. }
  282. void SceneGraph::set_world_pose(TransformInstance transform, const Matrix4x4 &pose)
  283. {
  284. CE_ASSERT(transform.i < _data.size, "Index out of bounds");
  285. _data.world[transform.i] = pose;
  286. _data.changed[transform.i] = true;
  287. }
  288. void SceneGraph::set_world_pose_and_rescale(TransformInstance transform, const Matrix4x4 &pose)
  289. {
  290. CE_ASSERT(transform.i < _data.size, "Index out of bounds");
  291. _data.world[transform.i] = pose;
  292. set_scale(_data.world[transform.i], _data.local[transform.i].scale);
  293. _data.changed[transform.i] = true;
  294. }
  295. u32 SceneGraph::num_nodes() const
  296. {
  297. return _data.size;
  298. }
  299. void SceneGraph::link(TransformInstance parent
  300. , TransformInstance child
  301. , const Vector3 &child_local_position
  302. , const Quaternion &child_local_rotation
  303. , const Vector3 &child_local_scale
  304. )
  305. {
  306. CE_ASSERT(child.i < _data.size, "Index out of bounds");
  307. CE_ASSERT(parent.i < _data.size, "Index out of bounds");
  308. unlink(child);
  309. // Append child transform to the parent's children list.
  310. if (!is_valid(_data.first_child[parent.i])) {
  311. _data.first_child[parent.i] = child;
  312. } else {
  313. TransformInstance prev = { UINT32_MAX };
  314. TransformInstance node = _data.first_child[parent.i];
  315. while (is_valid(node)) {
  316. prev = node;
  317. node = _data.next_sibling[node.i];
  318. }
  319. _data.next_sibling[prev.i] = child;
  320. _data.next_sibling[child.i].i = UINT32_MAX;
  321. _data.prev_sibling[child.i] = prev;
  322. }
  323. _data.local[child.i].position = child_local_position;
  324. _data.local[child.i].rotation = from_quaternion(child_local_rotation);
  325. _data.local[child.i].scale = child_local_scale;
  326. _data.parent[child.i] = parent;
  327. transform(_data.world[parent.i], child);
  328. }
  329. void SceneGraph::unlink(TransformInstance child)
  330. {
  331. CE_ASSERT(child.i < _data.size, "Index out of bounds");
  332. if (!is_valid(_data.parent[child.i]))
  333. return;
  334. if (_data.first_child[_data.parent[child.i].i].i == child.i)
  335. _data.first_child[_data.parent[child.i].i] = _data.next_sibling[child.i];
  336. else
  337. _data.next_sibling[_data.prev_sibling[child.i].i] = _data.next_sibling[child.i];
  338. if (is_valid(_data.next_sibling[child.i]))
  339. _data.prev_sibling[_data.next_sibling[child.i].i] = _data.prev_sibling[child.i];
  340. _data.local[child.i].position = translation(_data.world[child.i]);
  341. _data.local[child.i].rotation = from_quaternion(rotation(_data.world[child.i]));
  342. _data.local[child.i].scale = scale(_data.world[child.i]);
  343. _data.parent[child.i].i = UINT32_MAX;
  344. _data.next_sibling[child.i].i = UINT32_MAX;
  345. _data.prev_sibling[child.i].i = UINT32_MAX;
  346. }
  347. TransformInstance SceneGraph::parent(TransformInstance child)
  348. {
  349. CE_ASSERT(child.i < _data.size, "Index out of bounds");
  350. return _data.parent[child.i];
  351. }
  352. TransformInstance SceneGraph::first_child(TransformInstance parent)
  353. {
  354. CE_ASSERT(parent.i < _data.size, "Index out of bounds");
  355. return _data.first_child[parent.i];
  356. }
  357. TransformInstance SceneGraph::next_sibling(TransformInstance child)
  358. {
  359. CE_ASSERT(child.i < _data.size, "Index out of bounds");
  360. return _data.next_sibling[child.i];
  361. }
  362. void SceneGraph::clear_changed()
  363. {
  364. for (u32 i = 0; i < _data.size; ++i) {
  365. _data.changed[i] = false;
  366. }
  367. }
  368. void SceneGraph::get_changed(Array<UnitId> &units, Array<Matrix4x4> &world_poses)
  369. {
  370. for (u32 i = 0; i < _data.size; ++i) {
  371. if (_data.changed[i]) {
  372. array::push_back(units, _data.unit[i]);
  373. array::push_back(world_poses, _data.world[i]);
  374. }
  375. }
  376. }
  377. void SceneGraph::set_local(TransformInstance transform)
  378. {
  379. TransformInstance parent = _data.parent[transform.i];
  380. Matrix4x4 parent_tm = is_valid(parent) ? _data.world[parent.i] : MATRIX4X4_IDENTITY;
  381. SceneGraph::transform(parent_tm, transform);
  382. _data.changed[transform.i] = true;
  383. }
  384. void SceneGraph::transform(const Matrix4x4 &parent, TransformInstance transform)
  385. {
  386. _data.world[transform.i] = local_pose(transform) * parent;
  387. _data.changed[transform.i] = true;
  388. TransformInstance child = _data.first_child[transform.i];
  389. while (is_valid(child)) {
  390. SceneGraph::transform(_data.world[transform.i], child);
  391. child = _data.next_sibling[child.i];
  392. }
  393. }
  394. void SceneGraph::grow()
  395. {
  396. // Allocate one extra slot to be used as a temporary storage.
  397. allocate(2 + _data.capacity*2);
  398. }
  399. void SceneGraph::debug_draw(DebugLine &debug_line)
  400. {
  401. for (u32 i = 0; i < _data.size; ++i)
  402. debug_line.add_axes(_data.world[i], 1.0f);
  403. }
  404. } // namespace crown