Files
nodarium/packages/utils/src/geometry/extrude_path.rs

113 lines
4.0 KiB
Rust

use super::{create_geometry_data, wrap_geometry_data};
use glam::{Mat4, Quat, Vec3};
fn create_circle(res: usize) -> Vec<f32> {
let angle = (2.0 * std::f32::consts::PI) / res as f32;
let mut circle = Vec::new();
for i in 0..res {
circle.push((angle * i as f32).cos());
circle.push((angle * i as f32).sin());
}
circle
}
#[rustfmt::skip]
pub fn extrude_path(input_path: &[i32], res_x: usize) -> Vec<i32> {
let point_amount = input_path.len() / 4;
let face_amount = (point_amount - 1) * res_x * 2;
let vertices_amount = point_amount * res_x;
let circle = create_circle(res_x);
let mut geometry_data = create_geometry_data(vertices_amount, face_amount);
let geometry = wrap_geometry_data(&mut geometry_data);
let normals = geometry.normals;
let positions = geometry.positions;
let indices = geometry.faces;
let path: &[f32];
unsafe {
path = std::slice::from_raw_parts(input_path.as_ptr() as *const f32, input_path.len());
}
for i in 0..point_amount {
let index_offset = i * res_x * 6;
let position_offset = i * res_x;
let point = Vec3::from_slice(&path[i*4..i*4+3]);
let thickness = path[i*4+3];
let next_point = if i == point_amount - 1 { point } else { Vec3::from_slice(&path[(i+1)*4..(i+1)*4+3]) };
let prev_point = if i == 0 { point } else { Vec3::from_slice(&path[(i-1)*4..(i-1)*4+3]) };
let mut v = if i == 0 {
point - next_point
} else if i == point_amount - 1 {
prev_point - point
} else {
prev_point - next_point
};
v = v.normalize();
let n = Vec3::new(0.0, -1.0, 0.0); // Assuming 'n' is the up vector or similar
let axis = n.cross(v);
let angle = n.dot(v).acos();
let quat = Quat::from_axis_angle(axis, angle).normalize();
let mat = Mat4::IDENTITY * Mat4::from_quat(quat);
for j in 0..res_x {
if i < point_amount - 1 {
let i_index_offset = index_offset + j * 6;
let i_position_offset = position_offset + j;
//log!("i: {}, j: {}, i_index_offset: {}, i_position_offset: {} res_x: {}", i, j, i_index_offset, i_position_offset,res_x);
if j == res_x - 1 {
indices[i_index_offset ] = (i_position_offset + 1) as i32;
indices[i_index_offset + 1] = (i_position_offset + 1 - res_x) as i32;
indices[i_index_offset + 2] = (i_position_offset) as i32;
indices[i_index_offset + 3] = (i_position_offset) as i32;
indices[i_index_offset + 4] = (i_position_offset + res_x) as i32;
indices[i_index_offset + 5] = (i_position_offset + 1) as i32;
} else {
indices[i_index_offset ] = (i_position_offset + res_x + 1) as i32;
indices[i_index_offset + 1] = (i_position_offset + 1) as i32;
indices[i_index_offset + 2] = (i_position_offset) as i32;
indices[i_index_offset + 3] = (i_position_offset) as i32;
indices[i_index_offset + 4] = (i_position_offset + res_x) as i32;
indices[i_index_offset + 5] = (i_position_offset + res_x + 1) as i32;
}
}
// construct the points
let idx = i * res_x * 3 + j * 3;
let circle_x = circle[j * 2 ] * thickness;
let circle_y = circle[j * 2 + 1] * thickness;
let _pt = Vec3::new(
point[0] + circle_x,
point[1],
point[2] + circle_y,
);
let pt = Mat4::transform_vector3(&mat, _pt) + point;
normals[idx ] = circle_x;
normals[idx + 1] = 0.0;
normals[idx + 2] = circle_y;
positions[idx ] = pt[0];
positions[idx + 1] = pt[1];
positions[idx + 2] = pt[2];
}
}
geometry_data
}