Path: blob/master/scene/main/scene_tree_fti_tests.cpp
9896 views
/**************************************************************************/1/* scene_tree_fti_tests.cpp */2/**************************************************************************/3/* This file is part of: */4/* GODOT ENGINE */5/* https://godotengine.org */6/**************************************************************************/7/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */8/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */9/* */10/* Permission is hereby granted, free of charge, to any person obtaining */11/* a copy of this software and associated documentation files (the */12/* "Software"), to deal in the Software without restriction, including */13/* without limitation the rights to use, copy, modify, merge, publish, */14/* distribute, sublicense, and/or sell copies of the Software, and to */15/* permit persons to whom the Software is furnished to do so, subject to */16/* the following conditions: */17/* */18/* The above copyright notice and this permission notice shall be */19/* included in all copies or substantial portions of the Software. */20/* */21/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */22/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */23/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */24/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */25/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */26/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */27/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */28/**************************************************************************/2930#ifndef _3D_DISABLED3132#ifdef GODOT_SCENE_TREE_FTI_VERIFY33#include "scene_tree_fti_tests.h"3435#include "scene/3d/node_3d.h"36#include "scene/3d/visual_instance_3d.h"37#include "scene/main/scene_tree_fti.h"3839void SceneTreeFTITests::debug_verify_failed(const Node3D *p_node_3d, const Transform3D &p_test) {40print_line("VERIFY FAILED\n");41print_line("test xform : " + String(Variant(p_test)));4243bool first = true;4445while (p_node_3d) {46int32_t depth = MAX(p_node_3d->_get_scene_tree_depth(), 0);47String tabs;48for (int32_t n = 0; n < depth; n++) {49tabs += "\t";50}5152bool interp_equal = p_node_3d->_get_cached_global_transform_interpolated() == p_test;53bool glob_equal = p_node_3d->get_global_transform() == p_test;5455String sz = tabs + p_node_3d->get_name() + " [ " + p_node_3d->get_class_name() + " ]\n";5657if (first) {58sz += tabs + "... " + String(Variant(p_test)) + "\n";59}6061sz += tabs + (p_node_3d->data.fti_global_xform_interp_set ? "[I] " : "[i] ") + String(Variant(p_node_3d->_get_cached_global_transform_interpolated())) + (interp_equal ? " ***" : "") + "\n";62sz += tabs + "[g] " + String(Variant(p_node_3d->get_global_transform())) + (glob_equal ? " ***" : "");6364print_line(sz);6566p_node_3d = p_node_3d->get_parent_node_3d();67first = false;68}69}7071void SceneTreeFTITests::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) {72SceneTreeFTI::Data &data = _fti.data;7374// There are two runs going on here.75// FIRST the naive entire scene tree (reference), where we are76// setting state (i.e. writing out xforms, and other state)77// SECOND the optimized run, where we are NOT78// writing state, but only verifying that the xforms calculated79// match those from the reference approach.80bool should_verify = (data.traversal_mode == SceneTreeFTI::TM_DEBUG) && data.use_optimized_traversal_method;81bool set_state = !should_verify;8283Node3D *s = Object::cast_to<Node3D>(p_node);8485if (s && !s->is_visible()) {86return;87}8889if (!s) {90for (int n = 0; n < p_node->get_child_count(); n++) {91update_dirty_nodes(p_node->get_child(n), p_current_half_frame, p_interpolation_fraction, p_active, nullptr, p_depth + 1);92}93return;94}9596if (s->_test_dirty_bits(Node3D::DIRTY_GLOBAL_TRANSFORM)) {97_ALLOW_DISCARD_ s->get_global_transform();98}99100if (!p_active) {101if (data.frame_start) {102if (s->data.fti_on_frame_xform_list || s->data.fti_frame_xform_force_update) {103p_active = true;104}105} else {106if (s->_test_dirty_bits(Node3D::DIRTY_GLOBAL_INTERPOLATED_TRANSFORM)) {107p_active = true;108}109}110}111112if (data.frame_start) {113s->data.fti_global_xform_interp_set = p_active;114}115116if (p_active) {117Transform3D local_interp;118if (s->is_physics_interpolated()) {119if (s->data.fti_on_tick_xform_list) {120TransformInterpolator::interpolate_transform_3d(s->data.local_transform_prev, s->get_transform(), local_interp, p_interpolation_fraction);121} else {122local_interp = s->get_transform();123}124} else {125local_interp = s->get_transform();126}127128if (!s->is_set_as_top_level()) {129if (p_parent_global_xform) {130if (should_verify) {131Transform3D test = (*p_parent_global_xform) * local_interp;132if (s->data.disable_scale) {133test.basis.orthonormalize();134}135if (s->data.global_transform_interpolated != test) {136debug_verify_failed(s, test);137DEV_ASSERT(s->data.global_transform_interpolated == test);138}139} else {140s->data.global_transform_interpolated = s->data.fti_is_identity_xform ? (*p_parent_global_xform) : (*p_parent_global_xform) * local_interp;141}142} else {143const Node3D *parent = s->get_parent_node_3d();144145if (parent) {146const Transform3D &parent_glob = parent->data.fti_global_xform_interp_set ? parent->data.global_transform_interpolated : parent->get_global_transform();147148if (should_verify) {149Transform3D test = parent_glob * local_interp;150if (s->data.disable_scale) {151test.basis.orthonormalize();152}153if (s->data.global_transform_interpolated != test) {154debug_verify_failed(s, test);155DEV_ASSERT(s->data.global_transform_interpolated == test);156}157158} else {159s->data.global_transform_interpolated = s->data.fti_is_identity_xform ? parent_glob : parent_glob * local_interp;160}161} else {162if (set_state) {163s->data.global_transform_interpolated = local_interp;164}165}166}167} else {168if (set_state) {169s->data.global_transform_interpolated = local_interp;170}171}172173if (set_state) {174if (s->data.disable_scale) {175s->data.global_transform_interpolated.basis.orthonormalize();176}177178s->fti_update_servers_xform();179180s->data.fti_frame_xform_force_update = false;181}182183s->data.fti_processed = true;184} // if active.185186if (set_state) {187s->_clear_dirty_bits(Node3D::DIRTY_GLOBAL_INTERPOLATED_TRANSFORM);188}189190for (int n = 0; n < p_node->get_child_count(); n++) {191update_dirty_nodes(p_node->get_child(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);192}193}194195void SceneTreeFTITests::frame_update(Node *p_root, uint32_t p_half_frame, float p_interpolation_fraction) {196SceneTreeFTI::Data &data = _fti.data;197198// For testing, use both methods.199// FIRST the entire tree, writing out state.200{201data.use_optimized_traversal_method = false;202update_dirty_nodes(p_root, p_half_frame, p_interpolation_fraction, false);203}204205// SECOND the optimized depth lists only,206// no writing of state, and verifying results.207{208data.use_optimized_traversal_method = true;209210_fti._create_depth_lists();211212for (uint32_t d = 0; d < data.scene_tree_depth_limit; d++) {213const LocalVector<Node3D *> &list = data.dirty_node_depth_lists[d];214215for (uint32_t n = 0; n < list.size(); n++) {216Node3D *s = list[n];217218if (s->data.fti_processed) {219continue;220}221222if (Object::cast_to<VisualInstance3D>(s)) {223if (!s->_is_vi_visible()) {224continue;225}226} else if (!s->is_visible_in_tree()) {227continue;228}229230update_dirty_nodes(s, p_half_frame, p_interpolation_fraction, true);231}232}233234_fti._clear_depth_lists();235}236}237238SceneTreeFTITests::SceneTreeFTITests(SceneTreeFTI &p_fti) :239_fti(p_fti) {240print_line("SceneTreeFTI : GODOT_SCENE_TREE_FTI_VERIFY defined");241}242243#endif // def GODOT_SCENE_TREE_FTI_VERIFY244245#endif // ndef _3D_DISABLED246247248