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]
legion = { git = "https://github.com/TomGillen/legion.git", rev = "8628b227bcbe57582fffb5e80e73c634ec4eebd9" }
legion_transform = { path = "src/legion_transform" }
nalgebra-glm = "0.5.0"
legion_transform = { path = "src/transform" }
wgpu = { git = "https://github.com/gfx-rs/wgpu-rs.git", rev = "44fa1bc2fa208fa92f80944253e0da56cb7ac1fe"}
glam = "0.8.3"
winit = "0.20.0-alpha4"
glsl-to-spirv = "0.1"
zerocopy = "0.2"

View file

@ -1,5 +1,5 @@
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};
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(0.0, 0.001),
).normalize();
let distance = rng.gen_range(wander.distance_bounds.x, wander.distance_bounds.y);
navigation_point.target = translation.vector + direction * distance;
let distance = rng.gen_range(wander.distance_bounds.x(), wander.distance_bounds.y());
navigation_point.target = translation.0 + direction * distance;
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,
_, person_query| {
for (_, translation, mut velocity, navigation_point) in person_query.iter(world) {
let distance = navigation_point.target - translation.vector;
if math::length(&distance) > 0.01 {
let distance = navigation_point.target - translation.0;
if distance.length() > 0.01 {
let direction = distance.normalize();
velocity.value = direction * 2.0;
} else {
@ -66,7 +66,7 @@ fn build_move_system() -> Box<dyn Schedulable> {
)>::query())
.build(move |_, world, time , person_query| {
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>,
)>::query())
.build(move |_, world, time , light_query| {
for (mut light, mut rotation) in light_query.iter(world) {
let euler = math::quat_euler_angles(rotation.quaternion());
*rotation = Rotation::from_euler_angles(euler.z + time.delta_seconds, euler.y, euler.x);
for (_, mut rotation) in light_query.iter(world) {
rotation.0 = rotation.0 * Quat::from_rotation_x(3.0 * time.delta_seconds);
}
})
}
@ -235,15 +234,15 @@ fn main() {
// camera
(
Camera::new(CameraType::Projection {
fov: math::quarter_pi(),
fov: std::f32::consts::PI / 4.0,
near: 1.0,
far: 20.0,
far: 1000.0,
aspect_ratio: 1.0,
}),
LocalToWorld(math::look_at_rh(
&math::vec3(6.0, -40.0, 20.0),
&math::vec3(0.0, 0.0, 0.0),
&math::vec3(0.0, 0.0, 1.0),)),
LocalToWorld(Mat4::look_at_rh(
Vec3::new(6.0, -40.0, 20.0),
Vec3::new(0.0, 0.0, 0.0),
Vec3::new(0.0, 0.0, 1.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 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],
};
@ -110,7 +110,7 @@ impl Application {
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);
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 =
self.device.create_buffer_with_data(camera_matrix.as_bytes(), wgpu::BufferUsage::COPY_SRC);
for pass in self.render_passes.iter() {
@ -152,13 +152,8 @@ impl Application {
{
slot.copy_from_slice(
MaterialUniforms {
model: transform.0.into(),
color: [
material.color.x as f32,
material.color.y as f32,
material.color.z as f32,
material.color.w as f32,
],
model: transform.0.to_cols_array_2d(),
color: material.color.into(),
}
.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_transform::prelude::*;
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 {
Projection {
@ -10,14 +10,14 @@ pub enum CameraType {
}
pub struct Camera {
pub view_matrix: math::Mat4,
pub view_matrix: Mat4,
pub camera_type: CameraType,
}
impl Camera {
pub fn new(camera_type: CameraType) -> Self {
Camera {
view_matrix: math::identity(),
view_matrix: Mat4::identity(),
camera_type,
}
}
@ -32,17 +32,17 @@ impl Camera {
}
}
pub fn get_projection_matrix(fov: f32, aspect_ratio: f32, near: f32, far: f32) -> math::Mat4 {
let projection = math::perspective(aspect_ratio, fov, near, far);
pub fn get_projection_matrix(fov: f32, aspect_ratio: f32, near: f32, far: f32) -> Mat4 {
let projection = Mat4::perspective_rh_gl(fov, aspect_ratio, near, far);
opengl_to_wgpu_matrix() * projection
}
pub fn opengl_to_wgpu_matrix() -> math::Mat4 {
math::mat4(
pub fn opengl_to_wgpu_matrix() -> Mat4 {
Mat4::from_cols_array(&[
1.0, 0.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, 1.0,
)
])
}

View file

@ -20,10 +20,11 @@ pub struct LightRaw {
impl 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 {
proj: proj.into(),
pos: [translation.vector.x, translation.vector.y, translation.vector.z, 1.0],
proj: proj.to_cols_array_2d(),
pos: [x, y, z, 1.0],
color: [
light.color.r as f32,
light.color.g as f32,

View file

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

View file

@ -1,14 +1,14 @@
use crate::math::Matrix4;
use crate::math::Mat4;
use shrinkwraprs::Shrinkwrap;
use std::fmt;
#[derive(Shrinkwrap, Debug, PartialEq, Clone, Copy)]
#[shrinkwrap(mutable)]
pub struct LocalToParent(pub Matrix4<f32>);
pub struct LocalToParent(pub Mat4);
impl LocalToParent {
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 std::fmt;
#[derive(Shrinkwrap, Debug, PartialEq, Clone, Copy)]
#[shrinkwrap(mutable)]
pub struct LocalToWorld(pub Matrix4<f32>);
pub struct LocalToWorld(pub Mat4);
impl LocalToWorld {
#[inline(always)]
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 std::fmt;
#[derive(Shrinkwrap, Debug, PartialEq, Clone, Copy)]
#[shrinkwrap(mutable)]
pub struct NonUniformScale(pub Vector3<f32>);
pub struct NonUniformScale(pub Vec3);
impl NonUniformScale {
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 {
fn from(scale: Vector3<f32>) -> Self {
impl From<Vec3> for NonUniformScale {
fn from(scale: Vec3) -> Self {
Self(scale)
}
}
impl From<&Vector3<f32>> for NonUniformScale {
fn from(scale: &Vector3<f32>) -> Self {
impl From<&Vec3> for NonUniformScale {
fn from(scale: &Vec3) -> Self {
Self(*scale)
}
}
impl From<&mut Vector3<f32>> for NonUniformScale {
fn from(scale: &mut Vector3<f32>) -> Self {
impl From<&mut Vec3> for NonUniformScale {
fn from(scale: &mut Vec3) -> Self {
Self(*scale)
}
}
impl fmt::Display for NonUniformScale {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let (x, y, z) = self.0.into();
write!(
f,
"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 nalgebra as math;
pub use glam as math;
pub mod components;
pub mod hierarchy_maintenance_system;

View file

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

View file

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

View file

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