Implement sculpt mesh and OBJ support (#43)
Some checks failed
JPEG 2000 feature / linux (push) Has been cancelled
JPEG 2000 feature / macos (push) Has been cancelled
JPEG 2000 feature / windows (push) Has been cancelled
Skia feature / linux (push) Has been cancelled
Skia feature / macos (push) Has been cancelled
Skia feature / windows (push) Has been cancelled

This commit is contained in:
2026-08-09 04:59:49 +00:00
parent 5b3950c421
commit c6171dc625
10 changed files with 1451 additions and 330 deletions

View File

@@ -19,8 +19,7 @@
#![allow(clippy::too_many_arguments)] // Constructor and extrusion helpers mirror fixed APIs.
#![allow(clippy::too_many_lines)] // The extrusion sequence remains reviewable against C#.
use crate::{Error, PathType, VertexIndexer, ViewerPolygon, ViewerVertex};
use std::collections::HashMap;
use crate::{Error, PathType, VertexIndexer};
use std::f32::consts::{PI, TAU};
use std::fmt;
use std::fs::File;
@@ -1777,61 +1776,7 @@ impl PrimMesh {
}
pub fn get_vertex_indexer(&self) -> Result<Option<VertexIndexer>, Error> {
if self.viewer_mode && !self.viewer_faces.is_empty() {
let max_face = self
.viewer_faces
.iter()
.map(|face| face.prim_face_number)
.max()
.unwrap_or(0);
let num_prim_faces = max_face.checked_add(1).ok_or(Error::Argument)?;
let face_count = usize::try_from(num_prim_faces).map_err(|_| Error::Argument)?;
if face_count > MAX_PROFILE_VERTICES {
return Err(Error::Argument);
}
let mut viewer_vertices: Vec<Vec<ViewerVertex>> =
(0..face_count).map(|_| Vec::new()).collect();
let mut viewer_polygons: Vec<Option<Vec<ViewerPolygon>>> =
(0..face_count).map(|_| Some(Vec::new())).collect();
let mut indices: Vec<HashMap<i32, i32>> =
(0..face_count).map(|_| HashMap::new()).collect();
for face in &self.viewer_faces {
let face_index = idx(face.prim_face_number, face_count)?;
let vertices = &mut viewer_vertices[face_index];
let map = &mut indices[face_index];
let v1 = indexed_viewer_vertex(
map,
vertices,
face.coord_index1,
face.v1,
face.n1,
face.uv1,
)?;
let v2 = indexed_viewer_vertex(
map,
vertices,
face.coord_index2,
face.v2,
face.n2,
face.uv2,
)?;
let v3 = indexed_viewer_vertex(
map,
vertices,
face.coord_index3,
face.v3,
face.n3,
face.uv3,
)?;
viewer_polygons[face_index]
.as_mut()
.ok_or(Error::InvalidOperation)?
.push(ViewerPolygon { v1, v2, v3 });
}
Ok(Some(VertexIndexer {
num_prim_faces,
viewer_polygons,
viewer_vertices,
}))
Ok(Some(VertexIndexer::from_viewer_faces(&self.viewer_faces)?))
} else {
Ok(None)
}
@@ -1927,23 +1872,7 @@ fn assign_viewer_normals(
viewer.n3 = normals[idx(face.n3, normals.len())?];
Ok(())
}
fn indexed_viewer_vertex(
indices: &mut HashMap<i32, i32>,
vertices: &mut Vec<ViewerVertex>,
coord_index: i32,
v: Coord,
n: Coord,
uv: UVCoord,
) -> Result<i32, Error> {
if let Some(index) = indices.get(&coord_index) {
return Ok(*index);
}
let index = i32::try_from(vertices.len()).map_err(|_| Error::Argument)?;
vertices.push(ViewerVertex { n, uv, v });
indices.insert(coord_index, index);
Ok(index)
}
fn dump_raw_geometry(
pub(crate) fn dump_raw_geometry(
coords: &[Coord],
faces: &[Face],
path: String,