Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
73 changes: 48 additions & 25 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

137 changes: 136 additions & 1 deletion src.ts/geometry/collider.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import {RawColliderSet} from "../raw";
import {RawColliderSet, RawShape, RawVHACDParameters} from "../raw";
import {Rotation, RotationOps, Vector, VectorOps} from "../math";
import {
CoefficientCombineRule,
Expand All @@ -18,6 +18,7 @@ import {
TriMesh,
Polyline,
Heightfield,
Compound,
Segment,
Triangle,
RoundTriangle,
Expand All @@ -44,6 +45,64 @@ import {ColliderShapeCastHit, ShapeCastHit} from "./toi";
import {ShapeContact} from "./contact";
import {ColliderSet} from "./collider_set";

/**
* Parameters for VHACD convex decomposition algorithm.
*
* All parameters are optional. When not specified, default values from the
* underlying Rapier/Parry library are used.
*/
export interface VHACDParameters {
/**
* Controls the bias toward clipping along symmetry planes.
* Range: [0.0, 1.0]
*/
alpha?: number;

/**
* Controls the bias toward clipping along revolution planes.
* Range: [0.0, 1.0]
* Useful for objects with cylindrical or rotational features.
*/
beta?: number;

/**
* Controls maximum allowed deviation from convexity.
* Range: [0.0, 1.0]
* Lower values create more convex parts for a tighter fit.
*/
concavity?: number;

/**
* Controls the granularity of searching optimal clipping planes.
* Lower values test more planes (slower but more accurate).
*/
planeDownsampling?: number;

/**
* Controls the precision of convex hull generation.
* Lower values use more voxels for hull computation.
*/
convexHullDownsampling?: number;

/**
* Maximum number of convex parts to generate.
* Limits part count during decomposition.
*/
maxConvexHulls?: number;

/**
* Voxel grid resolution for decomposition.
* Higher resolution captures more detail but is slower.
*/
resolution?: number;

/**
* Whether to use approximate convex hulls for better performance.
* Faster method with minimal impact on quality.
*/
convexHullApproximation?: boolean;
}

/**
* Flags affecting whether collision-detection happens between two colliders
* depending on the type of rigid-bodies they are attached to.
Expand Down Expand Up @@ -1690,6 +1749,82 @@ export class ColliderDesc {

// #endif

/**
* Creates a new collider descriptor with a compound shape.
*
* @param shapes - The array of shapes composing this compound.
* @param positions - The array of positions for each shape (relative to the compound's origin).
* @param rotations - The array of rotations for each shape (relative to the compound's orientation).
*/
public static compound(
shapes: Shape[],
positions: Vector[],
rotations: Rotation[],
): ColliderDesc {
const shape = new Compound(shapes, positions, rotations);
return new ColliderDesc(shape);
}

/**
* Creates a new collider descriptor with a compound shape automatically created
* from a convex decomposition of the given triangle mesh.
*
* @param vertices - The coordinates of the mesh's vertices.
* @param indices - The indices of the mesh's triangles.
* @param params - Optional VHACD parameters to control the decomposition.
*/
public static convexDecomposition(
vertices: Float32Array,
indices: Uint32Array,
params?: VHACDParameters,
): ColliderDesc | null {
let rawShape: RawShape;

if (params) {
// Convert TypeScript params to Rust params
const rawParams = new RawVHACDParameters();
if (params.alpha !== undefined) rawParams.alpha = params.alpha;
if (params.beta !== undefined) rawParams.beta = params.beta;
if (params.concavity !== undefined)
rawParams.concavity = params.concavity;
if (params.planeDownsampling !== undefined)
rawParams.plane_downsampling = params.planeDownsampling;
if (params.convexHullDownsampling !== undefined)
rawParams.convex_hull_downsampling =
params.convexHullDownsampling;
if (params.maxConvexHulls !== undefined)
rawParams.max_convex_hulls = params.maxConvexHulls;
if (params.resolution !== undefined)
rawParams.resolution = params.resolution;
if (params.convexHullApproximation !== undefined)
rawParams.convex_hull_approximation =
params.convexHullApproximation;

rawShape = RawShape.convexDecompositionWithParams(
vertices,
indices,
rawParams,
);
} else {
rawShape = RawShape.convexDecomposition(vertices, indices);
}

if (!rawShape) {
return null;
}

// Create a wrapper - note: we can't deserialize compound shapes yet,
// so we create a minimal wrapper that just holds the raw shape
const shape = new (class extends Shape {
readonly type = ShapeType.Compound;
intoRaw(): RawShape {
return rawShape;
}
})();

return new ColliderDesc(shape);
}

// #if DIM2
/**
* Sets the position of the collider to be created relative to the rigid-body it is attached to.
Expand Down
Loading