flow_ngin/data_structures/
instance.rs1use std::ops::{Add, Mul};
7
8use cgmath::{One, SquareMatrix};
9
10use crate::data_structures::model;
11
12#[derive(Clone, Debug)]
18pub struct Instance {
19 pub position: cgmath::Vector3<f32>,
20 pub rotation: cgmath::Quaternion<f32>,
21 pub scale: cgmath::Vector3<f32>,
22}
23
24impl Instance {
25 pub fn new() -> Self {
27 Self {
28 position: cgmath::Vector3::new(0.0, 0.0, 0.0),
29 rotation: cgmath::Quaternion::one(),
31 scale: cgmath::Vector3::new(1.0, 1.0, 1.0),
32 }
33 }
34
35 pub fn to_matrix(&self) -> cgmath::Matrix4<f32> {
36 cgmath::Matrix4::from_translation(self.position)
37 * cgmath::Matrix4::from(self.rotation)
38 * cgmath::Matrix4::from_nonuniform_scale(self.scale.x, self.scale.y, self.scale.z)
39 }
40
41 pub fn to_raw(&self) -> InstanceRaw {
42 let world_matrix = self.to_matrix();
43 let det = world_matrix.determinant();
44 let handedness = det.signum();
45 InstanceRaw {
46 model: self.to_matrix().into(),
47 normal: cgmath::Matrix3::from(self.rotation).into(),
48 handedness: handedness,
49 }
50 }
51}
52
53impl Mul<Instance> for Instance {
54 type Output = Self;
55
56 fn mul(self, rhs: Instance) -> Self::Output {
57 let new_rotation = self.rotation * rhs.rotation;
58
59 let new_scale = cgmath::Vector3::new(
60 self.scale.x * rhs.scale.x,
61 self.scale.y * rhs.scale.y,
62 self.scale.z * rhs.scale.z,
63 );
64 let scaled_rhs_pos = cgmath::Vector3::new(
65 self.scale.x * rhs.position.x,
66 self.scale.y * rhs.position.y,
67 self.scale.z * rhs.position.z,
68 );
69 let new_position = self.position + (self.rotation * scaled_rhs_pos);
70
71 Instance {
72 position: new_position,
73 rotation: new_rotation,
74 scale: new_scale,
75 }
76 }
77}
78
79impl Add<Instance> for Instance {
80 type Output = Self;
81
82 fn add(self, rhs: Instance) -> Self::Output {
83 Instance {
84 position: self.position + rhs.position,
85 rotation: self.rotation + rhs.rotation,
86 scale: self.scale + rhs.scale,
87 }
88 }
89}
90
91impl<'a, 'b> Mul<&'b Instance> for &'a Instance {
92 type Output = Instance;
93
94 fn mul(self, rhs: &'b Instance) -> Self::Output {
95 let new_rotation = self.rotation * rhs.rotation;
96
97 let new_scale = cgmath::Vector3::new(
98 self.scale.x * rhs.scale.x,
99 self.scale.y * rhs.scale.y,
100 self.scale.z * rhs.scale.z,
101 );
102 let scaled_rhs_pos = cgmath::Vector3::new(
103 self.scale.x * rhs.position.x,
104 self.scale.y * rhs.position.y,
105 self.scale.z * rhs.position.z,
106 );
107 let new_position = self.position + (self.rotation * scaled_rhs_pos);
108
109 Instance {
110 position: new_position,
111 rotation: new_rotation,
112 scale: new_scale,
113 }
114 }
115}
116
117impl<'a, 'b> Add<&'b Instance> for &'a Instance {
118 type Output = Instance;
119
120 fn add(self, rhs: &'b Instance) -> Self::Output {
121 Instance {
122 position: self.position + rhs.position,
123 rotation: self.rotation + rhs.rotation,
124 scale: self.scale + rhs.scale,
125 }
126 }
127}
128
129impl From<cgmath::Vector3<f32>> for Instance {
130 fn from(position: cgmath::Vector3<f32>) -> Self {
131 Instance {
132 position,
133 ..Default::default()
134 }
135 }
136}
137
138impl Default for Instance {
139 fn default() -> Self {
140 Self::new()
141 }
142}
143
144#[repr(C)]
148#[derive(Debug, Copy, Clone, bytemuck::Pod, bytemuck::Zeroable)]
149#[allow(dead_code)]
150pub struct InstanceRaw {
151 model: [[f32; 4]; 4],
152 normal: [[f32; 3]; 3],
153 handedness: f32,
154}
155
156impl model::Vertex for InstanceRaw {
165 fn desc() -> wgpu::VertexBufferLayout<'static> {
166 use std::mem;
167 wgpu::VertexBufferLayout {
168 array_stride: mem::size_of::<InstanceRaw>() as wgpu::BufferAddress,
169 step_mode: wgpu::VertexStepMode::Instance,
173 attributes: &[
174 wgpu::VertexAttribute {
175 offset: 0,
176 shader_location: 5,
177 format: wgpu::VertexFormat::Float32x4,
178 },
179 wgpu::VertexAttribute {
182 offset: mem::size_of::<[f32; 4]>() as wgpu::BufferAddress,
183 shader_location: 6,
185 format: wgpu::VertexFormat::Float32x4,
186 },
187 wgpu::VertexAttribute {
188 offset: mem::size_of::<[f32; 8]>() as wgpu::BufferAddress,
189 shader_location: 7,
190 format: wgpu::VertexFormat::Float32x4,
191 },
192 wgpu::VertexAttribute {
193 offset: mem::size_of::<[f32; 12]>() as wgpu::BufferAddress,
194 shader_location: 8,
195 format: wgpu::VertexFormat::Float32x4,
196 },
197 wgpu::VertexAttribute {
199 offset: mem::size_of::<[f32; 16]>() as wgpu::BufferAddress,
200 shader_location: 9,
201 format: wgpu::VertexFormat::Float32x3,
202 },
203 wgpu::VertexAttribute {
204 offset: mem::size_of::<[f32; 19]>() as wgpu::BufferAddress,
205 shader_location: 10,
206 format: wgpu::VertexFormat::Float32x3,
207 },
208 wgpu::VertexAttribute {
209 offset: mem::size_of::<[f32; 22]>() as wgpu::BufferAddress,
210 shader_location: 11,
211 format: wgpu::VertexFormat::Float32x3,
212 },
213 wgpu::VertexAttribute {
214 offset: mem::size_of::<[f32; 25]>() as wgpu::BufferAddress,
215 shader_location: 12,
216 format: wgpu::VertexFormat::Float32,
217 },
218 ],
219 }
220 }
221}