@@ -53,13 +53,16 @@ void SoftBodyRenderingServerHandler::prepare(RID p_mesh, int p_surface) {
53
53
RS::get_singleton ()->mesh_surface_make_offsets_from_format (surface_data.format , surface_data.vertex_count , surface_data.index_count , surface_offsets, vertex_stride, normal_tangent_stride, attrib_stride, skin_stride);
54
54
55
55
buffer = surface_data.vertex_data ;
56
+ vertex_count = surface_data.vertex_count ;
56
57
stride = vertex_stride;
57
58
normal_stride = normal_tangent_stride;
58
59
offset_vertices = surface_offsets[RS::ARRAY_VERTEX];
59
60
offset_normal = surface_offsets[RS::ARRAY_NORMAL];
60
61
}
61
62
62
63
void SoftBodyRenderingServerHandler::clear () {
64
+ aabb_prev = AABB ();
65
+ buffer_prev.resize (0 );
63
66
buffer.resize (0 );
64
67
stride = 0 ;
65
68
normal_stride = 0 ;
@@ -78,8 +81,48 @@ void SoftBodyRenderingServerHandler::close() {
78
81
write_buffer = nullptr ;
79
82
}
80
83
81
- void SoftBodyRenderingServerHandler::commit_changes () {
82
- RS::get_singleton ()->mesh_surface_update_vertex_region (mesh, surface, 0 , buffer);
84
+ void SoftBodyRenderingServerHandler::fti_pump () {
85
+ buffer_prev = buffer;
86
+ aabb_prev = aabb;
87
+ }
88
+
89
+ void SoftBodyRenderingServerHandler::commit_changes (real_t p_interpolation_fraction) {
90
+ real_t f = p_interpolation_fraction;
91
+ Vector<uint8_t > buffer_interp = buffer;
92
+ AABB aabb_interp = aabb;
93
+
94
+ if (p_interpolation_fraction < 1 ) {
95
+ // AABB.
96
+ aabb_interp = AABB (aabb_prev.position .lerp (aabb.position , f), aabb_prev.size .lerp (aabb.size , f));
97
+
98
+ for (uint32_t i = 0 ; i < vertex_count; i++) {
99
+ // Vertex.
100
+ float *vertex_buffer_prev = reinterpret_cast <float *>(buffer_prev.ptrw () + i * stride + offset_vertices);
101
+ float *vertex_buffer_interp = reinterpret_cast <float *>(buffer_interp.ptrw () + i * stride + offset_vertices);
102
+
103
+ *vertex_buffer_interp = Math::lerp (*vertex_buffer_prev, *vertex_buffer_interp, (float )f);
104
+ vertex_buffer_interp++;
105
+ vertex_buffer_prev++;
106
+ *vertex_buffer_interp = Math::lerp (*vertex_buffer_prev, *vertex_buffer_interp, (float )f);
107
+ vertex_buffer_interp++;
108
+ vertex_buffer_prev++;
109
+ *vertex_buffer_interp = Math::lerp (*vertex_buffer_prev, *vertex_buffer_interp, (float )f);
110
+
111
+ // Normal.
112
+ uint32_t *normal_buffer_prev = reinterpret_cast <uint32_t *>(buffer_prev.ptrw () + i * normal_stride + offset_normal);
113
+ uint32_t *normal_buffer_interp = reinterpret_cast <uint32_t *>(buffer_interp.ptrw () + i * normal_stride + offset_normal);
114
+ Vector2 prev = Vector2 ((normal_buffer_prev[0 ] & 0xffff ) / 65535 .0f , (normal_buffer_prev[0 ] >> 16 ) / 65535 .0f );
115
+ Vector2 curr = Vector2 ((normal_buffer_interp[0 ] & 0xffff ) / 65535 .0f , (normal_buffer_prev[0 ] >> 16 ) / 65535 .0f );
116
+ Vector2 interp = Vector3::octahedron_decode (prev).lerp (Vector3::octahedron_decode (curr), f).octahedron_encode ();
117
+ uint32_t value = 0 ;
118
+ value |= (uint16_t )CLAMP (interp.x * 65535 , 0 , 65535 );
119
+ value |= (uint16_t )CLAMP (interp.y * 65535 , 0 , 65535 ) << 16 ;
120
+ normal_buffer_interp[0 ] = value;
121
+ }
122
+ }
123
+
124
+ RS::get_singleton ()->mesh_set_custom_aabb (mesh, aabb_interp);
125
+ RS::get_singleton ()->mesh_surface_update_vertex_region (mesh, surface, 0 , buffer_interp);
83
126
}
84
127
85
128
void SoftBodyRenderingServerHandler::set_vertex (int p_vertex_id, const Vector3 &p_vertex) {
@@ -98,7 +141,7 @@ void SoftBodyRenderingServerHandler::set_normal(int p_vertex_id, const Vector3 &
98
141
}
99
142
100
143
void SoftBodyRenderingServerHandler::set_aabb (const AABB &p_aabb) {
101
- RS::get_singleton ()-> mesh_set_custom_aabb (mesh, p_aabb) ;
144
+ aabb = p_aabb;
102
145
}
103
146
104
147
SoftBody3D::PinnedPoint::PinnedPoint () {
@@ -274,7 +317,16 @@ void SoftBody3D::_notification(int p_what) {
274
317
PhysicsServer3D::get_singleton ()->soft_body_set_space (physics_rid, space);
275
318
_prepare_physics_server ();
276
319
} break ;
277
-
320
+ case NOTIFICATION_INTERNAL_PROCESS: {
321
+ if (is_inside_tree ()) {
322
+ _commit_soft_mesh (is_physics_interpolated_and_enabled () ? Engine::get_singleton ()->get_physics_interpolation_fraction () : 1 );
323
+ }
324
+ } break ;
325
+ case NOTIFICATION_INTERNAL_PHYSICS_PROCESS: {
326
+ if (is_inside_tree ()) {
327
+ _update_soft_mesh ();
328
+ }
329
+ } break ;
278
330
case NOTIFICATION_READY: {
279
331
if (!parent_collision_ignore.is_empty ()) {
280
332
add_collision_exception_with (get_node (parent_collision_ignore));
@@ -295,7 +347,11 @@ void SoftBody3D::_notification(int p_what) {
295
347
set_transform (Transform3D ());
296
348
set_notify_transform (true );
297
349
} break ;
298
-
350
+ case NOTIFICATION_RESET_PHYSICS_INTERPOLATION: {
351
+ if (mesh.is_valid () && rendering_server_handler->is_ready (mesh->get_rid ())) {
352
+ rendering_server_handler->fti_pump ();
353
+ }
354
+ } break ;
299
355
case NOTIFICATION_VISIBILITY_CHANGED: {
300
356
_update_pickable ();
301
357
} break ;
@@ -394,6 +450,13 @@ void SoftBody3D::_bind_methods() {
394
450
BIND_ENUM_CONSTANT (DISABLE_MODE_KEEP_ACTIVE);
395
451
}
396
452
453
+ void SoftBody3D::_physics_interpolated_changed () {
454
+ if (mesh.is_valid () && rendering_server_handler->is_ready (mesh->get_rid ())) {
455
+ rendering_server_handler->fti_pump ();
456
+ }
457
+ MeshInstance3D::_physics_interpolated_changed ();
458
+ }
459
+
397
460
PackedStringArray SoftBody3D::get_configuration_warnings () const {
398
461
PackedStringArray warnings = MeshInstance3D::get_configuration_warnings ();
399
462
@@ -420,7 +483,7 @@ void SoftBody3D::_update_physics_server() {
420
483
}
421
484
}
422
485
423
- void SoftBody3D::_draw_soft_mesh () {
486
+ void SoftBody3D::_update_soft_mesh () {
424
487
if (mesh.is_null ()) {
425
488
return ;
426
489
}
@@ -443,11 +506,18 @@ void SoftBody3D::_draw_soft_mesh() {
443
506
444
507
_update_physics_server ();
445
508
509
+ if (is_physics_interpolated_and_enabled ()) {
510
+ rendering_server_handler->fti_pump ();
511
+ }
446
512
rendering_server_handler->open ();
447
513
PhysicsServer3D::get_singleton ()->soft_body_update_rendering_server (physics_rid, rendering_server_handler);
448
514
rendering_server_handler->close ();
515
+ }
449
516
450
- rendering_server_handler->commit_changes ();
517
+ void SoftBody3D::_commit_soft_mesh (real_t p_interpolation_fraction) {
518
+ if (mesh.is_valid () && rendering_server_handler->is_ready (mesh->get_rid ())) {
519
+ rendering_server_handler->commit_changes (p_interpolation_fraction);
520
+ }
451
521
}
452
522
453
523
void SoftBody3D::_prepare_physics_server () {
@@ -470,12 +540,12 @@ void SoftBody3D::_prepare_physics_server() {
470
540
mesh_rid = mesh->get_rid ();
471
541
}
472
542
PhysicsServer3D::get_singleton ()->soft_body_set_mesh (physics_rid, mesh_rid);
473
- RS::get_singleton ()->connect (" frame_pre_draw" , callable_mp (this , &SoftBody3D::_draw_soft_mesh));
543
+ set_process_internal (true );
544
+ set_physics_process_internal (true );
474
545
} else {
475
546
PhysicsServer3D::get_singleton ()->soft_body_set_mesh (physics_rid, RID ());
476
- if (RS::get_singleton ()->is_connected (" frame_pre_draw" , callable_mp (this , &SoftBody3D::_draw_soft_mesh))) {
477
- RS::get_singleton ()->disconnect (" frame_pre_draw" , callable_mp (this , &SoftBody3D::_draw_soft_mesh));
478
- }
547
+ set_process_internal (false );
548
+ set_physics_process_internal (false );
479
549
}
480
550
}
481
551
0 commit comments