Merge pull request #45583 from lawnjelly/optimize_transform_propagate

Optimize transform propagation for hidden 3d objects
This commit is contained in:
Rémi Verschelde 2021-02-06 12:23:52 +01:00 committed by GitHub
commit f05e068d6c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 54 additions and 10 deletions

View file

@ -246,10 +246,7 @@ void Spatial::set_transform(const Transform &p_transform) {
void Spatial::set_global_transform(const Transform &p_transform) {
Transform xform =
(data.parent && !data.toplevel_active) ?
data.parent->get_global_transform().affine_inverse() * p_transform :
p_transform;
Transform xform = (data.parent && !data.toplevel_active) ? data.parent->get_global_transform().affine_inverse() * p_transform : p_transform;
set_transform(xform);
}
@ -541,8 +538,9 @@ void Spatial::show() {
data.visible = true;
if (!is_inside_tree())
if (!is_inside_tree()) {
return;
}
_propagate_visibility_changed();
}
@ -554,8 +552,9 @@ void Spatial::hide() {
data.visible = false;
if (!is_inside_tree())
if (!is_inside_tree()) {
return;
}
_propagate_visibility_changed();
}
@ -834,6 +833,8 @@ Spatial::Spatial() :
data.visible = true;
data.disable_scale = false;
data.spatial_flags = SPATIAL_FLAG_VI_VISIBLE;
#ifdef TOOLS_ENABLED
data.gizmo_disabled = false;
data.gizmo_dirty = false;

View file

@ -54,6 +54,15 @@ class Spatial : public Node {
GDCLASS(Spatial, Node);
OBJ_CATEGORY("3D");
public:
enum SpatialFlags {
// this is cached, and only currently kept up to date in visual instances
// this is set if a visual instance is
// (a) in the tree AND (b) visible via is_visible_in_tree() call
SPATIAL_FLAG_VI_VISIBLE = 1 << 0,
};
private:
enum TransformDirty {
DIRTY_NONE = 0,
DIRTY_VECTORS = 1,
@ -65,6 +74,9 @@ class Spatial : public Node {
struct Data {
// defined in Spatial::SpatialFlags
uint32_t spatial_flags;
mutable Transform global_transform;
mutable Transform local_transform;
mutable Vector3 rotation;
@ -109,6 +121,16 @@ protected:
_FORCE_INLINE_ void _update_local_transform() const;
uint32_t _get_spatial_flags() const { return data.spatial_flags; }
void _replace_spatial_flags(uint32_t p_flags) { data.spatial_flags = p_flags; }
void _set_spatial_flag(uint32_t p_flag, bool p_set) {
if (p_set) {
data.spatial_flags |= p_flag;
} else {
data.spatial_flags &= ~p_flag;
}
}
void _notification(int p_what);
static void _bind_methods();

View file

@ -41,11 +41,26 @@ AABB VisualInstance::get_transformed_aabb() const {
void VisualInstance::_update_visibility() {
if (!is_inside_tree())
if (!is_inside_tree()) {
return;
}
bool visible = is_visible_in_tree();
// keep a quick flag available in each node.
// no need to call is_visible_in_tree all over the place,
// providing it is propagated with a notification.
bool already_visible = (_get_spatial_flags() & SPATIAL_FLAG_VI_VISIBLE) != 0;
_set_spatial_flag(SPATIAL_FLAG_VI_VISIBLE, visible);
// if making visible, make sure the visual server is up to date with the transform
if (visible && (!already_visible)) {
Transform gt = get_global_transform();
VisualServer::get_singleton()->instance_set_transform(instance, gt);
}
_change_notify("visible");
VS::get_singleton()->instance_set_visible(get_instance(), is_visible_in_tree());
VS::get_singleton()->instance_set_visible(get_instance(), visible);
}
void VisualInstance::_notification(int p_what) {
@ -67,8 +82,10 @@ void VisualInstance::_notification(int p_what) {
} break;
case NOTIFICATION_TRANSFORM_CHANGED: {
Transform gt = get_global_transform();
VisualServer::get_singleton()->instance_set_transform(instance, gt);
if (_get_spatial_flags() & SPATIAL_FLAG_VI_VISIBLE) {
Transform gt = get_global_transform();
VisualServer::get_singleton()->instance_set_transform(instance, gt);
}
} break;
case NOTIFICATION_EXIT_WORLD: {
@ -76,6 +93,10 @@ void VisualInstance::_notification(int p_what) {
VisualServer::get_singleton()->instance_attach_skeleton(instance, RID());
//VS::get_singleton()->instance_geometry_set_baked_light_sampler(instance, RID() );
// the vi visible flag is always set to invisible when outside the tree,
// so it can detect re-entering the tree and becoming visible, and send
// the transform to the visual server
_set_spatial_flag(SPATIAL_FLAG_VI_VISIBLE, false);
} break;
case NOTIFICATION_VISIBILITY_CHANGED: {