Skip to content

Commit

Permalink
Transform and GlobalTransform are now Similarities (bevyengine#596)
Browse files Browse the repository at this point in the history
Transform and GlobalTransform are now Similarities.

This resolves precision errors and simplifies the api

Co-authored-by: Carter Anderson <[email protected]>
  • Loading branch information
2 people authored and joshuajbouw committed Oct 24, 2020
1 parent 8d6fdf5 commit 0c75197
Show file tree
Hide file tree
Showing 28 changed files with 317 additions and 369 deletions.
4 changes: 2 additions & 2 deletions crates/bevy_pbr/src/light.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,8 @@ impl LightRaw {
far: light.depth.end,
};

let proj = perspective.get_projection_matrix() * *global_transform.value();
let (x, y, z) = global_transform.translation().into();
let proj = perspective.get_projection_matrix() * global_transform.compute_matrix();
let (x, y, z) = global_transform.translation.into();
LightRaw {
proj: proj.to_cols_array_2d(),
pos: [x, y, z, 1.0],
Expand Down
4 changes: 2 additions & 2 deletions crates/bevy_render/src/camera/visible_entities.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ pub fn visible_entities_system(
) {
for (camera, camera_global_transform, mut visible_entities) in &mut camera_query.iter() {
visible_entities.value.clear();
let camera_position = camera_global_transform.translation();
let camera_position = camera_global_transform.translation;

let mut no_transform_order = 0.0;
let mut transparent_entities = Vec::new();
Expand All @@ -41,7 +41,7 @@ pub fn visible_entities_system(

let order =
if let Ok(global_transform) = draw_transform_query.get::<GlobalTransform>(entity) {
let position = global_transform.translation();
let position = global_transform.translation;
// smaller distances are sorted to lower indices by using the distance from the camera
FloatOrd(match camera.depth_calculation {
DepthCalculation::ZDifference => camera_position.z() - position.z(),
Expand Down
2 changes: 1 addition & 1 deletion crates/bevy_render/src/render_graph/nodes/camera_node.rs
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ pub fn camera_node_system(

let matrix_size = std::mem::size_of::<[[f32; 4]; 4]>();
let camera_matrix: [f32; 16] =
(camera.projection_matrix * global_transform.value().inverse()).to_cols_array();
(camera.projection_matrix * global_transform.compute_matrix().inverse()).to_cols_array();

render_resource_context.write_mapped_buffer(
staging_buffer,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ use bevy_asset::Handle;
use bevy_core::{Byteable, Bytes};
pub use bevy_derive::{RenderResource, RenderResources};
use bevy_math::{Mat4, Vec2, Vec3, Vec4};
use bevy_transform::components::GlobalTransform;

#[derive(Debug, Clone, Eq, PartialEq)]
pub enum RenderResourceType {
Expand Down Expand Up @@ -179,14 +180,33 @@ where
}
}

impl RenderResource for GlobalTransform {
fn resource_type(&self) -> Option<RenderResourceType> {
Some(RenderResourceType::Buffer)
}

fn write_buffer_bytes(&self, buffer: &mut [u8]) {
let mat4 = self.compute_matrix();
mat4.write_bytes(buffer);
}

fn buffer_byte_len(&self) -> Option<usize> {
Some(std::mem::size_of::<[f32; 16]>())
}

fn texture(&self) -> Option<Handle<Texture>> {
None
}
}

impl RenderResources for bevy_transform::prelude::GlobalTransform {
fn render_resources_len(&self) -> usize {
1
}

fn get_render_resource(&self, index: usize) -> Option<&dyn RenderResource> {
if index == 0 {
Some(self.value())
Some(self)
} else {
None
}
Expand Down
223 changes: 106 additions & 117 deletions crates/bevy_transform/src/components/global_transform.rs
Original file line number Diff line number Diff line change
@@ -1,174 +1,163 @@
use bevy_math::{Mat3, Mat4, Quat, Vec3};
use bevy_property::Properties;
use std::fmt;
use std::ops::Mul;

use super::Transform;

#[derive(Debug, PartialEq, Clone, Copy, Properties)]
pub struct GlobalTransform {
value: Mat4,
pub translation: Vec3,
pub rotation: Quat,
pub scale: Vec3,
}

impl GlobalTransform {
#[inline(always)]
pub fn new(value: Mat4) -> Self {
GlobalTransform { value }
}

#[inline(always)]
#[inline]
pub fn identity() -> Self {
GlobalTransform {
value: Mat4::identity(),
translation: Vec3::zero(),
rotation: Quat::identity(),
scale: Vec3::one(),
}
}

pub fn from_translation(translation: Vec3) -> Self {
GlobalTransform::new(Mat4::from_translation(translation))
}
#[inline]
pub fn from_matrix(matrix: Mat4) -> Self {
let (scale, rotation, translation) = matrix.to_scale_rotation_translation();

pub fn from_rotation(rotation: Quat) -> Self {
GlobalTransform::new(Mat4::from_quat(rotation))
}

pub fn from_scale(scale: f32) -> Self {
GlobalTransform::new(Mat4::from_scale(Vec3::splat(scale)))
}

pub fn from_translation_rotation(translation: Vec3, rotation: Quat) -> Self {
GlobalTransform::new(Mat4::from_scale_rotation_translation(
Vec3::splat(1.0),
rotation,
GlobalTransform {
translation,
))
}

pub fn from_translation_rotation_scale(translation: Vec3, rotation: Quat, scale: f32) -> Self {
GlobalTransform::new(Mat4::from_scale_rotation_translation(
Vec3::splat(scale),
rotation,
translation,
))
}

pub fn from_non_uniform_scale(scale: Vec3) -> Self {
GlobalTransform::new(Mat4::from_scale(scale))
}

pub fn with_translation(mut self, translation: Vec3) -> Self {
self.set_translation(translation);
self
}

pub fn with_rotation(mut self, rotation: Quat) -> Self {
self.set_rotation(rotation);
self
}

pub fn with_scale(mut self, scale: f32) -> Self {
self.set_scale(scale);
self
scale,
}
}

pub fn with_non_uniform_scale(mut self, scale: Vec3) -> Self {
self.set_non_uniform_scale(scale);
self
#[inline]
pub fn from_translation(translation: Vec3) -> Self {
GlobalTransform {
translation,
..Default::default()
}
}

pub fn with_translate(mut self, translation: Vec3) -> Self {
self.translate(translation);
self
#[inline]
pub fn from_rotation(rotation: Quat) -> Self {
GlobalTransform {
rotation,
..Default::default()
}
}

pub fn with_rotate(mut self, rotation: Quat) -> Self {
self.rotate(rotation);
self
#[inline]
pub fn from_scale(scale: Vec3) -> Self {
GlobalTransform {
scale,
..Default::default()
}
}

pub fn with_apply_scale(mut self, scale: f32) -> Self {
self.apply_scale(scale);
self
/// Returns transform with the same translation and scale, but rotation so that transform.forward() points at the origin
#[inline]
pub fn looking_at_origin(self) -> Self {
self.looking_at(Vec3::zero(), Vec3::unit_y())
}

pub fn with_apply_non_uniform_scale(mut self, scale: Vec3) -> Self {
self.apply_non_uniform_scale(scale);
/// Returns transform with the same translation and scale, but rotation so that transform.forward() points at target
#[inline]
pub fn looking_at(mut self, target: Vec3, up: Vec3) -> Self {
self.look_at(target, up);
self
}

pub fn value(&self) -> &Mat4 {
&self.value
#[inline]
pub fn compute_matrix(&self) -> Mat4 {
Mat4::from_scale_rotation_translation(self.scale, self.rotation, self.translation)
}

pub fn value_mut(&mut self) -> &mut Mat4 {
&mut self.value
#[inline]
pub fn forward(&self) -> Vec3 {
self.rotation * Vec3::unit_z()
}

pub fn translation(&self) -> Vec3 {
Vec3::from(self.value.w_axis().truncate())
#[inline]
/// Rotate the transform by the given rotation
pub fn rotate(&mut self, rotation: Quat) {
self.rotation *= rotation;
}

pub fn rotation(&self) -> Quat {
let scale = self.scale();

Quat::from_rotation_mat3(&Mat3::from_cols(
Vec3::from(self.value.x_axis().truncate()) / scale.x(),
Vec3::from(self.value.y_axis().truncate()) / scale.y(),
Vec3::from(self.value.z_axis().truncate()) / scale.z(),
))
#[inline]
pub fn mul_transform(&self, transform: Transform) -> GlobalTransform {
let translation = self.mul_vec3(transform.translation);
let rotation = self.rotation * transform.rotation;
let scale = self.scale * transform.scale;
GlobalTransform {
scale,
rotation,
translation,
}
}

pub fn scale(&self) -> Vec3 {
Vec3::new(
self.value.x_axis().truncate().length(),
self.value.y_axis().truncate().length(),
self.value.z_axis().truncate().length(),
)
#[inline]
pub fn mul_vec3(&self, mut value: Vec3) -> Vec3 {
value = self.rotation * value;
value = self.scale * value;
value += self.translation;
value
}

pub fn set_translation(&mut self, translation: Vec3) {
*self.value.w_axis_mut() = translation.extend(1.0);
#[inline]
pub fn apply_non_uniform_scale(&mut self, scale: Vec3) {
self.scale *= scale;
}

pub fn set_rotation(&mut self, rotation: Quat) {
self.value =
Mat4::from_scale_rotation_translation(self.scale(), rotation, self.translation());
#[inline]
pub fn look_at(&mut self, target: Vec3, up: Vec3) {
let forward = Vec3::normalize(self.translation - target);
let right = up.cross(forward).normalize();
let up = forward.cross(right);
self.rotation = Quat::from_rotation_mat3(&Mat3::from_cols(right, up, forward));
}
}

pub fn set_scale(&mut self, scale: f32) {
self.value = Mat4::from_scale_rotation_translation(
Vec3::splat(scale),
self.rotation(),
self.translation(),
);
impl Default for GlobalTransform {
fn default() -> Self {
Self::identity()
}
}

pub fn set_non_uniform_scale(&mut self, scale: Vec3) {
self.value =
Mat4::from_scale_rotation_translation(scale, self.rotation(), self.translation());
impl From<Transform> for GlobalTransform {
fn from(transform: Transform) -> Self {
Self {
translation: transform.translation,
rotation: transform.rotation,
scale: transform.scale,
}
}
}

pub fn translate(&mut self, translation: Vec3) {
*self.value.w_axis_mut() += translation.extend(0.0);
}
impl Mul<GlobalTransform> for GlobalTransform {
type Output = GlobalTransform;

pub fn rotate(&mut self, rotation: Quat) {
self.value = Mat4::from_quat(rotation) * self.value;
#[inline]
fn mul(self, global_transform: GlobalTransform) -> Self::Output {
self.mul_transform(global_transform.into())
}
}

pub fn apply_scale(&mut self, scale: f32) {
self.value = Mat4::from_scale(Vec3::splat(scale)) * self.value;
}
impl Mul<Transform> for GlobalTransform {
type Output = GlobalTransform;

pub fn apply_non_uniform_scale(&mut self, scale: Vec3) {
self.value = Mat4::from_scale(scale) * self.value;
#[inline]
fn mul(self, transform: Transform) -> Self::Output {
self.mul_transform(transform)
}
}

impl Default for GlobalTransform {
fn default() -> Self {
Self::identity()
}
}
impl Mul<Vec3> for GlobalTransform {
type Output = Vec3;

impl fmt::Display for GlobalTransform {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", self.value)
#[inline]
fn mul(self, value: Vec3) -> Self::Output {
self.mul_vec3(value)
}
}
Loading

0 comments on commit 0c75197

Please sign in to comment.