123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208 |
- module BABYLON {
- export interface PhysicsImpostorJoint {
- mainImpostor: PhysicsImpostor;
- connectedImpostor: PhysicsImpostor;
- joint: PhysicsJoint;
- }
- export class PhysicsEngine {
- public gravity: Vector3;
- constructor(gravity: Nullable<Vector3>, private _physicsPlugin: IPhysicsEnginePlugin = new CannonJSPlugin()) {
- if (!this._physicsPlugin.isSupported()) {
- throw new Error("Physics Engine " + this._physicsPlugin.name + " cannot be found. "
- + "Please make sure it is included.")
- }
- gravity = gravity || new Vector3(0, -9.807, 0)
- this.setGravity(gravity);
- this.setTimeStep();
- }
- public setGravity(gravity: Vector3): void {
- this.gravity = gravity;
- this._physicsPlugin.setGravity(this.gravity);
- }
- /**
- * Set the time step of the physics engine.
- * default is 1/60.
- * To slow it down, enter 1/600 for example.
- * To speed it up, 1/30
- * @param {number} newTimeStep the new timestep to apply to this world.
- */
- public setTimeStep(newTimeStep: number = 1 / 60) {
- this._physicsPlugin.setTimeStep(newTimeStep);
- }
- /**
- * Get the time step of the physics engine.
- */
- public getTimeStep(): number {
- return this._physicsPlugin.getTimeStep();
- }
- public dispose(): void {
- this._impostors.forEach(function (impostor) {
- impostor.dispose();
- })
- this._physicsPlugin.dispose();
- }
- public getPhysicsPluginName(): string {
- return this._physicsPlugin.name;
- }
- // Statics
- public static Epsilon = 0.001;
- //new methods and parameters
- private _impostors: Array<PhysicsImpostor> = [];
- private _joints: Array<PhysicsImpostorJoint> = [];
- /**
- * Adding a new impostor for the impostor tracking.
- * This will be done by the impostor itself.
- * @param {PhysicsImpostor} impostor the impostor to add
- */
- public addImpostor(impostor: PhysicsImpostor) {
- impostor.uniqueId = this._impostors.push(impostor);
- //if no parent, generate the body
- if (!impostor.parent) {
- this._physicsPlugin.generatePhysicsBody(impostor);
- }
- }
- /**
- * Remove an impostor from the engine.
- * This impostor and its mesh will not longer be updated by the physics engine.
- * @param {PhysicsImpostor} impostor the impostor to remove
- */
- public removeImpostor(impostor: PhysicsImpostor) {
- var index = this._impostors.indexOf(impostor);
- if (index > -1) {
- var removed = this._impostors.splice(index, 1);
- //Is it needed?
- if (removed.length) {
- //this will also remove it from the world.
- removed[0].physicsBody = null;
- }
- }
- }
- /**
- * Add a joint to the physics engine
- * @param {PhysicsImpostor} mainImpostor the main impostor to which the joint is added.
- * @param {PhysicsImpostor} connectedImpostor the impostor that is connected to the main impostor using this joint
- * @param {PhysicsJoint} the joint that will connect both impostors.
- */
- public addJoint(mainImpostor: PhysicsImpostor, connectedImpostor: PhysicsImpostor, joint: PhysicsJoint) {
- var impostorJoint = {
- mainImpostor: mainImpostor,
- connectedImpostor: connectedImpostor,
- joint: joint
- }
- joint.physicsPlugin = this._physicsPlugin;
- this._joints.push(impostorJoint);
- this._physicsPlugin.generateJoint(impostorJoint);
- }
- public removeJoint(mainImpostor: PhysicsImpostor, connectedImpostor: PhysicsImpostor, joint: PhysicsJoint) {
- var matchingJoints = this._joints.filter(function (impostorJoint) {
- return (impostorJoint.connectedImpostor === connectedImpostor
- && impostorJoint.joint === joint
- && impostorJoint.mainImpostor === mainImpostor)
- });
- if (matchingJoints.length) {
- this._physicsPlugin.removeJoint(matchingJoints[0]);
- //TODO remove it from the list as well
- }
- }
- /**
- * Called by the scene. no need to call it.
- */
- public _step(delta: number) {
- //check if any mesh has no body / requires an update
- this._impostors.forEach((impostor) => {
- if (impostor.isBodyInitRequired()) {
- this._physicsPlugin.generatePhysicsBody(impostor);
- }
- });
- if (delta > 0.1) {
- delta = 0.1;
- } else if (delta <= 0) {
- delta = 1.0 / 60.0;
- }
- this._physicsPlugin.executeStep(delta, this._impostors);
- }
- public getPhysicsPlugin(): IPhysicsEnginePlugin {
- return this._physicsPlugin;
- }
- public getImpostorForPhysicsObject(object: IPhysicsEnabledObject): Nullable<PhysicsImpostor> {
- for (var i = 0; i < this._impostors.length; ++i) {
- if (this._impostors[i].object === object) {
- return this._impostors[i];
- }
- }
- return null;
- }
- public getImpostorWithPhysicsBody(body: any): Nullable<PhysicsImpostor> {
- for (var i = 0; i < this._impostors.length; ++i) {
- if (this._impostors[i].physicsBody === body) {
- return this._impostors[i];
- }
- }
- return null;
- }
- }
- export interface IPhysicsEnginePlugin {
- world: any;
- name: string;
- setGravity(gravity: Vector3): void;
- setTimeStep(timeStep: number): void;
- getTimeStep(): number;
- executeStep(delta: number, impostors: Array<PhysicsImpostor>): void; //not forgetting pre and post events
- applyImpulse(impostor: PhysicsImpostor, force: Vector3, contactPoint: Vector3): void;
- applyForce(impostor: PhysicsImpostor, force: Vector3, contactPoint: Vector3): void;
- generatePhysicsBody(impostor: PhysicsImpostor): void;
- removePhysicsBody(impostor: PhysicsImpostor): void;
- generateJoint(joint: PhysicsImpostorJoint): void;
- removeJoint(joint: PhysicsImpostorJoint): void;
- isSupported(): boolean;
- setTransformationFromPhysicsBody(impostor: PhysicsImpostor): void;
- setPhysicsBodyTransformation(impostor: PhysicsImpostor, newPosition: Vector3, newRotation: Quaternion): void;
- setLinearVelocity(impostor: PhysicsImpostor, velocity: Vector3): void;
- setAngularVelocity(impostor: PhysicsImpostor, velocity: Vector3): void;
- getLinearVelocity(impostor: PhysicsImpostor) : Vector3;
- getAngularVelocity(impostor: PhysicsImpostor) : Vector3;
- setBodyMass(impostor: PhysicsImpostor, mass: number): void;
- getBodyMass(impostor: PhysicsImpostor): number;
- getBodyFriction(impostor: PhysicsImpostor): number;
- setBodyFriction(impostor: PhysicsImpostor, friction: number): void;
- getBodyRestitution(impostor: PhysicsImpostor): number;
- setBodyRestitution(impostor: PhysicsImpostor, restitution: number): void;
- sleepBody(impostor: PhysicsImpostor): void;
- wakeUpBody(impostor: PhysicsImpostor): void;
- //Joint Update
- updateDistanceJoint(joint: PhysicsJoint, maxDistance:number, minDistance?: number): void;
- setMotor(joint: IMotorEnabledJoint, speed: number, maxForce?: number, motorIndex?: number): void;
- setLimit(joint: IMotorEnabledJoint, upperLimit: number, lowerLimit?: number, motorIndex?: number): void;
- getRadius(impostor: PhysicsImpostor):number;
- getBoxSizeToRef(impostor: PhysicsImpostor, result:Vector3): void;
- syncMeshWithImpostor(mesh:AbstractMesh, impostor:PhysicsImpostor): void;
- dispose(): void;
- }
- }
|