Julien Barrois před 7 roky
rodič
revize
53e3673c35

+ 6 - 4
src/Culling/babylon.boundingBox.ts

@@ -59,9 +59,10 @@
          * Creates a new bounding box
          * @param min defines the minimum vector (in local space)
          * @param max defines the maximum vector (in local space)
+         * @param worldMatrix defines the new world matrix
          */
-        constructor(min: Vector3, max: Vector3) {
-            this.reConstruct(min, max);
+        constructor(min: Vector3, max: Vector3, worldMatrix?: Matrix) {
+            this.reConstruct(min, max, worldMatrix);
         }
 
         // Methods
@@ -70,8 +71,9 @@
          * Recreates the entire bounding box from scratch
          * @param min defines the new minimum vector (in local space)
          * @param max defines the new maximum vector (in local space) 
+         * @param worldMatrix defines the new world matrix
          */
-        public reConstruct(min: Vector3, max: Vector3) {
+        public reConstruct(min: Vector3, max: Vector3, worldMatrix?: Matrix) {
             this.minimum.copyFrom(min);
             this.maximum.copyFrom(max);
 
@@ -109,7 +111,7 @@
             this.centerWorld.copyFromFloats(0,0,0);
             this.extendSizeWorld.copyFromFloats(0,0,0);
 
-            this._update(this._worldMatrix || Matrix.Identity());
+            this._update(worldMatrix || this._worldMatrix || Matrix.Identity());
         }
 
         /**

+ 16 - 3
src/Culling/babylon.boundingInfo.ts

@@ -56,14 +56,27 @@
         public boundingSphere: BoundingSphere;
 
         private _isLocked = false;
+        
         /**
          * Constructs bounding info
          * @param minimum min vector of the bounding box/sphere
          * @param maximum max vector of the bounding box/sphere
+         * @param worldMatrix defines the new world matrix 
          */
-        constructor(minimum: Vector3, maximum: Vector3) {
-            this.boundingBox = new BoundingBox(minimum, maximum);
-            this.boundingSphere = new BoundingSphere(minimum, maximum);
+        constructor(minimum: Vector3, maximum: Vector3, worldMatrix?: Matrix) {
+            this.boundingBox = new BoundingBox(minimum, maximum, worldMatrix);
+            this.boundingSphere = new BoundingSphere(minimum, maximum, worldMatrix);
+        }
+
+        /**
+         * Recreates the entire bounding info from scratch
+         * @param min defines the new minimum vector (in local space)
+         * @param max defines the new maximum vector (in local space) 
+         * @param worldMatrix defines the new world matrix
+         */
+        public reConstruct(min: Vector3, max: Vector3, worldMatrix?: Matrix) {
+            this.boundingBox.reConstruct(min, max, worldMatrix);
+            this.boundingSphere.reConstruct(min, max, worldMatrix);
         }
 
         /**

+ 6 - 4
src/Culling/babylon.boundingSphere.ts

@@ -35,17 +35,19 @@
          * Creates a new bounding sphere
          * @param min defines the minimum vector (in local space)
          * @param max defines the maximum vector (in local space)
+         * @param worldMatrix defines the new world matrix
          */
-        constructor(min: Vector3, max: Vector3) {
-            this.reConstruct(min, max);
+        constructor(min: Vector3, max: Vector3, worldMatrix?: Matrix) {
+            this.reConstruct(min, max, worldMatrix);
         }
 
         /**
          * Recreates the entire bounding sphere from scratch
          * @param min defines the new minimum vector (in local space)
          * @param max defines the new maximum vector (in local space) 
+         * @param worldMatrix defines the new world matrix
          */
-        public reConstruct(min: Vector3, max: Vector3) {
+        public reConstruct(min: Vector3, max: Vector3, worldMatrix?: Matrix) {
             this.minimum.copyFrom(min);
             this.maximum.copyFrom(max);
 
@@ -55,7 +57,7 @@
             this.radius = distance * 0.5;
 
             this.centerWorld.set(0, 0, 0);
-            this._update(_identityMatrix);
+            this._update(worldMatrix || _identityMatrix);
         }
 
         /**

+ 66 - 40
src/Math/babylon.math.ts

@@ -534,10 +534,7 @@
          * @param index defines an optional index in the target array to define where to start storing values
          * @returns the current Color4 object
          */
-        public toArray(array: number[], index?: number): Color4 {
-            if (index === undefined) {
-                index = 0;
-            }
+        public toArray(array: number[], index: number = 0): Color4 {
             array[index] = this.r;
             array[index + 1] = this.g;
             array[index + 2] = this.b;
@@ -1454,8 +1451,9 @@
          * @param result defines the target vector
          */
         public static TransformToRef(vector: Vector2, transformation: Matrix, result: Vector2) {
-            var x = (vector.x * transformation.m[0]) + (vector.y * transformation.m[4]) + transformation.m[12];
-            var y = (vector.x * transformation.m[1]) + (vector.y * transformation.m[5]) + transformation.m[13];
+            const m = transformation.m;
+            var x = (vector.x * m[0]) + (vector.y * m[4]) + m[12];
+            var y = (vector.x * m[1]) + (vector.y * m[5]) + m[13];
             result.x = x;
             result.y = y;
         }
@@ -1880,7 +1878,10 @@
          * @returns the current updated Vector3  
          */
         public minimizeInPlace(other: Vector3): Vector3 {
-            return this.minimizeInPlaceFromFloats(other.x, other.y, other.z);
+            if (other.x < this.x) this.x = other.x;
+            if (other.y < this.y) this.y = other.y;
+            if (other.z < this.z) this.z = other.z;
+            return this;
         }
 
         /**
@@ -1889,7 +1890,10 @@
          * @returns the current updated Vector3
          */
         public maximizeInPlace(other: Vector3): Vector3 {
-            return this.maximizeInPlaceFromFloats(other.x, other.y, other.z);
+            if (other.x < this.x) this.x = other.x;
+            if (other.y < this.y) this.y = other.y;
+            if (other.z < this.z) this.z = other.z;
+            return this;
         }
 
         /**
@@ -1981,7 +1985,16 @@
          * @returns the current updated Vector3 
          */
         public normalize(): Vector3 {
-            var len = this.length();
+            return this.normalizeFromLength(this.length());
+        }
+
+        /**
+         * Normalize the current Vector3 with the given input length.
+         * Please note that this is an in place operation.
+         * @param len the length of the vector
+         * @returns the current updated Vector3 
+         */
+        public normalizeFromLength(len : number): Vector3 {
             if (len === 0 || len === 1.0)
                 return this;
 
@@ -1992,6 +2005,7 @@
             return this;
         }
 
+
         /**
          * Normalize the current Vector3 to a new vector
          * @returns the new Vector3
@@ -2064,6 +2078,16 @@
             return this.copyFromFloats(x, y, z);
         }
 
+        /**
+         * Copies the given float to the current Vector3 coordinates
+         * @param v defines the x, y and z coordinates of the operand
+         * @returns the current updated Vector3
+         */
+        public setAll(v: number): Vector3 {
+            this.x = this.y = this.z = v;
+            return this;
+        }
+
         // Statics
 
         /**
@@ -2241,14 +2265,7 @@
          * @param result defines the Vector3 where to store the result
          */
         public static TransformCoordinatesToRef(vector: Vector3, transformation: Matrix, result: Vector3): void {
-            var x = (vector.x * transformation.m[0]) + (vector.y * transformation.m[4]) + (vector.z * transformation.m[8]) + transformation.m[12];
-            var y = (vector.x * transformation.m[1]) + (vector.y * transformation.m[5]) + (vector.z * transformation.m[9]) + transformation.m[13];
-            var z = (vector.x * transformation.m[2]) + (vector.y * transformation.m[6]) + (vector.z * transformation.m[10]) + transformation.m[14];
-            var w = (vector.x * transformation.m[3]) + (vector.y * transformation.m[7]) + (vector.z * transformation.m[11]) + transformation.m[15];
-
-            result.x = x / w;
-            result.y = y / w;
-            result.z = z / w;
+            return Vector3.TransformCoordinatesFromFloatsToRef(vector.x, vector.y, vector.z, transformation, result)
         }
 
         /**
@@ -2261,14 +2278,15 @@
          * @param result defines the Vector3 where to store the result
          */
         public static TransformCoordinatesFromFloatsToRef(x: number, y: number, z: number, transformation: Matrix, result: Vector3): void {
-            var rx = (x * transformation.m[0]) + (y * transformation.m[4]) + (z * transformation.m[8]) + transformation.m[12];
-            var ry = (x * transformation.m[1]) + (y * transformation.m[5]) + (z * transformation.m[9]) + transformation.m[13];
-            var rz = (x * transformation.m[2]) + (y * transformation.m[6]) + (z * transformation.m[10]) + transformation.m[14];
-            var rw = (x * transformation.m[3]) + (y * transformation.m[7]) + (z * transformation.m[11]) + transformation.m[15];
+            const m = transformation.m;
+            var rx = x * m[0] + y * m[4] + z * m[8] + m[12];
+            var ry = x * m[1] + y * m[5] + z * m[9] + m[13];
+            var rz = x * m[2] + y * m[6] + z * m[10] + m[14];
+            var rw = 1/(x * m[3] + y * m[7] + z * m[11] + m[15]);
 
-            result.x = rx / rw;
-            result.y = ry / rw;
-            result.z = rz / rw;
+            result.x = rx * rw;
+            result.y = ry * rw;
+            result.z = rz * rw;
         }
 
         /**
@@ -2292,12 +2310,7 @@
          * @param result defines the Vector3 where to store the result
          */
         public static TransformNormalToRef(vector: Vector3, transformation: Matrix, result: Vector3): void {
-            var x = (vector.x * transformation.m[0]) + (vector.y * transformation.m[4]) + (vector.z * transformation.m[8]);
-            var y = (vector.x * transformation.m[1]) + (vector.y * transformation.m[5]) + (vector.z * transformation.m[9]);
-            var z = (vector.x * transformation.m[2]) + (vector.y * transformation.m[6]) + (vector.z * transformation.m[10]);
-            result.x = x;
-            result.y = y;
-            result.z = z;
+            this.TransformNormalFromFloatsToRef(vector.x, vector.y, vector.z, transformation, result);
         }
 
         /**
@@ -2310,9 +2323,10 @@
          * @param result defines the Vector3 where to store the result
          */
         public static TransformNormalFromFloatsToRef(x: number, y: number, z: number, transformation: Matrix, result: Vector3): void {
-            result.x = (x * transformation.m[0]) + (y * transformation.m[4]) + (z * transformation.m[8]);
-            result.y = (x * transformation.m[1]) + (y * transformation.m[5]) + (z * transformation.m[9]);
-            result.z = (x * transformation.m[2]) + (y * transformation.m[6]) + (z * transformation.m[10]);
+            const m = transformation.m;
+            result.x = x * m[0] + y * m[4] + z * m[8];
+            result.y = x * m[1] + y * m[5] + z * m[9];
+            result.z = x * m[2] + y * m[6] + z * m[10];
         }
 
         /**
@@ -3166,6 +3180,16 @@
             return this.copyFromFloats(x, y, z, w);
         }
 
+                /**
+         * Copies the given float to the current Vector3 coordinates
+         * @param v defines the x, y, z and w coordinates of the operand
+         * @returns the current updated Vector3
+         */
+        public setAll(v: number): Vector4 {
+            this.x = this.y = this.z = this.w = v;
+            return this;
+        }
+
         // Statics
         /**
          * Returns a new Vector4 set from the starting index of the given array.
@@ -3327,9 +3351,10 @@
          * @param result the vector to store the result in
          */
         public static TransformNormalToRef(vector: Vector4, transformation: Matrix, result: Vector4): void {
-            var x = (vector.x * transformation.m[0]) + (vector.y * transformation.m[4]) + (vector.z * transformation.m[8]);
-            var y = (vector.x * transformation.m[1]) + (vector.y * transformation.m[5]) + (vector.z * transformation.m[9]);
-            var z = (vector.x * transformation.m[2]) + (vector.y * transformation.m[6]) + (vector.z * transformation.m[10]);
+            const m = transformation.m;
+            var x = (vector.x * m[0]) + (vector.y * m[4]) + (vector.z * m[8]);
+            var y = (vector.x * m[1]) + (vector.y * m[5]) + (vector.z * m[9]);
+            var z = (vector.x * m[2]) + (vector.y * m[6]) + (vector.z * m[10]);
             result.x = x;
             result.y = y;
             result.z = z;
@@ -3347,9 +3372,10 @@
          * @param result the vector to store the results in
          */
         public static TransformNormalFromFloatsToRef(x: number, y: number, z: number, w: number, transformation: Matrix, result: Vector4): void {
-            result.x = (x * transformation.m[0]) + (y * transformation.m[4]) + (z * transformation.m[8]);
-            result.y = (x * transformation.m[1]) + (y * transformation.m[5]) + (z * transformation.m[9]);
-            result.z = (x * transformation.m[2]) + (y * transformation.m[6]) + (z * transformation.m[10]);
+            const m = transformation.m;
+            result.x = (x * m[0]) + (y * m[4]) + (z * m[8]);
+            result.y = (x * m[1]) + (y * m[5]) + (z * m[9]);
+            result.z = (x * m[2]) + (y * m[6]) + (z * m[10]);
             result.w = w;
         }
     }
@@ -7188,7 +7214,7 @@
         public static Color4: Color4[] = [new Color4(0, 0, 0, 0), new Color4(0, 0, 0, 0)];
         public static Vector2: Vector2[] = [Vector2.Zero(), Vector2.Zero(), Vector2.Zero()];  // 3 temp Vector2 at once should be enough
         public static Vector3: Vector3[] = [Vector3.Zero(), Vector3.Zero(), Vector3.Zero(),
-        Vector3.Zero(), Vector3.Zero(), Vector3.Zero(), Vector3.Zero(), Vector3.Zero(), Vector3.Zero()];    // 9 temp Vector3 at once should be enough
+        Vector3.Zero(), Vector3.Zero(), Vector3.Zero(), Vector3.Zero(), Vector3.Zero(), Vector3.Zero(), Vector3.Zero(), Vector3.Zero()]; // 11 temp Vector3 at once should be enough
         public static Vector4: Vector4[] = [Vector4.Zero(), Vector4.Zero(), Vector4.Zero()];  // 3 temp Vector4 at once should be enough
         public static Quaternion: Quaternion[] = [Quaternion.Zero(), Quaternion.Zero()];                // 2 temp Quaternion at once should be enough
         public static Matrix: Matrix[] = [Matrix.Zero(), Matrix.Zero(),

+ 322 - 378
src/Particles/babylon.solidParticleSystem.ts

@@ -89,8 +89,6 @@
         private _depthSort: boolean = false;
         private _shapeCounter: number = 0;
         private _copy: SolidParticle = new SolidParticle(0, 0, 0, null, 0, 0, this);
-        private _shape: Vector3[];
-        private _shapeUV: number[];
         private _color: Color4 = new Color4(0, 0, 0, 0);
         private _computeParticleColor: boolean = true;
         private _computeParticleTexture: boolean = true;
@@ -98,37 +96,21 @@
         private _computeParticleVertex: boolean = false;
         private _computeBoundingBox: boolean = false;
         private _depthSortParticles: boolean = true;
-        private _cam_axisZ: Vector3 = Vector3.Zero();
-        private _cam_axisY: Vector3 = Vector3.Zero();
-        private _cam_axisX: Vector3 = Vector3.Zero();
+        private static _cam_axisX = Vector3.Zero();
+        private static _cam_axisY = Vector3.Zero();
+        private static _cam_axisZ = Vector3.Zero();
         private _axisZ: Vector3 = Axis.Z;
         private _camera: TargetCamera;
-        private _particle: SolidParticle;
         private _camDir: Vector3 = Vector3.Zero();
         private _camInvertedPosition: Vector3 = Vector3.Zero();
         private _rotMatrix: Matrix = new Matrix();
         private _invertMatrix: Matrix = new Matrix();
-        private _rotated: Vector3 = Vector3.Zero();
+        private static _rotated: Vector3 = Vector3.Zero();
         private _quaternion: Quaternion = new Quaternion();
-        private _vertex: Vector3 = Vector3.Zero();
-        private _normal: Vector3 = Vector3.Zero();
-        private _yaw: number = 0.0;
-        private _pitch: number = 0.0;
-        private _roll: number = 0.0;
-        private _halfroll: number = 0.0;
-        private _halfpitch: number = 0.0;
-        private _halfyaw: number = 0.0;
-        private _sinRoll: number = 0.0;
-        private _cosRoll: number = 0.0;
-        private _sinPitch: number = 0.0;
-        private _cosPitch: number = 0.0;
-        private _sinYaw: number = 0.0;
-        private _cosYaw: number = 0.0;
+        private static _vertex: Vector3 = Vector3.Zero();
         private _mustUnrotateFixedNormals = false;
-        private _minimum: Vector3 = Vector3.Zero();
-        private _maximum: Vector3 = Vector3.Zero();
-        private _minBbox: Vector3 = Vector3.Zero();
-        private _maxBbox: Vector3 = Vector3.Zero();
+        private static _minimum: Vector3 = Vector3.Zero();
+        private static _maximum: Vector3 = Vector3.Zero();
         private _particlesIntersect: boolean = false;
         private _depthSortFunction: (p1: DepthSortedParticle, p2: DepthSortedParticle) => number =
             function (p1, p2) {
@@ -137,8 +119,6 @@
         private _needs32Bits: boolean = false;
         private _pivotBackTranslation: Vector3 = Vector3.Zero();
         private _scaledPivot: Vector3 = Vector3.Zero();
-        private _particleHasParent: boolean = false;
-        private _parent: SolidParticle;
 
         /**
          * Creates a SPS (Solid Particle System) object.
@@ -337,27 +317,24 @@
         private _unrotateFixedNormals() {
             var index = 0;
             var idx = 0;
+            const tmpNormal = SolidParticleSystem._vertex;
             for (var p = 0; p < this.particles.length; p++) {
-                this._particle = this.particles[p];
-                this._shape = this._particle._model._shape;
-                if (this._particle.rotationQuaternion) {
-                    this._quaternion.copyFrom(this._particle.rotationQuaternion);
+                const particle = this.particles[p];
+                const shape = particle._model._shape;
+                if (particle.rotationQuaternion) {
+                    this._quaternion.copyFrom(particle.rotationQuaternion);
                 }
                 else {
-                    this._yaw = this._particle.rotation.y;
-                    this._pitch = this._particle.rotation.x;
-                    this._roll = this._particle.rotation.z;
-                    this._quaternionRotationYPR();
+                    const rotation = particle.rotation;
+                    this._quaternionRotationYPR(rotation.y, rotation.x, rotation.z);
                 }
                 this._quaternionToRotationMatrix();
                 this._rotMatrix.invertToRef(this._invertMatrix);
 
-                for (var pt = 0; pt < this._shape.length; pt++) {
+                for (var pt = 0; pt < shape.length; pt++) {
                     idx = index + pt * 3;
-                    Vector3.TransformNormalFromFloatsToRef(this._normals32[idx], this._normals32[idx + 1], this._normals32[idx + 2], this._invertMatrix, this._normal);
-                    this._fixedNormal32[idx] = this._normal.x;
-                    this._fixedNormal32[idx + 1] = this._normal.y;
-                    this._fixedNormal32[idx + 2] = this._normal.z;
+                    Vector3.TransformNormalFromFloatsToRef(this._normals32[idx], this._normals32[idx + 1], this._normals32[idx + 2], this._invertMatrix, tmpNormal);
+                    tmpNormal.toArray(this._fixedNormal32, idx);
                 }
                 index = idx + 3;
             }
@@ -365,22 +342,14 @@
 
         //reset copy
         private _resetCopy() {
-            this._copy.position.x = 0;
-            this._copy.position.y = 0;
-            this._copy.position.z = 0;
-            this._copy.rotation.x = 0;
-            this._copy.rotation.y = 0;
-            this._copy.rotation.z = 0;
-            this._copy.rotationQuaternion = null;
-            this._copy.scaling.x = 1.0;
-            this._copy.scaling.y = 1.0;
-            this._copy.scaling.z = 1.0;
-            this._copy.uvs.x = 0;
-            this._copy.uvs.y = 0;
-            this._copy.uvs.z = 1.0;
-            this._copy.uvs.w = 1.0;
-            this._copy.color = null;
-            this._copy.translateFromPivot = false;
+            const copy = this._copy;
+            copy.position.setAll(0);
+            copy.rotation.setAll(0);
+            copy.rotationQuaternion = null;
+            copy.scaling.setAll(1);
+            copy.uvs.copyFromFloats(0.0, 0.0, 1.0, 1.0);
+            copy.color = null;
+            copy.translateFromPivot = false;
         }
 
         // _meshBuilder : inserts the shape model in the global SPS mesh
@@ -391,80 +360,72 @@
             var n = 0;
 
             this._resetCopy();
+            const copy = this._copy;
             if (options && options.positionFunction) {        // call to custom positionFunction
-                options.positionFunction(this._copy, idx, idxInShape);
+                options.positionFunction(copy, idx, idxInShape);
                 this._mustUnrotateFixedNormals = true;
             }
 
-            if (this._copy.rotationQuaternion) {
-                this._quaternion.copyFrom(this._copy.rotationQuaternion);
+            if (copy.rotationQuaternion) {
+                this._quaternion.copyFrom(copy.rotationQuaternion);
             } else {
-                this._yaw = this._copy.rotation.y;
-                this._pitch = this._copy.rotation.x;
-                this._roll = this._copy.rotation.z;
-                this._quaternionRotationYPR();
+                const rotation = copy.rotation;
+                this._quaternionRotationYPR(rotation.y, rotation.x, rotation.z);
             }
             this._quaternionToRotationMatrix();
 
-            this._scaledPivot.x = this._copy.pivot.x * this._copy.scaling.x;
-            this._scaledPivot.y = this._copy.pivot.y * this._copy.scaling.y;
-            this._scaledPivot.z = this._copy.pivot.z * this._copy.scaling.z;
+            copy.pivot.multiplyToRef(copy.scaling, this._scaledPivot)
 
-            if (this._copy.translateFromPivot) {
+            if (copy.translateFromPivot) {
                 this._pivotBackTranslation.copyFromFloats(0.0, 0.0, 0.0);
             }
             else {
                 this._pivotBackTranslation.copyFrom(this._scaledPivot);
             }
 
+            const tmpVertex = SolidParticleSystem._vertex;
+            const tmpRotated = SolidParticleSystem._rotated;
             for (i = 0; i < shape.length; i++) {
-                this._vertex.x = shape[i].x;
-                this._vertex.y = shape[i].y;
-                this._vertex.z = shape[i].z;
-
+                tmpVertex.copyFrom(shape[i]);
                 if (options && options.vertexFunction) {
-                    options.vertexFunction(this._copy, this._vertex, i);
+                    options.vertexFunction(copy, tmpVertex, i);
                 }
 
-                this._vertex.x *= this._copy.scaling.x;
-                this._vertex.y *= this._copy.scaling.y;
-                this._vertex.z *= this._copy.scaling.z;
-
-                this._vertex.x -= this._scaledPivot.x;
-                this._vertex.y -= this._scaledPivot.y;
-                this._vertex.z -= this._scaledPivot.z;
-
-                Vector3.TransformCoordinatesToRef(this._vertex, this._rotMatrix, this._rotated);
-
-                this._rotated.addInPlace(this._pivotBackTranslation);
-                positions.push(this._copy.position.x + this._rotated.x, this._copy.position.y + this._rotated.y, this._copy.position.z + this._rotated.z);
+                tmpVertex.multiplyInPlace(copy.scaling).subtractInPlace(this._scaledPivot);
+                Vector3.TransformCoordinatesToRef(tmpVertex, this._rotMatrix, tmpRotated);
+                tmpRotated.addInPlace(this._pivotBackTranslation).addInPlace(copy.position);
+                positions.push(tmpRotated.x, tmpRotated.y, tmpRotated.z);
                 if (meshUV) {
-                    uvs.push((this._copy.uvs.z - this._copy.uvs.x) * meshUV[u] + this._copy.uvs.x, (this._copy.uvs.w - this._copy.uvs.y) * meshUV[u + 1] + this._copy.uvs.y);
+                    const copyUvs = copy.uvs;
+                    uvs.push((copyUvs.z - copyUvs.x) * meshUV[u] + copyUvs.x, (copyUvs.w - copyUvs.y) * meshUV[u + 1] + copyUvs.y);
                     u += 2;
                 }
 
-                if (this._copy.color) {
-                    this._color = this._copy.color;
-                } else if (meshCol && meshCol[c] !== undefined) {
-                    this._color.r = meshCol[c];
-                    this._color.g = meshCol[c + 1];
-                    this._color.b = meshCol[c + 2];
-                    this._color.a = meshCol[c + 3];
+                if (copy.color) {
+                    this._color = copy.color;
                 } else {
-                    this._color.r = 1.0;
-                    this._color.g = 1.0;
-                    this._color.b = 1.0;
-                    this._color.a = 1.0;
+                    const color = this._color;
+                    if (meshCol && meshCol[c] !== undefined) {
+                        color.r = meshCol[c];
+                        color.g = meshCol[c + 1];
+                        color.b = meshCol[c + 2];
+                        color.a = meshCol[c + 3];
+                    } else {
+                        color.r = 1.0;
+                        color.g = 1.0;
+                        color.b = 1.0;
+                        color.a = 1.0;
+                    }
                 }
                 colors.push(this._color.r, this._color.g, this._color.b, this._color.a);
                 c += 4;
 
                 if (!this.recomputeNormals && meshNor) {
-                    this._normal.x = meshNor[n];
-                    this._normal.y = meshNor[n + 1];
-                    this._normal.z = meshNor[n + 2];
-                    Vector3.TransformNormalToRef(this._normal, this._rotMatrix, this._normal);
-                    normals.push(this._normal.x, this._normal.y, this._normal.z);
+                    tmpVertex.x = meshNor[n];
+                    tmpVertex.y = meshNor[n + 1];
+                    tmpVertex.z = meshNor[n + 2];
+                    Vector3.TransformNormalToRef(tmpVertex, this._rotMatrix, tmpVertex);
+                    normals.push(tmpVertex.x, tmpVertex.y, tmpVertex.z);
                     n += 3;
                 }
 
@@ -489,14 +450,14 @@
                 this.depthSortedParticles.push(new DepthSortedParticle());
             }
 
-            return this._copy;
+            return copy;
         }
 
         // returns a shape array from positions array
         private _posToShape(positions: number[] | Float32Array): Vector3[] {
             var shape = [];
             for (var i = 0; i < positions.length; i += 3) {
-                shape.push(new Vector3(positions[i], positions[i + 1], positions[i + 2]));
+                shape.push(Vector3.FromArray(positions, i));
             }
             return shape;
         }
@@ -578,73 +539,47 @@
         // rebuilds a particle back to its just built status : if needed, recomputes the custom positions and vertices
         private _rebuildParticle(particle: SolidParticle): void {
             this._resetCopy();
+            const copy = this._copy;
             if (particle._model._positionFunction) {        // recall to stored custom positionFunction
-                particle._model._positionFunction(this._copy, particle.idx, particle.idxInShape);
+                particle._model._positionFunction(copy, particle.idx, particle.idxInShape);
             }
 
-            if (this._copy.rotationQuaternion) {
-                this._quaternion.copyFrom(this._copy.rotationQuaternion);
+            if (copy.rotationQuaternion) {
+                this._quaternion.copyFrom(copy.rotationQuaternion);
             } else {
-                this._yaw = this._copy.rotation.y;
-                this._pitch = this._copy.rotation.x;
-                this._roll = this._copy.rotation.z;
-                this._quaternionRotationYPR();
+                const rotation = copy.rotation
+                this._quaternionRotationYPR(rotation.y, rotation.x, rotation.z);
             }
             this._quaternionToRotationMatrix();
 
-            this._scaledPivot.x = this._particle.pivot.x * this._particle.scaling.x;
-            this._scaledPivot.y = this._particle.pivot.y * this._particle.scaling.y;
-            this._scaledPivot.z = this._particle.pivot.z * this._particle.scaling.z;
+            particle.pivot.multiplyToRef(particle.scaling, this._scaledPivot);
 
-            if (this._copy.translateFromPivot) {
+            if (copy.translateFromPivot) {
                 this._pivotBackTranslation.copyFromFloats(0.0, 0.0, 0.0);
             }
             else {
                 this._pivotBackTranslation.copyFrom(this._scaledPivot);
             }
 
-            this._shape = particle._model._shape;
-            for (var pt = 0; pt < this._shape.length; pt++) {
-                this._vertex.x = this._shape[pt].x;
-                this._vertex.y = this._shape[pt].y;
-                this._vertex.z = this._shape[pt].z;
-
+            const shape = particle._model._shape;
+            const tmpVertex = SolidParticleSystem._vertex;
+            const tmpRotated = SolidParticleSystem._rotated;
+            for (var pt = 0; pt < shape.length; pt++) {
+                tmpVertex.copyFrom(shape[pt]);
                 if (particle._model._vertexFunction) {
-                    particle._model._vertexFunction(this._copy, this._vertex, pt); // recall to stored vertexFunction
+                    particle._model._vertexFunction(copy, tmpVertex, pt); // recall to stored vertexFunction
                 }
 
-                this._vertex.x *= this._copy.scaling.x;
-                this._vertex.y *= this._copy.scaling.y;
-                this._vertex.z *= this._copy.scaling.z;
-
-                this._vertex.x -= this._scaledPivot.x;
-                this._vertex.y -= this._scaledPivot.y;
-                this._vertex.z -= this._scaledPivot.z;
-
-                Vector3.TransformCoordinatesToRef(this._vertex, this._rotMatrix, this._rotated);
-                this._rotated.addInPlace(this._pivotBackTranslation);
-
-                this._positions32[particle._pos + pt * 3] = this._copy.position.x + this._rotated.x;
-                this._positions32[particle._pos + pt * 3 + 1] = this._copy.position.y + this._rotated.y;
-                this._positions32[particle._pos + pt * 3 + 2] = this._copy.position.z + this._rotated.z;
+                tmpVertex.multiplyInPlace(copy.scaling).subtractInPlace(this._scaledPivot);
+                Vector3.TransformCoordinatesToRef(tmpVertex, this._rotMatrix, tmpRotated);
+                tmpRotated.addInPlace(this._pivotBackTranslation).addInPlace(copy.position).toArray(this._positions32, particle._pos + pt * 3);
             }
-            particle.position.x = 0.0;
-            particle.position.y = 0.0;
-            particle.position.z = 0.0;
-            particle.rotation.x = 0.0;
-            particle.rotation.y = 0.0;
-            particle.rotation.z = 0.0;
+            particle.position.setAll(0.0);
+            particle.rotation.setAll(0.0);
             particle.rotationQuaternion = null;
-            particle.scaling.x = 1.0;
-            particle.scaling.y = 1.0;
-            particle.scaling.z = 1.0;
-            particle.uvs.x = 0.0;
-            particle.uvs.y = 0.0;
-            particle.uvs.z = 1.0;
-            particle.uvs.w = 1.0;
-            particle.pivot.x = 0.0;
-            particle.pivot.y = 0.0;
-            particle.pivot.z = 0.0;
+            particle.scaling.setAll(1.0);
+            particle.uvs.setAll(0.0);
+            particle.pivot.setAll(0.0);
             particle.translateFromPivot = false;
             particle.parentId = null;
         }
@@ -678,17 +613,11 @@
             // custom beforeUpdate
             this.beforeUpdateParticles(start, end, update);
 
-            this._cam_axisX.x = 1.0;
-            this._cam_axisX.y = 0.0;
-            this._cam_axisX.z = 0.0;
-
-            this._cam_axisY.x = 0.0;
-            this._cam_axisY.y = 1.0;
-            this._cam_axisY.z = 0.0;
-
-            this._cam_axisZ.x = 0.0;
-            this._cam_axisZ.y = 0.0;
-            this._cam_axisZ.z = 1.0;
+            const camAxisX = SolidParticleSystem._cam_axisX.copyFromFloats(1.0, 0.0, 0.0);
+            const camAxisY = SolidParticleSystem._cam_axisY.copyFromFloats(0.0, 1.0, 0.0);
+            const camAxisZ = SolidParticleSystem._cam_axisZ.copyFromFloats(0.0, 0.0, 1.0);
+            const minimum = SolidParticleSystem._minimum;
+            const maximum = SolidParticleSystem._maximum;
 
             // cases when the World Matrix is to be computed first
             if (this.billboard || this._depthSort) {
@@ -699,14 +628,14 @@
             if (this.billboard) {
                 // compute the camera position and un-rotate it by the current mesh rotation
                 this._camera.getDirectionToRef(this._axisZ, this._camDir);
-                Vector3.TransformNormalToRef(this._camDir, this._invertMatrix, this._cam_axisZ);
-                this._cam_axisZ.normalize();
+                Vector3.TransformNormalToRef(this._camDir, this._invertMatrix, camAxisZ);
+                camAxisZ.normalize();
                 // same for camera up vector extracted from the cam view matrix
                 var view = this._camera.getViewMatrix(true);
-                Vector3.TransformNormalFromFloatsToRef(view.m[1], view.m[5], view.m[9], this._invertMatrix, this._cam_axisY);
-                Vector3.CrossToRef(this._cam_axisY, this._cam_axisZ, this._cam_axisX);
-                this._cam_axisY.normalize();
-                this._cam_axisX.normalize();
+                Vector3.TransformNormalFromFloatsToRef(view.m[1], view.m[5], view.m[9], this._invertMatrix, camAxisY);
+                Vector3.CrossToRef(camAxisY, camAxisZ, camAxisX);
+                camAxisY.normalize();
+                camAxisX.normalize();
             }
 
             // if depthSort, compute the camera global position in the mesh local system
@@ -730,13 +659,18 @@
             end = (end >= this.nbParticles) ? this.nbParticles - 1 : end;
             if (this._computeBoundingBox) {
                 if (start == 0 && end == this.nbParticles - 1) {        // all the particles are updated, then recompute the BBox from scratch
-                    Vector3.FromFloatsToRef(Number.MAX_VALUE, Number.MAX_VALUE, Number.MAX_VALUE, this._minimum);
-                    Vector3.FromFloatsToRef(-Number.MAX_VALUE, -Number.MAX_VALUE, -Number.MAX_VALUE, this._maximum);
+                    minimum.setAll(Number.MAX_VALUE);
+                    maximum.setAll(-Number.MAX_VALUE);
                 }
                 else {      // only some particles are updated, then use the current existing BBox basis. Note : it can only increase.
-                    if (this.mesh._boundingInfo) {
-                        this._minimum.copyFrom(this.mesh._boundingInfo.boundingBox.minimum);
-                        this._maximum.copyFrom(this.mesh._boundingInfo.boundingBox.maximum);
+                    const boundingInfo = this.mesh._boundingInfo
+                    if (boundingInfo) {
+                        minimum.copyFrom(boundingInfo.minimum);
+                        maximum.copyFrom(boundingInfo.maximum);
+                    }
+                    else {
+                        minimum.setAll(Number.MAX_VALUE);
+                        maximum.setAll(-Number.MAX_VALUE);
                     }
                 }
             }
@@ -746,250 +680,253 @@
             var vpos = (index / 3) | 0;
             colorIndex = vpos * 4;
             uvIndex = vpos * 2;
+
+            const rotMatrixValues = this._rotMatrix.m;
+            const scaledPivot = this._scaledPivot;
+            const pivotBackTranslation = this._pivotBackTranslation;
+            const tmpVertex = SolidParticleSystem._vertex;
+            const mesh = this.mesh;
+            const colors32 = this._colors32;
+            const positions32 = this._positions32;
+            const normals32 = this._normals32;
+            const uvs32 = this._uvs32;
+            const indices32 = this._indices32;
+            const indices = this._indices;
+            const fixedNormal32 = this._fixedNormal32;
+            
+
             for (var p = start; p <= end; p++) {
-                this._particle = this.particles[p];
-                this._shape = this._particle._model._shape;
-                this._shapeUV = this._particle._model._shapeUV;
+                const particle = this.particles[p];
+                const shape = particle._model._shape;
+                const shapeUV = particle._model._shapeUV;
+                
+                const rotationMatrix = particle._rotationMatrix;
+                const position = particle.position;
+                const rotation = particle.rotation;
+                const globalPosition = particle._globalPosition;
+                const scaling = particle.scaling;
 
                 // call to custom user function to update the particle properties
-                this.updateParticle(this._particle);
+                this.updateParticle(particle);
 
                 // camera-particle distance for depth sorting
                 if (this._depthSort && this._depthSortParticles) {
                     var dsp = this.depthSortedParticles[p];
-                    dsp.ind = this._particle._ind;
-                    dsp.indicesLength = this._particle._model._indicesLength;
-                    dsp.sqDistance = Vector3.DistanceSquared(this._particle.position, this._camInvertedPosition);
+                    dsp.ind = particle._ind;
+                    dsp.indicesLength = particle._model._indicesLength;
+                    dsp.sqDistance = Vector3.DistanceSquared(particle.position, this._camInvertedPosition);
                 }
 
                 // skip the computations for inactive or already invisible particles
-                if (!this._particle.alive || (this._particle._stillInvisible && !this._particle.isVisible)) {
+                if (!particle.alive || (particle._stillInvisible && !particle.isVisible)) {
                     // increment indexes for the next particle
-                    pt = this._shape.length;
+                    pt = shape.length;
                     index += pt * 3;
                     colorIndex += pt * 4;
                     uvIndex += pt * 2;
                     continue;
                 }
 
-                if (this._particle.isVisible) {
-                    this._particle._stillInvisible = false; // un-mark permanent invisibility
-                    this._particleHasParent = (this._particle.parentId !== null);
+                if (particle.isVisible) {
+                    particle._stillInvisible = false; // un-mark permanent invisibility
 
-                    this._scaledPivot.x = this._particle.pivot.x * this._particle.scaling.x;
-                    this._scaledPivot.y = this._particle.pivot.y * this._particle.scaling.y;
-                    this._scaledPivot.z = this._particle.pivot.z * this._particle.scaling.z;
+                    particle.pivot.multiplyToRef(scaling, scaledPivot);
 
                     // particle rotation matrix
                     if (this.billboard) {
-                        this._particle.rotation.x = 0.0;
-                        this._particle.rotation.y = 0.0;
+                        rotation.x = 0.0;
+                        rotation.y = 0.0;
                     }
                     if (this._computeParticleRotation || this.billboard) {
-                        if (this._particle.rotationQuaternion) {
-                            this._quaternion.copyFrom(this._particle.rotationQuaternion);
+                        if (particle.rotationQuaternion) {
+                            this._quaternion.copyFrom(particle.rotationQuaternion);
                         } else {
-                            this._yaw = this._particle.rotation.y;
-                            this._pitch = this._particle.rotation.x;
-                            this._roll = this._particle.rotation.z;
-                            this._quaternionRotationYPR();
+                            this._quaternionRotationYPR(rotation.y, rotation.x, rotation.z);
                         }
                         this._quaternionToRotationMatrix();
                     }
 
-                    if (this._particleHasParent) {
-                        this._parent = this.particles[this._particle.parentId!];
-                        this._rotated.x = this._particle.position.x * this._parent._rotationMatrix[0] + this._particle.position.y * this._parent._rotationMatrix[3] + this._particle.position.z * this._parent._rotationMatrix[6];
-                        this._rotated.y = this._particle.position.x * this._parent._rotationMatrix[1] + this._particle.position.y * this._parent._rotationMatrix[4] + this._particle.position.z * this._parent._rotationMatrix[7];
-                        this._rotated.z = this._particle.position.x * this._parent._rotationMatrix[2] + this._particle.position.y * this._parent._rotationMatrix[5] + this._particle.position.z * this._parent._rotationMatrix[8];
+                    const particleHasParent = (particle.parentId !== null);
+                    if (particleHasParent) {
+                        const parent = this.particles[particle.parentId!];
+                        const parentRotMatrix = parent._rotationMatrix
+                        const parentGlobalPosition = parent._globalPosition;
 
-                        this._particle._globalPosition.x = this._parent._globalPosition.x + this._rotated.x;
-                        this._particle._globalPosition.y = this._parent._globalPosition.y + this._rotated.y;
-                        this._particle._globalPosition.z = this._parent._globalPosition.z + this._rotated.z;
+                        const rotatedY = position.x * parentRotMatrix[1] + position.y * parentRotMatrix[4] + position.z * parentRotMatrix[7];
+                        const rotatedX = position.x * parentRotMatrix[0] + position.y * parentRotMatrix[3] + position.z * parentRotMatrix[6];
+                        const rotatedZ = position.x * parentRotMatrix[2] + position.y * parentRotMatrix[5] + position.z * parentRotMatrix[8];
+
+                        globalPosition.x = parentGlobalPosition.x + rotatedX;
+                        globalPosition.y = parentGlobalPosition.y + rotatedY;
+                        globalPosition.z = parentGlobalPosition.z + rotatedZ;
 
                         if (this._computeParticleRotation || this.billboard) {
-                            this._particle._rotationMatrix[0] = this._rotMatrix.m[0] * this._parent._rotationMatrix[0] + this._rotMatrix.m[1] * this._parent._rotationMatrix[3] + this._rotMatrix.m[2] * this._parent._rotationMatrix[6];
-                            this._particle._rotationMatrix[1] = this._rotMatrix.m[0] * this._parent._rotationMatrix[1] + this._rotMatrix.m[1] * this._parent._rotationMatrix[4] + this._rotMatrix.m[2] * this._parent._rotationMatrix[7];
-                            this._particle._rotationMatrix[2] = this._rotMatrix.m[0] * this._parent._rotationMatrix[2] + this._rotMatrix.m[1] * this._parent._rotationMatrix[5] + this._rotMatrix.m[2] * this._parent._rotationMatrix[8];
-                            this._particle._rotationMatrix[3] = this._rotMatrix.m[4] * this._parent._rotationMatrix[0] + this._rotMatrix.m[5] * this._parent._rotationMatrix[3] + this._rotMatrix.m[6] * this._parent._rotationMatrix[6];
-                            this._particle._rotationMatrix[4] = this._rotMatrix.m[4] * this._parent._rotationMatrix[1] + this._rotMatrix.m[5] * this._parent._rotationMatrix[4] + this._rotMatrix.m[6] * this._parent._rotationMatrix[7];
-                            this._particle._rotationMatrix[5] = this._rotMatrix.m[4] * this._parent._rotationMatrix[2] + this._rotMatrix.m[5] * this._parent._rotationMatrix[5] + this._rotMatrix.m[6] * this._parent._rotationMatrix[8];
-                            this._particle._rotationMatrix[6] = this._rotMatrix.m[8] * this._parent._rotationMatrix[0] + this._rotMatrix.m[9] * this._parent._rotationMatrix[3] + this._rotMatrix.m[10] * this._parent._rotationMatrix[6];
-                            this._particle._rotationMatrix[7] = this._rotMatrix.m[8] * this._parent._rotationMatrix[1] + this._rotMatrix.m[9] * this._parent._rotationMatrix[4] + this._rotMatrix.m[10] * this._parent._rotationMatrix[7];
-                            this._particle._rotationMatrix[8] = this._rotMatrix.m[8] * this._parent._rotationMatrix[2] + this._rotMatrix.m[9] * this._parent._rotationMatrix[5] + this._rotMatrix.m[10] * this._parent._rotationMatrix[8];
+                            rotationMatrix[0] = rotMatrixValues[0] * parentRotMatrix[0] + rotMatrixValues[1] * parentRotMatrix[3] + rotMatrixValues[2] * parentRotMatrix[6];
+                            rotationMatrix[1] = rotMatrixValues[0] * parentRotMatrix[1] + rotMatrixValues[1] * parentRotMatrix[4] + rotMatrixValues[2] * parentRotMatrix[7];
+                            rotationMatrix[2] = rotMatrixValues[0] * parentRotMatrix[2] + rotMatrixValues[1] * parentRotMatrix[5] + rotMatrixValues[2] * parentRotMatrix[8];
+                            rotationMatrix[3] = rotMatrixValues[4] * parentRotMatrix[0] + rotMatrixValues[5] * parentRotMatrix[3] + rotMatrixValues[6] * parentRotMatrix[6];
+                            rotationMatrix[4] = rotMatrixValues[4] * parentRotMatrix[1] + rotMatrixValues[5] * parentRotMatrix[4] + rotMatrixValues[6] * parentRotMatrix[7];
+                            rotationMatrix[5] = rotMatrixValues[4] * parentRotMatrix[2] + rotMatrixValues[5] * parentRotMatrix[5] + rotMatrixValues[6] * parentRotMatrix[8];
+                            rotationMatrix[6] = rotMatrixValues[8] * parentRotMatrix[0] + rotMatrixValues[9] * parentRotMatrix[3] + rotMatrixValues[10] * parentRotMatrix[6];
+                            rotationMatrix[7] = rotMatrixValues[8] * parentRotMatrix[1] + rotMatrixValues[9] * parentRotMatrix[4] + rotMatrixValues[10] * parentRotMatrix[7];
+                            rotationMatrix[8] = rotMatrixValues[8] * parentRotMatrix[2] + rotMatrixValues[9] * parentRotMatrix[5] + rotMatrixValues[10] * parentRotMatrix[8];
                         }
                     }
                     else {
-                        this._particle._globalPosition.x = this._particle.position.x;
-                        this._particle._globalPosition.y = this._particle.position.y;
-                        this._particle._globalPosition.z = this._particle.position.z;
+                        globalPosition.x = position.x;
+                        globalPosition.y = position.y;
+                        globalPosition.z = position.z;
 
                         if (this._computeParticleRotation || this.billboard) {
-                            this._particle._rotationMatrix[0] = this._rotMatrix.m[0];
-                            this._particle._rotationMatrix[1] = this._rotMatrix.m[1];
-                            this._particle._rotationMatrix[2] = this._rotMatrix.m[2];
-                            this._particle._rotationMatrix[3] = this._rotMatrix.m[4];
-                            this._particle._rotationMatrix[4] = this._rotMatrix.m[5];
-                            this._particle._rotationMatrix[5] = this._rotMatrix.m[6];
-                            this._particle._rotationMatrix[6] = this._rotMatrix.m[8];
-                            this._particle._rotationMatrix[7] = this._rotMatrix.m[9];
-                            this._particle._rotationMatrix[8] = this._rotMatrix.m[10];
+                            rotationMatrix[0] = rotMatrixValues[0];
+                            rotationMatrix[1] = rotMatrixValues[1];
+                            rotationMatrix[2] = rotMatrixValues[2];
+                            rotationMatrix[3] = rotMatrixValues[4];
+                            rotationMatrix[4] = rotMatrixValues[5];
+                            rotationMatrix[5] = rotMatrixValues[6];
+                            rotationMatrix[6] = rotMatrixValues[8];
+                            rotationMatrix[7] = rotMatrixValues[9];
+                            rotationMatrix[8] = rotMatrixValues[10];
                         }
                     }
 
-                    if (this._particle.translateFromPivot) {
-                        this._pivotBackTranslation.x = 0.0;
-                        this._pivotBackTranslation.y = 0.0;
-                        this._pivotBackTranslation.z = 0.0;
+                    if (particle.translateFromPivot) {
+                        this._pivotBackTranslation.setAll(0.0);
                     }
                     else {
-                        this._pivotBackTranslation.x = this._scaledPivot.x;
-                        this._pivotBackTranslation.y = this._scaledPivot.y;
-                        this._pivotBackTranslation.z = this._scaledPivot.z;
+                        this._pivotBackTranslation.copyFrom(scaledPivot);
                     }
                     // particle vertex loop
-                    for (pt = 0; pt < this._shape.length; pt++) {
+                    for (pt = 0; pt < shape.length; pt++) {
                         idx = index + pt * 3;
                         colidx = colorIndex + pt * 4;
                         uvidx = uvIndex + pt * 2;
 
-                        this._vertex.x = this._shape[pt].x;
-                        this._vertex.y = this._shape[pt].y;
-                        this._vertex.z = this._shape[pt].z;
-
+                        tmpVertex.copyFrom(shape[pt]);
                         if (this._computeParticleVertex) {
-                            this.updateParticleVertex(this._particle, this._vertex, pt);
+                            this.updateParticleVertex(particle, tmpVertex, pt);
                         }
-
+                        
                         // positions
-                        this._vertex.x *= this._particle.scaling.x;
-                        this._vertex.y *= this._particle.scaling.y;
-                        this._vertex.z *= this._particle.scaling.z;
+                        const vertexX = tmpVertex.x * scaling.x - scaledPivot.x;
+                        const vertexY = tmpVertex.y * scaling.y - scaledPivot.y;
+                        const vertexZ = tmpVertex.z * scaling.z - scaledPivot.z;
 
-                        this._vertex.x -= this._scaledPivot.x;
-                        this._vertex.y -= this._scaledPivot.y;
-                        this._vertex.z -= this._scaledPivot.z;
+                        let rotatedX = vertexX * rotationMatrix[0] + vertexY * rotationMatrix[3] + vertexZ * rotationMatrix[6];
+                        let rotatedY = vertexX * rotationMatrix[1] + vertexY * rotationMatrix[4] + vertexZ * rotationMatrix[7];
+                        let rotatedZ = vertexX * rotationMatrix[2] + vertexY * rotationMatrix[5] + vertexZ * rotationMatrix[8];
 
-                        this._rotated.x = this._vertex.x * this._particle._rotationMatrix[0] + this._vertex.y * this._particle._rotationMatrix[3] + this._vertex.z * this._particle._rotationMatrix[6];
-                        this._rotated.y = this._vertex.x * this._particle._rotationMatrix[1] + this._vertex.y * this._particle._rotationMatrix[4] + this._vertex.z * this._particle._rotationMatrix[7];
-                        this._rotated.z = this._vertex.x * this._particle._rotationMatrix[2] + this._vertex.y * this._particle._rotationMatrix[5] + this._vertex.z * this._particle._rotationMatrix[8];
+                        rotatedX += pivotBackTranslation.x;
+                        rotatedY += pivotBackTranslation.y;
+                        rotatedZ += pivotBackTranslation.z;
 
-                        this._rotated.x += this._pivotBackTranslation.x;
-                        this._rotated.y += this._pivotBackTranslation.y;
-                        this._rotated.z += this._pivotBackTranslation.z;
-
-                        this._positions32[idx] = this._particle._globalPosition.x + this._cam_axisX.x * this._rotated.x + this._cam_axisY.x * this._rotated.y + this._cam_axisZ.x * this._rotated.z;
-                        this._positions32[idx + 1] = this._particle._globalPosition.y + this._cam_axisX.y * this._rotated.x + this._cam_axisY.y * this._rotated.y + this._cam_axisZ.y * this._rotated.z;
-                        this._positions32[idx + 2] = this._particle._globalPosition.z + this._cam_axisX.z * this._rotated.x + this._cam_axisY.z * this._rotated.y + this._cam_axisZ.z * this._rotated.z;
+                        positions32[idx] = globalPosition.x + camAxisX.x * rotatedX + camAxisY.x * rotatedY + camAxisZ.x * rotatedZ;
+                        positions32[idx + 1] = globalPosition.y + camAxisX.y * rotatedX + camAxisY.y * rotatedY + camAxisZ.y * rotatedZ;
+                        positions32[idx + 2] = globalPosition.z + camAxisX.z * rotatedX + camAxisY.z * rotatedY + camAxisZ.z * rotatedZ;
 
                         if (this._computeBoundingBox) {
-                            if (this._positions32[idx] < this._minimum.x) {
-                                this._minimum.x = this._positions32[idx];
-                            }
-                            if (this._positions32[idx] > this._maximum.x) {
-                                this._maximum.x = this._positions32[idx];
-                            }
-                            if (this._positions32[idx + 1] < this._minimum.y) {
-                                this._minimum.y = this._positions32[idx + 1];
-                            }
-                            if (this._positions32[idx + 1] > this._maximum.y) {
-                                this._maximum.y = this._positions32[idx + 1];
-                            }
-                            if (this._positions32[idx + 2] < this._minimum.z) {
-                                this._minimum.z = this._positions32[idx + 2];
-                            }
-                            if (this._positions32[idx + 2] > this._maximum.z) {
-                                this._maximum.z = this._positions32[idx + 2];
-                            }
+                            minimum.minimizeInPlaceFromFloats(positions32[idx], positions32[idx+1], positions32[idx+1]);
+                            maximum.maximizeInPlaceFromFloats(positions32[idx], positions32[idx+1], positions32[idx+1]);
                         }
 
                         // normals : if the particles can't be morphed then just rotate the normals, what is much more faster than ComputeNormals()
                         if (!this._computeParticleVertex) {
-                            this._normal.x = this._fixedNormal32[idx];
-                            this._normal.y = this._fixedNormal32[idx + 1];
-                            this._normal.z = this._fixedNormal32[idx + 2];
+                            const normalx = fixedNormal32[idx];
+                            const normaly = fixedNormal32[idx + 1];
+                            const normalz = fixedNormal32[idx + 2];
 
-                            this._rotated.x = this._normal.x * this._particle._rotationMatrix[0] + this._normal.y * this._particle._rotationMatrix[3] + this._normal.z * this._particle._rotationMatrix[6];
-                            this._rotated.y = this._normal.x * this._particle._rotationMatrix[1] + this._normal.y * this._particle._rotationMatrix[4] + this._normal.z * this._particle._rotationMatrix[7];
-                            this._rotated.z = this._normal.x * this._particle._rotationMatrix[2] + this._normal.y * this._particle._rotationMatrix[5] + this._normal.z * this._particle._rotationMatrix[8];
+                            const rotatedx = normalx * rotationMatrix[0] + normaly * rotationMatrix[3] + normalz * rotationMatrix[6];
+                            const rotatedy = normalx * rotationMatrix[1] + normaly * rotationMatrix[4] + normalz * rotationMatrix[7];
+                            const rotatedz = normalx * rotationMatrix[2] + normaly * rotationMatrix[5] + normalz * rotationMatrix[8];
 
-                            this._normals32[idx] = this._cam_axisX.x * this._rotated.x + this._cam_axisY.x * this._rotated.y + this._cam_axisZ.x * this._rotated.z;
-                            this._normals32[idx + 1] = this._cam_axisX.y * this._rotated.x + this._cam_axisY.y * this._rotated.y + this._cam_axisZ.y * this._rotated.z;
-                            this._normals32[idx + 2] = this._cam_axisX.z * this._rotated.x + this._cam_axisY.z * this._rotated.y + this._cam_axisZ.z * this._rotated.z;
+                            normals32[idx] = camAxisX.x * rotatedx + camAxisY.x * rotatedy + camAxisZ.x * rotatedz;
+                            normals32[idx + 1] = camAxisX.y * rotatedx + camAxisY.y * rotatedy + camAxisZ.y * rotatedz;
+                            normals32[idx + 2] = camAxisX.z * rotatedx + camAxisY.z * rotatedy + camAxisZ.z * rotatedz;
                         }
 
-                        if (this._computeParticleColor && this._particle.color) {
-                            this._colors32[colidx] = this._particle.color.r;
-                            this._colors32[colidx + 1] = this._particle.color.g;
-                            this._colors32[colidx + 2] = this._particle.color.b;
-                            this._colors32[colidx + 3] = this._particle.color.a;
+                        if (this._computeParticleColor && particle.color) {
+                            const color = particle.color;
+                            const colors32 = this._colors32;
+                            colors32[colidx] = color.r;
+                            colors32[colidx + 1] = color.g;
+                            colors32[colidx + 2] = color.b;
+                            colors32[colidx + 3] = color.a;
                         }
 
                         if (this._computeParticleTexture) {
-                            this._uvs32[uvidx] = this._shapeUV[pt * 2] * (this._particle.uvs.z - this._particle.uvs.x) + this._particle.uvs.x;
-                            this._uvs32[uvidx + 1] = this._shapeUV[pt * 2 + 1] * (this._particle.uvs.w - this._particle.uvs.y) + this._particle.uvs.y;
+                            const uvs = particle.uvs;
+                            uvs32[uvidx] = shapeUV[pt * 2] * (uvs.z - uvs.x) + uvs.x;
+                            uvs32[uvidx + 1] = shapeUV[pt * 2 + 1] * (uvs.w - uvs.y) + uvs.y;
                         }
                     }
                 }
                 // particle just set invisible : scaled to zero and positioned at the origin
                 else {
-                    this._particle._stillInvisible = true;      // mark the particle as invisible
-                    for (pt = 0; pt < this._shape.length; pt++) {
+                    particle._stillInvisible = true;      // mark the particle as invisible
+                    for (pt = 0; pt < shape.length; pt++) {
                         idx = index + pt * 3;
                         colidx = colorIndex + pt * 4;
                         uvidx = uvIndex + pt * 2;
 
-                        this._positions32[idx] = 0.0;
-                        this._positions32[idx + 1] = 0.0;
-                        this._positions32[idx + 2] = 0.0;
-                        this._normals32[idx] = 0.0;
-                        this._normals32[idx + 1] = 0.0;
-                        this._normals32[idx + 2] = 0.0;
-                        if (this._computeParticleColor && this._particle.color) {
-                            this._colors32[colidx] = this._particle.color.r;
-                            this._colors32[colidx + 1] = this._particle.color.g;
-                            this._colors32[colidx + 2] = this._particle.color.b;
-                            this._colors32[colidx + 3] = this._particle.color.a;
+                        positions32[idx] = 0.0;
+                        positions32[idx + 1] = 0.0;
+                        positions32[idx + 2] = 0.0;
+                        normals32[idx] = 0.0;
+                        normals32[idx + 1] = 0.0;
+                        normals32[idx + 2] = 0.0;
+                        if (this._computeParticleColor && particle.color) {
+                            const color = particle.color;
+                            colors32[colidx] = color.r;
+                            colors32[colidx + 1] = color.g;
+                            colors32[colidx + 2] = color.b;
+                            colors32[colidx + 3] = color.a;
                         }
                         if (this._computeParticleTexture) {
-                            this._uvs32[uvidx] = this._shapeUV[pt * 2] * (this._particle.uvs.z - this._particle.uvs.x) + this._particle.uvs.x;
-                            this._uvs32[uvidx + 1] = this._shapeUV[pt * 2 + 1] * (this._particle.uvs.w - this._particle.uvs.y) + this._particle.uvs.y;
+                            const uvs = particle.uvs;
+                            uvs32[uvidx] = shapeUV[pt * 2] * (uvs.z - uvs.x) + uvs.x;
+                            uvs32[uvidx + 1] = shapeUV[pt * 2 + 1] * (uvs.w - uvs.y) + uvs.y;
                         }
                     }
                 }
 
                 // if the particle intersections must be computed : update the bbInfo
                 if (this._particlesIntersect) {
-                    var bInfo = this._particle._boundingInfo;
-                    var bBox = bInfo.boundingBox;
-                    var bSphere = bInfo.boundingSphere;
+                    const bInfo = particle._boundingInfo;
+                    const bBox = bInfo.boundingBox;
+                    const bSphere = bInfo.boundingSphere;
+                    const modelBoundingInfo = particle._modelBoundingInfo;
                     if (!this._bSphereOnly) {
                         // place, scale and rotate the particle bbox within the SPS local system, then update it
-                        for (var b = 0; b < bBox.vectors.length; b++) {
-                            this._vertex.x = this._particle._modelBoundingInfo.boundingBox.vectors[b].x * this._particle.scaling.x;
-                            this._vertex.y = this._particle._modelBoundingInfo.boundingBox.vectors[b].y * this._particle.scaling.y;
-                            this._vertex.z = this._particle._modelBoundingInfo.boundingBox.vectors[b].z * this._particle.scaling.z;
-                            this._rotated.x = this._vertex.x * this._particle._rotationMatrix[0] + this._vertex.y * this._particle._rotationMatrix[3] + this._vertex.z * this._particle._rotationMatrix[6];
-                            this._rotated.y = this._vertex.x * this._particle._rotationMatrix[1] + this._vertex.y * this._particle._rotationMatrix[4] + this._vertex.z * this._particle._rotationMatrix[7];
-                            this._rotated.z = this._vertex.x * this._particle._rotationMatrix[2] + this._vertex.y * this._particle._rotationMatrix[5] + this._vertex.z * this._particle._rotationMatrix[8];
-                            bBox.vectors[b].x = this._particle.position.x + this._cam_axisX.x * this._rotated.x + this._cam_axisY.x * this._rotated.y + this._cam_axisZ.x * this._rotated.z;
-                            bBox.vectors[b].y = this._particle.position.y + this._cam_axisX.y * this._rotated.x + this._cam_axisY.y * this._rotated.y + this._cam_axisZ.y * this._rotated.z;
-                            bBox.vectors[b].z = this._particle.position.z + this._cam_axisX.z * this._rotated.x + this._cam_axisY.z * this._rotated.y + this._cam_axisZ.z * this._rotated.z;
+                        const modelBoundingInfoVectors = modelBoundingInfo.boundingBox.vectors;
+                        const min = Tmp.Vector3[0];
+                        const max = Tmp.Vector3[1];
+                        min.setAll(Number.MAX_VALUE);
+                        max.setAll(-Number.MAX_VALUE);
+                        for (var b = 0; b < 8; b++) {
+                            const vertexX = modelBoundingInfoVectors[b].x * scaling.x;
+                            const vertexY = modelBoundingInfoVectors[b].y * scaling.y;
+                            const vertexZ = modelBoundingInfoVectors[b].z * scaling.z;
+                            const rotatedX = vertexX * rotationMatrix[0] + vertexY * rotationMatrix[3] + vertexZ * rotationMatrix[6];
+                            const rotatedY = vertexX * rotationMatrix[1] + vertexY * rotationMatrix[4] + vertexZ * rotationMatrix[7];
+                            const rotatedZ = vertexX * rotationMatrix[2] + vertexY * rotationMatrix[5] + vertexZ * rotationMatrix[8];
+                            const x = position.x + camAxisX.x * rotatedX + camAxisY.x * rotatedY + camAxisZ.x * rotatedZ;
+                            const y = position.y + camAxisX.y * rotatedX + camAxisY.y * rotatedY + camAxisZ.y * rotatedZ;
+                            const z = position.z + camAxisX.z * rotatedX + camAxisY.z * rotatedY + camAxisZ.z * rotatedZ;
+                            min.minimizeInPlaceFromFloats(x, y, z);
+                            max.maximizeInPlaceFromFloats(x, y, z);
                         }
-                        bBox._update(this.mesh._worldMatrix);
+
+                        bBox.reConstruct(min, max, mesh._worldMatrix);
                     }
                     // place and scale the particle bouding sphere in the SPS local system, then update it
-                    this._minBbox.x = this._particle._modelBoundingInfo.minimum.x * this._particle.scaling.x;
-                    this._minBbox.y = this._particle._modelBoundingInfo.minimum.y * this._particle.scaling.y;
-                    this._minBbox.z = this._particle._modelBoundingInfo.minimum.z * this._particle.scaling.z;
-                    this._maxBbox.x = this._particle._modelBoundingInfo.maximum.x * this._particle.scaling.x;
-                    this._maxBbox.y = this._particle._modelBoundingInfo.maximum.y * this._particle.scaling.y;
-                    this._maxBbox.z = this._particle._modelBoundingInfo.maximum.z * this._particle.scaling.z;
-                    bSphere.center.x = this._particle._globalPosition.x + (this._minBbox.x + this._maxBbox.x) * 0.5;
-                    bSphere.center.y = this._particle._globalPosition.y + (this._minBbox.y + this._maxBbox.y) * 0.5;
-                    bSphere.center.z = this._particle._globalPosition.z + (this._minBbox.z + this._maxBbox.z) * 0.5;
-                    bSphere.radius = this._bSphereRadiusFactor * 0.5 * Math.sqrt((this._maxBbox.x - this._minBbox.x) * (this._maxBbox.x - this._minBbox.x) + (this._maxBbox.y - this._minBbox.y) * (this._maxBbox.y - this._minBbox.y) + (this._maxBbox.z - this._minBbox.z) * (this._maxBbox.z - this._minBbox.z));
-                    bSphere._update(this.mesh._worldMatrix);
+                    const minBbox = modelBoundingInfo.minimum.multiplyToRef(scaling, Tmp.Vector3[0]);
+                    const maxBbox = modelBoundingInfo.maximum.multiplyToRef(scaling, Tmp.Vector3[1]);
+
+                    const center = maxBbox.addToRef(minBbox, Tmp.Vector3[2]).scaleInPlace(0.5);
+                    const halfDiag  = maxBbox.subtractToRef(minBbox, Tmp.Vector3[3]).scaleInPlace(0.5 * this._bSphereRadiusFactor);
+                    const sphereMinBbox = center.subtractToRef(halfDiag, Tmp.Vector3[4]);
+                    const sphereMaxBbox = center.addToRef(halfDiag, Tmp.Vector3[5]);
+                    bSphere.reConstruct(sphereMinBbox, sphereMaxBbox, mesh._worldMatrix);
                 }
 
                 // increment indexes for the next particle
@@ -1001,84 +938,91 @@
             // if the VBO must be updated
             if (update) {
                 if (this._computeParticleColor) {
-                    this.mesh.updateVerticesData(VertexBuffer.ColorKind, this._colors32, false, false);
+                    mesh.updateVerticesData(VertexBuffer.ColorKind, colors32, false, false);
                 }
                 if (this._computeParticleTexture) {
-                    this.mesh.updateVerticesData(VertexBuffer.UVKind, this._uvs32, false, false);
+                    mesh.updateVerticesData(VertexBuffer.UVKind, uvs32, false, false);
                 }
-                this.mesh.updateVerticesData(VertexBuffer.PositionKind, this._positions32, false, false);
-                if (!this.mesh.areNormalsFrozen || this.mesh.isFacetDataEnabled) {
-                    if (this._computeParticleVertex || this.mesh.isFacetDataEnabled) {
+                mesh.updateVerticesData(VertexBuffer.PositionKind, positions32, false, false);
+                if (!mesh.areNormalsFrozen || mesh.isFacetDataEnabled) {
+                    if (this._computeParticleVertex || mesh.isFacetDataEnabled) {
                         // recompute the normals only if the particles can be morphed, update then also the normal reference array _fixedNormal32[]
-                        var params = this.mesh.isFacetDataEnabled ? this.mesh.getFacetDataParameters() : null;
-                        VertexData.ComputeNormals(this._positions32, this._indices32, this._normals32, params);
-                        for (var i = 0; i < this._normals32.length; i++) {
-                            this._fixedNormal32[i] = this._normals32[i];
+                        var params = mesh.isFacetDataEnabled ? mesh.getFacetDataParameters() : null;
+                        VertexData.ComputeNormals(positions32, indices32, normals32, params);
+                        for (var i = 0; i < normals32.length; i++) {
+                            fixedNormal32[i] = normals32[i];
                         }
                     }
-                    if (!this.mesh.areNormalsFrozen) {
-                        this.mesh.updateVerticesData(VertexBuffer.NormalKind, this._normals32, false, false);
+                    if (!mesh.areNormalsFrozen) {
+                        mesh.updateVerticesData(VertexBuffer.NormalKind, normals32, false, false);
                     }
                 }
                 if (this._depthSort && this._depthSortParticles) {
-                    this.depthSortedParticles.sort(this._depthSortFunction);
-                    var dspl = this.depthSortedParticles.length;
+                    const depthSortedParticles = this.depthSortedParticles;
+                    depthSortedParticles.sort(this._depthSortFunction);
+                    var dspl = depthSortedParticles.length;
                     var sorted = 0;
                     var lind = 0;
                     var sind = 0;
                     var sid = 0;
                     for (sorted = 0; sorted < dspl; sorted++) {
-                        lind = this.depthSortedParticles[sorted].indicesLength;
-                        sind = this.depthSortedParticles[sorted].ind;
+                        lind = depthSortedParticles[sorted].indicesLength;
+                        sind = depthSortedParticles[sorted].ind;
                         for (var i = 0; i < lind; i++) {
-                            this._indices32[sid] = this._indices[sind + i];
+                            indices32[sid] = indices[sind + i];
                             sid++;
                         }
                     }
-                    this.mesh.updateIndices(this._indices32);
+                    mesh.updateIndices(indices32);
                 }
             }
             if (this._computeBoundingBox) {
-                this.mesh._boundingInfo = new BoundingInfo(this._minimum, this._maximum);
-                this.mesh._boundingInfo.update(this.mesh._worldMatrix);
+                if (mesh._boundingInfo) {
+                    mesh._boundingInfo.reConstruct(minimum, maximum, mesh._worldMatrix);
+                }
+                else {
+                    mesh._boundingInfo = new BoundingInfo(minimum, maximum, mesh._worldMatrix);
+                }
             }
             this.afterUpdateParticles(start, end, update);
             return this;
         }
 
-        private _quaternionRotationYPR(): void {
-            this._halfroll = this._roll * 0.5;
-            this._halfpitch = this._pitch * 0.5;
-            this._halfyaw = this._yaw * 0.5;
-            this._sinRoll = Math.sin(this._halfroll);
-            this._cosRoll = Math.cos(this._halfroll);
-            this._sinPitch = Math.sin(this._halfpitch);
-            this._cosPitch = Math.cos(this._halfpitch);
-            this._sinYaw = Math.sin(this._halfyaw);
-            this._cosYaw = Math.cos(this._halfyaw);
-            this._quaternion.x = this._cosYaw * this._sinPitch * this._cosRoll + this._sinYaw * this._cosPitch * this._sinRoll;
-            this._quaternion.y = this._sinYaw * this._cosPitch * this._cosRoll - this._cosYaw * this._sinPitch * this._sinRoll;
-            this._quaternion.z = this._cosYaw * this._cosPitch * this._sinRoll - this._sinYaw * this._sinPitch * this._cosRoll;
-            this._quaternion.w = this._cosYaw * this._cosPitch * this._cosRoll + this._sinYaw * this._sinPitch * this._sinRoll;
+        private _quaternionRotationYPR(yaw:number, pitch:number, roll:number): void {
+            const halfroll = roll * 0.5;
+            const halfpitch = pitch * 0.5;
+            const halfyaw = yaw * 0.5;
+            const sinRoll = Math.sin(halfroll);
+            const cosRoll = Math.cos(halfroll);
+            const sinPitch = Math.sin(halfpitch);
+            const cosPitch = Math.cos(halfpitch);
+            const sinYaw = Math.sin(halfyaw);
+            const cosYaw = Math.cos(halfyaw);
+            this._quaternion.x = cosYaw * sinPitch * cosRoll + sinYaw * cosPitch * sinRoll;
+            this._quaternion.y = sinYaw * cosPitch * cosRoll - cosYaw * sinPitch * sinRoll;
+            this._quaternion.z = cosYaw * cosPitch * sinRoll - sinYaw * sinPitch * cosRoll;
+            this._quaternion.w = cosYaw * cosPitch * cosRoll + sinYaw * sinPitch * sinRoll;
         }
 
         private _quaternionToRotationMatrix(): void {
-            this._rotMatrix.m[0] = 1.0 - (2.0 * (this._quaternion.y * this._quaternion.y + this._quaternion.z * this._quaternion.z));
-            this._rotMatrix.m[1] = 2.0 * (this._quaternion.x * this._quaternion.y + this._quaternion.z * this._quaternion.w);
-            this._rotMatrix.m[2] = 2.0 * (this._quaternion.z * this._quaternion.x - this._quaternion.y * this._quaternion.w);
-            this._rotMatrix.m[3] = 0;
-            this._rotMatrix.m[4] = 2.0 * (this._quaternion.x * this._quaternion.y - this._quaternion.z * this._quaternion.w);
-            this._rotMatrix.m[5] = 1.0 - (2.0 * (this._quaternion.z * this._quaternion.z + this._quaternion.x * this._quaternion.x));
-            this._rotMatrix.m[6] = 2.0 * (this._quaternion.y * this._quaternion.z + this._quaternion.x * this._quaternion.w);
-            this._rotMatrix.m[7] = 0;
-            this._rotMatrix.m[8] = 2.0 * (this._quaternion.z * this._quaternion.x + this._quaternion.y * this._quaternion.w);
-            this._rotMatrix.m[9] = 2.0 * (this._quaternion.y * this._quaternion.z - this._quaternion.x * this._quaternion.w);
-            this._rotMatrix.m[10] = 1.0 - (2.0 * (this._quaternion.y * this._quaternion.y + this._quaternion.x * this._quaternion.x));
-            this._rotMatrix.m[11] = 0;
-            this._rotMatrix.m[12] = 0;
-            this._rotMatrix.m[13] = 0;
-            this._rotMatrix.m[14] = 0;
-            this._rotMatrix.m[15] = 1.0;
+            const rotMatrixValues = this._rotMatrix.m;
+            const x = this._quaternion.x, y = this._quaternion.y, z = this._quaternion.z, w = this._quaternion.w;
+            rotMatrixValues[0] = 1.0 - (2.0 * (y * y + z * z));
+            rotMatrixValues[1] = 2.0 * (x * y + z * w);
+            rotMatrixValues[2] = 2.0 * (z * x - y * w);
+            rotMatrixValues[3] = 0;
+            rotMatrixValues[4] = 2.0 * (x * y - z * w);
+            rotMatrixValues[5] = 1.0 - (2.0 * (z * z + x * x));
+            rotMatrixValues[6] = 2.0 * (y * z + x * w);
+            rotMatrixValues[7] = 0;
+            rotMatrixValues[8] = 2.0 * (z * x + y * w);
+            rotMatrixValues[9] = 2.0 * (y * z - x * w);
+            rotMatrixValues[10] = 1.0 - (2.0 * (y * y + x * x));
+            rotMatrixValues[11] = 0;
+            rotMatrixValues[12] = 0;
+            rotMatrixValues[13] = 0;
+            rotMatrixValues[14] = 0;
+            rotMatrixValues[15] = 1.0;
         }
 
         /**