scene_tree_fti.cpp 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818
  1. /**************************************************************************/
  2. /* scene_tree_fti.cpp */
  3. /**************************************************************************/
  4. /* This file is part of: */
  5. /* GODOT ENGINE */
  6. /* https://godotengine.org */
  7. /**************************************************************************/
  8. /* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
  9. /* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
  10. /* */
  11. /* Permission is hereby granted, free of charge, to any person obtaining */
  12. /* a copy of this software and associated documentation files (the */
  13. /* "Software"), to deal in the Software without restriction, including */
  14. /* without limitation the rights to use, copy, modify, merge, publish, */
  15. /* distribute, sublicense, and/or sell copies of the Software, and to */
  16. /* permit persons to whom the Software is furnished to do so, subject to */
  17. /* the following conditions: */
  18. /* */
  19. /* The above copyright notice and this permission notice shall be */
  20. /* included in all copies or substantial portions of the Software. */
  21. /* */
  22. /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
  23. /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
  24. /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
  25. /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
  26. /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
  27. /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
  28. /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
  29. /**************************************************************************/
  30. #ifndef _3D_DISABLED
  31. #include "scene_tree_fti.h"
  32. #include "core/config/engine.h"
  33. #include "core/config/project_settings.h"
  34. #include "core/math/transform_interpolator.h"
  35. #include "core/os/os.h"
  36. #include "scene/3d/visual_instance_3d.h"
  37. #ifdef GODOT_SCENE_TREE_FTI_VERIFY
  38. #include "scene_tree_fti_tests.h"
  39. #endif
  40. #ifdef DEV_ENABLED
  41. // Uncomment this to enable some slow extra DEV_ENABLED
  42. // checks to ensure there aren't more than one object added to the lists.
  43. // #define GODOT_SCENE_TREE_FTI_EXTRA_CHECKS
  44. // Uncomment this to regularly print the tree that is being interpolated.
  45. // #define GODOT_SCENE_TREE_FTI_PRINT_TREE
  46. #endif
  47. void SceneTreeFTI::_reset_node3d_flags(Node3D &r_node) {
  48. r_node.data.fti_on_tick_xform_list = false;
  49. r_node.data.fti_on_tick_property_list = false;
  50. r_node.data.fti_on_frame_xform_list = false;
  51. r_node.data.fti_on_frame_property_list = false;
  52. r_node.data.fti_global_xform_interp_set = false;
  53. r_node.data.fti_frame_xform_force_update = false;
  54. r_node.data.fti_processed = false;
  55. }
  56. void SceneTreeFTI::_reset_flags(Node *p_node) {
  57. Node3D *s = Object::cast_to<Node3D>(p_node);
  58. if (s) {
  59. _reset_node3d_flags(*s);
  60. // In most cases the later NOTIFICATION_RESET_PHYSICS_INTERPOLATION
  61. // will reset this, but this should help cover hidden nodes.
  62. s->data.local_transform_prev = s->get_transform();
  63. }
  64. for (int n = 0; n < p_node->get_child_count(); n++) {
  65. _reset_flags(p_node->get_child(n));
  66. }
  67. }
  68. void SceneTreeFTI::set_enabled(Node *p_root, bool p_enabled) {
  69. if (data.enabled == p_enabled) {
  70. return;
  71. }
  72. MutexLock(data.mutex);
  73. data.tick_xform_list[0].clear();
  74. data.tick_xform_list[1].clear();
  75. data.frame_xform_list.clear();
  76. data.frame_xform_list_forced.clear();
  77. data.tick_property_list[0].clear();
  78. data.tick_property_list[1].clear();
  79. data.frame_property_list.clear();
  80. data.request_reset_list.clear();
  81. _clear_depth_lists();
  82. // Node3D flags must be reset.
  83. if (p_root) {
  84. _reset_flags(p_root);
  85. }
  86. data.enabled = p_enabled;
  87. }
  88. void SceneTreeFTI::tick_update() {
  89. if (!data.enabled) {
  90. return;
  91. }
  92. MutexLock(data.mutex);
  93. _update_request_resets();
  94. uint32_t curr_mirror = data.mirror;
  95. uint32_t prev_mirror = curr_mirror ? 0 : 1;
  96. LocalVector<Node3D *> &curr = data.tick_xform_list[curr_mirror];
  97. LocalVector<Node3D *> &prev = data.tick_xform_list[prev_mirror];
  98. // First detect on the previous list but not on this tick list.
  99. for (uint32_t n = 0; n < prev.size(); n++) {
  100. Node3D *s = prev[n];
  101. if (!s->data.fti_on_tick_xform_list) {
  102. // Needs a reset so jittering will stop.
  103. s->fti_pump_xform();
  104. // Optimization - detect whether we have rested at identity xform.
  105. s->data.fti_is_identity_xform = s->data.local_transform == Transform3D();
  106. // This may not get updated so set it to the same as global xform.
  107. // TODO: double check this is the best value.
  108. s->data.global_transform_interpolated = s->get_global_transform();
  109. // Remove from interpolation list.
  110. if (s->data.fti_on_frame_xform_list) {
  111. _node_remove_from_frame_list(*s, false);
  112. }
  113. // Ensure that the node gets at least ONE further
  114. // update in the resting position in the next frame update.
  115. if (!s->data.fti_frame_xform_force_update) {
  116. _node_add_to_frame_list(*s, true);
  117. }
  118. }
  119. }
  120. LocalVector<Node3D *> &curr_prop = data.tick_property_list[curr_mirror];
  121. LocalVector<Node3D *> &prev_prop = data.tick_property_list[prev_mirror];
  122. // Detect on the previous property list but not on this tick list.
  123. for (uint32_t n = 0; n < prev_prop.size(); n++) {
  124. Node3D *s = prev_prop[n];
  125. if (!s->data.fti_on_tick_property_list) {
  126. // Needs a reset so jittering will stop.
  127. s->fti_pump_xform();
  128. // Ensure the servers are up to date with the final resting value.
  129. s->fti_update_servers_property();
  130. // Remove from interpolation list.
  131. if (s->data.fti_on_frame_property_list) {
  132. s->data.fti_on_frame_property_list = false;
  133. data.frame_property_list.erase_unordered(s);
  134. #ifdef GODOT_SCENE_TREE_FTI_EXTRA_CHECKS
  135. DEV_CHECK_ONCE(data.frame_property_list.find(s) == -1);
  136. #endif
  137. }
  138. }
  139. }
  140. // Pump all on the property list that are NOT on the tick list.
  141. for (uint32_t n = 0; n < curr_prop.size(); n++) {
  142. Node3D *s = curr_prop[n];
  143. // Reset, needs to be marked each tick.
  144. s->data.fti_on_tick_property_list = false;
  145. s->fti_pump_property();
  146. }
  147. // Now pump all on the current list.
  148. for (uint32_t n = 0; n < curr.size(); n++) {
  149. Node3D *s = curr[n];
  150. // Reset, needs to be marked each tick.
  151. s->data.fti_on_tick_xform_list = false;
  152. // Pump.
  153. s->fti_pump_xform();
  154. }
  155. // Clear previous list and flip.
  156. prev.clear();
  157. prev_prop.clear();
  158. data.mirror = prev_mirror;
  159. }
  160. void SceneTreeFTI::_update_request_resets() {
  161. // For instance when first adding to the tree, when the previous transform is
  162. // unset, to prevent streaking from the origin.
  163. for (uint32_t n = 0; n < data.request_reset_list.size(); n++) {
  164. Node3D *s = data.request_reset_list[n];
  165. if (s->_is_physics_interpolation_reset_requested()) {
  166. if (s->_is_vi_visible() && !s->_is_using_identity_transform()) {
  167. s->notification(Node3D::NOTIFICATION_RESET_PHYSICS_INTERPOLATION);
  168. }
  169. s->_set_physics_interpolation_reset_requested(false);
  170. }
  171. }
  172. data.request_reset_list.clear();
  173. }
  174. void SceneTreeFTI::node_3d_request_reset(Node3D *p_node) {
  175. DEV_CHECK_ONCE(data.enabled);
  176. DEV_ASSERT(p_node);
  177. MutexLock(data.mutex);
  178. if (!p_node->_is_physics_interpolation_reset_requested()) {
  179. p_node->_set_physics_interpolation_reset_requested(true);
  180. #ifdef GODOT_SCENE_TREE_FTI_EXTRA_CHECKS
  181. DEV_CHECK_ONCE(data.request_reset_list.find(p_node) == -1);
  182. #endif
  183. data.request_reset_list.push_back(p_node);
  184. }
  185. }
  186. void SceneTreeFTI::_node_3d_notify_set_property(Node3D &r_node) {
  187. if (!r_node.is_physics_interpolated()) {
  188. return;
  189. }
  190. DEV_CHECK_ONCE(data.enabled);
  191. // Note that a Node3D can be on BOTH the transform list and the property list.
  192. if (!r_node.data.fti_on_tick_property_list) {
  193. r_node.data.fti_on_tick_property_list = true;
  194. // Should only appear once in the property list.
  195. #ifdef GODOT_SCENE_TREE_FTI_EXTRA_CHECKS
  196. DEV_CHECK_ONCE(data.tick_property_list[data.mirror].find(&r_node) == -1);
  197. #endif
  198. data.tick_property_list[data.mirror].push_back(&r_node);
  199. }
  200. if (!r_node.data.fti_on_frame_property_list) {
  201. r_node.data.fti_on_frame_property_list = true;
  202. // Should only appear once in the property frame list.
  203. #ifdef GODOT_SCENE_TREE_FTI_EXTRA_CHECKS
  204. DEV_CHECK_ONCE(data.frame_property_list.find(&r_node) == -1);
  205. #endif
  206. data.frame_property_list.push_back(&r_node);
  207. }
  208. }
  209. void SceneTreeFTI::_create_depth_lists() {
  210. uint32_t first_list = data.frame_start ? 0 : 1;
  211. for (uint32_t l = first_list; l < 2; l++) {
  212. LocalVector<Node3D *> &source_list = l == 0 ? data.frame_xform_list : data.frame_xform_list_forced;
  213. #ifdef DEBUG_ENABLED
  214. bool log_nodes_moved_on_frame = (data.traversal_mode == TM_DEBUG) && !data.frame_start && data.periodic_debug_log;
  215. if (log_nodes_moved_on_frame) {
  216. if (source_list.size()) {
  217. print_line(String("\n") + itos(source_list.size()) + " nodes moved during frame:");
  218. } else {
  219. print_line("0 nodes moved during frame.");
  220. }
  221. }
  222. #endif
  223. for (uint32_t n = 0; n < source_list.size(); n++) {
  224. Node3D *s = source_list[n];
  225. s->data.fti_processed = false;
  226. int32_t depth = s->_get_scene_tree_depth();
  227. // This shouldn't happen, but wouldn't be terrible if it did.
  228. DEV_ASSERT(depth >= 0);
  229. depth = MIN(depth, (int32_t)data.scene_tree_depth_limit);
  230. LocalVector<Node3D *> &dest_list = data.dirty_node_depth_lists[depth];
  231. #ifdef GODOT_SCENE_TREE_FTI_EXTRA_CHECKS
  232. // Shouldn't really happen, but duplicates don't really matter that much.
  233. if (dest_list.find(s) != -1) {
  234. ERR_FAIL_COND(dest_list.find(s) != -1);
  235. }
  236. #endif
  237. #ifdef DEBUG_ENABLED
  238. if (log_nodes_moved_on_frame) {
  239. print_line("\t" + s->get_name());
  240. }
  241. #endif
  242. // Prevent being added to the dest_list twice when on
  243. // the frame_xform_list AND the frame_xform_list_forced.
  244. if ((l == 0) && s->data.fti_frame_xform_force_update) {
  245. #ifdef GODOT_SCENE_TREE_FTI_EXTRA_CHECKS
  246. DEV_ASSERT(data.frame_xform_list_forced.find(s) != -1);
  247. #endif
  248. continue;
  249. }
  250. dest_list.push_back(s);
  251. }
  252. }
  253. }
  254. void SceneTreeFTI::_clear_depth_lists() {
  255. for (uint32_t d = 0; d < data.scene_tree_depth_limit; d++) {
  256. data.dirty_node_depth_lists[d].clear();
  257. }
  258. }
  259. void SceneTreeFTI::_node_add_to_frame_list(Node3D &r_node, bool p_forced) {
  260. if (p_forced) {
  261. DEV_ASSERT(!r_node.data.fti_frame_xform_force_update);
  262. #ifdef GODOT_SCENE_TREE_FTI_EXTRA_CHECKS
  263. int64_t found = data.frame_xform_list_forced.find(&r_node);
  264. if (found != -1) {
  265. ERR_FAIL_COND(found != -1);
  266. }
  267. #endif
  268. data.frame_xform_list_forced.push_back(&r_node);
  269. r_node.data.fti_frame_xform_force_update = true;
  270. } else {
  271. DEV_ASSERT(!r_node.data.fti_on_frame_xform_list);
  272. #ifdef GODOT_SCENE_TREE_FTI_EXTRA_CHECKS
  273. int64_t found = data.frame_xform_list.find(&r_node);
  274. if (found != -1) {
  275. ERR_FAIL_COND(found != -1);
  276. }
  277. #endif
  278. data.frame_xform_list.push_back(&r_node);
  279. r_node.data.fti_on_frame_xform_list = true;
  280. }
  281. }
  282. void SceneTreeFTI::_node_remove_from_frame_list(Node3D &r_node, bool p_forced) {
  283. if (p_forced) {
  284. DEV_ASSERT(r_node.data.fti_frame_xform_force_update);
  285. data.frame_xform_list_forced.erase_unordered(&r_node);
  286. r_node.data.fti_frame_xform_force_update = false;
  287. } else {
  288. DEV_ASSERT(r_node.data.fti_on_frame_xform_list);
  289. data.frame_xform_list.erase_unordered(&r_node);
  290. r_node.data.fti_on_frame_xform_list = false;
  291. }
  292. }
  293. void SceneTreeFTI::_node_3d_notify_set_xform(Node3D &r_node) {
  294. DEV_CHECK_ONCE(data.enabled);
  295. if (!r_node.is_physics_interpolated()) {
  296. // Force an update of non-interpolated to servers
  297. // on the next traversal.
  298. if (!r_node.data.fti_frame_xform_force_update) {
  299. _node_add_to_frame_list(r_node, true);
  300. }
  301. // ToDo: Double check this is a win,
  302. // non-interpolated nodes we always check for identity,
  303. // *just in case*.
  304. r_node.data.fti_is_identity_xform = r_node.get_transform() == Transform3D();
  305. return;
  306. }
  307. r_node.data.fti_is_identity_xform = false;
  308. if (!r_node.data.fti_on_tick_xform_list) {
  309. r_node.data.fti_on_tick_xform_list = true;
  310. // Should only appear once in the xform list.
  311. #ifdef GODOT_SCENE_TREE_FTI_EXTRA_CHECKS
  312. DEV_CHECK_ONCE(data.tick_xform_list[data.mirror].find(&r_node) == -1);
  313. #endif
  314. data.tick_xform_list[data.mirror].push_back(&r_node);
  315. // The following flag could have been previously set
  316. // (for removal from the tick list).
  317. // We no longer need this guarantee,
  318. // however there is probably no downside to leaving it set
  319. // as it will be cleared on the next frame anyway.
  320. // This line is left for reference.
  321. // r_node.data.fti_frame_xform_force_update = false;
  322. }
  323. if (!r_node.data.fti_on_frame_xform_list) {
  324. _node_add_to_frame_list(r_node, false);
  325. }
  326. // If we are in the second half of a frame, always add to the force update list,
  327. // because we ignore the tick update list during the second update.
  328. if (data.in_frame) {
  329. if (!r_node.data.fti_frame_xform_force_update) {
  330. _node_add_to_frame_list(r_node, true);
  331. }
  332. }
  333. }
  334. void SceneTreeFTI::node_3d_notify_delete(Node3D *p_node) {
  335. if (!data.enabled) {
  336. return;
  337. }
  338. ERR_FAIL_NULL(p_node);
  339. MutexLock(data.mutex);
  340. // Remove from frame lists.
  341. if (p_node->data.fti_on_frame_xform_list) {
  342. _node_remove_from_frame_list(*p_node, false);
  343. }
  344. if (p_node->data.fti_frame_xform_force_update) {
  345. _node_remove_from_frame_list(*p_node, true);
  346. }
  347. // Ensure this is kept in sync with the lists, in case a node
  348. // is removed and re-added to the scene tree multiple times
  349. // on the same frame / tick.
  350. p_node->_set_physics_interpolation_reset_requested(false);
  351. // Keep flags consistent for the same as a new node,
  352. // because this node may re-enter the scene tree.
  353. _reset_node3d_flags(*p_node);
  354. // This can potentially be optimized for large scenes with large churn,
  355. // as it will be doing a linear search through the lists.
  356. data.tick_xform_list[0].erase_unordered(p_node);
  357. data.tick_xform_list[1].erase_unordered(p_node);
  358. data.tick_property_list[0].erase_unordered(p_node);
  359. data.tick_property_list[1].erase_unordered(p_node);
  360. data.frame_property_list.erase_unordered(p_node);
  361. data.request_reset_list.erase_unordered(p_node);
  362. #ifdef GODOT_SCENE_TREE_FTI_EXTRA_CHECKS
  363. // There should only be one occurrence on the lists.
  364. // Check this in DEV_ENABLED builds.
  365. DEV_CHECK_ONCE(data.tick_xform_list[0].find(p_node) == -1);
  366. DEV_CHECK_ONCE(data.tick_xform_list[1].find(p_node) == -1);
  367. DEV_CHECK_ONCE(data.tick_property_list[0].find(p_node) == -1);
  368. DEV_CHECK_ONCE(data.tick_property_list[1].find(p_node) == -1);
  369. DEV_CHECK_ONCE(data.frame_property_list.find(p_node) == -1);
  370. DEV_CHECK_ONCE(data.request_reset_list.find(p_node) == -1);
  371. DEV_CHECK_ONCE(data.frame_xform_list.find(p_node) == -1);
  372. DEV_CHECK_ONCE(data.frame_xform_list_forced.find(p_node) == -1);
  373. #endif
  374. }
  375. void SceneTreeFTI::_update_dirty_nodes(Node *p_node, uint32_t p_current_half_frame, float p_interpolation_fraction, bool p_active, const Transform3D *p_parent_global_xform, int p_depth) {
  376. Node3D *s = Object::cast_to<Node3D>(p_node);
  377. #ifdef DEBUG_ENABLED
  378. data.debug_node_count++;
  379. #endif
  380. // Don't recurse into hidden branches.
  381. if (s && !s->data.visible) {
  382. // NOTE : If we change from recursing entire tree, we should do an is_visible_in_tree()
  383. // check for the first of the branch.
  384. return;
  385. }
  386. // Temporary direct access to children cache for speed.
  387. // Maybe replaced later by a more generic fast access method
  388. // for children.
  389. p_node->_update_children_cache();
  390. Span<Node *> children = p_node->data.children_cache.span();
  391. uint32_t num_children = children.size();
  392. // Not a Node3D.
  393. // Could be e.g. a viewport or something
  394. // so we should still recurse to children.
  395. if (!s) {
  396. for (uint32_t n = 0; n < num_children; n++) {
  397. _update_dirty_nodes(children.ptr()[n], p_current_half_frame, p_interpolation_fraction, p_active, nullptr, p_depth + 1);
  398. }
  399. return;
  400. }
  401. // We are going to be using data.global_transform, so
  402. // we need to ensure data.global_transform is not dirty!
  403. if (s->_test_dirty_bits(Node3D::DIRTY_GLOBAL_TRANSFORM)) {
  404. _ALLOW_DISCARD_ s->get_global_transform();
  405. }
  406. // Start the active interpolation chain from here onwards
  407. // as we recurse further into the SceneTree.
  408. // Once we hit an active (interpolated) node, we have to fully
  409. // process all ancestors because their xform will also change.
  410. // Anything not moving (inactive) higher in the tree need not be processed.
  411. if (!p_active) {
  412. if (data.frame_start) {
  413. // On the frame start, activate whenever we hit something that requests interpolation.
  414. if (s->data.fti_on_frame_xform_list || s->data.fti_frame_xform_force_update) {
  415. p_active = true;
  416. }
  417. } else {
  418. // On the frame end, we want to re-interpolate *anything* that has moved
  419. // since the frame start.
  420. if (s->_test_dirty_bits(Node3D::DIRTY_GLOBAL_INTERPOLATED_TRANSFORM)) {
  421. p_active = true;
  422. #if 0
  423. if (data.periodic_debug_log) {
  424. print_line("activating on : " + s->get_name());
  425. }
  426. #endif
  427. }
  428. }
  429. }
  430. // ToDo : Check global_xform_interp is up to date for nodes
  431. // that are not traversed by the depth lists.
  432. if (data.frame_start) {
  433. // Mark on the Node3D whether we have set global_transform_interp.
  434. // This can later be used when calling `get_global_transform_interpolated()`
  435. // to know which xform to return.
  436. s->data.fti_global_xform_interp_set = p_active;
  437. }
  438. if (p_active) {
  439. #ifdef GODOT_SCENE_TREE_FTI_PRINT_TREE
  440. bool dirty = s->_test_dirty_bits(Node3D::DIRTY_GLOBAL_INTERPOLATED_TRANSFORM);
  441. if (data.periodic_debug_log && !data.use_optimized_traversal_method && !data.frame_start) {
  442. String sz;
  443. for (int n = 0; n < p_depth; n++) {
  444. sz += "\t";
  445. }
  446. print_line(sz + p_node->get_name() + (dirty ? " DIRTY" : "") + (s->get_transform() == Transform3D() ? "\t[IDENTITY]" : ""));
  447. }
  448. #endif
  449. // First calculate our local xform.
  450. // This will either use interpolation, or just use the current local if not interpolated.
  451. Transform3D local_interp;
  452. if (s->is_physics_interpolated()) {
  453. // There may be no need to interpolate if the node has not been moved recently
  454. // and is therefore not on the tick list...
  455. if (s->data.fti_on_tick_xform_list) {
  456. // Make sure to call `get_transform()` rather than using local_transform directly, because
  457. // local_transform may be dirty and need updating from rotation / scale.
  458. TransformInterpolator::interpolate_transform_3d(s->data.local_transform_prev, s->get_transform(), local_interp, p_interpolation_fraction);
  459. } else {
  460. local_interp = s->get_transform();
  461. }
  462. } else {
  463. local_interp = s->get_transform();
  464. }
  465. // Concatenate parent xform.
  466. if (!s->is_set_as_top_level()) {
  467. if (p_parent_global_xform) {
  468. s->data.global_transform_interpolated = s->data.fti_is_identity_xform ? *p_parent_global_xform : ((*p_parent_global_xform) * local_interp);
  469. } else {
  470. const Node3D *parent = s->get_parent_node_3d();
  471. if (parent) {
  472. const Transform3D &parent_glob = parent->data.fti_global_xform_interp_set ? parent->data.global_transform_interpolated : parent->get_global_transform();
  473. s->data.global_transform_interpolated = s->data.fti_is_identity_xform ? parent_glob : parent_glob * local_interp;
  474. } else {
  475. s->data.global_transform_interpolated = local_interp;
  476. }
  477. }
  478. } else {
  479. s->data.global_transform_interpolated = local_interp;
  480. }
  481. // Watch for this, disable_scale can cause incredibly confusing bugs
  482. // and must be checked for when calculating global xforms.
  483. if (s->data.disable_scale) {
  484. s->data.global_transform_interpolated.basis.orthonormalize();
  485. }
  486. // Upload to RenderingServer the interpolated global xform.
  487. s->fti_update_servers_xform();
  488. // Ensure branches are only processed once on each traversal.
  489. s->data.fti_processed = true;
  490. #ifdef DEBUG_ENABLED
  491. data.debug_nodes_processed++;
  492. #endif
  493. } // if active.
  494. // Remove the dirty interp flag from EVERYTHING as we go.
  495. s->_clear_dirty_bits(Node3D::DIRTY_GLOBAL_INTERPOLATED_TRANSFORM);
  496. // Recurse to children.
  497. for (uint32_t n = 0; n < num_children; n++) {
  498. _update_dirty_nodes(children.ptr()[n], p_current_half_frame, p_interpolation_fraction, p_active, s->data.fti_global_xform_interp_set ? &s->data.global_transform_interpolated : &s->data.global_transform, p_depth + 1);
  499. }
  500. }
  501. void SceneTreeFTI::frame_update(Node *p_root, bool p_frame_start) {
  502. if (!data.enabled || !p_root) {
  503. return;
  504. }
  505. MutexLock(data.mutex);
  506. data.frame_start = p_frame_start;
  507. data.in_frame = true;
  508. _update_request_resets();
  509. float interpolation_fraction = Engine::get_singleton()->get_physics_interpolation_fraction();
  510. uint32_t frame = Engine::get_singleton()->get_frames_drawn();
  511. uint64_t before = 0;
  512. #ifdef DEBUG_ENABLED
  513. if (data.traversal_mode == TM_DEBUG) {
  514. before = OS::get_singleton()->get_ticks_usec();
  515. if (p_frame_start && ((frame % ((60 * 15) - 3)) == 0)) {
  516. data.periodic_debug_log = true;
  517. }
  518. }
  519. #ifdef GODOT_SCENE_TREE_FTI_PRINT_TREE
  520. if (data.periodic_debug_log) {
  521. print_line(String("\nScene: ") + (data.frame_start ? "start" : "end") + "\n");
  522. }
  523. #endif
  524. #endif
  525. data.debug_node_count = 0;
  526. data.debug_nodes_processed = 0;
  527. uint32_t half_frame = p_frame_start ? (frame * 2) : ((frame * 2) + 1);
  528. bool print_debug_stats = false;
  529. switch (data.traversal_mode) {
  530. case TM_LEGACY: {
  531. data.use_optimized_traversal_method = false;
  532. } break;
  533. case TM_DEBUG: {
  534. // Switch on alternate frames between the two methods.
  535. data.use_optimized_traversal_method = (frame % 2) == 1;
  536. // Odd number ensures we debug stats for both methods.
  537. print_debug_stats = (frame % ((60 * 8) - 1)) == 0;
  538. } break;
  539. default: {
  540. data.use_optimized_traversal_method = true;
  541. } break;
  542. }
  543. #ifdef GODOT_SCENE_TREE_FTI_VERIFY
  544. _tests->frame_update(p_root, half_frame, interpolation_fraction);
  545. #else
  546. uint32_t skipped = 0;
  547. if (!data.use_optimized_traversal_method) {
  548. // Reference approach.
  549. // Traverse the entire scene tree.
  550. // Slow, but robust.
  551. _update_dirty_nodes(p_root, half_frame, interpolation_fraction, false);
  552. } else {
  553. // Optimized approach.
  554. // Traverse from depth lists.
  555. // Be sure to check against the reference
  556. // implementation when making changes.
  557. _create_depth_lists();
  558. for (uint32_t d = 0; d < data.scene_tree_depth_limit; d++) {
  559. const LocalVector<Node3D *> &list = data.dirty_node_depth_lists[d];
  560. #if 0
  561. if (list.size() > 0) {
  562. print_line("depth " + itos(d) + ", contains " + itos(list.size()));
  563. }
  564. #endif
  565. for (uint32_t n = 0; n < list.size(); n++) {
  566. // Already processed this frame?
  567. Node3D *s = list[n];
  568. if (s->data.fti_processed) {
  569. #ifdef DEBUG_ENABLED
  570. skipped++;
  571. #endif
  572. continue;
  573. }
  574. // The first node requires a recursive visibility check
  575. // up the tree, because `is_visible()` only returns the node
  576. // local flag.
  577. if (Object::cast_to<VisualInstance3D>(s)) {
  578. if (!s->_is_vi_visible()) {
  579. #ifdef DEBUG_ENABLED
  580. skipped++;
  581. #endif
  582. continue;
  583. }
  584. } else if (!s->is_visible_in_tree()) {
  585. #ifdef DEBUG_ENABLED
  586. skipped++;
  587. #endif
  588. continue;
  589. }
  590. _update_dirty_nodes(s, half_frame, interpolation_fraction, true);
  591. }
  592. }
  593. _clear_depth_lists();
  594. }
  595. if (print_debug_stats) {
  596. uint64_t after = OS::get_singleton()->get_ticks_usec();
  597. print_line(String(data.use_optimized_traversal_method ? "FTI optimized" : "FTI reference") + " nodes traversed : " + itos(data.debug_node_count) + (skipped == 0 ? "" : ", skipped " + itos(skipped)) + ", processed : " + itos(data.debug_nodes_processed) + ", took " + itos(after - before) + " usec " + (data.frame_start ? "(start)" : "(end)"));
  598. }
  599. #endif // not GODOT_SCENE_TREE_FTI_VERIFY
  600. // In theory we could clear the `force_update` flags from the nodes in the traversal.
  601. // The problem is that hidden nodes are not recursed into, therefore the flags would
  602. // never get cleared and could get out of sync with the forced list.
  603. // So instead we are clearing them here manually.
  604. // This is not ideal in terms of cache coherence so perhaps another method can be
  605. // explored in future.
  606. uint32_t forced_list_size = data.frame_xform_list_forced.size();
  607. for (uint32_t n = 0; n < forced_list_size; n++) {
  608. Node3D *s = data.frame_xform_list_forced[n];
  609. s->data.fti_frame_xform_force_update = false;
  610. }
  611. data.frame_xform_list_forced.clear();
  612. if (!p_frame_start && data.periodic_debug_log) {
  613. data.periodic_debug_log = false;
  614. }
  615. // Update the properties once off at the end of the frame.
  616. // No need for two passes for properties.
  617. if (!p_frame_start) {
  618. for (uint32_t n = 0; n < data.frame_property_list.size(); n++) {
  619. Node3D *s = data.frame_property_list[n];
  620. s->fti_update_servers_property();
  621. }
  622. }
  623. // Marks the end of the frame.
  624. // Enables us to recognize when change notifications
  625. // come in _during_ a frame (they get treated differently).
  626. if (!data.frame_start) {
  627. data.in_frame = false;
  628. }
  629. }
  630. SceneTreeFTI::SceneTreeFTI() {
  631. #ifdef GODOT_SCENE_TREE_FTI_VERIFY
  632. _tests = memnew(SceneTreeFTITests(*this));
  633. #endif
  634. Variant traversal_mode_string = GLOBAL_DEF("physics/3d/physics_interpolation/scene_traversal", "DEFAULT");
  635. ProjectSettings::get_singleton()->set_custom_property_info(PropertyInfo(Variant::STRING, "physics/3d/physics_interpolation/scene_traversal", PROPERTY_HINT_ENUM, "DEFAULT,Legacy,Debug"));
  636. data.traversal_mode = TM_DEFAULT;
  637. if (traversal_mode_string == "Legacy") {
  638. data.traversal_mode = TM_LEGACY;
  639. } else if (traversal_mode_string == "Debug") {
  640. // Don't allow debug mode in final exports,
  641. // it will almost certainly be a mistake.
  642. #ifdef DEBUG_ENABLED
  643. data.traversal_mode = TM_DEBUG;
  644. #else
  645. data.traversal_mode = TM_DEFAULT;
  646. #endif
  647. }
  648. switch (data.traversal_mode) {
  649. default: {
  650. print_verbose("SceneTreeFTI: traversal method DEFAULT");
  651. } break;
  652. case TM_LEGACY: {
  653. print_verbose("SceneTreeFTI: traversal method Legacy");
  654. } break;
  655. case TM_DEBUG: {
  656. print_verbose("SceneTreeFTI: traversal method Debug");
  657. } break;
  658. }
  659. #ifdef GODOT_SCENE_TREE_FTI_EXTRA_CHECKS
  660. print_line("SceneTreeFTI : GODOT_SCENE_TREE_FTI_EXTRA_CHECKS defined");
  661. #endif
  662. #ifdef GODOT_SCENE_TREE_FTI_PRINT_TREE
  663. print_line("SceneTreeFTI : GODOT_SCENE_TREE_FTI_PRINT_TREE defined");
  664. #endif
  665. }
  666. SceneTreeFTI::~SceneTreeFTI() {
  667. #ifdef GODOT_SCENE_TREE_FTI_VERIFY
  668. if (_tests) {
  669. memfree(_tests);
  670. _tests = nullptr;
  671. }
  672. #endif
  673. }
  674. #endif // ndef _3D_DISABLED