All checks were successful
Deploy to GitHub Pages / build_site (push) Successful in 2m44s
119 lines
3.5 KiB
Rust
119 lines
3.5 KiB
Rust
use super::GeometryData;
|
|
|
|
pub struct InstanceData<'a> {
|
|
pub instances: &'a mut [f32], // View into `data`
|
|
pub instance_amount: usize,
|
|
pub positions: &'a mut [f32], // View into `data`
|
|
pub normals: &'a mut [f32], // View into `data`
|
|
pub faces: &'a mut [i32], // View into `data`
|
|
}
|
|
|
|
impl InstanceData<'_> {
|
|
pub fn set_geometry(&mut self, geometry: GeometryData) {
|
|
assert_eq!(self.positions.len(), geometry.positions.len());
|
|
|
|
for i in 0..self.positions.len() {
|
|
self.positions[i] = geometry.positions[i];
|
|
}
|
|
for i in 0..self.normals.len() {
|
|
self.normals[i] = geometry.normals[i];
|
|
}
|
|
for i in 0..self.faces.len() {
|
|
self.faces[i] = geometry.faces[i];
|
|
}
|
|
}
|
|
|
|
pub fn set_transformation_matrix(&mut self, index: usize, matrix: &[f32; 16]) {
|
|
assert_eq!(matrix.len(), 16, "Matrix length must be 16.");
|
|
assert!(
|
|
index * 16 + 16 <= self.instances.len(),
|
|
"Matrix does not fit. index: {} len: {}",
|
|
index,
|
|
self.instances.len()
|
|
);
|
|
|
|
(0..16).for_each(|i| {
|
|
self.instances[index * 16 + i] = matrix[i];
|
|
});
|
|
}
|
|
}
|
|
|
|
static INSTANCE_HEADER_SIZE: usize = 5;
|
|
// 0: type instance = 2;
|
|
// 1: vertex amount
|
|
// 2: face amount
|
|
// 3: stem_depth
|
|
// 4: instance amount
|
|
|
|
pub fn create_instance_data(
|
|
vertex_amount: usize,
|
|
face_amount: usize,
|
|
instance_amount: usize,
|
|
) -> Vec<i32> {
|
|
let amount = INSTANCE_HEADER_SIZE // definition (type, vertex_amount, face_amount, instance_amount)
|
|
+ 4 // opening and closing brackets
|
|
+ instance_amount * 16 // instances stored as 4x4 matrices
|
|
+ vertex_amount * 3 // positions
|
|
+ vertex_amount * 3 // normals
|
|
+ face_amount * 3; // faces
|
|
|
|
let mut geo = vec![0; amount];
|
|
|
|
geo[0] = 0; // opening bracket
|
|
geo[1] = amount as i32 - 3; // opening bracket
|
|
geo[2] = 2; // type: instance
|
|
geo[3] = vertex_amount as i32;
|
|
geo[4] = face_amount as i32;
|
|
geo[5] = instance_amount as i32;
|
|
geo[6] = 1; // stem_depth
|
|
|
|
geo[amount - 2] = 1; // closing bracket
|
|
geo[amount - 1] = 1; // closing bracket
|
|
|
|
geo
|
|
}
|
|
|
|
pub fn wrap_instance_data(instances: &mut [i32]) -> InstanceData {
|
|
assert!(
|
|
instances.len() > INSTANCE_HEADER_SIZE,
|
|
"Instance vector does not contain enough data for a header."
|
|
);
|
|
|
|
let (header, rest) = instances.split_at_mut(2 + INSTANCE_HEADER_SIZE);
|
|
|
|
let vertices_amount = header[3] as usize;
|
|
let face_amount = header[4] as usize;
|
|
let instance_amount = header[5] as usize;
|
|
|
|
let (faces, rest) = rest.split_at_mut(face_amount * 3);
|
|
let (positions_slice, rest) = rest.split_at_mut(vertices_amount * 3);
|
|
let (normals_slice, rest) = rest.split_at_mut(vertices_amount * 3);
|
|
let (instances_slice, _) = rest.split_at_mut(instance_amount * 16);
|
|
|
|
let positions: &mut [f32] = unsafe {
|
|
std::slice::from_raw_parts_mut(
|
|
positions_slice.as_mut_ptr() as *mut f32,
|
|
positions_slice.len(),
|
|
)
|
|
};
|
|
|
|
let normals: &mut [f32] = unsafe {
|
|
std::slice::from_raw_parts_mut(normals_slice.as_mut_ptr() as *mut f32, normals_slice.len())
|
|
};
|
|
|
|
let instances: &mut [f32] = unsafe {
|
|
std::slice::from_raw_parts_mut(
|
|
instances_slice.as_mut_ptr() as *mut f32,
|
|
instances_slice.len(),
|
|
)
|
|
};
|
|
|
|
InstanceData {
|
|
instances,
|
|
instance_amount,
|
|
positions,
|
|
normals,
|
|
faces,
|
|
}
|
|
}
|