Skip to content

Commit

Permalink
use make GlobalTransform a Similarity, implement math ops, and clean up
Browse files Browse the repository at this point in the history
  • Loading branch information
cart committed Oct 16, 2020
1 parent 51f738e commit 1abe219
Show file tree
Hide file tree
Showing 18 changed files with 280 additions and 121 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
156 changes: 134 additions & 22 deletions crates/bevy_transform/src/components/global_transform.rs
Original file line number Diff line number Diff line change
@@ -1,40 +1,121 @@
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 {
pub value: Mat4,
pub translation: Vec3,
pub rotation: Quat,
pub scale: Vec3,
}

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

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

GlobalTransform {
translation,
rotation,
scale,
}
}

#[inline]
pub fn from_translation(translation: Vec3) -> Self {
GlobalTransform {
translation,
..Default::default()
}
}

#[inline]
pub fn from_rotation(rotation: Quat) -> Self {
GlobalTransform {
rotation,
..Default::default()
}
}

pub fn translation(&self) -> Vec3 {
Vec3::from(self.value.w_axis().truncate())
#[inline]
pub fn from_scale(scale: Vec3) -> Self {
GlobalTransform {
scale,
..Default::default()
}
}

/// 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())
}

/// 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
}

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

pub fn rotation(&self) -> Quat {
let scale = self.scale();
#[inline]
pub fn forward(&self) -> Vec3 {
self.rotation * Vec3::unit_z()
}

#[inline]
/// Rotate the transform by the given rotation
pub fn rotate(&mut self, rotation: Quat) {
self.rotation *= rotation;
}

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
}

#[inline]
pub fn apply_non_uniform_scale(&mut self, scale: Vec3) {
self.scale *= scale;
}

#[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));
}
}

Expand All @@ -44,8 +125,39 @@ impl Default for GlobalTransform {
}
}

impl fmt::Display for GlobalTransform {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", self.value)
impl From<Transform> for GlobalTransform {
fn from(transform: Transform) -> Self {
Self {
translation: transform.translation,
rotation: transform.rotation,
scale: transform.scale,
}
}
}

impl Mul<GlobalTransform> for GlobalTransform {
type Output = GlobalTransform;

#[inline]
fn mul(self, global_transform: GlobalTransform) -> Self::Output {
self.mul_transform(global_transform.into())
}
}

impl Mul<Transform> for GlobalTransform {
type Output = GlobalTransform;

#[inline]
fn mul(self, transform: Transform) -> Self::Output {
self.mul_transform(transform)
}
}

impl Mul<Vec3> for GlobalTransform {
type Output = Vec3;

#[inline]
fn mul(self, value: Vec3) -> Self::Output {
self.mul_vec3(value)
}
}
Loading

0 comments on commit 1abe219

Please sign in to comment.