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检测到的代码问题
This commit is contained in:
13
thirdparty/rapier.js/src/dynamics/ccd_solver.rs
vendored
Normal file
13
thirdparty/rapier.js/src/dynamics/ccd_solver.rs
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
use rapier::dynamics::CCDSolver;
|
||||
use wasm_bindgen::prelude::*;
|
||||
|
||||
#[wasm_bindgen]
|
||||
pub struct RawCCDSolver(pub(crate) CCDSolver);
|
||||
|
||||
#[wasm_bindgen]
|
||||
impl RawCCDSolver {
|
||||
#[wasm_bindgen(constructor)]
|
||||
pub fn new() -> Self {
|
||||
RawCCDSolver(CCDSolver::new())
|
||||
}
|
||||
}
|
||||
215
thirdparty/rapier.js/src/dynamics/impulse_joint.rs
vendored
Normal file
215
thirdparty/rapier.js/src/dynamics/impulse_joint.rs
vendored
Normal file
@@ -0,0 +1,215 @@
|
||||
use crate::dynamics::{RawImpulseJointSet, RawJointAxis, RawJointType, RawMotorModel};
|
||||
use crate::math::{RawRotation, RawVector};
|
||||
use crate::utils::{self, FlatHandle};
|
||||
use rapier::dynamics::JointAxis;
|
||||
use wasm_bindgen::prelude::*;
|
||||
|
||||
#[wasm_bindgen]
|
||||
impl RawImpulseJointSet {
|
||||
/// The type of this joint.
|
||||
pub fn jointType(&self, handle: FlatHandle) -> RawJointType {
|
||||
self.map(handle, |j| j.data.locked_axes.into())
|
||||
}
|
||||
|
||||
/// The unique integer identifier of the first rigid-body this joint it attached to.
|
||||
pub fn jointBodyHandle1(&self, handle: FlatHandle) -> FlatHandle {
|
||||
self.map(handle, |j| utils::flat_handle(j.body1.0))
|
||||
}
|
||||
|
||||
/// The unique integer identifier of the second rigid-body this joint is attached to.
|
||||
pub fn jointBodyHandle2(&self, handle: FlatHandle) -> FlatHandle {
|
||||
self.map(handle, |j| utils::flat_handle(j.body2.0))
|
||||
}
|
||||
|
||||
/// The angular part of the joint’s local frame relative to the first rigid-body it is attached to.
|
||||
pub fn jointFrameX1(&self, handle: FlatHandle) -> RawRotation {
|
||||
self.map(handle, |j| j.data.local_frame1.rotation.into())
|
||||
}
|
||||
|
||||
/// The angular part of the joint’s local frame relative to the second rigid-body it is attached to.
|
||||
pub fn jointFrameX2(&self, handle: FlatHandle) -> RawRotation {
|
||||
self.map(handle, |j| j.data.local_frame2.rotation.into())
|
||||
}
|
||||
|
||||
/// The position of the first anchor of this joint.
|
||||
///
|
||||
/// The first anchor gives the position of the points application point on the
|
||||
/// local frame of the first rigid-body it is attached to.
|
||||
pub fn jointAnchor1(&self, handle: FlatHandle) -> RawVector {
|
||||
self.map(handle, |j| j.data.local_frame1.translation.vector.into())
|
||||
}
|
||||
|
||||
/// The position of the second anchor of this joint.
|
||||
///
|
||||
/// The second anchor gives the position of the points application point on the
|
||||
/// local frame of the second rigid-body it is attached to.
|
||||
pub fn jointAnchor2(&self, handle: FlatHandle) -> RawVector {
|
||||
self.map(handle, |j| j.data.local_frame2.translation.vector.into())
|
||||
}
|
||||
|
||||
/// Sets the position of the first local anchor
|
||||
pub fn jointSetAnchor1(&mut self, handle: FlatHandle, newPos: &RawVector) {
|
||||
self.map_mut(handle, |j| {
|
||||
j.data.set_local_anchor1(newPos.0.into());
|
||||
});
|
||||
}
|
||||
|
||||
/// Sets the position of the second local anchor
|
||||
pub fn jointSetAnchor2(&mut self, handle: FlatHandle, newPos: &RawVector) {
|
||||
self.map_mut(handle, |j| {
|
||||
j.data.set_local_anchor2(newPos.0.into());
|
||||
})
|
||||
}
|
||||
|
||||
/// Are contacts between the rigid-bodies attached by this joint enabled?
|
||||
pub fn jointContactsEnabled(&self, handle: FlatHandle) -> bool {
|
||||
self.map(handle, |j| j.data.contacts_enabled)
|
||||
}
|
||||
|
||||
/// Sets whether contacts are enabled between the rigid-bodies attached by this joint.
|
||||
pub fn jointSetContactsEnabled(&mut self, handle: FlatHandle, enabled: bool) {
|
||||
self.map_mut(handle, |j| {
|
||||
j.data.contacts_enabled = enabled;
|
||||
});
|
||||
}
|
||||
|
||||
/// Are the limits for this joint enabled?
|
||||
pub fn jointLimitsEnabled(&self, handle: FlatHandle, axis: RawJointAxis) -> bool {
|
||||
self.map(handle, |j| {
|
||||
j.data.limit_axes.contains(JointAxis::from(axis).into())
|
||||
})
|
||||
}
|
||||
|
||||
/// Return the lower limit along the given joint axis.
|
||||
pub fn jointLimitsMin(&self, handle: FlatHandle, axis: RawJointAxis) -> f32 {
|
||||
self.map(handle, |j| j.data.limits[axis as usize].min)
|
||||
}
|
||||
|
||||
/// If this is a prismatic joint, returns its upper limit.
|
||||
pub fn jointLimitsMax(&self, handle: FlatHandle, axis: RawJointAxis) -> f32 {
|
||||
self.map(handle, |j| j.data.limits[axis as usize].max)
|
||||
}
|
||||
|
||||
/// Enables and sets the joint limits
|
||||
pub fn jointSetLimits(&mut self, handle: FlatHandle, axis: RawJointAxis, min: f32, max: f32) {
|
||||
self.map_mut(handle, |j| {
|
||||
j.data.set_limits(axis.into(), [min, max]);
|
||||
});
|
||||
}
|
||||
|
||||
pub fn jointConfigureMotorModel(
|
||||
&mut self,
|
||||
handle: FlatHandle,
|
||||
axis: RawJointAxis,
|
||||
model: RawMotorModel,
|
||||
) {
|
||||
self.map_mut(handle, |j| {
|
||||
j.data.motors[axis as usize].model = model.into()
|
||||
})
|
||||
}
|
||||
|
||||
/*
|
||||
#[cfg(feature = "dim3")]
|
||||
pub fn jointConfigureBallMotorVelocity(
|
||||
&mut self,
|
||||
handle: FlatHandle,
|
||||
vx: f32,
|
||||
vy: f32,
|
||||
vz: f32,
|
||||
factor: f32,
|
||||
) {
|
||||
let targetVel = Vector3::new(vx, vy, vz);
|
||||
|
||||
self.map_mut(handle, |j| match &mut j.params {
|
||||
JointData::SphericalJoint(j) => j.configure_motor_velocity(targetVel, factor),
|
||||
_ => {}
|
||||
})
|
||||
}
|
||||
|
||||
#[cfg(feature = "dim3")]
|
||||
pub fn jointConfigureBallMotorPosition(
|
||||
&mut self,
|
||||
handle: FlatHandle,
|
||||
qw: f32,
|
||||
qx: f32,
|
||||
qy: f32,
|
||||
qz: f32,
|
||||
stiffness: f32,
|
||||
damping: f32,
|
||||
) {
|
||||
let quat = Quaternion::new(qw, qx, qy, qz);
|
||||
|
||||
self.map_mut(handle, |j| match &mut j.params {
|
||||
JointData::SphericalJoint(j) => {
|
||||
if let Some(unit_quat) = UnitQuaternion::try_new(quat, 1.0e-5) {
|
||||
j.configure_motor_position(unit_quat, stiffness, damping)
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
})
|
||||
}
|
||||
|
||||
#[cfg(feature = "dim3")]
|
||||
pub fn jointConfigureBallMotor(
|
||||
&mut self,
|
||||
handle: FlatHandle,
|
||||
qw: f32,
|
||||
qx: f32,
|
||||
qy: f32,
|
||||
qz: f32,
|
||||
vx: f32,
|
||||
vy: f32,
|
||||
vz: f32,
|
||||
stiffness: f32,
|
||||
damping: f32,
|
||||
) {
|
||||
let quat = Quaternion::new(qw, qx, qy, qz);
|
||||
let vel = Vector3::new(vx, vy, vz);
|
||||
|
||||
self.map_mut(handle, |j| match &mut j.params {
|
||||
JointData::SphericalJoint(j) => {
|
||||
if let Some(unit_quat) = UnitQuaternion::try_new(quat, 1.0e-5) {
|
||||
j.configure_motor(unit_quat, vel, stiffness, damping)
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
})
|
||||
}
|
||||
*/
|
||||
|
||||
pub fn jointConfigureMotorVelocity(
|
||||
&mut self,
|
||||
handle: FlatHandle,
|
||||
axis: RawJointAxis,
|
||||
targetVel: f32,
|
||||
factor: f32,
|
||||
) {
|
||||
self.jointConfigureMotor(handle, axis, 0.0, targetVel, 0.0, factor)
|
||||
}
|
||||
|
||||
pub fn jointConfigureMotorPosition(
|
||||
&mut self,
|
||||
handle: FlatHandle,
|
||||
axis: RawJointAxis,
|
||||
targetPos: f32,
|
||||
stiffness: f32,
|
||||
damping: f32,
|
||||
) {
|
||||
self.jointConfigureMotor(handle, axis, targetPos, 0.0, stiffness, damping)
|
||||
}
|
||||
|
||||
pub fn jointConfigureMotor(
|
||||
&mut self,
|
||||
handle: FlatHandle,
|
||||
axis: RawJointAxis,
|
||||
targetPos: f32,
|
||||
targetVel: f32,
|
||||
stiffness: f32,
|
||||
damping: f32,
|
||||
) {
|
||||
self.map_mut(handle, |j| {
|
||||
j.data
|
||||
.set_motor(axis.into(), targetPos, targetVel, stiffness, damping);
|
||||
})
|
||||
}
|
||||
}
|
||||
92
thirdparty/rapier.js/src/dynamics/impulse_joint_set.rs
vendored
Normal file
92
thirdparty/rapier.js/src/dynamics/impulse_joint_set.rs
vendored
Normal file
@@ -0,0 +1,92 @@
|
||||
use crate::dynamics::RawGenericJoint;
|
||||
use crate::utils::{self, FlatHandle};
|
||||
use rapier::dynamics::{ImpulseJoint, ImpulseJointSet};
|
||||
use wasm_bindgen::prelude::*;
|
||||
|
||||
#[wasm_bindgen]
|
||||
pub struct RawImpulseJointSet(pub(crate) ImpulseJointSet);
|
||||
|
||||
impl RawImpulseJointSet {
|
||||
pub(crate) fn map<T>(&self, handle: FlatHandle, f: impl FnOnce(&ImpulseJoint) -> T) -> T {
|
||||
let body = self.0.get(utils::impulse_joint_handle(handle)).expect(
|
||||
"Invalid ImpulseJoint reference. It may have been removed from the physics World.",
|
||||
);
|
||||
f(body)
|
||||
}
|
||||
|
||||
pub(crate) fn map_mut<T>(
|
||||
&mut self,
|
||||
handle: FlatHandle,
|
||||
f: impl FnOnce(&mut ImpulseJoint) -> T,
|
||||
) -> T {
|
||||
let body = self
|
||||
.0
|
||||
.get_mut(utils::impulse_joint_handle(handle), true)
|
||||
.expect(
|
||||
"Invalid ImpulseJoint reference. It may have been removed from the physics World.",
|
||||
);
|
||||
f(body)
|
||||
}
|
||||
}
|
||||
|
||||
#[wasm_bindgen]
|
||||
impl RawImpulseJointSet {
|
||||
#[wasm_bindgen(constructor)]
|
||||
pub fn new() -> Self {
|
||||
RawImpulseJointSet(ImpulseJointSet::new())
|
||||
}
|
||||
|
||||
pub fn createJoint(
|
||||
&mut self,
|
||||
params: &RawGenericJoint,
|
||||
parent1: FlatHandle,
|
||||
parent2: FlatHandle,
|
||||
wake_up: bool,
|
||||
) -> FlatHandle {
|
||||
utils::flat_handle(
|
||||
self.0
|
||||
.insert(
|
||||
utils::body_handle(parent1),
|
||||
utils::body_handle(parent2),
|
||||
params.0.clone(),
|
||||
wake_up,
|
||||
)
|
||||
.0,
|
||||
)
|
||||
}
|
||||
|
||||
pub fn remove(&mut self, handle: FlatHandle, wakeUp: bool) {
|
||||
let handle = utils::impulse_joint_handle(handle);
|
||||
self.0.remove(handle, wakeUp);
|
||||
}
|
||||
|
||||
pub fn len(&self) -> usize {
|
||||
self.0.len()
|
||||
}
|
||||
|
||||
pub fn contains(&self, handle: FlatHandle) -> bool {
|
||||
self.0.get(utils::impulse_joint_handle(handle)).is_some()
|
||||
}
|
||||
|
||||
/// Applies the given JavaScript function to the integer handle of each joint managed by this physics world.
|
||||
///
|
||||
/// # Parameters
|
||||
/// - `f(handle)`: the function to apply to the integer handle of each joint managed by this set. Called as `f(collider)`.
|
||||
pub fn forEachJointHandle(&self, f: &js_sys::Function) {
|
||||
let this = JsValue::null();
|
||||
for (handle, _) in self.0.iter() {
|
||||
let _ = f.call1(&this, &JsValue::from(utils::flat_handle(handle.0)));
|
||||
}
|
||||
}
|
||||
|
||||
/// Applies the given JavaScript function to the integer handle of each joint attached to the given rigid-body.
|
||||
///
|
||||
/// # Parameters
|
||||
/// - `f(handle)`: the function to apply to the integer handle of each joint attached to the rigid-body. Called as `f(collider)`.
|
||||
pub fn forEachJointAttachedToRigidBody(&self, body: FlatHandle, f: &js_sys::Function) {
|
||||
let this = JsValue::null();
|
||||
for (_, _, handle, _) in self.0.attached_joints(utils::body_handle(body)) {
|
||||
let _ = f.call1(&this, &JsValue::from(utils::flat_handle(handle.0)));
|
||||
}
|
||||
}
|
||||
}
|
||||
101
thirdparty/rapier.js/src/dynamics/integration_parameters.rs
vendored
Normal file
101
thirdparty/rapier.js/src/dynamics/integration_parameters.rs
vendored
Normal file
@@ -0,0 +1,101 @@
|
||||
use rapier::dynamics::IntegrationParameters;
|
||||
use wasm_bindgen::prelude::*;
|
||||
|
||||
#[wasm_bindgen]
|
||||
pub struct RawIntegrationParameters(pub(crate) IntegrationParameters);
|
||||
|
||||
#[wasm_bindgen]
|
||||
impl RawIntegrationParameters {
|
||||
#[wasm_bindgen(constructor)]
|
||||
pub fn new() -> Self {
|
||||
RawIntegrationParameters(IntegrationParameters::default())
|
||||
}
|
||||
|
||||
#[wasm_bindgen(getter)]
|
||||
pub fn dt(&self) -> f32 {
|
||||
self.0.dt
|
||||
}
|
||||
|
||||
#[wasm_bindgen(getter)]
|
||||
pub fn contact_erp(&self) -> f32 {
|
||||
self.0.contact_erp()
|
||||
}
|
||||
|
||||
#[wasm_bindgen(getter)]
|
||||
pub fn normalizedAllowedLinearError(&self) -> f32 {
|
||||
self.0.normalized_allowed_linear_error
|
||||
}
|
||||
|
||||
#[wasm_bindgen(getter)]
|
||||
pub fn normalizedPredictionDistance(&self) -> f32 {
|
||||
self.0.normalized_prediction_distance
|
||||
}
|
||||
|
||||
#[wasm_bindgen(getter)]
|
||||
pub fn numSolverIterations(&self) -> usize {
|
||||
self.0.num_solver_iterations
|
||||
}
|
||||
|
||||
#[wasm_bindgen(getter)]
|
||||
pub fn numInternalPgsIterations(&self) -> usize {
|
||||
self.0.num_internal_pgs_iterations
|
||||
}
|
||||
|
||||
#[wasm_bindgen(getter)]
|
||||
pub fn minIslandSize(&self) -> usize {
|
||||
self.0.min_island_size
|
||||
}
|
||||
|
||||
#[wasm_bindgen(getter)]
|
||||
pub fn maxCcdSubsteps(&self) -> usize {
|
||||
self.0.max_ccd_substeps
|
||||
}
|
||||
|
||||
#[wasm_bindgen(getter)]
|
||||
pub fn lengthUnit(&self) -> f32 {
|
||||
self.0.length_unit
|
||||
}
|
||||
|
||||
#[wasm_bindgen(setter)]
|
||||
pub fn set_dt(&mut self, value: f32) {
|
||||
self.0.dt = value;
|
||||
}
|
||||
|
||||
#[wasm_bindgen(setter)]
|
||||
pub fn set_contact_natural_frequency(&mut self, value: f32) {
|
||||
self.0.contact_natural_frequency = value
|
||||
}
|
||||
|
||||
#[wasm_bindgen(setter)]
|
||||
pub fn set_normalizedAllowedLinearError(&mut self, value: f32) {
|
||||
self.0.normalized_allowed_linear_error = value
|
||||
}
|
||||
|
||||
#[wasm_bindgen(setter)]
|
||||
pub fn set_normalizedPredictionDistance(&mut self, value: f32) {
|
||||
self.0.normalized_prediction_distance = value
|
||||
}
|
||||
|
||||
#[wasm_bindgen(setter)]
|
||||
pub fn set_numSolverIterations(&mut self, value: usize) {
|
||||
self.0.num_solver_iterations = value;
|
||||
}
|
||||
#[wasm_bindgen(setter)]
|
||||
pub fn set_numInternalPgsIterations(&mut self, value: usize) {
|
||||
self.0.num_internal_pgs_iterations = value;
|
||||
}
|
||||
#[wasm_bindgen(setter)]
|
||||
pub fn set_minIslandSize(&mut self, value: usize) {
|
||||
self.0.min_island_size = value
|
||||
}
|
||||
|
||||
#[wasm_bindgen(setter)]
|
||||
pub fn set_maxCcdSubsteps(&mut self, value: usize) {
|
||||
self.0.max_ccd_substeps = value
|
||||
}
|
||||
|
||||
#[wasm_bindgen(setter)]
|
||||
pub fn set_lengthUnit(&mut self, value: f32) {
|
||||
self.0.length_unit = value
|
||||
}
|
||||
}
|
||||
31
thirdparty/rapier.js/src/dynamics/island_manager.rs
vendored
Normal file
31
thirdparty/rapier.js/src/dynamics/island_manager.rs
vendored
Normal file
@@ -0,0 +1,31 @@
|
||||
use crate::utils;
|
||||
use rapier::dynamics::IslandManager;
|
||||
use wasm_bindgen::prelude::*;
|
||||
|
||||
#[wasm_bindgen]
|
||||
pub struct RawIslandManager(pub(crate) IslandManager);
|
||||
|
||||
#[wasm_bindgen]
|
||||
impl RawIslandManager {
|
||||
#[wasm_bindgen(constructor)]
|
||||
pub fn new() -> Self {
|
||||
RawIslandManager(IslandManager::new())
|
||||
}
|
||||
|
||||
/// Applies the given JavaScript function to the integer handle of each active rigid-body
|
||||
/// managed by this island manager.
|
||||
///
|
||||
/// After a short time of inactivity, a rigid-body is automatically deactivated ("asleep") by
|
||||
/// the physics engine in order to save computational power. A sleeping rigid-body never moves
|
||||
/// unless it is moved manually by the user.
|
||||
///
|
||||
/// # Parameters
|
||||
/// - `f(handle)`: the function to apply to the integer handle of each active rigid-body managed by this
|
||||
/// set. Called as `f(collider)`.
|
||||
pub fn forEachActiveRigidBodyHandle(&self, f: &js_sys::Function) {
|
||||
let this = JsValue::null();
|
||||
for handle in self.0.active_bodies() {
|
||||
let _ = f.call1(&this, &JsValue::from(utils::flat_handle(handle.0)));
|
||||
}
|
||||
}
|
||||
}
|
||||
314
thirdparty/rapier.js/src/dynamics/joint.rs
vendored
Normal file
314
thirdparty/rapier.js/src/dynamics/joint.rs
vendored
Normal file
@@ -0,0 +1,314 @@
|
||||
use crate::math::{RawRotation, RawVector};
|
||||
use na::Unit;
|
||||
use rapier::dynamics::{
|
||||
FixedJointBuilder, GenericJoint, JointAxesMask, JointAxis, MotorModel, PrismaticJointBuilder,
|
||||
RevoluteJointBuilder, RopeJointBuilder, SpringJointBuilder,
|
||||
};
|
||||
#[cfg(feature = "dim3")]
|
||||
use rapier::dynamics::{GenericJointBuilder, SphericalJointBuilder};
|
||||
use rapier::math::Isometry;
|
||||
use wasm_bindgen::prelude::*;
|
||||
|
||||
#[wasm_bindgen]
|
||||
#[cfg(feature = "dim2")]
|
||||
pub enum RawJointType {
|
||||
Revolute,
|
||||
Fixed,
|
||||
Prismatic,
|
||||
Rope,
|
||||
Spring,
|
||||
Generic,
|
||||
}
|
||||
|
||||
#[wasm_bindgen]
|
||||
#[cfg(feature = "dim3")]
|
||||
pub enum RawJointType {
|
||||
Revolute,
|
||||
Fixed,
|
||||
Prismatic,
|
||||
Rope,
|
||||
Spring,
|
||||
Spherical,
|
||||
Generic,
|
||||
}
|
||||
|
||||
/// The type of this joint.
|
||||
#[cfg(feature = "dim2")]
|
||||
impl From<JointAxesMask> for RawJointType {
|
||||
fn from(ty: JointAxesMask) -> RawJointType {
|
||||
let rev_axes = JointAxesMask::LIN_X | JointAxesMask::LIN_Y;
|
||||
let pri_axes = JointAxesMask::LIN_Y | JointAxesMask::ANG_X;
|
||||
let fix_axes = JointAxesMask::LIN_X | JointAxesMask::LIN_Y | JointAxesMask::ANG_X;
|
||||
|
||||
if ty == rev_axes {
|
||||
RawJointType::Revolute
|
||||
} else if ty == pri_axes {
|
||||
RawJointType::Prismatic
|
||||
} else if ty == fix_axes {
|
||||
RawJointType::Fixed
|
||||
} else {
|
||||
RawJointType::Generic
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// The type of this joint.
|
||||
#[cfg(feature = "dim3")]
|
||||
impl From<JointAxesMask> for RawJointType {
|
||||
fn from(ty: JointAxesMask) -> RawJointType {
|
||||
let rev_axes = JointAxesMask::LIN_X
|
||||
| JointAxesMask::LIN_Y
|
||||
| JointAxesMask::LIN_Z
|
||||
| JointAxesMask::ANG_Y
|
||||
| JointAxesMask::ANG_Z;
|
||||
let pri_axes = JointAxesMask::LIN_Y
|
||||
| JointAxesMask::LIN_Z
|
||||
| JointAxesMask::ANG_X
|
||||
| JointAxesMask::ANG_Y
|
||||
| JointAxesMask::ANG_Z;
|
||||
let sph_axes = JointAxesMask::ANG_X | JointAxesMask::ANG_Y | JointAxesMask::ANG_Z;
|
||||
let fix_axes = JointAxesMask::LIN_X
|
||||
| JointAxesMask::LIN_Y
|
||||
| JointAxesMask::LIN_Z
|
||||
| JointAxesMask::ANG_X
|
||||
| JointAxesMask::ANG_Y
|
||||
| JointAxesMask::ANG_Z;
|
||||
|
||||
if ty == rev_axes {
|
||||
RawJointType::Revolute
|
||||
} else if ty == pri_axes {
|
||||
RawJointType::Prismatic
|
||||
} else if ty == sph_axes {
|
||||
RawJointType::Spherical
|
||||
} else if ty == fix_axes {
|
||||
RawJointType::Fixed
|
||||
} else {
|
||||
RawJointType::Generic
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[wasm_bindgen]
|
||||
pub enum RawMotorModel {
|
||||
AccelerationBased,
|
||||
ForceBased,
|
||||
}
|
||||
|
||||
impl From<RawMotorModel> for MotorModel {
|
||||
fn from(model: RawMotorModel) -> MotorModel {
|
||||
match model {
|
||||
RawMotorModel::AccelerationBased => MotorModel::AccelerationBased,
|
||||
RawMotorModel::ForceBased => MotorModel::ForceBased,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "dim2")]
|
||||
#[wasm_bindgen]
|
||||
#[derive(Copy, Clone)]
|
||||
pub enum RawJointAxis {
|
||||
LinX,
|
||||
LinY,
|
||||
AngX,
|
||||
}
|
||||
|
||||
#[cfg(feature = "dim3")]
|
||||
#[wasm_bindgen]
|
||||
#[derive(Copy, Clone)]
|
||||
pub enum RawJointAxis {
|
||||
LinX,
|
||||
LinY,
|
||||
LinZ,
|
||||
AngX,
|
||||
AngY,
|
||||
AngZ,
|
||||
}
|
||||
|
||||
impl From<RawJointAxis> for JointAxis {
|
||||
fn from(axis: RawJointAxis) -> JointAxis {
|
||||
match axis {
|
||||
RawJointAxis::LinX => JointAxis::LinX,
|
||||
RawJointAxis::LinY => JointAxis::LinY,
|
||||
#[cfg(feature = "dim3")]
|
||||
RawJointAxis::LinZ => JointAxis::LinZ,
|
||||
RawJointAxis::AngX => JointAxis::AngX,
|
||||
#[cfg(feature = "dim3")]
|
||||
RawJointAxis::AngY => JointAxis::AngY,
|
||||
#[cfg(feature = "dim3")]
|
||||
RawJointAxis::AngZ => JointAxis::AngZ,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[wasm_bindgen]
|
||||
pub struct RawGenericJoint(pub(crate) GenericJoint);
|
||||
|
||||
#[wasm_bindgen]
|
||||
impl RawGenericJoint {
|
||||
/// Creates a new joint descriptor that builds generic joints.
|
||||
///
|
||||
/// Generic joints allow arbitrary axes of freedom to be selected
|
||||
/// for the joint from the available 6 degrees of freedom.
|
||||
#[cfg(feature = "dim3")]
|
||||
pub fn generic(
|
||||
anchor1: &RawVector,
|
||||
anchor2: &RawVector,
|
||||
axis: &RawVector,
|
||||
lockedAxes: u8,
|
||||
) -> Option<RawGenericJoint> {
|
||||
let axesMask: JointAxesMask = JointAxesMask::from_bits(lockedAxes)?;
|
||||
let axis = Unit::try_new(axis.0, 0.0)?;
|
||||
let joint: GenericJoint = GenericJointBuilder::new(axesMask)
|
||||
.local_anchor1(anchor1.0.into())
|
||||
.local_anchor2(anchor2.0.into())
|
||||
.local_axis1(axis)
|
||||
.local_axis2(axis)
|
||||
.into();
|
||||
Some(Self(joint))
|
||||
}
|
||||
|
||||
pub fn spring(
|
||||
rest_length: f32,
|
||||
stiffness: f32,
|
||||
damping: f32,
|
||||
anchor1: &RawVector,
|
||||
anchor2: &RawVector,
|
||||
) -> Self {
|
||||
Self(
|
||||
SpringJointBuilder::new(rest_length, stiffness, damping)
|
||||
.local_anchor1(anchor1.0.into())
|
||||
.local_anchor2(anchor2.0.into())
|
||||
.into(),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn rope(length: f32, anchor1: &RawVector, anchor2: &RawVector) -> Self {
|
||||
Self(
|
||||
RopeJointBuilder::new(length)
|
||||
.local_anchor1(anchor1.0.into())
|
||||
.local_anchor2(anchor2.0.into())
|
||||
.into(),
|
||||
)
|
||||
}
|
||||
|
||||
/// Create a new joint descriptor that builds spherical joints.
|
||||
///
|
||||
/// A spherical joints allows three relative rotational degrees of freedom
|
||||
/// by preventing any relative translation between the anchors of the
|
||||
/// two attached rigid-bodies.
|
||||
#[cfg(feature = "dim3")]
|
||||
pub fn spherical(anchor1: &RawVector, anchor2: &RawVector) -> Self {
|
||||
Self(
|
||||
SphericalJointBuilder::new()
|
||||
.local_anchor1(anchor1.0.into())
|
||||
.local_anchor2(anchor2.0.into())
|
||||
.into(),
|
||||
)
|
||||
}
|
||||
|
||||
/// Creates a new joint descriptor that builds a Prismatic joint.
|
||||
///
|
||||
/// A prismatic joint removes all the degrees of freedom between the
|
||||
/// affected bodies, except for the translation along one axis.
|
||||
///
|
||||
/// Returns `None` if any of the provided axes cannot be normalized.
|
||||
#[cfg(feature = "dim2")]
|
||||
pub fn prismatic(
|
||||
anchor1: &RawVector,
|
||||
anchor2: &RawVector,
|
||||
axis: &RawVector,
|
||||
limitsEnabled: bool,
|
||||
limitsMin: f32,
|
||||
limitsMax: f32,
|
||||
) -> Option<RawGenericJoint> {
|
||||
let axis = Unit::try_new(axis.0, 0.0)?;
|
||||
let mut joint = PrismaticJointBuilder::new(axis)
|
||||
.local_anchor1(anchor1.0.into())
|
||||
.local_anchor2(anchor2.0.into());
|
||||
|
||||
if limitsEnabled {
|
||||
joint = joint.limits([limitsMin, limitsMax]);
|
||||
}
|
||||
|
||||
Some(Self(joint.into()))
|
||||
}
|
||||
|
||||
/// Creates a new joint descriptor that builds a Prismatic joint.
|
||||
///
|
||||
/// A prismatic joint removes all the degrees of freedom between the
|
||||
/// affected bodies, except for the translation along one axis.
|
||||
///
|
||||
/// Returns `None` if any of the provided axes cannot be normalized.
|
||||
#[cfg(feature = "dim3")]
|
||||
pub fn prismatic(
|
||||
anchor1: &RawVector,
|
||||
anchor2: &RawVector,
|
||||
axis: &RawVector,
|
||||
limitsEnabled: bool,
|
||||
limitsMin: f32,
|
||||
limitsMax: f32,
|
||||
) -> Option<RawGenericJoint> {
|
||||
let axis = Unit::try_new(axis.0, 0.0)?;
|
||||
let mut joint = PrismaticJointBuilder::new(axis)
|
||||
.local_anchor1(anchor1.0.into())
|
||||
.local_anchor2(anchor2.0.into());
|
||||
|
||||
if limitsEnabled {
|
||||
joint = joint.limits([limitsMin, limitsMax]);
|
||||
}
|
||||
|
||||
Some(Self(joint.into()))
|
||||
}
|
||||
|
||||
/// Creates a new joint descriptor that builds a Fixed joint.
|
||||
///
|
||||
/// A fixed joint removes all the degrees of freedom between the affected bodies.
|
||||
pub fn fixed(
|
||||
anchor1: &RawVector,
|
||||
axes1: &RawRotation,
|
||||
anchor2: &RawVector,
|
||||
axes2: &RawRotation,
|
||||
) -> RawGenericJoint {
|
||||
let pos1 = Isometry::from_parts(anchor1.0.into(), axes1.0);
|
||||
let pos2 = Isometry::from_parts(anchor2.0.into(), axes2.0);
|
||||
Self(
|
||||
FixedJointBuilder::new()
|
||||
.local_frame1(pos1)
|
||||
.local_frame2(pos2)
|
||||
.into(),
|
||||
)
|
||||
}
|
||||
|
||||
/// Create a new joint descriptor that builds Revolute joints.
|
||||
///
|
||||
/// A revolute joint removes all degrees of freedom between the affected
|
||||
/// bodies except for the rotation.
|
||||
#[cfg(feature = "dim2")]
|
||||
pub fn revolute(anchor1: &RawVector, anchor2: &RawVector) -> Option<RawGenericJoint> {
|
||||
Some(Self(
|
||||
RevoluteJointBuilder::new()
|
||||
.local_anchor1(anchor1.0.into())
|
||||
.local_anchor2(anchor2.0.into())
|
||||
.into(),
|
||||
))
|
||||
}
|
||||
|
||||
/// Create a new joint descriptor that builds Revolute joints.
|
||||
///
|
||||
/// A revolute joint removes all degrees of freedom between the affected
|
||||
/// bodies except for the rotation along one axis.
|
||||
#[cfg(feature = "dim3")]
|
||||
pub fn revolute(
|
||||
anchor1: &RawVector,
|
||||
anchor2: &RawVector,
|
||||
axis: &RawVector,
|
||||
) -> Option<RawGenericJoint> {
|
||||
let axis = Unit::try_new(axis.0, 0.0)?;
|
||||
Some(Self(
|
||||
RevoluteJointBuilder::new(axis)
|
||||
.local_anchor1(anchor1.0.into())
|
||||
.local_anchor2(anchor2.0.into())
|
||||
.into(),
|
||||
))
|
||||
}
|
||||
}
|
||||
20
thirdparty/rapier.js/src/dynamics/mod.rs
vendored
Normal file
20
thirdparty/rapier.js/src/dynamics/mod.rs
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
//! Structures related to dynamics: bodies, joints, etc.
|
||||
|
||||
pub use self::ccd_solver::*;
|
||||
pub use self::impulse_joint_set::*;
|
||||
pub use self::integration_parameters::*;
|
||||
pub use self::island_manager::*;
|
||||
pub use self::joint::*;
|
||||
pub use self::multibody_joint_set::*;
|
||||
pub use self::rigid_body_set::*;
|
||||
|
||||
mod ccd_solver;
|
||||
mod impulse_joint;
|
||||
mod impulse_joint_set;
|
||||
mod integration_parameters;
|
||||
mod island_manager;
|
||||
mod joint;
|
||||
mod multibody_joint;
|
||||
mod multibody_joint_set;
|
||||
mod rigid_body;
|
||||
mod rigid_body_set;
|
||||
196
thirdparty/rapier.js/src/dynamics/multibody_joint.rs
vendored
Normal file
196
thirdparty/rapier.js/src/dynamics/multibody_joint.rs
vendored
Normal file
@@ -0,0 +1,196 @@
|
||||
use crate::dynamics::{RawJointAxis, RawJointType, RawMultibodyJointSet};
|
||||
use crate::math::{RawRotation, RawVector};
|
||||
use crate::utils::FlatHandle;
|
||||
use rapier::dynamics::JointAxis;
|
||||
use wasm_bindgen::prelude::*;
|
||||
|
||||
#[wasm_bindgen]
|
||||
impl RawMultibodyJointSet {
|
||||
/// The type of this joint.
|
||||
pub fn jointType(&self, handle: FlatHandle) -> RawJointType {
|
||||
self.map(handle, |j| j.data.locked_axes.into())
|
||||
}
|
||||
|
||||
// /// The unique integer identifier of the first rigid-body this joint it attached to.
|
||||
// pub fn jointBodyHandle1(&self, handle: FlatHandle) -> u32 {
|
||||
// self.map(handle, |j| j.body1.into_raw_parts().0)
|
||||
// }
|
||||
//
|
||||
// /// The unique integer identifier of the second rigid-body this joint is attached to.
|
||||
// pub fn jointBodyHandle2(&self, handle: FlatHandle) -> u32 {
|
||||
// self.map(handle, |j| j.body2.into_raw_parts().0)
|
||||
// }
|
||||
|
||||
/// The angular part of the joint’s local frame relative to the first rigid-body it is attached to.
|
||||
pub fn jointFrameX1(&self, handle: FlatHandle) -> RawRotation {
|
||||
self.map(handle, |j| j.data.local_frame1.rotation.into())
|
||||
}
|
||||
|
||||
/// The angular part of the joint’s local frame relative to the second rigid-body it is attached to.
|
||||
pub fn jointFrameX2(&self, handle: FlatHandle) -> RawRotation {
|
||||
self.map(handle, |j| j.data.local_frame2.rotation.into())
|
||||
}
|
||||
|
||||
/// The position of the first anchor of this joint.
|
||||
///
|
||||
/// The first anchor gives the position of the points application point on the
|
||||
/// local frame of the first rigid-body it is attached to.
|
||||
pub fn jointAnchor1(&self, handle: FlatHandle) -> RawVector {
|
||||
self.map(handle, |j| j.data.local_frame1.translation.vector.into())
|
||||
}
|
||||
|
||||
/// The position of the second anchor of this joint.
|
||||
///
|
||||
/// The second anchor gives the position of the points application point on the
|
||||
/// local frame of the second rigid-body it is attached to.
|
||||
pub fn jointAnchor2(&self, handle: FlatHandle) -> RawVector {
|
||||
self.map(handle, |j| j.data.local_frame2.translation.vector.into())
|
||||
}
|
||||
|
||||
/// Are contacts between the rigid-bodies attached by this joint enabled?
|
||||
pub fn jointContactsEnabled(&self, handle: FlatHandle) -> bool {
|
||||
self.map(handle, |j| j.data.contacts_enabled)
|
||||
}
|
||||
|
||||
/// Sets whether contacts are enabled between the rigid-bodies attached by this joint.
|
||||
pub fn jointSetContactsEnabled(&mut self, handle: FlatHandle, enabled: bool) {
|
||||
self.map_mut(handle, |j| {
|
||||
j.data.contacts_enabled = enabled;
|
||||
});
|
||||
}
|
||||
|
||||
/// Are the limits for this joint enabled?
|
||||
pub fn jointLimitsEnabled(&self, handle: FlatHandle, axis: RawJointAxis) -> bool {
|
||||
self.map(handle, |j| {
|
||||
j.data.limit_axes.contains(JointAxis::from(axis).into())
|
||||
})
|
||||
}
|
||||
|
||||
/// Return the lower limit along the given joint axis.
|
||||
pub fn jointLimitsMin(&self, handle: FlatHandle, axis: RawJointAxis) -> f32 {
|
||||
self.map(handle, |j| j.data.limits[axis as usize].min)
|
||||
}
|
||||
|
||||
/// If this is a prismatic joint, returns its upper limit.
|
||||
pub fn jointLimitsMax(&self, handle: FlatHandle, axis: RawJointAxis) -> f32 {
|
||||
self.map(handle, |j| j.data.limits[axis as usize].max)
|
||||
}
|
||||
|
||||
// pub fn jointConfigureMotorModel(
|
||||
// &mut self,
|
||||
// handle: FlatHandle,
|
||||
// axis: RawJointAxis,
|
||||
// model: RawMotorModel,
|
||||
// ) {
|
||||
// self.map_mut(handle, |j| {
|
||||
// j.data.motors[axis as usize].model = model.into()
|
||||
// })
|
||||
// }
|
||||
|
||||
/*
|
||||
#[cfg(feature = "dim3")]
|
||||
pub fn jointConfigureBallMotorVelocity(
|
||||
&mut self,
|
||||
handle: FlatHandle,
|
||||
vx: f32,
|
||||
vy: f32,
|
||||
vz: f32,
|
||||
factor: f32,
|
||||
) {
|
||||
let targetVel = Vector3::new(vx, vy, vz);
|
||||
|
||||
self.map_mut(handle, |j| match &mut j.params {
|
||||
JointData::SphericalJoint(j) => j.configure_motor_velocity(targetVel, factor),
|
||||
_ => {}
|
||||
})
|
||||
}
|
||||
|
||||
#[cfg(feature = "dim3")]
|
||||
pub fn jointConfigureBallMotorPosition(
|
||||
&mut self,
|
||||
handle: FlatHandle,
|
||||
qw: f32,
|
||||
qx: f32,
|
||||
qy: f32,
|
||||
qz: f32,
|
||||
stiffness: f32,
|
||||
damping: f32,
|
||||
) {
|
||||
let quat = Quaternion::new(qw, qx, qy, qz);
|
||||
|
||||
self.map_mut(handle, |j| match &mut j.params {
|
||||
JointData::SphericalJoint(j) => {
|
||||
if let Some(unit_quat) = UnitQuaternion::try_new(quat, 1.0e-5) {
|
||||
j.configure_motor_position(unit_quat, stiffness, damping)
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
})
|
||||
}
|
||||
|
||||
#[cfg(feature = "dim3")]
|
||||
pub fn jointConfigureBallMotor(
|
||||
&mut self,
|
||||
handle: FlatHandle,
|
||||
qw: f32,
|
||||
qx: f32,
|
||||
qy: f32,
|
||||
qz: f32,
|
||||
vx: f32,
|
||||
vy: f32,
|
||||
vz: f32,
|
||||
stiffness: f32,
|
||||
damping: f32,
|
||||
) {
|
||||
let quat = Quaternion::new(qw, qx, qy, qz);
|
||||
let vel = Vector3::new(vx, vy, vz);
|
||||
|
||||
self.map_mut(handle, |j| match &mut j.params {
|
||||
JointData::SphericalJoint(j) => {
|
||||
if let Some(unit_quat) = UnitQuaternion::try_new(quat, 1.0e-5) {
|
||||
j.configure_motor(unit_quat, vel, stiffness, damping)
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
})
|
||||
}
|
||||
*/
|
||||
|
||||
// pub fn jointConfigureMotorVelocity(
|
||||
// &mut self,
|
||||
// handle: FlatHandle,
|
||||
// axis: RawJointAxis,
|
||||
// targetVel: f32,
|
||||
// factor: f32,
|
||||
// ) {
|
||||
// self.jointConfigureMotor(handle, axis, 0.0, targetVel, 0.0, factor)
|
||||
// }
|
||||
//
|
||||
// pub fn jointConfigureMotorPosition(
|
||||
// &mut self,
|
||||
// handle: FlatHandle,
|
||||
// axis: RawJointAxis,
|
||||
// targetPos: f32,
|
||||
// stiffness: f32,
|
||||
// damping: f32,
|
||||
// ) {
|
||||
// self.jointConfigureMotor(handle, axis, targetPos, 0.0, stiffness, damping)
|
||||
// }
|
||||
|
||||
// pub fn jointConfigureMotor(
|
||||
// &mut self,
|
||||
// handle: FlatHandle,
|
||||
// axis: RawJointAxis,
|
||||
// targetPos: f32,
|
||||
// targetVel: f32,
|
||||
// stiffness: f32,
|
||||
// damping: f32,
|
||||
// ) {
|
||||
// self.map_mut(handle, |j| {
|
||||
// j.data.motors[axis as usize].target_pos = targetPos;
|
||||
// j.data.motors[axis as usize].target_vel = targetVel;
|
||||
// j.data.motors[axis as usize].stiffness = stiffness;
|
||||
// j.data.motors[axis as usize].damping = damping;
|
||||
// })
|
||||
// }
|
||||
}
|
||||
85
thirdparty/rapier.js/src/dynamics/multibody_joint_set.rs
vendored
Normal file
85
thirdparty/rapier.js/src/dynamics/multibody_joint_set.rs
vendored
Normal file
@@ -0,0 +1,85 @@
|
||||
use crate::dynamics::RawGenericJoint;
|
||||
use crate::utils::{self, FlatHandle};
|
||||
use rapier::dynamics::{MultibodyJoint, MultibodyJointSet};
|
||||
use wasm_bindgen::prelude::*;
|
||||
|
||||
#[wasm_bindgen]
|
||||
pub struct RawMultibodyJointSet(pub(crate) MultibodyJointSet);
|
||||
|
||||
impl RawMultibodyJointSet {
|
||||
pub(crate) fn map<T>(&self, handle: FlatHandle, f: impl FnOnce(&MultibodyJoint) -> T) -> T {
|
||||
let (body, link_id) = self
|
||||
.0
|
||||
.get(utils::multibody_joint_handle(handle))
|
||||
.expect("Invalid Joint reference. It may have been removed from the physics World.");
|
||||
f(body.link(link_id).unwrap().joint())
|
||||
}
|
||||
|
||||
pub(crate) fn map_mut<T>(
|
||||
&mut self,
|
||||
handle: FlatHandle,
|
||||
f: impl FnOnce(&mut MultibodyJoint) -> T,
|
||||
) -> T {
|
||||
let (body, link_id) = self
|
||||
.0
|
||||
.get_mut(utils::multibody_joint_handle(handle))
|
||||
.expect("Invalid Joint reference. It may have been removed from the physics World.");
|
||||
f(&mut body.link_mut(link_id).unwrap().joint)
|
||||
}
|
||||
}
|
||||
|
||||
#[wasm_bindgen]
|
||||
impl RawMultibodyJointSet {
|
||||
#[wasm_bindgen(constructor)]
|
||||
pub fn new() -> Self {
|
||||
RawMultibodyJointSet(MultibodyJointSet::new())
|
||||
}
|
||||
|
||||
pub fn createJoint(
|
||||
&mut self,
|
||||
params: &RawGenericJoint,
|
||||
parent1: FlatHandle,
|
||||
parent2: FlatHandle,
|
||||
wakeUp: bool,
|
||||
) -> FlatHandle {
|
||||
// TODO: avoid the unwrap?
|
||||
let parent1 = utils::body_handle(parent1);
|
||||
let parent2 = utils::body_handle(parent2);
|
||||
|
||||
self.0
|
||||
.insert(parent1, parent2, params.0.clone(), wakeUp)
|
||||
.map(|h| utils::flat_handle(h.0))
|
||||
.unwrap_or(FlatHandle::MAX)
|
||||
}
|
||||
|
||||
pub fn remove(&mut self, handle: FlatHandle, wakeUp: bool) {
|
||||
let handle = utils::multibody_joint_handle(handle);
|
||||
self.0.remove(handle, wakeUp);
|
||||
}
|
||||
|
||||
pub fn contains(&self, handle: FlatHandle) -> bool {
|
||||
self.0.get(utils::multibody_joint_handle(handle)).is_some()
|
||||
}
|
||||
|
||||
/// Applies the given JavaScript function to the integer handle of each joint managed by this physics world.
|
||||
///
|
||||
/// # Parameters
|
||||
/// - `f(handle)`: the function to apply to the integer handle of each joint managed by this set. Called as `f(collider)`.
|
||||
pub fn forEachJointHandle(&self, f: &js_sys::Function) {
|
||||
let this = JsValue::null();
|
||||
for (handle, _, _, _) in self.0.iter() {
|
||||
let _ = f.call1(&this, &JsValue::from(utils::flat_handle(handle.0)));
|
||||
}
|
||||
}
|
||||
|
||||
/// Applies the given JavaScript function to the integer handle of each joint attached to the given rigid-body.
|
||||
///
|
||||
/// # Parameters
|
||||
/// - `f(handle)`: the function to apply to the integer handle of each joint attached to the rigid-body. Called as `f(collider)`.
|
||||
pub fn forEachJointAttachedToRigidBody(&self, body: FlatHandle, f: &js_sys::Function) {
|
||||
let this = JsValue::null();
|
||||
for (_, _, handle) in self.0.attached_joints(utils::body_handle(body)) {
|
||||
let _ = f.call1(&this, &JsValue::from(utils::flat_handle(handle.0)));
|
||||
}
|
||||
}
|
||||
}
|
||||
753
thirdparty/rapier.js/src/dynamics/rigid_body.rs
vendored
Normal file
753
thirdparty/rapier.js/src/dynamics/rigid_body.rs
vendored
Normal file
@@ -0,0 +1,753 @@
|
||||
use crate::dynamics::{RawRigidBodySet, RawRigidBodyType};
|
||||
use crate::geometry::RawColliderSet;
|
||||
#[cfg(feature = "dim3")]
|
||||
use crate::math::RawSdpMatrix3;
|
||||
use crate::math::{RawRotation, RawVector};
|
||||
use crate::utils::{self, FlatHandle};
|
||||
use na::Point;
|
||||
use rapier::dynamics::MassProperties;
|
||||
use wasm_bindgen::prelude::*;
|
||||
|
||||
#[wasm_bindgen]
|
||||
impl RawRigidBodySet {
|
||||
/// The world-space translation of this rigid-body.
|
||||
pub fn rbTranslation(&self, handle: FlatHandle) -> RawVector {
|
||||
self.map(handle, |rb| RawVector(rb.position().translation.vector))
|
||||
}
|
||||
|
||||
/// The world-space orientation of this rigid-body.
|
||||
pub fn rbRotation(&self, handle: FlatHandle) -> RawRotation {
|
||||
self.map(handle, |rb| RawRotation(rb.position().rotation))
|
||||
}
|
||||
|
||||
/// Put the given rigid-body to sleep.
|
||||
pub fn rbSleep(&mut self, handle: FlatHandle) {
|
||||
self.map_mut(handle, |rb| rb.sleep());
|
||||
}
|
||||
|
||||
/// Is this rigid-body sleeping?
|
||||
pub fn rbIsSleeping(&self, handle: FlatHandle) -> bool {
|
||||
self.map(handle, |rb| rb.is_sleeping())
|
||||
}
|
||||
|
||||
/// Is the velocity of this rigid-body not zero?
|
||||
pub fn rbIsMoving(&self, handle: FlatHandle) -> bool {
|
||||
self.map(handle, |rb| rb.is_moving())
|
||||
}
|
||||
|
||||
/// The world-space predicted translation of this rigid-body.
|
||||
///
|
||||
/// If this rigid-body is kinematic this value is set by the `setNextKinematicTranslation`
|
||||
/// method and is used for estimating the kinematic body velocity at the next timestep.
|
||||
/// For non-kinematic bodies, this value is currently unspecified.
|
||||
pub fn rbNextTranslation(&self, handle: FlatHandle) -> RawVector {
|
||||
self.map(handle, |rb| {
|
||||
RawVector(rb.next_position().translation.vector)
|
||||
})
|
||||
}
|
||||
|
||||
/// The world-space predicted orientation of this rigid-body.
|
||||
///
|
||||
/// If this rigid-body is kinematic this value is set by the `setNextKinematicRotation`
|
||||
/// method and is used for estimating the kinematic body velocity at the next timestep.
|
||||
/// For non-kinematic bodies, this value is currently unspecified.
|
||||
pub fn rbNextRotation(&self, handle: FlatHandle) -> RawRotation {
|
||||
self.map(handle, |rb| RawRotation(rb.next_position().rotation))
|
||||
}
|
||||
|
||||
/// Sets the translation of this rigid-body.
|
||||
///
|
||||
/// # Parameters
|
||||
/// - `x`: the world-space position of the rigid-body along the `x` axis.
|
||||
/// - `y`: the world-space position of the rigid-body along the `y` axis.
|
||||
/// - `z`: the world-space position of the rigid-body along the `z` axis.
|
||||
/// - `wakeUp`: forces the rigid-body to wake-up so it is properly affected by forces if it
|
||||
/// wasn't moving before modifying its position.
|
||||
#[cfg(feature = "dim3")]
|
||||
pub fn rbSetTranslation(&mut self, handle: FlatHandle, x: f32, y: f32, z: f32, wakeUp: bool) {
|
||||
self.map_mut(handle, |rb| {
|
||||
rb.set_translation(na::Vector3::new(x, y, z), wakeUp);
|
||||
})
|
||||
}
|
||||
|
||||
/// Sets the translation of this rigid-body.
|
||||
///
|
||||
/// # Parameters
|
||||
/// - `x`: the world-space position of the rigid-body along the `x` axis.
|
||||
/// - `y`: the world-space position of the rigid-body along the `y` axis.
|
||||
/// - `wakeUp`: forces the rigid-body to wake-up so it is properly affected by forces if it
|
||||
/// wasn't moving before modifying its position.
|
||||
#[cfg(feature = "dim2")]
|
||||
pub fn rbSetTranslation(&mut self, handle: FlatHandle, x: f32, y: f32, wakeUp: bool) {
|
||||
self.map_mut(handle, |rb| {
|
||||
rb.set_translation(na::Vector2::new(x, y), wakeUp);
|
||||
})
|
||||
}
|
||||
|
||||
/// Sets the rotation quaternion of this rigid-body.
|
||||
///
|
||||
/// 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 rigid-body to wake-up so it is properly affected by forces if it
|
||||
/// wasn't moving before modifying its position.
|
||||
#[cfg(feature = "dim3")]
|
||||
pub fn rbSetRotation(
|
||||
&mut self,
|
||||
handle: FlatHandle,
|
||||
x: f32,
|
||||
y: f32,
|
||||
z: f32,
|
||||
w: f32,
|
||||
wakeUp: bool,
|
||||
) {
|
||||
if let Some(q) = na::Unit::try_new(na::Quaternion::new(w, x, y, z), 0.0) {
|
||||
self.map_mut(handle, |rb| rb.set_rotation(q, wakeUp))
|
||||
}
|
||||
}
|
||||
|
||||
/// Sets the rotation angle of this rigid-body.
|
||||
///
|
||||
/// # Parameters
|
||||
/// - `angle`: the rotation angle, in radians.
|
||||
/// - `wakeUp`: forces the rigid-body to wake-up so it is properly affected by forces if it
|
||||
/// wasn't moving before modifying its position.
|
||||
#[cfg(feature = "dim2")]
|
||||
pub fn rbSetRotation(&mut self, handle: FlatHandle, angle: f32, wakeUp: bool) {
|
||||
self.map_mut(handle, |rb| {
|
||||
rb.set_rotation(na::UnitComplex::new(angle), wakeUp)
|
||||
})
|
||||
}
|
||||
|
||||
/// Sets the linear velocity of this rigid-body.
|
||||
pub fn rbSetLinvel(&mut self, handle: FlatHandle, linvel: &RawVector, wakeUp: bool) {
|
||||
self.map_mut(handle, |rb| {
|
||||
rb.set_linvel(linvel.0, wakeUp);
|
||||
});
|
||||
}
|
||||
|
||||
/// Sets the angular velocity of this rigid-body.
|
||||
#[cfg(feature = "dim2")]
|
||||
pub fn rbSetAngvel(&mut self, handle: FlatHandle, angvel: f32, wakeUp: bool) {
|
||||
self.map_mut(handle, |rb| {
|
||||
rb.set_angvel(angvel, wakeUp);
|
||||
});
|
||||
}
|
||||
|
||||
/// Sets the angular velocity of this rigid-body.
|
||||
#[cfg(feature = "dim3")]
|
||||
pub fn rbSetAngvel(&mut self, handle: FlatHandle, angvel: &RawVector, wakeUp: bool) {
|
||||
self.map_mut(handle, |rb| {
|
||||
rb.set_angvel(angvel.0, wakeUp);
|
||||
});
|
||||
}
|
||||
|
||||
/// If this rigid body is kinematic, sets its future translation after the next timestep integration.
|
||||
///
|
||||
/// This should be used instead of `rigidBody.setTranslation` to make the dynamic object
|
||||
/// interacting with this kinematic body behave as expected. Internally, Rapier will compute
|
||||
/// an artificial velocity for this rigid-body from its current position and its next kinematic
|
||||
/// position. This velocity will be used to compute forces on dynamic bodies interacting with
|
||||
/// this body.
|
||||
///
|
||||
/// # Parameters
|
||||
/// - `x`: the world-space position of the rigid-body along the `x` axis.
|
||||
/// - `y`: the world-space position of the rigid-body along the `y` axis.
|
||||
/// - `z`: the world-space position of the rigid-body along the `z` axis.
|
||||
#[cfg(feature = "dim3")]
|
||||
pub fn rbSetNextKinematicTranslation(&mut self, handle: FlatHandle, x: f32, y: f32, z: f32) {
|
||||
self.map_mut(handle, |rb| {
|
||||
rb.set_next_kinematic_translation(na::Vector3::new(x, y, z));
|
||||
})
|
||||
}
|
||||
|
||||
/// If this rigid body is kinematic, sets its future translation after the next timestep integration.
|
||||
///
|
||||
/// This should be used instead of `rigidBody.setTranslation` to make the dynamic object
|
||||
/// interacting with this kinematic body behave as expected. Internally, Rapier will compute
|
||||
/// an artificial velocity for this rigid-body from its current position and its next kinematic
|
||||
/// position. This velocity will be used to compute forces on dynamic bodies interacting with
|
||||
/// this body.
|
||||
///
|
||||
/// # Parameters
|
||||
/// - `x`: the world-space position of the rigid-body along the `x` axis.
|
||||
/// - `y`: the world-space position of the rigid-body along the `y` axis.
|
||||
#[cfg(feature = "dim2")]
|
||||
pub fn rbSetNextKinematicTranslation(&mut self, handle: FlatHandle, x: f32, y: f32) {
|
||||
self.map_mut(handle, |rb| {
|
||||
rb.set_next_kinematic_translation(na::Vector2::new(x, y));
|
||||
})
|
||||
}
|
||||
|
||||
/// If this rigid body is kinematic, sets its future rotation after the next timestep integration.
|
||||
///
|
||||
/// This should be used instead of `rigidBody.setRotation` to make the dynamic object
|
||||
/// interacting with this kinematic body behave as expected. Internally, Rapier will compute
|
||||
/// an artificial velocity for this rigid-body from its current position and its next kinematic
|
||||
/// position. This velocity will be used to compute forces on dynamic bodies interacting with
|
||||
/// this body.
|
||||
///
|
||||
/// # 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.
|
||||
#[cfg(feature = "dim3")]
|
||||
pub fn rbSetNextKinematicRotation(
|
||||
&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, |rb| {
|
||||
rb.set_next_kinematic_rotation(q);
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/// If this rigid body is kinematic, sets its future rotation after the next timestep integration.
|
||||
///
|
||||
/// This should be used instead of `rigidBody.setRotation` to make the dynamic object
|
||||
/// interacting with this kinematic body behave as expected. Internally, Rapier will compute
|
||||
/// an artificial velocity for this rigid-body from its current position and its next kinematic
|
||||
/// position. This velocity will be used to compute forces on dynamic bodies interacting with
|
||||
/// this body.
|
||||
///
|
||||
/// # Parameters
|
||||
/// - `angle`: the rotation angle, in radians.
|
||||
#[cfg(feature = "dim2")]
|
||||
pub fn rbSetNextKinematicRotation(&mut self, handle: FlatHandle, angle: f32) {
|
||||
self.map_mut(handle, |rb| {
|
||||
rb.set_next_kinematic_rotation(na::UnitComplex::new(angle));
|
||||
})
|
||||
}
|
||||
|
||||
pub fn rbRecomputeMassPropertiesFromColliders(
|
||||
&mut self,
|
||||
handle: FlatHandle,
|
||||
colliders: &RawColliderSet,
|
||||
) {
|
||||
self.map_mut(handle, |rb| {
|
||||
rb.recompute_mass_properties_from_colliders(&colliders.0)
|
||||
})
|
||||
}
|
||||
|
||||
pub fn rbSetAdditionalMass(&mut self, handle: FlatHandle, mass: f32, wake_up: bool) {
|
||||
self.map_mut(handle, |rb| {
|
||||
rb.set_additional_mass(mass, wake_up);
|
||||
})
|
||||
}
|
||||
|
||||
#[cfg(feature = "dim3")]
|
||||
pub fn rbSetAdditionalMassProperties(
|
||||
&mut self,
|
||||
handle: FlatHandle,
|
||||
mass: f32,
|
||||
centerOfMass: &RawVector,
|
||||
principalAngularInertia: &RawVector,
|
||||
angularInertiaFrame: &RawRotation,
|
||||
wake_up: bool,
|
||||
) {
|
||||
self.map_mut(handle, |rb| {
|
||||
let mprops = MassProperties::with_principal_inertia_frame(
|
||||
centerOfMass.0.into(),
|
||||
mass,
|
||||
principalAngularInertia.0,
|
||||
angularInertiaFrame.0,
|
||||
);
|
||||
rb.set_additional_mass_properties(mprops, wake_up)
|
||||
})
|
||||
}
|
||||
|
||||
#[cfg(feature = "dim2")]
|
||||
pub fn rbSetAdditionalMassProperties(
|
||||
&mut self,
|
||||
handle: FlatHandle,
|
||||
mass: f32,
|
||||
centerOfMass: &RawVector,
|
||||
principalAngularInertia: f32,
|
||||
wake_up: bool,
|
||||
) {
|
||||
self.map_mut(handle, |rb| {
|
||||
let props = MassProperties::new(centerOfMass.0.into(), mass, principalAngularInertia);
|
||||
rb.set_additional_mass_properties(props, wake_up)
|
||||
})
|
||||
}
|
||||
|
||||
/// The linear velocity of this rigid-body.
|
||||
pub fn rbLinvel(&self, handle: FlatHandle) -> RawVector {
|
||||
self.map(handle, |rb| RawVector(*rb.linvel()))
|
||||
}
|
||||
|
||||
/// The angular velocity of this rigid-body.
|
||||
#[cfg(feature = "dim2")]
|
||||
pub fn rbAngvel(&self, handle: FlatHandle) -> f32 {
|
||||
self.map(handle, |rb| rb.angvel())
|
||||
}
|
||||
|
||||
/// The angular velocity of this rigid-body.
|
||||
#[cfg(feature = "dim3")]
|
||||
pub fn rbAngvel(&self, handle: FlatHandle) -> RawVector {
|
||||
self.map(handle, |rb| RawVector(*rb.angvel()))
|
||||
}
|
||||
|
||||
/// The velocity of the given world-space point on this rigid-body.
|
||||
pub fn rbVelocityAtPoint(&self, handle: FlatHandle, point: &RawVector) -> RawVector {
|
||||
self.map(handle, |rb| {
|
||||
rb.velocity_at_point(&Point::from(point.0)).into()
|
||||
})
|
||||
}
|
||||
|
||||
pub fn rbLockTranslations(&mut self, handle: FlatHandle, locked: bool, wake_up: bool) {
|
||||
self.map_mut(handle, |rb| rb.lock_translations(locked, wake_up))
|
||||
}
|
||||
|
||||
#[cfg(feature = "dim2")]
|
||||
pub fn rbSetEnabledTranslations(
|
||||
&mut self,
|
||||
handle: FlatHandle,
|
||||
allow_x: bool,
|
||||
allow_y: bool,
|
||||
wake_up: bool,
|
||||
) {
|
||||
self.map_mut(handle, |rb| {
|
||||
rb.set_enabled_translations(allow_x, allow_y, wake_up)
|
||||
})
|
||||
}
|
||||
|
||||
#[cfg(feature = "dim3")]
|
||||
pub fn rbSetEnabledTranslations(
|
||||
&mut self,
|
||||
handle: FlatHandle,
|
||||
allow_x: bool,
|
||||
allow_y: bool,
|
||||
allow_z: bool,
|
||||
wake_up: bool,
|
||||
) {
|
||||
self.map_mut(handle, |rb| {
|
||||
rb.set_enabled_translations(allow_x, allow_y, allow_z, wake_up)
|
||||
})
|
||||
}
|
||||
|
||||
pub fn rbLockRotations(&mut self, handle: FlatHandle, locked: bool, wake_up: bool) {
|
||||
self.map_mut(handle, |rb| rb.lock_rotations(locked, wake_up))
|
||||
}
|
||||
|
||||
#[cfg(feature = "dim3")]
|
||||
pub fn rbSetEnabledRotations(
|
||||
&mut self,
|
||||
handle: FlatHandle,
|
||||
allow_x: bool,
|
||||
allow_y: bool,
|
||||
allow_z: bool,
|
||||
wake_up: bool,
|
||||
) {
|
||||
self.map_mut(handle, |rb| {
|
||||
rb.set_enabled_rotations(allow_x, allow_y, allow_z, wake_up)
|
||||
})
|
||||
}
|
||||
|
||||
pub fn rbDominanceGroup(&self, handle: FlatHandle) -> i8 {
|
||||
self.map(handle, |rb| rb.dominance_group())
|
||||
}
|
||||
|
||||
pub fn rbSetDominanceGroup(&mut self, handle: FlatHandle, group: i8) {
|
||||
self.map_mut(handle, |rb| rb.set_dominance_group(group))
|
||||
}
|
||||
|
||||
pub fn rbEnableCcd(&mut self, handle: FlatHandle, enabled: bool) {
|
||||
self.map_mut(handle, |rb| rb.enable_ccd(enabled))
|
||||
}
|
||||
|
||||
pub fn rbSetSoftCcdPrediction(&mut self, handle: FlatHandle, prediction: f32) {
|
||||
self.map_mut(handle, |rb| rb.set_soft_ccd_prediction(prediction))
|
||||
}
|
||||
|
||||
/// The mass of this rigid-body.
|
||||
pub fn rbMass(&self, handle: FlatHandle) -> f32 {
|
||||
self.map(handle, |rb| rb.mass())
|
||||
}
|
||||
|
||||
/// The inverse of the mass of a rigid-body.
|
||||
///
|
||||
/// If this is zero, the rigid-body is assumed to have infinite mass.
|
||||
pub fn rbInvMass(&self, handle: FlatHandle) -> f32 {
|
||||
self.map(handle, |rb| rb.mass_properties().local_mprops.inv_mass)
|
||||
}
|
||||
|
||||
/// The inverse mass taking into account translation locking.
|
||||
pub fn rbEffectiveInvMass(&self, handle: FlatHandle) -> RawVector {
|
||||
self.map(handle, |rb| rb.mass_properties().effective_inv_mass.into())
|
||||
}
|
||||
|
||||
/// The center of mass of a rigid-body expressed in its local-space.
|
||||
pub fn rbLocalCom(&self, handle: FlatHandle) -> RawVector {
|
||||
self.map(handle, |rb| {
|
||||
rb.mass_properties().local_mprops.local_com.into()
|
||||
})
|
||||
}
|
||||
|
||||
/// The world-space center of mass of the rigid-body.
|
||||
pub fn rbWorldCom(&self, handle: FlatHandle) -> RawVector {
|
||||
self.map(handle, |rb| rb.mass_properties().world_com.into())
|
||||
}
|
||||
|
||||
/// The inverse of the principal angular inertia of the rigid-body.
|
||||
///
|
||||
/// Components set to zero are assumed to be infinite along the corresponding principal axis.
|
||||
#[cfg(feature = "dim2")]
|
||||
pub fn rbInvPrincipalInertia(&self, handle: FlatHandle) -> f32 {
|
||||
self.map(handle, |rb| {
|
||||
rb.mass_properties()
|
||||
.local_mprops
|
||||
.inv_principal_inertia
|
||||
.into()
|
||||
})
|
||||
}
|
||||
|
||||
/// The inverse of the principal angular inertia of the rigid-body.
|
||||
///
|
||||
/// Components set to zero are assumed to be infinite along the corresponding principal axis.
|
||||
#[cfg(feature = "dim3")]
|
||||
pub fn rbInvPrincipalInertia(&self, handle: FlatHandle) -> RawVector {
|
||||
self.map(handle, |rb| {
|
||||
rb.mass_properties()
|
||||
.local_mprops
|
||||
.inv_principal_inertia
|
||||
.into()
|
||||
})
|
||||
}
|
||||
|
||||
#[cfg(feature = "dim3")]
|
||||
/// The principal vectors of the local angular inertia tensor of the rigid-body.
|
||||
pub fn rbPrincipalInertiaLocalFrame(&self, handle: FlatHandle) -> RawRotation {
|
||||
self.map(handle, |rb| {
|
||||
RawRotation::from(
|
||||
rb.mass_properties()
|
||||
.local_mprops
|
||||
.principal_inertia_local_frame,
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
/// The angular inertia along the principal inertia axes of the rigid-body.
|
||||
#[cfg(feature = "dim2")]
|
||||
pub fn rbPrincipalInertia(&self, handle: FlatHandle) -> f32 {
|
||||
self.map(handle, |rb| {
|
||||
rb.mass_properties().local_mprops.principal_inertia().into()
|
||||
})
|
||||
}
|
||||
|
||||
/// The angular inertia along the principal inertia axes of the rigid-body.
|
||||
#[cfg(feature = "dim3")]
|
||||
pub fn rbPrincipalInertia(&self, handle: FlatHandle) -> RawVector {
|
||||
self.map(handle, |rb| {
|
||||
rb.mass_properties().local_mprops.principal_inertia().into()
|
||||
})
|
||||
}
|
||||
|
||||
/// The world-space inverse angular inertia tensor of the rigid-body,
|
||||
/// taking into account rotation locking.
|
||||
#[cfg(feature = "dim2")]
|
||||
pub fn rbEffectiveWorldInvInertia(&self, handle: FlatHandle) -> f32 {
|
||||
self.map(handle, |rb| {
|
||||
rb.mass_properties().effective_world_inv_inertia.into()
|
||||
})
|
||||
}
|
||||
|
||||
/// The world-space inverse angular inertia tensor of the rigid-body,
|
||||
/// taking into account rotation locking.
|
||||
#[cfg(feature = "dim3")]
|
||||
pub fn rbEffectiveWorldInvInertia(&self, handle: FlatHandle) -> RawSdpMatrix3 {
|
||||
self.map(handle, |rb| {
|
||||
rb.mass_properties().effective_world_inv_inertia.into()
|
||||
})
|
||||
}
|
||||
|
||||
/// The effective world-space angular inertia (that takes the potential rotation locking into account) of
|
||||
/// this rigid-body.
|
||||
#[cfg(feature = "dim2")]
|
||||
pub fn rbEffectiveAngularInertia(&self, handle: FlatHandle) -> f32 {
|
||||
self.map(handle, |rb| {
|
||||
rb.mass_properties().effective_angular_inertia().into()
|
||||
})
|
||||
}
|
||||
|
||||
/// The effective world-space angular inertia (that takes the potential rotation locking into account) of
|
||||
/// this rigid-body.
|
||||
#[cfg(feature = "dim3")]
|
||||
pub fn rbEffectiveAngularInertia(&self, handle: FlatHandle) -> RawSdpMatrix3 {
|
||||
self.map(handle, |rb| {
|
||||
rb.mass_properties().effective_angular_inertia().into()
|
||||
})
|
||||
}
|
||||
|
||||
/// Wakes this rigid-body up.
|
||||
///
|
||||
/// A dynamic rigid-body that does not move during several consecutive frames will
|
||||
/// be put to sleep by the physics engine, i.e., it will stop being simulated in order
|
||||
/// to avoid useless computations.
|
||||
/// This method forces a sleeping rigid-body to wake-up. This is useful, e.g., before modifying
|
||||
/// the position of a dynamic body so that it is properly simulated afterwards.
|
||||
pub fn rbWakeUp(&mut self, handle: FlatHandle) {
|
||||
self.map_mut(handle, |rb| rb.wake_up(true))
|
||||
}
|
||||
|
||||
/// Is Continuous Collision Detection enabled for this rigid-body?
|
||||
pub fn rbIsCcdEnabled(&self, handle: FlatHandle) -> bool {
|
||||
self.map(handle, |rb| rb.is_ccd_enabled())
|
||||
}
|
||||
pub fn rbSoftCcdPrediction(&self, handle: FlatHandle) -> f32 {
|
||||
self.map(handle, |rb| rb.soft_ccd_prediction())
|
||||
}
|
||||
|
||||
/// The number of colliders attached to this rigid-body.
|
||||
pub fn rbNumColliders(&self, handle: FlatHandle) -> usize {
|
||||
self.map(handle, |rb| rb.colliders().len())
|
||||
}
|
||||
|
||||
/// Retrieves the `i-th` collider attached to this rigid-body.
|
||||
///
|
||||
/// # Parameters
|
||||
/// - `at`: The index of the collider to retrieve. Must be a number in `[0, this.numColliders()[`.
|
||||
/// This index is **not** the same as the unique identifier of the collider.
|
||||
pub fn rbCollider(&self, handle: FlatHandle, at: usize) -> FlatHandle {
|
||||
self.map(handle, |rb| utils::flat_handle(rb.colliders()[at].0))
|
||||
}
|
||||
|
||||
/// The status of this rigid-body: fixed, dynamic, or kinematic.
|
||||
pub fn rbBodyType(&self, handle: FlatHandle) -> RawRigidBodyType {
|
||||
self.map(handle, |rb| rb.body_type().into())
|
||||
}
|
||||
|
||||
/// Set a new status for this rigid-body: fixed, dynamic, or kinematic.
|
||||
pub fn rbSetBodyType(&mut self, handle: FlatHandle, status: RawRigidBodyType, wake_up: bool) {
|
||||
self.map_mut(handle, |rb| rb.set_body_type(status.into(), wake_up));
|
||||
}
|
||||
|
||||
/// Is this rigid-body fixed?
|
||||
pub fn rbIsFixed(&self, handle: FlatHandle) -> bool {
|
||||
self.map(handle, |rb| rb.is_fixed())
|
||||
}
|
||||
|
||||
/// Is this rigid-body kinematic?
|
||||
pub fn rbIsKinematic(&self, handle: FlatHandle) -> bool {
|
||||
self.map(handle, |rb| rb.is_kinematic())
|
||||
}
|
||||
|
||||
/// Is this rigid-body dynamic?
|
||||
pub fn rbIsDynamic(&self, handle: FlatHandle) -> bool {
|
||||
self.map(handle, |rb| rb.is_dynamic())
|
||||
}
|
||||
|
||||
/// The linear damping coefficient of this rigid-body.
|
||||
pub fn rbLinearDamping(&self, handle: FlatHandle) -> f32 {
|
||||
self.map(handle, |rb| rb.linear_damping())
|
||||
}
|
||||
|
||||
/// The angular damping coefficient of this rigid-body.
|
||||
pub fn rbAngularDamping(&self, handle: FlatHandle) -> f32 {
|
||||
self.map(handle, |rb| rb.angular_damping())
|
||||
}
|
||||
|
||||
pub fn rbSetLinearDamping(&mut self, handle: FlatHandle, factor: f32) {
|
||||
self.map_mut(handle, |rb| rb.set_linear_damping(factor));
|
||||
}
|
||||
|
||||
pub fn rbSetAngularDamping(&mut self, handle: FlatHandle, factor: f32) {
|
||||
self.map_mut(handle, |rb| rb.set_angular_damping(factor));
|
||||
}
|
||||
|
||||
pub fn rbSetEnabled(&mut self, handle: FlatHandle, enabled: bool) {
|
||||
self.map_mut(handle, |rb| rb.set_enabled(enabled))
|
||||
}
|
||||
|
||||
pub fn rbIsEnabled(&self, handle: FlatHandle) -> bool {
|
||||
self.map(handle, |rb| rb.is_enabled())
|
||||
}
|
||||
|
||||
pub fn rbGravityScale(&self, handle: FlatHandle) -> f32 {
|
||||
self.map(handle, |rb| rb.gravity_scale())
|
||||
}
|
||||
|
||||
pub fn rbSetGravityScale(&mut self, handle: FlatHandle, factor: f32, wakeUp: bool) {
|
||||
self.map_mut(handle, |rb| rb.set_gravity_scale(factor, wakeUp));
|
||||
}
|
||||
|
||||
/// Resets to zero all user-added forces added to this rigid-body.
|
||||
pub fn rbResetForces(&mut self, handle: FlatHandle, wakeUp: bool) {
|
||||
self.map_mut(handle, |rb| {
|
||||
rb.reset_forces(wakeUp);
|
||||
})
|
||||
}
|
||||
|
||||
/// Resets to zero all user-added torques added to this rigid-body.
|
||||
pub fn rbResetTorques(&mut self, handle: FlatHandle, wakeUp: bool) {
|
||||
self.map_mut(handle, |rb| {
|
||||
rb.reset_torques(wakeUp);
|
||||
})
|
||||
}
|
||||
|
||||
/// Adds a force at the center-of-mass of this rigid-body.
|
||||
///
|
||||
/// # Parameters
|
||||
/// - `force`: the world-space force to apply on the rigid-body.
|
||||
/// - `wakeUp`: should the rigid-body be automatically woken-up?
|
||||
pub fn rbAddForce(&mut self, handle: FlatHandle, force: &RawVector, wakeUp: bool) {
|
||||
self.map_mut(handle, |rb| {
|
||||
rb.add_force(force.0, wakeUp);
|
||||
})
|
||||
}
|
||||
|
||||
/// Applies an impulse at the center-of-mass of this rigid-body.
|
||||
///
|
||||
/// # Parameters
|
||||
/// - `impulse`: the world-space impulse to apply on the rigid-body.
|
||||
/// - `wakeUp`: should the rigid-body be automatically woken-up?
|
||||
pub fn rbApplyImpulse(&mut self, handle: FlatHandle, impulse: &RawVector, wakeUp: bool) {
|
||||
self.map_mut(handle, |rb| {
|
||||
rb.apply_impulse(impulse.0, wakeUp);
|
||||
})
|
||||
}
|
||||
|
||||
/// Adds a torque at the center-of-mass of this rigid-body.
|
||||
///
|
||||
/// # Parameters
|
||||
/// - `torque`: the torque to apply on the rigid-body.
|
||||
/// - `wakeUp`: should the rigid-body be automatically woken-up?
|
||||
#[cfg(feature = "dim2")]
|
||||
pub fn rbAddTorque(&mut self, handle: FlatHandle, torque: f32, wakeUp: bool) {
|
||||
self.map_mut(handle, |rb| {
|
||||
rb.add_torque(torque, wakeUp);
|
||||
})
|
||||
}
|
||||
|
||||
/// Adds a torque at the center-of-mass of this rigid-body.
|
||||
///
|
||||
/// # Parameters
|
||||
/// - `torque`: the world-space torque to apply on the rigid-body.
|
||||
/// - `wakeUp`: should the rigid-body be automatically woken-up?
|
||||
#[cfg(feature = "dim3")]
|
||||
pub fn rbAddTorque(&mut self, handle: FlatHandle, torque: &RawVector, wakeUp: bool) {
|
||||
self.map_mut(handle, |rb| {
|
||||
rb.add_torque(torque.0, wakeUp);
|
||||
})
|
||||
}
|
||||
|
||||
/// Applies an impulsive torque at the center-of-mass of this rigid-body.
|
||||
///
|
||||
/// # Parameters
|
||||
/// - `torque impulse`: the torque impulse to apply on the rigid-body.
|
||||
/// - `wakeUp`: should the rigid-body be automatically woken-up?
|
||||
#[cfg(feature = "dim2")]
|
||||
pub fn rbApplyTorqueImpulse(&mut self, handle: FlatHandle, torque_impulse: f32, wakeUp: bool) {
|
||||
self.map_mut(handle, |rb| {
|
||||
rb.apply_torque_impulse(torque_impulse, wakeUp);
|
||||
})
|
||||
}
|
||||
|
||||
/// Applies an impulsive torque at the center-of-mass of this rigid-body.
|
||||
///
|
||||
/// # Parameters
|
||||
/// - `torque impulse`: the world-space torque impulse to apply on the rigid-body.
|
||||
/// - `wakeUp`: should the rigid-body be automatically woken-up?
|
||||
#[cfg(feature = "dim3")]
|
||||
pub fn rbApplyTorqueImpulse(
|
||||
&mut self,
|
||||
handle: FlatHandle,
|
||||
torque_impulse: &RawVector,
|
||||
wakeUp: bool,
|
||||
) {
|
||||
self.map_mut(handle, |rb| {
|
||||
rb.apply_torque_impulse(torque_impulse.0, wakeUp);
|
||||
})
|
||||
}
|
||||
|
||||
/// Adds a force at the given world-space point of this rigid-body.
|
||||
///
|
||||
/// # Parameters
|
||||
/// - `force`: the world-space force to apply on the rigid-body.
|
||||
/// - `point`: the world-space point where the impulse is to be applied on the rigid-body.
|
||||
/// - `wakeUp`: should the rigid-body be automatically woken-up?
|
||||
pub fn rbAddForceAtPoint(
|
||||
&mut self,
|
||||
handle: FlatHandle,
|
||||
force: &RawVector,
|
||||
point: &RawVector,
|
||||
wakeUp: bool,
|
||||
) {
|
||||
self.map_mut(handle, |rb| {
|
||||
rb.add_force_at_point(force.0, point.0.into(), wakeUp);
|
||||
})
|
||||
}
|
||||
|
||||
/// Applies an impulse at the given world-space point of this rigid-body.
|
||||
///
|
||||
/// # Parameters
|
||||
/// - `impulse`: the world-space impulse to apply on the rigid-body.
|
||||
/// - `point`: the world-space point where the impulse is to be applied on the rigid-body.
|
||||
/// - `wakeUp`: should the rigid-body be automatically woken-up?
|
||||
pub fn rbApplyImpulseAtPoint(
|
||||
&mut self,
|
||||
handle: FlatHandle,
|
||||
impulse: &RawVector,
|
||||
point: &RawVector,
|
||||
wakeUp: bool,
|
||||
) {
|
||||
self.map_mut(handle, |rb| {
|
||||
rb.apply_impulse_at_point(impulse.0, point.0.into(), wakeUp);
|
||||
})
|
||||
}
|
||||
|
||||
pub fn rbAdditionalSolverIterations(&self, handle: FlatHandle) -> usize {
|
||||
self.map(handle, |rb| rb.additional_solver_iterations())
|
||||
}
|
||||
|
||||
pub fn rbSetAdditionalSolverIterations(&mut self, handle: FlatHandle, iters: usize) {
|
||||
self.map_mut(handle, |rb| {
|
||||
rb.set_additional_solver_iterations(iters as usize);
|
||||
})
|
||||
}
|
||||
|
||||
/// An arbitrary user-defined 32-bit integer
|
||||
pub fn rbUserData(&self, handle: FlatHandle) -> u32 {
|
||||
self.map(handle, |rb| rb.user_data as u32)
|
||||
}
|
||||
|
||||
/// Sets the user-defined 32-bit integer of this rigid-body.
|
||||
///
|
||||
/// # Parameters
|
||||
/// - `data`: an arbitrary user-defined 32-bit integer.
|
||||
pub fn rbSetUserData(&mut self, handle: FlatHandle, data: u32) {
|
||||
self.map_mut(handle, |rb| {
|
||||
rb.user_data = data as u128;
|
||||
})
|
||||
}
|
||||
|
||||
/// Retrieves the constant force(s) the user added to this rigid-body.
|
||||
/// Returns zero if the rigid-body is not dynamic.
|
||||
pub fn rbUserForce(&self, handle: FlatHandle) -> RawVector {
|
||||
self.map(handle, |rb| rb.user_force().into())
|
||||
}
|
||||
|
||||
/// Retrieves the constant torque(s) the user added to this rigid-body.
|
||||
/// Returns zero if the rigid-body is not dynamic.
|
||||
#[cfg(feature = "dim2")]
|
||||
pub fn rbUserTorque(&self, handle: FlatHandle) -> f32 {
|
||||
self.map(handle, |rb| rb.user_torque())
|
||||
}
|
||||
|
||||
/// Retrieves the constant torque(s) the user added to this rigid-body.
|
||||
/// Returns zero if the rigid-body is not dynamic.
|
||||
#[cfg(feature = "dim3")]
|
||||
pub fn rbUserTorque(&self, handle: FlatHandle) -> RawVector {
|
||||
self.map(handle, |rb| rb.user_torque().into())
|
||||
}
|
||||
}
|
||||
237
thirdparty/rapier.js/src/dynamics/rigid_body_set.rs
vendored
Normal file
237
thirdparty/rapier.js/src/dynamics/rigid_body_set.rs
vendored
Normal file
@@ -0,0 +1,237 @@
|
||||
use crate::dynamics::{RawImpulseJointSet, RawIslandManager, RawMultibodyJointSet};
|
||||
use crate::geometry::RawColliderSet;
|
||||
use crate::math::{RawRotation, RawVector};
|
||||
use crate::utils::{self, FlatHandle};
|
||||
use rapier::dynamics::{MassProperties, RigidBody, RigidBodyBuilder, RigidBodySet, RigidBodyType};
|
||||
use wasm_bindgen::prelude::*;
|
||||
|
||||
#[wasm_bindgen]
|
||||
pub enum RawRigidBodyType {
|
||||
Dynamic,
|
||||
Fixed,
|
||||
KinematicPositionBased,
|
||||
KinematicVelocityBased,
|
||||
}
|
||||
|
||||
impl Into<RigidBodyType> for RawRigidBodyType {
|
||||
fn into(self) -> RigidBodyType {
|
||||
match self {
|
||||
RawRigidBodyType::Dynamic => RigidBodyType::Dynamic,
|
||||
RawRigidBodyType::Fixed => RigidBodyType::Fixed,
|
||||
RawRigidBodyType::KinematicPositionBased => RigidBodyType::KinematicPositionBased,
|
||||
RawRigidBodyType::KinematicVelocityBased => RigidBodyType::KinematicVelocityBased,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Into<RawRigidBodyType> for RigidBodyType {
|
||||
fn into(self) -> RawRigidBodyType {
|
||||
match self {
|
||||
RigidBodyType::Dynamic => RawRigidBodyType::Dynamic,
|
||||
RigidBodyType::Fixed => RawRigidBodyType::Fixed,
|
||||
RigidBodyType::KinematicPositionBased => RawRigidBodyType::KinematicPositionBased,
|
||||
RigidBodyType::KinematicVelocityBased => RawRigidBodyType::KinematicVelocityBased,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[wasm_bindgen]
|
||||
pub struct RawRigidBodySet(pub(crate) RigidBodySet);
|
||||
|
||||
impl RawRigidBodySet {
|
||||
pub(crate) fn map<T>(&self, handle: FlatHandle, f: impl FnOnce(&RigidBody) -> T) -> T {
|
||||
let body = self.0.get(utils::body_handle(handle)).expect(
|
||||
"Invalid RigidBody reference. It may have been removed from the physics World.",
|
||||
);
|
||||
f(body)
|
||||
}
|
||||
|
||||
pub(crate) fn map_mut<T>(
|
||||
&mut self,
|
||||
handle: FlatHandle,
|
||||
f: impl FnOnce(&mut RigidBody) -> T,
|
||||
) -> T {
|
||||
let body = self.0.get_mut(utils::body_handle(handle)).expect(
|
||||
"Invalid RigidBody reference. It may have been removed from the physics World.",
|
||||
);
|
||||
f(body)
|
||||
}
|
||||
}
|
||||
|
||||
#[wasm_bindgen]
|
||||
impl RawRigidBodySet {
|
||||
#[wasm_bindgen(constructor)]
|
||||
pub fn new() -> Self {
|
||||
RawRigidBodySet(RigidBodySet::new())
|
||||
}
|
||||
|
||||
#[cfg(feature = "dim3")]
|
||||
pub fn createRigidBody(
|
||||
&mut self,
|
||||
enabled: bool,
|
||||
translation: &RawVector,
|
||||
rotation: &RawRotation,
|
||||
gravityScale: f32,
|
||||
mass: f32,
|
||||
massOnly: bool,
|
||||
centerOfMass: &RawVector,
|
||||
linvel: &RawVector,
|
||||
angvel: &RawVector,
|
||||
principalAngularInertia: &RawVector,
|
||||
angularInertiaFrame: &RawRotation,
|
||||
translationEnabledX: bool,
|
||||
translationEnabledY: bool,
|
||||
translationEnabledZ: bool,
|
||||
rotationEnabledX: bool,
|
||||
rotationEnabledY: bool,
|
||||
rotationEnabledZ: bool,
|
||||
linearDamping: f32,
|
||||
angularDamping: f32,
|
||||
rb_type: RawRigidBodyType,
|
||||
canSleep: bool,
|
||||
sleeping: bool,
|
||||
softCcdPrediction: f32,
|
||||
ccdEnabled: bool,
|
||||
dominanceGroup: i8,
|
||||
additional_solver_iterations: usize,
|
||||
) -> FlatHandle {
|
||||
let pos = na::Isometry3::from_parts(translation.0.into(), rotation.0);
|
||||
|
||||
let mut rigid_body = RigidBodyBuilder::new(rb_type.into())
|
||||
.enabled(enabled)
|
||||
.pose(pos)
|
||||
.gravity_scale(gravityScale)
|
||||
.enabled_translations(
|
||||
translationEnabledX,
|
||||
translationEnabledY,
|
||||
translationEnabledZ,
|
||||
)
|
||||
.enabled_rotations(rotationEnabledX, rotationEnabledY, rotationEnabledZ)
|
||||
.linvel(linvel.0)
|
||||
.angvel(angvel.0)
|
||||
.linear_damping(linearDamping)
|
||||
.angular_damping(angularDamping)
|
||||
.can_sleep(canSleep)
|
||||
.sleeping(sleeping)
|
||||
.ccd_enabled(ccdEnabled)
|
||||
.dominance_group(dominanceGroup)
|
||||
.additional_solver_iterations(additional_solver_iterations)
|
||||
.soft_ccd_prediction(softCcdPrediction);
|
||||
|
||||
rigid_body = if massOnly {
|
||||
rigid_body.additional_mass(mass)
|
||||
} else {
|
||||
let props = MassProperties::with_principal_inertia_frame(
|
||||
centerOfMass.0.into(),
|
||||
mass,
|
||||
principalAngularInertia.0,
|
||||
angularInertiaFrame.0,
|
||||
);
|
||||
rigid_body.additional_mass_properties(props)
|
||||
};
|
||||
|
||||
utils::flat_handle(self.0.insert(rigid_body.build()).0)
|
||||
}
|
||||
|
||||
#[cfg(feature = "dim2")]
|
||||
pub fn createRigidBody(
|
||||
&mut self,
|
||||
enabled: bool,
|
||||
translation: &RawVector,
|
||||
rotation: &RawRotation,
|
||||
gravityScale: f32,
|
||||
mass: f32,
|
||||
massOnly: bool,
|
||||
centerOfMass: &RawVector,
|
||||
linvel: &RawVector,
|
||||
angvel: f32,
|
||||
principalAngularInertia: f32,
|
||||
translationEnabledX: bool,
|
||||
translationEnabledY: bool,
|
||||
rotationsEnabled: bool,
|
||||
linearDamping: f32,
|
||||
angularDamping: f32,
|
||||
rb_type: RawRigidBodyType,
|
||||
canSleep: bool,
|
||||
sleeping: bool,
|
||||
softCcdPrediciton: f32,
|
||||
ccdEnabled: bool,
|
||||
dominanceGroup: i8,
|
||||
additional_solver_iterations: usize,
|
||||
) -> FlatHandle {
|
||||
let pos = na::Isometry2::from_parts(translation.0.into(), rotation.0);
|
||||
let mut rigid_body = RigidBodyBuilder::new(rb_type.into())
|
||||
.enabled(enabled)
|
||||
.pose(pos)
|
||||
.gravity_scale(gravityScale)
|
||||
.enabled_translations(translationEnabledX, translationEnabledY)
|
||||
.linvel(linvel.0)
|
||||
.angvel(angvel)
|
||||
.linear_damping(linearDamping)
|
||||
.angular_damping(angularDamping)
|
||||
.can_sleep(canSleep)
|
||||
.sleeping(sleeping)
|
||||
.ccd_enabled(ccdEnabled)
|
||||
.dominance_group(dominanceGroup)
|
||||
.additional_solver_iterations(additional_solver_iterations)
|
||||
.soft_ccd_prediction(softCcdPrediciton);
|
||||
|
||||
rigid_body = if massOnly {
|
||||
rigid_body.additional_mass(mass)
|
||||
} else {
|
||||
let props = MassProperties::new(centerOfMass.0.into(), mass, principalAngularInertia);
|
||||
rigid_body.additional_mass_properties(props)
|
||||
};
|
||||
|
||||
if !rotationsEnabled {
|
||||
rigid_body = rigid_body.lock_rotations();
|
||||
}
|
||||
|
||||
utils::flat_handle(self.0.insert(rigid_body.build()).0)
|
||||
}
|
||||
|
||||
pub fn remove(
|
||||
&mut self,
|
||||
handle: FlatHandle,
|
||||
islands: &mut RawIslandManager,
|
||||
colliders: &mut RawColliderSet,
|
||||
joints: &mut RawImpulseJointSet,
|
||||
articulations: &mut RawMultibodyJointSet,
|
||||
) {
|
||||
let handle = utils::body_handle(handle);
|
||||
self.0.remove(
|
||||
handle,
|
||||
&mut islands.0,
|
||||
&mut colliders.0,
|
||||
&mut joints.0,
|
||||
&mut articulations.0,
|
||||
true,
|
||||
);
|
||||
}
|
||||
|
||||
/// The number of rigid-bodies on this set.
|
||||
pub fn len(&self) -> usize {
|
||||
self.0.len()
|
||||
}
|
||||
|
||||
/// Checks if a rigid-body with the given integer handle exists.
|
||||
pub fn contains(&self, handle: FlatHandle) -> bool {
|
||||
self.0.get(utils::body_handle(handle)).is_some()
|
||||
}
|
||||
|
||||
/// Applies the given JavaScript function to the integer handle of each rigid-body managed by this set.
|
||||
///
|
||||
/// # Parameters
|
||||
/// - `f(handle)`: the function to apply to the integer handle of each rigid-body managed by this set. Called as `f(collider)`.
|
||||
pub fn forEachRigidBodyHandle(&self, f: &js_sys::Function) {
|
||||
let this = JsValue::null();
|
||||
for (handle, _) in self.0.iter() {
|
||||
let _ = f.call1(&this, &JsValue::from(utils::flat_handle(handle.0)));
|
||||
}
|
||||
}
|
||||
|
||||
pub fn propagateModifiedBodyPositionsToColliders(&mut self, colliders: &mut RawColliderSet) {
|
||||
self.0
|
||||
.propagate_modified_body_positions_to_colliders(&mut colliders.0);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user