ソースを参照

LinesMesh intersection is now supported.

nockawa 9 年 前
コミット
6b40c50f58

+ 1 - 1
src/Culling/babylon.ray.ts

@@ -270,7 +270,7 @@
             // get the difference of the two closest points
             var dP = w.add(u.multiplyByFloats(sc, sc, sc)).subtract(v.multiplyByFloats(tc, tc, tc));  // = S1(sc) - S2(tc)
 
-            var isIntersected = dP.lengthSquared() < (threshold * threshold);   // return intersection result
+            var isIntersected = (tc > 0) && (tc <= this.length) && (dP.lengthSquared() < (threshold * threshold));   // return intersection result
 
             if (isIntersected) {
                 return tc;

+ 34 - 3
src/Mesh/babylon.geometry.ts

@@ -15,12 +15,30 @@
         private _vertexBuffers;
         private _isDisposed = false;
         private _extend: { minimum: Vector3, maximum: Vector3 };
+        private _boundingBias: Vector2;
         public _delayInfo; //ANY
         private _indexBuffer;
         public _boundingInfo: BoundingInfo;
         public _delayLoadingFunction: (any: any, geometry: Geometry) => void;
         public _softwareSkinningRenderId: number;
 
+        /**
+         *  The Bias Vector to apply on the bounding elements (box/sphere), the max extend is computed as v += v * bias.x + bias.y, the min is computed as v -= v * bias.x + bias.y 
+         * @returns The Bias Vector 
+         */
+        public get boundingBias(): Vector2 {
+            return this._boundingBias;
+        }
+
+        public set boundingBias(value: Vector2) {
+            if (this._boundingBias && this._boundingBias.equals(value)) {
+                return;
+            }
+
+            this._boundingBias = value.clone();
+            this.updateExtend();
+        }
+
         constructor(id: string, scene: Scene, vertexData?: VertexData, updatable?: boolean, mesh?: Mesh) {
             this.id = id;
             this._engine = scene.getEngine();
@@ -41,6 +59,11 @@
 
             // applyToMesh
             if (mesh) {
+                if (mesh instanceof LinesMesh) {
+                    this.boundingBias = new Vector2(0, mesh.intersectionThreshold);
+                    this.updateExtend();
+                }
+
                 this.applyToMesh(mesh);
                 mesh.computeWorldMatrix(true);
             }
@@ -79,7 +102,7 @@
 
                 this._totalVertices = data.length / stride;
 
-                this._extend = Tools.ExtractMinAndMax(data, 0, this._totalVertices);
+                this.updateExtend(data);
 
                 var meshes = this._meshes;
                 var numOfMeshes = meshes.length;
@@ -121,7 +144,7 @@
                 this._totalVertices = data.length / stride;
 
                 if (updateExtends) {
-                    this._extend = Tools.ExtractMinAndMax(data, 0, this._totalVertices);
+                    this.updateExtend(data);
                 }
 
                 var meshes = this._meshes;
@@ -316,6 +339,14 @@
             }
         }
 
