@babylonjs/core
Version:
Getting started? Play directly with the Babylon.js API using our [playground](https://playground.babylonjs.com/). It also contains a lot of samples to learn how to use it.
988 lines • 35.7 kB
JavaScript
import { Logger } from "../../Misc/logger.js";
import { BuildArray } from "../../Misc/arrayTools.js";
import { Vector3, Quaternion } from "../../Maths/math.vector.js";
import { AbstractMesh } from "../../Meshes/abstractMesh.js";
import { Mesh } from "../../Meshes/mesh.js";
import { PhysicsJoint } from "./physicsJoint.js";
Mesh._PhysicsImpostorParser = function (scene, physicObject, jsonObject) {
return new PhysicsImpostor(physicObject, jsonObject.physicsImpostor, {
mass: jsonObject.physicsMass,
friction: jsonObject.physicsFriction,
restitution: jsonObject.physicsRestitution,
}, scene);
};
/**
* Represents a physics imposter
* @see https://doc.babylonjs.com/features/featuresDeepDive/physics/usingPhysicsEngine
*/
export class PhysicsImpostor {
/**
* Specifies if the physics imposter is disposed
*/
get isDisposed() {
return this._isDisposed;
}
/**
* Gets the mass of the physics imposter
*/
get mass() {
return this._physicsEngine ? this._physicsEngine.getPhysicsPlugin().getBodyMass(this) : 0;
}
set mass(value) {
this.setMass(value);
}
/**
* Gets the coefficient of friction
*/
get friction() {
return this._physicsEngine ? this._physicsEngine.getPhysicsPlugin().getBodyFriction(this) : 0;
}
/**
* Sets the coefficient of friction
*/
set friction(value) {
if (!this._physicsEngine) {
return;
}
this._physicsEngine.getPhysicsPlugin().setBodyFriction(this, value);
}
/**
* Gets the coefficient of restitution
*/
get restitution() {
return this._physicsEngine ? this._physicsEngine.getPhysicsPlugin().getBodyRestitution(this) : 0;
}
/**
* Sets the coefficient of restitution
*/
set restitution(value) {
if (!this._physicsEngine) {
return;
}
this._physicsEngine.getPhysicsPlugin().setBodyRestitution(this, value);
}
/**
* Gets the pressure of a soft body; only supported by the AmmoJSPlugin
*/
get pressure() {
if (!this._physicsEngine) {
return 0;
}
const plugin = this._physicsEngine.getPhysicsPlugin();
if (!plugin.setBodyPressure) {
return 0;
}
return plugin.getBodyPressure(this);
}
/**
* Sets the pressure of a soft body; only supported by the AmmoJSPlugin
*/
set pressure(value) {
if (!this._physicsEngine) {
return;
}
const plugin = this._physicsEngine.getPhysicsPlugin();
if (!plugin.setBodyPressure) {
return;
}
plugin.setBodyPressure(this, value);
}
/**
* Gets the stiffness of a soft body; only supported by the AmmoJSPlugin
*/
get stiffness() {
if (!this._physicsEngine) {
return 0;
}
const plugin = this._physicsEngine.getPhysicsPlugin();
if (!plugin.getBodyStiffness) {
return 0;
}
return plugin.getBodyStiffness(this);
}
/**
* Sets the stiffness of a soft body; only supported by the AmmoJSPlugin
*/
set stiffness(value) {
if (!this._physicsEngine) {
return;
}
const plugin = this._physicsEngine.getPhysicsPlugin();
if (!plugin.setBodyStiffness) {
return;
}
plugin.setBodyStiffness(this, value);
}
/**
* Gets the velocityIterations of a soft body; only supported by the AmmoJSPlugin
*/
get velocityIterations() {
if (!this._physicsEngine) {
return 0;
}
const plugin = this._physicsEngine.getPhysicsPlugin();
if (!plugin.getBodyVelocityIterations) {
return 0;
}
return plugin.getBodyVelocityIterations(this);
}
/**
* Sets the velocityIterations of a soft body; only supported by the AmmoJSPlugin
*/
set velocityIterations(value) {
if (!this._physicsEngine) {
return;
}
const plugin = this._physicsEngine.getPhysicsPlugin();
if (!plugin.setBodyVelocityIterations) {
return;
}
plugin.setBodyVelocityIterations(this, value);
}
/**
* Gets the positionIterations of a soft body; only supported by the AmmoJSPlugin
*/
get positionIterations() {
if (!this._physicsEngine) {
return 0;
}
const plugin = this._physicsEngine.getPhysicsPlugin();
if (!plugin.getBodyPositionIterations) {
return 0;
}
return plugin.getBodyPositionIterations(this);
}
/**
* Sets the positionIterations of a soft body; only supported by the AmmoJSPlugin
*/
set positionIterations(value) {
if (!this._physicsEngine) {
return;
}
const plugin = this._physicsEngine.getPhysicsPlugin();
if (!plugin.setBodyPositionIterations) {
return;
}
plugin.setBodyPositionIterations(this, value);
}
/**
* Initializes the physics imposter
* @param object The physics-enabled object used as the physics imposter
* @param type The type of the physics imposter. Types are available as static members of this class.
* @param _options The options for the physics imposter
* @param _scene The Babylon scene
*/
constructor(
/**
* The physics-enabled object used as the physics imposter
*/
object,
/**
* The type of the physics imposter
*/
type, _options = { mass: 0 }, _scene) {
this.object = object;
this.type = type;
this._options = _options;
this._scene = _scene;
/** @internal */
this._pluginData = {};
this._bodyUpdateRequired = false;
this._onBeforePhysicsStepCallbacks = new Array();
this._onAfterPhysicsStepCallbacks = new Array();
/** @internal */
this._onPhysicsCollideCallbacks = [];
this._deltaPosition = Vector3.Zero();
this._isDisposed = false;
/**
* @internal
*/
this.soft = false;
/**
* @internal
*/
this.segments = 0;
//temp variables for parent rotation calculations
//private _mats: Array<Matrix> = [new Matrix(), new Matrix()];
this._tmpQuat = new Quaternion();
this._tmpQuat2 = new Quaternion();
/**
* this function is executed by the physics engine.
*/
this.beforeStep = () => {
if (!this._physicsEngine) {
return;
}
this.object.translate(this._deltaPosition, -1);
this._deltaRotationConjugated &&
this.object.rotationQuaternion &&
this.object.rotationQuaternion.multiplyToRef(this._deltaRotationConjugated, this.object.rotationQuaternion);
this.object.computeWorldMatrix(false);
if (this.object.parent && this.object.rotationQuaternion) {
this.getParentsRotation();
this._tmpQuat.multiplyToRef(this.object.rotationQuaternion, this._tmpQuat);
}
else {
this._tmpQuat.copyFrom(this.object.rotationQuaternion || new Quaternion());
}
if (!this._options.disableBidirectionalTransformation) {
this.object.rotationQuaternion &&
this._physicsEngine.getPhysicsPlugin().setPhysicsBodyTransformation(this, /*bInfo.boundingBox.centerWorld*/ this.object.getAbsolutePosition(), this._tmpQuat);
}
for (const func of this._onBeforePhysicsStepCallbacks) {
func(this);
}
};
/**
* this function is executed by the physics engine
*/
this.afterStep = () => {
if (!this._physicsEngine) {
return;
}
for (const func of this._onAfterPhysicsStepCallbacks) {
func(this);
}
this._physicsEngine.getPhysicsPlugin().setTransformationFromPhysicsBody(this);
// object has now its world rotation. needs to be converted to local.
if (this.object.parent && this.object.rotationQuaternion) {
this.getParentsRotation();
this._tmpQuat.conjugateInPlace();
this._tmpQuat.multiplyToRef(this.object.rotationQuaternion, this.object.rotationQuaternion);
}
// take the position set and make it the absolute position of this object.
this.object.setAbsolutePosition(this.object.position);
if (this._deltaRotation) {
this.object.rotationQuaternion && this.object.rotationQuaternion.multiplyToRef(this._deltaRotation, this.object.rotationQuaternion);
this._deltaPosition.applyRotationQuaternionToRef(this._deltaRotation, PhysicsImpostor._TmpVecs[0]);
this.object.translate(PhysicsImpostor._TmpVecs[0], 1);
}
else {
this.object.translate(this._deltaPosition, 1);
}
this.object.computeWorldMatrix(true);
};
/**
* Legacy collision detection event support
*/
this.onCollideEvent = null;
/**
* define an onCollide function to call when this impostor collides against a different body
* @param e collide event data
*/
this.onCollide = (e) => {
if (!this._onPhysicsCollideCallbacks.length && !this.onCollideEvent) {
return;
}
if (!this._physicsEngine) {
return;
}
const otherImpostor = this._physicsEngine.getImpostorWithPhysicsBody(e.body);
if (otherImpostor) {
// Legacy collision detection event support
if (this.onCollideEvent) {
this.onCollideEvent(this, otherImpostor);
}
const callbacks = this._onPhysicsCollideCallbacks.filter((obj) => {
return obj.otherImpostors.indexOf(otherImpostor) !== -1;
});
for (const obj of callbacks) {
obj.callback(this, otherImpostor, e.point, e.distance, e.impulse, e.normal);
}
}
};
//sanity check!
if (!this.object) {
Logger.Error("No object was provided. A physics object is obligatory");
return;
}
if (this.object.parent && _options.mass !== 0) {
Logger.Warn("A physics impostor has been created for an object which has a parent. Babylon physics currently works in local space so unexpected issues may occur.");
}
// Legacy support for old syntax.
if (!this._scene && object.getScene) {
this._scene = object.getScene();
}
if (!this._scene) {
return;
}
if (this.type > 100) {
this.soft = true;
}
this._physicsEngine = this._scene.getPhysicsEngine();
if (!this._physicsEngine) {
Logger.Error("Physics not enabled. Please use scene.enablePhysics(...) before creating impostors.");
}
else {
//set the object's quaternion, if not set
if (!this.object.rotationQuaternion) {
if (this.object.rotation) {
this.object.rotationQuaternion = Quaternion.RotationYawPitchRoll(this.object.rotation.y, this.object.rotation.x, this.object.rotation.z);
}
else {
this.object.rotationQuaternion = new Quaternion();
}
}
//default options params
this._options.mass = _options.mass === void 0 ? 0 : _options.mass;
this._options.friction = _options.friction === void 0 ? 0.2 : _options.friction;
this._options.restitution = _options.restitution === void 0 ? 0.2 : _options.restitution;
if (this.soft) {
//softbody mass must be above 0;
this._options.mass = this._options.mass > 0 ? this._options.mass : 1;
this._options.pressure = _options.pressure === void 0 ? 200 : _options.pressure;
this._options.stiffness = _options.stiffness === void 0 ? 1 : _options.stiffness;
this._options.velocityIterations = _options.velocityIterations === void 0 ? 20 : _options.velocityIterations;
this._options.positionIterations = _options.positionIterations === void 0 ? 20 : _options.positionIterations;
this._options.fixedPoints = _options.fixedPoints === void 0 ? 0 : _options.fixedPoints;
this._options.margin = _options.margin === void 0 ? 0 : _options.margin;
this._options.damping = _options.damping === void 0 ? 0 : _options.damping;
this._options.path = _options.path === void 0 ? null : _options.path;
this._options.shape = _options.shape === void 0 ? null : _options.shape;
}
this._joints = [];
//If the mesh has a parent, don't initialize the physicsBody. Instead wait for the parent to do that.
if (!this.object.parent || this._options.ignoreParent) {
this._init();
}
else if (this.object.parent.physicsImpostor) {
Logger.Warn("You must affect impostors to children before affecting impostor to parent.");
}
}
}
/**
* This function will completely initialize this impostor.
* It will create a new body - but only if this mesh has no parent.
* If it has, this impostor will not be used other than to define the impostor
* of the child mesh.
* @internal
*/
_init() {
if (!this._physicsEngine) {
return;
}
this._physicsEngine.removeImpostor(this);
this.physicsBody = null;
this._parent = this._parent || this._getPhysicsParent();
if (!this._isDisposed && (!this.parent || this._options.ignoreParent)) {
this._physicsEngine.addImpostor(this);
}
}
_getPhysicsParent() {
if (this.object.parent instanceof AbstractMesh) {
const parentMesh = this.object.parent;
return parentMesh.physicsImpostor;
}
return null;
}
/**
* Should a new body be generated.
* @returns boolean specifying if body initialization is required
*/
isBodyInitRequired() {
return this._bodyUpdateRequired || (!this._physicsBody && (!this._parent || !!this._options.ignoreParent));
}
/**
* Sets the updated scaling
*/
setScalingUpdated() {
this.forceUpdate();
}
/**
* Force a regeneration of this or the parent's impostor's body.
* Use with caution - This will remove all previously-instantiated joints.
*/
forceUpdate() {
this._init();
if (this.parent && !this._options.ignoreParent) {
this.parent.forceUpdate();
}
}
/*public get mesh(): AbstractMesh {
return this._mesh;
}*/
/**
* Gets the body that holds this impostor. Either its own, or its parent.
*/
get physicsBody() {
return this._parent && !this._options.ignoreParent ? this._parent.physicsBody : this._physicsBody;
}
/**
* Get the parent of the physics imposter
* @returns Physics imposter or null
*/
get parent() {
return !this._options.ignoreParent && this._parent ? this._parent : null;
}
/**
* Sets the parent of the physics imposter
*/
set parent(value) {
this._parent = value;
}
/**
* Set the physics body. Used mainly by the physics engine/plugin
*/
set physicsBody(physicsBody) {
if (this._physicsBody && this._physicsEngine) {
this._physicsEngine.getPhysicsPlugin().removePhysicsBody(this);
}
this._physicsBody = physicsBody;
this.resetUpdateFlags();
}
/**
* Resets the update flags
*/
resetUpdateFlags() {
this._bodyUpdateRequired = false;
}
/**
* Gets the object extents
* @returns the object extents
*/
getObjectExtents() {
if (this.object.getBoundingInfo) {
const q = this.object.rotationQuaternion;
const scaling = this.object.scaling.clone();
//reset rotation
this.object.rotationQuaternion = PhysicsImpostor.IDENTITY_QUATERNION;
//calculate the world matrix with no rotation
const worldMatrix = this.object.computeWorldMatrix && this.object.computeWorldMatrix(true);
if (worldMatrix) {
worldMatrix.decompose(scaling, undefined, undefined);
}
const boundingInfo = this.object.getBoundingInfo();
// get the global scaling of the object
const size = boundingInfo.boundingBox.extendSize.scale(2).multiplyInPlace(scaling);
size.x = Math.abs(size.x);
size.y = Math.abs(size.y);
size.z = Math.abs(size.z);
//bring back the rotation
this.object.rotationQuaternion = q;
//calculate the world matrix with the new rotation
this.object.computeWorldMatrix && this.object.computeWorldMatrix(true);
return size;
}
else {
return PhysicsImpostor.DEFAULT_OBJECT_SIZE;
}
}
/**
* Gets the object center
* @returns The object center
*/
getObjectCenter() {
if (this.object.getBoundingInfo) {
const boundingInfo = this.object.getBoundingInfo();
return boundingInfo.boundingBox.centerWorld;
}
else {
return this.object.position;
}
}
/**
* Get a specific parameter from the options parameters
* @param paramName The object parameter name
* @returns The object parameter
*/
getParam(paramName) {
return this._options[paramName];
}
/**
* Sets a specific parameter in the options given to the physics plugin
* @param paramName The parameter name
* @param value The value of the parameter
*/
setParam(paramName, value) {
this._options[paramName] = value;
this._bodyUpdateRequired = true;
}
/**
* Specifically change the body's mass. Won't recreate the physics body object
* @param mass The mass of the physics imposter
*/
setMass(mass) {
if (this.getParam("mass") !== mass) {
this.setParam("mass", mass);
}
if (this._physicsEngine) {
this._physicsEngine.getPhysicsPlugin().setBodyMass(this, mass);
}
}
/**
* Gets the linear velocity
* @returns linear velocity or null
*/
getLinearVelocity() {
return this._physicsEngine ? this._physicsEngine.getPhysicsPlugin().getLinearVelocity(this) : Vector3.Zero();
}
/**
* Sets the linear velocity
* @param velocity linear velocity or null
*/
setLinearVelocity(velocity) {
if (this._physicsEngine) {
this._physicsEngine.getPhysicsPlugin().setLinearVelocity(this, velocity);
}
}
/**
* Gets the angular velocity
* @returns angular velocity or null
*/
getAngularVelocity() {
return this._physicsEngine ? this._physicsEngine.getPhysicsPlugin().getAngularVelocity(this) : Vector3.Zero();
}
/**
* Sets the angular velocity
* @param velocity The velocity or null
*/
setAngularVelocity(velocity) {
if (this._physicsEngine) {
this._physicsEngine.getPhysicsPlugin().setAngularVelocity(this, velocity);
}
}
/**
* Execute a function with the physics plugin native code
* Provide a function the will have two variables - the world object and the physics body object
* @param func The function to execute with the physics plugin native code
*/
executeNativeFunction(func) {
if (this._physicsEngine) {
func(this._physicsEngine.getPhysicsPlugin().world, this.physicsBody);
}
}
/**
* Register a function that will be executed before the physics world is stepping forward
* @param func The function to execute before the physics world is stepped forward
*/
registerBeforePhysicsStep(func) {
this._onBeforePhysicsStepCallbacks.push(func);
}
/**
* Unregister a function that will be executed before the physics world is stepping forward
* @param func The function to execute before the physics world is stepped forward
*/
unregisterBeforePhysicsStep(func) {
const index = this._onBeforePhysicsStepCallbacks.indexOf(func);
if (index > -1) {
this._onBeforePhysicsStepCallbacks.splice(index, 1);
}
else {
Logger.Warn("Function to remove was not found");
}
}
/**
* Register a function that will be executed after the physics step
* @param func The function to execute after physics step
*/
registerAfterPhysicsStep(func) {
this._onAfterPhysicsStepCallbacks.push(func);
}
/**
* Unregisters a function that will be executed after the physics step
* @param func The function to execute after physics step
*/
unregisterAfterPhysicsStep(func) {
const index = this._onAfterPhysicsStepCallbacks.indexOf(func);
if (index > -1) {
this._onAfterPhysicsStepCallbacks.splice(index, 1);
}
else {
Logger.Warn("Function to remove was not found");
}
}
/**
* register a function that will be executed when this impostor collides against a different body
* @param collideAgainst Physics imposter, or array of physics imposters to collide against
* @param func Callback that is executed on collision
*/
registerOnPhysicsCollide(collideAgainst, func) {
const collidedAgainstList = collideAgainst instanceof Array ? collideAgainst : [collideAgainst];
this._onPhysicsCollideCallbacks.push({ callback: func, otherImpostors: collidedAgainstList });
}
/**
* Unregisters the physics imposter's collision callback
* @param collideAgainst The physics object to collide against
* @param func Callback to execute on collision
*/
unregisterOnPhysicsCollide(collideAgainst, func) {
const collidedAgainstList = collideAgainst instanceof Array ? collideAgainst : [collideAgainst];
let index = -1;
const found = this._onPhysicsCollideCallbacks.some((cbDef, idx) => {
if (cbDef.callback === func && cbDef.otherImpostors.length === collidedAgainstList.length) {
// chcek the arrays match
const sameList = cbDef.otherImpostors.every((impostor) => {
return collidedAgainstList.indexOf(impostor) > -1;
});
if (sameList) {
index = idx;
}
return sameList;
}
return false;
});
if (found) {
this._onPhysicsCollideCallbacks.splice(index, 1);
}
else {
Logger.Warn("Function to remove was not found");
}
}
/**
* Get the parent rotation
* @returns The parent rotation
*/
getParentsRotation() {
let parent = this.object.parent;
this._tmpQuat.copyFromFloats(0, 0, 0, 1);
while (parent) {
if (parent.rotationQuaternion) {
this._tmpQuat2.copyFrom(parent.rotationQuaternion);
}
else {
Quaternion.RotationYawPitchRollToRef(parent.rotation.y, parent.rotation.x, parent.rotation.z, this._tmpQuat2);
}
this._tmpQuat.multiplyToRef(this._tmpQuat2, this._tmpQuat);
parent = parent.parent;
}
return this._tmpQuat;
}
/**
* Apply a force
* @param force The force to apply
* @param contactPoint The contact point for the force
* @returns The physics imposter
*/
applyForce(force, contactPoint) {
if (this._physicsEngine) {
this._physicsEngine.getPhysicsPlugin().applyForce(this, force, contactPoint);
}
return this;
}
/**
* Apply an impulse
* @param force The impulse force
* @param contactPoint The contact point for the impulse force
* @returns The physics imposter
*/
applyImpulse(force, contactPoint) {
if (this._physicsEngine) {
this._physicsEngine.getPhysicsPlugin().applyImpulse(this, force, contactPoint);
}
return this;
}
/**
* A help function to create a joint
* @param otherImpostor A physics imposter used to create a joint
* @param jointType The type of joint
* @param jointData The data for the joint
* @returns The physics imposter
*/
createJoint(otherImpostor, jointType, jointData) {
const joint = new PhysicsJoint(jointType, jointData);
this.addJoint(otherImpostor, joint);
return this;
}
/**
* Add a joint to this impostor with a different impostor
* @param otherImpostor A physics imposter used to add a joint
* @param joint The joint to add
* @returns The physics imposter
*/
addJoint(otherImpostor, joint) {
this._joints.push({
otherImpostor: otherImpostor,
joint: joint,
});
if (this._physicsEngine) {
this._physicsEngine.addJoint(this, otherImpostor, joint);
}
return this;
}
/**
* Add an anchor to a cloth impostor
* @param otherImpostor rigid impostor to anchor to
* @param width ratio across width from 0 to 1
* @param height ratio up height from 0 to 1
* @param influence the elasticity between cloth impostor and anchor from 0, very stretchy to 1, little stretch
* @param noCollisionBetweenLinkedBodies when true collisions between cloth impostor and anchor are ignored; default false
* @returns impostor the soft imposter
*/
addAnchor(otherImpostor, width, height, influence, noCollisionBetweenLinkedBodies) {
if (!this._physicsEngine) {
return this;
}
const plugin = this._physicsEngine.getPhysicsPlugin();
if (!plugin.appendAnchor) {
return this;
}
if (this._physicsEngine) {
plugin.appendAnchor(this, otherImpostor, width, height, influence, noCollisionBetweenLinkedBodies);
}
return this;
}
/**
* Add a hook to a rope impostor
* @param otherImpostor rigid impostor to anchor to
* @param length ratio across rope from 0 to 1
* @param influence the elasticity between rope impostor and anchor from 0, very stretchy to 1, little stretch
* @param noCollisionBetweenLinkedBodies when true collisions between soft impostor and anchor are ignored; default false
* @returns impostor the rope imposter
*/
addHook(otherImpostor, length, influence, noCollisionBetweenLinkedBodies) {
if (!this._physicsEngine) {
return this;
}
const plugin = this._physicsEngine.getPhysicsPlugin();
if (!plugin.appendAnchor) {
return this;
}
if (this._physicsEngine) {
plugin.appendHook(this, otherImpostor, length, influence, noCollisionBetweenLinkedBodies);
}
return this;
}
/**
* Will keep this body still, in a sleep mode.
* @returns the physics imposter
*/
sleep() {
if (this._physicsEngine) {
this._physicsEngine.getPhysicsPlugin().sleepBody(this);
}
return this;
}
/**
* Wake the body up.
* @returns The physics imposter
*/
wakeUp() {
if (this._physicsEngine) {
this._physicsEngine.getPhysicsPlugin().wakeUpBody(this);
}
return this;
}
/**
* Clones the physics imposter
* @param newObject The physics imposter clones to this physics-enabled object
* @returns A nullable physics imposter
*/
clone(newObject) {
if (!newObject) {
return null;
}
return new PhysicsImpostor(newObject, this.type, this._options, this._scene);
}
/**
* Disposes the physics imposter
*/
dispose( /*disposeChildren: boolean = true*/) {
//no dispose if no physics engine is available.
if (!this._physicsEngine) {
return;
}
for (const j of this._joints) {
if (this._physicsEngine) {
this._physicsEngine.removeJoint(this, j.otherImpostor, j.joint);
}
}
//dispose the physics body
this._physicsEngine.removeImpostor(this);
if (this.parent) {
this.parent.forceUpdate();
}
this._isDisposed = true;
}
/**
* Sets the delta position
* @param position The delta position amount
*/
setDeltaPosition(position) {
this._deltaPosition.copyFrom(position);
}
/**
* Sets the delta rotation
* @param rotation The delta rotation amount
*/
setDeltaRotation(rotation) {
if (!this._deltaRotation) {
this._deltaRotation = new Quaternion();
}
this._deltaRotation.copyFrom(rotation);
this._deltaRotationConjugated = this._deltaRotation.conjugate();
}
/**
* Gets the box size of the physics imposter and stores the result in the input parameter
* @param result Stores the box size
* @returns The physics imposter
*/
getBoxSizeToRef(result) {
if (this._physicsEngine) {
this._physicsEngine.getPhysicsPlugin().getBoxSizeToRef(this, result);
}
return this;
}
/**
* Gets the radius of the physics imposter
* @returns Radius of the physics imposter
*/
getRadius() {
return this._physicsEngine ? this._physicsEngine.getPhysicsPlugin().getRadius(this) : 0;
}
/**
* Sync a bone with this impostor
* @param bone The bone to sync to the impostor.
* @param boneMesh The mesh that the bone is influencing.
* @param jointPivot The pivot of the joint / bone in local space.
* @param distToJoint Optional distance from the impostor to the joint.
* @param adjustRotation Optional quaternion for adjusting the local rotation of the bone.
*/
syncBoneWithImpostor(bone, boneMesh, jointPivot, distToJoint, adjustRotation) {
const tempVec = PhysicsImpostor._TmpVecs[0];
const mesh = this.object;
if (mesh.rotationQuaternion) {
if (adjustRotation) {
const tempQuat = PhysicsImpostor._TmpQuat;
mesh.rotationQuaternion.multiplyToRef(adjustRotation, tempQuat);
bone.setRotationQuaternion(tempQuat, 1 /* Space.WORLD */, boneMesh);
}
else {
bone.setRotationQuaternion(mesh.rotationQuaternion, 1 /* Space.WORLD */, boneMesh);
}
}
tempVec.x = 0;
tempVec.y = 0;
tempVec.z = 0;
if (jointPivot) {
tempVec.x = jointPivot.x;
tempVec.y = jointPivot.y;
tempVec.z = jointPivot.z;
bone.getDirectionToRef(tempVec, boneMesh, tempVec);
if (distToJoint === undefined || distToJoint === null) {
distToJoint = jointPivot.length();
}
tempVec.x *= distToJoint;
tempVec.y *= distToJoint;
tempVec.z *= distToJoint;
}
if (bone.getParent()) {
tempVec.addInPlace(mesh.getAbsolutePosition());
bone.setAbsolutePosition(tempVec, boneMesh);
}
else {
boneMesh.setAbsolutePosition(mesh.getAbsolutePosition());
boneMesh.position.x -= tempVec.x;
boneMesh.position.y -= tempVec.y;
boneMesh.position.z -= tempVec.z;
}
}
/**
* Sync impostor to a bone
* @param bone The bone that the impostor will be synced to.
* @param boneMesh The mesh that the bone is influencing.
* @param jointPivot The pivot of the joint / bone in local space.
* @param distToJoint Optional distance from the impostor to the joint.
* @param adjustRotation Optional quaternion for adjusting the local rotation of the bone.
* @param boneAxis Optional vector3 axis the bone is aligned with
*/
syncImpostorWithBone(bone, boneMesh, jointPivot, distToJoint, adjustRotation, boneAxis) {
const mesh = this.object;
if (mesh.rotationQuaternion) {
if (adjustRotation) {
const tempQuat = PhysicsImpostor._TmpQuat;
bone.getRotationQuaternionToRef(1 /* Space.WORLD */, boneMesh, tempQuat);
tempQuat.multiplyToRef(adjustRotation, mesh.rotationQuaternion);
}
else {
bone.getRotationQuaternionToRef(1 /* Space.WORLD */, boneMesh, mesh.rotationQuaternion);
}
}
const pos = PhysicsImpostor._TmpVecs[0];
const boneDir = PhysicsImpostor._TmpVecs[1];
if (!boneAxis) {
boneAxis = PhysicsImpostor._TmpVecs[2];
boneAxis.x = 0;
boneAxis.y = 1;
boneAxis.z = 0;
}
bone.getDirectionToRef(boneAxis, boneMesh, boneDir);
bone.getAbsolutePositionToRef(boneMesh, pos);
if ((distToJoint === undefined || distToJoint === null) && jointPivot) {
distToJoint = jointPivot.length();
}
if (distToJoint !== undefined && distToJoint !== null) {
pos.x += boneDir.x * distToJoint;
pos.y += boneDir.y * distToJoint;
pos.z += boneDir.z * distToJoint;
}
mesh.setAbsolutePosition(pos);
}
}
/**
* The default object size of the imposter
*/
PhysicsImpostor.DEFAULT_OBJECT_SIZE = new Vector3(1, 1, 1);
/**
* The identity quaternion of the imposter
*/
PhysicsImpostor.IDENTITY_QUATERNION = Quaternion.Identity();
PhysicsImpostor._TmpVecs = BuildArray(3, Vector3.Zero);
PhysicsImpostor._TmpQuat = Quaternion.Identity();
//Impostor types
/**
* No-Imposter type
*/
PhysicsImpostor.NoImpostor = 0;
/**
* Sphere-Imposter type
*/
PhysicsImpostor.SphereImpostor = 1;
/**
* Box-Imposter type
*/
PhysicsImpostor.BoxImpostor = 2;
/**
* Plane-Imposter type
*/
PhysicsImpostor.PlaneImpostor = 3;
/**
* Mesh-imposter type (Only available to objects with vertices data)
*/
PhysicsImpostor.MeshImpostor = 4;
/**
* Capsule-Impostor type (Ammo.js plugin only)
*/
PhysicsImpostor.CapsuleImpostor = 6;
/**
* Cylinder-Imposter type
*/
PhysicsImpostor.CylinderImpostor = 7;
/**
* Particle-Imposter type
*/
PhysicsImpostor.ParticleImpostor = 8;
/**
* Heightmap-Imposter type
*/
PhysicsImpostor.HeightmapImpostor = 9;
/**
* ConvexHull-Impostor type (Ammo.js plugin only)
*/
PhysicsImpostor.ConvexHullImpostor = 10;
/**
* Custom-Imposter type (Ammo.js plugin only)
*/
PhysicsImpostor.CustomImpostor = 100;
/**
* Rope-Imposter type
*/
PhysicsImpostor.RopeImpostor = 101;
/**
* Cloth-Imposter type
*/
PhysicsImpostor.ClothImpostor = 102;
/**
* Softbody-Imposter type
*/
PhysicsImpostor.SoftbodyImpostor = 103;
//# sourceMappingURL=physicsImpostor.js.map