瀏覽代碼

Improved picking memory management

David Catuhe 7 年之前
父節點
當前提交
9824853960
共有 5 個文件被更改,包括 20012 次插入19949 次删除
  1. 9969 9962
      dist/preview release/babylon.d.ts
  2. 9969 9962
      dist/preview release/babylon.module.d.ts
  3. 16 6
      src/Culling/babylon.ray.ts
  4. 18 5
      src/Math/babylon.math.ts
  5. 40 14
      src/babylon.scene.ts

文件差異過大導致無法顯示
+ 9969 - 9962
dist/preview release/babylon.d.ts


文件差異過大導致無法顯示
+ 9969 - 9962
dist/preview release/babylon.module.d.ts


+ 16 - 6
src/Culling/babylon.ray.ts

@@ -331,16 +331,26 @@
             return -1;
         }
 
+        public update(x: number, y: number, viewportWidth: number, viewportHeight: number, world: Matrix, view: Matrix, projection: Matrix): Ray {
+            Vector3.UnprojectFloatsToRef(x, y, 0, viewportWidth, viewportHeight, world, view, projection, this.origin);
+            Vector3.UnprojectFloatsToRef(x, y, 1, viewportWidth, viewportHeight, world, view, projection, Tmp.Vector3[0]);
+
+            Tmp.Vector3[0].subtractToRef(this.origin, this.direction);
+            this.direction.normalize();
+            return this;
+        }
+
         // Statics
