From ee924959eeaec8a21c53d638936767e63864e6d8 Mon Sep 17 00:00:00 2001 From: Garrett Johnson Date: Fri, 25 Oct 2019 08:46:29 -0700 Subject: [PATCH 01/14] raycast progress --- examples/js/lines/LineSegments2.js | 101 ++++++++++++++++++++++++++++- 1 file changed, 100 insertions(+), 1 deletion(-) diff --git a/examples/js/lines/LineSegments2.js b/examples/js/lines/LineSegments2.js index fd17bb39bd2630..2ba1f0148ade88 100644 --- a/examples/js/lines/LineSegments2.js +++ b/examples/js/lines/LineSegments2.js @@ -1,3 +1,5 @@ +import { Matrix4, Vector3, Vector2, PositionalAudio, Line } from "../../../build/three.module.js"; + /** * @author WestLangley / http://github.com/WestLangley * @@ -52,6 +54,103 @@ THREE.LineSegments2.prototype = Object.assign( Object.create( THREE.Mesh.prototy }; - }() ) + }() ), + + raycast: ( function () { + + var start = new Vector4(); + var end = new Vector4(); + + var origin = new Vector4(); + var mvMatrix = new Matrix4(); + var line = new Line(); + var closestPoint = new Vector3(); + + return function raycast( raycaster, insterescts ) { + + if ( raycaster.camera === null ) { + + console.error( 'THREE.LineSegments2: "Raycaster.camera" needs to be set in order to raycast against sprites.' ); + + } + + var ray = raycaster.ray; + var camera = raycaster.camera; + var projectionMatrix = camera.projectionMatrix; + + var geometry = this.geometry; + var material = this.material; + var resolution = material.resolution; + var lineWidth = material.lineWidth; + + var instanceStart = geometry.attributes.instanceStart; + var instanceEnd = geometry.attributes.instanceEnd; + + var isPerspective = projectionMatrix[ 2 ][ 3 ] === -1; + var aspect = resolution.x / resolution.y; + + // ndc space [ - 0.5, 0.5 ] + origin.copy( ray.origin ); + origin.w = 1; + origin.applyMatrix4( camera.matrixWorldInverse ); + origin.applyMatrix4( projectionMatrix ); + origin.multiplyScalar( 1 / origin.w ); + + // screen space + origin.x *= resolution.x; + origin.y *= resolution.y; + origin.z = 0; + + mvMatrix.multiplyMatrices( camera.matrixWorldInverse, this.matrixWorld ); + + for ( var i = 0, l = instanceStart.count; i < l; i ++ ) { + + // TODO: Maybe have to clip the line based on the camera? + + start.fromBufferAttribute( instanceStart, i ); + end.fromBufferAttribute( instanceEnd, i ); + + start.w = 1; + end.w = 1; + + // camera space + start.applyMatrix4( mvMatrix ); + end.applyMatrix4( mvMatrix ); + + // clip space + start.applyMatrix4( projectionMatrix ); + end.applyMatrix4( projectionMatrix ); + + // ndc space [ - 0.5, 0.5 ] + start.multiplyScalar( 1 / start.w ); + end.multiplyScalar( 1 / end.w ); + + // screen space + start.x *= resolution.x; + start.y *= resolution.y; + + end.y *= resolution.y; + end.y *= resolution.y; + + line.start.copy( start ); + line.start.z = 0; + + line.end.copy( end ); + line.end.z = 0; + + var param = line.closestPointToPointParameter( origin, true ); + line.at( param, closestPoint ); + + if ( origin.distanceTo( closestPoint ) < lineWidth * 0.5 ) { + + // intersected! output a hit + + } + + } + + } + + } () ) } ); From 76b55e4e71fa71873d21eb0e2e77346a7fa51324 Mon Sep 17 00:00:00 2001 From: Garrett Johnson Date: Mon, 4 Nov 2019 14:42:35 -0800 Subject: [PATCH 02/14] updates --- examples/js/lines/LineSegments2.js | 78 +++++++++++++++++++++++------- 1 file changed, 60 insertions(+), 18 deletions(-) diff --git a/examples/js/lines/LineSegments2.js b/examples/js/lines/LineSegments2.js index 2ba1f0148ade88..2688f606996497 100644 --- a/examples/js/lines/LineSegments2.js +++ b/examples/js/lines/LineSegments2.js @@ -1,4 +1,4 @@ -import { Matrix4, Vector3, Vector2, PositionalAudio, Line } from "../../../build/three.module.js"; +import { Matrix4, Vector3, Line, Math as MathUtils } from "../../../build/three.module.js"; /** * @author WestLangley / http://github.com/WestLangley @@ -61,12 +61,12 @@ THREE.LineSegments2.prototype = Object.assign( Object.create( THREE.Mesh.prototy var start = new Vector4(); var end = new Vector4(); - var origin = new Vector4(); + var ssOrigin = new Vector4(); var mvMatrix = new Matrix4(); var line = new Line(); var closestPoint = new Vector3(); - return function raycast( raycaster, insterescts ) { + return function raycast( raycaster, intersects ) { if ( raycaster.camera === null ) { @@ -86,22 +86,20 @@ THREE.LineSegments2.prototype = Object.assign( Object.create( THREE.Mesh.prototy var instanceStart = geometry.attributes.instanceStart; var instanceEnd = geometry.attributes.instanceEnd; - var isPerspective = projectionMatrix[ 2 ][ 3 ] === -1; - var aspect = resolution.x / resolution.y; - // ndc space [ - 0.5, 0.5 ] - origin.copy( ray.origin ); - origin.w = 1; - origin.applyMatrix4( camera.matrixWorldInverse ); - origin.applyMatrix4( projectionMatrix ); - origin.multiplyScalar( 1 / origin.w ); + ssOrigin.copy( ray.origin ); + ssOrigin.w = 1; + ssOrigin.applyMatrix4( camera.matrixWorldInverse ); + ssOrigin.applyMatrix4( projectionMatrix ); + ssOrigin.multiplyScalar( 1 / ssOrigin.w ); // screen space - origin.x *= resolution.x; - origin.y *= resolution.y; - origin.z = 0; + ssOrigin.x *= resolution.x; + ssOrigin.y *= resolution.y; + ssOrigin.z = 0; - mvMatrix.multiplyMatrices( camera.matrixWorldInverse, this.matrixWorld ); + var matrixWorld = this.matrixWorld; + mvMatrix.multiplyMatrices( camera.matrixWorldInverse, matrixWorld ); for ( var i = 0, l = instanceStart.count; i < l; i ++ ) { @@ -121,6 +119,20 @@ THREE.LineSegments2.prototype = Object.assign( Object.create( THREE.Mesh.prototy start.applyMatrix4( projectionMatrix ); end.applyMatrix4( projectionMatrix ); + // segment is behind camera near + if ( start.z > 0 && end.z > 0 ) { + + continue; + + } + + // segment is in front of camera far + if ( start.z < - 1 && end.z < - 1 ) { + + continue; + + } + // ndc space [ - 0.5, 0.5 ] start.multiplyScalar( 1 / start.w ); end.multiplyScalar( 1 / end.w ); @@ -132,18 +144,48 @@ THREE.LineSegments2.prototype = Object.assign( Object.create( THREE.Mesh.prototy end.y *= resolution.y; end.y *= resolution.y; + // create 2d segment line.start.copy( start ); line.start.z = 0; line.end.copy( end ); line.end.z = 0; - var param = line.closestPointToPointParameter( origin, true ); + // get closest point on ray to segment + var param = line.closestPointToPointParameter( ssOrigin, true ); line.at( param, closestPoint ); - if ( origin.distanceTo( closestPoint ) < lineWidth * 0.5 ) { + // check if the intersection point is within clip space + var zPos = MathUtils.lerp( start.z, end.z, param ); + var isInClipSpace = zPos < 0 && zPos > - 1; + + if ( isInClipSpace && ssOrigin.distanceTo( closestPoint ) < lineWidth * 0.5 ) { + + line.start.fromBufferAttribute( instanceStart, i ); + line.end.fromBufferAttribute( instanceEnd, i ); + + line.start.applyMatrix4( matrixWorld ); + line.end.applyMatrix4( matrixWorld ); + + var pointOnLine = new Vector3(); + line.at( param, pointOnLine ); + + var point = new Vector3(); + ray.closestPointToPoint( pointOnLine, point ); + + intersects.push( { + + point: point, + pointOnLine: pointOnLine, + distance: ray.origin.distanceTo( point ), + + object: this, + face: null, + faceIndex: i, + uv: null, + uv2: null, - // intersected! output a hit + } ); } From 7907d6c3299ff8ea958e9307c3795af52de86f1b Mon Sep 17 00:00:00 2001 From: Garrett Johnson Date: Mon, 4 Nov 2019 15:16:04 -0800 Subject: [PATCH 03/14] Get it working --- examples/jsm/lines/LineSegments2.js | 161 ++++++++++++++++++++++++++-- 1 file changed, 151 insertions(+), 10 deletions(-) diff --git a/examples/jsm/lines/LineSegments2.js b/examples/jsm/lines/LineSegments2.js index 20beea38349097..f5567a839d8f02 100644 --- a/examples/jsm/lines/LineSegments2.js +++ b/examples/jsm/lines/LineSegments2.js @@ -1,17 +1,12 @@ +import { Matrix4, Vector3, Vector4, Line3, Math as MathUtils, Mesh, InstancedInterleavedBuffer, InterleavedBufferAttribute } from "../../../build/three.module.js"; +import { LineSegmentsGeometry } from "../lines/LineSegmentsGeometry.js"; +import { LineMaterial } from "../lines/LineMaterial.js"; + /** * @author WestLangley / http://github.com/WestLangley * */ -import { - InstancedInterleavedBuffer, - InterleavedBufferAttribute, - Mesh, - Vector3 -} from "../../../build/three.module.js"; -import { LineSegmentsGeometry } from "../lines/LineSegmentsGeometry.js"; -import { LineMaterial } from "../lines/LineMaterial.js"; - var LineSegments2 = function ( geometry, material ) { Mesh.call( this ); @@ -61,7 +56,153 @@ LineSegments2.prototype = Object.assign( Object.create( Mesh.prototype ), { }; - }() ) + }() ), + + raycast: ( function () { + + var start = new Vector4(); + var end = new Vector4(); + + var ssOrigin = new Vector4(); + var ssOrigin3 = new Vector3(); + var mvMatrix = new Matrix4(); + var line = new Line3(); + var closestPoint = new Vector3(); + + return function raycast( raycaster, intersects ) { + + if ( raycaster.camera === null ) { + + console.error( 'LineSegments2: "Raycaster.camera" needs to be set in order to raycast against sprites.' ); + + } + + var ray = raycaster.ray; + var camera = raycaster.camera; + var projectionMatrix = camera.projectionMatrix; + + var geometry = this.geometry; + var material = this.material; + var resolution = material.resolution; + var lineWidth = material.linewidth; + + var instanceStart = geometry.attributes.instanceStart; + var instanceEnd = geometry.attributes.instanceEnd; + + // ndc space [ - 0.5, 0.5 ] + ray.at( 1, ssOrigin ); + ssOrigin.w = 1; + ssOrigin.applyMatrix4( camera.matrixWorldInverse ); + ssOrigin.applyMatrix4( projectionMatrix ); + ssOrigin.multiplyScalar( 1 / ssOrigin.w ); + + // screen space + ssOrigin.x *= resolution.x / 2; + ssOrigin.y *= resolution.y / 2; + ssOrigin.z = 0; + + ssOrigin3.copy( ssOrigin ); + + var matrixWorld = this.matrixWorld; + mvMatrix.multiplyMatrices( camera.matrixWorldInverse, matrixWorld ); + + for ( var i = 0, l = instanceStart.count; i < l; i ++ ) { + + // TODO: Maybe have to clip the line based on the camera? + + start.fromBufferAttribute( instanceStart, i ); + end.fromBufferAttribute( instanceEnd, i ); + + start.w = 1; + end.w = 1; + + // camera space + start.applyMatrix4( mvMatrix ); + end.applyMatrix4( mvMatrix ); + + // clip space + start.applyMatrix4( projectionMatrix ); + end.applyMatrix4( projectionMatrix ); + + // console.log( start.z, end.z ) + // // segment is behind camera near + // if ( start.z > 0 && end.z > 0 ) { + + // continue; + + // } + // console.log(2 ); + + // // segment is in front of camera far + // if ( start.z < - 1 && end.z < - 1 ) { + + // continue; + + // } + + // ndc space [ - 0.5, 0.5 ] + start.multiplyScalar( 1 / start.w ); + end.multiplyScalar( 1 / end.w ); + + // screen space + start.x *= resolution.x / 2; + start.y *= resolution.y / 2; + + end.x *= resolution.x / 2; + end.y *= resolution.y / 2; + + // create 2d segment + line.start.copy( start ); + line.start.z = 0; + + line.end.copy( end ); + line.end.z = 0; + + // get closest point on ray to segment + var param = line.closestPointToPointParameter( ssOrigin, true ); + line.at( param, closestPoint ); + + // check if the intersection point is within clip space + var zPos = MathUtils.lerp( start.z, end.z, param ); + var isInClipSpace = true; //zPos < 0 && zPos > - 1; + + console.log(ssOrigin3 ); //ssOrigin3.distanceTo( closestPoint ), lineWidth) + + if ( isInClipSpace && ssOrigin3.distanceTo( closestPoint ) < lineWidth * 0.5 ) { + + line.start.fromBufferAttribute( instanceStart, i ); + line.end.fromBufferAttribute( instanceEnd, i ); + + line.start.applyMatrix4( matrixWorld ); + line.end.applyMatrix4( matrixWorld ); + + var pointOnLine = new Vector3(); + line.at( param, pointOnLine ); + + var point = new Vector3(); + ray.closestPointToPoint( pointOnLine, point ); + + intersects.push( { + + point: point, + pointOnLine: pointOnLine, + distance: ray.origin.distanceTo( point ), + + object: this, + face: null, + faceIndex: i, + uv: null, + uv2: null, + + } ); + + } + + } + + } + + } () ) } ); From 74a0a3f9f308c583dd88ad73f10b723971ef470c Mon Sep 17 00:00:00 2001 From: Garrett Johnson Date: Mon, 4 Nov 2019 15:24:36 -0800 Subject: [PATCH 04/14] update example --- examples/webgl_lines_fat.html | 40 +++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/examples/webgl_lines_fat.html b/examples/webgl_lines_fat.html index 6d9cf8591077b4..8abdb67906b79c 100644 --- a/examples/webgl_lines_fat.html +++ b/examples/webgl_lines_fat.html @@ -31,6 +31,7 @@ var matLine, matLineBasic, matLineDashed; var stats; var gui; + var mouse, raycaster, raycastPoint; // viewport var insetWidth; @@ -123,6 +124,14 @@ window.addEventListener( 'resize', onWindowResize, false ); onWindowResize(); + mouse = new THREE.Vector2(); + raycaster = new THREE.Raycaster(); + raycastPoint = new THREE.Mesh( new THREE.SphereBufferGeometry( 1, 20, 10 ) ); + raycastPoint.material.color.set( 0xff0000 ); + raycastPoint.scale.setScalar( 0.25 ); + scene.add( raycastPoint ); + document.addEventListener( 'mousemove', onMouseMove, false ); + stats = new Stats(); document.body.appendChild( stats.dom ); @@ -145,6 +154,33 @@ } + function onMouseMove( e ) { + + e.preventDefault(); + + mouse.x = ( e.clientX / window.innerWidth ) * 2 - 1; + mouse.y = - ( e.clientY / window.innerHeight ) * 2 + 1; + + } + + function doRaycast() { + + camera.updateMatrixWorld(); + raycaster.setFromCamera( mouse, camera ); + var intersects = raycaster.intersectObjects( [ line, line1 ] ); + if ( intersects.length !== 0 ) { + + raycastPoint.position.copy( intersects[ 0 ].point ); + raycastPoint.visible = true; + + } else { + + raycastPoint.visible = false; + + } + + } + function animate() { requestAnimationFrame( animate ); @@ -160,6 +196,10 @@ // renderer will set this eventually matLine.resolution.set( window.innerWidth, window.innerHeight ); // resolution of the viewport + // perform raycast after the resolution has been updated for the camera + // view we care about + doRaycast(); + renderer.render( scene, camera ); // inset scene From d073165cca5dbae3ffe4830603ff6f54eca38de0 Mon Sep 17 00:00:00 2001 From: Garrett Johnson Date: Mon, 4 Nov 2019 15:31:50 -0800 Subject: [PATCH 05/14] Early out --- examples/jsm/lines/LineSegments2.js | 30 +++++++++++++---------------- 1 file changed, 13 insertions(+), 17 deletions(-) diff --git a/examples/jsm/lines/LineSegments2.js b/examples/jsm/lines/LineSegments2.js index f5567a839d8f02..16849d03e6ee0c 100644 --- a/examples/jsm/lines/LineSegments2.js +++ b/examples/jsm/lines/LineSegments2.js @@ -124,25 +124,23 @@ LineSegments2.prototype = Object.assign( Object.create( Mesh.prototype ), { start.applyMatrix4( projectionMatrix ); end.applyMatrix4( projectionMatrix ); - // console.log( start.z, end.z ) - // // segment is behind camera near - // if ( start.z > 0 && end.z > 0 ) { + // ndc space [ - 1.0, 1.0 ] + start.multiplyScalar( 1 / start.w ); + end.multiplyScalar( 1 / end.w ); - // continue; + // segment is behind camera near + if ( start.z < - 1 && end.z < - 1 ) { - // } - // console.log(2 ); + continue; - // // segment is in front of camera far - // if ( start.z < - 1 && end.z < - 1 ) { + } - // continue; + // segment is in front of camera far + if ( start.z > 1 && end.z > 1 ) { - // } + continue; - // ndc space [ - 0.5, 0.5 ] - start.multiplyScalar( 1 / start.w ); - end.multiplyScalar( 1 / end.w ); + } // screen space start.x *= resolution.x / 2; @@ -159,14 +157,12 @@ LineSegments2.prototype = Object.assign( Object.create( Mesh.prototype ), { line.end.z = 0; // get closest point on ray to segment - var param = line.closestPointToPointParameter( ssOrigin, true ); + var param = line.closestPointToPointParameter( ssOrigin3, true ); line.at( param, closestPoint ); // check if the intersection point is within clip space var zPos = MathUtils.lerp( start.z, end.z, param ); - var isInClipSpace = true; //zPos < 0 && zPos > - 1; - - console.log(ssOrigin3 ); //ssOrigin3.distanceTo( closestPoint ), lineWidth) + var isInClipSpace = zPos >= -1 && zPos <= 1; if ( isInClipSpace && ssOrigin3.distanceTo( closestPoint ) < lineWidth * 0.5 ) { From fcd8db2c7b49d709c927c654983ef59f2b693c05 Mon Sep 17 00:00:00 2001 From: Garrett Johnson Date: Mon, 4 Nov 2019 16:05:06 -0800 Subject: [PATCH 06/14] comments update --- examples/jsm/lines/LineSegments2.js | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/examples/jsm/lines/LineSegments2.js b/examples/jsm/lines/LineSegments2.js index 16849d03e6ee0c..d7a9e856f143a0 100644 --- a/examples/jsm/lines/LineSegments2.js +++ b/examples/jsm/lines/LineSegments2.js @@ -73,7 +73,7 @@ LineSegments2.prototype = Object.assign( Object.create( Mesh.prototype ), { if ( raycaster.camera === null ) { - console.error( 'LineSegments2: "Raycaster.camera" needs to be set in order to raycast against sprites.' ); + console.error( 'LineSegments2: "Raycaster.camera" needs to be set in order to raycast against LineSegments2.' ); } @@ -108,8 +108,6 @@ LineSegments2.prototype = Object.assign( Object.create( Mesh.prototype ), { for ( var i = 0, l = instanceStart.count; i < l; i ++ ) { - // TODO: Maybe have to clip the line based on the camera? - start.fromBufferAttribute( instanceStart, i ); end.fromBufferAttribute( instanceEnd, i ); From 9e4fb7174fdec07e576521d9647819a065537d5a Mon Sep 17 00:00:00 2001 From: Garrett Johnson Date: Mon, 4 Nov 2019 16:06:30 -0800 Subject: [PATCH 07/14] Update js file --- examples/js/lines/LineSegments2.js | 59 +++++++++++++++--------------- 1 file changed, 29 insertions(+), 30 deletions(-) diff --git a/examples/js/lines/LineSegments2.js b/examples/js/lines/LineSegments2.js index 2688f606996497..a964184cd7c944 100644 --- a/examples/js/lines/LineSegments2.js +++ b/examples/js/lines/LineSegments2.js @@ -1,5 +1,3 @@ -import { Matrix4, Vector3, Line, Math as MathUtils } from "../../../build/three.module.js"; - /** * @author WestLangley / http://github.com/WestLangley * @@ -58,19 +56,20 @@ THREE.LineSegments2.prototype = Object.assign( Object.create( THREE.Mesh.prototy raycast: ( function () { - var start = new Vector4(); - var end = new Vector4(); + var start = new THREE.Vector4(); + var end = new THREE.Vector4(); - var ssOrigin = new Vector4(); - var mvMatrix = new Matrix4(); - var line = new Line(); - var closestPoint = new Vector3(); + var ssOrigin = new THREE.Vector4(); + var ssOrigin3 = new THREE.Vector3(); + var mvMatrix = new THREE.Matrix4(); + var line = new THREE.Line3(); + var closestPoint = new THREE.Vector3(); return function raycast( raycaster, intersects ) { if ( raycaster.camera === null ) { - console.error( 'THREE.LineSegments2: "Raycaster.camera" needs to be set in order to raycast against sprites.' ); + console.error( 'LineSegments2: "Raycaster.camera" needs to be set in order to raycast against LineSegments2.' ); } @@ -81,30 +80,30 @@ THREE.LineSegments2.prototype = Object.assign( Object.create( THREE.Mesh.prototy var geometry = this.geometry; var material = this.material; var resolution = material.resolution; - var lineWidth = material.lineWidth; + var lineWidth = material.linewidth; var instanceStart = geometry.attributes.instanceStart; var instanceEnd = geometry.attributes.instanceEnd; // ndc space [ - 0.5, 0.5 ] - ssOrigin.copy( ray.origin ); + ray.at( 1, ssOrigin ); ssOrigin.w = 1; ssOrigin.applyMatrix4( camera.matrixWorldInverse ); ssOrigin.applyMatrix4( projectionMatrix ); ssOrigin.multiplyScalar( 1 / ssOrigin.w ); // screen space - ssOrigin.x *= resolution.x; - ssOrigin.y *= resolution.y; + ssOrigin.x *= resolution.x / 2; + ssOrigin.y *= resolution.y / 2; ssOrigin.z = 0; + ssOrigin3.copy( ssOrigin ); + var matrixWorld = this.matrixWorld; mvMatrix.multiplyMatrices( camera.matrixWorldInverse, matrixWorld ); for ( var i = 0, l = instanceStart.count; i < l; i ++ ) { - // TODO: Maybe have to clip the line based on the camera? - start.fromBufferAttribute( instanceStart, i ); end.fromBufferAttribute( instanceEnd, i ); @@ -119,30 +118,30 @@ THREE.LineSegments2.prototype = Object.assign( Object.create( THREE.Mesh.prototy start.applyMatrix4( projectionMatrix ); end.applyMatrix4( projectionMatrix ); + // ndc space [ - 1.0, 1.0 ] + start.multiplyScalar( 1 / start.w ); + end.multiplyScalar( 1 / end.w ); + // segment is behind camera near - if ( start.z > 0 && end.z > 0 ) { + if ( start.z < - 1 && end.z < - 1 ) { continue; } // segment is in front of camera far - if ( start.z < - 1 && end.z < - 1 ) { + if ( start.z > 1 && end.z > 1 ) { continue; } - // ndc space [ - 0.5, 0.5 ] - start.multiplyScalar( 1 / start.w ); - end.multiplyScalar( 1 / end.w ); - // screen space - start.x *= resolution.x; - start.y *= resolution.y; + start.x *= resolution.x / 2; + start.y *= resolution.y / 2; - end.y *= resolution.y; - end.y *= resolution.y; + end.x *= resolution.x / 2; + end.y *= resolution.y / 2; // create 2d segment line.start.copy( start ); @@ -152,14 +151,14 @@ THREE.LineSegments2.prototype = Object.assign( Object.create( THREE.Mesh.prototy line.end.z = 0; // get closest point on ray to segment - var param = line.closestPointToPointParameter( ssOrigin, true ); + var param = line.closestPointToPointParameter( ssOrigin3, true ); line.at( param, closestPoint ); // check if the intersection point is within clip space var zPos = MathUtils.lerp( start.z, end.z, param ); - var isInClipSpace = zPos < 0 && zPos > - 1; + var isInClipSpace = zPos >= -1 && zPos <= 1; - if ( isInClipSpace && ssOrigin.distanceTo( closestPoint ) < lineWidth * 0.5 ) { + if ( isInClipSpace && ssOrigin3.distanceTo( closestPoint ) < lineWidth * 0.5 ) { line.start.fromBufferAttribute( instanceStart, i ); line.end.fromBufferAttribute( instanceEnd, i ); @@ -167,10 +166,10 @@ THREE.LineSegments2.prototype = Object.assign( Object.create( THREE.Mesh.prototy line.start.applyMatrix4( matrixWorld ); line.end.applyMatrix4( matrixWorld ); - var pointOnLine = new Vector3(); + var pointOnLine = new THREE.Vector3(); line.at( param, pointOnLine ); - var point = new Vector3(); + var point = new THREE.Vector3(); ray.closestPointToPoint( pointOnLine, point ); intersects.push( { From 30b27b228a2bf221375ed0eed7687f9938c0e1c9 Mon Sep 17 00:00:00 2001 From: Garrett Johnson Date: Mon, 4 Nov 2019 16:07:55 -0800 Subject: [PATCH 08/14] js -> jsm --- examples/jsm/lines/LineSegments2.js | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/examples/jsm/lines/LineSegments2.js b/examples/jsm/lines/LineSegments2.js index d7a9e856f143a0..550482cebad663 100644 --- a/examples/jsm/lines/LineSegments2.js +++ b/examples/jsm/lines/LineSegments2.js @@ -1,12 +1,20 @@ -import { Matrix4, Vector3, Vector4, Line3, Math as MathUtils, Mesh, InstancedInterleavedBuffer, InterleavedBufferAttribute } from "../../../build/three.module.js"; -import { LineSegmentsGeometry } from "../lines/LineSegmentsGeometry.js"; -import { LineMaterial } from "../lines/LineMaterial.js"; - /** * @author WestLangley / http://github.com/WestLangley * */ +import { + InstancedInterleavedBuffer, + InterleavedBufferAttribute, + Line3, + Matrix4, + Mesh, + Vector3, + Vector4 +} from "../../../build/three.module.js"; +import { LineSegmentsGeometry } from "../lines/LineSegmentsGeometry.js"; +import { LineMaterial } from "../lines/LineMaterial.js"; + var LineSegments2 = function ( geometry, material ) { Mesh.call( this ); From 3d420b115b4efa61022b43220519bd0619845402 Mon Sep 17 00:00:00 2001 From: Garrett Johnson Date: Mon, 4 Nov 2019 16:49:14 -0800 Subject: [PATCH 09/14] Fix world space intersection point calculation --- examples/js/lines/LineSegments2.js | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/examples/js/lines/LineSegments2.js b/examples/js/lines/LineSegments2.js index a964184cd7c944..3d60c56d06a7e2 100644 --- a/examples/js/lines/LineSegments2.js +++ b/examples/js/lines/LineSegments2.js @@ -155,10 +155,12 @@ THREE.LineSegments2.prototype = Object.assign( Object.create( THREE.Mesh.prototy line.at( param, closestPoint ); // check if the intersection point is within clip space - var zPos = MathUtils.lerp( start.z, end.z, param ); + var zPos = THREE.Math.lerp( start.z, end.z, param ); var isInClipSpace = zPos >= -1 && zPos <= 1; - if ( isInClipSpace && ssOrigin3.distanceTo( closestPoint ) < lineWidth * 0.5 ) { + var isInside = ssOrigin3.distanceTo( closestPoint ) < lineWidth * 0.5; + + if ( isInClipSpace && isInside ) { line.start.fromBufferAttribute( instanceStart, i ); line.end.fromBufferAttribute( instanceEnd, i ); @@ -167,10 +169,9 @@ THREE.LineSegments2.prototype = Object.assign( Object.create( THREE.Mesh.prototy line.end.applyMatrix4( matrixWorld ); var pointOnLine = new THREE.Vector3(); - line.at( param, pointOnLine ); - var point = new THREE.Vector3(); - ray.closestPointToPoint( pointOnLine, point ); + + ray.distanceSqToSegment( line.start, line.end, point, pointOnLine ); intersects.push( { From 1dc2887f3476f1409763b01af1e31ba54bcf493d Mon Sep 17 00:00:00 2001 From: Garrett Johnson Date: Mon, 4 Nov 2019 16:56:06 -0800 Subject: [PATCH 10/14] clarity --- examples/js/lines/LineSegments2.js | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/examples/js/lines/LineSegments2.js b/examples/js/lines/LineSegments2.js index 3d60c56d06a7e2..f74a2a55c795c0 100644 --- a/examples/js/lines/LineSegments2.js +++ b/examples/js/lines/LineSegments2.js @@ -122,15 +122,10 @@ THREE.LineSegments2.prototype = Object.assign( Object.create( THREE.Mesh.prototy start.multiplyScalar( 1 / start.w ); end.multiplyScalar( 1 / end.w ); - // segment is behind camera near - if ( start.z < - 1 && end.z < - 1 ) { - - continue; - - } - - // segment is in front of camera far - if ( start.z > 1 && end.z > 1 ) { + // skip the segment if it's outside the camera near and far planes + var isBehindCameraNear = start.z < - 1 && end.z < - 1; + var isPastCameraFar = start.z > 1 && end.z > 1; + if ( isBehindCameraNear || isPastCameraFar ) { continue; From e1120f963e2c59bb01082cf1d1902b261379302b Mon Sep 17 00:00:00 2001 From: Garrett Johnson Date: Mon, 4 Nov 2019 17:02:57 -0800 Subject: [PATCH 11/14] js -> jsm --- examples/jsm/lines/LineSegments2.js | 25 +++++++++++-------------- 1 file changed, 11 insertions(+), 14 deletions(-) diff --git a/examples/jsm/lines/LineSegments2.js b/examples/jsm/lines/LineSegments2.js index 550482cebad663..bcaec41806ca1c 100644 --- a/examples/jsm/lines/LineSegments2.js +++ b/examples/jsm/lines/LineSegments2.js @@ -7,6 +7,7 @@ import { InstancedInterleavedBuffer, InterleavedBufferAttribute, Line3, + Math as _Math, Matrix4, Mesh, Vector3, @@ -134,15 +135,10 @@ LineSegments2.prototype = Object.assign( Object.create( Mesh.prototype ), { start.multiplyScalar( 1 / start.w ); end.multiplyScalar( 1 / end.w ); - // segment is behind camera near - if ( start.z < - 1 && end.z < - 1 ) { - - continue; - - } - - // segment is in front of camera far - if ( start.z > 1 && end.z > 1 ) { + // skip the segment if it's outside the camera near and far planes + var isBehindCameraNear = start.z < - 1 && end.z < - 1; + var isPastCameraFar = start.z > 1 && end.z > 1; + if ( isBehindCameraNear || isPastCameraFar ) { continue; @@ -167,10 +163,12 @@ LineSegments2.prototype = Object.assign( Object.create( Mesh.prototype ), { line.at( param, closestPoint ); // check if the intersection point is within clip space - var zPos = MathUtils.lerp( start.z, end.z, param ); + var zPos = _Math.lerp( start.z, end.z, param ); var isInClipSpace = zPos >= -1 && zPos <= 1; - if ( isInClipSpace && ssOrigin3.distanceTo( closestPoint ) < lineWidth * 0.5 ) { + var isInside = ssOrigin3.distanceTo( closestPoint ) < lineWidth * 0.5; + + if ( isInClipSpace && isInside ) { line.start.fromBufferAttribute( instanceStart, i ); line.end.fromBufferAttribute( instanceEnd, i ); @@ -179,10 +177,9 @@ LineSegments2.prototype = Object.assign( Object.create( Mesh.prototype ), { line.end.applyMatrix4( matrixWorld ); var pointOnLine = new Vector3(); - line.at( param, pointOnLine ); - var point = new Vector3(); - ray.closestPointToPoint( pointOnLine, point ); + + ray.distanceSqToSegment( line.start, line.end, point, pointOnLine ); intersects.push( { From fca2ea8108732bbbec5f8b050d359ff88962e853 Mon Sep 17 00:00:00 2001 From: Garrett Johnson Date: Mon, 4 Nov 2019 17:05:33 -0800 Subject: [PATCH 12/14] comments update --- examples/js/lines/LineSegments2.js | 2 +- examples/jsm/lines/LineSegments2.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/js/lines/LineSegments2.js b/examples/js/lines/LineSegments2.js index f74a2a55c795c0..f00a07d7fa16aa 100644 --- a/examples/js/lines/LineSegments2.js +++ b/examples/js/lines/LineSegments2.js @@ -85,7 +85,7 @@ THREE.LineSegments2.prototype = Object.assign( Object.create( THREE.Mesh.prototy var instanceStart = geometry.attributes.instanceStart; var instanceEnd = geometry.attributes.instanceEnd; - // ndc space [ - 0.5, 0.5 ] + // ndc space [ - 1.0, 1.0 ] ray.at( 1, ssOrigin ); ssOrigin.w = 1; ssOrigin.applyMatrix4( camera.matrixWorldInverse ); diff --git a/examples/jsm/lines/LineSegments2.js b/examples/jsm/lines/LineSegments2.js index bcaec41806ca1c..89e7791e22fd42 100644 --- a/examples/jsm/lines/LineSegments2.js +++ b/examples/jsm/lines/LineSegments2.js @@ -98,7 +98,7 @@ LineSegments2.prototype = Object.assign( Object.create( Mesh.prototype ), { var instanceStart = geometry.attributes.instanceStart; var instanceEnd = geometry.attributes.instanceEnd; - // ndc space [ - 0.5, 0.5 ] + // ndc space [ - 1.0, 1.0 ] ray.at( 1, ssOrigin ); ssOrigin.w = 1; ssOrigin.applyMatrix4( camera.matrixWorldInverse ); From eca2412e0e9b01e84b4ea6beeb35acb8dd3da594 Mon Sep 17 00:00:00 2001 From: Garrett Johnson Date: Fri, 8 Nov 2019 11:20:00 -0800 Subject: [PATCH 13/14] add clarifying comment --- examples/js/lines/LineSegments2.js | 6 +++++- examples/jsm/lines/LineSegments2.js | 6 +++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/examples/js/lines/LineSegments2.js b/examples/js/lines/LineSegments2.js index f00a07d7fa16aa..0c364675ac7ca8 100644 --- a/examples/js/lines/LineSegments2.js +++ b/examples/js/lines/LineSegments2.js @@ -85,8 +85,12 @@ THREE.LineSegments2.prototype = Object.assign( Object.create( THREE.Mesh.prototy var instanceStart = geometry.attributes.instanceStart; var instanceEnd = geometry.attributes.instanceEnd; - // ndc space [ - 1.0, 1.0 ] + // pick a point 1 unit out along the ray to avoid the ray origin + // sitting at the camera origin which will cause "w" to be 0 when + // applying the projection matrix. ray.at( 1, ssOrigin ); + + // ndc space [ - 1.0, 1.0 ] ssOrigin.w = 1; ssOrigin.applyMatrix4( camera.matrixWorldInverse ); ssOrigin.applyMatrix4( projectionMatrix ); diff --git a/examples/jsm/lines/LineSegments2.js b/examples/jsm/lines/LineSegments2.js index 89e7791e22fd42..c94d10f19eca9a 100644 --- a/examples/jsm/lines/LineSegments2.js +++ b/examples/jsm/lines/LineSegments2.js @@ -98,8 +98,12 @@ LineSegments2.prototype = Object.assign( Object.create( Mesh.prototype ), { var instanceStart = geometry.attributes.instanceStart; var instanceEnd = geometry.attributes.instanceEnd; - // ndc space [ - 1.0, 1.0 ] + // pick a point 1 unit out along the ray to avoid the ray origin + // sitting at the camera origin which will cause "w" to be 0 when + // applying the projection matrix. ray.at( 1, ssOrigin ); + + // ndc space [ - 1.0, 1.0 ] ssOrigin.w = 1; ssOrigin.applyMatrix4( camera.matrixWorldInverse ); ssOrigin.applyMatrix4( projectionMatrix ); From dc96a86c7cf4878f1f26a36bb14a412ac011af63 Mon Sep 17 00:00:00 2001 From: Garrett Johnson Date: Mon, 16 Dec 2019 15:01:09 -0800 Subject: [PATCH 14/14] remove example changes --- examples/webgl_lines_fat.html | 40 ----------------------------------- 1 file changed, 40 deletions(-) diff --git a/examples/webgl_lines_fat.html b/examples/webgl_lines_fat.html index 8abdb67906b79c..6d9cf8591077b4 100644 --- a/examples/webgl_lines_fat.html +++ b/examples/webgl_lines_fat.html @@ -31,7 +31,6 @@ var matLine, matLineBasic, matLineDashed; var stats; var gui; - var mouse, raycaster, raycastPoint; // viewport var insetWidth; @@ -124,14 +123,6 @@ window.addEventListener( 'resize', onWindowResize, false ); onWindowResize(); - mouse = new THREE.Vector2(); - raycaster = new THREE.Raycaster(); - raycastPoint = new THREE.Mesh( new THREE.SphereBufferGeometry( 1, 20, 10 ) ); - raycastPoint.material.color.set( 0xff0000 ); - raycastPoint.scale.setScalar( 0.25 ); - scene.add( raycastPoint ); - document.addEventListener( 'mousemove', onMouseMove, false ); - stats = new Stats(); document.body.appendChild( stats.dom ); @@ -154,33 +145,6 @@ } - function onMouseMove( e ) { - - e.preventDefault(); - - mouse.x = ( e.clientX / window.innerWidth ) * 2 - 1; - mouse.y = - ( e.clientY / window.innerHeight ) * 2 + 1; - - } - - function doRaycast() { - - camera.updateMatrixWorld(); - raycaster.setFromCamera( mouse, camera ); - var intersects = raycaster.intersectObjects( [ line, line1 ] ); - if ( intersects.length !== 0 ) { - - raycastPoint.position.copy( intersects[ 0 ].point ); - raycastPoint.visible = true; - - } else { - - raycastPoint.visible = false; - - } - - } - function animate() { requestAnimationFrame( animate ); @@ -196,10 +160,6 @@ // renderer will set this eventually matLine.resolution.set( window.innerWidth, window.innerHeight ); // resolution of the viewport - // perform raycast after the resolution has been updated for the camera - // view we care about - doRaycast(); - renderer.render( scene, camera ); // inset scene