center coordinate system of renderer at player camera

this avoids rendering glitches when camera is far away from the center
of the coordinate system.
This commit is contained in:
yuni 2024-04-01 17:19:43 +02:00
parent 8fbbcc3708
commit 5894a2443c
2 changed files with 54 additions and 29 deletions

View file

@ -34,7 +34,7 @@ struct ParserState {
// Actor fields
id: String,
pos: Vec3,
pos: DVec3,
model: String,
model_scale: f32,
rotation: Quat,
@ -84,7 +84,7 @@ impl Default for ParserState {
chat: "".to_string(),
id: "".to_string(),
pos: Vec3::new(0.0, 0.0, 0.0),
pos: DVec3::new(0.0, 0.0, 0.0),
model: "".to_string(),
model_scale: 1.0,
rotation: Quat::IDENTITY,
@ -205,8 +205,8 @@ pub fn load_defs(
state.class = DefClass::Actor;
state.model = model.to_string();
if let (Ok(x_float), Ok(y_float), Ok(z_float)) =
(x.parse::<f32>(), y.parse::<f32>(), z.parse::<f32>()) {
state.pos = Vec3::new(x_float, y_float, z_float);
(x.parse::<f64>(), y.parse::<f64>(), z.parse::<f64>()) {
state.pos = DVec3::new(x_float, y_float, z_float);
}
else {
error!("Can't parse coordinates as floats in def: {line}");
@ -506,6 +506,8 @@ fn spawn_entities(
camdistance: state.camdistance,
..default()
});
actor.insert(Position::from(state.pos));
actor.insert(Rotation::from(state.rotation));
if state.is_sphere {
let sphere_texture_handle: Handle<Image> = asset_server.load(format!("textures/{}.jpg", state.model));
let sphere_handle = meshes.add(Sphere::default().mesh().uv(128, 128));
@ -519,18 +521,16 @@ fn spawn_entities(
mesh: sphere_handle,
material: sphere_material_handle,
transform: Transform {
translation: state.pos,
scale: Vec3::splat(state.model_scale),
rotation: state.rotation,
..default()
},
..default()
});
} else {
actor.insert(SceneBundle {
transform: Transform {
translation: state.pos,
scale: Vec3::splat(state.model_scale),
rotation: state.rotation,
..default()
},
scene: asset_server.load(world::asset_name_to_path(state.model.as_str())),
..default()
@ -582,11 +582,6 @@ fn spawn_entities(
radius: 100.0,
..default()
},
transform: Transform {
translation: state.pos,
scale: Vec3::splat(state.model_scale),
rotation: state.rotation,
},
..default()
});
}

View file

@ -4,6 +4,7 @@ use bevy::pbr::CascadeShadowConfigBuilder;
use bevy::render::render_resource::{AsBindGroup, ShaderRef};
use bevy::math::DVec3;
use bevy_xpbd_3d::prelude::*;
use bevy_xpbd_3d::plugins::sync::SyncConfig;
use std::f32::consts::PI;
const ASTEROID_SIZE: f32 = 100.0;
@ -35,6 +36,14 @@ impl Plugin for WorldPlugin {
app.add_plugins(MaterialPlugin::<RingMaterial>::default());
//app.add_plugins(PhysicsDebugPlugin::default());
app.insert_resource(Gravity(DVec3::splat(0.0)));
// Disable bevy_xpbd's position->transform sync because we have a
// custom syncing function.
app.insert_resource(SyncConfig {
position_to_transform: false,
transform_to_position: false,
});
app.add_systems(PreUpdate, position_to_transform);
}
}
@ -153,17 +162,19 @@ pub fn setup(
// Add shaded ring
let ring_radius = 640000.0;
let jupiter_radius = 200000.0;
commands.spawn(MaterialMeshBundle {
mesh: meshes.add(Mesh::from(Cylinder::new(ring_radius, 1.0))),
transform: Transform::from_xyz(300000.0, -1000.0, 500000.0)
.with_rotation(Quat::from_rotation_z(1f32.to_radians())),
material: materials_custom.add(RingMaterial {
alpha_mode: AlphaMode::Blend,
ring_radius: ring_radius,
jupiter_radius: jupiter_radius,
}),
..default()
});
commands.spawn((
MaterialMeshBundle {
mesh: meshes.add(Mesh::from(Cylinder::new(ring_radius, 1.0))),
material: materials_custom.add(RingMaterial {
alpha_mode: AlphaMode::Blend,
ring_radius: ring_radius,
jupiter_radius: jupiter_radius,
}),
..default()
},
Position::from_xyz(300000.0, -1000.0, 500000.0),
Rotation::from(Quat::from_rotation_z(1f32.to_radians())),
));
// Add Light from the Sun
commands.spawn(DirectionalLightBundle {
@ -185,23 +196,23 @@ pub fn setup(
fn handle_cheats(
key_input: Res<ButtonInput<KeyCode>>,
mut q_player: Query<(&mut Transform, &mut LinearVelocity), With<actor::PlayerCamera>>,
mut q_player: Query<(&Transform, &mut Position, &mut LinearVelocity), With<actor::PlayerCamera>>,
mut q_life: Query<(&mut actor::LifeForm, ), With<actor::Player>>,
settings: ResMut<settings::Settings>,
) {
if !settings.dev_mode || q_player.is_empty() || q_life.is_empty() {
return;
}
let (mut trans, mut v) = q_player.get_single_mut().unwrap();
let (trans, mut pos, mut v) = q_player.get_single_mut().unwrap();
let (mut lifeform, ) = q_life.get_single_mut().unwrap();
if key_input.just_pressed(settings.key_cheat_pizza) {
trans.translation = Vec3::new(-3370.0, 0.0, 0.0);
pos.0 = DVec3::new(-3370.0, 0.0, 0.0);
}
if key_input.just_pressed(settings.key_cheat_farview1) {
trans.translation = Vec3::new(-800000.0, 800000.0, 0.0);
pos.0 = DVec3::new(-800000.0, 800000.0, 0.0);
}
if key_input.just_pressed(settings.key_cheat_farview2) {
trans.translation = Vec3::new(800000.0, 400000.0, 0.0);
pos.0 = DVec3::new(800000.0, 400000.0, 0.0);
}
if key_input.just_pressed(settings.key_cheat_stop) {
v.0 = DVec3::ZERO;
@ -219,3 +230,22 @@ fn handle_cheats(
lifeform.adrenaline = 1.0;
}
}
// A variant of bevy_xpbd_3d::plugins::position_to_transform that adjusts
// the rendering position to center entities at the player camera.
// This avoids rendering glitches when very far away from the origin.
pub fn position_to_transform(
q_player: Query<&Position, With<actor::PlayerCamera>>,
mut q_trans: Query<(&mut Transform, &Position, &Rotation)>,
) {
if let Ok(player_pos) = q_player.get_single() {
for (mut transform, pos, rot) in &mut q_trans {
transform.translation = Vec3::new(
(pos.x - player_pos.x) as f32,
(pos.y - player_pos.y) as f32,
(pos.z - player_pos.z) as f32,
);
transform.rotation = rot.as_quat();
}
}
}