Selaa lähdekoodia

Merge branch 'master'

Gary Hsu 8 vuotta sitten
vanhempi
commit
fec4fa4d9b

Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 1 - 1
dist/preview release/babylon.core.js


Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 3241 - 3233
dist/preview release/babylon.d.ts


Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 15 - 15
dist/preview release/babylon.js


+ 105 - 17
dist/preview release/babylon.max.js

@@ -31659,7 +31659,7 @@ var BABYLON;
         VertexData.CreateCylinder = function (options) {
             var height = options.height || 2;
             var diameterTop = (options.diameterTop === 0) ? 0 : options.diameterTop || options.diameter || 1;
-            var diameterBottom = options.diameterBottom || options.diameter || 1;
+            var diameterBottom = (options.diameterBottom === 0) ? 0 : options.diameterBottom || options.diameter || 1;
             var tessellation = options.tessellation || 24;
             var subdivisions = options.subdivisions || 1;
             var hasRings = options.hasRings;
@@ -38915,6 +38915,7 @@ var BABYLON;
             this._matrices = {};
             this._matrices3x3 = {};
             this._matrices2x2 = {};
+            this._vectors3Arrays = {};
             this._cachedWorldViewMatrix = new BABYLON.Matrix();
             this._shaderPath = shaderPath;
             options.needAlphaBlending = options.needAlphaBlending || false;
@@ -39001,6 +39002,11 @@ var BABYLON;
             this._matrices2x2[name] = value;
             return this;
         };
+        ShaderMaterial.prototype.setVector3Array = function (name, value) {
+            this._checkUniform(name);
+            this._vectors3Arrays[name] = value;
+            return this;
+        };
         ShaderMaterial.prototype.isReady = function (mesh, useInstances) {
             var scene = this.getScene();
             var engine = scene.getEngine();
@@ -39120,6 +39126,10 @@ var BABYLON;
                 for (name in this._matrices2x2) {
                     this._effect.setMatrix2x2(name, this._matrices2x2[name]);
                 }
+                // Vector3Array   
+                for (name in this._vectors3Arrays) {
+                    this._effect.setArray3(name, this._vectors3Arrays[name]);
+                }
             }
             _super.prototype.bind.call(this, world, mesh);
         };
@@ -39213,6 +39223,11 @@ var BABYLON;
             for (name in this._matrices2x2) {
                 serializationObject.matrices2x2[name] = this._matrices2x2[name];
             }
+            // Vector3Array
+            serializationObject.vectors3Arrays = {};
+            for (name in this._vectors3Arrays) {
+                serializationObject.vectors3Arrays[name] = this._vectors3Arrays[name];
+            }
             return serializationObject;
         };
         ShaderMaterial.Parse = function (source, scene, rootUrl) {
@@ -39271,6 +39286,10 @@ var BABYLON;
             for (name in source.matrices2x2) {
                 material.setMatrix2x2(name, source.matrices2x2[name]);
             }
+            // Vector3Array
+            for (name in source.vectors3Arrays) {
+                material.setVector3Array(name, source.vectors3Arrays[name]);
+            }
             return material;
         };
         return ShaderMaterial;
@@ -47325,20 +47344,28 @@ var BABYLON;
 var BABYLON;
 (function (BABYLON) {
     var SolidParticle = (function () {
-        function SolidParticle(particleIndex, positionIndex, model, shapeId, idxInShape) {
-            this.color = new BABYLON.Color4(1, 1, 1, 1); // color
+        function SolidParticle(particleIndex, positionIndex, model, shapeId, idxInShape, modelBoundingInfo) {
+            this.idx = 0; // particle global index
+            this.color = new BABYLON.Color4(1.0, 1.0, 1.0, 1.0); // color
             this.position = BABYLON.Vector3.Zero(); // position
             this.rotation = BABYLON.Vector3.Zero(); // rotation
-            this.scaling = new BABYLON.Vector3(1, 1, 1); // scaling
-            this.uvs = new BABYLON.Vector4(0, 0, 1, 1); // uvs
+            this.scaling = new BABYLON.Vector3(1.0, 1.0, 1.0); // scaling
+            this.uvs = new BABYLON.Vector4(0.0, 0.0, 1.0, 1.0); // uvs
             this.velocity = BABYLON.Vector3.Zero(); // velocity
             this.alive = true; // alive
             this.isVisible = true; // visibility
+            this._pos = 0; // index of this particle in the global "positions" array
+            this.shapeId = 0; // model shape id
+            this.idxInShape = 0; // index of the particle in its shape id
             this.idx = particleIndex;
             this._pos = positionIndex;
             this._model = model;
             this.shapeId = shapeId;
             this.idxInShape = idxInShape;
+            if (modelBoundingInfo) {
+                this._modelBoundingInfo = modelBoundingInfo;
+                this._boundingInfo = new BABYLON.BoundingInfo(modelBoundingInfo.minimum, modelBoundingInfo.maximum);
+            }
         }
         Object.defineProperty(SolidParticle.prototype, "scale", {
             //legacy support, changed scale to scaling
@@ -47362,6 +47389,12 @@ var BABYLON;
             enumerable: true,
             configurable: true
         });
+        SolidParticle.prototype.intersectsMesh = function (target) {
+            if (!this._boundingInfo || !target._boundingInfo) {
+                return false;
+            }
+            return this._boundingInfo.intersects(target._boundingInfo, false);
+        };
         return SolidParticle;
     }());
     BABYLON.SolidParticle = SolidParticle;
@@ -47390,6 +47423,7 @@ var BABYLON;
         * `scene` (Scene) is the scene in which the SPS is added.
         * `updatable` (default true) : if the SPS must be updatable or immutable.
         * `isPickable` (default false) : if the solid particles must be pickable.
+        * `particleIntersection` (default false) : if the solid particle intersections must be computed
         */
         function SolidParticleSystem(name, scene, options) {
             // public members
@@ -47467,10 +47501,12 @@ var BABYLON;
             this._maximum = BABYLON.Tmp.Vector3[1];
             this._scale = BABYLON.Tmp.Vector3[2];
             this._translation = BABYLON.Tmp.Vector3[3];
+            this._particlesIntersect = false;
             this.name = name;
             this._scene = scene;
             this._camera = scene.activeCamera;
             this._pickable = options ? options.isPickable : false;
+            this._particlesIntersect = options ? options.particleIntersection : false;
             if (options && options.updatable) {
                 this._updatable = options.updatable;
             }
@@ -47720,8 +47756,8 @@ var BABYLON;
             return shapeUV;
         };
         // adds a new particle object in the particles array
-        SolidParticleSystem.prototype._addParticle = function (idx, idxpos, model, shapeId, idxInShape) {
-            this.particles.push(new BABYLON.SolidParticle(idx, idxpos, model, shapeId, idxInShape));
+        SolidParticleSystem.prototype._addParticle = function (idx, idxpos, model, shapeId, idxInShape, bbInfo) {
+            this.particles.push(new BABYLON.SolidParticle(idx, idxpos, model, shapeId, idxInShape, bbInfo));
         };
         /**
         * Adds some particles to the SPS from the model shape. Returns the shape id.
@@ -47737,6 +47773,10 @@ var BABYLON;
             var meshUV = mesh.getVerticesData(BABYLON.VertexBuffer.UVKind);
             var meshCol = mesh.getVerticesData(BABYLON.VertexBuffer.ColorKind);
             var meshNor = mesh.getVerticesData(BABYLON.VertexBuffer.NormalKind);
+            var bbInfo;
+            if (this._particlesIntersect) {
+                bbInfo = mesh.getBoundingInfo();
+            }
             var shape = this._posToShape(meshPos);
             var shapeUV = this._uvsToShapeUV(meshUV);
             var posfunc = options ? options.positionFunction : null;
@@ -47747,7 +47787,7 @@ var BABYLON;
             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);
                 if (this._updatable) {
-                    this._addParticle(idx, this._positions.length, modelShape, this._shapeCounter, i);
+                    this._addParticle(idx, this._positions.length, modelShape, this._shapeCounter, i, bbInfo);
                 }
                 this._index += shape.length;
                 idx++;
@@ -47788,16 +47828,16 @@ var BABYLON;
                 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;
             }
-            particle.position.x = 0;
-            particle.position.y = 0;
-            particle.position.z = 0;
-            particle.rotation.x = 0;
-            particle.rotation.y = 0;
-            particle.rotation.z = 0;
+            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.rotationQuaternion = null;
-            particle.scaling.x = 1;
-            particle.scaling.y = 1;
-            particle.scaling.z = 1;
+            particle.scaling.x = 1.0;
+            particle.scaling.y = 1.0;
+            particle.scaling.z = 1.0;
         };
         /**
         * Rebuilds the whole mesh and updates the VBO : custom positions and vertices are recomputed if needed.
@@ -47978,6 +48018,54 @@ var BABYLON;
                         }
                     }
                 }
+                // 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;
+                    // place, scale and rotate the particle bbox within the SPS local system
+                    for (var b = 0; b < bBox.vectors.length; b++) {
+                        if (this._particle.isVisible) {
+                            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._w = (this._vertex.x * this._rotMatrix.m[3]) + (this._vertex.y * this._rotMatrix.m[7]) + (this._vertex.z * this._rotMatrix.m[11]) + this._rotMatrix.m[15];
+                            this._rotated.x = ((this._vertex.x * this._rotMatrix.m[0]) + (this._vertex.y * this._rotMatrix.m[4]) + (this._vertex.z * this._rotMatrix.m[8]) + this._rotMatrix.m[12]) / this._w;
+                            this._rotated.y = ((this._vertex.x * this._rotMatrix.m[1]) + (this._vertex.y * this._rotMatrix.m[5]) + (this._vertex.z * this._rotMatrix.m[9]) + this._rotMatrix.m[13]) / this._w;
+                            this._rotated.z = ((this._vertex.x * this._rotMatrix.m[2]) + (this._vertex.y * this._rotMatrix.m[6]) + (this._vertex.z * this._rotMatrix.m[10]) + this._rotMatrix.m[14]) / this._w;
+                            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;
+                        }
+                        else {
+                            bBox.vectors[b].x = this._camera.position.x;
+                            bBox.vectors[b].y = this._camera.position.y;
+                            bBox.vectors[b].z = this._camera.position.z;
+                        }
+                    }
+                    // place and scale the particle bouding sphere in the SPS local system
+                    if (this._particle.isVisible) {
+                        this._minimum.x = this._particle._modelBoundingInfo.minimum.x * this._particle.scaling.x;
+                        this._minimum.y = this._particle._modelBoundingInfo.minimum.y * this._particle.scaling.y;
+                        this._minimum.z = this._particle._modelBoundingInfo.minimum.z * this._particle.scaling.z;
+                        this._maximum.x = this._particle._modelBoundingInfo.maximum.x * this._particle.scaling.x;
+                        this._maximum.y = this._particle._modelBoundingInfo.maximum.y * this._particle.scaling.y;
+                        this._maximum.z = this._particle._modelBoundingInfo.maximum.z * this._particle.scaling.z;
+                        bSphere.center.x = this._particle.position.x + (this._minimum.x + this._maximum.x) * 0.5;
+                        bSphere.center.y = this._particle.position.y + (this._minimum.y + this._maximum.y) * 0.5;
+                        bSphere.center.z = this._particle.position.z + (this._minimum.z + this._maximum.z) * 0.5;
+                        bSphere.radius = BABYLON.Vector3.Distance(this._minimum, this._maximum) * 0.5;
+                    }
+                    else {
+                        bSphere.center.x = this._camera.position.x;
+                        bSphere.center.y = this._camera.position.x;
+                        bSphere.center.z = this._camera.position.x;
+                        bSphere.radius = 0.0;
+                    }
+                    // then update the bbox and the bsphere into the world system
+                    bBox._update(this.mesh.getWorldMatrix());
+                    bSphere._update(this.mesh.getWorldMatrix());
+                }
                 // increment indexes for the next particle
                 index = idx + 3;
                 colorIndex = colidx + 4;

Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 15 - 15
dist/preview release/babylon.noworker.js


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

@@ -17,6 +17,7 @@
 - Several memory allocation reduction ([benaadams](https://github.com/benaadams))
 - Several GPU state change reduction ([benaadams](https://github.com/benaadams)) 
 - MapTexture: add `supersample` mode to double font quality. ([nockawa](https://github.com/nockawa))
+- New SPS feature : solid particle intersection with other solid particle or with any mesh `particle.intersectsMesh()` ([jerome](https://github.com/jbousquie))
 - New `invertUV` parameter an all ribbon based shapes : ribbon, tube, lathe, basic and custom extrusion ([jerome](https://github.com/jbousquie))
 - Text2D: new `fontSuperSample` setting to use high quality font ([nockawa](https://github.com/nockawa))
 - PerfCounter class added to monitor time/counter and expose min/max/average/lastSecondAverage/current metrics. Updated engine/scene current counter to use this class, exposing new properties as well to access the PerfCounter object ([nockawa](https://github.com/nockawa))

+ 19 - 0
src/Materials/babylon.shaderMaterial.js

@@ -21,6 +21,7 @@ var BABYLON;
             this._matrices = {};
             this._matrices3x3 = {};
             this._matrices2x2 = {};
+            this._vectors3Arrays = {};
             this._cachedWorldViewMatrix = new BABYLON.Matrix();
             this._shaderPath = shaderPath;
             options.needAlphaBlending = options.needAlphaBlending || false;
@@ -107,6 +108,11 @@ var BABYLON;
             this._matrices2x2[name] = value;
             return this;
         };
+        ShaderMaterial.prototype.setVector3Array = function (name, value) {
+            this._checkUniform(name);
+            this._vectors3Arrays[name] = value;
+            return this;
+        };
         ShaderMaterial.prototype.isReady = function (mesh, useInstances) {
             var scene = this.getScene();
             var engine = scene.getEngine();
@@ -226,6 +232,10 @@ var BABYLON;
                 for (name in this._matrices2x2) {
                     this._effect.setMatrix2x2(name, this._matrices2x2[name]);
                 }
+                // Vector3Array   
+                for (name in this._vectors3Arrays) {
+                    this._effect.setArray3(name, this._vectors3Arrays[name]);
+                }
             }
             _super.prototype.bind.call(this, world, mesh);
         };
@@ -319,6 +329,11 @@ var BABYLON;
             for (name in this._matrices2x2) {
                 serializationObject.matrices2x2[name] = this._matrices2x2[name];
             }
+            // Vector3Array
+            serializationObject.vectors3Arrays = {};
+            for (name in this._vectors3Arrays) {
+                serializationObject.vectors3Arrays[name] = this._vectors3Arrays[name];
+            }
             return serializationObject;
         };
         ShaderMaterial.Parse = function (source, scene, rootUrl) {
@@ -377,6 +392,10 @@ var BABYLON;
             for (name in source.matrices2x2) {
                 material.setMatrix2x2(name, source.matrices2x2[name]);
             }
+            // Vector3Array
+            for (name in source.vectors3Arrays) {
+                material.setVector3Array(name, source.vectors3Arrays[name]);
+            }
             return material;
         };
         return ShaderMaterial;

+ 2 - 2
src/Materials/babylon.shaderMaterial.ts

@@ -14,7 +14,7 @@
         private _matrices: { [name: string]: Matrix } = {};
         private _matrices3x3: { [name: string]: Float32Array } = {};
         private _matrices2x2: { [name: string]: Float32Array } = {};
-        private _vectors3Arrays: { [name: string]: Vector3[] } = {};
+        private _vectors3Arrays: { [name: string]: number[] } = {};
         private _cachedWorldViewMatrix = new Matrix();
         private _renderId: number;
 
@@ -137,7 +137,7 @@
             return this;
         }
 
-        public setVector3Array(name: string, value: Vector3[]): ShaderMaterial {
+        public setVector3Array(name: string, value: number[]): ShaderMaterial {
             this._checkUniform(name);
             this._vectors3Arrays[name] = value;
 

+ 1 - 1
src/Mesh/babylon.mesh.vertexData.js

@@ -646,7 +646,7 @@ var BABYLON;
         VertexData.CreateCylinder = function (options) {
             var height = options.height || 2;
             var diameterTop = (options.diameterTop === 0) ? 0 : options.diameterTop || options.diameter || 1;
-            var diameterBottom = options.diameterBottom || options.diameter || 1;
+            var diameterBottom = (options.diameterBottom === 0) ? 0 : options.diameterBottom || options.diameter || 1;
             var tessellation = options.tessellation || 24;
             var subdivisions = options.subdivisions || 1;
             var hasRings = options.hasRings;

+ 2 - 2
src/Mesh/babylon.mesh.vertexData.ts

@@ -800,7 +800,7 @@
         public static CreateCylinder(options: { height?: number, diameterTop?: number, diameterBottom?: number, diameter?: number, tessellation?: number, subdivisions?: number, arc?: number, faceColors?: Color4[], faceUV?: Vector4[], hasRings?: boolean, enclose?: boolean, sideOrientation?: number }): VertexData {
             var height: number = options.height || 2;
             var diameterTop: number = (options.diameterTop === 0) ? 0 : options.diameterTop || options.diameter || 1;
-            var diameterBottom: number = options.diameterBottom || options.diameter || 1;
+            var diameterBottom: number = (options.diameterBottom === 0) ? 0 : options.diameterBottom || options.diameter || 1;
             var tessellation: number = options.tessellation || 24;
             var subdivisions: number = options.subdivisions || 1;
             var hasRings: boolean = options.hasRings;
@@ -809,12 +809,12 @@
             var sideOrientation: number = (options.sideOrientation === 0) ? 0 : options.sideOrientation || Mesh.DEFAULTSIDE;
             var faceUV: Vector4[] = options.faceUV || new Array<Vector4>(3);
             var faceColors: Color4[] = options.faceColors;
-
             // default face colors and UV if undefined
             var quadNb: number = (arc !== 1 && enclose) ? 2 : 0;
             var ringNb: number = (hasRings) ? subdivisions : 1;
             var surfaceNb: number = 2 + (1 + quadNb) * ringNb;
             var f: number;
+
             for (f = 0; f < surfaceNb; f++) {
                 if (faceColors && faceColors[f] === undefined) {
                     faceColors[f] = new Color4(1, 1, 1, 1);

+ 18 - 4
src/Particles/babylon.solidParticle.js

@@ -1,20 +1,28 @@
 var BABYLON;
 (function (BABYLON) {
     var SolidParticle = (function () {
-        function SolidParticle(particleIndex, positionIndex, model, shapeId, idxInShape) {
-            this.color = new BABYLON.Color4(1, 1, 1, 1); // color
+        function SolidParticle(particleIndex, positionIndex, model, shapeId, idxInShape, modelBoundingInfo) {
+            this.idx = 0; // particle global index
+            this.color = new BABYLON.Color4(1.0, 1.0, 1.0, 1.0); // color
             this.position = BABYLON.Vector3.Zero(); // position
             this.rotation = BABYLON.Vector3.Zero(); // rotation
-            this.scaling = new BABYLON.Vector3(1, 1, 1); // scaling
-            this.uvs = new BABYLON.Vector4(0, 0, 1, 1); // uvs
+            this.scaling = new BABYLON.Vector3(1.0, 1.0, 1.0); // scaling
+            this.uvs = new BABYLON.Vector4(0.0, 0.0, 1.0, 1.0); // uvs
             this.velocity = BABYLON.Vector3.Zero(); // velocity
             this.alive = true; // alive
             this.isVisible = true; // visibility
+            this._pos = 0; // index of this particle in the global "positions" array
+            this.shapeId = 0; // model shape id
+            this.idxInShape = 0; // index of the particle in its shape id
             this.idx = particleIndex;
             this._pos = positionIndex;
             this._model = model;
             this.shapeId = shapeId;
             this.idxInShape = idxInShape;
+            if (modelBoundingInfo) {
+                this._modelBoundingInfo = modelBoundingInfo;
+                this._boundingInfo = new BABYLON.BoundingInfo(modelBoundingInfo.minimum, modelBoundingInfo.maximum);
+            }
         }
         Object.defineProperty(SolidParticle.prototype, "scale", {
             //legacy support, changed scale to scaling
@@ -38,6 +46,12 @@ var BABYLON;
             enumerable: true,
             configurable: true
         });
+        SolidParticle.prototype.intersectsMesh = function (target) {
+            if (!this._boundingInfo || !target._boundingInfo) {
+                return false;
+            }
+            return this._boundingInfo.intersects(target._boundingInfo, false);
+        };
         return SolidParticle;
     }());
     BABYLON.SolidParticle = SolidParticle;

+ 29 - 16
src/Particles/babylon.solidParticle.ts

@@ -1,27 +1,33 @@
 module BABYLON {
 
     export class SolidParticle {
-        public idx: number;                     // particle global index
-        public color = new Color4(1, 1, 1, 1);  // color
-        public position = Vector3.Zero();       // position
-        public rotation = Vector3.Zero();       // rotation
-        public rotationQuaternion: Quaternion;    // quaternion, will overwrite rotation
-        public scaling = new Vector3(1, 1, 1);  // scaling
-        public uvs = new Vector4(0, 0, 1, 1);   // uvs
-        public velocity = Vector3.Zero();       // velocity
-        public alive = true;                    // alive
-        public isVisible = true;                // visibility
-        public _pos: number;                    // index of this particle in the global "positions" array
-        public _model: ModelShape;              // model shape reference
-        public shapeId: number;                 // model shape id
-        public idxInShape: number;              // index of the particle in its shape id
-
-        constructor(particleIndex: number, positionIndex: number, model: ModelShape, shapeId: number, idxInShape: number) {
+        public idx: number = 0;                         // particle global index
+        public color = new Color4(1.0, 1.0, 1.0, 1.0);  // color
+        public position = Vector3.Zero();               // position
+        public rotation = Vector3.Zero();               // rotation
+        public rotationQuaternion: Quaternion;          // quaternion, will overwrite rotation
+        public scaling = new Vector3(1.0, 1.0, 1.0);    // scaling
+        public uvs = new Vector4(0.0, 0.0, 1.0, 1.0);   // uvs
+        public velocity = Vector3.Zero();               // velocity
+        public alive = true;                            // alive
+        public isVisible = true;                        // visibility
+        public _pos: number = 0;                        // index of this particle in the global "positions" array
+        public _model: ModelShape;                      // model shape reference
+        public shapeId: number = 0;                     // model shape id
+        public idxInShape: number = 0;                  // index of the particle in its shape id
+        public _modelBoundingInfo: BoundingInfo;        // reference to the shape model BoundingInfo object
+        public _boundingInfo: BoundingInfo;             // particle BoundingInfo
+
+        constructor(particleIndex: number, positionIndex: number, model: ModelShape, shapeId: number, idxInShape: number, modelBoundingInfo?: BoundingInfo) {
             this.idx = particleIndex;
             this._pos = positionIndex;
             this._model = model;
             this.shapeId = shapeId;
             this.idxInShape = idxInShape;
+            if (modelBoundingInfo) {
+                this._modelBoundingInfo = modelBoundingInfo;
+                this._boundingInfo = new BoundingInfo(modelBoundingInfo.minimum, modelBoundingInfo.maximum);
+            }
         }
 
         //legacy support, changed scale to scaling
@@ -41,6 +47,13 @@ module BABYLON {
         public set quaternion(q: Quaternion) {
             this.rotationQuaternion = q;
         }
+
+        public intersectsMesh(target: Mesh | SolidParticle): boolean {
+            if (!this._boundingInfo || !target._boundingInfo) {
+                return false;
+            }
+            return this._boundingInfo.intersects(target._boundingInfo, false);
+        }
     }
 
     export class ModelShape {

+ 67 - 12
src/Particles/babylon.solidParticleSystem.js

@@ -10,6 +10,7 @@ var BABYLON;
         * `scene` (Scene) is the scene in which the SPS is added.
         * `updatable` (default true) : if the SPS must be updatable or immutable.
         * `isPickable` (default false) : if the solid particles must be pickable.
+        * `particleIntersection` (default false) : if the solid particle intersections must be computed
         */
         function SolidParticleSystem(name, scene, options) {
             // public members
@@ -87,10 +88,12 @@ var BABYLON;
             this._maximum = BABYLON.Tmp.Vector3[1];
             this._scale = BABYLON.Tmp.Vector3[2];
             this._translation = BABYLON.Tmp.Vector3[3];
+            this._particlesIntersect = false;
             this.name = name;
             this._scene = scene;
             this._camera = scene.activeCamera;
             this._pickable = options ? options.isPickable : false;
+            this._particlesIntersect = options ? options.particleIntersection : false;
             if (options && options.updatable) {
                 this._updatable = options.updatable;
             }
@@ -340,8 +343,8 @@ var BABYLON;
             return shapeUV;
         };
         // adds a new particle object in the particles array
-        SolidParticleSystem.prototype._addParticle = function (idx, idxpos, model, shapeId, idxInShape) {
-            this.particles.push(new BABYLON.SolidParticle(idx, idxpos, model, shapeId, idxInShape));
+        SolidParticleSystem.prototype._addParticle = function (idx, idxpos, model, shapeId, idxInShape, bbInfo) {
+            this.particles.push(new BABYLON.SolidParticle(idx, idxpos, model, shapeId, idxInShape, bbInfo));
         };
         /**
         * Adds some particles to the SPS from the model shape. Returns the shape id.
@@ -357,6 +360,10 @@ var BABYLON;
             var meshUV = mesh.getVerticesData(BABYLON.VertexBuffer.UVKind);
             var meshCol = mesh.getVerticesData(BABYLON.VertexBuffer.ColorKind);
             var meshNor = mesh.getVerticesData(BABYLON.VertexBuffer.NormalKind);
+            var bbInfo;
+            if (this._particlesIntersect) {
+                bbInfo = mesh.getBoundingInfo();
+            }
             var shape = this._posToShape(meshPos);
             var shapeUV = this._uvsToShapeUV(meshUV);
             var posfunc = options ? options.positionFunction : null;
@@ -367,7 +374,7 @@ var BABYLON;
             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);
                 if (this._updatable) {
-                    this._addParticle(idx, this._positions.length, modelShape, this._shapeCounter, i);
+                    this._addParticle(idx, this._positions.length, modelShape, this._shapeCounter, i, bbInfo);
                 }
                 this._index += shape.length;
                 idx++;
@@ -408,16 +415,16 @@ var BABYLON;
                 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;
             }
-            particle.position.x = 0;
-            particle.position.y = 0;
-            particle.position.z = 0;
-            particle.rotation.x = 0;
-            particle.rotation.y = 0;
-            particle.rotation.z = 0;
+            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.rotationQuaternion = null;
-            particle.scaling.x = 1;
-            particle.scaling.y = 1;
-            particle.scaling.z = 1;
+            particle.scaling.x = 1.0;
+            particle.scaling.y = 1.0;
+            particle.scaling.z = 1.0;
         };
         /**
         * Rebuilds the whole mesh and updates the VBO : custom positions and vertices are recomputed if needed.
@@ -598,6 +605,54 @@ var BABYLON;
                         }
                     }
                 }
+                // 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;
+                    // place, scale and rotate the particle bbox within the SPS local system
+                    for (var b = 0; b < bBox.vectors.length; b++) {
+                        if (this._particle.isVisible) {
+                            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._w = (this._vertex.x * this._rotMatrix.m[3]) + (this._vertex.y * this._rotMatrix.m[7]) + (this._vertex.z * this._rotMatrix.m[11]) + this._rotMatrix.m[15];
+                            this._rotated.x = ((this._vertex.x * this._rotMatrix.m[0]) + (this._vertex.y * this._rotMatrix.m[4]) + (this._vertex.z * this._rotMatrix.m[8]) + this._rotMatrix.m[12]) / this._w;
+                            this._rotated.y = ((this._vertex.x * this._rotMatrix.m[1]) + (this._vertex.y * this._rotMatrix.m[5]) + (this._vertex.z * this._rotMatrix.m[9]) + this._rotMatrix.m[13]) / this._w;
+                            this._rotated.z = ((this._vertex.x * this._rotMatrix.m[2]) + (this._vertex.y * this._rotMatrix.m[6]) + (this._vertex.z * this._rotMatrix.m[10]) + this._rotMatrix.m[14]) / this._w;
+                            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;
+                        }
+                        else {
+                            bBox.vectors[b].x = this._camera.position.x;
+                            bBox.vectors[b].y = this._camera.position.y;
+                            bBox.vectors[b].z = this._camera.position.z;
+                        }
+                    }
+                    // place and scale the particle bouding sphere in the SPS local system
+                    if (this._particle.isVisible) {
+                        this._minimum.x = this._particle._modelBoundingInfo.minimum.x * this._particle.scaling.x;
+                        this._minimum.y = this._particle._modelBoundingInfo.minimum.y * this._particle.scaling.y;
+                        this._minimum.z = this._particle._modelBoundingInfo.minimum.z * this._particle.scaling.z;
+                        this._maximum.x = this._particle._modelBoundingInfo.maximum.x * this._particle.scaling.x;
+                        this._maximum.y = this._particle._modelBoundingInfo.maximum.y * this._particle.scaling.y;
+                        this._maximum.z = this._particle._modelBoundingInfo.maximum.z * this._particle.scaling.z;
+                        bSphere.center.x = this._particle.position.x + (this._minimum.x + this._maximum.x) * 0.5;
+                        bSphere.center.y = this._particle.position.y + (this._minimum.y + this._maximum.y) * 0.5;
+                        bSphere.center.z = this._particle.position.z + (this._minimum.z + this._maximum.z) * 0.5;
+                        bSphere.radius = BABYLON.Vector3.Distance(this._minimum, this._maximum) * 0.5;
+                    }
+                    else {
+                        bSphere.center.x = this._camera.position.x;
+                        bSphere.center.y = this._camera.position.x;
+                        bSphere.center.z = this._camera.position.x;
+                        bSphere.radius = 0.0;
+                    }
+                    // then update the bbox and the bsphere into the world system
+                    bBox._update(this.mesh.getWorldMatrix());
+                    bSphere._update(this.mesh.getWorldMatrix());
+                }
                 // increment indexes for the next particle
                 index = idx + 3;
                 colorIndex = colidx + 4;

+ 71 - 15
src/Particles/babylon.solidParticleSystem.ts

@@ -108,6 +108,7 @@
         private _maximum: Vector3 = Tmp.Vector3[1];
         private _scale: Vector3 = Tmp.Vector3[2];
         private _translation: Vector3 = Tmp.Vector3[3];
+        private _particlesIntersect: boolean = false;
 
 
         /**
@@ -116,12 +117,14 @@
         * `scene` (Scene) is the scene in which the SPS is added.  
         * `updatable` (default true) : if the SPS must be updatable or immutable.  
         * `isPickable` (default false) : if the solid particles must be pickable.  
+        * `particleIntersection` (default false) : if the solid particle intersections must be computed
         */
-        constructor(name: string, scene: Scene, options?: { updatable?: boolean; isPickable?: boolean }) {
+        constructor(name: string, scene: Scene, options?: { updatable?: boolean; isPickable?: boolean; particleIntersection?: boolean }) {
             this.name = name;
             this._scene = scene;
             this._camera = <TargetCamera>scene.activeCamera;
             this._pickable = options ? options.isPickable : false;
+            this._particlesIntersect = options ? options.particleIntersection : false;
             if (options && options.updatable) {
                 this._updatable = options.updatable;
             } else {
@@ -395,8 +398,8 @@
         }
 
         // adds a new particle object in the particles array
-        private _addParticle(idx: number, idxpos: number, model: ModelShape, shapeId: number, idxInShape: number): void {
-            this.particles.push(new SolidParticle(idx, idxpos, model, shapeId, idxInShape));
+        private _addParticle(idx: number, idxpos: number, model: ModelShape, shapeId: number, idxInShape: number, bbInfo?: BoundingInfo): void {
+            this.particles.push(new SolidParticle(idx, idxpos, model, shapeId, idxInShape, bbInfo));
         }
 
         /**
@@ -413,6 +416,10 @@
             var meshUV = mesh.getVerticesData(VertexBuffer.UVKind);
             var meshCol = mesh.getVerticesData(VertexBuffer.ColorKind);
             var meshNor = mesh.getVerticesData(VertexBuffer.NormalKind);
+            var bbInfo;
+            if (this._particlesIntersect) {
+                bbInfo = mesh.getBoundingInfo();
+            }
 
             var shape = this._posToShape(meshPos);
             var shapeUV = this._uvsToShapeUV(meshUV);
@@ -427,7 +434,7 @@
             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);
                 if (this._updatable) {
-                    this._addParticle(idx, this._positions.length, modelShape, this._shapeCounter, i);
+                    this._addParticle(idx, this._positions.length, modelShape, this._shapeCounter, i, bbInfo);
                 }
                 this._index += shape.length;
                 idx++;
@@ -474,16 +481,16 @@
                 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;
             }
-            particle.position.x = 0;
-            particle.position.y = 0;
-            particle.position.z = 0;
-            particle.rotation.x = 0;
-            particle.rotation.y = 0;
-            particle.rotation.z = 0;
+            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.rotationQuaternion = null;
-            particle.scaling.x = 1;
-            particle.scaling.y = 1;
-            particle.scaling.z = 1;
+            particle.scaling.x = 1.0;
+            particle.scaling.y = 1.0;
+            particle.scaling.z = 1.0;
         }
 
         /**
@@ -661,8 +668,7 @@
                             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;
                         }
-                    }
-
+                    } 
                 } 
                 // particle not visible : scaled to zero and positioned to the camera position
                 else {
@@ -689,6 +695,56 @@
                     }
                 }
                 
+                // 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;
+                    
+                    // place, scale and rotate the particle bbox within the SPS local system
+                    for (var b = 0; b < bBox.vectors.length; b++) {
+                        if (this._particle.isVisible) {
+                            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._w = (this._vertex.x * this._rotMatrix.m[3]) + (this._vertex.y * this._rotMatrix.m[7]) + (this._vertex.z * this._rotMatrix.m[11]) + this._rotMatrix.m[15];
+                            this._rotated.x = ((this._vertex.x * this._rotMatrix.m[0]) + (this._vertex.y * this._rotMatrix.m[4]) + (this._vertex.z * this._rotMatrix.m[8]) + this._rotMatrix.m[12]) / this._w;
+                            this._rotated.y = ((this._vertex.x * this._rotMatrix.m[1]) + (this._vertex.y * this._rotMatrix.m[5]) + (this._vertex.z * this._rotMatrix.m[9]) + this._rotMatrix.m[13]) / this._w;
+                            this._rotated.z = ((this._vertex.x * this._rotMatrix.m[2]) + (this._vertex.y * this._rotMatrix.m[6]) + (this._vertex.z * this._rotMatrix.m[10]) + this._rotMatrix.m[14]) / this._w;
+                            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;
+                        }
+                        else {
+                            bBox.vectors[b].x = this._camera.position.x;
+                            bBox.vectors[b].y = this._camera.position.y;
+                            bBox.vectors[b].z = this._camera.position.z;
+                        }
+                    }
+                    // place and scale the particle bouding sphere in the SPS local system
+                    if (this._particle.isVisible) {
+                        this._minimum.x = this._particle._modelBoundingInfo.minimum.x * this._particle.scaling.x;
+                        this._minimum.y = this._particle._modelBoundingInfo.minimum.y * this._particle.scaling.y;
+                        this._minimum.z = this._particle._modelBoundingInfo.minimum.z * this._particle.scaling.z;
+                        this._maximum.x = this._particle._modelBoundingInfo.maximum.x * this._particle.scaling.x;
+                        this._maximum.y = this._particle._modelBoundingInfo.maximum.y * this._particle.scaling.y;
+                        this._maximum.z = this._particle._modelBoundingInfo.maximum.z * this._particle.scaling.z;
+                        bSphere.center.x = this._particle.position.x + (this._minimum.x + this._maximum.x) * 0.5;
+                        bSphere.center.y = this._particle.position.y + (this._minimum.y + this._maximum.y) * 0.5;
+                        bSphere.center.z = this._particle.position.z + (this._minimum.z + this._maximum.z) * 0.5;
+                        bSphere.radius = Vector3.Distance(this._minimum, this._maximum) * 0.5;
+                    } else {
+                        bSphere.center.x = this._camera.position.x;
+                        bSphere.center.y = this._camera.position.x;
+                        bSphere.center.z = this._camera.position.x;
+                        bSphere.radius = 0.0;                       
+                    }
+
+                    // then update the bbox and the bsphere into the world system
+                    bBox._update(this.mesh.getWorldMatrix());
+                    bSphere._update(this.mesh.getWorldMatrix());
+                }
+
                 // increment indexes for the next particle
                 index = idx + 3;
                 colorIndex = colidx + 4;