LineSegments2.js 5.2 KB
Newer Older
W
WestLangley 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
/**
 * @author WestLangley / http://github.com/WestLangley
 *
 */

THREE.LineSegments2 = function ( geometry, material ) {

	THREE.Mesh.call( this );

	this.type = 'LineSegments2';

	this.geometry = geometry !== undefined ? geometry : new THREE.LineSegmentsGeometry();
	this.material = material !== undefined ? material : new THREE.LineMaterial( { color: Math.random() * 0xffffff } );

};

THREE.LineSegments2.prototype = Object.assign( Object.create( THREE.Mesh.prototype ), {

	constructor: THREE.LineSegments2,

	isLineSegments2: true,

W
WestLangley 已提交
23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47
	computeLineDistances: ( function () { // for backwards-compatability, but could be a method of LineSegmentsGeometry...

		var start = new THREE.Vector3();
		var end = new THREE.Vector3();

		return function computeLineDistances() {

			var geometry = this.geometry;

			var instanceStart = geometry.attributes.instanceStart;
			var instanceEnd = geometry.attributes.instanceEnd;
			var lineDistances = new Float32Array( 2 * instanceStart.data.count );

			for ( var i = 0, j = 0, l = instanceStart.data.count; i < l; i ++, j += 2 ) {

				start.fromBufferAttribute( instanceStart, i );
				end.fromBufferAttribute( instanceEnd, i );

				lineDistances[ j ] = ( j === 0 ) ? 0 : lineDistances[ j - 1 ];
				lineDistances[ j + 1 ] = lineDistances[ j ] + start.distanceTo( end );

			}

			var instanceDistanceBuffer = new THREE.InstancedInterleavedBuffer( lineDistances, 2, 1 ); // d0, d1

48 49
			geometry.setAttribute( 'instanceDistanceStart', new THREE.InterleavedBufferAttribute( instanceDistanceBuffer, 1, 0 ) ); // d0
			geometry.setAttribute( 'instanceDistanceEnd', new THREE.InterleavedBufferAttribute( instanceDistanceBuffer, 1, 1 ) ); // d1
W
WestLangley 已提交
50 51 52 53 54

			return this;

		};

G
Garrett Johnson 已提交
55 56 57 58
	}() ),

	raycast: ( function () {

G
Garrett Johnson 已提交
59 60
		var start = new THREE.Vector4();
		var end = new THREE.Vector4();
G
Garrett Johnson 已提交
61

G
Garrett Johnson 已提交
62 63 64 65 66
		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();
G
Garrett Johnson 已提交
67

G
updates  
Garrett Johnson 已提交
68
		return function raycast( raycaster, intersects ) {
G
Garrett Johnson 已提交
69 70 71

			if ( raycaster.camera === null ) {

G
Garrett Johnson 已提交
72
				console.error( 'LineSegments2: "Raycaster.camera" needs to be set in order to raycast against LineSegments2.' );
G
Garrett Johnson 已提交
73 74 75 76 77 78 79 80 81 82

			}

			var ray = raycaster.ray;
			var camera = raycaster.camera;
			var projectionMatrix = camera.projectionMatrix;

			var geometry = this.geometry;
			var material = this.material;
			var resolution = material.resolution;
G
Garrett Johnson 已提交
83
			var lineWidth = material.linewidth;
G
Garrett Johnson 已提交
84 85 86 87

			var instanceStart = geometry.attributes.instanceStart;
			var instanceEnd = geometry.attributes.instanceEnd;

G
Garrett Johnson 已提交
88 89 90
			// 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.
G
Garrett Johnson 已提交
91
			ray.at( 1, ssOrigin );
G
Garrett Johnson 已提交
92 93

			// ndc space [ - 1.0, 1.0 ]
G
updates  
Garrett Johnson 已提交
94 95 96 97
			ssOrigin.w = 1;
			ssOrigin.applyMatrix4( camera.matrixWorldInverse );
			ssOrigin.applyMatrix4( projectionMatrix );
			ssOrigin.multiplyScalar( 1 / ssOrigin.w );
G
Garrett Johnson 已提交
98 99

			// screen space
G
Garrett Johnson 已提交
100 101
			ssOrigin.x *= resolution.x / 2;
			ssOrigin.y *= resolution.y / 2;
G
updates  
Garrett Johnson 已提交
102
			ssOrigin.z = 0;
G
Garrett Johnson 已提交
103

G
Garrett Johnson 已提交
104 105
			ssOrigin3.copy( ssOrigin );

G
updates  
Garrett Johnson 已提交
106 107
			var matrixWorld = this.matrixWorld;
			mvMatrix.multiplyMatrices( camera.matrixWorldInverse, matrixWorld );
G
Garrett Johnson 已提交
108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124

			for ( var i = 0, l = instanceStart.count; i < l; i ++ ) {

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

G
Garrett Johnson 已提交
125 126 127 128
				// ndc space [ - 1.0, 1.0 ]
				start.multiplyScalar( 1 / start.w );
				end.multiplyScalar( 1 / end.w );

G
clarity  
Garrett Johnson 已提交
129 130 131 132
				// 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 ) {
G
updates  
Garrett Johnson 已提交
133 134 135 136 137

					continue;

				}

G
Garrett Johnson 已提交
138
				// screen space
G
Garrett Johnson 已提交
139 140
				start.x *= resolution.x / 2;
				start.y *= resolution.y / 2;
G
Garrett Johnson 已提交
141

G
Garrett Johnson 已提交
142 143
				end.x *= resolution.x / 2;
				end.y *= resolution.y / 2;
G
Garrett Johnson 已提交
144

G
updates  
Garrett Johnson 已提交
145
				// create 2d segment
G
Garrett Johnson 已提交
146 147 148 149 150 151
				line.start.copy( start );
				line.start.z = 0;

				line.end.copy( end );
				line.end.z = 0;

G
updates  
Garrett Johnson 已提交
152
				// get closest point on ray to segment
G
Garrett Johnson 已提交
153
				var param = line.closestPointToPointParameter( ssOrigin3, true );
G
Garrett Johnson 已提交
154 155
				line.at( param, closestPoint );

G
updates  
Garrett Johnson 已提交
156
				// check if the intersection point is within clip space
157
				var zPos = THREE.Math.lerp( start.z, end.z, param );
M
Mugen87 已提交
158
				var isInClipSpace = zPos >= - 1 && zPos <= 1;
G
updates  
Garrett Johnson 已提交
159

160 161 162
				var isInside = ssOrigin3.distanceTo( closestPoint ) < lineWidth * 0.5;

				if ( isInClipSpace && isInside ) {
G
updates  
Garrett Johnson 已提交
163 164 165 166 167 168 169

					line.start.fromBufferAttribute( instanceStart, i );
					line.end.fromBufferAttribute( instanceEnd, i );

					line.start.applyMatrix4( matrixWorld );
					line.end.applyMatrix4( matrixWorld );

G
Garrett Johnson 已提交
170 171
					var pointOnLine = new THREE.Vector3();
					var point = new THREE.Vector3();
172 173

					ray.distanceSqToSegment( line.start, line.end, point, pointOnLine );
G
updates  
Garrett Johnson 已提交
174 175 176 177 178 179 180 181 182 183 184 185

					intersects.push( {

						point: point,
						pointOnLine: pointOnLine,
						distance: ray.origin.distanceTo( point ),

						object: this,
						face: null,
						faceIndex: i,
						uv: null,
						uv2: null,
G
Garrett Johnson 已提交
186

G
updates  
Garrett Johnson 已提交
187
					} );
G
Garrett Johnson 已提交
188 189 190 191 192

				}

			}

M
Mugen87 已提交
193
		};
G
Garrett Johnson 已提交
194

M
Mugen87 已提交
195
	}() )
W
WestLangley 已提交
196 197

} );