feat: instance node
All checks were successful
Deploy to GitHub Pages / build_site (push) Successful in 2m44s

This commit is contained in:
2024-05-06 01:10:23 +02:00
parent a01a409b97
commit 10a12ad41c
20 changed files with 695 additions and 147 deletions

View File

@ -1,7 +1,7 @@
use crate::{decode_float, encode_float};
use glam::Vec3;
pub fn calculate_normals(geometry: &mut [i32]) {
pub fn calculate_normals(geometry: &mut [i32]) -> &mut [i32] {
let vertex_count = geometry[1] as usize;
let face_count = geometry[2] as usize;
let index_start = 3;
@ -47,4 +47,5 @@ pub fn calculate_normals(geometry: &mut [i32]) {
geometry[normals_start + idx + 2] = encode_float(normal.z);
}
}
geometry
}

View File

@ -11,6 +11,30 @@ pub struct GeometryData<'a> {
pub faces: &'a mut [i32], // View into `data`
}
impl GeometryData<'_> {
pub fn set_position(&mut self, index: usize, x: f32, y: f32, z: f32) {
assert!(index < self.positions.len() / 3, "Index out of bounds.");
let i = index * 3;
self.positions[i] = x;
self.positions[i + 1] = y;
self.positions[i + 2] = z;
}
pub fn set_normal(&mut self, index: usize, x: f32, y: f32, z: f32) {
assert!(index < self.normals.len() / 3, "Index out of bounds.");
let i = index * 3;
self.normals[i] = x;
self.normals[i + 1] = y;
self.normals[i + 2] = z;
}
pub fn set_face(&mut self, index: usize, a: i32, b: i32, c: i32) {
assert!(index < self.faces.len() / 3, "Index out of bounds.");
let i = index * 3;
self.faces[i] = a;
self.faces[i + 1] = b;
self.faces[i + 2] = c;
}
}
pub fn create_geometry_data(vertex_amount: usize, face_amount: usize) -> Vec<i32> {
let amount = GEOMETRY_HEADER_SIZE // definition (type, vertex_amount, face_amount)
+ 4 // opening and closing brackets

View File

@ -0,0 +1,118 @@
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,
}
}

View File

@ -1,6 +1,7 @@
mod calculate_normals;
mod extrude_path;
mod geometry_data;
mod instance_data;
mod math;
mod path_data;
mod transform;
@ -8,6 +9,7 @@ mod transform;
pub use calculate_normals::*;
pub use extrude_path::*;
pub use geometry_data::*;
pub use instance_data::*;
pub use math::*;
pub use path_data::*;
pub use transform::*;

View File

@ -31,6 +31,7 @@ impl PathDataMut<'_> {
}
}
#[derive(Debug)]
pub struct PathData<'a> {
pub depth: i32,
pub length: usize,
@ -55,6 +56,15 @@ impl PathData<'_> {
}
l
}
pub fn get_point_at(&self, alpha: f32) -> [f32; 4] {
get_point_at_path(self.points, alpha)
}
pub fn get_direction_at(&self, alpha: f32) -> [f32; 3] {
get_direction_at_path(self.points, alpha)
}
pub fn interpolate_along(&self, alpha: f32) -> (Vec4, Vec3, Vec3) {
interpolate_along_path(self.points, alpha)
}
}
pub fn create_multiple_paths(amount: usize, point_amount: usize, depth: i32) -> Vec<i32> {

View File

@ -118,11 +118,12 @@ pub fn concat_args(mut data: Vec<&[i32]>) -> Vec<i32> {
}
pub fn wrap_arg(arg: &[i32]) -> Vec<i32> {
let mut out_args = Vec::with_capacity(arg.len() + 8);
out_args.extend_from_slice(&[0, 1, 0, arg.len() as i32 + 1]);
let mut out_args = Vec::with_capacity(arg.len() + 4);
out_args.push(0);
out_args.push(arg.len() as i32 + 1);
out_args.extend_from_slice(arg);
out_args.extend_from_slice(&[1, 1]);
out_args.extend_from_slice(&[1, 1]);
out_args.push(1);
out_args.push(1);
out_args
}