Module utils

Source
Expand description

Low-level utilities for mesh and geometry generation.

This module provides primitive building blocks for constructing triangle meshes and other geometric structures. These functions are primarily used internally by Parry’s shape-to-mesh conversion utilities, but are exposed for users who need fine-grained control over mesh generation.

§Overview

The utilities fall into several categories:

§Point Transformations

§Vertex Generation

  • push_circle - Generate circle points in 3D (XZ plane)
  • push_xy_arc - Generate arc points in 2D (XY plane)
  • push_arc - Generate arc points between two endpoints

§Index Buffer Generation

  • push_ring_indices / push_open_ring_indices - Connect two circles into a tube
  • push_rectangle_indices - Generate two triangles forming a quad
  • push_degenerate_top_ring_indices - Connect circle to a single apex point
  • push_filled_circle_indices - Fill a circle with triangles (fan triangulation)

§Edge/Outline Generation

  • push_circle_outline_indices - Edge loop for a closed circle
  • push_open_circle_outline_indices - Edge chain (not closed)
  • push_arc_idx - Edge indices for an arc

§Advanced Operations

  • reverse_clockwising - Flip triangle winding order (reverse normals)
  • apply_revolution - Create surface of revolution from a profile curve
  • push_arc_and_idx - Generate arc geometry and indices together

§Usage Patterns

§Building a Cylinder

use parry3d::transformation::utils::{push_circle, push_ring_indices, push_filled_circle_indices};
use parry3d::math::Point;
use std::f32::consts::PI;

let mut vertices = Vec::new();
let mut indices = Vec::new();

let radius = 2.0;
let height = 10.0;
let nsubdiv = 16;
let dtheta = 2.0 * PI / nsubdiv as f32;

// Create bottom and top circles
push_circle(radius, nsubdiv, dtheta, 0.0, &mut vertices);      // Bottom at y=0
push_circle(radius, nsubdiv, dtheta, height, &mut vertices);   // Top at y=height

// Connect the circles to form the cylinder body
push_ring_indices(0, nsubdiv, nsubdiv, &mut indices);

// Cap the bottom
push_filled_circle_indices(0, nsubdiv, &mut indices);

// Cap the top
push_filled_circle_indices(nsubdiv, nsubdiv, &mut indices);

println!("Cylinder: {} vertices, {} triangles", vertices.len(), indices.len());

§Building a Cone

use parry3d::transformation::utils::{push_circle, push_degenerate_top_ring_indices, push_filled_circle_indices};
use parry3d::math::Point;
use std::f32::consts::PI;

let mut vertices = Vec::new();
let mut indices = Vec::new();

let radius = 3.0;
let height = 5.0;
let nsubdiv = 20;
let dtheta = 2.0 * PI / nsubdiv as f32;

// Create the base circle
push_circle(radius, nsubdiv, dtheta, 0.0, &mut vertices);

// Add apex point at the top
vertices.push(Point::new(0.0, height, 0.0));
let apex_idx = (vertices.len() - 1) as u32;

// Connect base circle to apex
push_degenerate_top_ring_indices(0, apex_idx, nsubdiv, &mut indices);

// Cap the base
push_filled_circle_indices(0, nsubdiv, &mut indices);

println!("Cone: {} vertices, {} triangles", vertices.len(), indices.len());

§Transforming Existing Geometry

use parry3d::transformation::utils::{transform, scaled};
use parry3d::math::{Point, Vector, Isometry};
use parry3d::na::{Translation3, UnitQuaternion};
use std::f32::consts::PI;

let mut points = vec![
    Point::new(1.0, 0.0, 0.0),
    Point::new(0.0, 1.0, 0.0),
    Point::new(0.0, 0.0, 1.0),
];

// First, scale non-uniformly
let points = scaled(points, Vector::new(2.0, 1.0, 0.5));

// Then rotate 45 degrees around Y axis
let rotation = UnitQuaternion::from_axis_angle(&Vector::y_axis(), PI / 4.0);
let translation = Translation3::new(10.0, 5.0, 0.0);
let isometry = Isometry::from_parts(translation.into(), rotation);

let final_points = parry3d::transformation::utils::transformed(points, isometry);

§Design Philosophy

These functions follow a “builder” pattern where:

  1. Vertices are pushed to a Vec<Point<Real>>
  2. Indices are pushed to a Vec<[u32; 3]> (triangles) or Vec<[u32; 2]> (edges)
  3. Functions work with index offsets, allowing incremental construction
  4. No memory is allocated except for the output buffers

This design allows for efficient, flexible mesh construction with minimal overhead.

§Performance Notes

  • All functions use simple loops without SIMD (suitable for small to medium subdivisions)
  • Index generation has O(n) complexity where n is the subdivision count
  • Point generation involves trigonometric functions (sin/cos) per subdivision
  • For high subdivision counts (>1000), consider caching generated geometry

§See Also

  • to_trimesh module - High-level shape to mesh conversion (see individual shape to_trimesh() methods)
  • convex_hull - Convex hull computation
  • TriMesh - Triangle mesh shape

Functions§

push_arc
Pushes points forming an arc between two points around a center.
push_xy_arc
Pushes a discretized counterclockwise arc to a buffer.
scaled
Returns the scaled version of a vector of points.
transform
Applies in-place a transformation to an array of points.
transformed
Returns the transformed version of a vector of points.