All checks were successful
Deploy to GitHub Pages / build_site (push) Successful in 1m52s
118 lines
4.2 KiB
Rust
118 lines
4.2 KiB
Rust
use super::{create_geometry_data, wrap_geometry_data, PathData};
|
|
use glam::{Mat4, 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
|
|
}
|
|
|
|
pub fn extrude_path(input_path: PathData, res_x: usize) -> Vec<i32> {
|
|
let point_amount = input_path.points.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] = input_path.points;
|
|
|
|
for i in 0..input_path.length {
|
|
let index_offset = i * res_x * 6;
|
|
let position_offset = i * res_x;
|
|
|
|
let pos = Vec3::new(path[i * 4], path[i * 4 + 1], path[i * 4 + 2]);
|
|
let thickness = path[i * 4 + 3].max(0.000001);
|
|
|
|
// Get direction of the current segment
|
|
let segment_dir = (if i == 0 {
|
|
Vec3::new(
|
|
pos[0] - path[i * 4 + 4],
|
|
pos[1] - path[i * 4 + 5],
|
|
pos[2] - path[i * 4 + 6],
|
|
)
|
|
} else if i == point_amount - 1 {
|
|
Vec3::new(
|
|
path[i * 4 - 4] - pos[0],
|
|
path[i * 4 - 3] - pos[1],
|
|
path[i * 4 - 2] - pos[2],
|
|
)
|
|
} else {
|
|
Vec3::new(
|
|
path[i * 4 - 4] - path[i * 4 + 4],
|
|
path[i * 4 - 3] - path[i * 4 + 5],
|
|
path[i * 4 - 2] - path[i * 4 + 6],
|
|
)
|
|
})
|
|
.normalize();
|
|
|
|
// In our case the up vector is always the Y axis
|
|
let up_vector = Vec3::NEG_Y;
|
|
|
|
let binormal = up_vector.cross(segment_dir);
|
|
|
|
let rotation_angle = up_vector.dot(segment_dir).acos();
|
|
|
|
let rotation_matrix = Mat4::from_axis_angle(binormal, rotation_angle);
|
|
|
|
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_z = circle[j * 2 + 1] * thickness;
|
|
|
|
let point = rotation_matrix.transform_point3(Vec3::new(circle_x, 0.0, circle_z)) + pos;
|
|
let normal = rotation_matrix
|
|
.transform_vector3(Vec3::new(circle_x, 0.0, circle_z))
|
|
.normalize();
|
|
|
|
normals[idx] = normal[0];
|
|
normals[idx + 1] = normal[1];
|
|
normals[idx + 2] = normal[2];
|
|
|
|
positions[idx] = point[0];
|
|
positions[idx + 1] = point[1];
|
|
positions[idx + 2] = point[2];
|
|
}
|
|
}
|
|
|
|
geometry_data
|
|
}
|