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};
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Transform {
|
||||
pub position: Vec3,
|
||||
pub rotation: Quat,
|
||||
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)]
|
||||
pub struct TransformRaw {
|
||||
#[format(R32G32B32A32_SFLOAT)]
|
||||
|
@ -26,49 +30,113 @@ pub struct TransformRaw {
|
|||
impl Default for Transform {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
position: Vec3::default(),
|
||||
rotation: Quat::default(),
|
||||
position: Vec3::ZERO,
|
||||
rotation: Quat::IDENTITY,
|
||||
scale: Vec3::ONE,
|
||||
cached_matrix: None,
|
||||
dirty: true,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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) {
|
||||
self.rotation *= rotation;
|
||||
self.mark_dirty();
|
||||
}
|
||||
|
||||
pub fn translate(&mut self, translation: Vec3) {
|
||||
self.position += translation;
|
||||
self.mark_dirty();
|
||||
}
|
||||
|
||||
pub fn scale(&mut self, scale: Vec3) {
|
||||
self.scale *= scale;
|
||||
self.mark_dirty();
|
||||
}
|
||||
|
||||
pub fn to_raw_tranform(&self) -> TransformRaw {
|
||||
TransformRaw {
|
||||
model: (Mat4::from_translation(self.position)
|
||||
pub fn set_position(&mut self, position: Vec3) {
|
||||
self.position = 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_scale(self.scale))
|
||||
.to_cols_array_2d(),
|
||||
* Mat4::from_scale(self.scale)
|
||||
}
|
||||
|
||||
/// 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(
|
||||
memory_allocator: &Arc<StandardMemoryAllocator>,
|
||||
transforms: &[Transform],
|
||||
) -> Result<Subbuffer<[TransformRaw]>, Validated<AllocateBufferError>> {
|
||||
TransformRaw::create_vertex_buffer(
|
||||
memory_allocator,
|
||||
&transforms
|
||||
.iter()
|
||||
.map(|t| t.to_raw_tranform())
|
||||
.collect::<Vec<_>>(),
|
||||
&transforms.iter().map(|t| t.to_raw()).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 {
|
||||
type BufferData = TransformRaw;
|
||||
|
||||
|
|
|
@ -58,19 +58,16 @@ impl Scene for MainScene {
|
|||
let instance_spacing = 10.0;
|
||||
let num_instances_per_row = (num_instances as f32 / instance_spacing).ceil() as u32;
|
||||
let instances: Vec<Transform> = (0..num_instances)
|
||||
.map(|i| Transform {
|
||||
position: Vec3::new(
|
||||
.map(|i| {
|
||||
Transform::new(
|
||||
Vec3::new(
|
||||
(i % num_instances_per_row) as f32 * (instance_spacing + instance_size),
|
||||
0.0,
|
||||
(i / num_instances_per_row) as f32 * (instance_spacing + instance_size),
|
||||
),
|
||||
rotation: Quat::from_euler(
|
||||
EulerRot::XYZ,
|
||||
0.0,
|
||||
rand::random_range(0.0..=360.0),
|
||||
0.0,
|
||||
),
|
||||
scale: Vec3::new(instance_size, instance_size, instance_size),
|
||||
Quat::from_euler(EulerRot::XYZ, 0.0, rand::random_range(0.0..=360.0), 0.0),
|
||||
Vec3::new(instance_size, instance_size, instance_size),
|
||||
)
|
||||
})
|
||||
.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
|
||||
.with_input_manager(|input_manager| input_manager.get_virtual_input_state("mouse_left"))
|
||||
> 0.0
|
||||
|
@ -167,7 +172,7 @@ impl Scene for MainScene {
|
|||
before_future: Box<dyn GpuFuture>,
|
||||
app_context: &mut WindowContext,
|
||||
) -> 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(
|
||||
app_context.command_buffer_allocator.clone(),
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue