Comments (7)
Oh, on second glance, Quat::from_axis_angle
, which is called in Transform::rotate_local_axis
, expects the input vector to be normalized. It looks like our API doesn't explain this, but the first input to rotate_local_axis
is definitely supposed to be a unit vector.
from bevy.
Well, this is a user error that is now solved by #12986, So I'm closing this as completed, feel free to open this again if you see something wrong!
from bevy.
The problem is that the Vec is not normalized. If you have a look at the internal function, it uses a function Quat::from_axis (IIRC) that will panic if you use a denormalized vec. So, to solve this, you just need to normalize your final vec. Now, using Dir3, we will assert that everything is normalized.
from bevy.
Update
Made a few changes, after removing the for
loop on mouse.read()
I don't get the panics anymore.
I don't know if I'm doing something wrong or if this is really a bug !
Here's the new code, I still get the panics when I uncomment the mouse.read()
loop.
use bevy::{
input::{keyboard::KeyboardInput, mouse::MouseMotion, ButtonState},
prelude::*,
};
fn main() {
App::new()
.add_plugins(DefaultPlugins)
.add_plugins(bevy_framepace::FramepacePlugin)
.add_systems(Startup, setup)
.add_systems(Update, update)
.run();
}
fn update(
mut cube: Query<(&mut Player, &mut Transform)>,
mut keys: EventReader<KeyboardInput>,
mut mouse: EventReader<MouseMotion>,
time: Res<Time>,
) {
let mut player = cube.single_mut();
for event in keys.read() {
if event.key_code == KeyCode::KeyR {
match event.state {
ButtonState::Pressed => player.0.move_direction.y = 1.0,
ButtonState::Released => player.0.move_direction.y = 0.0,
}
}
if event.key_code == KeyCode::KeyF {
match event.state {
ButtonState::Pressed => player.0.move_direction.y = -1.0,
ButtonState::Released => player.0.move_direction.y = 0.0,
}
}
if event.key_code == KeyCode::KeyW {
match event.state {
ButtonState::Pressed => player.0.move_direction.z = -1.0,
ButtonState::Released => player.0.move_direction.z = 0.0,
}
}
if event.key_code == KeyCode::KeyS {
match event.state {
ButtonState::Pressed => player.0.move_direction.z = 1.0,
ButtonState::Released => player.0.move_direction.z = 0.0,
}
}
if event.key_code == KeyCode::KeyD {
match event.state {
ButtonState::Pressed => player.0.move_direction.x = 1.0,
ButtonState::Released => player.0.move_direction.x = 0.0,
}
}
if event.key_code == KeyCode::KeyA {
match event.state {
ButtonState::Pressed => player.0.move_direction.x = -1.0,
ButtonState::Released => player.0.move_direction.x = 0.0,
}
}
}
let translation = time.delta_seconds()
* Vec3::new(
player.1.local_x().dot(player.0.move_direction),
player.1.local_y().dot(player.0.move_direction),
player.1.local_z().dot(player.0.move_direction),
);
player.1.translation += translation;
// for event in mouse.read() {
// player
// .1
// .rotate_local_axis(time.delta_seconds() * Vec3::X, event.delta.y);
// player
// .1
// .rotate_local_axis(time.delta_seconds() * Vec3::Y, event.delta.x);
// }
player.1.set_changed();
}
fn setup(
mut framepace: ResMut<bevy_framepace::FramepaceSettings>,
mut commands: Commands,
mut meshes: ResMut<Assets<Mesh>>,
mut materials: ResMut<Assets<StandardMaterial>>,
) {
framepace.limiter = bevy_framepace::Limiter::from_framerate(30.0);
// circular base
commands.spawn(PbrBundle {
mesh: meshes.add(Circle::new(4.0)),
material: materials.add(Color::WHITE),
transform: Transform::from_rotation(Quat::from_rotation_x(-std::f32::consts::FRAC_PI_2)),
..default()
});
// cube
commands.spawn(PbrBundle {
mesh: meshes.add(Cuboid::new(1.0, 1.0, 1.0)),
material: materials.add(Color::rgb_u8(124, 144, 255)),
transform: Transform::from_xyz(0.0, 0.5, 0.0),
..default()
});
// light
commands.spawn(PointLightBundle {
point_light: PointLight {
shadows_enabled: true,
..default()
},
transform: Transform::from_xyz(4.0, 8.0, 4.0),
..default()
});
// camera
commands.spawn((
Player::default(),
Camera3dBundle {
transform: Transform::from_xyz(-2.5, 4.5, 9.0).looking_at(Vec3::ZERO, Vec3::Y),
..default()
},
));
}
#[derive(Default, Component)]
struct Player {
move_direction: Vec3,
}
from bevy.
I haven't looked really deeply into this yet, but I'm guessing this is caused by repeated calls to rotate_local_axis
causing the rotation quaternion to denormalize, since Transform::rotate_local
just multiplies the current rotation quaternion by another one (so errors accumulate).
from bevy.
Thanks guys. One question though, I still didn't get what the cause is.
I'm guessing it's because I wrote time.delta_seconds() * Vec3::X
which is not a unit vector, so in that case will it be fixed by rotate_local_axis(Vec3::X, time.delta_seconds() * event.delta.y)
?
Just wanna make sure I understood correctly.
from bevy.
The problem is that the Vec is not normalized. If you have a look at the internal function, it uses a function Quat::from_axis (IIRC) that will panic if you use a denormalized vec. So, to solve this, you just need to normalize your final vec. Now, using Dir3, we will assert that everything is normalized.
I don't think it actually panics unless glam_assert
is enabled, but it would still cause other weird behaviors which could easily be at the root of the problem (e.g. causing the quaternion to denormalize).
That being said, do try using a normalized vector as input and seeing if the crash still occurs; if it does, you might need to renormalize the rotation quaternion every so often.
from bevy.
Related Issues (20)
- Implement all non-trivial color traits on `Color` type HOT 3
- Please re-export IntoDynamicImageError as public HOT 2
- `[f32; 4]` conversions missing from `bevy_color` HOT 3
- TrackedRenderPass::wgpu_pass may compromize invariants
- Add `bevy-cpal` crate to `bevy-audio` HOT 2
- Fluent builder methods for bevy_reflect ParsedPaths. HOT 1
- duplicate_vertices silently consumes indices HOT 1
- Allow external plugins to intervene more deeply in the rendering process of Sprite (Mesh2d).
- bevy_reflect::List::iter wraps silently on release
- Window despawns during Update schedule
- Bevy can't render default shapes if `bevy_render` has `shader_format_glsl` enabled. HOT 8
- Bevy panics when running empty scene
- Update `ui_test` to 0.23.0
- Make `bevy_time` optionally depend on `bevy_reflect` HOT 1
- Removing image crate from wasm builds
- `PlaneMeshBuilder` should include a configurable amount of subdivision for the mesh HOT 3
- Main branch fails to compile on Rust beta. HOT 2
- Mesh2d improvements tracking issues
- Remove `check-cfg` when Rust 1.80 is released
- `ci setup` command
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from bevy.