Migrated to bevy 0.9
This commit is contained in:
parent
b695fac4bb
commit
927910bf63
|
@ -4,3 +4,7 @@
|
||||||
# Version 0.1.1
|
# Version 0.1.1
|
||||||
- Fixed build issue when using the debug_lines feature
|
- Fixed build issue when using the debug_lines feature
|
||||||
- Fixed transforms giong to NaN when an exact match is found
|
- Fixed transforms giong to NaN when an exact match is found
|
||||||
|
|
||||||
|
# Version 0.2.0
|
||||||
|
- Migrated to bevy 0.9
|
||||||
|
- Removed debug_lines feature, to not have a third party bevy dependency.
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
[package]
|
[package]
|
||||||
name = "bevy_mod_inverse_kinematics"
|
name = "bevy_mod_inverse_kinematics"
|
||||||
version = "0.1.1"
|
version = "0.2.0"
|
||||||
authors = ["Bram Buurlage <brambuurlage@gmail.com>"]
|
authors = ["Bram Buurlage <brambuurlage@gmail.com>"]
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
categories = ["game-engines", "graphics", "rendering"]
|
categories = ["game-engines", "graphics", "rendering"]
|
||||||
|
@ -10,8 +10,8 @@ keywords = ["gamedev", "graphics", "bevy", "animation"]
|
||||||
license = "MIT OR Apache-2.0"
|
license = "MIT OR Apache-2.0"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
bevy = "0.8.1"
|
bevy = "0.9.0"
|
||||||
bevy_prototype_debug_lines = { version = "0.8.1", features = ["3d"], optional = true }
|
#bevy_prototype_debug_lines = { version = "0.9.1", features = ["3d"], optional = true }
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
debug_lines = ["bevy_prototype_debug_lines"]
|
#debug_lines = ["bevy_prototype_debug_lines"]
|
|
@ -14,6 +14,7 @@ I intend to track the latest releases of Bevy.
|
||||||
| bevy | bevy_mod_inverse_kinematics |
|
| bevy | bevy_mod_inverse_kinematics |
|
||||||
| ----- | --------------------------- |
|
| ----- | --------------------------- |
|
||||||
| 0.8.1 | 0.1 |
|
| 0.8.1 | 0.1 |
|
||||||
|
| 0.9.0 | 0.2 |
|
||||||
|
|
||||||
## Examples
|
## Examples
|
||||||
|
|
||||||
|
@ -23,11 +24,6 @@ Have the right arm of a skinned mesh follow the mouse cursor:
|
||||||
cargo run --example skin_mesh
|
cargo run --example skin_mesh
|
||||||
```
|
```
|
||||||
|
|
||||||
Turn on the debug_lines feature to see how the bone rotations are calculated:
|
|
||||||
```shell
|
|
||||||
cargo run --example skin_mesh --features debug_lines
|
|
||||||
```
|
|
||||||
|
|
||||||
## Licensing
|
## Licensing
|
||||||
|
|
||||||
This project is dual-licensed under either
|
This project is dual-licensed under either
|
||||||
|
|
|
@ -6,12 +6,14 @@ pub struct ManuallyTarget(Vec4);
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
App::new()
|
App::new()
|
||||||
.insert_resource(WindowDescriptor {
|
.add_plugins(DefaultPlugins.set(WindowPlugin {
|
||||||
|
window: WindowDescriptor {
|
||||||
width: 800.0,
|
width: 800.0,
|
||||||
height: 600.0,
|
height: 600.0,
|
||||||
..default()
|
..default()
|
||||||
})
|
},
|
||||||
.add_plugins(DefaultPlugins)
|
..default()
|
||||||
|
}))
|
||||||
.add_plugin(InverseKinematicsPlugin)
|
.add_plugin(InverseKinematicsPlugin)
|
||||||
.add_startup_system(setup)
|
.add_startup_system(setup)
|
||||||
.add_system(setup_ik)
|
.add_system(setup_ik)
|
||||||
|
@ -26,9 +28,9 @@ fn setup(
|
||||||
mut materials: ResMut<Assets<StandardMaterial>>,
|
mut materials: ResMut<Assets<StandardMaterial>>,
|
||||||
) {
|
) {
|
||||||
commands
|
commands
|
||||||
.spawn_bundle(SpatialBundle::default())
|
.spawn(SpatialBundle::default())
|
||||||
.with_children(|parent| {
|
.with_children(|parent| {
|
||||||
parent.spawn_bundle(Camera3dBundle {
|
parent.spawn(Camera3dBundle {
|
||||||
transform: Transform::from_xyz(-0.5, 1.5, 2.5)
|
transform: Transform::from_xyz(-0.5, 1.5, 2.5)
|
||||||
.looking_at(Vec3::new(0.0, 1.0, 0.0), Vec3::Y),
|
.looking_at(Vec3::new(0.0, 1.0, 0.0), Vec3::Y),
|
||||||
projection: bevy::render::camera::Projection::Perspective(PerspectiveProjection {
|
projection: bevy::render::camera::Projection::Perspective(PerspectiveProjection {
|
||||||
|
@ -42,7 +44,7 @@ fn setup(
|
||||||
});
|
});
|
||||||
|
|
||||||
let size = 30.0;
|
let size = 30.0;
|
||||||
commands.spawn_bundle(DirectionalLightBundle {
|
commands.spawn(DirectionalLightBundle {
|
||||||
directional_light: DirectionalLight {
|
directional_light: DirectionalLight {
|
||||||
color: Color::WHITE,
|
color: Color::WHITE,
|
||||||
illuminance: 10000.0,
|
illuminance: 10000.0,
|
||||||
|
@ -62,7 +64,7 @@ fn setup(
|
||||||
..default()
|
..default()
|
||||||
});
|
});
|
||||||
|
|
||||||
commands.spawn_bundle(PbrBundle {
|
commands.spawn(PbrBundle {
|
||||||
mesh: meshes.add(Mesh::from(shape::Plane { size: 5.0 })),
|
mesh: meshes.add(Mesh::from(shape::Plane { size: 5.0 })),
|
||||||
material: materials.add(StandardMaterial {
|
material: materials.add(StandardMaterial {
|
||||||
base_color: Color::WHITE,
|
base_color: Color::WHITE,
|
||||||
|
@ -71,7 +73,7 @@ fn setup(
|
||||||
..default()
|
..default()
|
||||||
});
|
});
|
||||||
|
|
||||||
commands.spawn_bundle(SceneBundle {
|
commands.spawn(SceneBundle {
|
||||||
scene: assets.load("skin.gltf#Scene0"),
|
scene: assets.load("skin.gltf#Scene0"),
|
||||||
transform: Transform::from_xyz(0.0, 0.0, 0.0),
|
transform: Transform::from_xyz(0.0, 0.0, 0.0),
|
||||||
..default()
|
..default()
|
||||||
|
@ -108,7 +110,8 @@ fn setup_ik(
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
let target = commands
|
let target = commands
|
||||||
.spawn_bundle(PbrBundle {
|
.spawn((
|
||||||
|
PbrBundle {
|
||||||
transform: Transform::from_xyz(0.3, 0.8, 0.2),
|
transform: Transform::from_xyz(0.3, 0.8, 0.2),
|
||||||
mesh: meshes.add(Mesh::from(shape::Icosphere {
|
mesh: meshes.add(Mesh::from(shape::Icosphere {
|
||||||
radius: 0.05,
|
radius: 0.05,
|
||||||
|
@ -119,12 +122,13 @@ fn setup_ik(
|
||||||
..default()
|
..default()
|
||||||
}),
|
}),
|
||||||
..default()
|
..default()
|
||||||
})
|
},
|
||||||
.insert(ManuallyTarget(Vec4::new(0.0, 0.0, 1.0, 0.3)))
|
ManuallyTarget(Vec4::new(0.0, 0.0, 1.0, 0.3)),
|
||||||
|
))
|
||||||
.id();
|
.id();
|
||||||
|
|
||||||
let pole_target = commands
|
let pole_target = commands
|
||||||
.spawn_bundle(PbrBundle {
|
.spawn(PbrBundle {
|
||||||
transform: Transform::from_xyz(-1.0, 0.4, -0.2),
|
transform: Transform::from_xyz(-1.0, 0.4, -0.2),
|
||||||
mesh: meshes.add(Mesh::from(shape::Icosphere {
|
mesh: meshes.add(Mesh::from(shape::Icosphere {
|
||||||
radius: 0.05,
|
radius: 0.05,
|
||||||
|
|
|
@ -28,8 +28,6 @@ pub struct IkConstraint {
|
||||||
|
|
||||||
impl Plugin for InverseKinematicsPlugin {
|
impl Plugin for InverseKinematicsPlugin {
|
||||||
fn build(&self, app: &mut App) {
|
fn build(&self, app: &mut App) {
|
||||||
#[cfg(feature = "debug_lines")]
|
|
||||||
app.add_plugin(bevy_prototype_debug_lines::DebugLinesPlugin::default());
|
|
||||||
app.add_system_to_stage(
|
app.add_system_to_stage(
|
||||||
CoreStage::PostUpdate,
|
CoreStage::PostUpdate,
|
||||||
solver::inverse_kinematics_system
|
solver::inverse_kinematics_system
|
||||||
|
|
|
@ -1,7 +1,5 @@
|
||||||
use bevy::ecs::query::QueryEntityError;
|
use bevy::ecs::query::QueryEntityError;
|
||||||
use bevy::prelude::*;
|
use bevy::prelude::*;
|
||||||
#[cfg(feature = "debug_lines")]
|
|
||||||
use bevy_prototype_debug_lines::{DebugLines, DebugLinesPlugin};
|
|
||||||
|
|
||||||
use super::IkConstraint;
|
use super::IkConstraint;
|
||||||
|
|
||||||
|
@ -16,15 +14,12 @@ pub fn inverse_kinematics_system(
|
||||||
query: Query<(Entity, &IkConstraint)>,
|
query: Query<(Entity, &IkConstraint)>,
|
||||||
parents: Query<&Parent>,
|
parents: Query<&Parent>,
|
||||||
mut transforms: Query<(&mut Transform, &mut GlobalTransform)>,
|
mut transforms: Query<(&mut Transform, &mut GlobalTransform)>,
|
||||||
#[cfg(feature = "debug_lines")] mut debug_lines: ResMut<DebugLines>,
|
|
||||||
) {
|
) {
|
||||||
for (entity, constraint) in query.iter() {
|
for (entity, constraint) in query.iter() {
|
||||||
if let Err(e) = constraint.solve(
|
if let Err(e) = constraint.solve(
|
||||||
entity,
|
entity,
|
||||||
&parents,
|
&parents,
|
||||||
&mut transforms,
|
&mut transforms,
|
||||||
#[cfg(feature = "debug_lines")]
|
|
||||||
&mut debug_lines,
|
|
||||||
) {
|
) {
|
||||||
bevy::log::warn!("Failed to solve IK constraint: {e}");
|
bevy::log::warn!("Failed to solve IK constraint: {e}");
|
||||||
}
|
}
|
||||||
|
@ -37,7 +32,6 @@ impl IkConstraint {
|
||||||
entity: Entity,
|
entity: Entity,
|
||||||
parents: &Query<&Parent>,
|
parents: &Query<&Parent>,
|
||||||
transforms: &mut Query<(&mut Transform, &mut GlobalTransform)>,
|
transforms: &mut Query<(&mut Transform, &mut GlobalTransform)>,
|
||||||
#[cfg(feature = "debug_lines")] debug_lines: &mut DebugLines,
|
|
||||||
) -> Result<(), QueryEntityError> {
|
) -> Result<(), QueryEntityError> {
|
||||||
if self.chain_length == 0 {
|
if self.chain_length == 0 {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
|
@ -56,9 +50,6 @@ impl IkConstraint {
|
||||||
let start = transforms.get(joints[self.chain_length])?.1.translation();
|
let start = transforms.get(joints[self.chain_length])?.1.translation();
|
||||||
let pole_target = transforms.get(pole_target)?.1.translation();
|
let pole_target = transforms.get(pole_target)?.1.translation();
|
||||||
|
|
||||||
#[cfg(feature = "debug_lines")]
|
|
||||||
debug_lines.line_colored(start, target, 0.0, Color::WHITE);
|
|
||||||
|
|
||||||
let tangent = (target - start).normalize();
|
let tangent = (target - start).normalize();
|
||||||
let axis = (pole_target - start).cross(tangent);
|
let axis = (pole_target - start).cross(tangent);
|
||||||
let normal = tangent.cross(axis).normalize();
|
let normal = tangent.cross(axis).normalize();
|
||||||
|
@ -80,11 +71,9 @@ impl IkConstraint {
|
||||||
target,
|
target,
|
||||||
pole_target.as_ref(),
|
pole_target.as_ref(),
|
||||||
transforms,
|
transforms,
|
||||||
#[cfg(feature = "debug_lines")]
|
|
||||||
debug_lines,
|
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
if result.mul_vec3(normal).distance_squared(target) < 0.001 {
|
if result.transform_point(normal).distance_squared(target) < 0.001 {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -98,27 +87,8 @@ impl IkConstraint {
|
||||||
target: Vec3,
|
target: Vec3,
|
||||||
pole_target: Option<&PoleTarget>,
|
pole_target: Option<&PoleTarget>,
|
||||||
transforms: &mut Query<(&mut Transform, &mut GlobalTransform)>,
|
transforms: &mut Query<(&mut Transform, &mut GlobalTransform)>,
|
||||||
#[cfg(feature = "debug_lines")] debug_lines: &mut DebugLines,
|
|
||||||
) -> Result<GlobalTransform, QueryEntityError> {
|
) -> Result<GlobalTransform, QueryEntityError> {
|
||||||
let (&transform, &global_transform) = transforms.get(chain[0])?;
|
let (&transform, &global_transform) = transforms.get(chain[0])?;
|
||||||
#[cfg(feature = "debug_lines")]
|
|
||||||
{
|
|
||||||
let p = global_transform.translation();
|
|
||||||
debug_lines.line_colored(p, global_transform.mul_vec3(Vec3::X * 0.1), 0.0, Color::RED);
|
|
||||||
debug_lines.line_colored(
|
|
||||||
p,
|
|
||||||
global_transform.mul_vec3(Vec3::Y * 0.1),
|
|
||||||
0.0,
|
|
||||||
Color::GREEN,
|
|
||||||
);
|
|
||||||
debug_lines.line_colored(
|
|
||||||
p,
|
|
||||||
global_transform.mul_vec3(Vec3::Z * 0.1),
|
|
||||||
0.0,
|
|
||||||
Color::BLUE,
|
|
||||||
);
|
|
||||||
debug_lines.line_colored(p, global_transform.mul_vec3(normal), 0.0, Color::YELLOW);
|
|
||||||
}
|
|
||||||
|
|
||||||
if chain.len() == 1 {
|
if chain.len() == 1 {
|
||||||
return Ok(global_transform);
|
return Ok(global_transform);
|
||||||
|
@ -160,8 +130,6 @@ impl IkConstraint {
|
||||||
translation,
|
translation,
|
||||||
pole_target,
|
pole_target,
|
||||||
transforms,
|
transforms,
|
||||||
#[cfg(feature = "debug_lines")]
|
|
||||||
debug_lines,
|
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
// apply constraints on the way back from recursing
|
// apply constraints on the way back from recursing
|
||||||
|
@ -172,14 +140,6 @@ impl IkConstraint {
|
||||||
* rotation;
|
* rotation;
|
||||||
*global_transform = parent_global_transform.mul_transform(*transform);
|
*global_transform = parent_global_transform.mul_transform(*transform);
|
||||||
|
|
||||||
#[cfg(feature = "debug_lines")]
|
|
||||||
debug_lines.line_colored(
|
|
||||||
global_transform.translation(),
|
|
||||||
global_transform.mul_vec3(normal),
|
|
||||||
0.0,
|
|
||||||
Color::CYAN,
|
|
||||||
);
|
|
||||||
|
|
||||||
Ok(*global_transform)
|
Ok(*global_transform)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue