Files
esengine/thirdparty/rapier.js/src/geometry/collider.rs
YHH 63f006ab62 feat: 添加跨平台运行时、资产系统和UI适配功能 (#256)
* feat(platform-common): 添加WASM加载器和环境检测API

* feat(rapier2d): 新增Rapier2D WASM绑定包

* feat(physics-rapier2d): 添加跨平台WASM加载器

* feat(asset-system): 添加运行时资产目录和bundle格式

* feat(asset-system-editor): 新增编辑器资产管理包

* feat(editor-core): 添加构建系统和模块管理

* feat(editor-app): 重构浏览器预览使用import maps

* feat(platform-web): 添加BrowserRuntime和资产读取

* feat(engine): 添加材质系统和着色器管理

* feat(material): 新增材质系统和着色器编辑器

* feat(tilemap): 增强tilemap编辑器和动画系统

* feat(modules): 添加module.json配置

* feat(core): 添加module.json和类型定义更新

* chore: 更新依赖和构建配置

* refactor(plugins): 更新插件模板使用ModuleManifest

* chore: 添加第三方依赖库

* chore: 移除BehaviourTree-ai和ecs-astar子模块

* docs: 更新README和文档主题样式

* fix: 修复Rust文档测试和添加rapier2d WASM绑定

* fix(tilemap-editor): 修复画布高DPI屏幕分辨率适配问题

* feat(ui): 添加UI屏幕适配系统(CanvasScaler/SafeArea)

* fix(ecs-engine-bindgen): 添加缺失的ecs-framework-math依赖

* fix: 添加缺失的包依赖修复CI构建

* fix: 修复CodeQL检测到的代码问题

* fix: 修复构建错误和缺失依赖

* fix: 修复类型检查错误

* fix(material-system): 修复tsconfig配置支持TypeScript项目引用

* fix(editor-core): 修复Rollup构建配置添加tauri external

* fix: 修复CodeQL检测到的代码问题

* fix: 修复CodeQL检测到的代码问题
2025-12-03 22:15:22 +08:00

994 lines
36 KiB
Rust
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
use crate::geometry::shape::SharedShapeUtility;
use crate::geometry::{
RawColliderSet, RawColliderShapeCastHit, RawPointProjection, RawRayIntersection, RawShape,
RawShapeCastHit, RawShapeContact, RawShapeType,
};
use crate::math::{RawRotation, RawVector};
use crate::utils::{self, FlatHandle};
use rapier::dynamics::MassProperties;
use rapier::geometry::{ActiveCollisionTypes, ShapeType};
use rapier::math::{Isometry, Point, Real, Vector};
use rapier::parry::query;
use rapier::parry::query::ShapeCastOptions;
use rapier::pipeline::{ActiveEvents, ActiveHooks};
use wasm_bindgen::prelude::*;
#[wasm_bindgen]
impl RawColliderSet {
/// The world-space translation of this collider.
pub fn coTranslation(&self, handle: FlatHandle) -> RawVector {
self.map(handle, |co| co.position().translation.vector.into())
}
/// The world-space orientation of this collider.
pub fn coRotation(&self, handle: FlatHandle) -> RawRotation {
self.map(handle, |co| co.position().rotation.into())
}
/// The translation of this collider relative to its parent rigid-body.
///
/// Returns the `None` if it doesnt have a parent.
pub fn coTranslationWrtParent(&self, handle: FlatHandle) -> Option<RawVector> {
self.map(handle, |co| {
co.position_wrt_parent()
.map(|pose| pose.translation.vector.into())
})
}
/// The orientation of this collider relative to its parent rigid-body.
///
/// Returns the `None` if it doesnt have a parent.
pub fn coRotationWrtParent(&self, handle: FlatHandle) -> Option<RawRotation> {
self.map(handle, |co| {
co.position_wrt_parent().map(|pose| pose.rotation.into())
})
}
/// Sets the translation of this collider.
///
/// # Parameters
/// - `x`: the world-space position of the collider along the `x` axis.
/// - `y`: the world-space position of the collider along the `y` axis.
/// - `z`: the world-space position of the collider along the `z` axis.
/// - `wakeUp`: forces the collider to wake-up so it is properly affected by forces if it
/// wasn't moving before modifying its position.
#[cfg(feature = "dim3")]
pub fn coSetTranslation(&mut self, handle: FlatHandle, x: f32, y: f32, z: f32) {
self.map_mut(handle, |co| {
co.set_translation(na::Vector3::new(x, y, z));
})
}
/// Sets the translation of this collider.
///
/// # Parameters
/// - `x`: the world-space position of the collider along the `x` axis.
/// - `y`: the world-space position of the collider along the `y` axis.
/// - `wakeUp`: forces the collider to wake-up so it is properly affected by forces if it
/// wasn't moving before modifying its position.
#[cfg(feature = "dim2")]
pub fn coSetTranslation(&mut self, handle: FlatHandle, x: f32, y: f32) {
self.map_mut(handle, |co| {
co.set_translation(na::Vector2::new(x, y));
})
}
#[cfg(feature = "dim3")]
pub fn coSetTranslationWrtParent(&mut self, handle: FlatHandle, x: f32, y: f32, z: f32) {
self.map_mut(handle, |co| {
co.set_translation_wrt_parent(na::Vector3::new(x, y, z));
})
}
#[cfg(feature = "dim2")]
pub fn coSetTranslationWrtParent(&mut self, handle: FlatHandle, x: f32, y: f32) {
self.map_mut(handle, |co| {
co.set_translation_wrt_parent(na::Vector2::new(x, y));
})
}
/// Sets the rotation quaternion of this collider.
///
/// This does nothing if a zero quaternion is provided.
///
/// # Parameters
/// - `x`: the first vector component of the quaternion.
/// - `y`: the second vector component of the quaternion.
/// - `z`: the third vector component of the quaternion.
/// - `w`: the scalar component of the quaternion.
/// - `wakeUp`: forces the collider to wake-up so it is properly affected by forces if it
/// wasn't moving before modifying its position.
#[cfg(feature = "dim3")]
pub fn coSetRotation(&mut self, handle: FlatHandle, x: f32, y: f32, z: f32, w: f32) {
if let Some(q) = na::Unit::try_new(na::Quaternion::new(w, x, y, z), 0.0) {
self.map_mut(handle, |co| co.set_rotation(q))
}
}
/// Sets the rotation angle of this collider.
///
/// # Parameters
/// - `angle`: the rotation angle, in radians.
/// - `wakeUp`: forces the collider to wake-up so it is properly affected by forces if it
/// wasn't moving before modifying its position.
#[cfg(feature = "dim2")]
pub fn coSetRotation(&mut self, handle: FlatHandle, angle: f32) {
self.map_mut(handle, |co| co.set_rotation(na::UnitComplex::new(angle)))
}
#[cfg(feature = "dim3")]
pub fn coSetRotationWrtParent(&mut self, handle: FlatHandle, x: f32, y: f32, z: f32, w: f32) {
if let Some(q) = na::Unit::try_new(na::Quaternion::new(w, x, y, z), 0.0) {
self.map_mut(handle, |co| co.set_rotation_wrt_parent(q.scaled_axis()))
}
}
#[cfg(feature = "dim2")]
pub fn coSetRotationWrtParent(&mut self, handle: FlatHandle, angle: f32) {
self.map_mut(handle, |co| co.set_rotation_wrt_parent(angle))
}
/// Is this collider a sensor?
pub fn coIsSensor(&self, handle: FlatHandle) -> bool {
self.map(handle, |co| co.is_sensor())
}
/// The type of the shape of this collider.
pub fn coShapeType(&self, handle: FlatHandle) -> RawShapeType {
self.map(handle, |co| match co.shape().shape_type() {
ShapeType::Ball => RawShapeType::Ball,
ShapeType::Cuboid => RawShapeType::Cuboid,
ShapeType::Capsule => RawShapeType::Capsule,
ShapeType::Segment => RawShapeType::Segment,
ShapeType::Polyline => RawShapeType::Polyline,
ShapeType::Triangle => RawShapeType::Triangle,
ShapeType::TriMesh => RawShapeType::TriMesh,
ShapeType::HeightField => RawShapeType::HeightField,
ShapeType::Compound => RawShapeType::Compound,
ShapeType::HalfSpace => RawShapeType::HalfSpace,
ShapeType::Voxels => RawShapeType::Voxels,
#[cfg(feature = "dim3")]
ShapeType::ConvexPolyhedron => RawShapeType::ConvexPolyhedron,
#[cfg(feature = "dim2")]
ShapeType::ConvexPolygon => RawShapeType::ConvexPolygon,
#[cfg(feature = "dim3")]
ShapeType::Cylinder => RawShapeType::Cylinder,
#[cfg(feature = "dim3")]
ShapeType::Cone => RawShapeType::Cone,
ShapeType::RoundCuboid => RawShapeType::RoundCuboid,
ShapeType::RoundTriangle => RawShapeType::RoundTriangle,
#[cfg(feature = "dim3")]
ShapeType::RoundCylinder => RawShapeType::RoundCylinder,
#[cfg(feature = "dim3")]
ShapeType::RoundCone => RawShapeType::RoundCone,
#[cfg(feature = "dim3")]
ShapeType::RoundConvexPolyhedron => RawShapeType::RoundConvexPolyhedron,
#[cfg(feature = "dim2")]
ShapeType::RoundConvexPolygon => RawShapeType::RoundConvexPolygon,
ShapeType::Custom => panic!("Not yet implemented."),
})
}
pub fn coHalfspaceNormal(&self, handle: FlatHandle) -> Option<RawVector> {
self.map(handle, |co| {
co.shape()
.as_halfspace()
.map(|h| h.normal.into_inner().into())
})
}
/// The half-extents of this collider if it is has a cuboid shape.
pub fn coHalfExtents(&self, handle: FlatHandle) -> Option<RawVector> {
self.map(handle, |co| {
co.shape()
.as_cuboid()
.map(|c| c.half_extents.into())
.or_else(|| {
co.shape()
.as_round_cuboid()
.map(|c| c.inner_shape.half_extents.into())
})
})
}
/// Set the half-extents of this collider if it has a cuboid shape.
pub fn coSetHalfExtents(&mut self, handle: FlatHandle, newHalfExtents: &RawVector) {
self.map_mut(handle, |co| match co.shape().shape_type() {
ShapeType::Cuboid => co
.shape_mut()
.as_cuboid_mut()
.map(|b| b.half_extents = newHalfExtents.0.into()),
ShapeType::RoundCuboid => co
.shape_mut()
.as_round_cuboid_mut()
.map(|b| b.inner_shape.half_extents = newHalfExtents.0.into()),
_ => None,
});
}
/// The radius of this collider if it is a ball, capsule, cylinder, or cone shape.
pub fn coRadius(&self, handle: FlatHandle) -> Option<f32> {
self.map(handle, |co| match co.shape().shape_type() {
ShapeType::Ball => co.shape().as_ball().map(|b| b.radius),
ShapeType::Capsule => co.shape().as_capsule().map(|b| b.radius),
#[cfg(feature = "dim3")]
ShapeType::Cylinder => co.shape().as_cylinder().map(|b| b.radius),
#[cfg(feature = "dim3")]
ShapeType::RoundCylinder => {
co.shape().as_round_cylinder().map(|b| b.inner_shape.radius)
}
#[cfg(feature = "dim3")]
ShapeType::Cone => co.shape().as_cone().map(|b| b.radius),
_ => None,
})
}
/// Set the radius of this collider if it is a ball, capsule, cylinder, or cone shape.
pub fn coSetRadius(&mut self, handle: FlatHandle, newRadius: Real) {
self.map_mut(handle, |co| match co.shape().shape_type() {
ShapeType::Ball => co.shape_mut().as_ball_mut().map(|b| b.radius = newRadius),
ShapeType::Capsule => co
.shape_mut()
.as_capsule_mut()
.map(|b| b.radius = newRadius),
#[cfg(feature = "dim3")]
ShapeType::Cylinder => co
.shape_mut()
.as_cylinder_mut()
.map(|b| b.radius = newRadius),
#[cfg(feature = "dim3")]
ShapeType::RoundCylinder => co
.shape_mut()
.as_round_cylinder_mut()
.map(|b| b.inner_shape.radius = newRadius),
#[cfg(feature = "dim3")]
ShapeType::Cone => co.shape_mut().as_cone_mut().map(|b| b.radius = newRadius),
_ => None,
});
}
/// The half height of this collider if it is a capsule, cylinder, or cone shape.
pub fn coHalfHeight(&self, handle: FlatHandle) -> Option<f32> {
self.map(handle, |co| match co.shape().shape_type() {
ShapeType::Capsule => co.shape().as_capsule().map(|b| b.half_height()),
#[cfg(feature = "dim3")]
ShapeType::Cylinder => co.shape().as_cylinder().map(|b| b.half_height),
#[cfg(feature = "dim3")]
ShapeType::RoundCylinder => co
.shape()
.as_round_cylinder()
.map(|b| b.inner_shape.half_height),
#[cfg(feature = "dim3")]
ShapeType::Cone => co.shape().as_cone().map(|b| b.half_height),
_ => None,
})
}
/// Set the half height of this collider if it is a capsule, cylinder, or cone shape.
pub fn coSetHalfHeight(&mut self, handle: FlatHandle, newHalfheight: Real) {
self.map_mut(handle, |co| match co.shape().shape_type() {
ShapeType::Capsule => {
let point = Point::from(Vector::y() * newHalfheight);
co.shape_mut().as_capsule_mut().map(|b| {
b.segment.a = -point;
b.segment.b = point;
})
}
#[cfg(feature = "dim3")]
ShapeType::Cylinder => co
.shape_mut()
.as_cylinder_mut()
.map(|b| b.half_height = newHalfheight),
#[cfg(feature = "dim3")]
ShapeType::RoundCylinder => co
.shape_mut()
.as_round_cylinder_mut()
.map(|b| b.inner_shape.half_height = newHalfheight),
#[cfg(feature = "dim3")]
ShapeType::Cone => co
.shape_mut()
.as_cone_mut()
.map(|b| b.half_height = newHalfheight),
_ => None,
});
}
/// The radius of the round edges of this collider.
pub fn coRoundRadius(&self, handle: FlatHandle) -> Option<f32> {
self.map(handle, |co| match co.shape().shape_type() {
ShapeType::RoundCuboid => co.shape().as_round_cuboid().map(|b| b.border_radius),
ShapeType::RoundTriangle => co.shape().as_round_triangle().map(|b| b.border_radius),
#[cfg(feature = "dim3")]
ShapeType::RoundCylinder => co.shape().as_round_cylinder().map(|b| b.border_radius),
#[cfg(feature = "dim3")]
ShapeType::RoundCone => co.shape().as_round_cone().map(|b| b.border_radius),
#[cfg(feature = "dim3")]
ShapeType::RoundConvexPolyhedron => co
.shape()
.as_round_convex_polyhedron()
.map(|b| b.border_radius),
#[cfg(feature = "dim2")]
ShapeType::RoundConvexPolygon => co
.shape()
.as_round_convex_polygon()
.map(|b| b.border_radius),
_ => None,
})
}
/// Set the radius of the round edges of this collider.
pub fn coSetRoundRadius(&mut self, handle: FlatHandle, newBorderRadius: Real) {
self.map_mut(handle, |co| match co.shape().shape_type() {
ShapeType::RoundCuboid => co
.shape_mut()
.as_round_cuboid_mut()
.map(|b| b.border_radius = newBorderRadius),
ShapeType::RoundTriangle => co
.shape_mut()
.as_round_triangle_mut()
.map(|b| b.border_radius = newBorderRadius),
#[cfg(feature = "dim3")]
ShapeType::RoundCylinder => co
.shape_mut()
.as_round_cylinder_mut()
.map(|b| b.border_radius = newBorderRadius),
#[cfg(feature = "dim3")]
ShapeType::RoundCone => co
.shape_mut()
.as_round_cone_mut()
.map(|b| b.border_radius = newBorderRadius),
#[cfg(feature = "dim3")]
ShapeType::RoundConvexPolyhedron => co
.shape_mut()
.as_round_convex_polyhedron_mut()
.map(|b| b.border_radius = newBorderRadius),
#[cfg(feature = "dim2")]
ShapeType::RoundConvexPolygon => co
.shape_mut()
.as_round_convex_polygon_mut()
.map(|b| b.border_radius = newBorderRadius),
_ => None,
});
}
pub fn coVoxelData(&self, handle: FlatHandle) -> Option<Vec<i32>> {
self.map(handle, |co| {
let vox = co.shape().as_voxels()?;
let coords = vox
.voxels()
.filter_map(|vox| (!vox.state.is_empty()).then_some(vox.grid_coords))
.flat_map(|ids| ids.coords.data.0[0])
.collect();
Some(coords)
})
}
pub fn coVoxelSize(&self, handle: FlatHandle) -> Option<RawVector> {
self.map(handle, |co| {
let vox = co.shape().as_voxels()?;
Some(RawVector(vox.voxel_size()))
})
}
#[cfg(feature = "dim2")]
pub fn coSetVoxel(&mut self, handle: FlatHandle, ix: i32, iy: i32, filled: bool) {
self.map_mut(handle, |co| {
if let Some(vox) = co.shape_mut().as_voxels_mut() {
vox.set_voxel(Point::new(ix, iy), filled);
}
})
}
#[cfg(feature = "dim3")]
pub fn coSetVoxel(&mut self, handle: FlatHandle, ix: i32, iy: i32, iz: i32, filled: bool) {
self.map_mut(handle, |co| {
if let Some(vox) = co.shape_mut().as_voxels_mut() {
vox.set_voxel(Point::new(ix, iy, iz), filled);
}
})
}
#[cfg(feature = "dim2")]
pub fn coPropagateVoxelChange(
&mut self,
handle1: FlatHandle,
handle2: FlatHandle,
ix: i32,
iy: i32,
shift_x: i32,
shift_y: i32,
) {
self.map_pair_mut(handle1, handle2, |co1, co2| {
if let (Some(co1), Some(co2)) = (co1, co2) {
if let (Some(vox1), Some(vox2)) = (
co1.shape_mut().as_voxels_mut(),
co2.shape_mut().as_voxels_mut(),
) {
vox1.propagate_voxel_change(
vox2,
Point::new(ix, iy),
Vector::new(shift_x, shift_y),
);
}
}
})
}
#[cfg(feature = "dim3")]
pub fn coPropagateVoxelChange(
&mut self,
handle1: FlatHandle,
handle2: FlatHandle,
ix: i32,
iy: i32,
iz: i32,
shift_x: i32,
shift_y: i32,
shift_z: i32,
) {
self.map_pair_mut(handle1, handle2, |co1, co2| {
if let (Some(co1), Some(co2)) = (co1, co2) {
if let (Some(vox1), Some(vox2)) = (
co1.shape_mut().as_voxels_mut(),
co2.shape_mut().as_voxels_mut(),
) {
vox1.propagate_voxel_change(
vox2,
Point::new(ix, iy, iz),
Vector::new(shift_x, shift_y, shift_z),
);
}
}
})
}
#[cfg(feature = "dim2")]
pub fn coCombineVoxelStates(
&mut self,
handle1: FlatHandle,
handle2: FlatHandle,
shift_x: i32,
shift_y: i32,
) {
self.map_pair_mut(handle1, handle2, |co1, co2| {
if let (Some(co1), Some(co2)) = (co1, co2) {
if let (Some(vox1), Some(vox2)) = (
co1.shape_mut().as_voxels_mut(),
co2.shape_mut().as_voxels_mut(),
) {
vox1.combine_voxel_states(vox2, Vector::new(shift_x, shift_y));
}
}
})
}
#[cfg(feature = "dim3")]
pub fn coCombineVoxelStates(
&mut self,
handle1: FlatHandle,
handle2: FlatHandle,
shift_x: i32,
shift_y: i32,
shift_z: i32,
) {
self.map_pair_mut(handle1, handle2, |co1, co2| {
if let (Some(co1), Some(co2)) = (co1, co2) {
if let (Some(vox1), Some(vox2)) = (
co1.shape_mut().as_voxels_mut(),
co2.shape_mut().as_voxels_mut(),
) {
vox1.combine_voxel_states(vox2, Vector::new(shift_x, shift_y, shift_z));
}
}
})
}
/// The vertices of this triangle mesh, polyline, convex polyhedron, segment, triangle or convex polyhedron, if it is one.
pub fn coVertices(&self, handle: FlatHandle) -> Option<Vec<f32>> {
let flatten =
|vertices: &[Point<f32>]| vertices.iter().flat_map(|p| p.iter()).copied().collect();
self.map(handle, |co| match co.shape().shape_type() {
ShapeType::TriMesh => co.shape().as_trimesh().map(|t| flatten(t.vertices())),
#[cfg(feature = "dim2")]
ShapeType::Polyline => co.shape().as_polyline().map(|p| flatten(p.vertices())),
#[cfg(feature = "dim3")]
ShapeType::ConvexPolyhedron => co
.shape()
.as_convex_polyhedron()
.map(|p| flatten(p.points())),
#[cfg(feature = "dim3")]
ShapeType::RoundConvexPolyhedron => co
.shape()
.as_round_convex_polyhedron()
.map(|p| flatten(p.inner_shape.points())),
#[cfg(feature = "dim2")]
ShapeType::ConvexPolygon => co.shape().as_convex_polygon().map(|p| flatten(p.points())),
#[cfg(feature = "dim2")]
ShapeType::RoundConvexPolygon => co
.shape()
.as_round_convex_polygon()
.map(|p| flatten(p.inner_shape.points())),
ShapeType::Segment => co.shape().as_segment().map(|s| flatten(&[s.a, s.b])),
ShapeType::RoundTriangle => co
.shape()
.as_round_triangle()
.map(|t| flatten(&[t.inner_shape.a, t.inner_shape.b, t.inner_shape.c])),
ShapeType::Triangle => co.shape().as_triangle().map(|t| flatten(&[t.a, t.b, t.c])),
_ => None,
})
}
/// The indices of this triangle mesh, polyline, or convex polyhedron, if it is one.
pub fn coIndices(&self, handle: FlatHandle) -> Option<Vec<u32>> {
self.map(handle, |co| match co.shape().shape_type() {
ShapeType::TriMesh => co
.shape()
.as_trimesh()
.map(|t| t.indices().iter().flat_map(|p| p.iter()).copied().collect()),
ShapeType::Polyline => co
.shape()
.as_polyline()
.map(|p| p.indices().iter().flat_map(|p| p.iter()).copied().collect()),
#[cfg(feature = "dim3")]
ShapeType::ConvexPolyhedron => co.shape().as_convex_polyhedron().map(|p| {
// TODO: avoid the `.to_trimesh()`.
p.to_trimesh()
.1
.iter()
.flat_map(|p| p.iter())
.copied()
.collect()
}),
#[cfg(feature = "dim3")]
ShapeType::RoundConvexPolyhedron => co.shape().as_round_convex_polyhedron().map(|p| {
// TODO: avoid the `.to_trimesh()`.
p.inner_shape
.to_trimesh()
.1
.iter()
.flat_map(|p| p.iter())
.copied()
.collect()
}),
_ => None,
})
}
pub fn coTriMeshFlags(&self, handle: FlatHandle) -> Option<u32> {
self.map(handle, |co| {
co.shape().as_trimesh().map(|tri| tri.flags().bits() as u32)
})
}
#[cfg(feature = "dim3")]
pub fn coHeightFieldFlags(&self, handle: FlatHandle) -> Option<u32> {
self.map(handle, |co| {
co.shape()
.as_heightfield()
.map(|hf| hf.flags().bits() as u32)
})
}
/// The height of this heightfield if it is one.
pub fn coHeightfieldHeights(&self, handle: FlatHandle) -> Option<Vec<f32>> {
self.map(handle, |co| match co.shape().shape_type() {
ShapeType::HeightField => co
.shape()
.as_heightfield()
.map(|h| h.heights().as_slice().to_vec()),
_ => None,
})
}
/// The scaling factor applied of this heightfield if it is one.
pub fn coHeightfieldScale(&self, handle: FlatHandle) -> Option<RawVector> {
self.map(handle, |co| match co.shape().shape_type() {
ShapeType::HeightField => co.shape().as_heightfield().map(|h| RawVector(*h.scale())),
_ => None,
})
}
/// The number of rows on this heightfield's height matrix, if it is one.
#[cfg(feature = "dim3")]
pub fn coHeightfieldNRows(&self, handle: FlatHandle) -> Option<usize> {
self.map(handle, |co| match co.shape().shape_type() {
ShapeType::HeightField => co.shape().as_heightfield().map(|h| h.nrows()),
_ => None,
})
}
/// The number of columns on this heightfield's height matrix, if it is one.
#[cfg(feature = "dim3")]
pub fn coHeightfieldNCols(&self, handle: FlatHandle) -> Option<usize> {
self.map(handle, |co| match co.shape().shape_type() {
ShapeType::HeightField => co.shape().as_heightfield().map(|h| h.ncols()),
_ => None,
})
}
/// The unique integer identifier of the collider this collider is attached to.
pub fn coParent(&self, handle: FlatHandle) -> Option<FlatHandle> {
self.map(handle, |co| co.parent().map(|p| utils::flat_handle(p.0)))
}
pub fn coSetEnabled(&mut self, handle: FlatHandle, enabled: bool) {
self.map_mut(handle, |co| co.set_enabled(enabled))
}
pub fn coIsEnabled(&self, handle: FlatHandle) -> bool {
self.map(handle, |co| co.is_enabled())
}
pub fn coSetContactSkin(&mut self, handle: FlatHandle, contact_skin: f32) {
self.map_mut(handle, |co| co.set_contact_skin(contact_skin))
}
pub fn coContactSkin(&self, handle: FlatHandle) -> f32 {
self.map(handle, |co| co.contact_skin())
}
/// The friction coefficient of this collider.
pub fn coFriction(&self, handle: FlatHandle) -> f32 {
self.map(handle, |co| co.material().friction)
}
/// The restitution coefficient of this collider.
pub fn coRestitution(&self, handle: FlatHandle) -> f32 {
self.map(handle, |co| co.material().restitution)
}
/// The density of this collider.
pub fn coDensity(&self, handle: FlatHandle) -> f32 {
self.map(handle, |co| co.density())
}
/// The mass of this collider.
pub fn coMass(&self, handle: FlatHandle) -> f32 {
self.map(handle, |co| co.mass())
}
/// The volume of this collider.
pub fn coVolume(&self, handle: FlatHandle) -> f32 {
self.map(handle, |co| co.volume())
}
/// The collision groups of this collider.
pub fn coCollisionGroups(&self, handle: FlatHandle) -> u32 {
self.map(handle, |co| {
super::pack_interaction_groups(co.collision_groups())
})
}
/// The solver groups of this collider.
pub fn coSolverGroups(&self, handle: FlatHandle) -> u32 {
self.map(handle, |co| {
super::pack_interaction_groups(co.solver_groups())
})
}
/// The physics hooks enabled for this collider.
pub fn coActiveHooks(&self, handle: FlatHandle) -> u32 {
self.map(handle, |co| co.active_hooks().bits())
}
/// The collision types enabled for this collider.
pub fn coActiveCollisionTypes(&self, handle: FlatHandle) -> u16 {
self.map(handle, |co| co.active_collision_types().bits())
}
/// The events enabled for this collider.
pub fn coActiveEvents(&self, handle: FlatHandle) -> u32 {
self.map(handle, |co| co.active_events().bits())
}
/// The total force magnitude beyond which a contact force event can be emitted.
pub fn coContactForceEventThreshold(&self, handle: FlatHandle) -> f32 {
self.map(handle, |co| co.contact_force_event_threshold())
}
pub fn coContainsPoint(&self, handle: FlatHandle, point: &RawVector) -> bool {
self.map(handle, |co| {
co.shared_shape()
.containsPoint(co.position(), &point.0.into())
})
}
pub fn coCastShape(
&self,
handle: FlatHandle,
colliderVel: &RawVector,
shape2: &RawShape,
shape2Pos: &RawVector,
shape2Rot: &RawRotation,
shape2Vel: &RawVector,
target_distance: f32,
maxToi: f32,
stop_at_penetration: bool,
) -> Option<RawShapeCastHit> {
let pos2 = Isometry::from_parts(shape2Pos.0.into(), shape2Rot.0);
self.map(handle, |co| {
let pos1 = co.position();
co.shared_shape().castShape(
pos1,
&colliderVel.0.into(),
&*shape2.0,
&pos2,
&shape2Vel.0.into(),
target_distance,
maxToi,
stop_at_penetration,
)
})
}
pub fn coCastCollider(
&self,
handle: FlatHandle,
collider1Vel: &RawVector,
collider2handle: FlatHandle,
collider2Vel: &RawVector,
target_distance: f32,
max_toi: f32,
stop_at_penetration: bool,
) -> Option<RawColliderShapeCastHit> {
let handle2 = utils::collider_handle(collider2handle);
let co2 = self
.0
.get(handle2)
.expect("Invalid Collider reference. It may have been removed from the physics World.");
self.map(handle, |co| {
query::cast_shapes(
co.position(),
&collider1Vel.0,
co.shape(),
co2.position(),
&collider2Vel.0,
co2.shape(),
ShapeCastOptions {
max_time_of_impact: max_toi,
stop_at_penetration,
target_distance,
compute_impact_geometry_on_penetration: true,
},
)
.unwrap_or(None)
.map_or(None, |hit| {
Some(RawColliderShapeCastHit {
handle: handle2,
hit,
})
})
})
}
pub fn coIntersectsShape(
&self,
handle: FlatHandle,
shape2: &RawShape,
shapePos2: &RawVector,
shapeRot2: &RawRotation,
) -> bool {
let pos2 = Isometry::from_parts(shapePos2.0.into(), shapeRot2.0);
self.map(handle, |co| {
co.shared_shape()
.intersectsShape(co.position(), &*shape2.0, &pos2)
})
}
pub fn coContactShape(
&self,
handle: FlatHandle,
shape2: &RawShape,
shapePos2: &RawVector,
shapeRot2: &RawRotation,
prediction: f32,
) -> Option<RawShapeContact> {
let pos2 = Isometry::from_parts(shapePos2.0.into(), shapeRot2.0);
self.map(handle, |co| {
co.shared_shape()
.contactShape(co.position(), &*shape2.0, &pos2, prediction)
})
}
pub fn coContactCollider(
&self,
handle: FlatHandle,
collider2handle: FlatHandle,
prediction: f32,
) -> Option<RawShapeContact> {
let co2 = self
.0
.get(utils::collider_handle(collider2handle))
.expect("Invalid Collider reference. It may have been removed from the physics World.");
self.map(handle, |co| {
query::contact(
co.position(),
co.shape(),
&co2.position(),
co2.shape(),
prediction,
)
.ok()
.flatten()
.map(|contact| RawShapeContact { contact })
})
}
pub fn coProjectPoint(
&self,
handle: FlatHandle,
point: &RawVector,
solid: bool,
) -> RawPointProjection {
self.map(handle, |co| {
co.shared_shape()
.projectPoint(co.position(), &point.0.into(), solid)
})
}
pub fn coIntersectsRay(
&self,
handle: FlatHandle,
rayOrig: &RawVector,
rayDir: &RawVector,
maxToi: f32,
) -> bool {
self.map(handle, |co| {
co.shared_shape().intersectsRay(
co.position(),
rayOrig.0.into(),
rayDir.0.into(),
maxToi,
)
})
}
pub fn coCastRay(
&self,
handle: FlatHandle,
rayOrig: &RawVector,
rayDir: &RawVector,
maxToi: f32,
solid: bool,
) -> f32 {
self.map(handle, |co| {
co.shared_shape().castRay(
co.position(),
rayOrig.0.into(),
rayDir.0.into(),
maxToi,
solid,
)
})
}
pub fn coCastRayAndGetNormal(
&self,
handle: FlatHandle,
rayOrig: &RawVector,
rayDir: &RawVector,
maxToi: f32,
solid: bool,
) -> Option<RawRayIntersection> {
self.map(handle, |co| {
co.shared_shape().castRayAndGetNormal(
co.position(),
rayOrig.0.into(),
rayDir.0.into(),
maxToi,
solid,
)
})
}
pub fn coSetSensor(&mut self, handle: FlatHandle, is_sensor: bool) {
self.map_mut(handle, |co| co.set_sensor(is_sensor))
}
pub fn coSetRestitution(&mut self, handle: FlatHandle, restitution: f32) {
self.map_mut(handle, |co| co.set_restitution(restitution))
}
pub fn coSetFriction(&mut self, handle: FlatHandle, friction: f32) {
self.map_mut(handle, |co| co.set_friction(friction))
}
pub fn coFrictionCombineRule(&self, handle: FlatHandle) -> u32 {
self.map(handle, |co| co.friction_combine_rule() as u32)
}
pub fn coSetFrictionCombineRule(&mut self, handle: FlatHandle, rule: u32) {
let rule = super::combine_rule_from_u32(rule);
self.map_mut(handle, |co| co.set_friction_combine_rule(rule))
}
pub fn coRestitutionCombineRule(&self, handle: FlatHandle) -> u32 {
self.map(handle, |co| co.restitution_combine_rule() as u32)
}
pub fn coSetRestitutionCombineRule(&mut self, handle: FlatHandle, rule: u32) {
let rule = super::combine_rule_from_u32(rule);
self.map_mut(handle, |co| co.set_restitution_combine_rule(rule))
}
pub fn coSetCollisionGroups(&mut self, handle: FlatHandle, groups: u32) {
let groups = super::unpack_interaction_groups(groups);
self.map_mut(handle, |co| co.set_collision_groups(groups))
}
pub fn coSetSolverGroups(&mut self, handle: FlatHandle, groups: u32) {
let groups = super::unpack_interaction_groups(groups);
self.map_mut(handle, |co| co.set_solver_groups(groups))
}
pub fn coSetActiveHooks(&mut self, handle: FlatHandle, hooks: u32) {
let hooks = ActiveHooks::from_bits(hooks).unwrap_or(ActiveHooks::empty());
self.map_mut(handle, |co| co.set_active_hooks(hooks));
}
pub fn coSetActiveEvents(&mut self, handle: FlatHandle, events: u32) {
let events = ActiveEvents::from_bits(events).unwrap_or(ActiveEvents::empty());
self.map_mut(handle, |co| co.set_active_events(events))
}
pub fn coSetActiveCollisionTypes(&mut self, handle: FlatHandle, types: u16) {
let types = ActiveCollisionTypes::from_bits(types).unwrap_or(ActiveCollisionTypes::empty());
self.map_mut(handle, |co| co.set_active_collision_types(types));
}
pub fn coSetShape(&mut self, handle: FlatHandle, shape: &RawShape) {
self.map_mut(handle, |co| co.set_shape(shape.0.clone()));
}
pub fn coSetContactForceEventThreshold(&mut self, handle: FlatHandle, threshold: f32) {
self.map_mut(handle, |co| co.set_contact_force_event_threshold(threshold))
}
pub fn coSetDensity(&mut self, handle: FlatHandle, density: f32) {
self.map_mut(handle, |co| co.set_density(density))
}
pub fn coSetMass(&mut self, handle: FlatHandle, mass: f32) {
self.map_mut(handle, |co| co.set_mass(mass))
}
#[cfg(feature = "dim3")]
pub fn coSetMassProperties(
&mut self,
handle: FlatHandle,
mass: f32,
centerOfMass: &RawVector,
principalAngularInertia: &RawVector,
angularInertiaFrame: &RawRotation,
) {
self.map_mut(handle, |co| {
let mprops = MassProperties::with_principal_inertia_frame(
centerOfMass.0.into(),
mass,
principalAngularInertia.0,
angularInertiaFrame.0,
);
co.set_mass_properties(mprops)
})
}
#[cfg(feature = "dim2")]
pub fn coSetMassProperties(
&mut self,
handle: FlatHandle,
mass: f32,
centerOfMass: &RawVector,
principalAngularInertia: f32,
) {
self.map_mut(handle, |co| {
let props = MassProperties::new(centerOfMass.0.into(), mass, principalAngularInertia);
co.set_mass_properties(props)
})
}
}