Add helper methods to Transform
This commit is contained in:
parent
432c54004e
commit
1bdf51a56b
|
@ -3,6 +3,7 @@ mod render;
|
|||
mod input_event;
|
||||
mod resources;
|
||||
mod ecs;
|
||||
mod math;
|
||||
|
||||
use ecs::components::model_2d::Model2dComponent;
|
||||
|
||||
|
|
|
@ -0,0 +1,36 @@
|
|||
use std::f32::consts::PI;
|
||||
|
||||
/// Convert degrees to radians
|
||||
pub fn degrees_to_radians(degrees: f32) -> f32 {
|
||||
degrees * PI / 180.0
|
||||
}
|
||||
|
||||
/// Convert radians to degrees
|
||||
pub fn radians_to_degrees(radians: f32) -> f32 {
|
||||
radians * 180.0 / PI
|
||||
}
|
||||
|
||||
pub enum Angle {
|
||||
Degrees(f32),
|
||||
Radians(f32),
|
||||
}
|
||||
|
||||
impl Angle {
|
||||
/// Converts Angle to radians.
|
||||
/// (conversion is only done if the Angle is in degrees).
|
||||
pub fn to_radians(&self) -> f32 {
|
||||
match *self {
|
||||
Self::Degrees(d) => degrees_to_radians(d),
|
||||
Self::Radians(r) => r,
|
||||
}
|
||||
}
|
||||
|
||||
/// Converts Angle to degrees.
|
||||
/// (conversion is only done if the Angle is in radians).
|
||||
pub fn to_degrees(&self) -> f32 {
|
||||
match *self {
|
||||
Self::Degrees(d) => d,
|
||||
Self::Radians(r) => radians_to_degrees(r),
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
/// Re-export of glam library
|
||||
pub use glam::*;
|
||||
|
||||
pub mod angle;
|
||||
pub use angle::*;
|
|
@ -1,19 +1,24 @@
|
|||
use hecs::Entity;
|
||||
|
||||
use super::{mesh::Mesh, material::Material};
|
||||
use super::{mesh::Mesh, material::Material, transform::Transform};
|
||||
|
||||
pub struct RenderJob {
|
||||
mesh: Mesh,
|
||||
material: Material,
|
||||
entity: Entity,
|
||||
|
||||
pub transform: Option<Transform>,
|
||||
pub last_transform: Option<Transform>, // TODO: render interpolation
|
||||
}
|
||||
|
||||
impl RenderJob {
|
||||
pub fn new(mesh: Mesh, material: Material, entity: Entity) -> Self {
|
||||
pub fn new(mesh: Mesh, material: Material, entity: Entity, transform: Option<Transform>, last_transform: Option<Transform>) -> Self {
|
||||
Self {
|
||||
mesh,
|
||||
material,
|
||||
entity,
|
||||
transform,
|
||||
last_transform,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -6,6 +6,7 @@ use std::borrow::Cow;
|
|||
use async_std::sync::Mutex;
|
||||
use async_trait::async_trait;
|
||||
|
||||
use tracing::debug;
|
||||
use wgpu::{BindGroup, BindGroupLayout};
|
||||
use wgpu::util::DeviceExt;
|
||||
use winit::window::Window;
|
||||
|
@ -55,7 +56,6 @@ pub struct BasicRenderer {
|
|||
|
||||
buffer_storage: HashMap<Entity, RenderBufferStorage>, // TODO: clean up left over buffers from deleted entities/components
|
||||
|
||||
transform_uniform: Transform,
|
||||
transform_bind_group: wgpu::BindGroup,
|
||||
transform_buffer: wgpu::Buffer,
|
||||
}
|
||||
|
@ -115,10 +115,6 @@ impl BasicRenderer {
|
|||
};
|
||||
surface.configure(&device, &config);
|
||||
|
||||
|
||||
/* let diffuse_bytes = include_bytes!("../../res/happy-tree.png");
|
||||
let diffuse_texture = RenderTexture::from_bytes(&device, &queue, diffuse_bytes, "happy-tree.png").unwrap(); */
|
||||
|
||||
let texture_bind_group_layout =
|
||||
device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
|
||||
entries: &[
|
||||
|
@ -144,52 +140,16 @@ impl BasicRenderer {
|
|||
label: Some("texture_bind_group_layout"),
|
||||
});
|
||||
|
||||
let transform_bind_group_layout =
|
||||
device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
|
||||
entries: &[
|
||||
wgpu::BindGroupLayoutEntry {
|
||||
binding: 0,
|
||||
visibility: wgpu::ShaderStages::FRAGMENT,
|
||||
ty: wgpu::BindingType::Texture {
|
||||
multisampled: false,
|
||||
view_dimension: wgpu::TextureViewDimension::D2,
|
||||
sample_type: wgpu::TextureSampleType::Float { filterable: true },
|
||||
},
|
||||
count: None,
|
||||
},
|
||||
],
|
||||
label: Some("texture_bind_group_layout"),
|
||||
});
|
||||
|
||||
/* let diffuse_bind_group = device.create_bind_group(
|
||||
&wgpu::BindGroupDescriptor {
|
||||
layout: &texture_bind_group_layout,
|
||||
entries: &[
|
||||
wgpu::BindGroupEntry {
|
||||
binding: 0,
|
||||
resource: wgpu::BindingResource::TextureView(diffuse_texture.view()),
|
||||
},
|
||||
wgpu::BindGroupEntry {
|
||||
binding: 1,
|
||||
resource: wgpu::BindingResource::Sampler(diffuse_texture.sampler()),
|
||||
}
|
||||
],
|
||||
label: Some("diffuse_bind_group"),
|
||||
}
|
||||
); */
|
||||
|
||||
|
||||
let shader_src = resources::load_string("shader/base_2d.wgsl").await.expect("Failed to load shader!");
|
||||
let shader = device.create_shader_module(wgpu::ShaderModuleDescriptor {
|
||||
label: Some("Shader"),
|
||||
source: wgpu::ShaderSource::Wgsl(Cow::Borrowed(&shader_src)),
|
||||
});
|
||||
|
||||
let transform_uniform = Transform::new();
|
||||
let transform_buffer = device.create_buffer_init(
|
||||
&wgpu::util::BufferInitDescriptor {
|
||||
label: Some("Camera Buffer"),
|
||||
contents: bytemuck::cast_slice(&[transform_uniform]),
|
||||
label: Some("Transform Buffer"),
|
||||
contents: bytemuck::cast_slice(&[Transform::new()]),
|
||||
usage: wgpu::BufferUsages::UNIFORM | wgpu::BufferUsages::COPY_DST,
|
||||
}
|
||||
);
|
||||
|
@ -221,8 +181,6 @@ impl BasicRenderer {
|
|||
label: Some("transform_bind_group"),
|
||||
});
|
||||
|
||||
|
||||
|
||||
let mut pipelines = HashMap::new();
|
||||
pipelines.insert(0, Arc::new(FullRenderPipeline::new(&device, &config, &shader,
|
||||
vec![super::vertex::Vertex::desc(),], vec![&texture_bind_group_layout, &transform_bind_group_layout])));
|
||||
|
@ -244,7 +202,6 @@ impl BasicRenderer {
|
|||
render_jobs: HashMap::new(),
|
||||
buffer_storage: HashMap::new(),
|
||||
|
||||
transform_uniform,
|
||||
transform_buffer,
|
||||
transform_bind_group,
|
||||
}
|
||||
|
@ -339,7 +296,14 @@ impl BasicRenderer {
|
|||
impl Renderer for BasicRenderer {
|
||||
async fn prepare(&mut self, main_world: &World) {
|
||||
for (entity, (model, transform)) in main_world.query::<(&Model2dComponent, Option<&TransformComponent>)>().iter() {
|
||||
let job = RenderJob::new(model.mesh.clone(), model.material.clone(), entity);
|
||||
let transform = match transform {
|
||||
Some(transform) => {
|
||||
Some(transform.transform)
|
||||
},
|
||||
None => None,
|
||||
};
|
||||
|
||||
let job = RenderJob::new(model.mesh.clone(), model.material.clone(), entity, transform, None);
|
||||
|
||||
// Insert the new job into the queue
|
||||
if let Some(shader_jobs) = self.render_jobs.get_mut(&model.material.shader_id) {
|
||||
|
@ -352,15 +316,7 @@ impl Renderer for BasicRenderer {
|
|||
let buffers = self.create_model_buffers(model);
|
||||
self.buffer_storage.insert(entity, buffers);
|
||||
} else {
|
||||
let mesh = &model.mesh;
|
||||
|
||||
// update existing buffers
|
||||
}
|
||||
|
||||
if let Some(transform) = transform {
|
||||
self.transform_uniform = transform.transform;
|
||||
|
||||
self.queue.write_buffer(&self.transform_buffer, 0, bytemuck::cast_slice(&[self.transform_uniform]));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -400,13 +356,19 @@ impl Renderer for BasicRenderer {
|
|||
if let Some(jobs) = pipeline_jobs {
|
||||
for job in jobs.iter() {
|
||||
let mesh = job.mesh();
|
||||
let buffers = self.buffer_storage.get(&job.entity()).unwrap(); // TODO: create buffers if not made
|
||||
let buffers = self.buffer_storage.get(&job.entity()).unwrap();
|
||||
|
||||
if let Some(tex) = buffers.texture_bindgroup.as_ref() {
|
||||
render_pass.set_bind_group(0, &tex, &[]);
|
||||
}
|
||||
|
||||
// If the job has a transform, set the uniform to it
|
||||
if let Some(transform) = job.transform {
|
||||
self.queue.write_buffer(&self.transform_buffer, 0, bytemuck::cast_slice(&[transform]));
|
||||
render_pass.set_bind_group(1, &self.transform_bind_group, &[]);
|
||||
} else {
|
||||
debug!("//TODO: clear transform uniform if the RenderJob doesn't have a transform.");
|
||||
}
|
||||
|
||||
if let Some(indices) = buffers.buffer_indices.as_ref() {
|
||||
let indices_len = indices.count().unwrap(); // index buffers will have count, if not thats a bug
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
use glam::Vec3;
|
||||
use glam::{Vec3, Mat4, Quat};
|
||||
|
||||
use crate::math::angle::{self, Angle};
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Debug, Copy, Clone, bytemuck::Pod, bytemuck::Zeroable)]
|
||||
|
@ -14,33 +16,115 @@ impl Default for Transform {
|
|||
}
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
impl Transform {
|
||||
pub fn new() -> Self {
|
||||
Self::default()
|
||||
}
|
||||
|
||||
pub fn from_glam(matrix: glam::Mat4) -> Self {
|
||||
pub fn from_matrix(matrix: glam::Mat4) -> Self {
|
||||
Self {
|
||||
matrix,
|
||||
}
|
||||
}
|
||||
|
||||
/// Create Transform from scale, rotation (in degrees), and translation
|
||||
pub fn from_scale_rotation_deg_translation(scale: Vec3, mut rotation: Vec3, translation: Vec3) -> Self {
|
||||
rotation.x = angle::degrees_to_radians(rotation.x);
|
||||
rotation.y = angle::degrees_to_radians(rotation.y);
|
||||
rotation.z = angle::degrees_to_radians(rotation.z);
|
||||
let rotation_quat = glam::Quat::from_euler(glam::EulerRot::XYZ, rotation.x, rotation.y, rotation.z);
|
||||
|
||||
let matrix = glam::Mat4::from_scale_rotation_translation(scale, rotation_quat, translation);
|
||||
|
||||
Self::from_matrix(matrix)
|
||||
}
|
||||
|
||||
/// Create Transform from scale, rotation (in radians), and translation
|
||||
pub fn from_scale_rotation_rad_translation(scale: Vec3, rotation: Vec3, translation: Vec3) -> Self {
|
||||
let rotation_quat = glam::Quat::from_euler(glam::EulerRot::XYZ, rotation.x, rotation.y, rotation.z);
|
||||
let matrix = glam::Mat4::from_scale_rotation_translation(scale, rotation_quat, translation);
|
||||
|
||||
Self::from_matrix(matrix)
|
||||
}
|
||||
|
||||
/// Create Transform from scale, rotation (as a quaternion), and translation
|
||||
pub fn from_scale_rotation_quat_translation(scale: Vec3, rotation: Quat, translation: Vec3) -> Self {
|
||||
let matrix = glam::Mat4::from_scale_rotation_translation(scale, rotation, translation);
|
||||
|
||||
Self::from_matrix(matrix)
|
||||
}
|
||||
|
||||
pub fn translate_vec3(&mut self, vec: Vec3) -> &mut Self {
|
||||
/* let first_col = self.matrix.col(0);
|
||||
let second_col = self.matrix.col(1);
|
||||
let third_col = self.matrix.col(2);
|
||||
|
||||
//let fourth_col = self.matrix.col_mut(3);
|
||||
let w_axis = &mut self.matrix.w_axis;
|
||||
//first_col.w
|
||||
//fourth_col = fourth_col.x * vec.x + second_col * vec.y + third_col * vec.z + fourth_col.clone();
|
||||
w_axis.x += vec.x;
|
||||
w_axis.y += vec.y;
|
||||
w_axis.z += vec.z; */
|
||||
|
||||
let translation = glam::Mat4::from_translation(vec);
|
||||
self.matrix *= translation;
|
||||
|
||||
self
|
||||
}
|
||||
|
||||
/// Rotate around the given axis.
|
||||
pub fn rotate_axis(&mut self, axis: Vec3, angle: Angle) -> &mut Self {
|
||||
let radians = angle.to_radians();
|
||||
|
||||
let rotation = glam::Mat4::from_axis_angle(axis, radians);
|
||||
self.matrix *= rotation;
|
||||
|
||||
self
|
||||
}
|
||||
|
||||
// Rotate the transform with degrees
|
||||
pub fn rotate_degrees(&mut self, mut x: f32, mut y: f32, mut z: f32) -> &mut Self {
|
||||
// Convert degrees to radians
|
||||
x = angle::degrees_to_radians(x);
|
||||
y = angle::degrees_to_radians(y);
|
||||
z = angle::degrees_to_radians(z);
|
||||
|
||||
let rotation = glam::Mat4::from_euler(glam::EulerRot::XYZ, x, y, z);
|
||||
self.matrix *= rotation;
|
||||
|
||||
self
|
||||
}
|
||||
|
||||
// Rotate the transform with degrees in a vec
|
||||
pub fn rotate_degrees_vec(&mut self, mut rotation: Vec3) -> &mut Self {
|
||||
self.rotate_degrees(rotation.x, rotation.y, rotation.z)
|
||||
}
|
||||
|
||||
// Rotate the transform with radians
|
||||
pub fn rotate_radians(&mut self, rotation: Vec3) -> &mut Self {
|
||||
let rotation = glam::Mat4::from_euler(glam::EulerRot::XYZ, rotation.x, rotation.y, rotation.z);
|
||||
self.matrix *= rotation;
|
||||
|
||||
self
|
||||
}
|
||||
|
||||
/// Rotate the transform with a quaternion
|
||||
pub fn rotate_quat(&mut self, quat: glam::Quat) -> &mut Self {
|
||||
let rotation = glam::Mat4::from_quat(quat);
|
||||
self.matrix *= rotation;
|
||||
|
||||
self
|
||||
}
|
||||
|
||||
/// Rotate around the x axis.
|
||||
pub fn rotate_x(&mut self, angle: Angle) -> &mut Self {
|
||||
self.rotate_axis(Vec3::new(1.0, 0.0, 0.0), angle)
|
||||
}
|
||||
|
||||
/// Rotate around the y axis.
|
||||
pub fn rotate_y(&mut self, angle: Angle) -> &mut Self {
|
||||
self.rotate_axis(Vec3::new(0.0, 1.0, 0.0), angle)
|
||||
}
|
||||
|
||||
/// Rotate around the z axis.
|
||||
pub fn rotate_z(&mut self, angle: Angle) -> &mut Self {
|
||||
self.rotate_axis(Vec3::new(0.0, 0.0, 0.0), angle)
|
||||
}
|
||||
|
||||
pub fn scale(&mut self, scale: Vec3) -> &mut Self {
|
||||
let scale = Mat4::from_scale(scale);
|
||||
self.matrix *= scale;
|
||||
|
||||
self
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue