Explorar o código

Merge pull request #1409 from jbousquie/feature.SPSParticleIntersection

Added particle boundingInfo and instersectsMesh()
David Catuhe %!s(int64=8) %!d(string=hai) anos
pai
achega
549e5648fa

+ 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 {

+ 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;