瀏覽代碼

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

David Catuhe 7 年之前
父節點
當前提交
a7fc28ae4c

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

@@ -68,6 +68,7 @@
 
 
 ### Core Engine
 ### Core Engine
 
 
+- Improved the way world matrices were computed ([Deltakosh](https://github.com/deltakosh))
 - Added `scene.rootNodes` to track root nodes (ie. nodes with no parent) ([Deltakosh](https://github.com/deltakosh))
 - Added `scene.rootNodes` to track root nodes (ie. nodes with no parent) ([Deltakosh](https://github.com/deltakosh))
 - Added `scene.pickSpriteWithRay` function ([Deltakosh](https://github.com/deltakosh))
 - Added `scene.pickSpriteWithRay` function ([Deltakosh](https://github.com/deltakosh))
 - Added support for multiple clip planes. [Demo](https://www.babylonjs-playground.com/#Y6W087) ([Deltakosh](https://github.com/deltakosh))
 - Added support for multiple clip planes. [Demo](https://www.babylonjs-playground.com/#Y6W087) ([Deltakosh](https://github.com/deltakosh))

+ 0 - 1
src/Cameras/babylon.camera.ts

@@ -166,7 +166,6 @@
         private _computedViewMatrix = Matrix.Identity();
         private _computedViewMatrix = Matrix.Identity();
         public _projectionMatrix = new Matrix();
         public _projectionMatrix = new Matrix();
         private _doNotComputeProjectionMatrix = false;
         private _doNotComputeProjectionMatrix = false;
-        private _worldMatrix = Matrix.Identity();
         public _postProcesses = new Array<Nullable<PostProcess>>();
         public _postProcesses = new Array<Nullable<PostProcess>>();
         private _transformMatrix = Matrix.Zero();
         private _transformMatrix = Matrix.Zero();
 
 

+ 6 - 5
src/Lights/babylon.hemisphericLight.ts

@@ -19,9 +19,7 @@
          * The light reflection direction, not the incoming direction.
          * The light reflection direction, not the incoming direction.
          */
          */
         @serializeAsVector3()
         @serializeAsVector3()
-        public direction: Vector3
-
-        private _worldMatrix: Matrix;
+        public direction: Vector3;
 
 
         /**
         /**
          * Creates a HemisphericLight object in the scene according to the passed direction (Vector3).  
          * Creates a HemisphericLight object in the scene according to the passed direction (Vector3).  
@@ -93,9 +91,12 @@
         }
         }
 
 
         /**
         /**
-         * @hidden internal use only.
+         * Computes the world matrix of the node
+         * @param force defines if the cache version should be invalidated forcing the world matrix to be created from scratch
+         * @param useWasUpdatedFlag defines a reserved property
+         * @returns the world matrix
          */
          */
-        public _getWorldMatrix(): Matrix {
+        public computeWorldMatrix(force?: boolean, useWasUpdatedFlag?: boolean): Matrix {
             if (!this._worldMatrix) {
             if (!this._worldMatrix) {
                 this._worldMatrix = Matrix.Identity();
                 this._worldMatrix = Matrix.Identity();
             }
             }

+ 0 - 32
src/Lights/babylon.light.ts

@@ -301,8 +301,6 @@ module BABYLON {
             this._markMeshesAsLightDirty();
             this._markMeshesAsLightDirty();
         }
         }
 
 
-        private _parentedWorldMatrix: Matrix;
-
         /**
         /**
          * Shadow generator associted to the light.
          * Shadow generator associted to the light.
          * @hidden Internal use only.
          * @hidden Internal use only.
@@ -354,11 +352,6 @@ module BABYLON {
         public abstract transferToEffect(effect: Effect, lightIndex: string): Light;
         public abstract transferToEffect(effect: Effect, lightIndex: string): Light;
 
 
         /**
         /**
-         * @hidden internal use only.
-         */
-        public abstract _getWorldMatrix(): Matrix;
-
-        /**
          * Returns the string "Light".
          * Returns the string "Light".
          * @returns the class name
          * @returns the class name
          */
          */
@@ -440,31 +433,6 @@ module BABYLON {
         }
         }
 
 
         /**
         /**
-         * Computes and Returns the light World matrix.
-         * @returns the world matrix 
-         */
-        public getWorldMatrix(): Matrix {
-            this._currentRenderId = this.getScene().getRenderId();
-            this._childRenderId = this._currentRenderId;
-
-            var worldMatrix = this._getWorldMatrix();
-
-            if (this.parent && this.parent.getWorldMatrix) {
-                if (!this._parentedWorldMatrix) {
-                    this._parentedWorldMatrix = Matrix.Identity();
-                }
-
-                worldMatrix.multiplyToRef(this.parent.getWorldMatrix(), this._parentedWorldMatrix);
-
-                this._markSyncedWithParent();
-
-                return this._parentedWorldMatrix;
-            }
-
-            return worldMatrix;
-        }
-
-        /**
 		 * Sort function to order lights for rendering.
 		 * Sort function to order lights for rendering.
 		 * @param a First Light object to compare to second.
 		 * @param a First Light object to compare to second.
 		 * @param b Second Light object to compare first.
 		 * @param b Second Light object to compare first.

+ 38 - 4
src/Lights/babylon.shadowLight.ts

@@ -206,7 +206,6 @@
          */
          */
         public transformedDirection: Vector3;
         public transformedDirection: Vector3;
 
 
-        private _worldMatrix: Matrix;
         private _needProjectionMatrixCompute: boolean = true;
         private _needProjectionMatrixCompute: boolean = true;
 
 
         /**
         /**
@@ -301,17 +300,52 @@
             this._needProjectionMatrixCompute = true;
             this._needProjectionMatrixCompute = true;
         }
         }
 
 
+        /** @hidden */
+        public _initCache() {
+            super._initCache();
+
+            this._cache.position = Vector3.Zero();
+        }
+
+        /** @hidden */
+        public _isSynchronized(): boolean {
+            if (!this._cache.position.equals(this.position))
+                return false;
+
+            return true;
+        }        
+
         /**
         /**
-         * Get the world matrix of the sahdow lights.
-         * @hidden Internal Use Only
+         * Computes the world matrix of the node
+         * @param force defines if the cache version should be invalidated forcing the world matrix to be created from scratch
+         * @param useWasUpdatedFlag defines a reserved property
+         * @returns the world matrix
          */
          */
-        public _getWorldMatrix(): Matrix {
+        public computeWorldMatrix(force?: boolean, useWasUpdatedFlag?: boolean): Matrix {
+            if (!force && this.isSynchronized(useWasUpdatedFlag)) {
+                this._currentRenderId = this.getScene().getRenderId();
+                return this._worldMatrix;
+            }
+
+            this._updateCache();
+            this._cache.position.copyFrom(this.position);
+            this._worldMatrixWasUpdated = true;
+
             if (!this._worldMatrix) {
             if (!this._worldMatrix) {
                 this._worldMatrix = Matrix.Identity();
                 this._worldMatrix = Matrix.Identity();
             }
             }
 
 
             Matrix.TranslationToRef(this.position.x, this.position.y, this.position.z, this._worldMatrix);
             Matrix.TranslationToRef(this.position.x, this.position.y, this.position.z, this._worldMatrix);
 
 
+            if (this.parent && this.parent.getWorldMatrix) {
+                this._worldMatrix.multiplyToRef(this.parent.getWorldMatrix(), this._worldMatrix);
+
+                this._markSyncedWithParent();
+            }            
+
+            // Cache the determinant
+            this._worldMatrixDeterminant = this._worldMatrix.determinant();
+
             return this._worldMatrix;
             return this._worldMatrix;
         }
         }
 
 

+ 1 - 1
src/Mesh/babylon.subMesh.ts

@@ -67,7 +67,7 @@
         }
         }
 
 
         public get IsGlobal(): boolean {
         public get IsGlobal(): boolean {
-            return (this.verticesStart === 0 && this.verticesCount == this._mesh.getTotalVertices());
+            return (this.verticesStart === 0 && this.verticesCount === this._mesh.getTotalVertices());
         }
         }
 
 
         /**
         /**

+ 37 - 56
src/Mesh/babylon.transformNode.ts

@@ -14,13 +14,16 @@ module BABYLON {
         private _rightInverted = new Vector3(-1, 0, 0);
         private _rightInverted = new Vector3(-1, 0, 0);
 
 
         // Properties
         // Properties
-        @serializeAsVector3()
+        @serializeAsVector3("position")
+        private _position = Vector3.Zero();
+
+        @serializeAsVector3("rotation")
         private _rotation = Vector3.Zero();
         private _rotation = Vector3.Zero();
 
 
-        @serializeAsQuaternion()
+        @serializeAsQuaternion("rotationQuaternion")
         private _rotationQuaternion: Nullable<Quaternion>;
         private _rotationQuaternion: Nullable<Quaternion>;
 
 
-        @serializeAsVector3()
+        @serializeAsVector3("scaling")
         protected _scaling = Vector3.One();
         protected _scaling = Vector3.One();
         protected _isDirty = false;
         protected _isDirty = false;
         private _transformToBoneReferal: Nullable<TransformNode>;
         private _transformToBoneReferal: Nullable<TransformNode>;
@@ -53,17 +56,11 @@ module BABYLON {
         @serialize()
         @serialize()
         public ignoreNonUniformScaling = false;
         public ignoreNonUniformScaling = false;
 
 
-        @serializeAsVector3()
-        public position = Vector3.Zero();
-
         // Cache      
         // Cache      
         /** @hidden */
         /** @hidden */
         public _poseMatrix: Matrix;
         public _poseMatrix: Matrix;
         private _localWorld = Matrix.Zero();
         private _localWorld = Matrix.Zero();
-        /** @hidden */
-        public _worldMatrix = Matrix.Zero();
-        /** @hidden */
-        public _worldMatrixDeterminant = 0;
+
         private _absolutePosition = Vector3.Zero();
         private _absolutePosition = Vector3.Zero();
         private _pivotMatrix = Matrix.Identity();
         private _pivotMatrix = Matrix.Identity();
         private _pivotMatrixInverse: Matrix;
         private _pivotMatrixInverse: Matrix;
@@ -93,9 +90,20 @@ module BABYLON {
         }
         }
 
 
         /**
         /**
-          * Rotation property : a Vector3 depicting the rotation value in radians around each local axis X, Y, Z. 
-          * If rotation quaternion is set, this Vector3 will (almost always) be the Zero vector!
-          * Default : (0.0, 0.0, 0.0)
+          * Gets or set the node position (default is (0.0, 0.0, 0.0))
+          */
+         public get position(): Vector3 {
+            return this._position;
+        }
+
+        public set position(newPosition: Vector3) {
+            this._position = newPosition;
+            this._isDirty = true;
+        }        
+
+        /**
+          * Gets or sets the rotation property : a Vector3 defining the rotation value in radians around each local axis X, Y, Z  (default is (0.0, 0.0, 0.0)).
+          * If rotation quaternion is set, this Vector3 will be ignored and copy from the quaternion
           */
           */
         public get rotation(): Vector3 {
         public get rotation(): Vector3 {
             return this._rotation;
             return this._rotation;
@@ -103,28 +111,24 @@ module BABYLON {
 
 
         public set rotation(newRotation: Vector3) {
         public set rotation(newRotation: Vector3) {
             this._rotation = newRotation;
             this._rotation = newRotation;
+            this._isDirty = true;
         }
         }
 
 
         /**
         /**
-         * Scaling property : a Vector3 depicting the mesh scaling along each local axis X, Y, Z.  
-         * Default : (1.0, 1.0, 1.0)
+         * Gets or sets the scaling property : a Vector3 defining the node scaling along each local axis X, Y, Z (default is (0.0, 0.0, 0.0)).
          */
          */
         public get scaling(): Vector3 {
         public get scaling(): Vector3 {
             return this._scaling;
             return this._scaling;
         }
         }
 
 
-        /**
-         * Scaling property : a Vector3 depicting the mesh scaling along each local axis X, Y, Z.  
-         * Default : (1.0, 1.0, 1.0)
-        */
         public set scaling(newScaling: Vector3) {
         public set scaling(newScaling: Vector3) {
             this._scaling = newScaling;
             this._scaling = newScaling;
+            this._isDirty = true;
         }
         }
 
 
         /**
         /**
-         * Rotation Quaternion property : this a Quaternion object depicting the mesh rotation by using a unit quaternion. 
-         * It's null by default.  
-         * If set, only the rotationQuaternion is then used to compute the mesh rotation and its property `.rotation\ is then ignored and set to (0.0, 0.0, 0.0)
+         * Gets or sets the rotation Quaternion property : this a Quaternion object defining the node rotation by using a unit quaternion (null by default).
+         * If set, only the rotationQuaternion is then used to compute the node rotation (ie. node.rotation will be ignored)
          */
          */
         public get rotationQuaternion(): Nullable<Quaternion> {
         public get rotationQuaternion(): Nullable<Quaternion> {
             return this._rotationQuaternion;
             return this._rotationQuaternion;
@@ -169,30 +173,6 @@ module BABYLON {
         }
         }
 
 
         /**
         /**
-         * Returns the latest update of the World matrix
-         * Returns a Matrix.  
-         */
-        public getWorldMatrix(): Matrix {
-            if (this._currentRenderId !== this.getScene().getRenderId()) {
-                this.computeWorldMatrix();
-            }
-            return this._worldMatrix;
-        }
-
-        /** @hidden */
-        public _getWorldMatrixDeterminant(): number {
-            return this._worldMatrixDeterminant;
-        }
-
-        /**
-         * Returns directly the latest state of the mesh World matrix. 
-         * A Matrix is returned.    
-         */
-        public get worldMatrixFromCache(): Matrix {
-            return this._worldMatrix;
-        }
-
-        /**
          * Copies the parameter passed Matrix into the mesh Pose matrix.  
          * Copies the parameter passed Matrix into the mesh Pose matrix.  
          * Returns the TransformNode.  
          * Returns the TransformNode.  
          */
          */
@@ -226,7 +206,7 @@ module BABYLON {
                 return false;
                 return false;
             }
             }
 
 
-            if (!this._cache.position.equals(this.position))
+            if (!this._cache.position.equals(this._position))
                 return false;
                 return false;
 
 
             if (this._rotationQuaternion) {
             if (this._rotationQuaternion) {
@@ -234,10 +214,10 @@ module BABYLON {
                     return false;
                     return false;
             }
             }
 
 
-            if (!this._cache.rotation.equals(this.rotation))
+            if (!this._cache.rotation.equals(this._rotation))
                 return false;
                 return false;
 
 
-            if (!this._cache.scaling.equals(this.scaling))
+            if (!this._cache.scaling.equals(this._scaling))
                 return false;
                 return false;
 
 
             return true;
             return true;
@@ -753,22 +733,22 @@ module BABYLON {
         }
         }
 
 
         /**
         /**
-         * Computes the mesh World matrix and returns it.  
-         * If the mesh world matrix is frozen, this computation does nothing more than returning the last frozen values.  
-         * If the parameter `force` is let to `false` (default), the current cached World matrix is returned. 
-         * If the parameter `force`is set to `true`, the actual computation is done.  
-         * Returns the mesh World Matrix.
+         * Computes the world matrix of the node
+         * @param force defines if the cache version should be invalidated forcing the world matrix to be created from scratch
+         * @param useWasUpdatedFlag defines a reserved property
+         * @returns the world matrix
          */
          */
-        public computeWorldMatrix(force?: boolean): Matrix {
+        public computeWorldMatrix(force?: boolean, useWasUpdatedFlag?: boolean): Matrix {
             if (this._isWorldMatrixFrozen) {
             if (this._isWorldMatrixFrozen) {
                 return this._worldMatrix;
                 return this._worldMatrix;
             }
             }
 
 
-            if (!force && this.isSynchronized(true)) {
+            if (!force && this.isSynchronized(useWasUpdatedFlag)) {
                 this._currentRenderId = this.getScene().getRenderId();
                 this._currentRenderId = this.getScene().getRenderId();
                 return this._worldMatrix;
                 return this._worldMatrix;
             }
             }
 
 
+            this._updateCache();
             this._cache.position.copyFrom(this.position);
             this._cache.position.copyFrom(this.position);
             this._cache.scaling.copyFrom(this.scaling);
             this._cache.scaling.copyFrom(this.scaling);
             this._cache.pivotMatrixUpdated = false;
             this._cache.pivotMatrixUpdated = false;
@@ -776,6 +756,7 @@ module BABYLON {
             this._currentRenderId = this.getScene().getRenderId();
             this._currentRenderId = this.getScene().getRenderId();
             this._childRenderId = this.getScene().getRenderId();
             this._childRenderId = this.getScene().getRenderId();
             this._isDirty = false;
             this._isDirty = false;
+            this._worldMatrixWasUpdated = true;
 
 
             // Scaling
             // Scaling
             Matrix.ScalingToRef(this.scaling.x * this.scalingDeterminant, this.scaling.y * this.scalingDeterminant, this.scaling.z * this.scalingDeterminant, Tmp.Matrix[1]);
             Matrix.ScalingToRef(this.scaling.x * this.scalingDeterminant, this.scaling.y * this.scalingDeterminant, this.scaling.z * this.scalingDeterminant, Tmp.Matrix[1]);

+ 46 - 20
src/babylon.node.ts

@@ -104,6 +104,14 @@
         private _parentNode: Nullable<Node>;
         private _parentNode: Nullable<Node>;
         private _children: Node[];
         private _children: Node[];
 
 
+        /** @hidden */
+        public _worldMatrixWasUpdated = false;
+
+        /** @hidden */
+        public _worldMatrix = Matrix.Zero();
+        /** @hidden */
+        public _worldMatrixDeterminant = 0;        
+
         /**
         /**
          * Gets a boolean indicating if the node has been disposed
          * Gets a boolean indicating if the node has been disposed
          * @returns true if the node was disposed
          * @returns true if the node was disposed
@@ -304,19 +312,32 @@
             return null;
             return null;
         }
         }
 
 
+
         /**
         /**
-         * Returns the world matrix of the node
-         * @returns a matrix containing the node's world matrix
+         * Returns the latest update of the World matrix
+         * @returns a Matrix
          */
          */
         public getWorldMatrix(): Matrix {
         public getWorldMatrix(): Matrix {
-            return Matrix.Identity();
+            if (this._currentRenderId !== this.getScene().getRenderId()) {
+                this.computeWorldMatrix();
+            }
+            return this._worldMatrix;
         }
         }
 
 
+
         /** @hidden */
         /** @hidden */
         public _getWorldMatrixDeterminant(): number {
         public _getWorldMatrixDeterminant(): number {
-            return 1;
+            return this._worldMatrixDeterminant;
         }
         }
 
 
+        /**
+         * Returns directly the latest state of the mesh World matrix. 
+         * A Matrix is returned.    
+         */
+        public get worldMatrixFromCache(): Matrix {
+            return this._worldMatrix;
+        }        
+
         // override it in derived class if you add new variables to the cache
         // override it in derived class if you add new variables to the cache
         // and call the parent class method
         // and call the parent class method
         /** @hidden */
         /** @hidden */
@@ -349,44 +370,45 @@
 
 
         /** @hidden */
         /** @hidden */
         public _markSyncedWithParent() {
         public _markSyncedWithParent() {
-            if (this.parent) {
-                this._parentRenderId = this.parent._childRenderId;
+            if (this._parentNode) {
+                this._parentRenderId = this._parentNode._childRenderId;
             }
             }
         }
         }
 
 
         /** @hidden */
         /** @hidden */
         public isSynchronizedWithParent(): boolean {
         public isSynchronizedWithParent(): boolean {
-            if (!this.parent) {
+            if (!this._parentNode) {
                 return true;
                 return true;
             }
             }
 
 
-            if (this._parentRenderId !== this.parent._childRenderId) {
+            if (this._parentRenderId !== this._parentNode._childRenderId) {
                 return false;
                 return false;
             }
             }
 
 
-            return this.parent.isSynchronized();
+            return this._parentNode.isSynchronized();
         }
         }
 
 
         /** @hidden */
         /** @hidden */
-        public isSynchronized(updateCache?: boolean): boolean {
+        public isSynchronized(useWasUpdatedFlag?: boolean): boolean {
             var check = this.hasNewParent();
             var check = this.hasNewParent();
 
 
-            check = check || !this.isSynchronizedWithParent();
+            if (!useWasUpdatedFlag) {
+                check = check || !this.isSynchronizedWithParent();
+            } else if (this._parentNode) {
+                check = this._parentNode._worldMatrixWasUpdated; 
+            }
 
 
             check = check || !this._isSynchronized();
             check = check || !this._isSynchronized();
 
 
-            if (updateCache)
-                this.updateCache(true);
-
             return !check;
             return !check;
         }
         }
 
 
         /** @hidden */
         /** @hidden */
         public hasNewParent(): boolean {
         public hasNewParent(): boolean {
-            if (this._cache.parent === this.parent)
+            if (this._cache.parent === this._parentNode)
                 return false;
                 return false;
 
 
-            this._cache.parent = this.parent;
+            this._cache.parent = this._parentNode;
 
 
             return true;
             return true;
         }
         }
@@ -415,8 +437,8 @@
                 return false;
                 return false;
             }
             }
 
 
-            if (this.parent !== undefined && this.parent !== null) {
-                return this.parent.isEnabled(checkAncestors);
+            if (this._parentNode !== undefined && this._parentNode !== null) {
+                return this._parentNode.isEnabled(checkAncestors);
             }
             }
 
 
             return true;
             return true;
@@ -637,10 +659,14 @@
         /**
         /**
          * Computes the world matrix of the node
          * Computes the world matrix of the node
          * @param force defines if the cache version should be invalidated forcing the world matrix to be created from scratch
          * @param force defines if the cache version should be invalidated forcing the world matrix to be created from scratch
+         * @param useWasUpdatedFlag defines a reserved property
          * @returns the world matrix
          * @returns the world matrix
          */
          */
-        public computeWorldMatrix(force?: boolean): Matrix {
-            return Matrix.Identity();
+        public computeWorldMatrix(force?: boolean, useWasUpdatedFlag?: boolean): Matrix {
+            if (!this._worldMatrix) {
+                this._worldMatrix = Matrix.Identity();
+            }
+            return this._worldMatrix;
         }
         }
 
 
         /**
         /**

+ 25 - 2
src/babylon.scene.ts

@@ -4067,6 +4067,28 @@
             return this;
             return this;
         }
         }
 
 
+        private _computeAllWorldMatricesforBranch(node: Node) {
+            node.computeWorldMatrix(false, true);
+            const children = node.getChildren();
+
+            if (children) {
+                for (var child of children) {
+                    this._computeAllWorldMatricesforBranch(child);
+                }
+            }
+            
+            node._worldMatrixWasUpdated = false;
+        }
+
+        /**
+         * This function will traverse the scene graph and makes sure that all worldMatrix are up to date
+         */
+        public computeAllWorldMatrices() {
+            for (var node of this.rootNodes) {
+                this._computeAllWorldMatricesforBranch(node);
+            }
+        }
+
         private _evaluateActiveMeshes(): void {
         private _evaluateActiveMeshes(): void {
             if (this._activeMeshesFrozen && this._activeMeshes.length) {
             if (this._activeMeshesFrozen && this._activeMeshes.length) {
                 return;
                 return;
@@ -4089,6 +4111,9 @@
                 step.action();
                 step.action();
             }
             }
 
 
+            // World matrices
+            this.computeAllWorldMatrices();
+
             // Determine mesh candidates
             // Determine mesh candidates
             const meshes = this.getActiveMeshCandidates();
             const meshes = this.getActiveMeshCandidates();
             
             
@@ -4106,8 +4131,6 @@
                     continue;
                     continue;
                 }
                 }
 
 
-                mesh.computeWorldMatrix();
-
                 // Intersections
                 // Intersections
                 if (mesh.actionManager && mesh.actionManager.hasSpecificTriggers2(ActionManager.OnIntersectionEnterTrigger, ActionManager.OnIntersectionExitTrigger)) {
                 if (mesh.actionManager && mesh.actionManager.hasSpecificTriggers2(ActionManager.OnIntersectionEnterTrigger, ActionManager.OnIntersectionExitTrigger)) {
                     this._meshesForIntersections.pushNoDuplicate(mesh);
                     this._meshesForIntersections.pushNoDuplicate(mesh);