فهرست منبع

Merge branch 'master' of https://github.com/BabylonJS/Babylon.js

David Catuhe 6 سال پیش
والد
کامیت
09c9ed0566

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

@@ -16,6 +16,7 @@
 - Individual gizmos can now be enabled/disabled ([Balupg](https://github.com/balupg))
 - Unify preparation of instance attributes. Added `MaterialHelper.PushAttributesForInstances` ([MarkusBillharz](https://github.com/MarkusBillharz))
 - Added support for PBR [irradiance map](https://doc.babylonjs.com/how_to/physically_based_rendering_master#irradiance-map)
+- Ability to set render camera on utility layer instead of using the latest active camera ([TrevorDev](https://github.com/TrevorDev))
 
 ### Engine
 - Added preprocessors for shaders to improve how shaders are compiled for WebGL1/2 or WebGPU ([Deltakosh](https://github.com/deltakosh/))
@@ -40,6 +41,7 @@
 
 ### Physics
 - Update Ammo.js library to support global collision contact callbacks ([MackeyK24](https://github.com/MackeyK24/))
+- Update AmmoJSPlugin to allow your own broadphase overlapping pair cache ([MackeyK24](https://github.com/MackeyK24/))
 
 ## Bug fixes
 - Added support for `AnimationGroup` serialization ([Drigax](https://github.com/drigax/))

+ 21 - 10
src/Behaviors/Meshes/sixDofDragBehavior.ts

@@ -74,6 +74,17 @@ export class SixDofDragBehavior implements Behavior<Mesh> {
     public init() { }
 
     /**
+     * In the case of multiplea active cameras, the cameraToUseForPointers should be used if set instead of active camera
+     */
+    private get _pointerCamera() {
+        if (this._scene.cameraToUseForPointers) {
+            return this._scene.cameraToUseForPointers;
+        }else {
+            return this._scene.activeCamera;
+        }
+    }
+
+    /**
      * Attaches the scale behavior the passed in mesh
      * @param ownerNode The mesh that will be scaled around once attached
      */
@@ -102,8 +113,8 @@ export class SixDofDragBehavior implements Behavior<Mesh> {
         this._pointerObserver = this._scene.onPointerObservable.add((pointerInfo, eventState) => {
             if (pointerInfo.type == PointerEventTypes.POINTERDOWN) {
                 if (!this.dragging && pointerInfo.pickInfo && pointerInfo.pickInfo.hit && pointerInfo.pickInfo.pickedMesh && pointerInfo.pickInfo.ray && pickPredicate(pointerInfo.pickInfo.pickedMesh)) {
-                    if (this._scene.activeCamera && this._scene.activeCamera.cameraRigMode == Camera.RIG_MODE_NONE) {
-                        pointerInfo.pickInfo.ray.origin.copyFrom(this._scene.activeCamera!.globalPosition);
+                    if (this._pointerCamera && this._pointerCamera.cameraRigMode == Camera.RIG_MODE_NONE) {
+                        pointerInfo.pickInfo.ray.origin.copyFrom(this._pointerCamera!.globalPosition);
                     }
 
                     pickedMesh = this._ownerNode;
@@ -133,10 +144,10 @@ export class SixDofDragBehavior implements Behavior<Mesh> {
                     this.currentDraggingPointerID = (<PointerEvent>pointerInfo.event).pointerId;
 
                     // Detatch camera controls
-                    if (this.detachCameraControls && this._scene.activeCamera && !this._scene.activeCamera.leftCamera) {
-                        if (this._scene.activeCamera.inputs.attachedElement) {
-                            attachedElement = this._scene.activeCamera.inputs.attachedElement;
-                            this._scene.activeCamera.detachControl(this._scene.activeCamera.inputs.attachedElement);
+                    if (this.detachCameraControls && this._pointerCamera && !this._pointerCamera.leftCamera) {
+                        if (this._pointerCamera.inputs.attachedElement) {
+                            attachedElement = this._pointerCamera.inputs.attachedElement;
+                            this._pointerCamera.detachControl(this._pointerCamera.inputs.attachedElement);
                         } else {
                             attachedElement = null;
                         }
@@ -153,16 +164,16 @@ export class SixDofDragBehavior implements Behavior<Mesh> {
                     this._virtualOriginMesh.removeChild(this._virtualDragMesh);
 
                     // Reattach camera controls
-                    if (this.detachCameraControls && attachedElement && this._scene.activeCamera && !this._scene.activeCamera.leftCamera) {
-                        this._scene.activeCamera.attachControl(attachedElement, true);
+                    if (this.detachCameraControls && attachedElement && this._pointerCamera && !this._pointerCamera.leftCamera) {
+                        this._pointerCamera.attachControl(attachedElement, true);
                     }
                     this.onDragEndObservable.notifyObservers({});
                 }
             } else if (pointerInfo.type == PointerEventTypes.POINTERMOVE) {
                 if (this.currentDraggingPointerID == (<PointerEvent>pointerInfo.event).pointerId && this.dragging && pointerInfo.pickInfo && pointerInfo.pickInfo.ray && pickedMesh) {
                     var zDragFactor = this.zDragFactor;
-                    if (this._scene.activeCamera && this._scene.activeCamera.cameraRigMode == Camera.RIG_MODE_NONE) {
-                        pointerInfo.pickInfo.ray.origin.copyFrom(this._scene.activeCamera!.globalPosition);
+                    if (this._pointerCamera && this._pointerCamera.cameraRigMode == Camera.RIG_MODE_NONE) {
+                        pointerInfo.pickInfo.ray.origin.copyFrom(this._pointerCamera!.globalPosition);
                         zDragFactor = 0;
                     }
 

+ 14 - 0
src/Gizmos/gizmoManager.ts

@@ -48,6 +48,20 @@ export class GizmoManager implements IDisposable {
     public usePointerToAttachGizmos = true;
 
     /**
+     * Utility layer that the bounding box gizmo belongs to
+     */
+    public get keepDepthUtilityLayer() {
+        return this._defaultKeepDepthUtilityLayer;
+    }
+
+    /**
+     * Utility layer that all gizmos besides bounding box belong to
+     */
+    public get utilityLayer() {
+        return this._defaultUtilityLayer;
+    }
+
+    /**
      * Instatiates a gizmo manager
      * @param scene the scene to overlay the gizmos on top of
      */

+ 3 - 2
src/Physics/Plugins/ammoJSPlugin.ts

@@ -63,8 +63,9 @@ export class AmmoJSPlugin implements IPhysicsEnginePlugin {
      * Initializes the ammoJS plugin
      * @param _useDeltaForWorldStep if the time between frames should be used when calculating physics steps (Default: true)
      * @param ammoInjection can be used to inject your own ammo reference
+     * @param overlappingPairCache can be used to specify your own overlapping pair cache
      */
-    public constructor(private _useDeltaForWorldStep: boolean = true, ammoInjection: any = Ammo) {
+    public constructor(private _useDeltaForWorldStep: boolean = true, ammoInjection: any = Ammo, overlappingPairCache: any = null) {
         if (typeof ammoInjection === "function") {
             ammoInjection(this.bjsAMMO);
         } else {
@@ -79,7 +80,7 @@ export class AmmoJSPlugin implements IPhysicsEnginePlugin {
         // Initialize the physics world
         this._collisionConfiguration = new this.bjsAMMO.btSoftBodyRigidBodyCollisionConfiguration();
         this._dispatcher = new this.bjsAMMO.btCollisionDispatcher(this._collisionConfiguration);
-        this._overlappingPairCache = new this.bjsAMMO.btDbvtBroadphase();
+        this._overlappingPairCache = overlappingPairCache || new this.bjsAMMO.btDbvtBroadphase();
         this._solver = new this.bjsAMMO.btSequentialImpulseConstraintSolver();
         this._softBodySolver = new this.bjsAMMO.btDefaultSoftBodySolver();
         this.world = new this.bjsAMMO.btSoftRigidDynamicsWorld(this._dispatcher, this._overlappingPairCache, this._solver, this._collisionConfiguration, this._softBodySolver);

+ 32 - 9
src/Rendering/utilityLayerRenderer.ts

@@ -7,6 +7,7 @@ import { AbstractMesh } from "../Meshes/abstractMesh";
 import { EngineStore } from "../Engines/engineStore";
 import { HemisphericLight } from '../Lights/hemisphericLight';
 import { Vector3, Color3 } from '../Maths/math';
+import { Camera } from '../Cameras/camera';
 
 /**
  * Renders a layer on top of an existing scene
@@ -17,6 +18,30 @@ export class UtilityLayerRenderer implements IDisposable {
     private static _DefaultUtilityLayer: Nullable<UtilityLayerRenderer> = null;
     private static _DefaultKeepDepthUtilityLayer: Nullable<UtilityLayerRenderer> = null;
     private _sharedGizmoLight: Nullable<HemisphericLight> = null;
+
+    private _renderCamera: Nullable<Camera> = null;
+
+    /**
+     * Gets the camera that is used to render the utility layer (when not set, this will be the last active camera)
+     * @returns the camera that is used when rendering the utility layer
+     */
+    public getRenderCamera() {
+        if (this._renderCamera) {
+            return this._renderCamera;
+        } else if (this.originalScene.activeCameras.length > 1) {
+            return this.originalScene.activeCameras[this.originalScene.activeCameras.length - 1];
+        } else {
+            return this.originalScene.activeCamera;
+        }
+    }
+    /**
+     * Sets the camera that should be used when rendering the utility layer (If set to null the last active camera will be used)
+     * @param cam the camera that should be used when rendering the utility layer
+     */
+    public setRenderCamera(cam: Nullable<Camera>) {
+        this._renderCamera = cam;
+    }
+
     /**
      * @hidden
      * Light which used by gizmos to get light shading
@@ -87,7 +112,7 @@ export class UtilityLayerRenderer implements IDisposable {
     /** Gets or sets a predicate that will be used to indicate utility meshes present in the main scene */
     public mainSceneTrackerPredicate: (mesh: Nullable<AbstractMesh>) => boolean;
 
-    private _afterRenderObserver: Nullable<Observer<Scene>>;
+    private _afterRenderObserver: Nullable<Observer<Camera>>;
     private _sceneDisposeObserver: Nullable<Observer<Scene>>;
     private _originalPointerObserver: Nullable<Observer<PointerInfoPre>>;
     /**
@@ -212,8 +237,9 @@ export class UtilityLayerRenderer implements IDisposable {
         // Render directly on top of existing scene without clearing
         this.utilityLayerScene.autoClear = false;
 
-        this._afterRenderObserver = this.originalScene.onAfterRenderObservable.add(() => {
-            if (this.shouldRender) {
+        this._afterRenderObserver = this.originalScene.onAfterCameraRenderObservable.add((camera) => {
+            // Only render when the render camera finishes rendering
+            if (this.shouldRender && camera == this.getRenderCamera()) {
                 this.render();
             }
         });
@@ -270,7 +296,7 @@ export class UtilityLayerRenderer implements IDisposable {
         this.onPointerOutObservable.clear();
 
         if (this._afterRenderObserver) {
-            this.originalScene.onAfterRenderObservable.remove(this._afterRenderObserver);
+            this.originalScene.onAfterCameraRenderObservable.remove(this._afterRenderObserver);
         }
         if (this._sceneDisposeObserver) {
             this.originalScene.onDisposeObservable.remove(this._sceneDisposeObserver);
@@ -282,10 +308,7 @@ export class UtilityLayerRenderer implements IDisposable {
     }
 
     private _updateCamera() {
-        if (this.originalScene.activeCameras.length > 1) {
-            this.utilityLayerScene.activeCamera = this.originalScene.activeCameras[this.originalScene.activeCameras.length - 1];
-        } else {
-            this.utilityLayerScene.activeCamera = this.originalScene.activeCamera;
-        }
+        this.utilityLayerScene.cameraToUseForPointers = this.getRenderCamera();
+        this.utilityLayerScene.activeCamera = this.getRenderCamera();
     }
 }

+ 7 - 0
src/scene.ts

@@ -367,6 +367,11 @@ export class Scene extends AbstractScene implements IAnimatable {
     */
     public onAfterRenderObservable = new Observable<Scene>();
 
+    /**
+    * An event triggered after rendering the scene for an active camera (When scene.render is called this will be called after each camera)
+    */
+   public onAfterRenderCameraObservable = new Observable<Camera>();
+
     private _onAfterRenderObserver: Nullable<Observer<Scene>> = null;
     /** Sets a function to be executed after rendering this scene */
     public set afterRender(callback: Nullable<() => void>) {
@@ -3537,6 +3542,7 @@ export class Scene extends AbstractScene implements IAnimatable {
     private _processSubCameras(camera: Camera): void {
         if (camera.cameraRigMode === Camera.RIG_MODE_NONE || (camera.outputRenderTarget && camera.outputRenderTarget.getViewCount() > 1 && this.getEngine().getCaps().multiview)) {
             this._renderForCamera(camera);
+            this.onAfterRenderCameraObservable.notifyObservers(camera);
             return;
         }
 
@@ -3552,6 +3558,7 @@ export class Scene extends AbstractScene implements IAnimatable {
         // Use _activeCamera instead of activeCamera to avoid onActiveCameraChanged
         this._activeCamera = camera;
         this.setTransformMatrix(this._activeCamera.getViewMatrix(), this._activeCamera.getProjectionMatrix());
+        this.onAfterRenderCameraObservable.notifyObservers(camera);
     }
 
     private _checkIntersections(): void {