-        public static CreateNew(x: number, y: number, viewportWidth: number, viewportHeight: number, world: Matrix, view: Matrix, projection: Matrix): Ray {
-            var start = Vector3.Unproject(new Vector3(x, y, 0), viewportWidth, viewportHeight, world, view, projection);
-            var end = Vector3.Unproject(new Vector3(x, y, 1), viewportWidth, viewportHeight, world, view, projection);
+        public static Zero(): Ray {
+            return new Ray(Vector3.Zero(), Vector3.Zero());
+        }
 
-            var direction = end.subtract(start);
-            direction.normalize();
+        public static CreateNew(x: number, y: number, viewportWidth: number, viewportHeight: number, world: Matrix, view: Matrix, projection: Matrix): Ray {
+            let result = Ray.Zero();
 
-            return new Ray(start, direction);
+            return result.update(x, y, viewportWidth, viewportHeight, world, view, projection);
         }
+        
 
         /**
         * Function will create a new transformed ray starting from origin and ending at the end point. Ray's length will be set, and ray will be

+ 18 - 5
src/Math/babylon.math.ts

@@ -1731,19 +1731,32 @@
         }
 
         public static Unproject(source: Vector3, viewportWidth: number, viewportHeight: number, world: Matrix, view: Matrix, projection: Matrix): Vector3 {
+            let result = Vector3.Zero();
+
+            Vector3.UnprojectToRef(source, viewportWidth, viewportHeight, world, view, projection, result);
+
+            return result;
+        }
+
+        public static UnprojectToRef(source: Vector3, viewportWidth: number, viewportHeight: number, world: Matrix, view: Matrix, projection: Matrix, result: Vector3): void {
+            Vector3.UnprojectFloatsToRef(source.x, source.y, source.z, viewportWidth, viewportHeight, world, view, projection, result);
+        }
+
+        public static UnprojectFloatsToRef(sourceX: float, sourceY: float, sourceZ: float, viewportWidth: number, viewportHeight: number, world: Matrix, view: Matrix, projection: Matrix, result: Vector3): void {
             var matrix = MathTmp.Matrix[0];
             world.multiplyToRef(view, matrix)
             matrix.multiplyToRef(projection, matrix);
             matrix.invert();
-            var screenSource = new Vector3(source.x / viewportWidth * 2 - 1, -(source.y / viewportHeight * 2 - 1), 2 * source.z - 1.0);
-            var vector = Vector3.TransformCoordinates(screenSource, matrix);
+            var screenSource = MathTmp.Vector3[0];
+            screenSource.x = sourceX / viewportWidth * 2 - 1;
+            screenSource.y = sourceY/ viewportHeight * 2 - 1;
+            screenSource.z = 2 * sourceZ - 1.0;
+            Vector3.TransformCoordinatesToRef(screenSource, matrix, result);
             var num = screenSource.x * matrix.m[3] + screenSource.y * matrix.m[7] + screenSource.z * matrix.m[11] + matrix.m[15];
 
             if (Scalar.WithinEpsilon(num, 1.0)) {
-                vector = vector.scale(1.0 / num);
+                result.scaleInPlace(1.0 / num);
             }
-
-            return vector;
         }
 
         public static Minimize(left: Vector3, right: Vector3): Vector3 {

+ 40 - 14
src/babylon.scene.ts

@@ -3981,6 +3981,14 @@
 
         // Picking
         public createPickingRay(x: number, y: number, world: Matrix, camera: Nullable<Camera>, cameraViewSpace = false): Ray {
+            let result = Ray.Zero();
+
+            this.createPickingRayToRef(x, y, world, result, camera, cameraViewSpace);
+
+            return result;
+        }
+
+        public createPickingRayToRef(x: number, y: number, world: Matrix, result: Ray, camera: Nullable<Camera>, cameraViewSpace = false): Scene {
             var engine = this._engine;
 
             if (!camera) {
@@ -3996,13 +4004,22 @@
             // Moving coordinates to local viewport world
             x = x / this._engine.getHardwareScalingLevel() - viewport.x;
             y = y / this._engine.getHardwareScalingLevel() - (this._engine.getRenderHeight() - viewport.y - viewport.height);
-            return Ray.CreateNew(x, y, viewport.width, viewport.height, world ? world : Matrix.Identity(), cameraViewSpace ? Matrix.Identity() : camera.getViewMatrix(), camera.getProjectionMatrix());
-            //       return BABYLON.Ray.CreateNew(x / window.devicePixelRatio, y / window.devicePixelRatio, viewport.width, viewport.height, world ? world : BABYLON.Matrix.Identity(), camera.getViewMatrix(), camera.getProjectionMatrix());
+            
+            result.update(x, y, viewport.width, viewport.height, world ? world : Matrix.Identity(), cameraViewSpace ? Matrix.Identity() : camera.getViewMatrix(), camera.getProjectionMatrix());
+            return this;
+        }
+
+        public createPickingRayInCameraSpace(x: number, y: number, camera?: Camera): Ray {
+            let result = Ray.Zero();
+
+            this.createPickingRayInCameraSpaceToRef(x, y, result, camera);
+
+            return result;
         }
 
-        public createPickingRayInCameraSpace(x: number, y: number, camera?: Camera): Nullable<Ray> {
+        public createPickingRayInCameraSpaceToRef(x: number, y: number, result: Ray, camera?: Camera): Scene {
             if (!BABYLON.PickingInfo) {
-                return null;
+                return this;
             }
 
             var engine = this._engine;
@@ -4021,7 +4038,8 @@
             // Moving coordinates to local viewport world
             x = x / this._engine.getHardwareScalingLevel() - viewport.x;
             y = y / this._engine.getHardwareScalingLevel() - (this._engine.getRenderHeight() - viewport.y - viewport.height);
-            return Ray.CreateNew(x, y, viewport.width, viewport.height, identity, identity, camera.getProjectionMatrix());
+            result.update(x, y, viewport.width, viewport.height, identity, identity, camera.getProjectionMatrix());
+            return this;
         }
 
         private _internalPick(rayFunction: (world: Matrix) => Ray, predicate?: (mesh: AbstractMesh) => boolean, fastCheck?: boolean): Nullable<PickingInfo> {
@@ -4133,6 +4151,8 @@
             return pickingInfo || new PickingInfo();
         }
 
+        private _tempPickingRay: Ray;
+
         /** Launch a ray to try to pick a mesh in the scene
          * @param x position on screen
          * @param y position on screen
@@ -4141,7 +4161,14 @@
          * @param camera to use for computing the picking ray. Can be set to null. In this case, the scene.activeCamera will be used
          */
         public pick(x: number, y: number, predicate?: (mesh: AbstractMesh) => boolean, fastCheck?: boolean, camera?: Nullable<Camera>): Nullable<PickingInfo> {
-            return this._internalPick(world => this.createPickingRay(x, y, world, camera || null), predicate, fastCheck);
+            if (!this._tempPickingRay) {
+                this._tempPickingRay = Ray.Zero();
+            }
+
+            return this._internalPick(world => {
+                this.createPickingRayToRef(x, y, world, this._tempPickingRay, camera || null);
+                return this._tempPickingRay;
+            }, predicate, fastCheck);
         }
 
         /** Launch a ray to try to pick a sprite in the scene
@@ -4152,13 +4179,12 @@
          * @param camera camera to use for computing the picking ray. Can be set to null. In this case, the scene.activeCamera will be used
          */
         public pickSprite(x: number, y: number, predicate?: (sprite: Sprite) => boolean, fastCheck?: boolean, camera?: Camera): Nullable<PickingInfo> {
-            let ray = this.createPickingRayInCameraSpace(x, y, camera);
-
-            if (!ray) {
-                return null;
-            }
+            if (!this._tempPickingRay) {
+                this._tempPickingRay = Ray.Zero();
+            }            
+            this.createPickingRayInCameraSpaceToRef(x, y, this._tempPickingRay, camera);
 
-            return this._internalPickSprites(ray, predicate, fastCheck, camera);
+            return this._internalPickSprites(this._tempPickingRay, predicate, fastCheck, camera);
         }
 
         private _cachedRayForTransform: Ray;
@@ -4176,7 +4202,7 @@
                 world.invertToRef(this._pickWithRayInverseMatrix);
 
                 if (!this._cachedRayForTransform) {
-                    this._cachedRayForTransform = new Ray(Vector3.Zero(), Vector3.Zero());
+                    this._cachedRayForTransform = Ray.Zero();
                 }
                 
                 Ray.TransformToRef(ray, this._pickWithRayInverseMatrix, this._cachedRayForTransform);
@@ -4208,7 +4234,7 @@
                 world.invertToRef(this._pickWithRayInverseMatrix);
 
                 if (!this._cachedRayForTransform) {
-                    this._cachedRayForTransform = new Ray(Vector3.Zero(), Vector3.Zero());
+                    this._cachedRayForTransform = Ray.Zero();
                 }
                 
                 Ray.TransformToRef(ray, this._pickWithRayInverseMatrix, this._cachedRayForTransform);