UNPKG

playcanvas

Version:

PlayCanvas WebGL game engine

587 lines (586 loc) 21.1 kB
/** * 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';