Skip to content

Bendzae/SMesh

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

CI crates.io

SMesh

Caution

Library is still work in progress

SMesh is a polygon mesh manipulation library based on the Surface Mesh data structure and the pmp library and the halfedge-mesh implementation of the blackjack project.

Version Compatibility

SMesh Version Bevy Version
0.2.7 0.17
0.2.5 0.16

The goal of this library is to provide a flexible mesh abstraction and set of operations to be used for procedural modeling and procedural generation of 3D meshes.

Examples

tree_example parameterized procedural mesh generation

cargo run --example tree

extrude_example mesh extrusion and manipulation example with the visual debug tools enabled

cargo run --example extrude

UV Unwrapping Example

Interactive example demonstrating all UV unwrapping methods on four different primitives with a checkerboard texture:

cargo run --example uv_unwrap --features xatlas

Press SPACE to cycle through UV methods: Planar Z, Planar Y, Cylindrical Y, Spherical, Cube, and XAtlas Auto. The four primitives (Cube, Sphere, Cylinder, and a complex extruded shape) update simultaneously to show how each method performs on different geometry.

Usage

Preface: Mesh elements in SMesh are identified by a unique typesafe id, which can be of type: VertexId, HalfedgeId and FaceId.

Mesh creation

SMesh has a simple api to add vertices to your mesh and connect them to faces: Add vertices

    let mut smesh = SMesh::new();
    let v0 = smesh.add_vertex(vec3(-1.0, -1.0, 0.0)); // Returns a unique VertexId
    let v1 = smesh.add_vertex(vec3(1.0, -1.0, 0.0));
    let v2 = smesh.add_vertex(vec3(1.0, 1.0, 0.0));
    let v3 = smesh.add_vertex(vec3(-1.0, 1.0, 0.0));

Build face

    smesh.add_face(vec![v0, v1, v2, v3])?;

Mesh queries

SMesh provides a chainable api to query mesh elements using the typical halfedge-mesh relationships:

get outgoing halfedge of a vertex

let outgoing_halfedge_query = v0.halfedge(); // returns a MeshQueryBuilder<HalfedgeId>

you can execute the query on a smesh instance by using .run(&smesh)

let outgoing_halfedge = v0.halfedge().run(&smesh)?;  // returns a HalfedgeId

chaining queries

let vertex = v0.halfedge_to(v1).cw_rotated_neighbour().dst_vert().run(&smesh)?;  // returns a VertexId

Mesh operations

SMesh provides a comprehensive set of mesh manipulation operations:

Topological Operations

// Insert a vertex along an edge
let new_halfedge = mesh.insert_vertex(halfedge_id, vertex_id)?;

// Delete mesh elements
mesh.delete_vertex(vertex_id)?;
mesh.delete_edge(halfedge_id)?;
mesh.delete_face(face_id)?;

// Edge collapse (for triangle meshes)
if mesh.is_collapse_ok(halfedge_id).is_ok() {
    mesh.collapse(halfedge_id)?;
}

// Remove edge (merges adjacent faces)
if mesh.is_removal_ok(halfedge_id).is_ok() {
    mesh.remove_edge(halfedge_id)?;
}

Edit Operations

// Extrude a single face
let new_face = mesh.extrude(face_id)?;

// Extrude multiple faces
let new_faces = mesh.extrude_faces(vec![face1, face2, face3])?;

// Extrude a boundary edge
let new_edge = mesh.extrude_edge(halfedge_id)?;

// Extrude a chain of connected boundary edges
let new_edges = mesh.extrude_edge_chain(vec![edge1, edge2, edge3])?;

// Subdivide faces
let selection = MeshSelection::from(vec![face1, face2]);
let new_selection = mesh.subdivide(selection)?;

// Combine two meshes
mesh.combine_with(other_mesh)?;

Transform Operations

All transform operations work with selections (vertices, edges, or faces):

use smesh::smesh::transform::Pivot;

// Translate
mesh.translate(face_id, Vec3::new(0.0, 1.0, 0.0))?;

// Scale around a pivot point
mesh.scale(
    vec![face1, face2],
    Vec3::new(2.0, 2.0, 2.0),
    Pivot::SelectionCog
)?;

// Rotate using a quaternion
mesh.rotate(
    vertex_id,
    Quat::from_rotation_y(PI / 4.0),
    Pivot::Origin
)?;

// Set position relative to a pivot
mesh.set_position(selection, Vec3::new(5.0, 0.0, 0.0), Pivot::MeshCog)?;

Available pivot options: Pivot::Origin, Pivot::MeshCog, Pivot::SelectionCog, Pivot::Point(Vec3)

Primitives

SMesh includes built-in primitive generators:

use smesh::smesh::primitives::*;

// Create a cube with subdivisions
let (cube, data) = Cube {
    subdivision: U16Vec3::new(2, 2, 2)
}.generate()?;

// Create an icosphere
let (sphere, data) = Icosphere {
    subdivisions: 3
}.generate()?;

// Create a cylinder
let (cylinder, data) = Cylinder {
    segments: 16,
    height: 2.0,
    radius: 0.5
}.generate()?;

// Create other primitives
let (quad, data) = Quad.generate()?;
let (circle, data) = Circle { segments: 32 }.generate()?;

Please check the examples for more :)

UV Unwrapping

SMesh supports both simple projection-based UV mapping and automatic UV unwrapping via xatlas.

Simple Projection Methods (built-in, no features required):

use smesh::smesh::uv_operations::ProjectionAxis;

// Planar projection
mesh.planar_project_uvs(ProjectionAxis::Z)?;

// Cylindrical projection
mesh.cylindrical_project_uvs(ProjectionAxis::Y)?;

// Spherical projection
mesh.spherical_project_uvs(Vec3::ZERO)?;

// Cube projection
mesh.cube_project_uvs(Vec3::ZERO)?;

Automatic UV Unwrapping via xatlas (requires xatlas feature):

[dependencies]
smesh = { version = "0.2", features = ["xatlas"] }

Then generate UVs for your mesh:

// Simple automatic unwrapping
mesh.auto_uv_unwrap()?;

// With custom options
use smesh::smesh::xatlas_integration::XatlasOptions;

let options = XatlasOptions::default();
mesh.auto_uv_unwrap_with_options(options)?;

Goals

I aim to provide a flexible rust implementation of the Surface Mesh with a focus on usefulness for procedural mesh generation. Other goals are:

  • Ergonomic and easy-to-use api
  • Port most operations from the pmp library and blackjack
  • Support most operations that are possible in modern 3D modeling software like blender
  • Integration with the bevy game engine
  • Target manifold tri & quad meshes for now

About

A polygon mesh manipulation library based on the Surface Mesh structure

Resources

License

Stars

Watchers

Forks

Packages

No packages published