diff --git a/CHANGELOG.md b/CHANGELOG.md index b3f25bca..89f8b6ad 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,9 @@ Minor version by [@jscastro76](https://github.com/jscastro76), some enhancements - #187 Create an option to translate an object based on world coordinates (obj.position) - #188 Add threebox.css to the /dist folder. Included now in `npm run build` command +#### :beetle: Bug fixes +- #177 [BUG] FollowPath animation with realSunlight produces an error + #### :pencil: Documentation - Updated [documentation](/docs/Threebox.md) started to link points and improving documentation descriptions in general. - Updated [README.md](/). diff --git a/dist/threebox.js b/dist/threebox.js index 76da5efc..8830df57 100755 --- a/dist/threebox.js +++ b/dist/threebox.js @@ -2258,8 +2258,6 @@ function line(obj){ module.exports = exports = line; - - /** * custom line shader by WestLangley, sourced from https://github.com/mrdoob/three.js/tree/master/examples/js/lines * @@ -2267,50 +2265,48 @@ module.exports = exports = line; THREE.LineSegmentsGeometry = function () { - THREE.InstancedBufferGeometry.call( this ); + THREE.InstancedBufferGeometry.call(this); this.type = 'LineSegmentsGeometry'; - var plane = new THREE.BufferGeometry(); - - var positions = [ - 1, 2, 0, 1, 2, 0, - 1, 1, 0, 1, 1, 0, - 1, 0, 0, 1, 0, 0, - 1, - 1, 0, 1, - 1, 0 ]; - var uvs = [ 0, 1, 1, 1, 0, .5, 1, .5, 0, .5, 1, .5, 0, 0, 1, 0 ]; - var index = [ 0, 2, 1, 2, 3, 1, 2, 4, 3, 4, 5, 3, 4, 6, 5, 6, 7, 5 ]; + var positions = [- 1, 2, 0, 1, 2, 0, - 1, 1, 0, 1, 1, 0, - 1, 0, 0, 1, 0, 0, - 1, - 1, 0, 1, - 1, 0]; + var uvs = [- 1, 2, 1, 2, - 1, 1, 1, 1, - 1, - 1, 1, - 1, - 1, - 2, 1, - 2]; + var index = [0, 2, 1, 2, 3, 1, 2, 4, 3, 4, 5, 3, 4, 6, 5, 6, 7, 5]; - this.setIndex( index ); - this.setAttribute( 'position', new THREE.Float32BufferAttribute( positions, 3 ) ); - this.setAttribute( 'uv', new THREE.Float32BufferAttribute( uvs, 2 ) ); + this.setIndex(index); + this.setAttribute('position', new THREE.Float32BufferAttribute(positions, 3)); + this.setAttribute('uv', new THREE.Float32BufferAttribute(uvs, 2)); }; -THREE.LineSegmentsGeometry.prototype = Object.assign( Object.create( THREE.InstancedBufferGeometry.prototype ), { +THREE.LineSegmentsGeometry.prototype = Object.assign(Object.create(THREE.InstancedBufferGeometry.prototype), { constructor: THREE.LineSegmentsGeometry, isLineSegmentsGeometry: true, - applyMatrix: function ( matrix ) { + applyMatrix4: function (matrix) { var start = this.attributes.instanceStart; var end = this.attributes.instanceEnd; - if ( start !== undefined ) { + if (start !== undefined) { - matrix.applyToBufferAttribute( start ); + start.applyMatrix4(matrix); - matrix.applyToBufferAttribute( end ); + end.applyMatrix4(matrix); - start.data.needsUpdate = true; + start.needsUpdate = true; } - if ( this.boundingBox !== null ) { + if (this.boundingBox !== null) { this.computeBoundingBox(); } - if ( this.boundingSphere !== null ) { + if (this.boundingSphere !== null) { this.computeBoundingSphere(); @@ -2320,24 +2316,24 @@ THREE.LineSegmentsGeometry.prototype = Object.assign( Object.create( THREE.Insta }, - setPositions: function ( array ) { + setPositions: function (array) { var lineSegments; - if ( array instanceof Float32Array ) { + if (array instanceof Float32Array) { lineSegments = array; - } else if ( Array.isArray( array ) ) { + } else if (Array.isArray(array)) { - lineSegments = new Float32Array( array ); + lineSegments = new Float32Array(array); } - var instanceBuffer = new THREE.InstancedInterleavedBuffer( lineSegments, 6, 1 ); // xyz, xyz + var instanceBuffer = new THREE.InstancedInterleavedBuffer(lineSegments, 6, 1); // xyz, xyz - this.setAttribute( 'instanceStart', new THREE.InterleavedBufferAttribute( instanceBuffer, 3, 0 ) ); // xyz - this.setAttribute( 'instanceEnd', new THREE.InterleavedBufferAttribute( instanceBuffer, 3, 3 ) ); // xyz + this.setAttribute('instanceStart', new THREE.InterleavedBufferAttribute(instanceBuffer, 3, 0)); // xyz + this.setAttribute('instanceEnd', new THREE.InterleavedBufferAttribute(instanceBuffer, 3, 3)); // xyz // @@ -2348,48 +2344,48 @@ THREE.LineSegmentsGeometry.prototype = Object.assign( Object.create( THREE.Insta }, - setColors: function ( array ) { + setColors: function (array) { var colors; - if ( array instanceof Float32Array ) { + if (array instanceof Float32Array) { colors = array; - } else if ( Array.isArray( array ) ) { + } else if (Array.isArray(array)) { - colors = new Float32Array( array ); + colors = new Float32Array(array); } - var instanceColorBuffer = new THREE.InstancedInterleavedBuffer( colors, 6, 1 ); // rgb, rgb + var instanceColorBuffer = new THREE.InstancedInterleavedBuffer(colors, 6, 1); // rgb, rgb - this.setAttribute( 'instanceColorStart', new THREE.InterleavedBufferAttribute( instanceColorBuffer, 3, 0 ) ); // rgb - this.setAttribute( 'instanceColorEnd', new THREE.InterleavedBufferAttribute( instanceColorBuffer, 3, 3 ) ); // rgb + this.setAttribute('instanceColorStart', new THREE.InterleavedBufferAttribute(instanceColorBuffer, 3, 0)); // rgb + this.setAttribute('instanceColorEnd', new THREE.InterleavedBufferAttribute(instanceColorBuffer, 3, 3)); // rgb return this; }, - fromWireframeGeometry: function ( geometry ) { + fromWireframeGeometry: function (geometry) { - this.setPositions( geometry.attributes.position.array ); + this.setPositions(geometry.attributes.position.array); return this; }, - fromEdgesGeometry: function ( geometry ) { + fromEdgesGeometry: function (geometry) { - this.setPositions( geometry.attributes.position.array ); + this.setPositions(geometry.attributes.position.array); return this; }, - fromMesh: function ( mesh ) { + fromMesh: function (mesh) { - this.fromWireframeGeometry( new THREE.WireframeGeometry( mesh.geometry ) ); + this.fromWireframeGeometry(new THREE.WireframeGeometry(mesh.geometry)); // set colors, maybe @@ -2397,17 +2393,18 @@ THREE.LineSegmentsGeometry.prototype = Object.assign( Object.create( THREE.Insta }, - fromLineSegements: function ( lineSegments ) { + fromLineSegments: function (lineSegments) { var geometry = lineSegments.geometry; - if ( geometry.isGeometry ) { + if (geometry.isGeometry) { - this.setPositions( geometry.vertices ); + console.error('THREE.LineSegmentsGeometry no longer supports THREE.Geometry. Use THREE.BufferGeometry instead.'); + return; - } else if ( geometry.isBufferGeometry ) { + } else if (geometry.isBufferGeometry) { - this.setPositions( geometry.position.array ); // assumes non-indexed + this.setPositions(geometry.attributes.position.array); // assumes non-indexed } @@ -2423,7 +2420,7 @@ THREE.LineSegmentsGeometry.prototype = Object.assign( Object.create( THREE.Insta return function computeBoundingBox() { - if ( this.boundingBox === null ) { + if (this.boundingBox === null) { this.boundingBox = new THREE.Box3(); @@ -2432,13 +2429,13 @@ THREE.LineSegmentsGeometry.prototype = Object.assign( Object.create( THREE.Insta var start = this.attributes.instanceStart; var end = this.attributes.instanceEnd; - if ( start !== undefined && end !== undefined ) { + if (start !== undefined && end !== undefined) { - this.boundingBox.setFromBufferAttribute( start ); + this.boundingBox.setFromBufferAttribute(start); - box.setFromBufferAttribute( end ); + box.setFromBufferAttribute(end); - this.boundingBox.union( box ); + this.boundingBox.union(box); } @@ -2452,13 +2449,13 @@ THREE.LineSegmentsGeometry.prototype = Object.assign( Object.create( THREE.Insta return function computeBoundingSphere() { - if ( this.boundingSphere === null ) { + if (this.boundingSphere === null) { this.boundingSphere = new THREE.Sphere(); } - if ( this.boundingBox === null ) { + if (this.boundingBox === null) { this.computeBoundingBox(); @@ -2467,29 +2464,29 @@ THREE.LineSegmentsGeometry.prototype = Object.assign( Object.create( THREE.Insta var start = this.attributes.instanceStart; var end = this.attributes.instanceEnd; - if ( start !== undefined && end !== undefined ) { + if (start !== undefined && end !== undefined) { var center = this.boundingSphere.center; - this.boundingBox.getCenter( center ); + this.boundingBox.getCenter(center); var maxRadiusSq = 0; - for ( var i = 0, il = start.count; i < il; i ++ ) { + for (var i = 0, il = start.count; i < il; i++) { - vector.fromBufferAttribute( start, i ); - maxRadiusSq = Math.max( maxRadiusSq, center.distanceToSquared( vector ) ); + vector.fromBufferAttribute(start, i); + maxRadiusSq = Math.max(maxRadiusSq, center.distanceToSquared(vector)); - vector.fromBufferAttribute( end, i ); - maxRadiusSq = Math.max( maxRadiusSq, center.distanceToSquared( vector ) ); + vector.fromBufferAttribute(end, i); + maxRadiusSq = Math.max(maxRadiusSq, center.distanceToSquared(vector)); } - this.boundingSphere.radius = Math.sqrt( maxRadiusSq ); + this.boundingSphere.radius = Math.sqrt(maxRadiusSq); - if ( isNaN( this.boundingSphere.radius ) ) { + if (isNaN(this.boundingSphere.radius)) { - console.error( 'THREE.LineSegmentsGeometry.computeBoundingSphere(): Computed radius is NaN. The instanced position data is likely to have NaN values.', this ); + console.error('THREE.LineSegmentsGeometry.computeBoundingSphere(): Computed radius is NaN. The instanced position data is likely to have NaN values.', this); } @@ -2505,21 +2502,15 @@ THREE.LineSegmentsGeometry.prototype = Object.assign( Object.create( THREE.Insta }, - clone: function () { - - // todo - - }, - - copy: function ( source ) { + applyMatrix: function (matrix) { - // todo + console.warn('THREE.LineSegmentsGeometry: applyMatrix() has been renamed to applyMatrix4().'); - return this; + return this.applyMatrix4(matrix); } -} ); +}); /** * @author WestLangley / http://github.com/WestLangley @@ -2528,79 +2519,80 @@ THREE.LineSegmentsGeometry.prototype = Object.assign( Object.create( THREE.Insta THREE.LineGeometry = function () { - THREE.LineSegmentsGeometry.call( this ); + THREE.LineSegmentsGeometry.call(this); this.type = 'LineGeometry'; }; -THREE.LineGeometry.prototype = Object.assign( Object.create( THREE.LineSegmentsGeometry.prototype ), { +THREE.LineGeometry.prototype = Object.assign(Object.create(THREE.LineSegmentsGeometry.prototype), { constructor: THREE.LineGeometry, isLineGeometry: true, - setPositions: function ( array ) { + setPositions: function (array) { // converts [ x1, y1, z1, x2, y2, z2, ... ] to pairs format var length = array.length - 3; - var points = new Float32Array( 2 * length ); + var points = new Float32Array(2 * length); - for ( var i = 0; i < length; i += 3 ) { + for (var i = 0; i < length; i += 3) { - points[ 2 * i ] = array[ i ]; - points[ 2 * i + 1 ] = array[ i + 1 ]; - points[ 2 * i + 2 ] = array[ i + 2 ]; + points[2 * i] = array[i]; + points[2 * i + 1] = array[i + 1]; + points[2 * i + 2] = array[i + 2]; - points[ 2 * i + 3 ] = array[ i + 3 ]; - points[ 2 * i + 4 ] = array[ i + 4 ]; - points[ 2 * i + 5 ] = array[ i + 5 ]; + points[2 * i + 3] = array[i + 3]; + points[2 * i + 4] = array[i + 4]; + points[2 * i + 5] = array[i + 5]; } - THREE.LineSegmentsGeometry.prototype.setPositions.call( this, points ); + THREE.LineSegmentsGeometry.prototype.setPositions.call(this, points); return this; }, - setColors: function ( array ) { + setColors: function (array) { // converts [ r1, g1, b1, r2, g2, b2, ... ] to pairs format var length = array.length - 3; - var colors = new Float32Array( 2 * length ); + var colors = new Float32Array(2 * length); - for ( var i = 0; i < length; i += 3 ) { + for (var i = 0; i < length; i += 3) { - colors[ 2 * i ] = array[ i ]; - colors[ 2 * i + 1 ] = array[ i + 1 ]; - colors[ 2 * i + 2 ] = array[ i + 2 ]; + colors[2 * i] = array[i]; + colors[2 * i + 1] = array[i + 1]; + colors[2 * i + 2] = array[i + 2]; - colors[ 2 * i + 3 ] = array[ i + 3 ]; - colors[ 2 * i + 4 ] = array[ i + 4 ]; - colors[ 2 * i + 5 ] = array[ i + 5 ]; + colors[2 * i + 3] = array[i + 3]; + colors[2 * i + 4] = array[i + 4]; + colors[2 * i + 5] = array[i + 5]; } - THREE.LineSegmentsGeometry.prototype.setColors.call( this, colors ); + THREE.LineSegmentsGeometry.prototype.setColors.call(this, colors); return this; }, - fromLine: function ( line ) { + fromLine: function (line) { var geometry = line.geometry; - if ( geometry.isGeometry ) { + if (geometry.isGeometry) { - this.setPositions( geometry.vertices ); + console.error('THREE.LineGeometry no longer supports THREE.Geometry. Use THREE.BufferGeometry instead.'); + return; - } else if ( geometry.isBufferGeometry ) { + } else if (geometry.isBufferGeometry) { - this.setPositions( geometry.position.array ); // assumes non-indexed + this.setPositions(geometry.attributes.position.array); // assumes non-indexed } @@ -2610,7 +2602,7 @@ THREE.LineGeometry.prototype = Object.assign( Object.create( THREE.LineSegmentsG }, - copy: function ( source ) { + copy: function ( /* source */) { // todo @@ -2618,40 +2610,32 @@ THREE.LineGeometry.prototype = Object.assign( Object.create( THREE.LineSegmentsG } -} ); +}); /** * @author WestLangley / http://github.com/WestLangley * */ -THREE.WireframeGeometry2 = function ( geometry ) { +THREE.WireframeGeometry2 = function (geometry) { - THREE.LineSegmentsGeometry.call( this ); + THREE.LineSegmentsGeometry.call(this); this.type = 'WireframeGeometry2'; - this.fromWireframeGeometry( new THREE.WireframeGeometry( geometry ) ); + this.fromWireframeGeometry(new THREE.WireframeGeometry(geometry)); // set colors, maybe }; -THREE.WireframeGeometry2.prototype = Object.assign( Object.create( THREE.LineSegmentsGeometry.prototype ), { +THREE.WireframeGeometry2.prototype = Object.assign(Object.create(THREE.LineSegmentsGeometry.prototype), { constructor: THREE.WireframeGeometry2, - isWireframeGeometry2: true, - - copy: function ( source ) { - - // todo - - return this; - - } + isWireframeGeometry2: true -} ); +}); /** * @author WestLangley / http://github.com/WestLangley @@ -2667,23 +2651,38 @@ THREE.WireframeGeometry2.prototype = Object.assign( Object.create( THREE.LineSeg * } */ +/** + * parameters = { + * color: , + * linewidth: , + * dashed: , + * dashScale: , + * dashSize: , + * dashOffset: , + * gapSize: , + * resolution: , // to be set by renderer + * } + */ + THREE.UniformsLib.line = { linewidth: { value: 1 }, - resolution: { value: new THREE.Vector2( 1, 1 ) }, + resolution: { value: new THREE.Vector2(1, 1) }, dashScale: { value: 1 }, dashSize: { value: 1 }, - gapSize: { value: 1 } // todo FIX - maybe change to totalSize + dashOffset: { value: 0 }, + gapSize: { value: 1 }, // todo FIX - maybe change to totalSize + opacity: { value: 1 } }; -THREE.ShaderLib[ 'line' ] = { +THREE.ShaderLib['line'] = { - uniforms: THREE.UniformsUtils.merge( [ + uniforms: THREE.UniformsUtils.merge([ THREE.UniformsLib.common, THREE.UniformsLib.fog, THREE.UniformsLib.line - ] ), + ]), vertexShader: ` @@ -2823,9 +2822,9 @@ THREE.ShaderLib[ 'line' ] = { gl_Position = clip; - #include + vec4 mvPosition = ( position.y < 0.5 ) ? start : end; // this is an approximation - #include + #include #include #include @@ -2840,6 +2839,7 @@ THREE.ShaderLib[ 'line' ] = { #ifdef USE_DASH uniform float dashSize; + uniform float dashOffset; uniform float gapSize; #endif @@ -2860,19 +2860,19 @@ THREE.ShaderLib[ 'line' ] = { #ifdef USE_DASH - if ( vUv.y < 0.5 || vUv.y > 0.5 ) discard; // discard endcaps + if ( vUv.y < - 1.0 || vUv.y > 1.0 ) discard; // discard endcaps - if ( mod( vLineDistance, dashSize + gapSize ) > dashSize ) discard; // todo - FIX + if ( mod( vLineDistance + dashOffset, dashSize + gapSize ) > dashSize ) discard; // todo - FIX #endif - if ( vUv.y < 0.5 || vUv.y > 0.5 ) { + if ( abs( vUv.y ) > 1.0 ) { - float a = vUv.x - 0.5; - float b = vUv.y - 0.5; + float a = vUv.x; + float b = ( vUv.y > 0.0 ) ? vUv.y - 1.0 : vUv.y + 1.0; float len2 = a * a + b * b; - if ( len2 > 0.25 ) discard; + if ( len2 > 1.0 ) discard; } @@ -2881,36 +2881,35 @@ THREE.ShaderLib[ 'line' ] = { #include #include - gl_FragColor = vec4( diffuseColor.rgb, opacity ); + gl_FragColor = vec4( diffuseColor.rgb, diffuseColor.a ); - #include #include #include #include + #include } ` }; -THREE.LineMaterial = function ( parameters ) { +THREE.LineMaterial = function (parameters) { - var lineUniforms = THREE.UniformsUtils.clone( THREE.ShaderLib[ 'line' ].uniforms ); - lineUniforms.opacity.value = parameters.opacity; - - THREE.ShaderMaterial.call( this, { + THREE.ShaderMaterial.call(this, { type: 'LineMaterial', - uniforms: lineUniforms, + uniforms: THREE.UniformsUtils.clone(THREE.ShaderLib['line'].uniforms), - vertexShader: THREE.ShaderLib[ 'line' ].vertexShader, - fragmentShader: THREE.ShaderLib[ 'line' ].fragmentShader + vertexShader: THREE.ShaderLib['line'].vertexShader, + fragmentShader: THREE.ShaderLib['line'].fragmentShader, - } ); + clipping: true // required for clipping support + + }); this.dashed = false; - Object.defineProperties( this, { + Object.defineProperties(this, { color: { @@ -2922,7 +2921,7 @@ THREE.LineMaterial = function ( parameters ) { }, - set: function ( value ) { + set: function (value) { this.uniforms.diffuse.value = value; @@ -2940,7 +2939,7 @@ THREE.LineMaterial = function ( parameters ) { }, - set: function ( value ) { + set: function (value) { this.uniforms.linewidth.value = value; @@ -2958,7 +2957,7 @@ THREE.LineMaterial = function ( parameters ) { }, - set: function ( value ) { + set: function (value) { this.uniforms.dashScale.value = value; @@ -2976,7 +2975,7 @@ THREE.LineMaterial = function ( parameters ) { }, - set: function ( value ) { + set: function (value) { this.uniforms.dashSize.value = value; @@ -2984,6 +2983,24 @@ THREE.LineMaterial = function ( parameters ) { }, + dashOffset: { + + enumerable: true, + + get: function () { + + return this.uniforms.dashOffset.value; + + }, + + set: function (value) { + + this.uniforms.dashOffset.value = value; + + } + + }, + gapSize: { enumerable: true, @@ -2994,7 +3011,7 @@ THREE.LineMaterial = function ( parameters ) { }, - set: function ( value ) { + set: function (value) { this.uniforms.gapSize.value = value; @@ -3002,74 +3019,76 @@ THREE.LineMaterial = function ( parameters ) { }, - resolution: { + opacity: { enumerable: true, get: function () { - return this.uniforms.resolution.value; + return this.uniforms.opacity.value; }, - set: function ( value ) { + set: function (value) { - this.uniforms.resolution.value.copy( value ); + this.uniforms.opacity.value = value; } - } - - } ); + }, - this.setValues( parameters ); + resolution: { -}; + enumerable: true, -THREE.LineMaterial.prototype = Object.create( THREE.ShaderMaterial.prototype ); -THREE.LineMaterial.prototype.constructor = THREE.LineMaterial; + get: function () { -THREE.LineMaterial.prototype.isLineMaterial = true; + return this.uniforms.resolution.value; -THREE.LineMaterial.prototype.copy = function ( source ) { + }, - THREE.ShaderMaterial.prototype.copy.call( this, source ); + set: function (value) { - this.color.copy( source.color ); + this.uniforms.resolution.value.copy(value); - this.linewidth = source.linewidth; + } - this.resolution = source.resolution; + } - // todo + }); - return this; + this.setValues(parameters); }; +THREE.LineMaterial.prototype = Object.create(THREE.ShaderMaterial.prototype); +THREE.LineMaterial.prototype.constructor = THREE.LineMaterial; + +THREE.LineMaterial.prototype.isLineMaterial = true; + /** * @author WestLangley / http://github.com/WestLangley * */ -THREE.LineSegments2 = function ( geometry, material ) { +THREE.LineSegments2 = function (geometry, material) { - THREE.Mesh.call( this ); + if (geometry === undefined) geometry = new THREE.LineSegmentsGeometry(); + if (material === undefined) material = new THREE.LineMaterial({ color: Math.random() * 0xffffff }); - this.type = 'LineSegments2'; + THREE.Mesh.call(this, geometry, material); - this.geometry = geometry !== undefined ? geometry : new THREE.LineSegmentsGeometry(); - this.material = material !== undefined ? material : new THREE.LineMaterial( { color: Math.random() * 0xffffff } ); + this.type = 'LineSegments2'; }; -THREE.LineSegments2.prototype = Object.assign( Object.create( THREE.Mesh.prototype ), { +THREE.LineSegments2.prototype = Object.assign(Object.create(THREE.Mesh.prototype), { constructor: THREE.LineSegments2, isLineSegments2: true, - computeLineDistances: ( function () { // for backwards-compatability, but could be a method of LineSegmentsGeometry... + computeLineDistances: (function () { // for backwards-compatability, but could be a method of LineSegmentsGeometry... var start = new THREE.Vector3(); var end = new THREE.Vector3(); @@ -3080,94 +3099,237 @@ THREE.LineSegments2.prototype = Object.assign( Object.create( THREE.Mesh.prototy var instanceStart = geometry.attributes.instanceStart; var instanceEnd = geometry.attributes.instanceEnd; - var lineDistances = new Float32Array( 2 * instanceStart.data.count ); + var lineDistances = new Float32Array(2 * instanceStart.data.count); - for ( var i = 0, j = 0, l = instanceStart.data.count; i < l; i ++, j += 2 ) { + for (var i = 0, j = 0, l = instanceStart.data.count; i < l; i++, j += 2) { - start.fromBufferAttribute( instanceStart, i ); - end.fromBufferAttribute( instanceEnd, i ); + start.fromBufferAttribute(instanceStart, i); + end.fromBufferAttribute(instanceEnd, i); - lineDistances[ j ] = ( j === 0 ) ? 0 : lineDistances[ j - 1 ]; - lineDistances[ j + 1 ] = lineDistances[ j ] + start.distanceTo( end ); + 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 + var instanceDistanceBuffer = new THREE.InstancedInterleavedBuffer(lineDistances, 2, 1); // d0, d1 - geometry.setAttribute( 'instanceDistanceStart', new THREE.InterleavedBufferAttribute( instanceDistanceBuffer, 1, 0 ) ); // d0 - geometry.setAttribute( 'instanceDistanceEnd', new THREE.InterleavedBufferAttribute( instanceDistanceBuffer, 1, 1 ) ); // d1 + geometry.setAttribute('instanceDistanceStart', new THREE.InterleavedBufferAttribute(instanceDistanceBuffer, 1, 0)); // d0 + geometry.setAttribute('instanceDistanceEnd', new THREE.InterleavedBufferAttribute(instanceDistanceBuffer, 1, 1)); // d1 return this; }; - }() ), + }()), - copy: function ( source ) { + raycast: (function () { - // todo + var start = new THREE.Vector4(); + var end = new THREE.Vector4(); - return this; + 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('LineSegments2: "Raycaster.camera" needs to be set in order to raycast against LineSegments2.'); + + } + + var threshold = (raycaster.params.Line2 !== undefined) ? raycaster.params.Line2.threshold || 0 : 0; + + 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 + threshold; + + var instanceStart = geometry.attributes.instanceStart; + var instanceEnd = geometry.attributes.instanceEnd; + + // camera forward is negative + var near = - camera.near; + + // 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); + 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++) { + + start.fromBufferAttribute(instanceStart, i); + end.fromBufferAttribute(instanceEnd, i); + + start.w = 1; + end.w = 1; + + // camera space + start.applyMatrix4(mvMatrix); + end.applyMatrix4(mvMatrix); + + // skip the segment if it's entirely behind the camera + var isBehindCameraNear = start.z > near && end.z > near; + if (isBehindCameraNear) { + + continue; + + } + + // trim the segment if it extends behind camera near + if (start.z > near) { + + const deltaDist = start.z - end.z; + const t = (start.z - near) / deltaDist; + start.lerp(end, t); + + } else if (end.z > near) { + + const deltaDist = end.z - start.z; + const t = (end.z - near) / deltaDist; + end.lerp(start, t); + + } + + // clip space + start.applyMatrix4(projectionMatrix); + end.applyMatrix4(projectionMatrix); + + // ndc space [ - 1.0, 1.0 ] + 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(ssOrigin3, true); + line.at(param, closestPoint); + + // check if the intersection point is within clip space + var zPos = THREE.MathUtils.lerp(start.z, end.z, param); + var isInClipSpace = zPos >= - 1 && zPos <= 1; + + var isInside = ssOrigin3.distanceTo(closestPoint) < lineWidth * 0.5; + + if (isInClipSpace && isInside) { + + line.start.fromBufferAttribute(instanceStart, i); + line.end.fromBufferAttribute(instanceEnd, i); + + line.start.applyMatrix4(matrixWorld); + line.end.applyMatrix4(matrixWorld); + + var pointOnLine = new THREE.Vector3(); + var point = new THREE.Vector3(); + + ray.distanceSqToSegment(line.start, line.end, point, pointOnLine); + + intersects.push({ + + point: point, + pointOnLine: pointOnLine, + distance: ray.origin.distanceTo(point), + + object: this, + face: null, + faceIndex: i, + uv: null, + uv2: null, + + }); + + } + + } + + }; + + }()) + +}); /** * @author WestLangley / http://github.com/WestLangley * */ -THREE.Line2 = function ( geometry, material ) { +THREE.Line2 = function (geometry, material) { - THREE.LineSegments2.call( this ); + if (geometry === undefined) geometry = new THREE.LineGeometry(); + if (material === undefined) material = new THREE.LineMaterial({ color: Math.random() * 0xffffff }); - this.type = 'Line2'; + THREE.LineSegments2.call(this, geometry, material); - this.geometry = geometry !== undefined ? geometry : new THREE.LineGeometry(); - this.material = material !== undefined ? material : new THREE.LineMaterial( { color: Math.random() * 0xffffff } ); + this.type = 'Line2'; }; -THREE.Line2.prototype = Object.assign( Object.create( THREE.LineSegments2.prototype ), { +THREE.Line2.prototype = Object.assign(Object.create(THREE.LineSegments2.prototype), { constructor: THREE.Line2, - isLine2: true, - - copy: function ( source ) { - - // todo - - return this; - - } + isLine2: true -} ); +}); /** * @author WestLangley / http://github.com/WestLangley * */ -THREE.Wireframe = function ( geometry, material ) { +THREE.Wireframe = function (geometry, material) { - THREE.Mesh.call( this ); + THREE.Mesh.call(this); this.type = 'Wireframe'; this.geometry = geometry !== undefined ? geometry : new THREE.LineSegmentsGeometry(); - this.material = material !== undefined ? material : new THREE.LineMaterial( { color: Math.random() * 0xffffff } ); + this.material = material !== undefined ? material : new THREE.LineMaterial({ color: Math.random() * 0xffffff }); }; -THREE.Wireframe.prototype = Object.assign( Object.create( THREE.Mesh.prototype ), { +THREE.Wireframe.prototype = Object.assign(Object.create(THREE.Mesh.prototype), { constructor: THREE.Wireframe, isWireframe: true, - computeLineDistances: ( function () { // for backwards-compatability, but could be a method of LineSegmentsGeometry... + computeLineDistances: (function () { // for backwards-compatability, but could be a method of LineSegmentsGeometry... var start = new THREE.Vector3(); var end = new THREE.Vector3(); @@ -3178,38 +3340,30 @@ THREE.Wireframe.prototype = Object.assign( Object.create( THREE.Mesh.prototype ) var instanceStart = geometry.attributes.instanceStart; var instanceEnd = geometry.attributes.instanceEnd; - var lineDistances = new Float32Array( 2 * instanceStart.data.count ); + var lineDistances = new Float32Array(2 * instanceStart.data.count); - for ( var i = 0, j = 0, l = instanceStart.data.count; i < l; i ++, j += 2 ) { + for (var i = 0, j = 0, l = instanceStart.data.count; i < l; i++, j += 2) { - start.fromBufferAttribute( instanceStart, i ); - end.fromBufferAttribute( instanceEnd, i ); + start.fromBufferAttribute(instanceStart, i); + end.fromBufferAttribute(instanceEnd, i); - lineDistances[ j ] = ( j === 0 ) ? 0 : lineDistances[ j - 1 ]; - lineDistances[ j + 1 ] = lineDistances[ j ] + start.distanceTo( end ); + 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 + var instanceDistanceBuffer = new THREE.InstancedInterleavedBuffer(lineDistances, 2, 1); // d0, d1 - geometry.setAttribute( 'instanceDistanceStart', new THREE.InterleavedBufferAttribute( instanceDistanceBuffer, 1, 0 ) ); // d0 - geometry.setAttribute( 'instanceDistanceEnd', new THREE.InterleavedBufferAttribute( instanceDistanceBuffer, 1, 1 ) ); // d1 + geometry.setAttribute('instanceDistanceStart', new THREE.InterleavedBufferAttribute(instanceDistanceBuffer, 1, 0)); // d0 + geometry.setAttribute('instanceDistanceEnd', new THREE.InterleavedBufferAttribute(instanceDistanceBuffer, 1, 1)); // d1 return this; }; - }() ), - - copy: function ( source ) { + }()) - // todo - - return this; - - } - -} ); +}); },{"../three.js":23,"../utils/utils.js":27,"./objects.js":19}],13:[function(require,module,exports){ /** diff --git a/dist/threebox.min.js b/dist/threebox.min.js index 92a89b50..4d5cdace 100644 --- a/dist/threebox.min.js +++ b/dist/threebox.min.js @@ -32,7 +32,7 @@ const Objects=require("./objects.js"),utils=require("../utils/utils.js"),THREE=r const utils=require("../utils/utils.js"),Objects=require("./objects.js"),CSS2D=require("./CSS2DRenderer.js");function Label(e){e=utils._validate(e,Objects.prototype._defaults.label);let s=Objects.prototype.drawLabelHTML(e.htmlElement,e.cssClass),t=new CSS2D.CSS2DObject(s);t.name="label",t.visible=e.alwaysVisible,t.alwaysVisible=e.alwaysVisible;var l=Objects.prototype._makeGroup(t,e);return Objects.prototype._addMethods(l),l.visibility=e.alwaysVisible,l}module.exports=exports=Label; },{"../utils/utils.js":27,"./CSS2DRenderer.js":5,"./objects.js":19}],12:[function(require,module,exports){ -const THREE=require("../three.js"),utils=require("../utils/utils.js"),Objects=require("./objects.js");function line(t){t=utils._validate(t,Objects.prototype._defaults.line);var e=utils.lnglatsToWorld(t.geometry),n=utils.normalizeVertices(e),i=utils.flattenVectors(n.vertices),r=new THREE.LineGeometry;r.setPositions(i);let o=new THREE.LineMaterial({color:t.color,linewidth:t.width,dashed:!1,opacity:t.opacity});return o.resolution.set(window.innerWidth,window.innerHeight),o.isMaterial=!0,o.transparent=!0,o.depthWrite=!1,(line=new THREE.Line2(r,o)).position.copy(n.position),line.computeLineDistances(),line}module.exports=exports=line,THREE.LineSegmentsGeometry=function(){THREE.InstancedBufferGeometry.call(this),this.type="LineSegmentsGeometry";new THREE.BufferGeometry;this.setIndex([0,2,1,2,3,1,2,4,3,4,5,3,4,6,5,6,7,5]),this.setAttribute("position",new THREE.Float32BufferAttribute([-1,2,0,1,2,0,-1,1,0,1,1,0,-1,0,0,1,0,0,-1,-1,0,1,-1,0],3)),this.setAttribute("uv",new THREE.Float32BufferAttribute([0,1,1,1,0,.5,1,.5,0,.5,1,.5,0,0,1,0],2))},THREE.LineSegmentsGeometry.prototype=Object.assign(Object.create(THREE.InstancedBufferGeometry.prototype),{constructor:THREE.LineSegmentsGeometry,isLineSegmentsGeometry:!0,applyMatrix:function(t){var e=this.attributes.instanceStart,n=this.attributes.instanceEnd;return void 0!==e&&(t.applyToBufferAttribute(e),t.applyToBufferAttribute(n),e.data.needsUpdate=!0),null!==this.boundingBox&&this.computeBoundingBox(),null!==this.boundingSphere&&this.computeBoundingSphere(),this},setPositions:function(t){var e;t instanceof Float32Array?e=t:Array.isArray(t)&&(e=new Float32Array(t));var n=new THREE.InstancedInterleavedBuffer(e,6,1);return this.setAttribute("instanceStart",new THREE.InterleavedBufferAttribute(n,3,0)),this.setAttribute("instanceEnd",new THREE.InterleavedBufferAttribute(n,3,3)),this.computeBoundingBox(),this.computeBoundingSphere(),this},setColors:function(t){var e;t instanceof Float32Array?e=t:Array.isArray(t)&&(e=new Float32Array(t));var n=new THREE.InstancedInterleavedBuffer(e,6,1);return this.setAttribute("instanceColorStart",new THREE.InterleavedBufferAttribute(n,3,0)),this.setAttribute("instanceColorEnd",new THREE.InterleavedBufferAttribute(n,3,3)),this},fromWireframeGeometry:function(t){return this.setPositions(t.attributes.position.array),this},fromEdgesGeometry:function(t){return this.setPositions(t.attributes.position.array),this},fromMesh:function(t){return this.fromWireframeGeometry(new THREE.WireframeGeometry(t.geometry)),this},fromLineSegements:function(t){var e=t.geometry;return e.isGeometry?this.setPositions(e.vertices):e.isBufferGeometry&&this.setPositions(e.position.array),this},computeBoundingBox:function(){var t=new THREE.Box3;return function(){null===this.boundingBox&&(this.boundingBox=new THREE.Box3);var e=this.attributes.instanceStart,n=this.attributes.instanceEnd;void 0!==e&&void 0!==n&&(this.boundingBox.setFromBufferAttribute(e),t.setFromBufferAttribute(n),this.boundingBox.union(t))}}(),computeBoundingSphere:function(){var t=new THREE.Vector3;return function(){null===this.boundingSphere&&(this.boundingSphere=new THREE.Sphere),null===this.boundingBox&&this.computeBoundingBox();var e=this.attributes.instanceStart,n=this.attributes.instanceEnd;if(void 0!==e&&void 0!==n){var i=this.boundingSphere.center;this.boundingBox.getCenter(i);for(var r=0,o=0,a=e.count;o\n\t\t#include \n\t\t#include \n\t\t#include \n\t\t#include \n\n\t\tuniform float linewidth;\n\t\tuniform vec2 resolution;\n\n\t\tattribute vec3 instanceStart;\n\t\tattribute vec3 instanceEnd;\n\n\t\tattribute vec3 instanceColorStart;\n\t\tattribute vec3 instanceColorEnd;\n\n\t\tvarying vec2 vUv;\n\n\t\t#ifdef USE_DASH\n\n\t\t\tuniform float dashScale;\n\t\t\tattribute float instanceDistanceStart;\n\t\t\tattribute float instanceDistanceEnd;\n\t\t\tvarying float vLineDistance;\n\n\t\t#endif\n\n\t\tvoid trimSegment( const in vec4 start, inout vec4 end ) {\n\n\t\t\t// trim end segment so it terminates between the camera plane and the near plane\n\n\t\t\t// conservative estimate of the near plane\n\t\t\tfloat a = projectionMatrix[ 2 ][ 2 ]; // 3nd entry in 3th column\n\t\t\tfloat b = projectionMatrix[ 3 ][ 2 ]; // 3nd entry in 4th column\n\t\t\tfloat nearEstimate = - 0.5 * b / a;\n\n\t\t\tfloat alpha = ( nearEstimate - start.z ) / ( end.z - start.z );\n\n\t\t\tend.xyz = mix( start.xyz, end.xyz, alpha );\n\n\t\t}\n\n\t\tvoid main() {\n\n\t\t\t#ifdef USE_COLOR\n\n\t\t\t\tvColor.xyz = ( position.y < 0.5 ) ? instanceColorStart : instanceColorEnd;\n\n\t\t\t#endif\n\n\t\t\t#ifdef USE_DASH\n\n\t\t\t\tvLineDistance = ( position.y < 0.5 ) ? dashScale * instanceDistanceStart : dashScale * instanceDistanceEnd;\n\n\t\t\t#endif\n\n\t\t\tfloat aspect = resolution.x / resolution.y;\n\n\t\t\tvUv = uv;\n\n\t\t\t// camera space\n\t\t\tvec4 start = modelViewMatrix * vec4( instanceStart, 1.0 );\n\t\t\tvec4 end = modelViewMatrix * vec4( instanceEnd, 1.0 );\n\n\t\t\t// special case for perspective projection, and segments that terminate either in, or behind, the camera plane\n\t\t\t// clearly the gpu firmware has a way of addressing this issue when projecting into ndc space\n\t\t\t// but we need to perform ndc-space calculations in the shader, so we must address this issue directly\n\t\t\t// perhaps there is a more elegant solution -- WestLangley\n\n\t\t\tbool perspective = ( projectionMatrix[ 2 ][ 3 ] == - 1.0 ); // 4th entry in the 3rd column\n\n\t\t\tif ( perspective ) {\n\n\t\t\t\tif ( start.z < 0.0 && end.z >= 0.0 ) {\n\n\t\t\t\t\ttrimSegment( start, end );\n\n\t\t\t\t} else if ( end.z < 0.0 && start.z >= 0.0 ) {\n\n\t\t\t\t\ttrimSegment( end, start );\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t\t// clip space\n\t\t\tvec4 clipStart = projectionMatrix * start;\n\t\t\tvec4 clipEnd = projectionMatrix * end;\n\n\t\t\t// ndc space\n\t\t\tvec2 ndcStart = clipStart.xy / clipStart.w;\n\t\t\tvec2 ndcEnd = clipEnd.xy / clipEnd.w;\n\n\t\t\t// direction\n\t\t\tvec2 dir = ndcEnd - ndcStart;\n\n\t\t\t// account for clip-space aspect ratio\n\t\t\tdir.x *= aspect;\n\t\t\tdir = normalize( dir );\n\n\t\t\t// perpendicular to dir\n\t\t\tvec2 offset = vec2( dir.y, - dir.x );\n\n\t\t\t// undo aspect ratio adjustment\n\t\t\tdir.x /= aspect;\n\t\t\toffset.x /= aspect;\n\n\t\t\t// sign flip\n\t\t\tif ( position.x < 0.0 ) offset *= - 1.0;\n\n\t\t\t// endcaps\n\t\t\tif ( position.y < 0.0 ) {\n\n\t\t\t\toffset += - dir;\n\n\t\t\t} else if ( position.y > 1.0 ) {\n\n\t\t\t\toffset += dir;\n\n\t\t\t}\n\n\t\t\t// adjust for linewidth\n\t\t\toffset *= linewidth;\n\n\t\t\t// adjust for clip-space to screen-space conversion // maybe resolution should be based on viewport ...\n\t\t\toffset /= resolution.y;\n\n\t\t\t// select end\n\t\t\tvec4 clip = ( position.y < 0.5 ) ? clipStart : clipEnd;\n\n\t\t\t// back to clip space\n\t\t\toffset *= clip.w;\n\n\t\t\tclip.xy += offset;\n\n\t\t\tgl_Position = clip;\n\n\t\t\t#include \n\n\t\t\t#include \n\t\t\t#include \n\t\t\t#include \n\n\t\t}\n\t\t",fragmentShader:"\n\t\tuniform vec3 diffuse;\n\t\tuniform float opacity;\n\n\t\t#ifdef USE_DASH\n\n\t\t\tuniform float dashSize;\n\t\t\tuniform float gapSize;\n\n\t\t#endif\n\n\t\tvarying float vLineDistance;\n\n\t\t#include \n\t\t#include \n\t\t#include \n\t\t#include \n\t\t#include \n\n\t\tvarying vec2 vUv;\n\n\t\tvoid main() {\n\n\t\t\t#include \n\n\t\t\t#ifdef USE_DASH\n\n\t\t\t\tif ( vUv.y < 0.5 || vUv.y > 0.5 ) discard; // discard endcaps\n\n\t\t\t\tif ( mod( vLineDistance, dashSize + gapSize ) > dashSize ) discard; // todo - FIX\n\n\t\t\t#endif\n\n\t\t\tif ( vUv.y < 0.5 || vUv.y > 0.5 ) {\n\n\t\t\t\tfloat a = vUv.x - 0.5;\n\t\t\t\tfloat b = vUv.y - 0.5;\n\t\t\t\tfloat len2 = a * a + b * b;\n\n\t\t\t\tif ( len2 > 0.25 ) discard;\n\n\t\t\t}\n\n\t\t\tvec4 diffuseColor = vec4( diffuse, opacity );\n\n\t\t\t#include \n\t\t\t#include \n\n\t\t\tgl_FragColor = vec4( diffuseColor.rgb, opacity );\n\n\t\t\t#include \n\t\t\t#include \n\t\t\t#include \n\t\t\t#include \n\n\t\t}\n\t\t"},THREE.LineMaterial=function(t){var e=THREE.UniformsUtils.clone(THREE.ShaderLib.line.uniforms);e.opacity.value=t.opacity,THREE.ShaderMaterial.call(this,{type:"LineMaterial",uniforms:e,vertexShader:THREE.ShaderLib.line.vertexShader,fragmentShader:THREE.ShaderLib.line.fragmentShader}),this.dashed=!1,Object.defineProperties(this,{color:{enumerable:!0,get:function(){return this.uniforms.diffuse.value},set:function(t){this.uniforms.diffuse.value=t}},linewidth:{enumerable:!0,get:function(){return this.uniforms.linewidth.value},set:function(t){this.uniforms.linewidth.value=t}},dashScale:{enumerable:!0,get:function(){return this.uniforms.dashScale.value},set:function(t){this.uniforms.dashScale.value=t}},dashSize:{enumerable:!0,get:function(){return this.uniforms.dashSize.value},set:function(t){this.uniforms.dashSize.value=t}},gapSize:{enumerable:!0,get:function(){return this.uniforms.gapSize.value},set:function(t){this.uniforms.gapSize.value=t}},resolution:{enumerable:!0,get:function(){return this.uniforms.resolution.value},set:function(t){this.uniforms.resolution.value.copy(t)}}}),this.setValues(t)},THREE.LineMaterial.prototype=Object.create(THREE.ShaderMaterial.prototype),THREE.LineMaterial.prototype.constructor=THREE.LineMaterial,THREE.LineMaterial.prototype.isLineMaterial=!0,THREE.LineMaterial.prototype.copy=function(t){return THREE.ShaderMaterial.prototype.copy.call(this,t),this.color.copy(t.color),this.linewidth=t.linewidth,this.resolution=t.resolution,this},THREE.LineSegments2=function(t,e){THREE.Mesh.call(this),this.type="LineSegments2",this.geometry=void 0!==t?t:new THREE.LineSegmentsGeometry,this.material=void 0!==e?e:new THREE.LineMaterial({color:16777215*Math.random()})},THREE.LineSegments2.prototype=Object.assign(Object.create(THREE.Mesh.prototype),{constructor:THREE.LineSegments2,isLineSegments2:!0,computeLineDistances:function(){var t=new THREE.Vector3,e=new THREE.Vector3;return function(){for(var n=this.geometry,i=n.attributes.instanceStart,r=n.attributes.instanceEnd,o=new Float32Array(2*i.data.count),a=0,s=0,c=i.data.count;a\n\t\t#include \n\t\t#include \n\t\t#include \n\t\t#include \n\n\t\tuniform float linewidth;\n\t\tuniform vec2 resolution;\n\n\t\tattribute vec3 instanceStart;\n\t\tattribute vec3 instanceEnd;\n\n\t\tattribute vec3 instanceColorStart;\n\t\tattribute vec3 instanceColorEnd;\n\n\t\tvarying vec2 vUv;\n\n\t\t#ifdef USE_DASH\n\n\t\t\tuniform float dashScale;\n\t\t\tattribute float instanceDistanceStart;\n\t\t\tattribute float instanceDistanceEnd;\n\t\t\tvarying float vLineDistance;\n\n\t\t#endif\n\n\t\tvoid trimSegment( const in vec4 start, inout vec4 end ) {\n\n\t\t\t// trim end segment so it terminates between the camera plane and the near plane\n\n\t\t\t// conservative estimate of the near plane\n\t\t\tfloat a = projectionMatrix[ 2 ][ 2 ]; // 3nd entry in 3th column\n\t\t\tfloat b = projectionMatrix[ 3 ][ 2 ]; // 3nd entry in 4th column\n\t\t\tfloat nearEstimate = - 0.5 * b / a;\n\n\t\t\tfloat alpha = ( nearEstimate - start.z ) / ( end.z - start.z );\n\n\t\t\tend.xyz = mix( start.xyz, end.xyz, alpha );\n\n\t\t}\n\n\t\tvoid main() {\n\n\t\t\t#ifdef USE_COLOR\n\n\t\t\t\tvColor.xyz = ( position.y < 0.5 ) ? instanceColorStart : instanceColorEnd;\n\n\t\t\t#endif\n\n\t\t\t#ifdef USE_DASH\n\n\t\t\t\tvLineDistance = ( position.y < 0.5 ) ? dashScale * instanceDistanceStart : dashScale * instanceDistanceEnd;\n\n\t\t\t#endif\n\n\t\t\tfloat aspect = resolution.x / resolution.y;\n\n\t\t\tvUv = uv;\n\n\t\t\t// camera space\n\t\t\tvec4 start = modelViewMatrix * vec4( instanceStart, 1.0 );\n\t\t\tvec4 end = modelViewMatrix * vec4( instanceEnd, 1.0 );\n\n\t\t\t// special case for perspective projection, and segments that terminate either in, or behind, the camera plane\n\t\t\t// clearly the gpu firmware has a way of addressing this issue when projecting into ndc space\n\t\t\t// but we need to perform ndc-space calculations in the shader, so we must address this issue directly\n\t\t\t// perhaps there is a more elegant solution -- WestLangley\n\n\t\t\tbool perspective = ( projectionMatrix[ 2 ][ 3 ] == - 1.0 ); // 4th entry in the 3rd column\n\n\t\t\tif ( perspective ) {\n\n\t\t\t\tif ( start.z < 0.0 && end.z >= 0.0 ) {\n\n\t\t\t\t\ttrimSegment( start, end );\n\n\t\t\t\t} else if ( end.z < 0.0 && start.z >= 0.0 ) {\n\n\t\t\t\t\ttrimSegment( end, start );\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t\t// clip space\n\t\t\tvec4 clipStart = projectionMatrix * start;\n\t\t\tvec4 clipEnd = projectionMatrix * end;\n\n\t\t\t// ndc space\n\t\t\tvec2 ndcStart = clipStart.xy / clipStart.w;\n\t\t\tvec2 ndcEnd = clipEnd.xy / clipEnd.w;\n\n\t\t\t// direction\n\t\t\tvec2 dir = ndcEnd - ndcStart;\n\n\t\t\t// account for clip-space aspect ratio\n\t\t\tdir.x *= aspect;\n\t\t\tdir = normalize( dir );\n\n\t\t\t// perpendicular to dir\n\t\t\tvec2 offset = vec2( dir.y, - dir.x );\n\n\t\t\t// undo aspect ratio adjustment\n\t\t\tdir.x /= aspect;\n\t\t\toffset.x /= aspect;\n\n\t\t\t// sign flip\n\t\t\tif ( position.x < 0.0 ) offset *= - 1.0;\n\n\t\t\t// endcaps\n\t\t\tif ( position.y < 0.0 ) {\n\n\t\t\t\toffset += - dir;\n\n\t\t\t} else if ( position.y > 1.0 ) {\n\n\t\t\t\toffset += dir;\n\n\t\t\t}\n\n\t\t\t// adjust for linewidth\n\t\t\toffset *= linewidth;\n\n\t\t\t// adjust for clip-space to screen-space conversion // maybe resolution should be based on viewport ...\n\t\t\toffset /= resolution.y;\n\n\t\t\t// select end\n\t\t\tvec4 clip = ( position.y < 0.5 ) ? clipStart : clipEnd;\n\n\t\t\t// back to clip space\n\t\t\toffset *= clip.w;\n\n\t\t\tclip.xy += offset;\n\n\t\t\tgl_Position = clip;\n\n\t\t\tvec4 mvPosition = ( position.y < 0.5 ) ? start : end; // this is an approximation\n\n\t\t\t#include \n\t\t\t#include \n\t\t\t#include \n\n\t\t}\n\t\t",fragmentShader:"\n\t\tuniform vec3 diffuse;\n\t\tuniform float opacity;\n\n\t\t#ifdef USE_DASH\n\n\t\t\tuniform float dashSize;\n\t\t\tuniform float dashOffset;\n\t\t\tuniform float gapSize;\n\n\t\t#endif\n\n\t\tvarying float vLineDistance;\n\n\t\t#include \n\t\t#include \n\t\t#include \n\t\t#include \n\t\t#include \n\n\t\tvarying vec2 vUv;\n\n\t\tvoid main() {\n\n\t\t\t#include \n\n\t\t\t#ifdef USE_DASH\n\n\t\t\t\tif ( vUv.y < - 1.0 || vUv.y > 1.0 ) discard; // discard endcaps\n\n\t\t\t\tif ( mod( vLineDistance + dashOffset, dashSize + gapSize ) > dashSize ) discard; // todo - FIX\n\n\t\t\t#endif\n\n\t\t\tif ( abs( vUv.y ) > 1.0 ) {\n\n\t\t\t\tfloat a = vUv.x;\n\t\t\t\tfloat b = ( vUv.y > 0.0 ) ? vUv.y - 1.0 : vUv.y + 1.0;\n\t\t\t\tfloat len2 = a * a + b * b;\n\n\t\t\t\tif ( len2 > 1.0 ) discard;\n\n\t\t\t}\n\n\t\t\tvec4 diffuseColor = vec4( diffuse, opacity );\n\n\t\t\t#include \n\t\t\t#include \n\n\t\t\tgl_FragColor = vec4( diffuseColor.rgb, diffuseColor.a );\n\n\t\t\t#include \n\t\t\t#include \n\t\t\t#include \n\t\t\t#include \n\n\t\t}\n\t\t"},THREE.LineMaterial=function(t){THREE.ShaderMaterial.call(this,{type:"LineMaterial",uniforms:THREE.UniformsUtils.clone(THREE.ShaderLib.line.uniforms),vertexShader:THREE.ShaderLib.line.vertexShader,fragmentShader:THREE.ShaderLib.line.fragmentShader,clipping:!0}),this.dashed=!1,Object.defineProperties(this,{color:{enumerable:!0,get:function(){return this.uniforms.diffuse.value},set:function(t){this.uniforms.diffuse.value=t}},linewidth:{enumerable:!0,get:function(){return this.uniforms.linewidth.value},set:function(t){this.uniforms.linewidth.value=t}},dashScale:{enumerable:!0,get:function(){return this.uniforms.dashScale.value},set:function(t){this.uniforms.dashScale.value=t}},dashSize:{enumerable:!0,get:function(){return this.uniforms.dashSize.value},set:function(t){this.uniforms.dashSize.value=t}},dashOffset:{enumerable:!0,get:function(){return this.uniforms.dashOffset.value},set:function(t){this.uniforms.dashOffset.value=t}},gapSize:{enumerable:!0,get:function(){return this.uniforms.gapSize.value},set:function(t){this.uniforms.gapSize.value=t}},opacity:{enumerable:!0,get:function(){return this.uniforms.opacity.value},set:function(t){this.uniforms.opacity.value=t}},resolution:{enumerable:!0,get:function(){return this.uniforms.resolution.value},set:function(t){this.uniforms.resolution.value.copy(t)}}}),this.setValues(t)},THREE.LineMaterial.prototype=Object.create(THREE.ShaderMaterial.prototype),THREE.LineMaterial.prototype.constructor=THREE.LineMaterial,THREE.LineMaterial.prototype.isLineMaterial=!0,THREE.LineSegments2=function(t,e){void 0===t&&(t=new THREE.LineSegmentsGeometry),void 0===e&&(e=new THREE.LineMaterial({color:16777215*Math.random()})),THREE.Mesh.call(this,t,e),this.type="LineSegments2"},THREE.LineSegments2.prototype=Object.assign(Object.create(THREE.Mesh.prototype),{constructor:THREE.LineSegments2,isLineSegments2:!0,computeLineDistances:function(){var t=new THREE.Vector3,e=new THREE.Vector3;return function(){for(var n=this.geometry,i=n.attributes.instanceStart,r=n.attributes.instanceEnd,a=new Float32Array(2*i.data.count),o=0,s=0,c=i.data.count;og&&e.z>g)){if(t.z>g){const n=t.z-e.z,i=(t.z-g)/n;t.lerp(e,i)}else if(e.z>g){const n=e.z-t.z,i=(e.z-g)/n;e.lerp(t,i)}t.applyMatrix4(d),e.applyMatrix4(d),t.multiplyScalar(1/t.w),e.multiplyScalar(1/e.w),t.x*=E.x/2,t.y*=E.y/2,e.x*=E.x/2,e.y*=E.y/2,a.start.copy(t),a.start.z=0,a.end.copy(e),a.end.z=0;var H=a.closestPointToPointParameter(i,!0);a.at(H,o);var R=THREE.MathUtils.lerp(t.z,e.z,H),w=R>=-1&&R<=1,x=i.distanceTo(o)<.5*h;if(w&&x){a.start.fromBufferAttribute(y,T),a.end.fromBufferAttribute(v,T),a.start.applyMatrix4(b),a.end.applyMatrix4(b);var L=new THREE.Vector3,B=new THREE.Vector3;l.distanceSqToSegment(a.start,a.end,B,L),c.push({point:B,pointOnLine:L,distance:l.origin.distanceTo(B),object:this,face:null,faceIndex:T,uv:null,uv2:null})}}}}}()}),THREE.Line2=function(t,e){void 0===t&&(t=new THREE.LineGeometry),void 0===e&&(e=new THREE.LineMaterial({color:16777215*Math.random()})),THREE.LineSegments2.call(this,t,e),this.type="Line2"},THREE.Line2.prototype=Object.assign(Object.create(THREE.LineSegments2.prototype),{constructor:THREE.Line2,isLine2:!0}),THREE.Wireframe=function(t,e){THREE.Mesh.call(this),this.type="Wireframe",this.geometry=void 0!==t?t:new THREE.LineSegmentsGeometry,this.material=void 0!==e?e:new THREE.LineMaterial({color:16777215*Math.random()})},THREE.Wireframe.prototype=Object.assign(Object.create(THREE.Mesh.prototype),{constructor:THREE.Wireframe,isWireframe:!0,computeLineDistances:function(){var t=new THREE.Vector3,e=new THREE.Vector3;return function(){for(var n=this.geometry,i=n.attributes.instanceStart,r=n.attributes.instanceEnd,a=new Float32Array(2*i.data.count),o=0,s=0,c=i.data.count;o{let t=[];switch(e.type){case"mtl":r=r.children[0];break;case"gltf":case"glb":case"dae":t=r.animations,r=r.scene;break;case"fbx":t=r.animations}r.animations=t;const l=utils.types.rotation(e.rotation,[0,0,0]),s=utils.types.scale(e.scale,[1,1,1]);r.rotation.set(l[0],l[1],l[2]),r.scale.set(s[0],s[1],s[2]),e.normalize&&function(e){e.traverse(function(e){if(e.isMesh){let a;"MeshStandardMaterial"==e.material.type?(e.material.metalness&&(e.material.metalness*=.1),e.material.glossiness&&(e.material.glossiness*=.25),a=new THREE.Color(12,12,12)):"MeshPhongMaterial"==e.material.type&&(e.material.shininess=.1,a=new THREE.Color(20,20,20)),e.material.specular&&e.material.specular.isColor&&(e.material.specular=a)}})}(r),r.name="model";let d=Objects.prototype._makeGroup(r,e);Objects.prototype._addMethods(d),d.setAnchor(e.anchor),d.setCenter(e.adjustment),d.raycasted=e.raycasted,o(d),a(d),d.setFixedZoom(e.mapScale),d.idle()},()=>null,a=>{console.error("Could not load model file: "+e.obj+" \n "+a.stack),o("Error loading the model")})},()=>null,e=>{console.warn("No material file found for SymbolLayer3D model "+m)})}module.exports=exports=loadObj; diff --git a/examples/19-fixedzoom.html b/examples/19-fixedzoom.html index 33ddbdb8..71fa55c3 100644 --- a/examples/19-fixedzoom.html +++ b/examples/19-fixedzoom.html @@ -29,7 +29,7 @@ mapboxgl.accessToken = config.accessToken; let mapConfig = { MAD: { - origin: [-3.460539968876, 40.4849214450, 0], destination: [-3.378467560041173, 40.551832030917126, 1500], center: [-3.44885, 40.49198, 0], zoom: 14.4, pitch: 50, bearing: -13, scale: 1, timezone: 'Europe/Madrid' + origin: [-3.460539968876, 40.4849214450, 0], destination: [-3.378467560041173, 40.551832030917126, 1500], center: [-3.44885, 40.49198, 0], zoom: 13.4, pitch: 50, bearing: -13, scale: 1, timezone: 'Europe/Madrid' }, names: { customLayer: "custom-layer" @@ -104,15 +104,14 @@ plane.castShadow = true; tb.add(plane); - //fly(flightPlan); - //setTimeout(() => { fly(flightPlan) }, 3000); - setTimeout(() => { - let opt = { - coords: mapConfig.MAD.destination, duration: 20000 - }; - plane.set(opt) - }, 3000); - + fly(flightPlan); + + //setTimeout(() => { + // let opt = { + // coords: mapConfig.MAD.destination, duration: 20000 + // }; + // plane.set(opt) + //}, 3000); }) }, @@ -148,5 +147,216 @@ tb.map.repaint = true; } + let line; + + function fly(data) { + // extract path geometry from callback geojson, and set duration of travel + var options = { + path: data.geometry.coordinates, + duration: 40000 + } + + // start the truck animation with above options, and remove the line when animation ends + plane.followPath( + options, + function () { + tb.remove(line); + } + ); + + // set up geometry for a line to be added to map, lofting it up a bit for *style* + let lineGeometry = options.path; + + // create and add line object + line = tb.line({ + geometry: lineGeometry, + width: 5, + color: 'steelblue' + }) + + tb.add(line, mapConfig.names.customLayer); + + } + + let flightPlan = { + "geometry": { + "coordinates": [ + [ + -3.459164318324355, + 40.483196679459695, + 0 + ], + [ + -3.46032158100065006, + 40.48405772625512, + 0 + ], + [ + -3.4601480276212726, + 40.48464924045098, + 0 + ], + [ + -3.4605399688768728, + 40.48492144503072, + 0 + ], + [ + -3.4544247306827174, + 40.489871726679894, + 0 + ], + [ + -3.4419511970175165, + 40.49989552385142, + 100 + ], + [ + -3.4199262740950473, + 40.51776139362727, + 800 + ], + [ + -3.4064155093898023, + 40.52744748436612, + 1000 + ], + [ + -3.394276165400413, + 40.53214151673197, + 1400 + ], + [ + -3.3774962506359145, + 40.53130304189972, + 1800 + ], + [ + -3.35977648690141, + 40.523996322867305, + 2000 + ], + [ + -3.3492733309630296, + 40.51239798757899, + 1000 + ], + [ + -3.345716577158697, + 40.494919870461985, + 1000 + ], + [ + -3.351353597163751, + 40.4797236141558, + 1000 + ], + [ + -3.3787722011184655, + 40.45432754114316, + 1000 + ], + [ + -3.4223595762896935, + 40.41937230956262, + 1000 + ], + [ + -3.444433667203299, + 40.40449665396977, + 1000 + ], + [ + -3.4678526394398546, + 40.39535552525871, + 1000 + ], + [ + -3.4864554257066516, + 40.39245520592732, + 1000 + ], + [ + -3.503812672766088, + 40.39513567933946, + 1000 + ], + [ + -3.5170856837534643, + 40.40280870363367, + 1000 + ], + [ + -3.526080266123671, + 40.41452098042856, + 1000 + ], + [ + -3.5294395670147196, + 40.42627781810833, + 1000 + ], + [ + -3.5263900139946713, + 40.43272665526561, + 1000 + ], + [ + -3.520955322876091, + 40.43652271714541, + 900 + ], + [ + -3.512454752467022, + 40.442395503099675, + 600 + ], + [ + -3.496113157862709, + 40.45605326123382, + 400 + ], + [ + -3.4802314192833705, + 40.46895283940685, + 200 + ], + [ + -3.4673761065382394, + 40.47937019244051, + 100 + ], + [ + -3.4611694105603874, + 40.4843367730719, + 0 + ], + [ + -3.460447314584286, + 40.48495391198887, + 0 + ], + [ + -3.460162097548647, + 40.48469346302471, + 0 + ], + [ + -3.460400363301318, + 40.48398852655413, + 0 + ], + [ + -3.4591431034406526, + 40.48323937836338, + 0 + ] + ], + "type": "LineString" + }, + "type": "Feature", + "properties": {} + } + diff --git a/src/objects/line.js b/src/objects/line.js index 80fbad3d..b32918c1 100644 --- a/src/objects/line.js +++ b/src/objects/line.js @@ -38,8 +38,6 @@ function line(obj){ module.exports = exports = line; - - /** * custom line shader by WestLangley, sourced from https://github.com/mrdoob/three.js/tree/master/examples/js/lines * @@ -47,50 +45,48 @@ module.exports = exports = line; THREE.LineSegmentsGeometry = function () { - THREE.InstancedBufferGeometry.call( this ); + THREE.InstancedBufferGeometry.call(this); this.type = 'LineSegmentsGeometry'; - var plane = new THREE.BufferGeometry(); - - var positions = [ - 1, 2, 0, 1, 2, 0, - 1, 1, 0, 1, 1, 0, - 1, 0, 0, 1, 0, 0, - 1, - 1, 0, 1, - 1, 0 ]; - var uvs = [ 0, 1, 1, 1, 0, .5, 1, .5, 0, .5, 1, .5, 0, 0, 1, 0 ]; - var index = [ 0, 2, 1, 2, 3, 1, 2, 4, 3, 4, 5, 3, 4, 6, 5, 6, 7, 5 ]; + var positions = [- 1, 2, 0, 1, 2, 0, - 1, 1, 0, 1, 1, 0, - 1, 0, 0, 1, 0, 0, - 1, - 1, 0, 1, - 1, 0]; + var uvs = [- 1, 2, 1, 2, - 1, 1, 1, 1, - 1, - 1, 1, - 1, - 1, - 2, 1, - 2]; + var index = [0, 2, 1, 2, 3, 1, 2, 4, 3, 4, 5, 3, 4, 6, 5, 6, 7, 5]; - this.setIndex( index ); - this.setAttribute( 'position', new THREE.Float32BufferAttribute( positions, 3 ) ); - this.setAttribute( 'uv', new THREE.Float32BufferAttribute( uvs, 2 ) ); + this.setIndex(index); + this.setAttribute('position', new THREE.Float32BufferAttribute(positions, 3)); + this.setAttribute('uv', new THREE.Float32BufferAttribute(uvs, 2)); }; -THREE.LineSegmentsGeometry.prototype = Object.assign( Object.create( THREE.InstancedBufferGeometry.prototype ), { +THREE.LineSegmentsGeometry.prototype = Object.assign(Object.create(THREE.InstancedBufferGeometry.prototype), { constructor: THREE.LineSegmentsGeometry, isLineSegmentsGeometry: true, - applyMatrix: function ( matrix ) { + applyMatrix4: function (matrix) { var start = this.attributes.instanceStart; var end = this.attributes.instanceEnd; - if ( start !== undefined ) { + if (start !== undefined) { - matrix.applyToBufferAttribute( start ); + start.applyMatrix4(matrix); - matrix.applyToBufferAttribute( end ); + end.applyMatrix4(matrix); - start.data.needsUpdate = true; + start.needsUpdate = true; } - if ( this.boundingBox !== null ) { + if (this.boundingBox !== null) { this.computeBoundingBox(); } - if ( this.boundingSphere !== null ) { + if (this.boundingSphere !== null) { this.computeBoundingSphere(); @@ -100,24 +96,24 @@ THREE.LineSegmentsGeometry.prototype = Object.assign( Object.create( THREE.Insta }, - setPositions: function ( array ) { + setPositions: function (array) { var lineSegments; - if ( array instanceof Float32Array ) { + if (array instanceof Float32Array) { lineSegments = array; - } else if ( Array.isArray( array ) ) { + } else if (Array.isArray(array)) { - lineSegments = new Float32Array( array ); + lineSegments = new Float32Array(array); } - var instanceBuffer = new THREE.InstancedInterleavedBuffer( lineSegments, 6, 1 ); // xyz, xyz + var instanceBuffer = new THREE.InstancedInterleavedBuffer(lineSegments, 6, 1); // xyz, xyz - this.setAttribute( 'instanceStart', new THREE.InterleavedBufferAttribute( instanceBuffer, 3, 0 ) ); // xyz - this.setAttribute( 'instanceEnd', new THREE.InterleavedBufferAttribute( instanceBuffer, 3, 3 ) ); // xyz + this.setAttribute('instanceStart', new THREE.InterleavedBufferAttribute(instanceBuffer, 3, 0)); // xyz + this.setAttribute('instanceEnd', new THREE.InterleavedBufferAttribute(instanceBuffer, 3, 3)); // xyz // @@ -128,48 +124,48 @@ THREE.LineSegmentsGeometry.prototype = Object.assign( Object.create( THREE.Insta }, - setColors: function ( array ) { + setColors: function (array) { var colors; - if ( array instanceof Float32Array ) { + if (array instanceof Float32Array) { colors = array; - } else if ( Array.isArray( array ) ) { + } else if (Array.isArray(array)) { - colors = new Float32Array( array ); + colors = new Float32Array(array); } - var instanceColorBuffer = new THREE.InstancedInterleavedBuffer( colors, 6, 1 ); // rgb, rgb + var instanceColorBuffer = new THREE.InstancedInterleavedBuffer(colors, 6, 1); // rgb, rgb - this.setAttribute( 'instanceColorStart', new THREE.InterleavedBufferAttribute( instanceColorBuffer, 3, 0 ) ); // rgb - this.setAttribute( 'instanceColorEnd', new THREE.InterleavedBufferAttribute( instanceColorBuffer, 3, 3 ) ); // rgb + this.setAttribute('instanceColorStart', new THREE.InterleavedBufferAttribute(instanceColorBuffer, 3, 0)); // rgb + this.setAttribute('instanceColorEnd', new THREE.InterleavedBufferAttribute(instanceColorBuffer, 3, 3)); // rgb return this; }, - fromWireframeGeometry: function ( geometry ) { + fromWireframeGeometry: function (geometry) { - this.setPositions( geometry.attributes.position.array ); + this.setPositions(geometry.attributes.position.array); return this; }, - fromEdgesGeometry: function ( geometry ) { + fromEdgesGeometry: function (geometry) { - this.setPositions( geometry.attributes.position.array ); + this.setPositions(geometry.attributes.position.array); return this; }, - fromMesh: function ( mesh ) { + fromMesh: function (mesh) { - this.fromWireframeGeometry( new THREE.WireframeGeometry( mesh.geometry ) ); + this.fromWireframeGeometry(new THREE.WireframeGeometry(mesh.geometry)); // set colors, maybe @@ -177,17 +173,18 @@ THREE.LineSegmentsGeometry.prototype = Object.assign( Object.create( THREE.Insta }, - fromLineSegements: function ( lineSegments ) { + fromLineSegments: function (lineSegments) { var geometry = lineSegments.geometry; - if ( geometry.isGeometry ) { + if (geometry.isGeometry) { - this.setPositions( geometry.vertices ); + console.error('THREE.LineSegmentsGeometry no longer supports THREE.Geometry. Use THREE.BufferGeometry instead.'); + return; - } else if ( geometry.isBufferGeometry ) { + } else if (geometry.isBufferGeometry) { - this.setPositions( geometry.position.array ); // assumes non-indexed + this.setPositions(geometry.attributes.position.array); // assumes non-indexed } @@ -203,7 +200,7 @@ THREE.LineSegmentsGeometry.prototype = Object.assign( Object.create( THREE.Insta return function computeBoundingBox() { - if ( this.boundingBox === null ) { + if (this.boundingBox === null) { this.boundingBox = new THREE.Box3(); @@ -212,13 +209,13 @@ THREE.LineSegmentsGeometry.prototype = Object.assign( Object.create( THREE.Insta var start = this.attributes.instanceStart; var end = this.attributes.instanceEnd; - if ( start !== undefined && end !== undefined ) { + if (start !== undefined && end !== undefined) { - this.boundingBox.setFromBufferAttribute( start ); + this.boundingBox.setFromBufferAttribute(start); - box.setFromBufferAttribute( end ); + box.setFromBufferAttribute(end); - this.boundingBox.union( box ); + this.boundingBox.union(box); } @@ -232,13 +229,13 @@ THREE.LineSegmentsGeometry.prototype = Object.assign( Object.create( THREE.Insta return function computeBoundingSphere() { - if ( this.boundingSphere === null ) { + if (this.boundingSphere === null) { this.boundingSphere = new THREE.Sphere(); } - if ( this.boundingBox === null ) { + if (this.boundingBox === null) { this.computeBoundingBox(); @@ -247,29 +244,29 @@ THREE.LineSegmentsGeometry.prototype = Object.assign( Object.create( THREE.Insta var start = this.attributes.instanceStart; var end = this.attributes.instanceEnd; - if ( start !== undefined && end !== undefined ) { + if (start !== undefined && end !== undefined) { var center = this.boundingSphere.center; - this.boundingBox.getCenter( center ); + this.boundingBox.getCenter(center); var maxRadiusSq = 0; - for ( var i = 0, il = start.count; i < il; i ++ ) { + for (var i = 0, il = start.count; i < il; i++) { - vector.fromBufferAttribute( start, i ); - maxRadiusSq = Math.max( maxRadiusSq, center.distanceToSquared( vector ) ); + vector.fromBufferAttribute(start, i); + maxRadiusSq = Math.max(maxRadiusSq, center.distanceToSquared(vector)); - vector.fromBufferAttribute( end, i ); - maxRadiusSq = Math.max( maxRadiusSq, center.distanceToSquared( vector ) ); + vector.fromBufferAttribute(end, i); + maxRadiusSq = Math.max(maxRadiusSq, center.distanceToSquared(vector)); } - this.boundingSphere.radius = Math.sqrt( maxRadiusSq ); + this.boundingSphere.radius = Math.sqrt(maxRadiusSq); - if ( isNaN( this.boundingSphere.radius ) ) { + if (isNaN(this.boundingSphere.radius)) { - console.error( 'THREE.LineSegmentsGeometry.computeBoundingSphere(): Computed radius is NaN. The instanced position data is likely to have NaN values.', this ); + console.error('THREE.LineSegmentsGeometry.computeBoundingSphere(): Computed radius is NaN. The instanced position data is likely to have NaN values.', this); } @@ -285,21 +282,15 @@ THREE.LineSegmentsGeometry.prototype = Object.assign( Object.create( THREE.Insta }, - clone: function () { - - // todo - - }, - - copy: function ( source ) { + applyMatrix: function (matrix) { - // todo + console.warn('THREE.LineSegmentsGeometry: applyMatrix() has been renamed to applyMatrix4().'); - return this; + return this.applyMatrix4(matrix); } -} ); +}); /** * @author WestLangley / http://github.com/WestLangley @@ -308,79 +299,80 @@ THREE.LineSegmentsGeometry.prototype = Object.assign( Object.create( THREE.Insta THREE.LineGeometry = function () { - THREE.LineSegmentsGeometry.call( this ); + THREE.LineSegmentsGeometry.call(this); this.type = 'LineGeometry'; }; -THREE.LineGeometry.prototype = Object.assign( Object.create( THREE.LineSegmentsGeometry.prototype ), { +THREE.LineGeometry.prototype = Object.assign(Object.create(THREE.LineSegmentsGeometry.prototype), { constructor: THREE.LineGeometry, isLineGeometry: true, - setPositions: function ( array ) { + setPositions: function (array) { // converts [ x1, y1, z1, x2, y2, z2, ... ] to pairs format var length = array.length - 3; - var points = new Float32Array( 2 * length ); + var points = new Float32Array(2 * length); - for ( var i = 0; i < length; i += 3 ) { + for (var i = 0; i < length; i += 3) { - points[ 2 * i ] = array[ i ]; - points[ 2 * i + 1 ] = array[ i + 1 ]; - points[ 2 * i + 2 ] = array[ i + 2 ]; + points[2 * i] = array[i]; + points[2 * i + 1] = array[i + 1]; + points[2 * i + 2] = array[i + 2]; - points[ 2 * i + 3 ] = array[ i + 3 ]; - points[ 2 * i + 4 ] = array[ i + 4 ]; - points[ 2 * i + 5 ] = array[ i + 5 ]; + points[2 * i + 3] = array[i + 3]; + points[2 * i + 4] = array[i + 4]; + points[2 * i + 5] = array[i + 5]; } - THREE.LineSegmentsGeometry.prototype.setPositions.call( this, points ); + THREE.LineSegmentsGeometry.prototype.setPositions.call(this, points); return this; }, - setColors: function ( array ) { + setColors: function (array) { // converts [ r1, g1, b1, r2, g2, b2, ... ] to pairs format var length = array.length - 3; - var colors = new Float32Array( 2 * length ); + var colors = new Float32Array(2 * length); - for ( var i = 0; i < length; i += 3 ) { + for (var i = 0; i < length; i += 3) { - colors[ 2 * i ] = array[ i ]; - colors[ 2 * i + 1 ] = array[ i + 1 ]; - colors[ 2 * i + 2 ] = array[ i + 2 ]; + colors[2 * i] = array[i]; + colors[2 * i + 1] = array[i + 1]; + colors[2 * i + 2] = array[i + 2]; - colors[ 2 * i + 3 ] = array[ i + 3 ]; - colors[ 2 * i + 4 ] = array[ i + 4 ]; - colors[ 2 * i + 5 ] = array[ i + 5 ]; + colors[2 * i + 3] = array[i + 3]; + colors[2 * i + 4] = array[i + 4]; + colors[2 * i + 5] = array[i + 5]; } - THREE.LineSegmentsGeometry.prototype.setColors.call( this, colors ); + THREE.LineSegmentsGeometry.prototype.setColors.call(this, colors); return this; }, - fromLine: function ( line ) { + fromLine: function (line) { var geometry = line.geometry; - if ( geometry.isGeometry ) { + if (geometry.isGeometry) { - this.setPositions( geometry.vertices ); + console.error('THREE.LineGeometry no longer supports THREE.Geometry. Use THREE.BufferGeometry instead.'); + return; - } else if ( geometry.isBufferGeometry ) { + } else if (geometry.isBufferGeometry) { - this.setPositions( geometry.position.array ); // assumes non-indexed + this.setPositions(geometry.attributes.position.array); // assumes non-indexed } @@ -390,7 +382,7 @@ THREE.LineGeometry.prototype = Object.assign( Object.create( THREE.LineSegmentsG }, - copy: function ( source ) { + copy: function ( /* source */) { // todo @@ -398,40 +390,32 @@ THREE.LineGeometry.prototype = Object.assign( Object.create( THREE.LineSegmentsG } -} ); +}); /** * @author WestLangley / http://github.com/WestLangley * */ -THREE.WireframeGeometry2 = function ( geometry ) { +THREE.WireframeGeometry2 = function (geometry) { - THREE.LineSegmentsGeometry.call( this ); + THREE.LineSegmentsGeometry.call(this); this.type = 'WireframeGeometry2'; - this.fromWireframeGeometry( new THREE.WireframeGeometry( geometry ) ); + this.fromWireframeGeometry(new THREE.WireframeGeometry(geometry)); // set colors, maybe }; -THREE.WireframeGeometry2.prototype = Object.assign( Object.create( THREE.LineSegmentsGeometry.prototype ), { +THREE.WireframeGeometry2.prototype = Object.assign(Object.create(THREE.LineSegmentsGeometry.prototype), { constructor: THREE.WireframeGeometry2, - isWireframeGeometry2: true, + isWireframeGeometry2: true - copy: function ( source ) { - - // todo - - return this; - - } - -} ); +}); /** * @author WestLangley / http://github.com/WestLangley @@ -447,23 +431,38 @@ THREE.WireframeGeometry2.prototype = Object.assign( Object.create( THREE.LineSeg * } */ +/** + * parameters = { + * color: , + * linewidth: , + * dashed: , + * dashScale: , + * dashSize: , + * dashOffset: , + * gapSize: , + * resolution: , // to be set by renderer + * } + */ + THREE.UniformsLib.line = { linewidth: { value: 1 }, - resolution: { value: new THREE.Vector2( 1, 1 ) }, + resolution: { value: new THREE.Vector2(1, 1) }, dashScale: { value: 1 }, dashSize: { value: 1 }, - gapSize: { value: 1 } // todo FIX - maybe change to totalSize + dashOffset: { value: 0 }, + gapSize: { value: 1 }, // todo FIX - maybe change to totalSize + opacity: { value: 1 } }; -THREE.ShaderLib[ 'line' ] = { +THREE.ShaderLib['line'] = { - uniforms: THREE.UniformsUtils.merge( [ + uniforms: THREE.UniformsUtils.merge([ THREE.UniformsLib.common, THREE.UniformsLib.fog, THREE.UniformsLib.line - ] ), + ]), vertexShader: ` @@ -603,9 +602,9 @@ THREE.ShaderLib[ 'line' ] = { gl_Position = clip; - #include + vec4 mvPosition = ( position.y < 0.5 ) ? start : end; // this is an approximation - #include + #include #include #include @@ -620,6 +619,7 @@ THREE.ShaderLib[ 'line' ] = { #ifdef USE_DASH uniform float dashSize; + uniform float dashOffset; uniform float gapSize; #endif @@ -640,19 +640,19 @@ THREE.ShaderLib[ 'line' ] = { #ifdef USE_DASH - if ( vUv.y < 0.5 || vUv.y > 0.5 ) discard; // discard endcaps + if ( vUv.y < - 1.0 || vUv.y > 1.0 ) discard; // discard endcaps - if ( mod( vLineDistance, dashSize + gapSize ) > dashSize ) discard; // todo - FIX + if ( mod( vLineDistance + dashOffset, dashSize + gapSize ) > dashSize ) discard; // todo - FIX #endif - if ( vUv.y < 0.5 || vUv.y > 0.5 ) { + if ( abs( vUv.y ) > 1.0 ) { - float a = vUv.x - 0.5; - float b = vUv.y - 0.5; + float a = vUv.x; + float b = ( vUv.y > 0.0 ) ? vUv.y - 1.0 : vUv.y + 1.0; float len2 = a * a + b * b; - if ( len2 > 0.25 ) discard; + if ( len2 > 1.0 ) discard; } @@ -661,36 +661,35 @@ THREE.ShaderLib[ 'line' ] = { #include #include - gl_FragColor = vec4( diffuseColor.rgb, opacity ); + gl_FragColor = vec4( diffuseColor.rgb, diffuseColor.a ); - #include #include #include #include + #include } ` }; -THREE.LineMaterial = function ( parameters ) { +THREE.LineMaterial = function (parameters) { - var lineUniforms = THREE.UniformsUtils.clone( THREE.ShaderLib[ 'line' ].uniforms ); - lineUniforms.opacity.value = parameters.opacity; - - THREE.ShaderMaterial.call( this, { + THREE.ShaderMaterial.call(this, { type: 'LineMaterial', - uniforms: lineUniforms, + uniforms: THREE.UniformsUtils.clone(THREE.ShaderLib['line'].uniforms), - vertexShader: THREE.ShaderLib[ 'line' ].vertexShader, - fragmentShader: THREE.ShaderLib[ 'line' ].fragmentShader + vertexShader: THREE.ShaderLib['line'].vertexShader, + fragmentShader: THREE.ShaderLib['line'].fragmentShader, - } ); + clipping: true // required for clipping support + + }); this.dashed = false; - Object.defineProperties( this, { + Object.defineProperties(this, { color: { @@ -702,7 +701,7 @@ THREE.LineMaterial = function ( parameters ) { }, - set: function ( value ) { + set: function (value) { this.uniforms.diffuse.value = value; @@ -720,7 +719,7 @@ THREE.LineMaterial = function ( parameters ) { }, - set: function ( value ) { + set: function (value) { this.uniforms.linewidth.value = value; @@ -738,7 +737,7 @@ THREE.LineMaterial = function ( parameters ) { }, - set: function ( value ) { + set: function (value) { this.uniforms.dashScale.value = value; @@ -756,7 +755,7 @@ THREE.LineMaterial = function ( parameters ) { }, - set: function ( value ) { + set: function (value) { this.uniforms.dashSize.value = value; @@ -764,6 +763,24 @@ THREE.LineMaterial = function ( parameters ) { }, + dashOffset: { + + enumerable: true, + + get: function () { + + return this.uniforms.dashOffset.value; + + }, + + set: function (value) { + + this.uniforms.dashOffset.value = value; + + } + + }, + gapSize: { enumerable: true, @@ -774,7 +791,7 @@ THREE.LineMaterial = function ( parameters ) { }, - set: function ( value ) { + set: function (value) { this.uniforms.gapSize.value = value; @@ -782,74 +799,76 @@ THREE.LineMaterial = function ( parameters ) { }, - resolution: { + opacity: { enumerable: true, get: function () { - return this.uniforms.resolution.value; + return this.uniforms.opacity.value; }, - set: function ( value ) { + set: function (value) { - this.uniforms.resolution.value.copy( value ); + this.uniforms.opacity.value = value; } - } - - } ); + }, - this.setValues( parameters ); + resolution: { -}; + enumerable: true, -THREE.LineMaterial.prototype = Object.create( THREE.ShaderMaterial.prototype ); -THREE.LineMaterial.prototype.constructor = THREE.LineMaterial; + get: function () { -THREE.LineMaterial.prototype.isLineMaterial = true; + return this.uniforms.resolution.value; -THREE.LineMaterial.prototype.copy = function ( source ) { + }, - THREE.ShaderMaterial.prototype.copy.call( this, source ); + set: function (value) { - this.color.copy( source.color ); + this.uniforms.resolution.value.copy(value); - this.linewidth = source.linewidth; + } - this.resolution = source.resolution; + } - // todo + }); - return this; + this.setValues(parameters); }; +THREE.LineMaterial.prototype = Object.create(THREE.ShaderMaterial.prototype); +THREE.LineMaterial.prototype.constructor = THREE.LineMaterial; + +THREE.LineMaterial.prototype.isLineMaterial = true; + /** * @author WestLangley / http://github.com/WestLangley * */ -THREE.LineSegments2 = function ( geometry, material ) { +THREE.LineSegments2 = function (geometry, material) { - THREE.Mesh.call( this ); + if (geometry === undefined) geometry = new THREE.LineSegmentsGeometry(); + if (material === undefined) material = new THREE.LineMaterial({ color: Math.random() * 0xffffff }); - this.type = 'LineSegments2'; + THREE.Mesh.call(this, geometry, material); - this.geometry = geometry !== undefined ? geometry : new THREE.LineSegmentsGeometry(); - this.material = material !== undefined ? material : new THREE.LineMaterial( { color: Math.random() * 0xffffff } ); + this.type = 'LineSegments2'; }; -THREE.LineSegments2.prototype = Object.assign( Object.create( THREE.Mesh.prototype ), { +THREE.LineSegments2.prototype = Object.assign(Object.create(THREE.Mesh.prototype), { constructor: THREE.LineSegments2, isLineSegments2: true, - computeLineDistances: ( function () { // for backwards-compatability, but could be a method of LineSegmentsGeometry... + computeLineDistances: (function () { // for backwards-compatability, but could be a method of LineSegmentsGeometry... var start = new THREE.Vector3(); var end = new THREE.Vector3(); @@ -860,94 +879,237 @@ THREE.LineSegments2.prototype = Object.assign( Object.create( THREE.Mesh.prototy var instanceStart = geometry.attributes.instanceStart; var instanceEnd = geometry.attributes.instanceEnd; - var lineDistances = new Float32Array( 2 * instanceStart.data.count ); + var lineDistances = new Float32Array(2 * instanceStart.data.count); - for ( var i = 0, j = 0, l = instanceStart.data.count; i < l; i ++, j += 2 ) { + for (var i = 0, j = 0, l = instanceStart.data.count; i < l; i++, j += 2) { - start.fromBufferAttribute( instanceStart, i ); - end.fromBufferAttribute( instanceEnd, i ); + start.fromBufferAttribute(instanceStart, i); + end.fromBufferAttribute(instanceEnd, i); - lineDistances[ j ] = ( j === 0 ) ? 0 : lineDistances[ j - 1 ]; - lineDistances[ j + 1 ] = lineDistances[ j ] + start.distanceTo( end ); + 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 + var instanceDistanceBuffer = new THREE.InstancedInterleavedBuffer(lineDistances, 2, 1); // d0, d1 - geometry.setAttribute( 'instanceDistanceStart', new THREE.InterleavedBufferAttribute( instanceDistanceBuffer, 1, 0 ) ); // d0 - geometry.setAttribute( 'instanceDistanceEnd', new THREE.InterleavedBufferAttribute( instanceDistanceBuffer, 1, 1 ) ); // d1 + geometry.setAttribute('instanceDistanceStart', new THREE.InterleavedBufferAttribute(instanceDistanceBuffer, 1, 0)); // d0 + geometry.setAttribute('instanceDistanceEnd', new THREE.InterleavedBufferAttribute(instanceDistanceBuffer, 1, 1)); // d1 return this; }; - }() ), + }()), - copy: function ( source ) { + raycast: (function () { - // todo + var start = new THREE.Vector4(); + var end = new THREE.Vector4(); - return this; + 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('LineSegments2: "Raycaster.camera" needs to be set in order to raycast against LineSegments2.'); + + } + + var threshold = (raycaster.params.Line2 !== undefined) ? raycaster.params.Line2.threshold || 0 : 0; + + 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 + threshold; + + var instanceStart = geometry.attributes.instanceStart; + var instanceEnd = geometry.attributes.instanceEnd; + + // camera forward is negative + var near = - camera.near; + + // 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); + 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++) { + + start.fromBufferAttribute(instanceStart, i); + end.fromBufferAttribute(instanceEnd, i); + + start.w = 1; + end.w = 1; + + // camera space + start.applyMatrix4(mvMatrix); + end.applyMatrix4(mvMatrix); + + // skip the segment if it's entirely behind the camera + var isBehindCameraNear = start.z > near && end.z > near; + if (isBehindCameraNear) { + + continue; + + } + + // trim the segment if it extends behind camera near + if (start.z > near) { + + const deltaDist = start.z - end.z; + const t = (start.z - near) / deltaDist; + start.lerp(end, t); + + } else if (end.z > near) { + + const deltaDist = end.z - start.z; + const t = (end.z - near) / deltaDist; + end.lerp(start, t); + + } + + // clip space + start.applyMatrix4(projectionMatrix); + end.applyMatrix4(projectionMatrix); + + // ndc space [ - 1.0, 1.0 ] + 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(ssOrigin3, true); + line.at(param, closestPoint); + + // check if the intersection point is within clip space + var zPos = THREE.MathUtils.lerp(start.z, end.z, param); + var isInClipSpace = zPos >= - 1 && zPos <= 1; + + var isInside = ssOrigin3.distanceTo(closestPoint) < lineWidth * 0.5; + + if (isInClipSpace && isInside) { + + line.start.fromBufferAttribute(instanceStart, i); + line.end.fromBufferAttribute(instanceEnd, i); + + line.start.applyMatrix4(matrixWorld); + line.end.applyMatrix4(matrixWorld); + + var pointOnLine = new THREE.Vector3(); + var point = new THREE.Vector3(); + + ray.distanceSqToSegment(line.start, line.end, point, pointOnLine); + + intersects.push({ + + point: point, + pointOnLine: pointOnLine, + distance: ray.origin.distanceTo(point), + + object: this, + face: null, + faceIndex: i, + uv: null, + uv2: null, + + }); + + } + + } + + }; + + }()) + +}); /** * @author WestLangley / http://github.com/WestLangley * */ -THREE.Line2 = function ( geometry, material ) { +THREE.Line2 = function (geometry, material) { - THREE.LineSegments2.call( this ); + if (geometry === undefined) geometry = new THREE.LineGeometry(); + if (material === undefined) material = new THREE.LineMaterial({ color: Math.random() * 0xffffff }); - this.type = 'Line2'; + THREE.LineSegments2.call(this, geometry, material); - this.geometry = geometry !== undefined ? geometry : new THREE.LineGeometry(); - this.material = material !== undefined ? material : new THREE.LineMaterial( { color: Math.random() * 0xffffff } ); + this.type = 'Line2'; }; -THREE.Line2.prototype = Object.assign( Object.create( THREE.LineSegments2.prototype ), { +THREE.Line2.prototype = Object.assign(Object.create(THREE.LineSegments2.prototype), { constructor: THREE.Line2, - isLine2: true, - - copy: function ( source ) { - - // todo - - return this; - - } + isLine2: true -} ); +}); /** * @author WestLangley / http://github.com/WestLangley * */ -THREE.Wireframe = function ( geometry, material ) { +THREE.Wireframe = function (geometry, material) { - THREE.Mesh.call( this ); + THREE.Mesh.call(this); this.type = 'Wireframe'; this.geometry = geometry !== undefined ? geometry : new THREE.LineSegmentsGeometry(); - this.material = material !== undefined ? material : new THREE.LineMaterial( { color: Math.random() * 0xffffff } ); + this.material = material !== undefined ? material : new THREE.LineMaterial({ color: Math.random() * 0xffffff }); }; -THREE.Wireframe.prototype = Object.assign( Object.create( THREE.Mesh.prototype ), { +THREE.Wireframe.prototype = Object.assign(Object.create(THREE.Mesh.prototype), { constructor: THREE.Wireframe, isWireframe: true, - computeLineDistances: ( function () { // for backwards-compatability, but could be a method of LineSegmentsGeometry... + computeLineDistances: (function () { // for backwards-compatability, but could be a method of LineSegmentsGeometry... var start = new THREE.Vector3(); var end = new THREE.Vector3(); @@ -958,35 +1120,27 @@ THREE.Wireframe.prototype = Object.assign( Object.create( THREE.Mesh.prototype ) var instanceStart = geometry.attributes.instanceStart; var instanceEnd = geometry.attributes.instanceEnd; - var lineDistances = new Float32Array( 2 * instanceStart.data.count ); + var lineDistances = new Float32Array(2 * instanceStart.data.count); - for ( var i = 0, j = 0, l = instanceStart.data.count; i < l; i ++, j += 2 ) { + for (var i = 0, j = 0, l = instanceStart.data.count; i < l; i++, j += 2) { - start.fromBufferAttribute( instanceStart, i ); - end.fromBufferAttribute( instanceEnd, i ); + start.fromBufferAttribute(instanceStart, i); + end.fromBufferAttribute(instanceEnd, i); - lineDistances[ j ] = ( j === 0 ) ? 0 : lineDistances[ j - 1 ]; - lineDistances[ j + 1 ] = lineDistances[ j ] + start.distanceTo( end ); + 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 + var instanceDistanceBuffer = new THREE.InstancedInterleavedBuffer(lineDistances, 2, 1); // d0, d1 - geometry.setAttribute( 'instanceDistanceStart', new THREE.InterleavedBufferAttribute( instanceDistanceBuffer, 1, 0 ) ); // d0 - geometry.setAttribute( 'instanceDistanceEnd', new THREE.InterleavedBufferAttribute( instanceDistanceBuffer, 1, 1 ) ); // d1 + geometry.setAttribute('instanceDistanceStart', new THREE.InterleavedBufferAttribute(instanceDistanceBuffer, 1, 0)); // d0 + geometry.setAttribute('instanceDistanceEnd', new THREE.InterleavedBufferAttribute(instanceDistanceBuffer, 1, 1)); // d1 return this; }; - }() ), - - copy: function ( source ) { - - // todo - - return this; - - } + }()) -} ); +}); diff --git a/tests/threebox-tests-bundle.js b/tests/threebox-tests-bundle.js index 0b80f86f..9101d592 100644 --- a/tests/threebox-tests-bundle.js +++ b/tests/threebox-tests-bundle.js @@ -13679,8 +13679,6 @@ function line(obj){ module.exports = exports = line; - - /** * custom line shader by WestLangley, sourced from https://github.com/mrdoob/three.js/tree/master/examples/js/lines * @@ -13688,50 +13686,48 @@ module.exports = exports = line; THREE.LineSegmentsGeometry = function () { - THREE.InstancedBufferGeometry.call( this ); + THREE.InstancedBufferGeometry.call(this); this.type = 'LineSegmentsGeometry'; - var plane = new THREE.BufferGeometry(); - - var positions = [ - 1, 2, 0, 1, 2, 0, - 1, 1, 0, 1, 1, 0, - 1, 0, 0, 1, 0, 0, - 1, - 1, 0, 1, - 1, 0 ]; - var uvs = [ 0, 1, 1, 1, 0, .5, 1, .5, 0, .5, 1, .5, 0, 0, 1, 0 ]; - var index = [ 0, 2, 1, 2, 3, 1, 2, 4, 3, 4, 5, 3, 4, 6, 5, 6, 7, 5 ]; + var positions = [- 1, 2, 0, 1, 2, 0, - 1, 1, 0, 1, 1, 0, - 1, 0, 0, 1, 0, 0, - 1, - 1, 0, 1, - 1, 0]; + var uvs = [- 1, 2, 1, 2, - 1, 1, 1, 1, - 1, - 1, 1, - 1, - 1, - 2, 1, - 2]; + var index = [0, 2, 1, 2, 3, 1, 2, 4, 3, 4, 5, 3, 4, 6, 5, 6, 7, 5]; - this.setIndex( index ); - this.setAttribute( 'position', new THREE.Float32BufferAttribute( positions, 3 ) ); - this.setAttribute( 'uv', new THREE.Float32BufferAttribute( uvs, 2 ) ); + this.setIndex(index); + this.setAttribute('position', new THREE.Float32BufferAttribute(positions, 3)); + this.setAttribute('uv', new THREE.Float32BufferAttribute(uvs, 2)); }; -THREE.LineSegmentsGeometry.prototype = Object.assign( Object.create( THREE.InstancedBufferGeometry.prototype ), { +THREE.LineSegmentsGeometry.prototype = Object.assign(Object.create(THREE.InstancedBufferGeometry.prototype), { constructor: THREE.LineSegmentsGeometry, isLineSegmentsGeometry: true, - applyMatrix: function ( matrix ) { + applyMatrix4: function (matrix) { var start = this.attributes.instanceStart; var end = this.attributes.instanceEnd; - if ( start !== undefined ) { + if (start !== undefined) { - matrix.applyToBufferAttribute( start ); + start.applyMatrix4(matrix); - matrix.applyToBufferAttribute( end ); + end.applyMatrix4(matrix); - start.data.needsUpdate = true; + start.needsUpdate = true; } - if ( this.boundingBox !== null ) { + if (this.boundingBox !== null) { this.computeBoundingBox(); } - if ( this.boundingSphere !== null ) { + if (this.boundingSphere !== null) { this.computeBoundingSphere(); @@ -13741,24 +13737,24 @@ THREE.LineSegmentsGeometry.prototype = Object.assign( Object.create( THREE.Insta }, - setPositions: function ( array ) { + setPositions: function (array) { var lineSegments; - if ( array instanceof Float32Array ) { + if (array instanceof Float32Array) { lineSegments = array; - } else if ( Array.isArray( array ) ) { + } else if (Array.isArray(array)) { - lineSegments = new Float32Array( array ); + lineSegments = new Float32Array(array); } - var instanceBuffer = new THREE.InstancedInterleavedBuffer( lineSegments, 6, 1 ); // xyz, xyz + var instanceBuffer = new THREE.InstancedInterleavedBuffer(lineSegments, 6, 1); // xyz, xyz - this.setAttribute( 'instanceStart', new THREE.InterleavedBufferAttribute( instanceBuffer, 3, 0 ) ); // xyz - this.setAttribute( 'instanceEnd', new THREE.InterleavedBufferAttribute( instanceBuffer, 3, 3 ) ); // xyz + this.setAttribute('instanceStart', new THREE.InterleavedBufferAttribute(instanceBuffer, 3, 0)); // xyz + this.setAttribute('instanceEnd', new THREE.InterleavedBufferAttribute(instanceBuffer, 3, 3)); // xyz // @@ -13769,48 +13765,48 @@ THREE.LineSegmentsGeometry.prototype = Object.assign( Object.create( THREE.Insta }, - setColors: function ( array ) { + setColors: function (array) { var colors; - if ( array instanceof Float32Array ) { + if (array instanceof Float32Array) { colors = array; - } else if ( Array.isArray( array ) ) { + } else if (Array.isArray(array)) { - colors = new Float32Array( array ); + colors = new Float32Array(array); } - var instanceColorBuffer = new THREE.InstancedInterleavedBuffer( colors, 6, 1 ); // rgb, rgb + var instanceColorBuffer = new THREE.InstancedInterleavedBuffer(colors, 6, 1); // rgb, rgb - this.setAttribute( 'instanceColorStart', new THREE.InterleavedBufferAttribute( instanceColorBuffer, 3, 0 ) ); // rgb - this.setAttribute( 'instanceColorEnd', new THREE.InterleavedBufferAttribute( instanceColorBuffer, 3, 3 ) ); // rgb + this.setAttribute('instanceColorStart', new THREE.InterleavedBufferAttribute(instanceColorBuffer, 3, 0)); // rgb + this.setAttribute('instanceColorEnd', new THREE.InterleavedBufferAttribute(instanceColorBuffer, 3, 3)); // rgb return this; }, - fromWireframeGeometry: function ( geometry ) { + fromWireframeGeometry: function (geometry) { - this.setPositions( geometry.attributes.position.array ); + this.setPositions(geometry.attributes.position.array); return this; }, - fromEdgesGeometry: function ( geometry ) { + fromEdgesGeometry: function (geometry) { - this.setPositions( geometry.attributes.position.array ); + this.setPositions(geometry.attributes.position.array); return this; }, - fromMesh: function ( mesh ) { + fromMesh: function (mesh) { - this.fromWireframeGeometry( new THREE.WireframeGeometry( mesh.geometry ) ); + this.fromWireframeGeometry(new THREE.WireframeGeometry(mesh.geometry)); // set colors, maybe @@ -13818,17 +13814,18 @@ THREE.LineSegmentsGeometry.prototype = Object.assign( Object.create( THREE.Insta }, - fromLineSegements: function ( lineSegments ) { + fromLineSegments: function (lineSegments) { var geometry = lineSegments.geometry; - if ( geometry.isGeometry ) { + if (geometry.isGeometry) { - this.setPositions( geometry.vertices ); + console.error('THREE.LineSegmentsGeometry no longer supports THREE.Geometry. Use THREE.BufferGeometry instead.'); + return; - } else if ( geometry.isBufferGeometry ) { + } else if (geometry.isBufferGeometry) { - this.setPositions( geometry.position.array ); // assumes non-indexed + this.setPositions(geometry.attributes.position.array); // assumes non-indexed } @@ -13844,7 +13841,7 @@ THREE.LineSegmentsGeometry.prototype = Object.assign( Object.create( THREE.Insta return function computeBoundingBox() { - if ( this.boundingBox === null ) { + if (this.boundingBox === null) { this.boundingBox = new THREE.Box3(); @@ -13853,13 +13850,13 @@ THREE.LineSegmentsGeometry.prototype = Object.assign( Object.create( THREE.Insta var start = this.attributes.instanceStart; var end = this.attributes.instanceEnd; - if ( start !== undefined && end !== undefined ) { + if (start !== undefined && end !== undefined) { - this.boundingBox.setFromBufferAttribute( start ); + this.boundingBox.setFromBufferAttribute(start); - box.setFromBufferAttribute( end ); + box.setFromBufferAttribute(end); - this.boundingBox.union( box ); + this.boundingBox.union(box); } @@ -13873,13 +13870,13 @@ THREE.LineSegmentsGeometry.prototype = Object.assign( Object.create( THREE.Insta return function computeBoundingSphere() { - if ( this.boundingSphere === null ) { + if (this.boundingSphere === null) { this.boundingSphere = new THREE.Sphere(); } - if ( this.boundingBox === null ) { + if (this.boundingBox === null) { this.computeBoundingBox(); @@ -13888,29 +13885,29 @@ THREE.LineSegmentsGeometry.prototype = Object.assign( Object.create( THREE.Insta var start = this.attributes.instanceStart; var end = this.attributes.instanceEnd; - if ( start !== undefined && end !== undefined ) { + if (start !== undefined && end !== undefined) { var center = this.boundingSphere.center; - this.boundingBox.getCenter( center ); + this.boundingBox.getCenter(center); var maxRadiusSq = 0; - for ( var i = 0, il = start.count; i < il; i ++ ) { + for (var i = 0, il = start.count; i < il; i++) { - vector.fromBufferAttribute( start, i ); - maxRadiusSq = Math.max( maxRadiusSq, center.distanceToSquared( vector ) ); + vector.fromBufferAttribute(start, i); + maxRadiusSq = Math.max(maxRadiusSq, center.distanceToSquared(vector)); - vector.fromBufferAttribute( end, i ); - maxRadiusSq = Math.max( maxRadiusSq, center.distanceToSquared( vector ) ); + vector.fromBufferAttribute(end, i); + maxRadiusSq = Math.max(maxRadiusSq, center.distanceToSquared(vector)); } - this.boundingSphere.radius = Math.sqrt( maxRadiusSq ); + this.boundingSphere.radius = Math.sqrt(maxRadiusSq); - if ( isNaN( this.boundingSphere.radius ) ) { + if (isNaN(this.boundingSphere.radius)) { - console.error( 'THREE.LineSegmentsGeometry.computeBoundingSphere(): Computed radius is NaN. The instanced position data is likely to have NaN values.', this ); + console.error('THREE.LineSegmentsGeometry.computeBoundingSphere(): Computed radius is NaN. The instanced position data is likely to have NaN values.', this); } @@ -13926,21 +13923,15 @@ THREE.LineSegmentsGeometry.prototype = Object.assign( Object.create( THREE.Insta }, - clone: function () { + applyMatrix: function (matrix) { - // todo + console.warn('THREE.LineSegmentsGeometry: applyMatrix() has been renamed to applyMatrix4().'); - }, - - copy: function ( source ) { - - // todo - - return this; + return this.applyMatrix4(matrix); } -} ); +}); /** * @author WestLangley / http://github.com/WestLangley @@ -13949,79 +13940,80 @@ THREE.LineSegmentsGeometry.prototype = Object.assign( Object.create( THREE.Insta THREE.LineGeometry = function () { - THREE.LineSegmentsGeometry.call( this ); + THREE.LineSegmentsGeometry.call(this); this.type = 'LineGeometry'; }; -THREE.LineGeometry.prototype = Object.assign( Object.create( THREE.LineSegmentsGeometry.prototype ), { +THREE.LineGeometry.prototype = Object.assign(Object.create(THREE.LineSegmentsGeometry.prototype), { constructor: THREE.LineGeometry, isLineGeometry: true, - setPositions: function ( array ) { + setPositions: function (array) { // converts [ x1, y1, z1, x2, y2, z2, ... ] to pairs format var length = array.length - 3; - var points = new Float32Array( 2 * length ); + var points = new Float32Array(2 * length); - for ( var i = 0; i < length; i += 3 ) { + for (var i = 0; i < length; i += 3) { - points[ 2 * i ] = array[ i ]; - points[ 2 * i + 1 ] = array[ i + 1 ]; - points[ 2 * i + 2 ] = array[ i + 2 ]; + points[2 * i] = array[i]; + points[2 * i + 1] = array[i + 1]; + points[2 * i + 2] = array[i + 2]; - points[ 2 * i + 3 ] = array[ i + 3 ]; - points[ 2 * i + 4 ] = array[ i + 4 ]; - points[ 2 * i + 5 ] = array[ i + 5 ]; + points[2 * i + 3] = array[i + 3]; + points[2 * i + 4] = array[i + 4]; + points[2 * i + 5] = array[i + 5]; } - THREE.LineSegmentsGeometry.prototype.setPositions.call( this, points ); + THREE.LineSegmentsGeometry.prototype.setPositions.call(this, points); return this; }, - setColors: function ( array ) { + setColors: function (array) { // converts [ r1, g1, b1, r2, g2, b2, ... ] to pairs format var length = array.length - 3; - var colors = new Float32Array( 2 * length ); + var colors = new Float32Array(2 * length); - for ( var i = 0; i < length; i += 3 ) { + for (var i = 0; i < length; i += 3) { - colors[ 2 * i ] = array[ i ]; - colors[ 2 * i + 1 ] = array[ i + 1 ]; - colors[ 2 * i + 2 ] = array[ i + 2 ]; + colors[2 * i] = array[i]; + colors[2 * i + 1] = array[i + 1]; + colors[2 * i + 2] = array[i + 2]; - colors[ 2 * i + 3 ] = array[ i + 3 ]; - colors[ 2 * i + 4 ] = array[ i + 4 ]; - colors[ 2 * i + 5 ] = array[ i + 5 ]; + colors[2 * i + 3] = array[i + 3]; + colors[2 * i + 4] = array[i + 4]; + colors[2 * i + 5] = array[i + 5]; } - THREE.LineSegmentsGeometry.prototype.setColors.call( this, colors ); + THREE.LineSegmentsGeometry.prototype.setColors.call(this, colors); return this; }, - fromLine: function ( line ) { + fromLine: function (line) { var geometry = line.geometry; - if ( geometry.isGeometry ) { + if (geometry.isGeometry) { - this.setPositions( geometry.vertices ); + console.error('THREE.LineGeometry no longer supports THREE.Geometry. Use THREE.BufferGeometry instead.'); + return; - } else if ( geometry.isBufferGeometry ) { + } else if (geometry.isBufferGeometry) { - this.setPositions( geometry.position.array ); // assumes non-indexed + this.setPositions(geometry.attributes.position.array); // assumes non-indexed } @@ -14031,7 +14023,7 @@ THREE.LineGeometry.prototype = Object.assign( Object.create( THREE.LineSegmentsG }, - copy: function ( source ) { + copy: function ( /* source */) { // todo @@ -14039,40 +14031,32 @@ THREE.LineGeometry.prototype = Object.assign( Object.create( THREE.LineSegmentsG } -} ); +}); /** * @author WestLangley / http://github.com/WestLangley * */ -THREE.WireframeGeometry2 = function ( geometry ) { +THREE.WireframeGeometry2 = function (geometry) { - THREE.LineSegmentsGeometry.call( this ); + THREE.LineSegmentsGeometry.call(this); this.type = 'WireframeGeometry2'; - this.fromWireframeGeometry( new THREE.WireframeGeometry( geometry ) ); + this.fromWireframeGeometry(new THREE.WireframeGeometry(geometry)); // set colors, maybe }; -THREE.WireframeGeometry2.prototype = Object.assign( Object.create( THREE.LineSegmentsGeometry.prototype ), { +THREE.WireframeGeometry2.prototype = Object.assign(Object.create(THREE.LineSegmentsGeometry.prototype), { constructor: THREE.WireframeGeometry2, - isWireframeGeometry2: true, - - copy: function ( source ) { - - // todo - - return this; - - } + isWireframeGeometry2: true -} ); +}); /** * @author WestLangley / http://github.com/WestLangley @@ -14088,23 +14072,38 @@ THREE.WireframeGeometry2.prototype = Object.assign( Object.create( THREE.LineSeg * } */ +/** + * parameters = { + * color: , + * linewidth: , + * dashed: , + * dashScale: , + * dashSize: , + * dashOffset: , + * gapSize: , + * resolution: , // to be set by renderer + * } + */ + THREE.UniformsLib.line = { linewidth: { value: 1 }, - resolution: { value: new THREE.Vector2( 1, 1 ) }, + resolution: { value: new THREE.Vector2(1, 1) }, dashScale: { value: 1 }, dashSize: { value: 1 }, - gapSize: { value: 1 } // todo FIX - maybe change to totalSize + dashOffset: { value: 0 }, + gapSize: { value: 1 }, // todo FIX - maybe change to totalSize + opacity: { value: 1 } }; -THREE.ShaderLib[ 'line' ] = { +THREE.ShaderLib['line'] = { - uniforms: THREE.UniformsUtils.merge( [ + uniforms: THREE.UniformsUtils.merge([ THREE.UniformsLib.common, THREE.UniformsLib.fog, THREE.UniformsLib.line - ] ), + ]), vertexShader: ` @@ -14244,9 +14243,9 @@ THREE.ShaderLib[ 'line' ] = { gl_Position = clip; - #include + vec4 mvPosition = ( position.y < 0.5 ) ? start : end; // this is an approximation - #include + #include #include #include @@ -14261,6 +14260,7 @@ THREE.ShaderLib[ 'line' ] = { #ifdef USE_DASH uniform float dashSize; + uniform float dashOffset; uniform float gapSize; #endif @@ -14281,19 +14281,19 @@ THREE.ShaderLib[ 'line' ] = { #ifdef USE_DASH - if ( vUv.y < 0.5 || vUv.y > 0.5 ) discard; // discard endcaps + if ( vUv.y < - 1.0 || vUv.y > 1.0 ) discard; // discard endcaps - if ( mod( vLineDistance, dashSize + gapSize ) > dashSize ) discard; // todo - FIX + if ( mod( vLineDistance + dashOffset, dashSize + gapSize ) > dashSize ) discard; // todo - FIX #endif - if ( vUv.y < 0.5 || vUv.y > 0.5 ) { + if ( abs( vUv.y ) > 1.0 ) { - float a = vUv.x - 0.5; - float b = vUv.y - 0.5; + float a = vUv.x; + float b = ( vUv.y > 0.0 ) ? vUv.y - 1.0 : vUv.y + 1.0; float len2 = a * a + b * b; - if ( len2 > 0.25 ) discard; + if ( len2 > 1.0 ) discard; } @@ -14302,36 +14302,35 @@ THREE.ShaderLib[ 'line' ] = { #include #include - gl_FragColor = vec4( diffuseColor.rgb, opacity ); + gl_FragColor = vec4( diffuseColor.rgb, diffuseColor.a ); - #include #include #include #include + #include } ` }; -THREE.LineMaterial = function ( parameters ) { - - var lineUniforms = THREE.UniformsUtils.clone( THREE.ShaderLib[ 'line' ].uniforms ); - lineUniforms.opacity.value = parameters.opacity; +THREE.LineMaterial = function (parameters) { - THREE.ShaderMaterial.call( this, { + THREE.ShaderMaterial.call(this, { type: 'LineMaterial', - uniforms: lineUniforms, + uniforms: THREE.UniformsUtils.clone(THREE.ShaderLib['line'].uniforms), - vertexShader: THREE.ShaderLib[ 'line' ].vertexShader, - fragmentShader: THREE.ShaderLib[ 'line' ].fragmentShader + vertexShader: THREE.ShaderLib['line'].vertexShader, + fragmentShader: THREE.ShaderLib['line'].fragmentShader, - } ); + clipping: true // required for clipping support + + }); this.dashed = false; - Object.defineProperties( this, { + Object.defineProperties(this, { color: { @@ -14343,7 +14342,7 @@ THREE.LineMaterial = function ( parameters ) { }, - set: function ( value ) { + set: function (value) { this.uniforms.diffuse.value = value; @@ -14361,7 +14360,7 @@ THREE.LineMaterial = function ( parameters ) { }, - set: function ( value ) { + set: function (value) { this.uniforms.linewidth.value = value; @@ -14379,7 +14378,7 @@ THREE.LineMaterial = function ( parameters ) { }, - set: function ( value ) { + set: function (value) { this.uniforms.dashScale.value = value; @@ -14397,7 +14396,7 @@ THREE.LineMaterial = function ( parameters ) { }, - set: function ( value ) { + set: function (value) { this.uniforms.dashSize.value = value; @@ -14405,6 +14404,24 @@ THREE.LineMaterial = function ( parameters ) { }, + dashOffset: { + + enumerable: true, + + get: function () { + + return this.uniforms.dashOffset.value; + + }, + + set: function (value) { + + this.uniforms.dashOffset.value = value; + + } + + }, + gapSize: { enumerable: true, @@ -14415,7 +14432,7 @@ THREE.LineMaterial = function ( parameters ) { }, - set: function ( value ) { + set: function (value) { this.uniforms.gapSize.value = value; @@ -14423,74 +14440,76 @@ THREE.LineMaterial = function ( parameters ) { }, - resolution: { + opacity: { enumerable: true, get: function () { - return this.uniforms.resolution.value; + return this.uniforms.opacity.value; }, - set: function ( value ) { + set: function (value) { - this.uniforms.resolution.value.copy( value ); + this.uniforms.opacity.value = value; } - } - - } ); + }, - this.setValues( parameters ); + resolution: { -}; + enumerable: true, -THREE.LineMaterial.prototype = Object.create( THREE.ShaderMaterial.prototype ); -THREE.LineMaterial.prototype.constructor = THREE.LineMaterial; + get: function () { -THREE.LineMaterial.prototype.isLineMaterial = true; + return this.uniforms.resolution.value; -THREE.LineMaterial.prototype.copy = function ( source ) { + }, - THREE.ShaderMaterial.prototype.copy.call( this, source ); + set: function (value) { - this.color.copy( source.color ); + this.uniforms.resolution.value.copy(value); - this.linewidth = source.linewidth; + } - this.resolution = source.resolution; + } - // todo + }); - return this; + this.setValues(parameters); }; +THREE.LineMaterial.prototype = Object.create(THREE.ShaderMaterial.prototype); +THREE.LineMaterial.prototype.constructor = THREE.LineMaterial; + +THREE.LineMaterial.prototype.isLineMaterial = true; + /** * @author WestLangley / http://github.com/WestLangley * */ -THREE.LineSegments2 = function ( geometry, material ) { +THREE.LineSegments2 = function (geometry, material) { - THREE.Mesh.call( this ); + if (geometry === undefined) geometry = new THREE.LineSegmentsGeometry(); + if (material === undefined) material = new THREE.LineMaterial({ color: Math.random() * 0xffffff }); - this.type = 'LineSegments2'; + THREE.Mesh.call(this, geometry, material); - this.geometry = geometry !== undefined ? geometry : new THREE.LineSegmentsGeometry(); - this.material = material !== undefined ? material : new THREE.LineMaterial( { color: Math.random() * 0xffffff } ); + this.type = 'LineSegments2'; }; -THREE.LineSegments2.prototype = Object.assign( Object.create( THREE.Mesh.prototype ), { +THREE.LineSegments2.prototype = Object.assign(Object.create(THREE.Mesh.prototype), { constructor: THREE.LineSegments2, isLineSegments2: true, - computeLineDistances: ( function () { // for backwards-compatability, but could be a method of LineSegmentsGeometry... + computeLineDistances: (function () { // for backwards-compatability, but could be a method of LineSegmentsGeometry... var start = new THREE.Vector3(); var end = new THREE.Vector3(); @@ -14501,94 +14520,237 @@ THREE.LineSegments2.prototype = Object.assign( Object.create( THREE.Mesh.prototy var instanceStart = geometry.attributes.instanceStart; var instanceEnd = geometry.attributes.instanceEnd; - var lineDistances = new Float32Array( 2 * instanceStart.data.count ); + var lineDistances = new Float32Array(2 * instanceStart.data.count); - for ( var i = 0, j = 0, l = instanceStart.data.count; i < l; i ++, j += 2 ) { + for (var i = 0, j = 0, l = instanceStart.data.count; i < l; i++, j += 2) { - start.fromBufferAttribute( instanceStart, i ); - end.fromBufferAttribute( instanceEnd, i ); + start.fromBufferAttribute(instanceStart, i); + end.fromBufferAttribute(instanceEnd, i); - lineDistances[ j ] = ( j === 0 ) ? 0 : lineDistances[ j - 1 ]; - lineDistances[ j + 1 ] = lineDistances[ j ] + start.distanceTo( end ); + 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 + var instanceDistanceBuffer = new THREE.InstancedInterleavedBuffer(lineDistances, 2, 1); // d0, d1 - geometry.setAttribute( 'instanceDistanceStart', new THREE.InterleavedBufferAttribute( instanceDistanceBuffer, 1, 0 ) ); // d0 - geometry.setAttribute( 'instanceDistanceEnd', new THREE.InterleavedBufferAttribute( instanceDistanceBuffer, 1, 1 ) ); // d1 + geometry.setAttribute('instanceDistanceStart', new THREE.InterleavedBufferAttribute(instanceDistanceBuffer, 1, 0)); // d0 + geometry.setAttribute('instanceDistanceEnd', new THREE.InterleavedBufferAttribute(instanceDistanceBuffer, 1, 1)); // d1 return this; }; - }() ), + }()), - copy: function ( source ) { + raycast: (function () { - // todo + var start = new THREE.Vector4(); + var end = new THREE.Vector4(); - return this; + 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('LineSegments2: "Raycaster.camera" needs to be set in order to raycast against LineSegments2.'); + + } + + var threshold = (raycaster.params.Line2 !== undefined) ? raycaster.params.Line2.threshold || 0 : 0; + + 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 + threshold; + + var instanceStart = geometry.attributes.instanceStart; + var instanceEnd = geometry.attributes.instanceEnd; + + // camera forward is negative + var near = - camera.near; + + // 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); + 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++) { + + start.fromBufferAttribute(instanceStart, i); + end.fromBufferAttribute(instanceEnd, i); + + start.w = 1; + end.w = 1; + + // camera space + start.applyMatrix4(mvMatrix); + end.applyMatrix4(mvMatrix); + + // skip the segment if it's entirely behind the camera + var isBehindCameraNear = start.z > near && end.z > near; + if (isBehindCameraNear) { + + continue; + + } + + // trim the segment if it extends behind camera near + if (start.z > near) { + + const deltaDist = start.z - end.z; + const t = (start.z - near) / deltaDist; + start.lerp(end, t); + + } else if (end.z > near) { + + const deltaDist = end.z - start.z; + const t = (end.z - near) / deltaDist; + end.lerp(start, t); + + } + + // clip space + start.applyMatrix4(projectionMatrix); + end.applyMatrix4(projectionMatrix); + + // ndc space [ - 1.0, 1.0 ] + 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(ssOrigin3, true); + line.at(param, closestPoint); -} ); + // check if the intersection point is within clip space + var zPos = THREE.MathUtils.lerp(start.z, end.z, param); + var isInClipSpace = zPos >= - 1 && zPos <= 1; + + var isInside = ssOrigin3.distanceTo(closestPoint) < lineWidth * 0.5; + + if (isInClipSpace && isInside) { + + line.start.fromBufferAttribute(instanceStart, i); + line.end.fromBufferAttribute(instanceEnd, i); + + line.start.applyMatrix4(matrixWorld); + line.end.applyMatrix4(matrixWorld); + + var pointOnLine = new THREE.Vector3(); + var point = new THREE.Vector3(); + + ray.distanceSqToSegment(line.start, line.end, point, pointOnLine); + + intersects.push({ + + point: point, + pointOnLine: pointOnLine, + distance: ray.origin.distanceTo(point), + + object: this, + face: null, + faceIndex: i, + uv: null, + uv2: null, + + }); + + } + + } + + }; + + }()) + +}); /** * @author WestLangley / http://github.com/WestLangley * */ -THREE.Line2 = function ( geometry, material ) { +THREE.Line2 = function (geometry, material) { - THREE.LineSegments2.call( this ); + if (geometry === undefined) geometry = new THREE.LineGeometry(); + if (material === undefined) material = new THREE.LineMaterial({ color: Math.random() * 0xffffff }); - this.type = 'Line2'; + THREE.LineSegments2.call(this, geometry, material); - this.geometry = geometry !== undefined ? geometry : new THREE.LineGeometry(); - this.material = material !== undefined ? material : new THREE.LineMaterial( { color: Math.random() * 0xffffff } ); + this.type = 'Line2'; }; -THREE.Line2.prototype = Object.assign( Object.create( THREE.LineSegments2.prototype ), { +THREE.Line2.prototype = Object.assign(Object.create(THREE.LineSegments2.prototype), { constructor: THREE.Line2, - isLine2: true, - - copy: function ( source ) { - - // todo - - return this; - - } + isLine2: true -} ); +}); /** * @author WestLangley / http://github.com/WestLangley * */ -THREE.Wireframe = function ( geometry, material ) { +THREE.Wireframe = function (geometry, material) { - THREE.Mesh.call( this ); + THREE.Mesh.call(this); this.type = 'Wireframe'; this.geometry = geometry !== undefined ? geometry : new THREE.LineSegmentsGeometry(); - this.material = material !== undefined ? material : new THREE.LineMaterial( { color: Math.random() * 0xffffff } ); + this.material = material !== undefined ? material : new THREE.LineMaterial({ color: Math.random() * 0xffffff }); }; -THREE.Wireframe.prototype = Object.assign( Object.create( THREE.Mesh.prototype ), { +THREE.Wireframe.prototype = Object.assign(Object.create(THREE.Mesh.prototype), { constructor: THREE.Wireframe, isWireframe: true, - computeLineDistances: ( function () { // for backwards-compatability, but could be a method of LineSegmentsGeometry... + computeLineDistances: (function () { // for backwards-compatability, but could be a method of LineSegmentsGeometry... var start = new THREE.Vector3(); var end = new THREE.Vector3(); @@ -14599,38 +14761,30 @@ THREE.Wireframe.prototype = Object.assign( Object.create( THREE.Mesh.prototype ) var instanceStart = geometry.attributes.instanceStart; var instanceEnd = geometry.attributes.instanceEnd; - var lineDistances = new Float32Array( 2 * instanceStart.data.count ); + var lineDistances = new Float32Array(2 * instanceStart.data.count); - for ( var i = 0, j = 0, l = instanceStart.data.count; i < l; i ++, j += 2 ) { + for (var i = 0, j = 0, l = instanceStart.data.count; i < l; i++, j += 2) { - start.fromBufferAttribute( instanceStart, i ); - end.fromBufferAttribute( instanceEnd, i ); + start.fromBufferAttribute(instanceStart, i); + end.fromBufferAttribute(instanceEnd, i); - lineDistances[ j ] = ( j === 0 ) ? 0 : lineDistances[ j - 1 ]; - lineDistances[ j + 1 ] = lineDistances[ j ] + start.distanceTo( end ); + 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 + var instanceDistanceBuffer = new THREE.InstancedInterleavedBuffer(lineDistances, 2, 1); // d0, d1 - geometry.setAttribute( 'instanceDistanceStart', new THREE.InterleavedBufferAttribute( instanceDistanceBuffer, 1, 0 ) ); // d0 - geometry.setAttribute( 'instanceDistanceEnd', new THREE.InterleavedBufferAttribute( instanceDistanceBuffer, 1, 1 ) ); // d1 + geometry.setAttribute('instanceDistanceStart', new THREE.InterleavedBufferAttribute(instanceDistanceBuffer, 1, 0)); // d0 + geometry.setAttribute('instanceDistanceEnd', new THREE.InterleavedBufferAttribute(instanceDistanceBuffer, 1, 1)); // d1 return this; }; - }() ), - - copy: function ( source ) { - - // todo - - return this; - - } + }()) -} ); +}); },{"../three.js":116,"../utils/utils.js":120,"./objects.js":112}],106:[function(require,module,exports){ /** @@ -30774,7 +30928,7 @@ var utils = { var geometry = new THREE.Geometry(); - for (var v3 of vertices) { + for (let v3 of vertices) { geometry.vertices.push(v3) } @@ -30793,7 +30947,7 @@ var utils = { //flatten an array of Vector3's into a shallow array of values in x-y-z order, for bufferGeometry flattenVectors(vectors) { var flattenedArray = []; - for (var vertex of vectors) { + for (let vertex of vectors) { flattenedArray.push(vertex.x, vertex.y, vertex.z); } return flattenedArray