switch bevy_xpbd physics engine to 64bit precision

in preparation for enlargement of coordinate system to match real scale
This commit is contained in:
yuni 2024-04-01 16:29:14 +02:00
parent f346624aff
commit 8fbbcc3708
4 changed files with 33 additions and 27 deletions

View file

@ -12,7 +12,7 @@ rust-version = "1.76.0"
[dependencies]
regex = "1"
bevy = { version = "0.13.1", default-features = false, features = ["jpeg", "bevy_asset", "bevy_audio", "bevy_scene", "bevy_winit", "bevy_core_pipeline", "bevy_pbr", "bevy_gltf", "bevy_render", "bevy_text", "bevy_ui", "file_watcher", "multi-threaded", "png", "vorbis", "x11", "tonemapping_luts"]}
bevy_xpbd_3d = { version = "0.4", default-features = false, features = ["3d", "f32", "parry-f32", "parallel", "async-collider"] }
bevy_xpbd_3d = { version = "0.4", default-features = false, features = ["3d", "f64", "parry-f64", "parallel", "async-collider"] }
bevy_embedded_assets = "0.10.2"
[features]

View file

@ -4,6 +4,7 @@ use bevy::window::PrimaryWindow;
use bevy::core_pipeline::bloom::{BloomCompositeMode, BloomSettings};
use bevy::core_pipeline::tonemapping::Tonemapping;
use bevy::transform::TransformSystem;
use bevy::math::DVec3;
use bevy_xpbd_3d::prelude::*;
use crate::{settings, audio, actor};
@ -136,6 +137,7 @@ fn apply_input_to_player(
) {
let dt = time.delta_seconds();
let mut play_thruster_sound = false;
let mut axis_input: DVec3 = DVec3::ZERO;
let window_result = windows.get_single_mut();
let mut focused = true;
@ -145,7 +147,6 @@ fn apply_input_to_player(
if let Ok((player_transform, mut engine, mut angularvelocity, mut v, mut torque)) = q_playercam.get_single_mut() {
// Handle key input
let mut axis_input = Vec3::ZERO;
if focused {
if key_input.pressed(settings.key_forward) {
axis_input.z += 1.2;
@ -168,7 +169,7 @@ fn apply_input_to_player(
if key_input.pressed(settings.key_stop) {
let stop_direction = -v.normalize();
if stop_direction.length_squared() > 0.3 {
axis_input += 1.0 * (player_transform.rotation.inverse() * stop_direction);
axis_input += 1.0 * DVec3::from(player_transform.rotation.inverse() * stop_direction.as_vec3());
}
}
}
@ -177,7 +178,7 @@ fn apply_input_to_player(
// absolute maximum of 1, since every thruster can be used separately. If the forward
// thrusters and the leftward thrusters are active at the same time, then of course the
// total diagonal acceleration is faster than the forward acceleration alone.
axis_input = axis_input.clamp(Vec3::splat(-1.0), Vec3::splat(1.0));
axis_input = axis_input.clamp(DVec3::splat(-1.0), DVec3::splat(1.0));
// Apply movement update
let forward_factor = engine.current_warmup * (if axis_input.z > 0.0 {
@ -187,11 +188,11 @@ fn apply_input_to_player(
});
let right_factor = engine.thrust_sideways * engine.current_warmup;
let up_factor = engine.thrust_sideways * engine.current_warmup;
let factor = Vec3::new(right_factor, up_factor, forward_factor);
let factor = DVec3::new(right_factor as f64, up_factor as f64, forward_factor as f64);
if axis_input.length_squared() > 0.003 {
let acceleration_global = player_transform.rotation * (axis_input * factor);
let mut acceleration_total = actor::ENGINE_SPEED_FACTOR * dt * acceleration_global;
let acceleration_global: DVec3 = DVec3::from(player_transform.rotation * (axis_input * factor).as_vec3());
let mut acceleration_total: DVec3 = (actor::ENGINE_SPEED_FACTOR * dt) as f64 * acceleration_global;
let threshold = 1e-5;
if key_input.pressed(settings.key_stop) {
// Decelerate
@ -248,20 +249,23 @@ fn apply_input_to_player(
}
}
let angular_slowdown = 2.0 - engine.reaction_wheels.powf(0.01).clamp(1.001, 1.1);
let angular_slowdown: f64 = (2.0 - engine.reaction_wheels.powf(0.01).clamp(1.001, 1.1)) as f64;
if pitch_yaw_rot.length_squared() > 0.0001 {
play_reactionwheel_sound = true;
pitch_yaw_rot *= settings.mouse_sensitivity * engine.reaction_wheels;
torque.apply_torque(player_transform.rotation * Vec3::new(
2.0*pitch_yaw_rot[0], pitch_yaw_rot[1], pitch_yaw_rot[2]));
angularvelocity.0 *= angular_slowdown.clamp(0.97, 1.0);
torque.apply_torque(DVec3::from(
player_transform.rotation * Vec3::new(
pitch_yaw_rot[0] * 2.0,
pitch_yaw_rot[1],
pitch_yaw_rot[2])));
angularvelocity.0 *= angular_slowdown.clamp(0.97, 1.0) as f64;
}
else {
if angularvelocity.length_squared() > 0.001 {
angularvelocity.0 *= angular_slowdown;
}
else {
angularvelocity.0 = Vec3::splat(0.0);
angularvelocity.0 = DVec3::splat(0.0);
}
}

View file

@ -2,6 +2,7 @@
extern crate regex;
use bevy::prelude::*;
use bevy_xpbd_3d::prelude::*;
use bevy::math::DVec3;
use crate::{actor, nature, world};
use regex::Regex;
use std::f32::consts::PI;
@ -37,7 +38,7 @@ struct ParserState {
model: String,
model_scale: f32,
rotation: Quat,
angular_momentum: Vec3,
angular_momentum: DVec3,
pronoun: String,
is_sphere: bool,
is_player: bool,
@ -54,7 +55,7 @@ struct ParserState {
warmup_seconds: f32,
engine_type: actor::EngineType,
oxygen: f32,
mass: f32,
mass: f64,
collider: Collider,
camdistance: f32,
suit_integrity: f32,
@ -87,7 +88,7 @@ impl Default for ParserState {
model: "".to_string(),
model_scale: 1.0,
rotation: Quat::IDENTITY,
angular_momentum: Vec3::new(0.03, 0.3, 0.09),
angular_momentum: DVec3::new(0.03, 0.3, 0.09),
pronoun: "they/them".to_string(),
is_sphere: false,
is_player: false,
@ -285,8 +286,8 @@ pub fn load_defs(
}
["angularmomentum", x, y, z] => {
if let (Ok(x_float), Ok(y_float), Ok(z_float)) =
(x.parse::<f32>(), y.parse::<f32>(), z.parse::<f32>()) {
state.angular_momentum = Vec3::new(x_float, y_float, z_float);
(x.parse::<f64>(), y.parse::<f64>(), z.parse::<f64>()) {
state.angular_momentum = DVec3::new(x_float, y_float, z_float);
}
else {
error!("Can't parse float: {line}");
@ -321,7 +322,7 @@ pub fn load_defs(
}
}
["mass", value] => {
if let Ok(value_float) = value.parse::<f32>() {
if let Ok(value_float) = value.parse::<f64>() {
state.mass = value_float;
}
else {
@ -333,7 +334,7 @@ pub fn load_defs(
state.has_physics = false;
}
["collider", "sphere", radius] => {
if let Ok(radius_float) = radius.parse::<f32>() {
if let Ok(radius_float) = radius.parse::<f64>() {
state.collider = Collider::sphere(radius_float);
}
else {
@ -342,7 +343,7 @@ pub fn load_defs(
}
}
["collider", "capsule", height, radius] => {
if let (Ok(height_float), Ok(radius_float)) = (height.parse::<f32>(), radius.parse::<f32>()) {
if let (Ok(height_float), Ok(radius_float)) = (height.parse::<f64>(), radius.parse::<f64>()) {
state.collider = Collider::capsule(height_float, radius_float);
}
else {
@ -538,10 +539,10 @@ fn spawn_entities(
// Physics Parameters
if state.has_physics {
let fix_scale = 1.0 / state.model_scale.powf(3.0);
let fix_scale: f64 = 1.0 / (state.model_scale as f64).powf(3.0);
actor.insert(RigidBody::Dynamic);
actor.insert(AngularVelocity(state.angular_momentum));
actor.insert(ColliderDensity(state.mass * fix_scale));
actor.insert(ColliderDensity((state.mass * fix_scale) as f64));
if state.collider_is_mesh {
actor.insert(AsyncSceneCollider::new(Some(
ComputedCollider::TriMesh

View file

@ -2,6 +2,7 @@ use crate::{actor, nature, settings};
use bevy::prelude::*;
use bevy::pbr::CascadeShadowConfigBuilder;
use bevy::render::render_resource::{AsBindGroup, ShaderRef};
use bevy::math::DVec3;
use bevy_xpbd_3d::prelude::*;
use std::f32::consts::PI;
@ -33,7 +34,7 @@ impl Plugin for WorldPlugin {
app.add_plugins(PhysicsPlugins::default());
app.add_plugins(MaterialPlugin::<RingMaterial>::default());
//app.add_plugins(PhysicsDebugPlugin::default());
app.insert_resource(Gravity(Vec3::splat(0.0)));
app.insert_resource(Gravity(DVec3::splat(0.0)));
}
}
@ -81,8 +82,8 @@ pub fn setup(
commands.spawn((
actor::Actor::default(),
RigidBody::Dynamic,
AngularVelocity(Vec3::new(0.1, 0.1, 0.03)),
LinearVelocity(Vec3::new(0.0, 0.0, 0.35)),
AngularVelocity(DVec3::new(0.1, 0.1, 0.03)),
LinearVelocity(DVec3::new(0.0, 0.0, 0.35)),
Collider::sphere(1.0),
SceneBundle {
transform: Transform {
@ -203,10 +204,10 @@ fn handle_cheats(
trans.translation = Vec3::new(800000.0, 400000.0, 0.0);
}
if key_input.just_pressed(settings.key_cheat_stop) {
v.0 = Vec3::ZERO;
v.0 = DVec3::ZERO;
}
if key_input.pressed(settings.key_cheat_speed) {
v.0 += trans.rotation * Vec3::new(0.0, 0.0, 1000.0);
v.0 += DVec3::from(trans.rotation * Vec3::new(0.0, 0.0, 1000.0));
}
if key_input.pressed(settings.key_cheat_adrenaline_zero) {
lifeform.adrenaline = 0.0;