diff --git a/doc/classes/MultiMesh.xml b/doc/classes/MultiMesh.xml index e99694c3f0a..ae3963d8fab 100644 --- a/doc/classes/MultiMesh.xml +++ b/doc/classes/MultiMesh.xml @@ -59,6 +59,13 @@ This allows you to move instances instantaneously, and should usually be used when initially placing an instance such as a bullet to prevent graphical glitches. + + + + When using [i]physics interpolation[/i], this function allows you to prevent interpolation for all instances in the current physics tick. + This allows you to move all instances instantaneously, and should usually be used when initially placing instances to prevent graphical glitches. + + diff --git a/doc/classes/RenderingServer.xml b/doc/classes/RenderingServer.xml index b3f36e6e00e..5d00eca29e4 100644 --- a/doc/classes/RenderingServer.xml +++ b/doc/classes/RenderingServer.xml @@ -2772,6 +2772,14 @@ Sets the [Transform2D] for this instance. For use when multimesh is used in 2D. Equivalent to [method MultiMesh.set_instance_transform_2d]. + + + + + Prevents physics interpolation for all instances during the current physics tick. + This is useful when moving all instances to new locations, to give instantaneous changes rather than interpolation from the previous locations. + + diff --git a/scene/resources/multimesh.cpp b/scene/resources/multimesh.cpp index 8cf68c1e61d..e3f0e120dd4 100644 --- a/scene/resources/multimesh.cpp +++ b/scene/resources/multimesh.cpp @@ -308,6 +308,10 @@ void MultiMesh::reset_instance_physics_interpolation(int p_instance) { RenderingServer::get_singleton()->multimesh_instance_reset_physics_interpolation(multimesh, p_instance); } +void MultiMesh::reset_instances_physics_interpolation() { + RenderingServer::get_singleton()->multimesh_instances_reset_physics_interpolation(multimesh); +} + void MultiMesh::set_physics_interpolated(bool p_interpolated) { RenderingServer::get_singleton()->multimesh_set_physics_interpolated(multimesh, p_interpolated); } @@ -382,6 +386,7 @@ void MultiMesh::_bind_methods() { ClassDB::bind_method(D_METHOD("set_instance_custom_data", "instance", "custom_data"), &MultiMesh::set_instance_custom_data); ClassDB::bind_method(D_METHOD("get_instance_custom_data", "instance"), &MultiMesh::get_instance_custom_data); ClassDB::bind_method(D_METHOD("reset_instance_physics_interpolation", "instance"), &MultiMesh::reset_instance_physics_interpolation); + ClassDB::bind_method(D_METHOD("reset_instances_physics_interpolation"), &MultiMesh::reset_instances_physics_interpolation); ClassDB::bind_method(D_METHOD("set_custom_aabb", "aabb"), &MultiMesh::set_custom_aabb); ClassDB::bind_method(D_METHOD("get_custom_aabb"), &MultiMesh::get_custom_aabb); ClassDB::bind_method(D_METHOD("get_aabb"), &MultiMesh::get_aabb); diff --git a/scene/resources/multimesh.h b/scene/resources/multimesh.h index 1545b454e63..a486bd6ef2f 100644 --- a/scene/resources/multimesh.h +++ b/scene/resources/multimesh.h @@ -115,6 +115,7 @@ public: Color get_instance_custom_data(int p_instance) const; void reset_instance_physics_interpolation(int p_instance); + void reset_instances_physics_interpolation(); void set_physics_interpolated(bool p_interpolated); diff --git a/servers/rendering/rendering_server.cpp b/servers/rendering/rendering_server.cpp index 8c02698ed5c..62f13bfc975 100644 --- a/servers/rendering/rendering_server.cpp +++ b/servers/rendering/rendering_server.cpp @@ -2543,6 +2543,7 @@ void RenderingServer::_bind_methods() { ClassDB::bind_method(D_METHOD("multimesh_set_physics_interpolated", "multimesh", "interpolated"), &RenderingServer::multimesh_set_physics_interpolated); ClassDB::bind_method(D_METHOD("multimesh_set_physics_interpolation_quality", "multimesh", "quality"), &RenderingServer::multimesh_set_physics_interpolation_quality); ClassDB::bind_method(D_METHOD("multimesh_instance_reset_physics_interpolation", "multimesh", "index"), &RenderingServer::multimesh_instance_reset_physics_interpolation); + ClassDB::bind_method(D_METHOD("multimesh_instances_reset_physics_interpolation", "multimesh"), &RenderingServer::multimesh_instances_reset_physics_interpolation); BIND_ENUM_CONSTANT(MULTIMESH_TRANSFORM_2D); BIND_ENUM_CONSTANT(MULTIMESH_TRANSFORM_3D); diff --git a/servers/rendering/rendering_server.h b/servers/rendering/rendering_server.h index 7fe0d3223c8..23f4b9d0cef 100644 --- a/servers/rendering/rendering_server.h +++ b/servers/rendering/rendering_server.h @@ -514,6 +514,7 @@ public: virtual void multimesh_set_physics_interpolated(RID p_multimesh, bool p_interpolated) = 0; virtual void multimesh_set_physics_interpolation_quality(RID p_multimesh, MultimeshPhysicsInterpolationQuality p_quality) = 0; virtual void multimesh_instance_reset_physics_interpolation(RID p_multimesh, int p_index) = 0; + virtual void multimesh_instances_reset_physics_interpolation(RID p_multimesh) = 0; virtual void multimesh_set_visible_instances(RID p_multimesh, int p_visible) = 0; virtual int multimesh_get_visible_instances(RID p_multimesh) const = 0; diff --git a/servers/rendering/rendering_server_default.h b/servers/rendering/rendering_server_default.h index 62a155a534c..34faef662c4 100644 --- a/servers/rendering/rendering_server_default.h +++ b/servers/rendering/rendering_server_default.h @@ -424,6 +424,7 @@ public: FUNC2(multimesh_set_physics_interpolated, RID, bool) FUNC2(multimesh_set_physics_interpolation_quality, RID, MultimeshPhysicsInterpolationQuality) FUNC2(multimesh_instance_reset_physics_interpolation, RID, int) + FUNC1(multimesh_instances_reset_physics_interpolation, RID) FUNC2(multimesh_set_visible_instances, RID, int) FUNC1RC(int, multimesh_get_visible_instances, RID) diff --git a/servers/rendering/storage/mesh_storage.cpp b/servers/rendering/storage/mesh_storage.cpp index 90f2def408a..c2829813834 100644 --- a/servers/rendering/storage/mesh_storage.cpp +++ b/servers/rendering/storage/mesh_storage.cpp @@ -329,6 +329,17 @@ void RendererMeshStorage::multimesh_instance_reset_physics_interpolation(RID p_m } } +void RendererMeshStorage::multimesh_instances_reset_physics_interpolation(RID p_multimesh) { + MultiMeshInterpolator *mmi = _multimesh_get_interpolator(p_multimesh); + if (mmi && mmi->_data_curr.size()) { + // We don't want to invoke COW here, so copy the data directly. + ERR_FAIL_COND(mmi->_data_prev.size() != mmi->_data_curr.size()); + float *w = mmi->_data_prev.ptrw(); + const float *r = mmi->_data_curr.ptr(); + memcpy(w, r, sizeof(float) * mmi->_data_curr.size()); + } +} + void RendererMeshStorage::multimesh_set_visible_instances(RID p_multimesh, int p_visible) { return _multimesh_set_visible_instances(p_multimesh, p_visible); } diff --git a/servers/rendering/storage/mesh_storage.h b/servers/rendering/storage/mesh_storage.h index 353d4cc9fc8..153750bfbd2 100644 --- a/servers/rendering/storage/mesh_storage.h +++ b/servers/rendering/storage/mesh_storage.h @@ -152,6 +152,7 @@ public: virtual void multimesh_set_physics_interpolated(RID p_multimesh, bool p_interpolated); virtual void multimesh_set_physics_interpolation_quality(RID p_multimesh, RS::MultimeshPhysicsInterpolationQuality p_quality); virtual void multimesh_instance_reset_physics_interpolation(RID p_multimesh, int p_index); + virtual void multimesh_instances_reset_physics_interpolation(RID p_multimesh); virtual void multimesh_set_visible_instances(RID p_multimesh, int p_visible); virtual int multimesh_get_visible_instances(RID p_multimesh) const;