diff --git a/src/framework/components/rigid-body/component.js b/src/framework/components/rigid-body/component.js index 2d8d9d5798c..a88f259d7e1 100644 --- a/src/framework/components/rigid-body/component.js +++ b/src/framework/components/rigid-body/component.js @@ -1,8 +1,11 @@ +import { Debug } from '../../../core/debug.js'; + import { Quat } from '../../../core/math/quat.js'; import { Vec3 } from '../../../core/math/vec3.js'; import { BODYFLAG_KINEMATIC_OBJECT, BODYTYPE_STATIC, + BODYFLAG_GRAVITY_WORLD_ENABLE, BODYFLAG_GRAVITY_WORLD_DISABLE, BODYGROUP_DYNAMIC, BODYGROUP_KINEMATIC, BODYGROUP_STATIC, BODYMASK_ALL, BODYMASK_NOT_STATIC, BODYSTATE_ACTIVE_TAG, BODYSTATE_DISABLE_DEACTIVATION, BODYSTATE_DISABLE_SIMULATION, @@ -161,6 +164,22 @@ class RigidBodyComponent extends Component { /** @private */ _type = BODYTYPE_STATIC; + /** + * Whether the RigidBody component uses gravity. + * + * @type {boolean} + * @private + */ + _useGravity = true; + + /** + * The current gravity of this body. + * + * @type {null|Vec3} + * @private + */ + _gravity = null; + /** * Create a new RigidBodyComponent instance. * @@ -572,6 +591,63 @@ class RigidBodyComponent extends Component { return this._type; } + /** + * Whether this rigid body should use gravity. + * + * @type {boolean} + */ + set useGravity(value) { + if (!!value === this._useGravity) { + return; + } + + Debug.assert(typeof Ammo !== 'undefined' && Ammo.btRigidBody.prototype.setFlags, 'pc.RigidBodyComponent.useGravity: Your version of ammo.js does not expose Ammo.btRigidBody#setFlags. Update it to latest.'); + + this._useGravity = !this._useGravity; + + if (this._body) { + this._body.setFlags(this._useGravity && !this._gravity ? BODYFLAG_GRAVITY_WORLD_ENABLE : BODYFLAG_GRAVITY_WORLD_DISABLE); + + if (this._useGravity) { + if (this._gravity) { + _ammoVec1.setValue(this._gravity.x, this._gravity.y, this._gravity.z); + this._body.setGravity(_ammoVec1); + } else { + this._body.setGravity(this.system.dynamicsWorld.getGravity()); + } + } else { + _ammoVec1.setValue(0, 0, 0); + this._body.setGravity(_ammoVec1); + } + } + } + + get useGravity() { + return this._useGravity; + } + + /** + * The gravity that affects this rigid body. Defaults to null to use world gravity. + * + * @type {Vec3} + */ + set gravity(value) { + Debug.assert(typeof Ammo !== 'undefined' && Ammo.btRigidBody.prototype.setFlags, 'pc.RigidBodyComponent#gravity: Your version of ammo.js does not expose Ammo.btRigidBody#setFlags. Update it to latest.'); + + this._gravity = value; + + if (this._body && this._useGravity) { + this._body.setFlags(BODYFLAG_GRAVITY_WORLD_DISABLE); + + _ammoVec1.setValue(value.x, value.y, value.z); + this._body.setGravity(_ammoVec1); + } + } + + get gravity() { + return this._gravity; + } + /** * If the Entity has a Collision shape attached then create a rigid body using this shape. This * method destroys the existing body. @@ -625,6 +701,17 @@ class RigidBodyComponent extends Component { body.setActivationState(BODYSTATE_DISABLE_DEACTIVATION); } + if (this._useGravity && this._gravity) { + Debug.assert(Ammo.btRigidBody.prototype.setFlags, 'pc.RigidBodyComponent#createBody: Your version of ammo.js does not expose Ammo.btRigidBody#setFlags. Update it to latest.'); + body.setFlags(BODYFLAG_GRAVITY_WORLD_DISABLE); + + _ammoVec1.setValue(this._gravity.x, this._gravity.y, this._gravity.z); + body.setGravity(_ammoVec1); + } else if (!this._useGravity) { + Debug.assert(Ammo.btRigidBody.prototype.setFlags, 'pc.RigidBodyComponent#createBody: Your version of ammo.js does not expose Ammo.btRigidBody#setFlags. Update it to latest.'); + body.setFlags(BODYFLAG_GRAVITY_WORLD_DISABLE); + } + body.entity = entity; this.body = body; diff --git a/src/framework/components/rigid-body/constants.js b/src/framework/components/rigid-body/constants.js index 3f4b85bb2f0..d5df9866858 100644 --- a/src/framework/components/rigid-body/constants.js +++ b/src/framework/components/rigid-body/constants.js @@ -35,6 +35,14 @@ export const BODYSTATE_WANTS_DEACTIVATION = 3; export const BODYSTATE_DISABLE_DEACTIVATION = 4; export const BODYSTATE_DISABLE_SIMULATION = 5; +// Gravity flags +export const BODYFLAG_GRAVITY_WORLD_ENABLE = 0; +export const BODYFLAG_GRAVITY_WORLD_DISABLE = 1; +export const BODYFLAG_GRAVITY_GYROSCOPIC_EXPLICIT = 2; +export const BODYFLAG_GRAVITY_GYROSCOPIC_IMPLICIT_WORLD = 4; +export const BODYFLAG_GRAVITY_GYROSCOPIC_IMPLICIT_BODY = 8; +export const BODYFLAG_GRAVITY_GYROSCOPIC_ENABLE = BODYFLAG_GRAVITY_GYROSCOPIC_IMPLICIT_BODY; + // groups export const BODYGROUP_NONE = 0; export const BODYGROUP_DEFAULT = 1; diff --git a/src/framework/components/rigid-body/system.js b/src/framework/components/rigid-body/system.js index d95b1989b86..7ced1f59390 100644 --- a/src/framework/components/rigid-body/system.js +++ b/src/framework/components/rigid-body/system.js @@ -418,7 +418,9 @@ class RigidBodyComponentSystem extends ComponentSystem { 'restitution', 'type', 'group', - 'mask' + 'mask', + 'useGravity', + 'gravity' ]; for (const property of props) { @@ -450,7 +452,9 @@ class RigidBodyComponentSystem extends ComponentSystem { restitution: rigidbody.restitution, type: rigidbody.type, group: rigidbody.group, - mask: rigidbody.mask + mask: rigidbody.mask, + useGravity: rigidbody.useGravity, + gravity: rigidbody.gravity }; return this.addComponent(clone, data);