-
-
Notifications
You must be signed in to change notification settings - Fork 24
Added code that allows for easier rendering of meshes #108
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from 3 commits
8bf462b
ff11285
aed941a
078325f
fc81145
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -15,11 +15,12 @@ use crate::float_types::{ | |||||||||||||||||||||||||||||||||||||
| use crate::mesh::{bsp::Node, plane::Plane, polygon::Polygon, vertex::Vertex}; | ||||||||||||||||||||||||||||||||||||||
| use crate::sketch::Sketch; | ||||||||||||||||||||||||||||||||||||||
| use crate::traits::CSG; | ||||||||||||||||||||||||||||||||||||||
| use bytemuck::cast; | ||||||||||||||||||||||||||||||||||||||
| use geo::{CoordsIter, Geometry, Polygon as GeoPolygon}; | ||||||||||||||||||||||||||||||||||||||
| use nalgebra::{ | ||||||||||||||||||||||||||||||||||||||
| Isometry3, Matrix4, Point3, Quaternion, Unit, Vector3, partial_max, partial_min, | ||||||||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||||||||
| use std::{cmp::PartialEq, fmt::Debug, num::NonZeroU32, sync::OnceLock}; | ||||||||||||||||||||||||||||||||||||||
| use std::{cmp::PartialEq, collections::HashMap, fmt::Debug, num::NonZeroU32, sync::OnceLock}; | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| #[cfg(feature = "parallel")] | ||||||||||||||||||||||||||||||||||||||
| use rayon::{iter::IntoParallelRefIterator, prelude::*}; | ||||||||||||||||||||||||||||||||||||||
|
|
@@ -47,6 +48,18 @@ pub mod smoothing; | |||||||||||||||||||||||||||||||||||||
| pub mod tpms; | ||||||||||||||||||||||||||||||||||||||
| pub mod vertex; | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| /// Stored as `(position: [f32; 3], normal: [f32; 3])` | ||||||||||||||||||||||||||||||||||||||
| pub type GraphicsMeshVertex = ([f32; 3], [f32; 3]); | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| /// Mesh ready for rendering. Uses f32s and provides vertices, indices and | ||||||||||||||||||||||||||||||||||||||
| /// normals. | ||||||||||||||||||||||||||||||||||||||
| #[derive(Debug, Clone)] | ||||||||||||||||||||||||||||||||||||||
| pub struct GraphicsMesh { | ||||||||||||||||||||||||||||||||||||||
| /// Vertices contain both position and normal | ||||||||||||||||||||||||||||||||||||||
| pub vertices: Vec<GraphicsMeshVertex>, | ||||||||||||||||||||||||||||||||||||||
| pub indices: Vec<u32>, | ||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| #[derive(Clone, Debug)] | ||||||||||||||||||||||||||||||||||||||
| pub struct Mesh<S: Clone + Send + Sync + Debug> { | ||||||||||||||||||||||||||||||||||||||
| /// 3D polygons for volumetric shapes | ||||||||||||||||||||||||||||||||||||||
|
|
@@ -237,7 +250,62 @@ impl<S: Clone + Send + Sync + Debug> Mesh<S> { | |||||||||||||||||||||||||||||||||||||
| dot.acos() | ||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| /// Converts a mesh to a graphics mesh which is more appropriate for rendering. | ||||||||||||||||||||||||||||||||||||||
| /// | ||||||||||||||||||||||||||||||||||||||
| /// Allocates a hashmap and a storage vec for removing redundant vertices. | ||||||||||||||||||||||||||||||||||||||
| pub fn build_graphics_mesh(&self) -> GraphicsMesh { | ||||||||||||||||||||||||||||||||||||||
| let triangles = self.triangulate().polygons; | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| let triangle_count = triangles.len(); | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| let mut indices: Vec<u32> = Vec::with_capacity(triangle_count); | ||||||||||||||||||||||||||||||||||||||
| let mut vertices: Vec<GraphicsMeshVertex> = Vec::with_capacity(triangle_count); | ||||||||||||||||||||||||||||||||||||||
| const VERT_DIM_SIZE: usize = std::mem::size_of::<[f32; 3]>(); | ||||||||||||||||||||||||||||||||||||||
| let mut vertices_hash: HashMap<([u8; VERT_DIM_SIZE], [u8; VERT_DIM_SIZE]), u32> = | ||||||||||||||||||||||||||||||||||||||
| HashMap::with_capacity(triangle_count); | ||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||
| let mut vertices: Vec<GraphicsMeshVertex> = Vec::with_capacity(triangle_count); | |
| const VERT_DIM_SIZE: usize = std::mem::size_of::<[f32; 3]>(); | |
| let mut vertices_hash: HashMap<([u8; VERT_DIM_SIZE], [u8; VERT_DIM_SIZE]), u32> = | |
| HashMap::with_capacity(triangle_count); | |
| let mut vertices: Vec<GraphicsMeshVertex> = Vec::with_capacity(triangle_count * 3 / 2); | |
| const VERT_DIM_SIZE: usize = std::mem::size_of::<[f32; 3]>(); | |
| let mut vertices_hash: HashMap<([u8; VERT_DIM_SIZE], [u8; VERT_DIM_SIZE]), u32> = | |
| HashMap::with_capacity(triangle_count * 3 / 2); |
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This block can be simplified. nalgebra provides a cast method to convert between numeric types for points and vectors, which is cleaner than casting each component individually. Additionally, the VERT_DIM_SIZE constant defined on line 263 should be used here for consistency instead of calling std::mem::size_of again.
| let pos_x = vertex.pos.x as f32; | |
| let pos_y = vertex.pos.y as f32; | |
| let pos_z = vertex.pos.z as f32; | |
| let norm_x = vertex.normal.x as f32; | |
| let norm_y = vertex.normal.y as f32; | |
| let norm_z = vertex.normal.z as f32; | |
| let pos_xyz = [pos_x, pos_y, pos_z]; | |
| let norm_xyz = [norm_x, norm_y, norm_z]; | |
| let pos_xyz_bytes: [u8; std::mem::size_of::<[f32; 3]>()] = cast(pos_xyz); | |
| let norm_xyz_bytes: [u8; std::mem::size_of::<[f32; 3]>()] = cast(norm_xyz); | |
| let pos_xyz: [f32; 3] = vertex.pos.cast::<f32>().coords.into(); | |
| let norm_xyz: [f32; 3] = vertex.normal.cast::<f32>().into(); | |
| let pos_xyz_bytes: [u8; VERT_DIM_SIZE] = cast(pos_xyz); | |
| let norm_xyz_bytes: [u8; VERT_DIM_SIZE] = cast(norm_xyz); |
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The current implementation performs a get and then potentially an insert on the HashMap, which results in two lookups for new vertices. Using the entry API is more idiomatic and efficient as it performs only one lookup. This also makes the code more concise.
let vertex_f32_bytes = (pos_xyz_bytes, norm_xyz_bytes);
let index = *vertices_hash.entry(vertex_f32_bytes).or_insert_with(|| {
let new_index = i_new_vertex;
vertices.push((pos_xyz, norm_xyz));
i_new_vertex += 1;
new_index
});
indices.push(index);
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The capacity for the
indicesvector is initialized totriangle_count, but it will eventually holdtriangle_count * 3elements. This will likely cause multiple reallocations for large meshes, impacting performance. Initializing it with the final capacity is more efficient.