parry2d/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<Vector>, 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::utils::Array2;
93//!
94//! // Create a simple 3×3 height field
95//! // Column-major order: column 0 first, then column 1, then column 2
96//! let heights = Array2::new(3, 3, vec![
97//! 0.0, 1.0, 0.0, // column 0
98//! 1.0, 2.0, 1.0, // column 1
99//! 0.0, 1.0, 0.0, // column 2
100//! ]);
101//!
102//! let heightfield = HeightField::new(heights, Vector::new(10.0, 10.0, 1.0));
103//! let (vertices, indices) = heightfield.to_trimesh();
104//!
105//! // Height fields generate 2 triangles per grid cell
106//! // (3-1) × (3-1) cells × 2 triangles = 8 triangles
107//! assert_eq!(indices.len(), 8);
108//! # }
109//! ```
110//!
111//! # Return Format
112//!
113//! All `to_trimesh()` methods return a tuple `(Vec<Vector>, Vec<[u32; 3]>)`:
114//!
115//! - **Vertices** (`Vec<Vector>`): Array of 3D points (or 2D for `dim2` feature)
116//! - **Indices** (`Vec<[u32; 3]>`): Array of triangle indices, where each `[u32; 3]` contains
117//! three indices into the vertices array
118//!
119//! The triangles follow a **counter-clockwise winding order** when viewed from outside the shape,
120//! which is the standard convention for outward-facing normals.
121//!
122//! # Performance Considerations
123//!
124//! - Triangle mesh generation allocates new memory each time
125//! - For dynamic scenes, consider caching generated meshes
126//! - Subdivision parameters have quadratic or cubic impact on triangle count
127//! - Simple shapes (Cuboid, ConvexPolyhedron) have negligible generation cost
128//! - Complex shapes (Ball, Capsule with high subdivision) can be expensive
129//!
130//! # See Also
131//!
132//! - \`to_polyline\` - 2D shape to polyline conversion (internal, not public API)
133#![cfg_attr(
134 feature = "dim3",
135 doc = "//! - `to_outline` - 3D shape outline generation (edge wireframes)"
136)]
137//! - [`TriMesh`](crate::shape::TriMesh) - Triangle mesh shape type
138
139#[cfg(feature = "dim3")]
140mod ball_to_trimesh;
141#[cfg(feature = "dim3")]
142mod capsule_to_trimesh;
143#[cfg(feature = "dim3")]
144mod cone_to_trimesh;
145#[cfg(feature = "dim3")]
146mod convex_polyhedron_to_trimesh;
147mod cuboid_to_trimesh;
148#[cfg(feature = "dim3")]
149mod cylinder_to_trimesh;
150#[cfg(feature = "dim3")]
151mod heightfield_to_trimesh;
152#[cfg(feature = "dim3")]
153mod voxels_to_trimesh;