we glam now

This commit is contained in:
Carter Anderson 2019-12-04 00:11:14 -08:00
parent 7ed5b2252d
commit 03c1ec3405
31 changed files with 261 additions and 224 deletions

View file

@ -6,9 +6,9 @@ edition = "2018"
[dependencies] [dependencies]
legion = { git = "https://github.com/TomGillen/legion.git", rev = "8628b227bcbe57582fffb5e80e73c634ec4eebd9" } legion = { git = "https://github.com/TomGillen/legion.git", rev = "8628b227bcbe57582fffb5e80e73c634ec4eebd9" }
legion_transform = { path = "src/legion_transform" } legion_transform = { path = "src/transform" }
nalgebra-glm = "0.5.0"
wgpu = { git = "https://github.com/gfx-rs/wgpu-rs.git", rev = "44fa1bc2fa208fa92f80944253e0da56cb7ac1fe"} wgpu = { git = "https://github.com/gfx-rs/wgpu-rs.git", rev = "44fa1bc2fa208fa92f80944253e0da56cb7ac1fe"}
glam = "0.8.3"
winit = "0.20.0-alpha4" winit = "0.20.0-alpha4"
glsl-to-spirv = "0.1" glsl-to-spirv = "0.1"
zerocopy = "0.2" zerocopy = "0.2"

View file

@ -1,5 +1,5 @@
use bevy::*; use bevy::*;
use bevy::{render::*, asset::{Asset, AssetStorage, Handle}, math, Schedulable, Parent}; use bevy::{render::*, asset::{Asset, AssetStorage, Handle}, math::{Mat4, Quat, Vec3}, Schedulable, Parent};
use rand::{rngs::StdRng, Rng, SeedableRng, random}; use rand::{rngs::StdRng, Rng, SeedableRng, random};
fn build_wander_system() -> Box<dyn Schedulable> { fn build_wander_system() -> Box<dyn Schedulable> {
@ -25,10 +25,10 @@ fn build_wander_system() -> Box<dyn Schedulable> {
rng.gen_range(-1.0, 1.0), rng.gen_range(-1.0, 1.0),
rng.gen_range(0.0, 0.001), rng.gen_range(0.0, 0.001),
).normalize(); ).normalize();
let distance = rng.gen_range(wander.distance_bounds.x, wander.distance_bounds.y); let distance = rng.gen_range(wander.distance_bounds.x(), wander.distance_bounds.y());
navigation_point.target = translation.vector + direction * distance; navigation_point.target = translation.0 + direction * distance;
wander.elapsed = 0.0; wander.elapsed = 0.0;
wander.duration = rng.gen_range(wander.duration_bounds.x, wander.duration_bounds.y); wander.duration = rng.gen_range(wander.duration_bounds.x(), wander.duration_bounds.y());
} }
} }
}) })
@ -46,8 +46,8 @@ fn build_navigate_system() -> Box<dyn Schedulable> {
_, world, _, world,
_, person_query| { _, person_query| {
for (_, translation, mut velocity, navigation_point) in person_query.iter(world) { for (_, translation, mut velocity, navigation_point) in person_query.iter(world) {
let distance = navigation_point.target - translation.vector; let distance = navigation_point.target - translation.0;
if math::length(&distance) > 0.01 { if distance.length() > 0.01 {
let direction = distance.normalize(); let direction = distance.normalize();
velocity.value = direction * 2.0; velocity.value = direction * 2.0;
} else { } else {
@ -66,7 +66,7 @@ fn build_move_system() -> Box<dyn Schedulable> {
)>::query()) )>::query())
.build(move |_, world, time , person_query| { .build(move |_, world, time , person_query| {
for (mut translation, velocity) in person_query.iter(world) { for (mut translation, velocity) in person_query.iter(world) {
translation.vector += velocity.value * time.delta_seconds; translation.0 += velocity.value * time.delta_seconds;
} }
}) })
} }
@ -122,9 +122,8 @@ fn build_light_rotator_system() -> Box<dyn Schedulable> {
Write<Rotation>, Write<Rotation>,
)>::query()) )>::query())
.build(move |_, world, time , light_query| { .build(move |_, world, time , light_query| {
for (mut light, mut rotation) in light_query.iter(world) { for (_, mut rotation) in light_query.iter(world) {
let euler = math::quat_euler_angles(rotation.quaternion()); rotation.0 = rotation.0 * Quat::from_rotation_x(3.0 * time.delta_seconds);
*rotation = Rotation::from_euler_angles(euler.z + time.delta_seconds, euler.y, euler.x);
} }
}) })
} }
@ -235,15 +234,15 @@ fn main() {
// camera // camera
( (
Camera::new(CameraType::Projection { Camera::new(CameraType::Projection {
fov: math::quarter_pi(), fov: std::f32::consts::PI / 4.0,
near: 1.0, near: 1.0,
far: 20.0, far: 1000.0,
aspect_ratio: 1.0, aspect_ratio: 1.0,
}), }),
LocalToWorld(math::look_at_rh( LocalToWorld(Mat4::look_at_rh(
&math::vec3(6.0, -40.0, 20.0), Vec3::new(6.0, -40.0, 20.0),
&math::vec3(0.0, 0.0, 0.0), Vec3::new(0.0, 0.0, 0.0),
&math::vec3(0.0, 0.0, 1.0),)), Vec3::new(0.0, 0.0, 1.0),)),
// Translation::new(0.0, 0.0, 0.0), // Translation::new(0.0, 0.0, 0.0),
) )
]); ]);

