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

View file

@ -4,6 +4,7 @@ use bevy::pbr::CascadeShadowConfigBuilder;
use bevy::render::render_resource::{AsBindGroup, ShaderRef}; use bevy::render::render_resource::{AsBindGroup, ShaderRef};
use bevy::math::DVec3; use bevy::math::DVec3;
use bevy_xpbd_3d::prelude::*; use bevy_xpbd_3d::prelude::*;
use bevy_xpbd_3d::plugins::sync::SyncConfig;
use std::f32::consts::PI; use std::f32::consts::PI;
const ASTEROID_SIZE: f32 = 100.0; const ASTEROID_SIZE: f32 = 100.0;
@ -35,6 +36,14 @@ impl Plugin for WorldPlugin {
app.add_plugins(MaterialPlugin::<RingMaterial>::default()); app.add_plugins(MaterialPlugin::<RingMaterial>::default());
//app.add_plugins(PhysicsDebugPlugin::default()); //app.add_plugins(PhysicsDebugPlugin::default());
app.insert_resource(Gravity(DVec3::splat(0.0))); 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 // Add shaded ring
let ring_radius = 640000.0; let ring_radius = 640000.0;
let jupiter_radius = 200000.0; let jupiter_radius = 200000.0;
commands.spawn(MaterialMeshBundle { commands.spawn((
MaterialMeshBundle {
mesh: meshes.add(Mesh::from(Cylinder::new(ring_radius, 1.0))), 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 { material: materials_custom.add(RingMaterial {
alpha_mode: AlphaMode::Blend, alpha_mode: AlphaMode::Blend,
ring_radius: ring_radius, ring_radius: ring_radius,
jupiter_radius: jupiter_radius, jupiter_radius: jupiter_radius,
}), }),
..default() ..default()
}); },
Position::from_xyz(300000.0, -1000.0, 500000.0),
Rotation::from(Quat::from_rotation_z(1f32.to_radians())),
));
// Add Light from the Sun // Add Light from the Sun
commands.spawn(DirectionalLightBundle { commands.spawn(DirectionalLightBundle {
@ -185,23 +196,23 @@ pub fn setup(
fn handle_cheats( fn handle_cheats(
key_input: Res<ButtonInput<KeyCode>>, 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>>, mut q_life: Query<(&mut actor::LifeForm, ), With<actor::Player>>,
settings: ResMut<settings::Settings>, settings: ResMut<settings::Settings>,
) { ) {
if !settings.dev_mode || q_player.is_empty() || q_life.is_empty() { if !settings.dev_mode || q_player.is_empty() || q_life.is_empty() {
return; 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(); let (mut lifeform, ) = q_life.get_single_mut().unwrap();
if key_input.just_pressed(settings.key_cheat_pizza) { 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) { 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) { 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) { if key_input.just_pressed(settings.key_cheat_stop) {
v.0 = DVec3::ZERO; v.0 = DVec3::ZERO;
@ -219,3 +230,22 @@ fn handle_cheats(
lifeform.adrenaline = 1.0; 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();
}
}
}