playcanvas
Version:
PlayCanvas WebGL game engine
587 lines (586 loc) • 21.1 kB
TypeScript
/**
* The RigidBodyComponent, when combined with a {@link CollisionComponent}, allows your entities
* to be simulated using realistic physics. A RigidBodyComponent will fall under gravity and
* collide with other rigid bodies. Using scripts, you can apply forces and impulses to rigid
* bodies.
*
* You should never need to use the RigidBodyComponent constructor directly. To add an
* RigidBodyComponent to an {@link Entity}, use {@link Entity#addComponent}:
*
* ```javascript
* // Create a static 1x1x1 box-shaped rigid body
* const entity = pc.Entity();
* entity.addComponent('collision'); // Without options, this defaults to a 1x1x1 box shape
* entity.addComponent('rigidbody'); // Without options, this defaults to a 'static' body
* ```
*
* To create a dynamic sphere with mass of 10, do:
*
* ```javascript
* const entity = pc.Entity();
* entity.addComponent('collision', {
* type: 'sphere'
* });
* entity.addComponent('rigidbody', {
* type: 'dynamic',
* mass: 10
* });
* ```
*
* Once the RigidBodyComponent is added to the entity, you can access it via the
* {@link Entity#rigidbody} property:
*
* ```javascript
* entity.rigidbody.mass = 10;
* console.log(entity.rigidbody.mass);
* ```
*
* Relevant Engine API examples:
*
* - [Falling shapes](https://playcanvas.github.io/#/physics/falling-shapes)
* - [Vehicle physics](https://playcanvas.github.io/#/physics/vehicle)
*
* @hideconstructor
* @category Physics
*/
export class RigidBodyComponent extends Component {
/**
* Fired when a contact occurs between two rigid bodies. The handler is passed a
* {@link ContactResult} object containing details of the contact between the two rigid bodies.
*
* @event
* @example
* entity.rigidbody.on('contact', (result) => {
* console.log(`Contact between ${entity.name} and ${result.other.name}`);
* });
*/
static EVENT_CONTACT: string;
/**
* Fired when two rigid bodies start touching. The handler is passed a {@link ContactResult}
* object containing details of the contact between the two rigid bodies.
*
* @event
* @example
* entity.rigidbody.on('collisionstart', (result) => {
* console.log(`Collision started between ${entity.name} and ${result.other.name}`);
* });
*/
static EVENT_COLLISIONSTART: string;
/**
* Fired when two rigid bodies stop touching. The handler is passed an {@link Entity} that
* represents the other rigid body involved in the collision.
*
* @event
* @example
* entity.rigidbody.on('collisionend', (other) => {
* console.log(`${entity.name} stopped touching ${other.name}`);
* });
*/
static EVENT_COLLISIONEND: string;
/**
* Fired when a rigid body enters a trigger volume. The handler is passed an {@link Entity}
* representing the trigger volume that this rigid body entered.
*
* @event
* @example
* entity.rigidbody.on('triggerenter', (trigger) => {
* console.log(`Entity ${entity.name} entered trigger volume ${trigger.name}`);
* });
*/
static EVENT_TRIGGERENTER: string;
/**
* Fired when a rigid body exits a trigger volume. The handler is passed an {@link Entity}
* representing the trigger volume that this rigid body exited.
*
* @event
* @example
* entity.rigidbody.on('triggerleave', (trigger) => {
* console.log(`Entity ${entity.name} exited trigger volume ${trigger.name}`);
* });
*/
static EVENT_TRIGGERLEAVE: string;
/** @ignore */
static onLibraryLoaded(): void;
/** @ignore */
static onAppDestroy(): void;
/** @private */
private _angularDamping;
/** @private */
private _angularFactor;
/** @private */
private _angularVelocity;
/** @private */
private _body;
/** @private */
private _friction;
/** @private */
private _group;
/** @private */
private _linearDamping;
/** @private */
private _linearFactor;
/** @private */
private _linearVelocity;
/** @private */
private _mask;
/** @private */
private _mass;
/** @private */
private _restitution;
/** @private */
private _rollingFriction;
/** @private */
private _simulationEnabled;
/** @private */
private _type;
/**
* Sets the rate at which a body loses angular velocity over time.
*
* @type {number}
*/
set angularDamping(damping: number);
/**
* Gets the rate at which a body loses angular velocity over time.
*
* @type {number}
*/
get angularDamping(): number;
/**
* Sets the scaling factor for angular movement of the body in each axis. Only valid for rigid
* bodies of type {@link BODYTYPE_DYNAMIC}. Defaults to 1 in all axes (body can freely rotate).
*
* @type {Vec3}
*/
set angularFactor(factor: Vec3);
/**
* Gets the scaling factor for angular movement of the body in each axis.
*
* @type {Vec3}
*/
get angularFactor(): Vec3;
/**
* Sets the rotational speed of the body around each world axis.
*
* @type {Vec3}
*/
set angularVelocity(velocity: Vec3);
/**
* Gets the rotational speed of the body around each world axis.
*
* @type {Vec3}
*/
get angularVelocity(): Vec3;
set body(body: any);
get body(): any;
/**
* Sets the friction value used when contacts occur between two bodies. A higher value indicates
* more friction. Should be set in the range 0 to 1. Defaults to 0.5.
*
* @type {number}
*/
set friction(friction: number);
/**
* Gets the friction value used when contacts occur between two bodies.
*
* @type {number}
*/
get friction(): number;
/**
* Sets the collision group this body belongs to. Combine the group and the mask to prevent bodies
* colliding with each other. Defaults to 1.
*
* @type {number}
*/
set group(group: number);
/**
* Gets the collision group this body belongs to.
*
* @type {number}
*/
get group(): number;
/**
* Sets the rate at which a body loses linear velocity over time. Defaults to 0.
*
* @type {number}
*/
set linearDamping(damping: number);
/**
* Gets the rate at which a body loses linear velocity over time.
*
* @type {number}
*/
get linearDamping(): number;
/**
* Sets the scaling factor for linear movement of the body in each axis. Only valid for rigid
* bodies of type {@link BODYTYPE_DYNAMIC}. Defaults to 1 in all axes (body can freely move).
*
* @type {Vec3}
*/
set linearFactor(factor: Vec3);
/**
* Gets the scaling factor for linear movement of the body in each axis.
*
* @type {Vec3}
*/
get linearFactor(): Vec3;
/**
* Sets the speed of the body in a given direction.
*
* @type {Vec3}
*/
set linearVelocity(velocity: Vec3);
/**
* Gets the speed of the body in a given direction.
*
* @type {Vec3}
*/
get linearVelocity(): Vec3;
/**
* Sets the collision mask sets which groups this body collides with. It is a bit field of 16
* bits, the first 8 bits are reserved for engine use. Defaults to 65535.
*
* @type {number}
*/
set mask(mask: number);
/**
* Gets the collision mask sets which groups this body collides with.
*
* @type {number}
*/
get mask(): number;
/**
* Sets the mass of the body. This is only relevant for {@link BODYTYPE_DYNAMIC} bodies, other
* types have infinite mass. Defaults to 1.
*
* @type {number}
*/
set mass(mass: number);
/**
* Gets the mass of the body.
*
* @type {number}
*/
get mass(): number;
/**
* Sets the value that controls the amount of energy lost when two rigid bodies collide. The
* calculation multiplies the restitution values for both colliding bodies. A multiplied value
* of 0 means that all energy is lost in the collision while a value of 1 means that no energy
* is lost. Should be set in the range 0 to 1. Defaults to 0.
*
* @type {number}
*/
set restitution(restitution: number);
/**
* Gets the value that controls the amount of energy lost when two rigid bodies collide.
*
* @type {number}
*/
get restitution(): number;
/**
* Sets the torsional friction orthogonal to the contact point. Defaults to 0.
*
* @type {number}
*/
set rollingFriction(friction: number);
/**
* Gets the torsional friction orthogonal to the contact point.
*
* @type {number}
*/
get rollingFriction(): number;
/**
* Sets the rigid body type determines how the body is simulated. Can be:
*
* - {@link BODYTYPE_STATIC}: infinite mass and cannot move.
* - {@link BODYTYPE_DYNAMIC}: simulated according to applied forces.
* - {@link BODYTYPE_KINEMATIC}: infinite mass and does not respond to forces (can only be
* moved by setting the position and rotation of component's {@link Entity}).
*
* Defaults to {@link BODYTYPE_STATIC}.
*
* @type {string}
*/
set type(type: string);
/**
* Gets the rigid body type determines how the body is simulated.
*
* @type {string}
*/
get type(): string;
/**
* If the Entity has a Collision shape attached then create a rigid body using this shape. This
* method destroys the existing body.
*
* @private
*/
private createBody;
/**
* Returns true if the rigid body is currently actively being simulated. I.e. Not 'sleeping'.
*
* @returns {boolean} True if the body is active.
*/
isActive(): boolean;
/**
* Forcibly activate the rigid body simulation. Only affects rigid bodies of type
* {@link BODYTYPE_DYNAMIC}.
*/
activate(): void;
/**
* Add a body to the simulation.
*
* @ignore
*/
enableSimulation(): void;
/**
* Remove a body from the simulation.
*
* @ignore
*/
disableSimulation(): void;
/**
* Apply a force to the body at a point. By default, the force is applied at the origin of the
* body. However, the force can be applied at an offset this point by specifying a world space
* vector from the body's origin to the point of application.
*
* @overload
* @param {number} x - X-component of the force in world space.
* @param {number} y - Y-component of the force in world space.
* @param {number} z - Z-component of the force in world space.
* @param {number} [px] - X-component of the relative point at which to apply the force in
* world space.
* @param {number} [py] - Y-component of the relative point at which to apply the force in
* world space.
* @param {number} [pz] - Z-component of the relative point at which to apply the force in
* world space.
* @returns {void}
* @example
* // Apply an approximation of gravity at the body's center
* this.entity.rigidbody.applyForce(0, -10, 0);
* @example
* // Apply an approximation of gravity at 1 unit down the world Z from the center of the body
* this.entity.rigidbody.applyForce(0, -10, 0, 0, 0, 1);
*/
applyForce(x: number, y: number, z: number, px?: number, py?: number, pz?: number): void;
/**
* Apply a force to the body at a point. By default, the force is applied at the origin of the
* body. However, the force can be applied at an offset this point by specifying a world space
* vector from the body's origin to the point of application.
*
* @overload
* @param {Vec3} force - Vector representing the force in world space.
* @param {Vec3} [relativePoint] - Optional vector representing the relative point at which to
* apply the force in world space.
* @returns {void}
* @example
* // Calculate a force vector pointing in the world space direction of the entity
* const force = this.entity.forward.clone().mulScalar(100);
*
* // Apply the force at the body's center
* this.entity.rigidbody.applyForce(force);
* @example
* // Apply a force at some relative offset from the body's center
* // Calculate a force vector pointing in the world space direction of the entity
* const force = this.entity.forward.clone().mulScalar(100);
*
* // Calculate the world space relative offset
* const relativePoint = new pc.Vec3();
* const childEntity = this.entity.findByName('Engine');
* relativePoint.sub2(childEntity.getPosition(), this.entity.getPosition());
*
* // Apply the force
* this.entity.rigidbody.applyForce(force, relativePoint);
*/
applyForce(force: Vec3, relativePoint?: Vec3): void;
/**
* Apply torque (rotational force) to the body.
*
* @overload
* @param {number} x - The x-component of the torque force in world space.
* @param {number} y - The y-component of the torque force in world space.
* @param {number} z - The z-component of the torque force in world space.
* @returns {void}
* @example
* entity.rigidbody.applyTorque(0, 10, 0);
*/
applyTorque(x: number, y: number, z: number): void;
/**
* Apply torque (rotational force) to the body.
*
* @overload
* @param {Vec3} torque - Vector representing the torque force in world space.
* @returns {void}
* @example
* const torque = new pc.Vec3(0, 10, 0);
* entity.rigidbody.applyTorque(torque);
*/
applyTorque(torque: Vec3): void;
/**
* Apply an impulse (instantaneous change of velocity) to the body at a point.
*
* @overload
* @param {number} x - X-component of the impulse in world space.
* @param {number} y - Y-component of the impulse in world space.
* @param {number} z - Z-component of the impulse in world space.
* @param {number} [px] - X-component of the point at which to apply the impulse in the local
* space of the entity.
* @param {number} [py] - Y-component of the point at which to apply the impulse in the local
* space of the entity.
* @param {number} [pz] - Z-component of the point at which to apply the impulse in the local
* space of the entity.
* @returns {void}
* @example
* // Apply an impulse along the world space positive y-axis at the entity's position.
* entity.rigidbody.applyImpulse(0, 10, 0);
* @example
* // Apply an impulse along the world space positive y-axis at 1 unit down the positive
* // z-axis of the entity's local space.
* entity.rigidbody.applyImpulse(0, 10, 0, 0, 0, 1);
*/
applyImpulse(x: number, y: number, z: number, px?: number, py?: number, pz?: number): void;
/**
* Apply an impulse (instantaneous change of velocity) to the body at a point.
*
* @overload
* @param {Vec3} impulse - Vector representing the impulse in world space.
* @param {Vec3} [relativePoint] - Optional vector representing the relative point at which to
* apply the impulse in the local space of the entity.
* @returns {void}
* @example
* // Apply an impulse along the world space positive y-axis at the entity's position.
* const impulse = new pc.Vec3(0, 10, 0);
* entity.rigidbody.applyImpulse(impulse);
* @example
* // Apply an impulse along the world space positive y-axis at 1 unit down the positive
* // z-axis of the entity's local space.
* const impulse = new pc.Vec3(0, 10, 0);
* const relativePoint = new pc.Vec3(0, 0, 1);
* entity.rigidbody.applyImpulse(impulse, relativePoint);
*/
applyImpulse(impulse: Vec3, relativePoint?: Vec3): void;
/**
* Apply a torque impulse (rotational force applied instantaneously) to the body.
*
* @overload
* @param {number} x - X-component of the torque impulse in world space.
* @param {number} y - Y-component of the torque impulse in world space.
* @param {number} z - Z-component of the torque impulse in world space.
* @returns {void}
* @example
* entity.rigidbody.applyTorqueImpulse(0, 10, 0);
*/
applyTorqueImpulse(x: number, y: number, z: number): void;
/**
* Apply a torque impulse (rotational force applied instantaneously) to the body.
*
* @overload
* @param {Vec3} torque - Vector representing the torque impulse in world space.
* @returns {void}
* @example
* const torque = new pc.Vec3(0, 10, 0);
* entity.rigidbody.applyTorqueImpulse(torque);
*/
applyTorqueImpulse(torque: Vec3): void;
/**
* Returns true if the rigid body is of type {@link BODYTYPE_STATIC}.
*
* @returns {boolean} True if static.
*/
isStatic(): boolean;
/**
* Returns true if the rigid body is of type {@link BODYTYPE_STATIC} or {@link BODYTYPE_KINEMATIC}.
*
* @returns {boolean} True if static or kinematic.
*/
isStaticOrKinematic(): boolean;
/**
* Returns true if the rigid body is of type {@link BODYTYPE_KINEMATIC}.
*
* @returns {boolean} True if kinematic.
*/
isKinematic(): boolean;
/**
* Writes an entity transform into an Ammo.btTransform but ignoring scale.
*
* @param {object} transform - The ammo transform to write the entity transform to.
* @private
*/
private _getEntityTransform;
/**
* Set the rigid body transform to be the same as the Entity transform. This must be called
* after any Entity transformation functions (e.g. {@link Entity#setPosition}) are called in
* order to update the rigid body to match the Entity.
*
* @private
*/
private syncEntityToBody;
/**
* Sets an entity's transform to match that of the world transformation matrix of a dynamic
* rigid body's motion state.
*
* @private
*/
private _updateDynamic;
/**
* Writes the entity's world transformation matrix into the motion state of a kinematic body.
*
* @private
*/
private _updateKinematic;
/**
* Teleport an entity to a new world space position, optionally setting orientation. This
* function should only be called for rigid bodies that are dynamic.
*
* @overload
* @param {number} x - X-coordinate of the new world space position.
* @param {number} y - Y-coordinate of the new world space position.
* @param {number} z - Z-coordinate of the new world space position.
* @param {number} [rx] - X-rotation of the world space Euler angles in degrees.
* @param {number} [ry] - Y-rotation of the world space Euler angles in degrees.
* @param {number} [rz] - Z-rotation of the world space Euler angles in degrees.
* @returns {void}
* @example
* // Teleport the entity to the origin
* entity.rigidbody.teleport(0, 0, 0);
* @example
* // Teleport the entity to world space coordinate [1, 2, 3] and reset orientation
* entity.rigidbody.teleport(1, 2, 3, 0, 0, 0);
*/
teleport(x: number, y: number, z: number, rx?: number, ry?: number, rz?: number): void;
/**
* Teleport an entity to a new world space position, optionally setting orientation. This
* function should only be called for rigid bodies that are dynamic.
*
* @overload
* @param {Vec3} position - Vector holding the new world space position.
* @param {Vec3} [angles] - Vector holding the new world space Euler angles in degrees.
* @returns {void}
* @example
* // Teleport the entity to the origin
* entity.rigidbody.teleport(pc.Vec3.ZERO);
* @example
* // Teleport the entity to world space coordinate [1, 2, 3] and reset orientation
* const position = new pc.Vec3(1, 2, 3);
* entity.rigidbody.teleport(position, pc.Vec3.ZERO);
*/
teleport(position: Vec3, angles?: Vec3): void;
/**
* Teleport an entity to a new world space position, optionally setting orientation. This
* function should only be called for rigid bodies that are dynamic.
*
* @overload
* @param {Vec3} position - Vector holding the new world space position.
* @param {Quat} [rotation] - Quaternion holding the new world space rotation.
* @returns {void}
* @example
* // Teleport the entity to the origin
* entity.rigidbody.teleport(pc.Vec3.ZERO);
* @example
* // Teleport the entity to world space coordinate [1, 2, 3] and reset orientation
* const position = new pc.Vec3(1, 2, 3);
* entity.rigidbody.teleport(position, pc.Quat.IDENTITY);
*/
teleport(position: Vec3, rotation?: Quat): void;
}
import { Component } from '../component.js';
import { Vec3 } from '../../../core/math/vec3.js';
import { Quat } from '../../../core/math/quat.js';