View file

@ -58,7 +58,7 @@ impl Application {
let light_count = <Read<Light>>::query().iter(&mut self.world).count(); let light_count = <Read<Light>>::query().iter(&mut self.world).count();
let forward_uniforms = ForwardUniforms { let forward_uniforms = ForwardUniforms {
proj: math::Mat4::identity().into(), proj: math::Mat4::identity().to_cols_array_2d(),
num_lights: [light_count as u32, 0, 0, 0], num_lights: [light_count as u32, 0, 0, 0],
}; };
@ -110,7 +110,7 @@ impl Application {
for (mut camera, local_to_world) in <(Write<Camera>, Read<LocalToWorld>)>::query().iter(&mut self.world) { for (mut camera, local_to_world) in <(Write<Camera>, Read<LocalToWorld>)>::query().iter(&mut self.world) {
camera.update(self.swap_chain_descriptor.width, self.swap_chain_descriptor.height); camera.update(self.swap_chain_descriptor.width, self.swap_chain_descriptor.height);
let camera_matrix: [[f32; 4]; 4] = (camera.view_matrix * local_to_world.0).into(); let camera_matrix: [[f32; 4]; 4] = (camera.view_matrix * local_to_world.0).to_cols_array_2d();
let temp_buf = let temp_buf =
self.device.create_buffer_with_data(camera_matrix.as_bytes(), wgpu::BufferUsage::COPY_SRC); self.device.create_buffer_with_data(camera_matrix.as_bytes(), wgpu::BufferUsage::COPY_SRC);
for pass in self.render_passes.iter() { for pass in self.render_passes.iter() {
@ -152,13 +152,8 @@ impl Application {
{ {
slot.copy_from_slice( slot.copy_from_slice(
MaterialUniforms { MaterialUniforms {
model: transform.0.into(), model: transform.0.to_cols_array_2d(),
color: [ color: material.color.into(),
material.color.x as f32,
material.color.y as f32,
material.color.z as f32,
material.color.w as f32,
],
} }
.as_bytes(), .as_bytes(),
); );

View file

@ -1,29 +0,0 @@
use crate::math::UnitQuaternion;
use shrinkwraprs::Shrinkwrap;
#[derive(Shrinkwrap, Debug, PartialEq, Clone, Copy)]
#[shrinkwrap(mutable)]
pub struct Rotation(pub UnitQuaternion<f32>);
impl Rotation {
#[inline(always)]
pub fn identity() -> Self {
Self(UnitQuaternion::identity())
}
#[inline(always)]
pub fn from_euler_angles(roll: f32, pitch: f32, yaw: f32) -> Self {
Self(UnitQuaternion::from_euler_angles(roll, pitch, yaw))
}
}
impl Default for Rotation {
fn default() -> Self {
Self::identity()
}
}
impl From<UnitQuaternion<f32>> for Rotation {
fn from(rotation: UnitQuaternion<f32>) -> Self {
Self(rotation)
}
}

View file

@ -1,36 +0,0 @@
use crate::math::{Translation3, Vector3};
use shrinkwraprs::Shrinkwrap;
#[derive(Shrinkwrap, Debug, PartialEq, Clone, Copy)]
#[shrinkwrap(mutable)]
pub struct Translation(pub Translation3<f32>);
impl Translation {
#[inline(always)]
pub fn identity() -> Self {
Self(Translation3::identity())
}
#[inline(always)]
pub fn new(x: f32, y: f32, z: f32) -> Self {
Self(Translation3::new(x, y, z))
}
}
impl Default for Translation {
fn default() -> Self {
Self::identity()
}
}
impl From<Vector3<f32>> for Translation {
fn from(translation: Vector3<f32>) -> Self {
Self(Translation3::from(translation))
}
}
impl From<Translation3<f32>> for Translation {
fn from(translation: Translation3<f32>) -> Self {
Self(translation)
}
}

View file

@ -14,4 +14,4 @@ pub use legion::prelude::*;
pub use legion::schedule::Schedulable; pub use legion::schedule::Schedulable;
pub use legion_transform::prelude::*; pub use legion_transform::prelude::*;
pub use legion_transform::transform_system_bundle; pub use legion_transform::transform_system_bundle;
pub use nalgebra_glm as math; pub use glam as math;

View file

@ -1,4 +1,4 @@
use crate::math; use crate::math::Mat4;
pub enum CameraType { pub enum CameraType {
Projection { Projection {
@ -10,14 +10,14 @@ pub enum CameraType {
} }
pub struct Camera { pub struct Camera {
pub view_matrix: math::Mat4, pub view_matrix: Mat4,
pub camera_type: CameraType, pub camera_type: CameraType,
} }
impl Camera { impl Camera {
pub fn new(camera_type: CameraType) -> Self { pub fn new(camera_type: CameraType) -> Self {
Camera { Camera {
view_matrix: math::identity(), view_matrix: Mat4::identity(),
camera_type, camera_type,
} }
} }
@ -32,17 +32,17 @@ impl Camera {
} }
} }
pub fn get_projection_matrix(fov: f32, aspect_ratio: f32, near: f32, far: f32) -> math::Mat4 { pub fn get_projection_matrix(fov: f32, aspect_ratio: f32, near: f32, far: f32) -> Mat4 {
let projection = math::perspective(aspect_ratio, fov, near, far); let projection = Mat4::perspective_rh_gl(fov, aspect_ratio, near, far);
opengl_to_wgpu_matrix() * projection opengl_to_wgpu_matrix() * projection
} }
pub fn opengl_to_wgpu_matrix() -> math::Mat4 { pub fn opengl_to_wgpu_matrix() -> Mat4 {
math::mat4( Mat4::from_cols_array(&[
1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0,
0.0, -1.0, 0.0, 0.0, 0.0, -1.0, 0.0, 0.0,
0.0, 0.0, 0.5, 0.0, 0.0, 0.0, 0.5, 0.0,
0.0, 0.0, 0.5, 1.0, 0.0, 0.0, 0.5, 1.0,
) ])
} }

View file

@ -20,10 +20,11 @@ pub struct LightRaw {
impl LightRaw { impl LightRaw {
pub fn from(light: &Light, transform: &math::Mat4, translation: &Translation) -> LightRaw { pub fn from(light: &Light, transform: &math::Mat4, translation: &Translation) -> LightRaw {
let proj = camera::get_projection_matrix(light.fov, 1.0, light.depth.start, light.depth.end) * transform; let proj = camera::get_projection_matrix(light.fov, 1.0, light.depth.start, light.depth.end) * *transform;
let (x, y, z) = translation.0.into();
LightRaw { LightRaw {
proj: proj.into(), proj: proj.to_cols_array_2d(),
pos: [translation.vector.x, translation.vector.y, translation.vector.z, 1.0], pos: [x, y, z, 1.0],
color: [ color: [
light.color.r as f32, light.color.r as f32,
light.color.g as f32, light.color.g as f32,

View file

@ -9,8 +9,8 @@ license = "MIT"
[dependencies] [dependencies]
legion = { git = "https://github.com/TomGillen/legion.git", rev = "8628b227bcbe57582fffb5e80e73c634ec4eebd9" } legion = { git = "https://github.com/TomGillen/legion.git", rev = "8628b227bcbe57582fffb5e80e73c634ec4eebd9" }
#legion = { path = "../legion" } #legion = { path = "../legion" }
glam = "0.8.3"
log = "0.4" log = "0.4"
nalgebra = { version = "0.19.0" }
rayon = "1.2" rayon = "1.2"
serde = { version = "1", features = ["derive"] } serde = { version = "1", features = ["derive"] }
smallvec = "0.6" smallvec = "0.6"

View file

@ -1,14 +1,14 @@
use crate::math::Matrix4; use crate::math::Mat4;
use shrinkwraprs::Shrinkwrap; use shrinkwraprs::Shrinkwrap;
use std::fmt; use std::fmt;
#[derive(Shrinkwrap, Debug, PartialEq, Clone, Copy)] #[derive(Shrinkwrap, Debug, PartialEq, Clone, Copy)]
#[shrinkwrap(mutable)] #[shrinkwrap(mutable)]
pub struct LocalToParent(pub Matrix4<f32>); pub struct LocalToParent(pub Mat4);
impl LocalToParent { impl LocalToParent {
pub fn identity() -> Self { pub fn identity() -> Self {
Self(Matrix4::identity()) Self(Mat4::identity())
} }
} }

View file

@ -1,15 +1,15 @@
use crate::math::Matrix4; use crate::math::Mat4;
use shrinkwraprs::Shrinkwrap; use shrinkwraprs::Shrinkwrap;
use std::fmt; use std::fmt;
#[derive(Shrinkwrap, Debug, PartialEq, Clone, Copy)] #[derive(Shrinkwrap, Debug, PartialEq, Clone, Copy)]
#[shrinkwrap(mutable)] #[shrinkwrap(mutable)]
pub struct LocalToWorld(pub Matrix4<f32>); pub struct LocalToWorld(pub Mat4);
impl LocalToWorld { impl LocalToWorld {
#[inline(always)] #[inline(always)]
pub fn identity() -> Self { pub fn identity() -> Self {
Self(Matrix4::identity()) Self(Mat4::identity())
} }
} }

View file

@ -1,41 +1,42 @@
use crate::math::Vector3; use crate::math::Vec3;
use shrinkwraprs::Shrinkwrap; use shrinkwraprs::Shrinkwrap;
use std::fmt; use std::fmt;
#[derive(Shrinkwrap, Debug, PartialEq, Clone, Copy)] #[derive(Shrinkwrap, Debug, PartialEq, Clone, Copy)]
#[shrinkwrap(mutable)] #[shrinkwrap(mutable)]
pub struct NonUniformScale(pub Vector3<f32>); pub struct NonUniformScale(pub Vec3);
impl NonUniformScale { impl NonUniformScale {
pub fn new(x: f32, y: f32, z: f32) -> Self { pub fn new(x: f32, y: f32, z: f32) -> Self {
Self(Vector3::new(x, y, z)) Self(Vec3::new(x, y, z))
} }
} }
impl From<Vector3<f32>> for NonUniformScale { impl From<Vec3> for NonUniformScale {
fn from(scale: Vector3<f32>) -> Self { fn from(scale: Vec3) -> Self {
Self(scale) Self(scale)
} }
} }
impl From<&Vector3<f32>> for NonUniformScale { impl From<&Vec3> for NonUniformScale {
fn from(scale: &Vector3<f32>) -> Self { fn from(scale: &Vec3) -> Self {
Self(*scale) Self(*scale)
} }
} }
impl From<&mut Vector3<f32>> for NonUniformScale { impl From<&mut Vec3> for NonUniformScale {
fn from(scale: &mut Vector3<f32>) -> Self { fn from(scale: &mut Vec3) -> Self {
Self(*scale) Self(*scale)
} }
} }
impl fmt::Display for NonUniformScale { impl fmt::Display for NonUniformScale {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let (x, y, z) = self.0.into();
write!( write!(
f, f,
"NonUniformScale({}, {}, {})", "NonUniformScale({}, {}, {})",
self.0.x, self.0.y, self.0.z x, y, z
) )
} }
} }

View file

@ -0,0 +1,29 @@
use crate::math::Quat;
use shrinkwraprs::Shrinkwrap;
#[derive(Shrinkwrap, Debug, PartialEq, Clone, Copy)]
#[shrinkwrap(mutable)]
pub struct Rotation(pub Quat);
impl Rotation {
#[inline(always)]
pub fn identity() -> Self {
Self(Quat::identity())
}
#[inline(always)]
pub fn from_euler_angles(yaw: f32, pitch: f32, roll: f32) -> Self {
Self(Quat::from_rotation_ypr(yaw, pitch, roll))
}
}
impl Default for Rotation {
fn default() -> Self {
Self::identity()
}
}
impl From<Quat> for Rotation {
fn from(rotation: Quat) -> Self {
Self(rotation)
}
}

View file

@ -0,0 +1,30 @@
use crate::math::Vec3;
use shrinkwraprs::Shrinkwrap;
#[derive(Shrinkwrap, Debug, PartialEq, Clone, Copy)]
#[shrinkwrap(mutable)]
pub struct Translation(pub Vec3);
impl Translation {
#[inline(always)]
pub fn identity() -> Self {
Self(Vec3::default())
}
#[inline(always)]
pub fn new(x: f32, y: f32, z: f32) -> Self {
Self(Vec3::new(x, y, z))
}
}
impl Default for Translation {
fn default() -> Self {
Self::identity()
}
}
impl From<Vec3> for Translation {
fn from(translation: Vec3) -> Self {
Self(Vec3::from(translation))
}
}

View file

@ -1,5 +1,5 @@
pub use legion as ecs; pub use legion as ecs;
pub use nalgebra as math; pub use glam as math;
pub mod components; pub mod components;
pub mod hierarchy_maintenance_system; pub mod hierarchy_maintenance_system;

View file

@ -1,5 +1,5 @@
#![allow(dead_code)] #![allow(dead_code)]
use crate::{components::*, ecs::prelude::*, math::Matrix4}; use crate::{components::*, ecs::prelude::*, math::{Mat4, Vec3, Quat}};
pub fn build(_: &mut World) -> Box<dyn Schedulable> { pub fn build(_: &mut World) -> Box<dyn Schedulable> {
SystemBuilder::<()>::new("LocalToParentUpdateSystem") SystemBuilder::<()>::new("LocalToParentUpdateSystem")
@ -114,76 +114,81 @@ pub fn build(_: &mut World) -> Box<dyn Schedulable> {
s.spawn(|_| unsafe { s.spawn(|_| unsafe {
// Translation // Translation
a.for_each_unchecked(world, |(mut ltw, translation)| { a.for_each_unchecked(world, |(mut ltw, translation)| {
*ltw = LocalToParent(translation.to_homogeneous()); *ltw = LocalToParent(Mat4::from_translation(translation.0));
}); });
}); });
s.spawn(|_| unsafe { s.spawn(|_| unsafe {
// Rotation // Rotation
b.for_each_unchecked(world, |(mut ltw, rotation)| { b.for_each_unchecked(world, |(mut ltw, rotation)| {
*ltw = LocalToParent(rotation.to_homogeneous()); *ltw = LocalToParent(Mat4::from_quat(rotation.0));
}); });
}); });
s.spawn(|_| unsafe { s.spawn(|_| unsafe {
// Scale // Scale
c.for_each_unchecked(world, |(mut ltw, scale)| { c.for_each_unchecked(world, |(mut ltw, scale)| {
*ltw = LocalToParent(Matrix4::new_scaling(scale.0)); *ltw = LocalToParent(Mat4::from_scale(Vec3::new(scale.0, scale.0, scale.0)));
}); });
}); });
s.spawn(|_| unsafe { s.spawn(|_| unsafe {
// NonUniformScale // NonUniformScale
d.for_each_unchecked(world, |(mut ltw, non_uniform_scale)| { d.for_each_unchecked(world, |(mut ltw, non_uniform_scale)| {
*ltw = LocalToParent(Matrix4::new_nonuniform_scaling(&non_uniform_scale.0)); *ltw = LocalToParent(Mat4::from_scale(non_uniform_scale.0));
}); });
// Translation + Rotation // Translation + Rotation
e.for_each_unchecked(world, |(mut ltw, translation, rotation)| { e.for_each_unchecked(world, |(mut ltw, translation, rotation)| {
*ltw = LocalToParent( *ltw = LocalToParent(
rotation Mat4::from_rotation_translation(rotation.0, translation.0)
.to_homogeneous()
.append_translation(&translation.vector),
); );
}); });
}); });
s.spawn(|_| unsafe { s.spawn(|_| unsafe {
// Translation + Scale // Translation + Scale
f.for_each_unchecked(world, |(mut ltw, translation, scale)| { f.for_each_unchecked(world, |(mut ltw, translation, scale)| {
*ltw = LocalToParent(translation.to_homogeneous().prepend_scaling(scale.0)); *ltw = LocalToParent(Mat4::from_scale_rotation_translation(
Vec3::new(scale.0, scale.0, scale.0),
Quat::default(),
translation.0,
));
}); });
// Translation + NonUniformScale // Translation + NonUniformScale
g.for_each_unchecked(world, |(mut ltw, translation, non_uniform_scale)| { g.for_each_unchecked(world, |(mut ltw, translation, non_uniform_scale)| {
*ltw = LocalToParent( *ltw = LocalToParent(Mat4::from_scale_rotation_translation(
translation non_uniform_scale.0,
.to_homogeneous() Quat::default(),
.prepend_nonuniform_scaling(&non_uniform_scale.0), translation.0,
); ));
}); });
}); });
s.spawn(|_| unsafe { s.spawn(|_| unsafe {
// Rotation + Scale // Rotation + Scale
h.for_each_unchecked(world, |(mut ltw, rotation, scale)| { h.for_each_unchecked(world, |(mut ltw, rotation, scale)| {
*ltw = LocalToParent(rotation.to_homogeneous().prepend_scaling(scale.0)); *ltw = LocalToParent(Mat4::from_scale_rotation_translation(
Vec3::new(scale.0, scale.0, scale.0),
rotation.0,
Vec3::default(),
));
}); });
}); });
s.spawn(|_| unsafe { s.spawn(|_| unsafe {
// Rotation + NonUniformScale // Rotation + NonUniformScale
i.for_each_unchecked(world, |(mut ltw, rotation, non_uniform_scale)| { i.for_each_unchecked(world, |(mut ltw, rotation, non_uniform_scale)| {
*ltw = LocalToParent( *ltw = LocalToParent(Mat4::from_scale_rotation_translation(
rotation non_uniform_scale.0,
.to_homogeneous() rotation.0,
.prepend_nonuniform_scaling(&non_uniform_scale.0), Vec3::default(),
); ));
}); });
}); });
s.spawn(|_| unsafe { s.spawn(|_| unsafe {
// Translation + Rotation + Scale // Translation + Rotation + Scale
j.for_each_unchecked(world, |(mut ltw, translation, rotation, scale)| { j.for_each_unchecked(world, |(mut ltw, translation, rotation, scale)| {
*ltw = LocalToParent( *ltw = LocalToParent(Mat4::from_scale_rotation_translation(
rotation Vec3::new(scale.0, scale.0, scale.0),
.to_homogeneous() rotation.0,
.append_translation(&translation.vector) translation.0,
.prepend_scaling(scale.0), ));
);
}); });
}); });
s.spawn(|_| unsafe { s.spawn(|_| unsafe {
@ -191,12 +196,11 @@ pub fn build(_: &mut World) -> Box<dyn Schedulable> {
k.for_each_unchecked( k.for_each_unchecked(
world, world,
|(mut ltw, translation, rotation, non_uniform_scale)| { |(mut ltw, translation, rotation, non_uniform_scale)| {
*ltw = LocalToParent( *ltw = LocalToParent(Mat4::from_scale_rotation_translation(
rotation non_uniform_scale.0,
.to_homogeneous() rotation.0,
.append_translation(&translation.vector) translation.0,
.prepend_nonuniform_scaling(&non_uniform_scale.0), ));
);
}, },
); );
}); });
@ -249,75 +253,92 @@ mod test {
// Verify that each was transformed correctly. // Verify that each was transformed correctly.
assert_eq!( assert_eq!(
world.get_component::<LocalToParent>(translation).unwrap().0, world.get_component::<LocalToParent>(translation).unwrap().0,
t.to_homogeneous() Mat4::from_translation(t.0)
); );
assert_eq!( assert_eq!(
world.get_component::<LocalToParent>(rotation).unwrap().0, world.get_component::<LocalToParent>(rotation).unwrap().0,
r.to_homogeneous() Mat4::from_quat(r.0)
); );
assert_eq!( assert_eq!(
world.get_component::<LocalToParent>(scale).unwrap().0, world.get_component::<LocalToParent>(scale).unwrap().0,
Matrix4::new_scaling(s.0), Mat4::from_scale(Vec3::new(s.0, s.0, s.0))
); );
assert_eq!( assert_eq!(
world world
.get_component::<LocalToParent>(non_uniform_scale) .get_component::<LocalToParent>(non_uniform_scale)
.unwrap() .unwrap()
.0, .0,
Matrix4::new_nonuniform_scaling(&nus.0), Mat4::from_scale(nus.0)
); );
assert_eq!( assert_eq!(
world world
.get_component::<LocalToParent>(translation_and_rotation) .get_component::<LocalToParent>(translation_and_rotation)
.unwrap() .unwrap()
.0, .0,
r.to_homogeneous().append_translation(&t.vector), Mat4::from_rotation_translation(r.0, t.0)
); );
assert_eq!( assert_eq!(
world world
.get_component::<LocalToParent>(translation_and_scale) .get_component::<LocalToParent>(translation_and_scale)
.unwrap() .unwrap()
.0, .0,
t.to_homogeneous().prepend_scaling(s.0), Mat4::from_scale_rotation_translation(
Vec3::new(s.0, s.0, s.0),
Quat::default(),
t.0
)
); );
assert_eq!( assert_eq!(
world world
.get_component::<LocalToParent>(translation_and_nus) .get_component::<LocalToParent>(translation_and_nus)
.unwrap() .unwrap()
.0, .0,
t.to_homogeneous().prepend_nonuniform_scaling(&nus.0), Mat4::from_scale_rotation_translation(
nus.0,
Quat::default(),
t.0
)
); );
assert_eq!( assert_eq!(
world world
.get_component::<LocalToParent>(rotation_scale) .get_component::<LocalToParent>(rotation_scale)
.unwrap() .unwrap()
.0, .0,
r.to_homogeneous().prepend_scaling(s.0) Mat4::from_scale_rotation_translation(
Vec3::new(s.0, s.0, s.0),
r.0,
Vec3::default()
)
); );
assert_eq!( assert_eq!(
world world.get_component::<LocalToParent>(rotation_nus).unwrap().0,
.get_component::<LocalToParent>(rotation_nus) Mat4::from_scale_rotation_translation(
.unwrap() nus.0,
.0, r.0,
r.to_homogeneous().prepend_nonuniform_scaling(&nus.0) Vec3::default()
)
); );
assert_eq!( assert_eq!(
world world
.get_component::<LocalToParent>(translation_rotation_scale) .get_component::<LocalToParent>(translation_rotation_scale)
.unwrap() .unwrap()
.0, .0,
r.to_homogeneous() Mat4::from_scale_rotation_translation(
.append_translation(&t.vector) Vec3::new(s.0, s.0, s.0),
.prepend_scaling(s.0) r.0,
t.0
)
); );
assert_eq!( assert_eq!(
world world
.get_component::<LocalToParent>(translation_rotation_nus) .get_component::<LocalToParent>(translation_rotation_nus)
.unwrap() .unwrap()
.0, .0,
r.to_homogeneous() Mat4::from_scale_rotation_translation(
.append_translation(&t.vector) nus.0,
.prepend_nonuniform_scaling(&nus.0) r.0,
t.0
)
); );
} }
} }

View file

@ -59,6 +59,7 @@ mod test {
use crate::{ use crate::{
hierarchy_maintenance_system, local_to_parent_system, local_to_world_propagate_system, hierarchy_maintenance_system, local_to_parent_system, local_to_world_propagate_system,
local_to_world_system, local_to_world_system,
math::{Vec3, Mat4}
}; };
#[test] #[test]
@ -120,14 +121,14 @@ mod test {
assert_eq!( assert_eq!(
world.get_component::<LocalToWorld>(e1).unwrap().0, world.get_component::<LocalToWorld>(e1).unwrap().0,
Translation::new(1.0, 0.0, 0.0).to_homogeneous() Mat4::from_translation(Vec3::new(1.0, 0.0, 0.0))
* Translation::new(0.0, 2.0, 0.0).to_homogeneous() * Mat4::from_translation(Vec3::new(0.0, 2.0, 0.0))
); );
assert_eq!( assert_eq!(
world.get_component::<LocalToWorld>(e2).unwrap().0, world.get_component::<LocalToWorld>(e2).unwrap().0,
Translation::new(1.0, 0.0, 0.0).to_homogeneous() Mat4::from_translation(Vec3::new(1.0, 0.0, 0.0))
* Translation::new(0.0, 0.0, 3.0).to_homogeneous() * Mat4::from_translation(Vec3::new(0.0, 0.0, 3.0))
); );
} }
} }

View file

@ -1,5 +1,5 @@
#![allow(dead_code)] #![allow(dead_code)]
use crate::{components::*, ecs::prelude::*, math::Matrix4}; use crate::{components::*, ecs::prelude::*, math::{Mat4, Vec3, Quat}};
pub fn build(_: &mut World) -> Box<dyn Schedulable> { pub fn build(_: &mut World) -> Box<dyn Schedulable> {
SystemBuilder::<()>::new("LocalToWorldUpdateSystem") SystemBuilder::<()>::new("LocalToWorldUpdateSystem")
@ -128,78 +128,83 @@ pub fn build(_: &mut World) -> Box<dyn Schedulable> {
s.spawn(|_| unsafe { s.spawn(|_| unsafe {
// Translation // Translation
a.for_each_unchecked(world, |(mut ltw, translation)| { a.for_each_unchecked(world, |(mut ltw, translation)| {
*ltw = LocalToWorld(translation.to_homogeneous()); *ltw = LocalToWorld(Mat4::from_translation(translation.0));
}); });
}); });
s.spawn(|_| unsafe { s.spawn(|_| unsafe {
// Rotation // Rotation
b.for_each_unchecked(world, |(mut ltw, rotation)| { b.for_each_unchecked(world, |(mut ltw, rotation)| {
*ltw = LocalToWorld(rotation.to_homogeneous()); *ltw = LocalToWorld(Mat4::from_quat(rotation.0));
}); });
}); });
s.spawn(|_| unsafe { s.spawn(|_| unsafe {
// Scale // Scale
c.for_each_unchecked(world, |(mut ltw, scale)| { c.for_each_unchecked(world, |(mut ltw, scale)| {
*ltw = LocalToWorld(Matrix4::new_scaling(scale.0)); *ltw = LocalToWorld(Mat4::from_scale(Vec3::new(scale.0, scale.0, scale.0)));
}); });
}); });
s.spawn(|_| unsafe { s.spawn(|_| unsafe {
// NonUniformScale // NonUniformScale
d.for_each_unchecked(world, |(mut ltw, non_uniform_scale)| { d.for_each_unchecked(world, |(mut ltw, non_uniform_scale)| {
*ltw = LocalToWorld(Matrix4::new_nonuniform_scaling(&non_uniform_scale.0)); *ltw = LocalToWorld(Mat4::from_scale(non_uniform_scale.0));
}); });
}); });
s.spawn(|_| unsafe { s.spawn(|_| unsafe {
// Translation + Rotation // Translation + Rotation
e.for_each_unchecked(world, |(mut ltw, translation, rotation)| { e.for_each_unchecked(world, |(mut ltw, translation, rotation)| {
*ltw = LocalToWorld( *ltw = LocalToWorld(
rotation Mat4::from_rotation_translation(rotation.0, translation.0)
.to_homogeneous()
.append_translation(&translation.vector),
); );
}); });
}); });
s.spawn(|_| unsafe { s.spawn(|_| unsafe {
// Translation + Scale // Translation + Scale
f.for_each_unchecked(world, |(mut ltw, translation, scale)| { f.for_each_unchecked(world, |(mut ltw, translation, scale)| {
*ltw = LocalToWorld(translation.to_homogeneous().prepend_scaling(scale.0)); *ltw = LocalToWorld(Mat4::from_scale_rotation_translation(
Vec3::new(scale.0, scale.0, scale.0),
Quat::default(),
translation.0,
));
}); });
}); });
s.spawn(|_| unsafe { s.spawn(|_| unsafe {
// Translation + NonUniformScale // Translation + NonUniformScale
g.for_each_unchecked(world, |(mut ltw, translation, non_uniform_scale)| { g.for_each_unchecked(world, |(mut ltw, translation, non_uniform_scale)| {
*ltw = LocalToWorld( *ltw = LocalToWorld(Mat4::from_scale_rotation_translation(
translation non_uniform_scale.0,
.to_homogeneous() Quat::default(),
.prepend_nonuniform_scaling(&non_uniform_scale.0), translation.0,
); ));
}); });
}); });
s.spawn(|_| unsafe { s.spawn(|_| unsafe {
// Rotation + Scale // Rotation + Scale
h.for_each_unchecked(world, |(mut ltw, rotation, scale)| { h.for_each_unchecked(world, |(mut ltw, rotation, scale)| {
*ltw = LocalToWorld(rotation.to_homogeneous().prepend_scaling(scale.0)); *ltw = LocalToWorld(Mat4::from_scale_rotation_translation(
Vec3::new(scale.0, scale.0, scale.0),
rotation.0,
Vec3::default(),
));
}); });
}); });
s.spawn(|_| unsafe { s.spawn(|_| unsafe {
// Rotation + NonUniformScale // Rotation + NonUniformScale
i.for_each_unchecked(world, |(mut ltw, rotation, non_uniform_scale)| { i.for_each_unchecked(world, |(mut ltw, rotation, non_uniform_scale)| {
*ltw = LocalToWorld( *ltw = LocalToWorld(Mat4::from_scale_rotation_translation(
rotation non_uniform_scale.0,
.to_homogeneous() rotation.0,
.prepend_nonuniform_scaling(&non_uniform_scale.0), Vec3::default(),
); ));
}); });
}); });
s.spawn(|_| unsafe { s.spawn(|_| unsafe {
// Translation + Rotation + Scale // Translation + Rotation + Scale
j.for_each_unchecked(world, |(mut ltw, translation, rotation, scale)| { j.for_each_unchecked(world, |(mut ltw, translation, rotation, scale)| {
*ltw = LocalToWorld( *ltw = LocalToWorld(Mat4::from_scale_rotation_translation(
rotation Vec3::new(scale.0, scale.0, scale.0),
.to_homogeneous() rotation.0,
.append_translation(&translation.vector) translation.0,
.prepend_scaling(scale.0), ));
);
}); });
}); });
s.spawn(|_| unsafe { s.spawn(|_| unsafe {
@ -207,12 +212,11 @@ pub fn build(_: &mut World) -> Box<dyn Schedulable> {
k.for_each_unchecked( k.for_each_unchecked(
world, world,
|(mut ltw, translation, rotation, non_uniform_scale)| { |(mut ltw, translation, rotation, non_uniform_scale)| {
*ltw = LocalToWorld( *ltw = LocalToWorld(Mat4::from_scale_rotation_translation(
rotation non_uniform_scale.0,
.to_homogeneous() rotation.0,
.append_translation(&translation.vector) translation.0,
.prepend_nonuniform_scaling(&non_uniform_scale.0), ));
);
}, },
); );
}); });
@ -236,6 +240,7 @@ pub fn build(_: &mut World) -> Box<dyn Schedulable> {
#[cfg(test)] #[cfg(test)]
mod test { mod test {
use super::*; use super::*;
use crate::math::{Mat4, Quat, Vec3};
#[test] #[test]
fn correct_world_transformation() { fn correct_world_transformation() {
@ -270,72 +275,92 @@ mod test {
// Verify that each was transformed correctly. // Verify that each was transformed correctly.
assert_eq!( assert_eq!(
world.get_component::<LocalToWorld>(translation).unwrap().0, world.get_component::<LocalToWorld>(translation).unwrap().0,
t.to_homogeneous() Mat4::from_translation(t.0)
); );
assert_eq!( assert_eq!(
world.get_component::<LocalToWorld>(rotation).unwrap().0, world.get_component::<LocalToWorld>(rotation).unwrap().0,
r.to_homogeneous() Mat4::from_quat(r.0)
); );
assert_eq!( assert_eq!(
world.get_component::<LocalToWorld>(scale).unwrap().0, world.get_component::<LocalToWorld>(scale).unwrap().0,
Matrix4::new_scaling(s.0), Mat4::from_scale(Vec3::new(s.0, s.0, s.0))
); );
assert_eq!( assert_eq!(
world world
.get_component::<LocalToWorld>(non_uniform_scale) .get_component::<LocalToWorld>(non_uniform_scale)
.unwrap() .unwrap()
.0, .0,
Matrix4::new_nonuniform_scaling(&nus.0), Mat4::from_scale(nus.0)
); );
assert_eq!( assert_eq!(
world world
.get_component::<LocalToWorld>(translation_and_rotation) .get_component::<LocalToWorld>(translation_and_rotation)
.unwrap() .unwrap()
.0, .0,
r.to_homogeneous().append_translation(&t.vector), Mat4::from_rotation_translation(r.0, t.0)
); );
assert_eq!( assert_eq!(
world world
.get_component::<LocalToWorld>(translation_and_scale) .get_component::<LocalToWorld>(translation_and_scale)
.unwrap() .unwrap()
.0, .0,
t.to_homogeneous().prepend_scaling(s.0), Mat4::from_scale_rotation_translation(
Vec3::new(s.0, s.0, s.0),
Quat::default(),
t.0
)
); );
assert_eq!( assert_eq!(
world world
.get_component::<LocalToWorld>(translation_and_nus) .get_component::<LocalToWorld>(translation_and_nus)
.unwrap() .unwrap()
.0, .0,
t.to_homogeneous().prepend_nonuniform_scaling(&nus.0), Mat4::from_scale_rotation_translation(
nus.0,
Quat::default(),
t.0
)
); );
assert_eq!( assert_eq!(
world world
.get_component::<LocalToWorld>(rotation_scale) .get_component::<LocalToWorld>(rotation_scale)
.unwrap() .unwrap()
.0, .0,
r.to_homogeneous().prepend_scaling(s.0) Mat4::from_scale_rotation_translation(
Vec3::new(s.0, s.0, s.0),
r.0,
Vec3::default()
)
); );
assert_eq!( assert_eq!(
world.get_component::<LocalToWorld>(rotation_nus).unwrap().0, world.get_component::<LocalToWorld>(rotation_nus).unwrap().0,
r.to_homogeneous().prepend_nonuniform_scaling(&nus.0) Mat4::from_scale_rotation_translation(
nus.0,
r.0,
Vec3::default()
)
); );
assert_eq!( assert_eq!(
world world
.get_component::<LocalToWorld>(translation_rotation_scale) .get_component::<LocalToWorld>(translation_rotation_scale)
.unwrap() .unwrap()
.0, .0,
r.to_homogeneous() Mat4::from_scale_rotation_translation(
.append_translation(&t.vector) Vec3::new(s.0, s.0, s.0),
.prepend_scaling(s.0) r.0,
t.0
)
); );
assert_eq!( assert_eq!(
world world
.get_component::<LocalToWorld>(translation_rotation_nus) .get_component::<LocalToWorld>(translation_rotation_nus)
.unwrap() .unwrap()
.0, .0,
r.to_homogeneous() Mat4::from_scale_rotation_translation(
.append_translation(&t.vector) nus.0,
.prepend_nonuniform_scaling(&nus.0) r.0,
t.0
)
); );
} }
} }