scene_tree_fti.cpp 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811
  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 - 1);
  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. // Not a Node3D.
  387. // Could be e.g. a viewport or something
  388. // so we should still recurse to children.
  389. if (!s) {
  390. for (Node *node : p_node->iterate_children()) {
  391. _update_dirty_nodes(node, p_current_half_frame, p_interpolation_fraction, p_active, nullptr, p_depth + 1);
  392. }
  393. return;
  394. }
  395. // We are going to be using data.global_transform, so
  396. // we need to ensure data.global_transform is not dirty!
  397. if (s->_test_dirty_bits(Node3D::DIRTY_GLOBAL_TRANSFORM)) {
  398. _ALLOW_DISCARD_ s->get_global_transform();
  399. }
  400. // Start the active interpolation chain from here onwards
  401. // as we recurse further into the SceneTree.
  402. // Once we hit an active (interpolated) node, we have to fully
  403. // process all ancestors because their xform will also change.
  404. // Anything not moving (inactive) higher in the tree need not be processed.
  405. if (!p_active) {
  406. if (data.frame_start) {
  407. // On the frame start, activate whenever we hit something that requests interpolation.
  408. if (s->data.fti_on_frame_xform_list || s->data.fti_frame_xform_force_update) {
  409. p_active = true;
  410. }
  411. } else {
  412. // On the frame end, we want to re-interpolate *anything* that has moved
  413. // since the frame start.
  414. if (s->_test_dirty_bits(Node3D::DIRTY_GLOBAL_INTERPOLATED_TRANSFORM)) {
  415. p_active = true;
  416. #if 0
  417. if (data.periodic_debug_log) {
  418. print_line("activating on : " + s->get_name());
  419. }
  420. #endif
  421. }
  422. }
  423. }
  424. // ToDo : Check global_xform_interp is up to date for nodes
  425. // that are not traversed by the depth lists.
  426. if (data.frame_start) {
  427. // Mark on the Node3D whether we have set global_transform_interp.
  428. // This can later be used when calling `get_global_transform_interpolated()`
  429. // to know which xform to return.
  430. s->data.fti_global_xform_interp_set = p_active;
  431. }
  432. if (p_active) {
  433. #ifdef GODOT_SCENE_TREE_FTI_PRINT_TREE
  434. bool dirty = s->_test_dirty_bits(Node3D::DIRTY_GLOBAL_INTERPOLATED_TRANSFORM);
  435. if (data.periodic_debug_log && !data.use_optimized_traversal_method && !data.frame_start) {
  436. String sz;
  437. for (int n = 0; n < p_depth; n++) {
  438. sz += "\t";
  439. }
  440. print_line(sz + p_node->get_name() + (dirty ? " DIRTY" : "") + (s->get_transform() == Transform3D() ? "\t[IDENTITY]" : ""));
  441. }
  442. #endif
  443. // First calculate our local xform.
  444. // This will either use interpolation, or just use the current local if not interpolated.
  445. Transform3D local_interp;
  446. if (s->is_physics_interpolated()) {
  447. // There may be no need to interpolate if the node has not been moved recently
  448. // and is therefore not on the tick list...
  449. if (s->data.fti_on_tick_xform_list) {
  450. // Make sure to call `get_transform()` rather than using local_transform directly, because
  451. // local_transform may be dirty and need updating from rotation / scale.
  452. TransformInterpolator::interpolate_transform_3d(s->data.local_transform_prev, s->get_transform(), local_interp, p_interpolation_fraction);
  453. } else {
  454. local_interp = s->get_transform();
  455. }
  456. } else {
  457. local_interp = s->get_transform();
  458. }
  459. // Concatenate parent xform.
  460. if (!s->is_set_as_top_level()) {
  461. if (p_parent_global_xform) {
  462. s->data.global_transform_interpolated = s->data.fti_is_identity_xform ? *p_parent_global_xform : ((*p_parent_global_xform) * local_interp);
  463. } else {
  464. const Node3D *parent = s->get_parent_node_3d();
  465. if (parent) {
  466. const Transform3D &parent_glob = parent->data.fti_global_xform_interp_set ? parent->data.global_transform_interpolated : parent->get_global_transform();
  467. s->data.global_transform_interpolated = s->data.fti_is_identity_xform ? parent_glob : parent_glob * local_interp;
  468. } else {
  469. s->data.global_transform_interpolated = local_interp;
  470. }
  471. }
  472. } else {
  473. s->data.global_transform_interpolated = local_interp;
  474. }
  475. // Watch for this, disable_scale can cause incredibly confusing bugs
  476. // and must be checked for when calculating global xforms.
  477. if (s->data.disable_scale) {
  478. s->data.global_transform_interpolated.basis.orthonormalize();
  479. }
  480. // Upload to RenderingServer the interpolated global xform.
  481. s->fti_update_servers_xform();
  482. // Ensure branches are only processed once on each traversal.
  483. s->data.fti_processed = true;
  484. #ifdef DEBUG_ENABLED
  485. data.debug_nodes_processed++;
  486. #endif
  487. } // if active.
  488. // Remove the dirty interp flag from EVERYTHING as we go.
  489. s->_clear_dirty_bits(Node3D::DIRTY_GLOBAL_INTERPOLATED_TRANSFORM);
  490. // Recurse to children.
  491. for (Node *node : p_node->iterate_children()) {
  492. _update_dirty_nodes(node, 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);
  493. }
  494. }
  495. void SceneTreeFTI::frame_update(Node *p_root, bool p_frame_start) {
  496. if (!data.enabled || !p_root) {
  497. return;
  498. }
  499. MutexLock(data.mutex);
  500. data.frame_start = p_frame_start;
  501. data.in_frame = true;
  502. _update_request_resets();
  503. float interpolation_fraction = Engine::get_singleton()->get_physics_interpolation_fraction();
  504. uint32_t frame = Engine::get_singleton()->get_frames_drawn();
  505. uint64_t before = 0;
  506. #ifdef DEBUG_ENABLED
  507. if (data.traversal_mode == TM_DEBUG) {
  508. before = OS::get_singleton()->get_ticks_usec();
  509. if (p_frame_start && ((frame % ((60 * 15) - 3)) == 0)) {
  510. data.periodic_debug_log = true;
  511. }
  512. }
  513. #ifdef GODOT_SCENE_TREE_FTI_PRINT_TREE
  514. if (data.periodic_debug_log) {
  515. print_line(String("\nScene: ") + (data.frame_start ? "start" : "end") + "\n");
  516. }
  517. #endif
  518. #endif
  519. data.debug_node_count = 0;
  520. data.debug_nodes_processed = 0;
  521. uint32_t half_frame = p_frame_start ? (frame * 2) : ((frame * 2) + 1);
  522. bool print_debug_stats = false;
  523. switch (data.traversal_mode) {
  524. case TM_LEGACY: {
  525. data.use_optimized_traversal_method = false;
  526. } break;
  527. case TM_DEBUG: {
  528. // Switch on alternate frames between the two methods.
  529. data.use_optimized_traversal_method = (frame % 2) == 1;
  530. // Odd number ensures we debug stats for both methods.
  531. print_debug_stats = (frame % ((60 * 8) - 1)) == 0;
  532. } break;
  533. default: {
  534. data.use_optimized_traversal_method = true;
  535. } break;
  536. }
  537. #ifdef GODOT_SCENE_TREE_FTI_VERIFY
  538. _tests->frame_update(p_root, half_frame, interpolation_fraction);
  539. #else
  540. uint32_t skipped = 0;
  541. if (!data.use_optimized_traversal_method) {
  542. // Reference approach.
  543. // Traverse the entire scene tree.
  544. // Slow, but robust.
  545. _update_dirty_nodes(p_root, half_frame, interpolation_fraction, false);
  546. } else {
  547. // Optimized approach.
  548. // Traverse from depth lists.
  549. // Be sure to check against the reference
  550. // implementation when making changes.
  551. _create_depth_lists();
  552. for (uint32_t d = 0; d < data.scene_tree_depth_limit; d++) {
  553. const LocalVector<Node3D *> &list = data.dirty_node_depth_lists[d];
  554. #if 0
  555. if (list.size() > 0) {
  556. print_line("depth " + itos(d) + ", contains " + itos(list.size()));
  557. }
  558. #endif
  559. for (uint32_t n = 0; n < list.size(); n++) {
  560. // Already processed this frame?
  561. Node3D *s = list[n];
  562. if (s->data.fti_processed) {
  563. #ifdef DEBUG_ENABLED
  564. skipped++;
  565. #endif
  566. continue;
  567. }
  568. // The first node requires a recursive visibility check
  569. // up the tree, because `is_visible()` only returns the node
  570. // local flag.
  571. if (Object::cast_to<VisualInstance3D>(s)) {
  572. if (!s->_is_vi_visible()) {
  573. #ifdef DEBUG_ENABLED
  574. skipped++;
  575. #endif
  576. continue;
  577. }
  578. } else if (!s->is_visible_in_tree()) {
  579. #ifdef DEBUG_ENABLED
  580. skipped++;
  581. #endif
  582. continue;
  583. }
  584. _update_dirty_nodes(s, half_frame, interpolation_fraction, true);
  585. }
  586. }
  587. _clear_depth_lists();
  588. }
  589. if (print_debug_stats) {
  590. uint64_t after = OS::get_singleton()->get_ticks_usec();
  591. 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)"));
  592. }
  593. #endif // not GODOT_SCENE_TREE_FTI_VERIFY
  594. // In theory we could clear the `force_update` flags from the nodes in the traversal.
  595. // The problem is that hidden nodes are not recursed into, therefore the flags would
  596. // never get cleared and could get out of sync with the forced list.
  597. // So instead we are clearing them here manually.
  598. // This is not ideal in terms of cache coherence so perhaps another method can be
  599. // explored in future.
  600. uint32_t forced_list_size = data.frame_xform_list_forced.size();
  601. for (uint32_t n = 0; n < forced_list_size; n++) {
  602. Node3D *s = data.frame_xform_list_forced[n];
  603. s->data.fti_frame_xform_force_update = false;
  604. }
  605. data.frame_xform_list_forced.clear();
  606. if (!p_frame_start && data.periodic_debug_log) {
  607. data.periodic_debug_log = false;
  608. }
  609. // Update the properties once off at the end of the frame.
  610. // No need for two passes for properties.
  611. if (!p_frame_start) {
  612. for (uint32_t n = 0; n < data.frame_property_list.size(); n++) {
  613. Node3D *s = data.frame_property_list[n];
  614. s->fti_update_servers_property();
  615. }
  616. }
  617. // Marks the end of the frame.
  618. // Enables us to recognize when change notifications
  619. // come in _during_ a frame (they get treated differently).
  620. if (!data.frame_start) {
  621. data.in_frame = false;
  622. }
  623. }
  624. SceneTreeFTI::SceneTreeFTI() {
  625. #ifdef GODOT_SCENE_TREE_FTI_VERIFY
  626. _tests = memnew(SceneTreeFTITests(*this));
  627. #endif
  628. Variant traversal_mode_string = GLOBAL_DEF("physics/3d/physics_interpolation/scene_traversal", "DEFAULT");
  629. ProjectSettings::get_singleton()->set_custom_property_info(PropertyInfo(Variant::STRING, "physics/3d/physics_interpolation/scene_traversal", PROPERTY_HINT_ENUM, "DEFAULT,Legacy,Debug"));
  630. data.traversal_mode = TM_DEFAULT;
  631. if (traversal_mode_string == "Legacy") {
  632. data.traversal_mode = TM_LEGACY;
  633. } else if (traversal_mode_string == "Debug") {
  634. // Don't allow debug mode in final exports,
  635. // it will almost certainly be a mistake.
  636. #ifdef DEBUG_ENABLED
  637. data.traversal_mode = TM_DEBUG;
  638. #else
  639. data.traversal_mode = TM_DEFAULT;
  640. #endif
  641. }
  642. switch (data.traversal_mode) {
  643. default: {
  644. print_verbose("SceneTreeFTI: traversal method DEFAULT");
  645. } break;
  646. case TM_LEGACY: {
  647. print_verbose("SceneTreeFTI: traversal method Legacy");
  648. } break;
  649. case TM_DEBUG: {
  650. print_verbose("SceneTreeFTI: traversal method Debug");
  651. } break;
  652. }
  653. #ifdef GODOT_SCENE_TREE_FTI_EXTRA_CHECKS
  654. print_line("SceneTreeFTI : GODOT_SCENE_TREE_FTI_EXTRA_CHECKS defined");
  655. #endif
  656. #ifdef GODOT_SCENE_TREE_FTI_PRINT_TREE
  657. print_line("SceneTreeFTI : GODOT_SCENE_TREE_FTI_PRINT_TREE defined");
  658. #endif
  659. }
  660. SceneTreeFTI::~SceneTreeFTI() {
  661. #ifdef GODOT_SCENE_TREE_FTI_VERIFY
  662. if (_tests) {
  663. memfree(_tests);
  664. _tests = nullptr;
  665. }
  666. #endif
  667. }
  668. #endif // ndef _3D_DISABLED