-
Hello, when i try to rotate a simple glb (gltf), default scene exported from blender, around the y axis and move it along the z axis, it starts rotating around itself and around the scene center and then it starts swaying around in weird ways. I've tested this with multiple models i created. Also, it doesnt help to use transform.rotate_local_y or any other type of rotation function, reset the transform to 0,0,0, do rotation and set transform again. Is the transform for gltf scene broken? Please look into this simple test code, taken from https://github.com/bevyengine/bevy/blob/v0.10.1/examples/transforms/3d_rotation.rs and extended with loading a simple cube from blender. What am i doing wrong?: //! Illustrates how to rotate an object around an axis.
use bevy::prelude::*;
use std::f32::consts::TAU;
use std::ops::Add;
// Define a component to designate a rotation speed to an entity.
#[derive(Component)]
struct Rotatable {
speed: f32,
}
#[derive(Component)]
struct MovedScene;
fn main() {
App::new()
.add_plugins(DefaultPlugins)
.add_startup_system(setup)
.add_system(rotate_cube)
.add_system(move_scene_entities)
.add_system(bevy::window::close_on_esc)
.run();
}
fn setup(
mut commands: Commands,
mut meshes: ResMut<Assets<Mesh>>,
mut materials: ResMut<Assets<StandardMaterial>>,
asset_server: Res<AssetServer>,
) {
// Spawn a cube to rotate.
commands.spawn((
PbrBundle {
mesh: meshes.add(Mesh::from(shape::Cube { size: 1.0 })),
material: materials.add(Color::WHITE.into()),
transform: Transform::from_translation(Vec3::ZERO),
..default()
},
Rotatable { speed: 0.3 },
));
// Spawn a camera looking at the entities to show what's happening in this example.
commands.spawn(Camera3dBundle {
transform: Transform::from_xyz(0.0, 5.0, 10.0).looking_at(Vec3::ZERO, Vec3::Y),
..default()
});
commands.spawn((SceneBundle {
scene: asset_server.load("models/untitled.glb#Scene0"),
transform: Transform::from_translation(Vec3{x: 0.0, y: 0.0, z: -5.0}),
..default()
},
MovedScene
));
// Add a light source so we can see clearly.
commands.spawn(PointLightBundle {
transform: Transform::from_translation(Vec3::ONE * 3.0),
..default()
});
}
// This system will rotate any entity in the scene with a Rotatable component around its y-axis.
fn rotate_cube(mut cubes: Query<(&mut Transform, &Rotatable)>, timer: Res<Time>) {
for (mut transform, cube) in &mut cubes {
// The speed is first multiplied by TAU which is a full rotation (360deg) in radians,
// and then multiplied by delta_seconds which is the time that passed last frame.
// In other words. Speed is equal to the amount of rotations per second.
transform.rotate_y(cube.speed * TAU * timer.delta_seconds());
}
}
// This system will move all entities that are descendants of MovedScene (which will be all entities spawned in the scene)
fn move_scene_entities(
time: Res<Time>,
moved_scene: Query<Entity, With<MovedScene>>,
children: Query<&Children>,
mut transforms: Query<&mut Transform, Without<Camera>>,
mut camera_transform: Query<&mut Transform, With<Camera>>,
) {
for moved_scene_entity in &moved_scene {
for entity in children.iter_descendants(moved_scene_entity) {
if let Ok(mut transform) = transforms.get_mut(entity) {
if let Ok(cam_transform) = camera_transform.get_single() {
transform.rotate_y(0.1 * time.delta_seconds());
// transform.translation.x += 0.001;
// transform.translation.y += 0.001;
transform.translation.z -= 0.01;
println!("cam_transform.rotation.normalize().to_axis_angle().0.y: {}", cam_transform.rotation.xyz().y);
println!("transform.translation.x: {}", transform.translation.x);
println!("transform.translation.y: {}", transform.translation.y);
println!("transform.translation.z: {}", transform.translation.z);
println!("transform.rotation.x: {}", transform.rotation.x);
println!("transform.rotation.y: {}", transform.rotation.y);
println!("transform.rotation.z: {}", transform.rotation.z);
println!("camera_transform.translation.x: {}", camera_transform.single().translation.x);
println!("camera_transform.translation.y: {}", camera_transform.single().translation.y);
println!("camera_transform.translation.z: {}", camera_transform.single().translation.z);
println!("camera_transform.rotation.x: {}", camera_transform.single().rotation.x);
println!("camera_transform.rotation.y: {}", camera_transform.single().rotation.y);
println!("camera_transform.rotation.z: {}", camera_transform.single().rotation.z);
}
}
}
}
} |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment 2 replies
-
As you know (given the code). A scene is a hierarchy of entities. In your case, you have:
Remember, your scene has 3 entities, each the child of another. In this code, you rotate all the three entities: for moved_scene_entity in &moved_scene {
for entity in children.iter_descendants(moved_scene_entity) {
if let Ok(mut transform) = transforms.get_mut(entity) {
// here you set the Transform of ALL children of the scene
}
}
} The rotation and movement is accumulated up to the last child. Meaning that the cube will follow the trajectory of a spiral. I'm not sure what you want to do here. If you just want to rotate the scene, don't iterate over all the children, only rotate the scene entity. Remove the inner for entity in &moved_scene {
if let Ok(mut transform) = transforms.get_mut(entity) {
// here you set the Transform of only the parent, which will be propagated to children
}
} Consider a GLTF file more complex than a simple cube. 3d model do have more than a single mesh. In bevy, each mesh is represented as an entity. You want to be able to move the 3d model, as a whole. Not just individual meshes. Imagine if you had to move individually each mesh of a 3d model, sound annoying right? You'll never be able to move characters, weapon, buildings as a whole, you would always have to carefully move each elements individually! This is where the hierarchy is very useful: you just update the Check out the |
Beta Was this translation helpful? Give feedback.
As you know (given the code). A scene is a hierarchy of entities. In your case, you have:
SceneBundle
SceneBundle
entity.Transform
in bevy is inherited and accumulated by children. Meaning that if you rotate the parent, all its children will be rotated. You can see the "actual" transform of an entity by reading theGlobalTransform
component. For example, if the parent has an offset oftranslation = Vec3::Z
, and the child has an offset oftrans…