Browse Source

fix : updatable SPS + use of positionFunction in addShape()

jbousquie 8 years ago
parent
commit
7b77967d34
2 changed files with 86 additions and 21 deletions
  1. 9 5
      dist/preview release/what's new.md
  2. 77 16
      src/Particles/babylon.solidParticleSystem.ts

+ 9 - 5
dist/preview release/what's new.md

@@ -23,6 +23,15 @@
 - GroundMesh : `getHeightAtCoordinates()`, `getNormalAtCoordinates()` and `getNormalAtCoordinatesToRef()` can now work with rotated grounds ([jerome](https://github.com/jbousquie))  
 - `GroundMesh`, `facetData` and `SolidParticleSystem` improvement in normal computations ([jerome](https://github.com/jbousquie))   
 - Added `AbstractMesh.addRotation()` ([jerome](https://github.com/jbousquie))  
+
+### Bug fixes
+ - Fixed an issue with Mesh.attachToBone when a mesh is moving and an animation is changed ([abow](https://github.com/abow))
+ - Fixed an issue withaspect ratio when using CreateScreenshot ([deltakosh](https://github.com/deltakosh))
+ - Fixed SPS particle initial status when used with a `positionFunction` in `addShape()` and set as `updatable` ([jerome](https://github.com/jbousquie))  
+ - Fixed SPS particle access indexes when used with `setParticles(start, end)` ([jerome](https://github.com/jbousquie))  
+
+### Breaking changes
+
  
 ### Canvas2D
 
@@ -46,8 +55,3 @@
     
 ### API doc
 
-### Bug fixes
- - Fixed an issue with Mesh.attachToBone when a mesh is moving and an animation is changed ([abow](https://github.com/abow))
- - Fixed an issue withaspect ratio when using CreateScreenshot ([deltakosh](https://github.com/deltakosh))
-
-### Breaking changes

+ 77 - 16
src/Particles/babylon.solidParticleSystem.ts

@@ -104,6 +104,7 @@
         private _sinYaw: number = 0.0;
         private _cosYaw: number = 0.0;
         private _w: number = 0.0;
+        private _mustUnrotateFixedNormals = false;
         private _minimum: Vector3 = Tmp.Vector3[0];
         private _maximum: Vector3 = Tmp.Vector3[1];
         private _scale: Vector3 = Tmp.Vector3[2];
@@ -114,6 +115,7 @@
         public _bSphereOnly: boolean = false;
         public _bSphereRadiusFactor: number = 1.0;
 
+
         /**
         * Creates a SPS (Solid Particle System) object.
         * `name` (String) is the SPS name, this will be the underlying mesh name.  
@@ -161,6 +163,9 @@
             }
             this._normals32 = new Float32Array(this._normals);
             this._fixedNormal32 = new Float32Array(this._normals);
+            if (this._mustUnrotateFixedNormals) {  // the particles could be created already rotated in the mesh with a positionFunction
+                this._unrotateFixedNormals();
+            }
             var vertexData = new VertexData();
             vertexData.set(this._positions32, VertexBuffer.PositionKind);
             vertexData.indices = this._indices;
@@ -276,8 +281,9 @@
                 var modelShape = new ModelShape(this._shapeCounter, shape, shapeUV, null, null);
 
                 // add the particle in the SPS
+                var currentPos = this._positions.length;
                 this._meshBuilder(this._index, shape, this._positions, facetInd, this._indices, facetUV, this._uvs, facetCol, this._colors, meshNor, this._normals, idx, 0, null);
-                this._addParticle(idx, this._positions.length, modelShape, this._shapeCounter, 0, bInfo);
+                this._addParticle(idx, currentPos, modelShape, this._shapeCounter, 0, bInfo);
                 // initialize the particle position
                 this.particles[this.nbParticles].position.addInPlace(barycenter);
 
@@ -290,6 +296,36 @@
             return this;
         }
 
+        // unrotate the fixed normals in case the mesh was built with pre-rotated particles, ex : use of positionFunction in addShape()
+        private _unrotateFixedNormals() {
+            var index = 0;
+            var idx = 0;
+            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);
+                } 
+                else {
+                    this._yaw = this._particle.rotation.y;
+                    this._pitch = this._particle.rotation.x;
+                    this._roll = this._particle.rotation.z;
+                    this._quaternionRotationYPR();
+                }
+                this._quaternionToRotationMatrix();
+                this._rotMatrix.invertToRef(this._invertMatrix);
+
+                for (var pt = 0; pt < this._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;
+                }
+                index = idx + 3;
+            } 
+        }
+
         //reset copy
         private _resetCopy() {
             this._copy.position.x = 0;
@@ -310,7 +346,7 @@
         }
 
         // _meshBuilder : inserts the shape model in the global SPS mesh
-        private _meshBuilder(p, shape, positions, meshInd, indices, meshUV, uvs, meshCol, colors, meshNor, normals, idx, idxInShape, options): void {
+        private _meshBuilder(p, shape, positions, meshInd, indices, meshUV, uvs, meshCol, colors, meshNor, normals, idx, idxInShape, options): SolidParticle {
             var i;
             var u = 0;
             var c = 0;
@@ -319,6 +355,7 @@
             this._resetCopy();
             if (options && options.positionFunction) {        // call to custom positionFunction
                 options.positionFunction(this._copy, idx, idxInShape);
+                this._mustUnrotateFixedNormals = true;
             }
 
             if (this._copy.rotationQuaternion) {
@@ -371,7 +408,7 @@
                     this._normal.x = meshNor[n];
                     this._normal.y = meshNor[n + 1];
                     this._normal.z = meshNor[n + 2];
-                    Vector3.TransformCoordinatesToRef(this._normal, this._rotMatrix, this._normal);
+                    Vector3.TransformNormalToRef(this._normal, this._rotMatrix, this._normal);
                     normals.push(this._normal.x, this._normal.y, this._normal.z);
                     n += 3;
                 }
@@ -388,6 +425,7 @@
                     this.pickedParticles.push({ idx: idx, faceId: i });
                 }
             }
+            return this._copy;
         }
 
         // returns a shape array from positions array
@@ -410,8 +448,10 @@
         }
 
         // adds a new particle object in the particles array
-        private _addParticle(idx: number, idxpos: number, model: ModelShape, shapeId: number, idxInShape: number, bInfo?: BoundingInfo): void {
-            this.particles.push(new SolidParticle(idx, idxpos, model, shapeId, idxInShape, this, bInfo));
+        private _addParticle(idx: number, idxpos: number, model: ModelShape, shapeId: number, idxInShape: number, bInfo?: BoundingInfo): SolidParticle {
+            var sp = new SolidParticle(idx, idxpos, model, shapeId, idxInShape, this, bInfo);
+            this.particles.push(sp);
+            return sp;
         }
 
         /**
@@ -442,11 +482,24 @@
             var modelShape = new ModelShape(this._shapeCounter, shape, shapeUV, posfunc, vtxfunc);
 
             // particles
+            var sp;
+            var currentCopy;
             var idx = this.nbParticles;
             for (var i = 0; i < nb; i++) {
-                this._meshBuilder(this._index, shape, this._positions, meshInd, this._indices, meshUV, this._uvs, meshCol, this._colors, meshNor, this._normals, idx, i, options);
+                var currentPos = this._positions.length;
+                currentCopy = this._meshBuilder(this._index, shape, this._positions, meshInd, this._indices, meshUV, this._uvs, meshCol, this._colors, meshNor, this._normals, idx, i, options);
                 if (this._updatable) {
-                    this._addParticle(idx, this._positions.length, modelShape, this._shapeCounter, i, bbInfo);
+                    sp = this._addParticle(idx, currentPos, modelShape, this._shapeCounter, i, bbInfo);
+                    sp.position.copyFrom(currentCopy.position);
+                    sp.rotation.copyFrom(currentCopy.rotation);
+                    if (currentCopy.rotationQuaternion) {
+                        sp.rotationQuaternion.copyFrom(currentCopy.rotationQuaternion);
+                    }
+                    if (currentCopy.color) {
+                        sp.color.copyFrom(currentCopy.color);
+                    }
+                    sp.scaling.copyFrom(currentCopy.scaling);
+                    sp.uvs.copyFrom(currentCopy.uvs);
                 }
                 this._index += shape.length;
                 idx++;
@@ -506,13 +559,15 @@
         }
 
         /**
-        * Rebuilds the whole mesh and updates the VBO : custom positions and vertices are recomputed if needed.
+        * Rebuilds the whole mesh and updates the VBO : custom positions and vertices are recomputed if needed.  
+        * Returns the SPS.  
         */
-        public rebuildMesh(): void {
+        public rebuildMesh(): SolidParticleSystem {
             for (var p = 0; p < this.particles.length; p++) {
                 this._rebuildParticle(this.particles[p]);
             }
             this.mesh.updateVerticesData(VertexBuffer.PositionKind, this._positions32, false, false);
+            return this;
         }
 
 
@@ -522,9 +577,10 @@
         *  For an animated SPS, it is usually called within the render loop.
         * @param start The particle index in the particle array where to start to compute the particle property values _(default 0)_
         * @param end The particle index in the particle array where to stop to compute the particle property values _(default nbParticle - 1)_
-        * @param update If the mesh must be finally updated on this call after all the particle computations _(default true)_
+        * @param update If the mesh must be finally updated on this call after all the particle computations _(default true)_   
+        * Returns the SPS.  
         */
-        public setParticles(start: number = 0, end: number = this.nbParticles - 1, update: boolean = true): void {
+        public setParticles(start: number = 0, end: number = this.nbParticles - 1, update: boolean = true): SolidParticleSystem {
             if (!this._updatable) {
                 return;
             }
@@ -580,7 +636,8 @@
             }
 
             // particle loop
-            end = (end > this.nbParticles - 1) ? this.nbParticles - 1 : end;
+            end = (end >= this.nbParticles) ? this.nbParticles - 1 : end;
+            index = this.particles[start]._pos;
             for (var p = start; p <= end; p++) {
                 this._particle = this.particles[p];
                 this._shape = this._particle._model._shape;
@@ -767,7 +824,7 @@
                         VertexData.ComputeNormals(this._positions32, this._indices, this._normals32, params);
                         for (var i = 0; i < this._normals32.length; i++) {
                             this._fixedNormal32[i] = this._normals32[i];
-                        }
+                        }                       
                     }
                     if (!this.mesh.areNormalsFrozen) {
                         this.mesh.updateVerticesData(VertexBuffer.NormalKind, this._normals32, false, false);
@@ -779,6 +836,7 @@
                 this.mesh._boundingInfo.update(this.mesh._worldMatrix);
             }
             this.afterUpdateParticles(start, end, update);
+            return this;
         }
 
         private _quaternionRotationYPR(): void {
@@ -817,7 +875,8 @@
         }
 
         /**
-        * Disposes the SPS
+        * Disposes the SPS.  
+        * Returns nothing.  
         */
         public dispose(): void {
             this.mesh.dispose();
@@ -838,12 +897,14 @@
 
         /**
         * Visibilty helper : Recomputes the visible size according to the mesh bounding box
-        * doc : http://doc.babylonjs.com/overviews/Solid_Particle_System#sps-visibility
+        * doc : http://doc.babylonjs.com/overviews/Solid_Particle_System#sps-visibility   
+        * Returns the SPS.  
         */
-        public refreshVisibleSize(): void {
+        public refreshVisibleSize(): SolidParticleSystem {
             if (!this._isVisibilityBoxLocked) {
                 this.mesh.refreshBoundingInfo();
             }
+            return this;
         }
 
         /**