M crates/unified/assets/config/world.wc.toml => crates/unified/assets/config/world.wc.toml +3 -3
@@ 8,10 8,10 @@ spawn_parts_interval_secs = 1
default_height = 50
default_width = 50
default_mass = 100
-joint_align_compliance = 0.00002
+joint_point_compliance = 0.00002
joint_angle_compliance = 0.000000002
-joint_limit_compliance = 0.0006
-joint_linear_damping = 4.0
+joint_distance_damping = 360.0
+#joint_linear_damping = 0.0
joint_angular_damping = 2.0
[hearty]
M crates/unified/src/config/world.rs => crates/unified/src/config/world.rs +2 -3
@@ 22,10 22,9 @@ pub struct WPartConfig {
pub default_width: f32,
pub default_height: f32,
pub default_mass: f32,
- pub joint_align_compliance: f32,
+ pub joint_point_compliance: f32,
pub joint_angle_compliance: f32,
- pub joint_limit_compliance: f32,
- pub joint_linear_damping: f32,
+ pub joint_distance_damping: f32,
pub joint_angular_damping: f32,
}
A crates/unified/src/server/damping.rs => crates/unified/src/server/damping.rs +76 -0
@@ 0,0 1,76 @@
+use avian2d::{dynamics::{joints::EntityConstraint, solver::{joint_damping, schedule::SubstepSolverSystems, solver_body::{SolverBody, SolverBodyInertia}}}, math::RecipOrZero};
+
+use crate::prelude::*;
+
+pub fn damping_plugin(app: &mut App) {
+ let substeps = app.get_schedule_mut(SubstepSchedule).expect("Add SubstepSchedule first");
+ substeps.add_systems(
+ module_joint_damping::<FixedJoint>
+ .after(joint_damping::<DistanceJoint>) // DistanceJoint is the last damping in vanilla avian
+ .in_set(SubstepSolverSystems::Damping)
+ );
+}
+
+#[derive(Component, Debug, Clone, Copy)]
+pub struct ModuleJointDamping {
+ pub distance: f32,
+ pub angular: f32,
+}
+fn module_joint_damping<T: Component + EntityConstraint<2>>(
+ bodies: Query<(&mut SolverBody, &SolverBodyInertia, &Transform)>,
+ joints: Query<(&T, &ModuleJointDamping)>,
+ time: Res<Time>,
+) {
+ let delta_secs = time.delta_secs();
+
+ let mut dummy_body1 = SolverBody::DUMMY;
+ let mut dummy_body2 = SolverBody::DUMMY;
+
+ for (joint, damping) in &joints {
+ let entities = joint.entities();
+
+ let (mut body1, mut inertia1, mut transform1) = (&mut dummy_body1, &SolverBodyInertia::DUMMY, Transform::default());
+ let (mut body2, mut inertia2, mut transform2) = (&mut dummy_body2, &SolverBodyInertia::DUMMY, Transform::default());
+
+ // Get the solver bodies for the two jointed entities.
+ if let Ok((body, inertia, transform)) = unsafe { bodies.get_unchecked(entities[0]) } {
+ body1 = body.into_inner();
+ inertia1 = inertia;
+ transform1 = *transform;
+ }
+ if let Ok((body, inertia, transform)) = unsafe { bodies.get_unchecked(entities[1]) } {
+ body2 = body.into_inner();
+ inertia2 = inertia;
+ transform2 = *transform;
+ }
+
+ let delta_omega = (body2.angular_velocity - body1.angular_velocity)
+ * (damping.angular * delta_secs).min(1.0);
+
+ if !body1.flags.is_kinematic() {
+ body1.angular_velocity += delta_omega;
+ }
+ if !body2.flags.is_kinematic() {
+ body2.angular_velocity -= delta_omega;
+ }
+
+ let position1 = transform1.translation.truncate() + body1.delta_position;
+ let position2 = transform2.translation.truncate() + body2.delta_position;
+
+ let relative_position = position1 - position2;
+
+ let parallel_velocity1 = body1.linear_velocity.project_onto(relative_position.normalize());
+ let parallel_velocity2 = body2.linear_velocity.project_onto(relative_position.normalize());
+
+ let delta_v = (parallel_velocity2 - parallel_velocity1)
+ * (damping.distance * delta_secs).min(1.0);
+
+ let w1 = inertia1.effective_inv_mass();
+ let w2 = inertia2.effective_inv_mass();
+
+ let p = delta_v * (w1 + w2).recip_or_zero();
+
+ body1.linear_velocity += p * w1;
+ body2.linear_velocity -= p * w2;
+ }
+}
M crates/unified/src/server/mod.rs => crates/unified/src/server/mod.rs +5 -2
@@ 4,11 4,13 @@ mod part;
mod heat;
mod drill;
mod craft;
+mod damping;
pub mod planets;
pub mod player;
mod system_sets;
use crate::server::craft::craft_plugin;
+use crate::server::damping::damping_plugin;
use crate::server::drill::drill_plugin;
use crate::server::earth_parts::spawn_parts_plugin;
use crate::server::gravity::newtonian_gravity_plugin;
@@ 56,11 58,12 @@ impl Plugin for ServerPlugin {
.add_plugins(spawn_parts_plugin)
.add_plugins(part_management_plugin)
.add_plugins(server_thrust_plugin)
- .add_plugins(heat_cooling_plugin)
+ /*.add_plugins(heat_cooling_plugin)
.add_plugins(heat_radiation_plugin)
- .add_plugins(heat_conduction_plugin)
+ .add_plugins(heat_conduction_plugin)*/
.add_plugins(drill_plugin)
.add_plugins(craft_plugin)
+ .add_plugins(damping_plugin)
.configure_sets(Update, WorldUpdateSet.before(PlayerInputSet));
//.configure_sets(Update, PlayerInputSet.before(PhysicsSet::SyncBackend));
}
M crates/unified/src/server/player.rs => crates/unified/src/server/player.rs +12 -4
@@ 3,6 3,7 @@ pub mod thrust;
use crate::attachment::{Joint, JointOf, Joints, PartInShip, Peer, SnapOf, SnapOfJoint};
use crate::ecs::{DragRequestEvent, Part, Player, PlayerStorage};
+use crate::server::damping::ModuleJointDamping;
use crate::server::system_sets::PlayerInputSet;
use crate::server::ConnectedNetworkEntity;
use crate::prelude::*;
@@ 22,6 23,7 @@ pub fn player_management_plugin(app: &mut App) {
.in_set(PlayerInputSet),
);
app.add_systems(Update, complete_partial_disconnects);
+ app.add_systems(FixedUpdate, complete_partial_disconnects);
}
#[derive(Component)]
@@ 349,7 351,7 @@ fn dragging(
);
// create the joint...
- let joint = PrismaticJoint::new(target_part.2, source_part.2)
+ /*let joint = PrismaticJoint::new(target_part.2, source_part.2)
.with_slider_axis(source_joint.2.translation.xy().normalize())
.with_local_anchor1(target_joint.2.translation.xy())
.with_local_basis1(target_joint.0.transform.rotation.to_euler(EulerRot::ZYX).0 + PI
@@ 357,9 359,15 @@ fn dragging(
.with_limits(0.0, 0.0)
.with_align_compliance(world_config.part.joint_align_compliance)
.with_angle_compliance(world_config.part.joint_angle_compliance)
- .with_limit_compliance(world_config.part.joint_limit_compliance);
- let joint_damping = JointDamping {
- linear: world_config.part.joint_linear_damping,
+ .with_limit_compliance(world_config.part.joint_limit_compliance);*/
+ let joint = FixedJoint::new(target_part.2, source_part.2)
+ .with_local_anchor1(target_joint.2.translation.xy())
+ .with_local_basis1(target_joint.0.transform.rotation.to_euler(EulerRot::ZYX).0 + PI
+ - source_joint.0.transform.rotation.to_euler(EulerRot::ZYX).0)
+ .with_point_compliance(world_config.part.joint_point_compliance)
+ .with_angle_compliance(world_config.part.joint_angle_compliance);
+ let joint_damping = ModuleJointDamping {
+ distance: world_config.part.joint_distance_damping,
angular: world_config.part.joint_angular_damping,
};