+        private updateExtend(data=null) {
+            if (!data) {
+                data = this._vertexBuffers[VertexBuffer.PositionKind].getData();
+            }
+
+            this._extend = Tools.ExtractMinAndMax(data, 0, this._totalVertices, this.boundingBias);
+        }
+
         private _applyToMesh(mesh: Mesh): void {
             var numOfMeshes = this._meshes.length;
 
@@ -330,7 +361,7 @@
                     mesh._resetPointsArrayCache();
 
                     if (!this._extend) {
-                        this._extend = Tools.ExtractMinAndMax(this._vertexBuffers[kind].getData(), 0, this._totalVertices);
+                        this.updateExtend(this._vertexBuffers[kind].getData());
                     }
                     mesh._boundingInfo = new BoundingInfo(this._extend.minimum, this._extend.maximum);
 

+ 29 - 5
src/Mesh/babylon.linesMesh.ts

@@ -3,11 +3,39 @@
         public color = new Color3(1, 1, 1);
         public alpha = 1;
 
+        /**
+         * The intersection Threshold is the margin applied when intersection a segment of the LinesMesh with a Ray.
+         * This margin is expressed in world space coordinates, so its value may vary.
+         * Default value is 0.1
+         * @returns the intersection Threshold value.
+         */
+        public get intersectionThreshold(): number {
+            return this._intersectionThreshold;
+        }
+
+        /**
+         * The intersection Threshold is the margin applied when intersection a segment of the LinesMesh with a Ray.
+         * This margin is expressed in world space coordinates, so its value may vary.
+         * @param value the new threshold to apply
+         */
+        public set intersectionThreshold(value: number) {
+            if (this._intersectionThreshold === value) {
+                return;
+            }
+
+            this._intersectionThreshold = value;
+            if (this.geometry) {
+                this.geometry.boundingBias = new Vector2(0, value);
+            }
+        }
+
+        private _intersectionThreshold: number;
         private _colorShader: ShaderMaterial;
 
         constructor(name: string, scene: Scene, parent: Node = null, source?: Mesh, doNotCloneChildren?: boolean) {
             super(name, scene, parent, source, doNotCloneChildren);
 
+            this._intersectionThreshold = 0.1;
             this._colorShader = new ShaderMaterial("colorShader", scene, "color",
                 {
                     attributes: ["position"],
@@ -21,7 +49,7 @@
         }
 
         public get isPickable(): boolean {
-            return false;
+            return true;
         }
 
         public get checkCollisions(): boolean {
@@ -51,10 +79,6 @@
             engine.draw(false, subMesh.indexStart, subMesh.indexCount);
         }
 
-        public intersects(ray: Ray, fastCheck?: boolean) {
-            return null;
-        }
-
         public dispose(doNotRecurse?: boolean): void {
             this._colorShader.dispose();
 

+ 37 - 12
src/Mesh/babylon.subMesh.ts

@@ -87,7 +87,7 @@
                 //the rendering mesh's bounding info can be used, it is the standard submesh for all indices.
                 extend = { minimum: this._renderingMesh.getBoundingInfo().minimum.clone(), maximum: this._renderingMesh.getBoundingInfo().maximum.clone() };
             } else {
-                extend = Tools.ExtractMinAndMaxIndexed(data, indices, this.indexStart, this.indexCount);
+                extend = Tools.ExtractMinAndMaxIndexed(data, indices, this.indexStart, this.indexCount, this._renderingMesh.geometry.boundingBias);
             }
             this._boundingInfo = new BoundingInfo(extend.minimum, extend.maximum);
         }
@@ -134,22 +134,22 @@
         public intersects(ray: Ray, positions: Vector3[], indices: number[] | Int32Array, fastCheck?: boolean): IntersectionInfo {
             var intersectInfo: IntersectionInfo = null;
 
-            // Triangles test
-            for (var index = this.indexStart; index < this.indexStart + this.indexCount; index += 3) {
-                var p0 = positions[indices[index]];
-                var p1 = positions[indices[index + 1]];
-                var p2 = positions[indices[index + 2]];
+            // LineMesh first as it's also a Mesh...
+            if (this._mesh instanceof LinesMesh) {
+                var lineMesh = <LinesMesh>this._mesh;
 
-                var currentIntersectInfo = ray.intersectsTriangle(p0, p1, p2);
+                // Line test
+                for (var index = this.indexStart; index < this.indexStart + this.indexCount; index += 2) {
+                    var p0 = positions[indices[index]];
+                    var p1 = positions[indices[index + 1]];
 
-                if (currentIntersectInfo) {
-                    if (currentIntersectInfo.distance < 0) {
+                    var length = ray.intersectionSegment(p0, p1, lineMesh.intersectionThreshold);
+                    if (!length) {
                         continue;
                     }
 
-                    if (fastCheck || !intersectInfo || currentIntersectInfo.distance < intersectInfo.distance) {
-                        intersectInfo = currentIntersectInfo;
-                        intersectInfo.faceId = index / 3;
+                    if (fastCheck || !intersectInfo || length < intersectInfo.distance) {
+                        intersectInfo = new IntersectionInfo(null, null, length);
 
                         if (fastCheck) {
                             break;
@@ -157,6 +157,31 @@
                     }
                 }
             }
+            else if (this._mesh instanceof Mesh) {
+                // Triangles test
+                for (var index = this.indexStart; index < this.indexStart + this.indexCount; index += 3) {
+                    var p0 = positions[indices[index]];
+                    var p1 = positions[indices[index + 1]];
+                    var p2 = positions[indices[index + 2]];
+
+                    var currentIntersectInfo = ray.intersectsTriangle(p0, p1, p2);
+
+                    if (currentIntersectInfo) {
+                        if (currentIntersectInfo.distance < 0) {
+                            continue;
+                        }
+
+                        if (fastCheck || !intersectInfo || currentIntersectInfo.distance < intersectInfo.distance) {
+                            intersectInfo = currentIntersectInfo;
+                            intersectInfo.faceId = index / 3;
+
+                            if (fastCheck) {
+                                break;
+                            }
+                        }
+                    }
+                }
+            }
 
             return intersectInfo;
         }

+ 20 - 2
src/Tools/babylon.tools.ts

@@ -137,7 +137,7 @@
             return "data:image/png;base64," + output;
         }
 
-        public static ExtractMinAndMaxIndexed(positions: number[] | Float32Array, indices: number[] | Int32Array, indexStart: number, indexCount: number): { minimum: Vector3; maximum: Vector3 } {
+        public static ExtractMinAndMaxIndexed(positions: number[] | Float32Array, indices: number[] | Int32Array, indexStart: number, indexCount: number, bias: Vector2 = null): { minimum: Vector3; maximum: Vector3 } {
             var minimum = new Vector3(Number.MAX_VALUE, Number.MAX_VALUE, Number.MAX_VALUE);
             var maximum = new Vector3(-Number.MAX_VALUE, -Number.MAX_VALUE, -Number.MAX_VALUE);
 
@@ -148,13 +148,22 @@
                 maximum = Vector3.Maximize(current, maximum);
             }
 
+            if (bias) {
+                minimum.x -= minimum.x * bias.x + bias.y;
+                minimum.y -= minimum.y * bias.x + bias.y;
+                minimum.z -= minimum.z * bias.x + bias.y;
+                maximum.x += maximum.x * bias.x + bias.y;
+                maximum.y += maximum.y * bias.x + bias.y;
+                maximum.z += maximum.z * bias.x + bias.y;
+            }
+
             return {
                 minimum: minimum,
                 maximum: maximum
             };
         }
 
-        public static ExtractMinAndMax(positions: number[] | Float32Array, start: number, count: number): { minimum: Vector3; maximum: Vector3 } {
+        public static ExtractMinAndMax(positions: number[] | Float32Array, start: number, count: number, bias: Vector2 = null): { minimum: Vector3; maximum: Vector3 } {
             var minimum = new Vector3(Number.MAX_VALUE, Number.MAX_VALUE, Number.MAX_VALUE);
             var maximum = new Vector3(-Number.MAX_VALUE, -Number.MAX_VALUE, -Number.MAX_VALUE);
 
@@ -165,6 +174,15 @@
                 maximum = Vector3.Maximize(current, maximum);
             }
 
+            if (bias) {
+                minimum.x -= minimum.x * bias.x + bias.y;
+                minimum.y -= minimum.y * bias.x + bias.y;
+                minimum.z -= minimum.z * bias.x + bias.y;
+                maximum.x += maximum.x * bias.x + bias.y;
+                maximum.y += maximum.y * bias.x + bias.y;
+                maximum.z += maximum.z * bias.x + bias.y;
+            }
+
             return {
                 minimum: minimum,
                 maximum: maximum