Update transform
This commit is contained in:
parent
1a61aab218
commit
4f96a1e4b5
2 changed files with 99 additions and 26 deletions
|
@ -10,13 +10,17 @@ use vulkano::{
|
||||||
|
|
||||||
use crate::core::render::primitives::{AsBindableBuffer, AsVertexBuffer};
|
use crate::core::render::primitives::{AsBindableBuffer, AsVertexBuffer};
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
pub struct Transform {
|
pub struct Transform {
|
||||||
pub position: Vec3,
|
pub position: Vec3,
|
||||||
pub rotation: Quat,
|
pub rotation: Quat,
|
||||||
pub scale: Vec3,
|
pub scale: Vec3,
|
||||||
|
// Cache to avoid unnecessary recalculations
|
||||||
|
cached_matrix: Option<Mat4>,
|
||||||
|
dirty: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(BufferContents, Vertex, Clone, Copy)]
|
#[derive(BufferContents, Vertex, Clone, Copy, Debug)]
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
pub struct TransformRaw {
|
pub struct TransformRaw {
|
||||||
#[format(R32G32B32A32_SFLOAT)]
|
#[format(R32G32B32A32_SFLOAT)]
|
||||||
|
@ -26,49 +30,113 @@ pub struct TransformRaw {
|
||||||
impl Default for Transform {
|
impl Default for Transform {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self {
|
Self {
|
||||||
position: Vec3::default(),
|
position: Vec3::ZERO,
|
||||||
rotation: Quat::default(),
|
rotation: Quat::IDENTITY,
|
||||||
scale: Vec3::ONE,
|
scale: Vec3::ONE,
|
||||||
|
cached_matrix: None,
|
||||||
|
dirty: true,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Transform {
|
impl Transform {
|
||||||
|
pub fn new(position: Vec3, rotation: Quat, scale: Vec3) -> Self {
|
||||||
|
Self {
|
||||||
|
position,
|
||||||
|
rotation,
|
||||||
|
scale,
|
||||||
|
cached_matrix: None,
|
||||||
|
dirty: true,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn rotate(&mut self, rotation: Quat) {
|
pub fn rotate(&mut self, rotation: Quat) {
|
||||||
self.rotation *= rotation;
|
self.rotation *= rotation;
|
||||||
|
self.mark_dirty();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn translate(&mut self, translation: Vec3) {
|
pub fn translate(&mut self, translation: Vec3) {
|
||||||
self.position += translation;
|
self.position += translation;
|
||||||
|
self.mark_dirty();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn scale(&mut self, scale: Vec3) {
|
pub fn scale(&mut self, scale: Vec3) {
|
||||||
self.scale *= scale;
|
self.scale *= scale;
|
||||||
|
self.mark_dirty();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn to_raw_tranform(&self) -> TransformRaw {
|
pub fn set_position(&mut self, position: Vec3) {
|
||||||
TransformRaw {
|
self.position = position;
|
||||||
model: (Mat4::from_translation(self.position)
|
self.mark_dirty();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_rotation(&mut self, rotation: Quat) {
|
||||||
|
self.rotation = rotation;
|
||||||
|
self.mark_dirty();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_scale(&mut self, scale: Vec3) {
|
||||||
|
self.scale = scale;
|
||||||
|
self.mark_dirty();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn mark_dirty(&mut self) {
|
||||||
|
self.dirty = true;
|
||||||
|
self.cached_matrix = None;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get the transformation matrix (immutable - recalculates each time)
|
||||||
|
pub fn matrix(&self) -> Mat4 {
|
||||||
|
Mat4::from_translation(self.position)
|
||||||
* Mat4::from_quat(self.rotation)
|
* Mat4::from_quat(self.rotation)
|
||||||
* Mat4::from_scale(self.scale))
|
* Mat4::from_scale(self.scale)
|
||||||
.to_cols_array_2d(),
|
}
|
||||||
|
|
||||||
|
/// Convert to GPU-ready format (immutable - recalculates each time)
|
||||||
|
pub fn to_raw(&self) -> TransformRaw {
|
||||||
|
TransformRaw {
|
||||||
|
model: self.matrix().to_cols_array_2d(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Create a buffer from transforms (immutable - recalculates each time)
|
||||||
pub fn create_buffer(
|
pub fn create_buffer(
|
||||||
memory_allocator: &Arc<StandardMemoryAllocator>,
|
memory_allocator: &Arc<StandardMemoryAllocator>,
|
||||||
transforms: &[Transform],
|
transforms: &[Transform],
|
||||||
) -> Result<Subbuffer<[TransformRaw]>, Validated<AllocateBufferError>> {
|
) -> Result<Subbuffer<[TransformRaw]>, Validated<AllocateBufferError>> {
|
||||||
TransformRaw::create_vertex_buffer(
|
TransformRaw::create_vertex_buffer(
|
||||||
memory_allocator,
|
memory_allocator,
|
||||||
&transforms
|
&transforms.iter().map(|t| t.to_raw()).collect::<Vec<_>>(),
|
||||||
.iter()
|
|
||||||
.map(|t| t.to_raw_tranform())
|
|
||||||
.collect::<Vec<_>>(),
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<&Transform> for TransformRaw {
|
||||||
|
fn from(transform: &Transform) -> Self {
|
||||||
|
transform.to_raw()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<Mat4> for TransformRaw {
|
||||||
|
fn from(matrix: Mat4) -> Self {
|
||||||
|
Self {
|
||||||
|
model: matrix.to_cols_array_2d(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TransformRaw {
|
||||||
|
pub fn from_matrix(matrix: Mat4) -> Self {
|
||||||
|
Self {
|
||||||
|
model: matrix.to_cols_array_2d(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn to_matrix(&self) -> Mat4 {
|
||||||
|
Mat4::from_cols_array_2d(&self.model)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl AsBindableBuffer<TransformRaw> for TransformRaw {
|
impl AsBindableBuffer<TransformRaw> for TransformRaw {
|
||||||
type BufferData = TransformRaw;
|
type BufferData = TransformRaw;
|
||||||
|
|
||||||
|
|
|
@ -58,19 +58,16 @@ impl Scene for MainScene {
|
||||||
let instance_spacing = 10.0;
|
let instance_spacing = 10.0;
|
||||||
let num_instances_per_row = (num_instances as f32 / instance_spacing).ceil() as u32;
|
let num_instances_per_row = (num_instances as f32 / instance_spacing).ceil() as u32;
|
||||||
let instances: Vec<Transform> = (0..num_instances)
|
let instances: Vec<Transform> = (0..num_instances)
|
||||||
.map(|i| Transform {
|
.map(|i| {
|
||||||
position: Vec3::new(
|
Transform::new(
|
||||||
|
Vec3::new(
|
||||||
(i % num_instances_per_row) as f32 * (instance_spacing + instance_size),
|
(i % num_instances_per_row) as f32 * (instance_spacing + instance_size),
|
||||||
0.0,
|
0.0,
|
||||||
(i / num_instances_per_row) as f32 * (instance_spacing + instance_size),
|
(i / num_instances_per_row) as f32 * (instance_spacing + instance_size),
|
||||||
),
|
),
|
||||||
rotation: Quat::from_euler(
|
Quat::from_euler(EulerRot::XYZ, 0.0, rand::random_range(0.0..=360.0), 0.0),
|
||||||
EulerRot::XYZ,
|
Vec3::new(instance_size, instance_size, instance_size),
|
||||||
0.0,
|
)
|
||||||
rand::random_range(0.0..=360.0),
|
|
||||||
0.0,
|
|
||||||
),
|
|
||||||
scale: Vec3::new(instance_size, instance_size, instance_size),
|
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
|
@ -129,6 +126,14 @@ impl Scene for MainScene {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
let delta_time = app_context.get_delta_time();
|
||||||
|
for (i, instance) in state.instances.iter_mut().enumerate() {
|
||||||
|
let rotation_speed = (i % 10) as f32;
|
||||||
|
let rotation_delta = Quat::from_rotation_y(rotation_speed * delta_time);
|
||||||
|
|
||||||
|
instance.rotate(rotation_delta);
|
||||||
|
}
|
||||||
|
|
||||||
if app_context
|
if app_context
|
||||||
.with_input_manager(|input_manager| input_manager.get_virtual_input_state("mouse_left"))
|
.with_input_manager(|input_manager| input_manager.get_virtual_input_state("mouse_left"))
|
||||||
> 0.0
|
> 0.0
|
||||||
|
@ -167,7 +172,7 @@ impl Scene for MainScene {
|
||||||
before_future: Box<dyn GpuFuture>,
|
before_future: Box<dyn GpuFuture>,
|
||||||
app_context: &mut WindowContext,
|
app_context: &mut WindowContext,
|
||||||
) -> Result<Box<dyn GpuFuture>, Box<dyn Error>> {
|
) -> Result<Box<dyn GpuFuture>, Box<dyn Error>> {
|
||||||
let state = self.state.as_ref().ok_or("State not loaded")?;
|
let state = self.state.as_mut().ok_or("State not loaded")?;
|
||||||
|
|
||||||
let mut builder = AutoCommandBufferBuilder::primary(
|
let mut builder = AutoCommandBufferBuilder::primary(
|
||||||
app_context.command_buffer_allocator.clone(),
|
app_context.command_buffer_allocator.clone(),
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue