parry3d/transformation/to_trimesh/mod.rs
1//! Triangle mesh generation from geometric shapes.
2//!
3//! This module provides functionality to convert various geometric shapes into triangle meshes
4//! (also called "trimesh" in Parry's nomenclature). A triangle mesh is represented as a pair
5//! of vectors: `(Vec<Point<Real>>, Vec<[u32; 3]>)` containing vertices and triangle indices.
6//!
7//! # Overview
8//!
9//! Each shape in Parry implements a `to_trimesh()` method that discretizes its boundary into
10//! a triangle mesh. This is useful for:
11//! - **Visualization**: Rendering shapes in graphics applications
12//! - **Export**: Converting shapes to standard mesh formats (OBJ, STL, etc.)
13//! - **Physics simulation**: Converting analytical shapes to mesh-based collision detection
14//! - **Mesh processing**: Using shape primitives as building blocks for complex geometry
15//!
16//! # Supported Shapes
17//!
18//! ## 2D and 3D Shapes
19//! - **Cuboid**: Axis-aligned box with rectangular faces
20//! - **Aabb**: Axis-aligned bounding box (uses `Cuboid` internally)
21//!
22//! ## 3D-Only Shapes
23//! - **Ball**: Sphere discretized into triangular patches
24//! - **Capsule**: Cylinder with hemispherical caps
25//! - **Cylinder**: Circular cylinder with flat caps
26//! - **Cone**: Circular cone with flat base
27//! - **ConvexPolyhedron**: Already a mesh, returns its triangles
28//! - **HeightField**: Terrain height map converted to mesh
29//! - **Voxels**: Voxel grid converted to boundary mesh
30//!
31//! # Mesh Quality Control
32//!
33//! Most curved shapes (Ball, Capsule, Cylinder, Cone) accept subdivision parameters that
34//! control the mesh resolution. Higher subdivision values produce smoother but heavier meshes:
35//! - **Low subdivision** (4-8): Fast, angular approximation
36//! - **Medium subdivision** (16-32): Good balance for most uses
37//! - **High subdivision** (64+): Smooth curves, high polygon count
38//!
39//! # Examples
40//!
41//! ## Basic Mesh Generation
42//!
43//! ```
44//! # #[cfg(all(feature = "dim3", feature = "f32"))]
45//! # {
46//! use parry3d::shape::{Ball, Cuboid};
47//! use parry3d::math::Vector;
48//!
49//! // Convert a cuboid to a triangle mesh
50//! let cuboid = Cuboid::new(Vector::new(1.0, 2.0, 3.0));
51//! let (vertices, indices) = cuboid.to_trimesh();
52//!
53//! // A cuboid has 8 vertices and 12 triangles (2 per face × 6 faces)
54//! assert_eq!(vertices.len(), 8);
55//! assert_eq!(indices.len(), 12);
56//!
57//! // Convert a sphere with medium resolution
58//! let ball = Ball::new(5.0);
59//! let (vertices, indices) = ball.to_trimesh(16, 32);
60//! // 16 theta subdivisions × 32 phi subdivisions
61//! println!("Ball mesh: {} vertices, {} triangles",
62//! vertices.len(), indices.len());
63//! # }
64//! ```
65//!
66//! ## Controlling Subdivision Quality
67//!
68//! ```
69//! # #[cfg(all(feature = "dim3", feature = "f32"))]
70//! # {
71//! use parry3d::shape::Cylinder;
72//!
73//! let cylinder = Cylinder::new(2.0, 1.0); // half-height=2.0, radius=1.0
74//!
75//! // Low quality - faster, fewer triangles
76//! let (vertices_low, indices_low) = cylinder.to_trimesh(8);
77//! println!("Low quality: {} triangles", indices_low.len());
78//!
79//! // High quality - slower, more triangles, smoother appearance
80//! let (vertices_high, indices_high) = cylinder.to_trimesh(64);
81//! println!("High quality: {} triangles", indices_high.len());
82//! # }
83//! ```
84//!
85//! ## Converting Height Fields
86//!
87//! ```
88//! # #[cfg(all(feature = "dim3", feature = "f32"))]
89//! # {
90//! use parry3d::shape::HeightField;
91//! use parry3d::math::Vector;
92//! use parry3d::na::DMatrix;
93//!
94//! // Create a simple 3×3 height field
95//! let heights = DMatrix::from_row_slice(3, 3, &[
96//! 0.0, 1.0, 0.0,
97//! 1.0, 2.0, 1.0,
98//! 0.0, 1.0, 0.0,
99//! ]);
100//!
101//! let heightfield = HeightField::new(heights, Vector::new(10.0, 10.0, 1.0));
102//! let (vertices, indices) = heightfield.to_trimesh();
103//!
104//! // Height fields generate 2 triangles per grid cell
105//! // (3-1) × (3-1) cells × 2 triangles = 8 triangles
106//! assert_eq!(indices.len(), 8);
107//! # }
108//! ```
109//!
110//! # Return Format
111//!
112//! All `to_trimesh()` methods return a tuple `(Vec<Point<Real>>, Vec<[u32; 3]>)`:
113//!
114//! - **Vertices** (`Vec<Point<Real>>`): Array of 3D points (or 2D for `dim2` feature)
115//! - **Indices** (`Vec<[u32; 3]>`): Array of triangle indices, where each `[u32; 3]` contains
116//! three indices into the vertices array
117//!
118//! The triangles follow a **counter-clockwise winding order** when viewed from outside the shape,
119//! which is the standard convention for outward-facing normals.
120//!
121//! # Performance Considerations
122//!
123//! - Triangle mesh generation allocates new memory each time
124//! - For dynamic scenes, consider caching generated meshes
125//! - Subdivision parameters have quadratic or cubic impact on triangle count
126//! - Simple shapes (Cuboid, ConvexPolyhedron) have negligible generation cost
127//! - Complex shapes (Ball, Capsule with high subdivision) can be expensive
128//!
129//! # See Also
130//!
131//! - \`to_polyline\` - 2D shape to polyline conversion (internal, not public API)
132#![cfg_attr(
133 feature = "dim3",
134 doc = "//! - `to_outline` - 3D shape outline generation (edge wireframes)"
135)]
136//! - [`TriMesh`](crate::shape::TriMesh) - Triangle mesh shape type
137
138#[cfg(feature = "dim3")]
139mod ball_to_trimesh;
140#[cfg(feature = "dim3")]
141mod capsule_to_trimesh;
142#[cfg(feature = "dim3")]
143mod cone_to_trimesh;
144#[cfg(feature = "dim3")]
145mod convex_polyhedron_to_trimesh;
146mod cuboid_to_trimesh;
147#[cfg(feature = "dim3")]
148mod cylinder_to_trimesh;
149#[cfg(feature = "dim3")]
150mod heightfield_to_trimesh;
151#[cfg(feature = "dim3")]
152mod voxels_to_trimesh;