瀏覽代碼

Merge pull request #7202 from CedricGuillemet/physicsSubSteps

physics substeps
David Catuhe 5 年之前
父節點
當前提交
ce5ad269a6

+ 1 - 0
dist/preview release/what's new.md

@@ -105,6 +105,7 @@
 - Update Ammo.js library to allow your own broadphase overlapping pair cache ([MackeyK24](https://github.com/MackeyK24/))
 - Update Ammo.js library for custom impostor shapes. PhysicsImpostor.CustomImposter type and AmmoJSPlugin.OnCreateCustomShape factoty function ([MackeyK24](https://github.com/MackeyK24/))
 - Update Ammo.js library and AmmoJS plugin to support ellipsoid ([CedricGuillemet](https://github.com/CedricGuillemet/))
+- Physics update substeps ([CedricGuillemet](https://github.com/CedricGuillemet))
 
 ### Loaders
 

+ 14 - 0
src/Physics/IPhysicsEngine.ts

@@ -99,6 +99,20 @@ export interface IPhysicsEngine {
     getTimeStep(): number;
 
     /**
+     * Set the sub time step of the physics engine.
+     * Default is 0 meaning there is no sub steps
+     * To increase physics resolution precision, set a small value (like 1 ms)
+     * @param subTimeStep defines the new sub timestep used for physics resolution.
+     */
+    setSubTimeStep(subTimeStep: number) : void;
+
+    /**
+     * Get the sub time step of the physics engine.
+     * @returns the current sub time step
+     */
+    getSubTimeStep(): number;
+
+    /**
      * Release all resources
      */
     dispose(): void;

+ 19 - 0
src/Physics/physicsEngine.ts

@@ -18,6 +18,7 @@ export class PhysicsEngine implements IPhysicsEngine {
 
     private _impostors: Array<PhysicsImpostor> = [];
     private _joints: Array<PhysicsImpostorJoint> = [];
+    private _subTimeStep: number = 0;
 
     /**
      * Gets the gravity vector used by the simulation
@@ -76,6 +77,24 @@ export class PhysicsEngine implements IPhysicsEngine {
     }
 
     /**
+     * Set the sub time step of the physics engine.
+     * Default is 0 meaning there is no sub steps
+     * To increase physics resolution precision, set a small value (like 1 ms)
+     * @param subTimeStep defines the new sub timestep used for physics resolution.
+     */
+    public setSubTimeStep(subTimeStep: number = 0) {
+        this._subTimeStep = subTimeStep;
+    }
+
+    /**
+     * Get the sub time step of the physics engine.
+     * @returns the current sub time step
+     */
+    public getSubTimeStep() {
+        return this._subTimeStep;
+    }
+
+    /**
      * Release all resources
      */
     public dispose(): void {

+ 17 - 3
src/Physics/physicsEngineComponent.ts

@@ -17,6 +17,8 @@ declare module "../scene" {
     export interface Scene {
         /** @hidden (Backing field) */
         _physicsEngine: Nullable<IPhysicsEngine>;
+        /** @hidden */
+        _physicsTimeAccumulator: number;
 
         /**
          * Gets the current physics engine
@@ -89,6 +91,7 @@ Scene.prototype.enablePhysics = function(gravity: Nullable<Vector3> = null, plug
 
     try {
         this._physicsEngine = new PhysicsEngine(gravity, plugin);
+        this._physicsTimeAccumulator = 0;
         return true;
     } catch (e) {
         Logger.Error(e.message);
@@ -132,9 +135,20 @@ Scene.prototype.deleteCompoundImpostor = function(compound: any): void {
 /** @hidden */
 Scene.prototype._advancePhysicsEngineStep = function(step: number) {
     if (this._physicsEngine) {
-        this.onBeforePhysicsObservable.notifyObservers(this);
-        this._physicsEngine._step(step / 1000);
-        this.onAfterPhysicsObservable.notifyObservers(this);
+        let subTime = this._physicsEngine.getSubTimeStep();
+        if (subTime > 0) {
+            this._physicsTimeAccumulator += step;
+            while (this._physicsTimeAccumulator > subTime) {
+                this.onBeforePhysicsObservable.notifyObservers(this);
+                this._physicsEngine._step(subTime / 1000);
+                this.onAfterPhysicsObservable.notifyObservers(this);
+                this._physicsTimeAccumulator -= subTime;
+            }
+        } else {
+            this.onBeforePhysicsObservable.notifyObservers(this);
+            this._physicsEngine._step(step / 1000);
+            this.onAfterPhysicsObservable.notifyObservers(this);
+        }
     }
 };