three-fatline
Advanced tools
Comparing version 0.5.0 to 0.5.1
@@ -114,3 +114,3 @@ 'use strict'; | ||
romLineSegments(lineSegments) { | ||
fromLineSegments(lineSegments) { | ||
const geometry = lineSegments.geometry; | ||
@@ -200,3 +200,2 @@ | ||
* dashSize: <float>, | ||
* dashOffset: <float>, | ||
* gapSize: <float>, | ||
@@ -215,2 +214,5 @@ * resolution: <Vector2>, // to be set by renderer | ||
THREE$1.UniformsLib.line = { | ||
worldUnits: { | ||
value: 1 | ||
}, | ||
linewidth: { | ||
@@ -220,3 +222,3 @@ value: 1 | ||
resolution: { | ||
value: new three.Vector2(1, 1) | ||
value: new THREE$1.Vector2(1, 1) | ||
}, | ||
@@ -229,16 +231,12 @@ dashScale: { | ||
}, | ||
dashOffset: { | ||
value: 0 | ||
}, | ||
gapSize: { | ||
value: 1 | ||
}, | ||
// todo FIX - maybe change to totalSize | ||
opacity: { | ||
value: 1 | ||
} | ||
} // todo FIX - maybe change to totalSize | ||
}; | ||
THREE$1.ShaderLib['line'] = { | ||
uniforms: THREE$1.UniformsUtils.merge([THREE$1.UniformsLib.common, THREE$1.UniformsLib.fog, THREE$1.UniformsLib.line]), | ||
vertexShader: ` | ||
vertexShader: | ||
/* glsl */ | ||
` | ||
#include <common> | ||
@@ -260,2 +258,5 @@ #include <color_pars_vertex> | ||
varying vec2 vUv; | ||
varying vec4 worldPos; | ||
varying vec3 worldStart; | ||
varying vec3 worldEnd; | ||
@@ -308,2 +309,5 @@ #ifdef USE_DASH | ||
worldStart = start.xyz; | ||
worldEnd = end.xyz; | ||
// special case for perspective projection, and segments that terminate either in, or behind, the camera plane | ||
@@ -335,7 +339,7 @@ // clearly the gpu firmware has a way of addressing this issue when projecting into ndc space | ||
// ndc space | ||
vec2 ndcStart = clipStart.xy / clipStart.w; | ||
vec2 ndcEnd = clipEnd.xy / clipEnd.w; | ||
vec3 ndcStart = clipStart.xyz / clipStart.w; | ||
vec3 ndcEnd = clipEnd.xyz / clipEnd.w; | ||
// direction | ||
vec2 dir = ndcEnd - ndcStart; | ||
vec2 dir = ndcEnd.xy - ndcStart.xy; | ||
@@ -346,5 +350,61 @@ // account for clip-space aspect ratio | ||
// perpendicular to dir | ||
#ifdef WORLD_UNITS | ||
// get the offset direction as perpendicular to the view vector | ||
vec3 worldDir = normalize( end.xyz - start.xyz ); | ||
vec3 offset; | ||
if ( position.y < 0.5 ) { | ||
offset = normalize( cross( start.xyz, worldDir ) ); | ||
} else { | ||
offset = normalize( cross( end.xyz, worldDir ) ); | ||
} | ||
// sign flip | ||
if ( position.x < 0.0 ) offset *= - 1.0; | ||
float forwardOffset = dot( worldDir, vec3( 0.0, 0.0, 1.0 ) ); | ||
// don't extend the line if we're rendering dashes because we | ||
// won't be rendering the endcaps | ||
#ifndef USE_DASH | ||
// extend the line bounds to encompass endcaps | ||
start.xyz += - worldDir * linewidth * 0.5; | ||
end.xyz += worldDir * linewidth * 0.5; | ||
// shift the position of the quad so it hugs the forward edge of the line | ||
offset.xy -= dir * forwardOffset; | ||
offset.z += 0.5; | ||
#endif | ||
// endcaps | ||
if ( position.y > 1.0 || position.y < 0.0 ) { | ||
offset.xy += dir * 2.0 * forwardOffset; | ||
} | ||
// adjust for linewidth | ||
offset *= linewidth * 0.5; | ||
// set the world position | ||
worldPos = ( position.y < 0.5 ) ? start : end; | ||
worldPos.xyz += offset; | ||
// project the worldpos | ||
vec4 clip = projectionMatrix * worldPos; | ||
// shift the depth of the projected points so the line | ||
// segements overlap neatly | ||
vec3 clipPose = ( position.y < 0.5 ) ? ndcStart : ndcEnd; | ||
clip.z = clipPose.z * clip.w; | ||
#else | ||
vec2 offset = vec2( dir.y, - dir.x ); | ||
// undo aspect ratio adjustment | ||
@@ -382,2 +442,4 @@ dir.x /= aspect; | ||
#endif | ||
gl_Position = clip; | ||
@@ -393,5 +455,8 @@ | ||
`, | ||
fragmentShader: ` | ||
fragmentShader: | ||
/* glsl */ | ||
` | ||
uniform vec3 diffuse; | ||
uniform float opacity; | ||
uniform float linewidth; | ||
@@ -401,3 +466,2 @@ #ifdef USE_DASH | ||
uniform float dashSize; | ||
uniform float dashOffset; | ||
uniform float gapSize; | ||
@@ -408,2 +472,5 @@ | ||
varying float vLineDistance; | ||
varying vec4 worldPos; | ||
varying vec3 worldStart; | ||
varying vec3 worldEnd; | ||
@@ -418,2 +485,31 @@ #include <common> | ||
vec2 closestLineToLine(vec3 p1, vec3 p2, vec3 p3, vec3 p4) { | ||
float mua; | ||
float mub; | ||
vec3 p13 = p1 - p3; | ||
vec3 p43 = p4 - p3; | ||
vec3 p21 = p2 - p1; | ||
float d1343 = dot( p13, p43 ); | ||
float d4321 = dot( p43, p21 ); | ||
float d1321 = dot( p13, p21 ); | ||
float d4343 = dot( p43, p43 ); | ||
float d2121 = dot( p21, p21 ); | ||
float denom = d2121 * d4343 - d4321 * d4321; | ||
float numer = d1343 * d4321 - d1321 * d4343; | ||
mua = numer / denom; | ||
mua = clamp( mua, 0.0, 1.0 ); | ||
mub = ( d1343 + d4321 * ( mua ) ) / d4343; | ||
mub = clamp( mub, 0.0, 1.0 ); | ||
return vec2( mua, mub ); | ||
} | ||
void main() { | ||
@@ -427,6 +523,58 @@ | ||
if ( mod( vLineDistance + dashOffset, dashSize + gapSize ) > dashSize ) discard; // todo - FIX | ||
if ( mod( vLineDistance, dashSize + gapSize ) > dashSize ) discard; // todo - FIX | ||
#endif | ||
float alpha = opacity; | ||
#ifdef WORLD_UNITS | ||
// Find the closest points on the view ray and the line segment | ||
vec3 rayEnd = normalize( worldPos.xyz ) * 1e5; | ||
vec3 lineDir = worldEnd - worldStart; | ||
vec2 params = closestLineToLine( worldStart, worldEnd, vec3( 0.0, 0.0, 0.0 ), rayEnd ); | ||
vec3 p1 = worldStart + lineDir * params.x; | ||
vec3 p2 = rayEnd * params.y; | ||
vec3 delta = p1 - p2; | ||
float len = length( delta ); | ||
float norm = len / linewidth; | ||
#ifndef USE_DASH | ||
#ifdef ALPHA_TO_COVERAGE | ||
float dnorm = fwidth( norm ); | ||
alpha = 1.0 - smoothstep( 0.5 - dnorm, 0.5 + dnorm, norm ); | ||
#else | ||
if ( norm > 0.5 ) { | ||
discard; | ||
} | ||
#endif | ||
#endif | ||
#else | ||
#ifdef ALPHA_TO_COVERAGE | ||
// artifacts appear on some hardware if a derivative is taken within a conditional | ||
float a = vUv.x; | ||
float b = ( vUv.y > 0.0 ) ? vUv.y - 1.0 : vUv.y + 1.0; | ||
float len2 = a * a + b * b; | ||
float dlen = fwidth( len2 ); | ||
if ( abs( vUv.y ) > 1.0 ) { | ||
alpha = 1.0 - smoothstep( 1.0 - dlen, 1.0 + dlen, len2 ); | ||
} | ||
#else | ||
if ( abs( vUv.y ) > 1.0 ) { | ||
@@ -442,8 +590,12 @@ | ||
vec4 diffuseColor = vec4( diffuse, opacity ); | ||
#endif | ||
#endif | ||
vec4 diffuseColor = vec4( diffuse, alpha ); | ||
#include <logdepthbuf_fragment> | ||
#include <color_fragment> | ||
gl_FragColor = vec4( diffuseColor.rgb, diffuseColor.a ); | ||
gl_FragColor = vec4( diffuseColor.rgb, alpha ); | ||
@@ -469,3 +621,2 @@ #include <tonemapping_fragment> | ||
}); | ||
this.dashed = false; | ||
Object.defineProperties(this, { | ||
@@ -481,2 +632,15 @@ color: { | ||
}, | ||
worldUnits: { | ||
enumerable: true, | ||
get: function () { | ||
return 'WORLD_UNITS' in this.defines; | ||
}, | ||
set: function (value) { | ||
if (value === true) { | ||
this.defines.WORLD_UNITS = ''; | ||
} else { | ||
delete this.defines.WORLD_UNITS; | ||
} | ||
} | ||
}, | ||
linewidth: { | ||
@@ -491,2 +655,21 @@ enumerable: true, | ||
}, | ||
dashed: { | ||
enumerable: true, | ||
get: function () { | ||
return Boolean('USE_DASH' in this.defines); | ||
}, | ||
set(value) { | ||
if (Boolean(value) !== Boolean('USE_DASH' in this.defines)) { | ||
this.needsUpdate = true; | ||
} | ||
if (value === true) { | ||
this.defines.USE_DASH = ''; | ||
} else { | ||
delete this.defines.USE_DASH; | ||
} | ||
} | ||
}, | ||
dashScale: { | ||
@@ -556,3 +739,3 @@ enumerable: true, | ||
if (value) { | ||
if (value === true) { | ||
this.defines.ALPHA_TO_COVERAGE = ''; | ||
@@ -750,4 +933,4 @@ this.extensions.derivatives = true; | ||
_start.w = 1; | ||
_end.w = 1; // camera space | ||
_start4.w = 1; | ||
_end4.w = 1; // camera space | ||
@@ -887,3 +1070,3 @@ _start4.applyMatrix4(_mvMatrix); | ||
if (geometry.isGeometry) { | ||
console.error('LineGeometry no longer supports Geometry. Use THREE.BufferGeometry instead.'); | ||
console.error('THREE.LineGeometry no longer supports Geometry. Use THREE.BufferGeometry instead.'); | ||
return; | ||
@@ -898,7 +1081,2 @@ } else if (geometry.isBufferGeometry) { | ||
copy() { | ||
// todo | ||
return this; | ||
} | ||
} | ||
@@ -905,0 +1083,0 @@ |
@@ -1,2 +0,2 @@ | ||
// Version 0.5.0 three-fatline - https://github.com/vasturiano/three-fatline | ||
// Version 0.5.1 three-fatline - https://github.com/vasturiano/three-fatline | ||
(function (global, factory) { | ||
@@ -6,3 +6,3 @@ typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('three')) : | ||
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.THREE = global.THREE || {}, global.THREE)); | ||
}(this, (function (exports, three) { 'use strict'; | ||
})(this, (function (exports, three) { 'use strict'; | ||
@@ -116,3 +116,3 @@ const THREE$2 = window.THREE ? window.THREE // Prefer consumption from global THREE, if exists | ||
romLineSegments(lineSegments) { | ||
fromLineSegments(lineSegments) { | ||
const geometry = lineSegments.geometry; | ||
@@ -202,3 +202,2 @@ | ||
* dashSize: <float>, | ||
* dashOffset: <float>, | ||
* gapSize: <float>, | ||
@@ -217,2 +216,5 @@ * resolution: <Vector2>, // to be set by renderer | ||
THREE$1.UniformsLib.line = { | ||
worldUnits: { | ||
value: 1 | ||
}, | ||
linewidth: { | ||
@@ -222,3 +224,3 @@ value: 1 | ||
resolution: { | ||
value: new three.Vector2(1, 1) | ||
value: new THREE$1.Vector2(1, 1) | ||
}, | ||
@@ -231,16 +233,12 @@ dashScale: { | ||
}, | ||
dashOffset: { | ||
value: 0 | ||
}, | ||
gapSize: { | ||
value: 1 | ||
}, | ||
// todo FIX - maybe change to totalSize | ||
opacity: { | ||
value: 1 | ||
} | ||
} // todo FIX - maybe change to totalSize | ||
}; | ||
THREE$1.ShaderLib['line'] = { | ||
uniforms: THREE$1.UniformsUtils.merge([THREE$1.UniformsLib.common, THREE$1.UniformsLib.fog, THREE$1.UniformsLib.line]), | ||
vertexShader: ` | ||
vertexShader: | ||
/* glsl */ | ||
` | ||
#include <common> | ||
@@ -262,2 +260,5 @@ #include <color_pars_vertex> | ||
varying vec2 vUv; | ||
varying vec4 worldPos; | ||
varying vec3 worldStart; | ||
varying vec3 worldEnd; | ||
@@ -310,2 +311,5 @@ #ifdef USE_DASH | ||
worldStart = start.xyz; | ||
worldEnd = end.xyz; | ||
// special case for perspective projection, and segments that terminate either in, or behind, the camera plane | ||
@@ -337,7 +341,7 @@ // clearly the gpu firmware has a way of addressing this issue when projecting into ndc space | ||
// ndc space | ||
vec2 ndcStart = clipStart.xy / clipStart.w; | ||
vec2 ndcEnd = clipEnd.xy / clipEnd.w; | ||
vec3 ndcStart = clipStart.xyz / clipStart.w; | ||
vec3 ndcEnd = clipEnd.xyz / clipEnd.w; | ||
// direction | ||
vec2 dir = ndcEnd - ndcStart; | ||
vec2 dir = ndcEnd.xy - ndcStart.xy; | ||
@@ -348,5 +352,61 @@ // account for clip-space aspect ratio | ||
// perpendicular to dir | ||
#ifdef WORLD_UNITS | ||
// get the offset direction as perpendicular to the view vector | ||
vec3 worldDir = normalize( end.xyz - start.xyz ); | ||
vec3 offset; | ||
if ( position.y < 0.5 ) { | ||
offset = normalize( cross( start.xyz, worldDir ) ); | ||
} else { | ||
offset = normalize( cross( end.xyz, worldDir ) ); | ||
} | ||
// sign flip | ||
if ( position.x < 0.0 ) offset *= - 1.0; | ||
float forwardOffset = dot( worldDir, vec3( 0.0, 0.0, 1.0 ) ); | ||
// don't extend the line if we're rendering dashes because we | ||
// won't be rendering the endcaps | ||
#ifndef USE_DASH | ||
// extend the line bounds to encompass endcaps | ||
start.xyz += - worldDir * linewidth * 0.5; | ||
end.xyz += worldDir * linewidth * 0.5; | ||
// shift the position of the quad so it hugs the forward edge of the line | ||
offset.xy -= dir * forwardOffset; | ||
offset.z += 0.5; | ||
#endif | ||
// endcaps | ||
if ( position.y > 1.0 || position.y < 0.0 ) { | ||
offset.xy += dir * 2.0 * forwardOffset; | ||
} | ||
// adjust for linewidth | ||
offset *= linewidth * 0.5; | ||
// set the world position | ||
worldPos = ( position.y < 0.5 ) ? start : end; | ||
worldPos.xyz += offset; | ||
// project the worldpos | ||
vec4 clip = projectionMatrix * worldPos; | ||
// shift the depth of the projected points so the line | ||
// segements overlap neatly | ||
vec3 clipPose = ( position.y < 0.5 ) ? ndcStart : ndcEnd; | ||
clip.z = clipPose.z * clip.w; | ||
#else | ||
vec2 offset = vec2( dir.y, - dir.x ); | ||
// undo aspect ratio adjustment | ||
@@ -384,2 +444,4 @@ dir.x /= aspect; | ||
#endif | ||
gl_Position = clip; | ||
@@ -395,5 +457,8 @@ | ||
`, | ||
fragmentShader: ` | ||
fragmentShader: | ||
/* glsl */ | ||
` | ||
uniform vec3 diffuse; | ||
uniform float opacity; | ||
uniform float linewidth; | ||
@@ -403,3 +468,2 @@ #ifdef USE_DASH | ||
uniform float dashSize; | ||
uniform float dashOffset; | ||
uniform float gapSize; | ||
@@ -410,2 +474,5 @@ | ||
varying float vLineDistance; | ||
varying vec4 worldPos; | ||
varying vec3 worldStart; | ||
varying vec3 worldEnd; | ||
@@ -420,2 +487,31 @@ #include <common> | ||
vec2 closestLineToLine(vec3 p1, vec3 p2, vec3 p3, vec3 p4) { | ||
float mua; | ||
float mub; | ||
vec3 p13 = p1 - p3; | ||
vec3 p43 = p4 - p3; | ||
vec3 p21 = p2 - p1; | ||
float d1343 = dot( p13, p43 ); | ||
float d4321 = dot( p43, p21 ); | ||
float d1321 = dot( p13, p21 ); | ||
float d4343 = dot( p43, p43 ); | ||
float d2121 = dot( p21, p21 ); | ||
float denom = d2121 * d4343 - d4321 * d4321; | ||
float numer = d1343 * d4321 - d1321 * d4343; | ||
mua = numer / denom; | ||
mua = clamp( mua, 0.0, 1.0 ); | ||
mub = ( d1343 + d4321 * ( mua ) ) / d4343; | ||
mub = clamp( mub, 0.0, 1.0 ); | ||
return vec2( mua, mub ); | ||
} | ||
void main() { | ||
@@ -429,6 +525,58 @@ | ||
if ( mod( vLineDistance + dashOffset, dashSize + gapSize ) > dashSize ) discard; // todo - FIX | ||
if ( mod( vLineDistance, dashSize + gapSize ) > dashSize ) discard; // todo - FIX | ||
#endif | ||
float alpha = opacity; | ||
#ifdef WORLD_UNITS | ||
// Find the closest points on the view ray and the line segment | ||
vec3 rayEnd = normalize( worldPos.xyz ) * 1e5; | ||
vec3 lineDir = worldEnd - worldStart; | ||
vec2 params = closestLineToLine( worldStart, worldEnd, vec3( 0.0, 0.0, 0.0 ), rayEnd ); | ||
vec3 p1 = worldStart + lineDir * params.x; | ||
vec3 p2 = rayEnd * params.y; | ||
vec3 delta = p1 - p2; | ||
float len = length( delta ); | ||
float norm = len / linewidth; | ||
#ifndef USE_DASH | ||
#ifdef ALPHA_TO_COVERAGE | ||
float dnorm = fwidth( norm ); | ||
alpha = 1.0 - smoothstep( 0.5 - dnorm, 0.5 + dnorm, norm ); | ||
#else | ||
if ( norm > 0.5 ) { | ||
discard; | ||
} | ||
#endif | ||
#endif | ||
#else | ||
#ifdef ALPHA_TO_COVERAGE | ||
// artifacts appear on some hardware if a derivative is taken within a conditional | ||
float a = vUv.x; | ||
float b = ( vUv.y > 0.0 ) ? vUv.y - 1.0 : vUv.y + 1.0; | ||
float len2 = a * a + b * b; | ||
float dlen = fwidth( len2 ); | ||
if ( abs( vUv.y ) > 1.0 ) { | ||
alpha = 1.0 - smoothstep( 1.0 - dlen, 1.0 + dlen, len2 ); | ||
} | ||
#else | ||
if ( abs( vUv.y ) > 1.0 ) { | ||
@@ -444,8 +592,12 @@ | ||
vec4 diffuseColor = vec4( diffuse, opacity ); | ||
#endif | ||
#endif | ||
vec4 diffuseColor = vec4( diffuse, alpha ); | ||
#include <logdepthbuf_fragment> | ||
#include <color_fragment> | ||
gl_FragColor = vec4( diffuseColor.rgb, diffuseColor.a ); | ||
gl_FragColor = vec4( diffuseColor.rgb, alpha ); | ||
@@ -471,3 +623,2 @@ #include <tonemapping_fragment> | ||
}); | ||
this.dashed = false; | ||
Object.defineProperties(this, { | ||
@@ -483,2 +634,15 @@ color: { | ||
}, | ||
worldUnits: { | ||
enumerable: true, | ||
get: function () { | ||
return 'WORLD_UNITS' in this.defines; | ||
}, | ||
set: function (value) { | ||
if (value === true) { | ||
this.defines.WORLD_UNITS = ''; | ||
} else { | ||
delete this.defines.WORLD_UNITS; | ||
} | ||
} | ||
}, | ||
linewidth: { | ||
@@ -493,2 +657,21 @@ enumerable: true, | ||
}, | ||
dashed: { | ||
enumerable: true, | ||
get: function () { | ||
return Boolean('USE_DASH' in this.defines); | ||
}, | ||
set(value) { | ||
if (Boolean(value) !== Boolean('USE_DASH' in this.defines)) { | ||
this.needsUpdate = true; | ||
} | ||
if (value === true) { | ||
this.defines.USE_DASH = ''; | ||
} else { | ||
delete this.defines.USE_DASH; | ||
} | ||
} | ||
}, | ||
dashScale: { | ||
@@ -558,3 +741,3 @@ enumerable: true, | ||
if (value) { | ||
if (value === true) { | ||
this.defines.ALPHA_TO_COVERAGE = ''; | ||
@@ -752,4 +935,4 @@ this.extensions.derivatives = true; | ||
_start.w = 1; | ||
_end.w = 1; // camera space | ||
_start4.w = 1; | ||
_end4.w = 1; // camera space | ||
@@ -889,3 +1072,3 @@ _start4.applyMatrix4(_mvMatrix); | ||
if (geometry.isGeometry) { | ||
console.error('LineGeometry no longer supports Geometry. Use THREE.BufferGeometry instead.'); | ||
console.error('THREE.LineGeometry no longer supports Geometry. Use THREE.BufferGeometry instead.'); | ||
return; | ||
@@ -900,7 +1083,2 @@ } else if (geometry.isBufferGeometry) { | ||
copy() { | ||
// todo | ||
return this; | ||
} | ||
} | ||
@@ -930,3 +1108,3 @@ | ||
}))); | ||
})); | ||
//# sourceMappingURL=three-fatline.js.map |
@@ -1,2 +0,2 @@ | ||
// Version 0.5.0 three-fatline - https://github.com/vasturiano/three-fatline | ||
!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?e(exports,require("three")):"function"==typeof define&&define.amd?define(["exports","three"],e):e((t="undefined"!=typeof globalThis?globalThis:t||self).THREE=t.THREE||{},t.THREE)}(this,(function(t,e){"use strict";const n=window.THREE?window.THREE:{Box3:e.Box3,BufferGeometry:e.BufferGeometry,Float32BufferAttribute:e.Float32BufferAttribute,InstancedBufferGeometry:e.InstancedBufferGeometry,InstancedInterleavedBuffer:e.InstancedInterleavedBuffer,InterleavedBufferAttribute:e.InterleavedBufferAttribute,Sphere:e.Sphere,Vector3:e.Vector3,WireframeGeometry:e.WireframeGeometry};var i=(new n.BufferGeometry).setAttribute?"setAttribute":"addAttribute";const r=new n.Box3,o=new n.Vector3;class a extends n.InstancedBufferGeometry{constructor(){super(),this.type="LineSegmentsGeometry";this.setIndex([0,2,1,2,3,1,2,4,3,4,5,3,4,6,5,6,7,5]),this[i]("position",new n.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[i]("uv",new n.Float32BufferAttribute([-1,2,1,2,-1,1,1,1,-1,-1,1,-1,-1,-2,1,-2],2))}applyMatrix4(t){const e=this.attributes.instanceStart,n=this.attributes.instanceEnd;return void 0!==e&&(e.applyMatrix4(t),n.applyMatrix4(t),e.needsUpdate=!0),null!==this.boundingBox&&this.computeBoundingBox(),null!==this.boundingSphere&&this.computeBoundingSphere(),this}setPositions(t){let e;t instanceof Float32Array?e=t:Array.isArray(t)&&(e=new Float32Array(t));const r=new n.InstancedInterleavedBuffer(e,6,1);return this[i]("instanceStart",new n.InterleavedBufferAttribute(r,3,0)),this[i]("instanceEnd",new n.InterleavedBufferAttribute(r,3,3)),this.computeBoundingBox(),this.computeBoundingSphere(),this}setColors(t){let e;t instanceof Float32Array?e=t:Array.isArray(t)&&(e=new Float32Array(t));const r=new n.InstancedInterleavedBuffer(e,6,1);return this[i]("instanceColorStart",new n.InterleavedBufferAttribute(r,3,0)),this[i]("instanceColorEnd",new n.InterleavedBufferAttribute(r,3,3)),this}fromWireframeGeometry(t){return this.setPositions(t.attributes.position.array),this}fromEdgesGeometry(t){return this.setPositions(t.attributes.position.array),this}fromMesh(t){return this.fromWireframeGeometry(new n.WireframeGeometry(t.geometry)),this}romLineSegments(t){const e=t.geometry;if(!e.isGeometry)return e.isBufferGeometry&&this.setPositions(e.attributes.position.array),this;console.error("LineSegmentsGeometry no longer supports Geometry. Use THREE.BufferGeometry instead.")}computeBoundingBox(){null===this.boundingBox&&(this.boundingBox=new n.Box3);const t=this.attributes.instanceStart,e=this.attributes.instanceEnd;void 0!==t&&void 0!==e&&(this.boundingBox.setFromBufferAttribute(t),r.setFromBufferAttribute(e),this.boundingBox.union(r))}computeBoundingSphere(){null===this.boundingSphere&&(this.boundingSphere=new n.Sphere),null===this.boundingBox&&this.computeBoundingBox();const t=this.attributes.instanceStart,e=this.attributes.instanceEnd;if(void 0!==t&&void 0!==e){const n=this.boundingSphere.center;this.boundingBox.getCenter(n);let i=0;for(let r=0,a=t.count;r<a;r++)o.fromBufferAttribute(t,r),i=Math.max(i,n.distanceToSquared(o)),o.fromBufferAttribute(e,r),i=Math.max(i,n.distanceToSquared(o));this.boundingSphere.radius=Math.sqrt(i),isNaN(this.boundingSphere.radius)&&console.error("THREE.LineSegmentsGeometry.computeBoundingSphere(): Computed radius is NaN. The instanced position data is likely to have NaN values.",this)}}toJSON(){}applyMatrix(t){return console.warn("THREE.LineSegmentsGeometry: applyMatrix() has been renamed to applyMatrix4()."),this.applyMatrix4(t)}}a.prototype.isLineSegmentsGeometry=!0;const s=window.THREE?window.THREE:{ShaderLib:e.ShaderLib,ShaderMaterial:e.ShaderMaterial,UniformsLib:e.UniformsLib,UniformsUtils:e.UniformsUtils,Vector2:e.Vector2};s.UniformsLib.line={linewidth:{value:1},resolution:{value:new e.Vector2(1,1)},dashScale:{value:1},dashSize:{value:1},dashOffset:{value:0},gapSize:{value:1},opacity:{value:1}},s.ShaderLib.line={uniforms:s.UniformsUtils.merge([s.UniformsLib.common,s.UniformsLib.fog,s.UniformsLib.line]),vertexShader:"\n\t\t#include <common>\n\t\t#include <color_pars_vertex>\n\t\t#include <fog_pars_vertex>\n\t\t#include <logdepthbuf_pars_vertex>\n\t\t#include <clipping_planes_pars_vertex>\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 <logdepthbuf_vertex>\n\t\t\t#include <clipping_planes_vertex>\n\t\t\t#include <fog_vertex>\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 <common>\n\t\t#include <color_pars_fragment>\n\t\t#include <fog_pars_fragment>\n\t\t#include <logdepthbuf_pars_fragment>\n\t\t#include <clipping_planes_pars_fragment>\n\n\t\tvarying vec2 vUv;\n\n\t\tvoid main() {\n\n\t\t\t#include <clipping_planes_fragment>\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 <logdepthbuf_fragment>\n\t\t\t#include <color_fragment>\n\n\t\t\tgl_FragColor = vec4( diffuseColor.rgb, diffuseColor.a );\n\n\t\t\t#include <tonemapping_fragment>\n\t\t\t#include <encodings_fragment>\n\t\t\t#include <fog_fragment>\n\t\t\t#include <premultiplied_alpha_fragment>\n\n\t\t}\n\t\t"};class u extends s.ShaderMaterial{constructor(t){super({type:"LineMaterial",uniforms:s.UniformsUtils.clone(s.ShaderLib.line.uniforms),vertexShader:s.ShaderLib.line.vertexShader,fragmentShader:s.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)}},alphaToCoverage:{enumerable:!0,get:function(){return Boolean("ALPHA_TO_COVERAGE"in this.defines)},set:function(t){Boolean(t)!==Boolean("ALPHA_TO_COVERAGE"in this.defines)&&(this.needsUpdate=!0),t?(this.defines.ALPHA_TO_COVERAGE="",this.extensions.derivatives=!0):(delete this.defines.ALPHA_TO_COVERAGE,this.extensions.derivatives=!1)}}}),this.setValues(t)}}u.prototype.isLineMaterial=!0;const c=window.THREE?window.THREE:{Box3:e.Box3,BufferGeometry:e.BufferGeometry,InstancedInterleavedBuffer:e.InstancedInterleavedBuffer,InterleavedBufferAttribute:e.InterleavedBufferAttribute,Line3:e.Line3,MathUtils:e.MathUtils,Matrix4:e.Matrix4,Mesh:e.Mesh,Sphere:e.Sphere,Vector3:e.Vector3,Vector4:e.Vector4};var l=(new c.BufferGeometry).setAttribute?"setAttribute":"addAttribute";const f=new c.Vector3,d=new c.Vector3,p=new c.Vector4,m=new c.Vector4,h=new c.Vector4,y=new c.Vector3,v=new c.Matrix4,g=new c.Line3,b=new c.Vector3,x=new c.Box3,S=new c.Sphere,w=new c.Vector4;class B extends c.Mesh{constructor(t=new a,e=new u({color:16777215*Math.random()})){super(t,e),this.type="LineSegments2"}computeLineDistances(){const t=this.geometry,e=t.attributes.instanceStart,n=t.attributes.instanceEnd,i=new Float32Array(2*e.count);for(let t=0,r=0,o=e.count;t<o;t++,r+=2)f.fromBufferAttribute(e,t),d.fromBufferAttribute(n,t),i[r]=0===r?0:i[r-1],i[r+1]=i[r]+f.distanceTo(d);const r=new c.InstancedInterleavedBuffer(i,2,1);return t[l]("instanceDistanceStart",new c.InterleavedBufferAttribute(r,1,0)),t[l]("instanceDistanceEnd",new c.InterleavedBufferAttribute(r,1,1)),this}raycast(t,e){null===t.camera&&console.error('LineSegments2: "Raycaster.camera" needs to be set in order to raycast against LineSegments2.');const n=void 0!==t.params.Line2&&t.params.Line2.threshold||0,i=t.ray,r=t.camera,o=r.projectionMatrix,a=this.matrixWorld,s=this.geometry,u=this.material,l=u.resolution,B=u.linewidth+n,E=s.attributes.instanceStart,M=s.attributes.instanceEnd,A=-r.near,L=2*Math.max(B/l.width,B/l.height);null===s.boundingSphere&&s.computeBoundingSphere(),S.copy(s.boundingSphere).applyMatrix4(a);const _=Math.max(r.near,S.distanceToPoint(i.origin));w.set(0,0,-_,1).applyMatrix4(r.projectionMatrix),w.multiplyScalar(1/w.w),w.applyMatrix4(r.projectionMatrixInverse);const z=.5*Math.abs(L/w.w);if(S.radius+=z,!1===t.ray.intersectsSphere(S))return;null===s.boundingBox&&s.computeBoundingBox(),x.copy(s.boundingBox).applyMatrix4(a);const G=Math.max(r.near,x.distanceToPoint(i.origin));w.set(0,0,-G,1).applyMatrix4(r.projectionMatrix),w.multiplyScalar(1/w.w),w.applyMatrix4(r.projectionMatrixInverse);const U=.5*Math.abs(L/w.w);if(x.max.x+=U,x.max.y+=U,x.max.z+=U,x.min.x-=U,x.min.y-=U,x.min.z-=U,!1!==t.ray.intersectsBox(x)){i.at(1,h),h.w=1,h.applyMatrix4(r.matrixWorldInverse),h.applyMatrix4(o),h.multiplyScalar(1/h.w),h.x*=l.x/2,h.y*=l.y/2,h.z=0,y.copy(h),v.multiplyMatrices(r.matrixWorldInverse,a);for(let t=0,n=E.count;t<n;t++){if(p.fromBufferAttribute(E,t),m.fromBufferAttribute(M,t),f.w=1,d.w=1,p.applyMatrix4(v),m.applyMatrix4(v),p.z>A&&m.z>A)continue;if(p.z>A){const t=p.z-m.z,e=(p.z-A)/t;p.lerp(m,e)}else if(m.z>A){const t=m.z-p.z,e=(m.z-A)/t;m.lerp(p,e)}p.applyMatrix4(o),m.applyMatrix4(o),p.multiplyScalar(1/p.w),m.multiplyScalar(1/m.w),p.x*=l.x/2,p.y*=l.y/2,m.x*=l.x/2,m.y*=l.y/2,g.start.copy(p),g.start.z=0,g.end.copy(m),g.end.z=0;const n=g.closestPointToPointParameter(y,!0);g.at(n,b);const r=c.MathUtils.lerp(p.z,m.z,n),s=r>=-1&&r<=1,u=y.distanceTo(b)<.5*B;if(s&&u){g.start.fromBufferAttribute(E,t),g.end.fromBufferAttribute(M,t),g.start.applyMatrix4(a),g.end.applyMatrix4(a);const n=new c.Vector3,r=new c.Vector3;i.distanceSqToSegment(g.start,g.end,r,n),e.push({point:r,pointOnLine:n,distance:i.origin.distanceTo(r),object:this,face:null,faceIndex:t,uv:null,uv2:null})}}}}}B.prototype.LineSegments2=!0;class E extends a{constructor(){super(),this.type="LineGeometry"}setPositions(t){for(var e=t.length-3,n=new Float32Array(2*e),i=0;i<e;i+=3)n[2*i]=t[i],n[2*i+1]=t[i+1],n[2*i+2]=t[i+2],n[2*i+3]=t[i+3],n[2*i+4]=t[i+4],n[2*i+5]=t[i+5];return super.setPositions(n),this}setColors(t){for(var e=t.length-3,n=new Float32Array(2*e),i=0;i<e;i+=3)n[2*i]=t[i],n[2*i+1]=t[i+1],n[2*i+2]=t[i+2],n[2*i+3]=t[i+3],n[2*i+4]=t[i+4],n[2*i+5]=t[i+5];return super.setColors(n),this}fromLine(t){var e=t.geometry;if(!e.isGeometry)return e.isBufferGeometry&&this.setPositions(e.attributes.position.array),this;console.error("LineGeometry no longer supports Geometry. Use THREE.BufferGeometry instead.")}copy(){return this}}E.prototype.isLineGeometry=!0;class M extends B{constructor(t=new E,e=new u({color:16777215*Math.random()})){super(t,e),this.type="Line2"}}M.prototype.isLine2=!0,t.Line2=M,t.LineGeometry=E,t.LineMaterial=u,t.LineSegments2=B,t.LineSegmentsGeometry=a,Object.defineProperty(t,"__esModule",{value:!0})})); | ||
// Version 0.5.1 three-fatline - https://github.com/vasturiano/three-fatline | ||
!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?e(exports,require("three")):"function"==typeof define&&define.amd?define(["exports","three"],e):e((t="undefined"!=typeof globalThis?globalThis:t||self).THREE=t.THREE||{},t.THREE)}(this,(function(t,e){"use strict";const n=window.THREE?window.THREE:{Box3:e.Box3,BufferGeometry:e.BufferGeometry,Float32BufferAttribute:e.Float32BufferAttribute,InstancedBufferGeometry:e.InstancedBufferGeometry,InstancedInterleavedBuffer:e.InstancedInterleavedBuffer,InterleavedBufferAttribute:e.InterleavedBufferAttribute,Sphere:e.Sphere,Vector3:e.Vector3,WireframeGeometry:e.WireframeGeometry};var i=(new n.BufferGeometry).setAttribute?"setAttribute":"addAttribute";const r=new n.Box3,o=new n.Vector3;class a extends n.InstancedBufferGeometry{constructor(){super(),this.type="LineSegmentsGeometry";this.setIndex([0,2,1,2,3,1,2,4,3,4,5,3,4,6,5,6,7,5]),this[i]("position",new n.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[i]("uv",new n.Float32BufferAttribute([-1,2,1,2,-1,1,1,1,-1,-1,1,-1,-1,-2,1,-2],2))}applyMatrix4(t){const e=this.attributes.instanceStart,n=this.attributes.instanceEnd;return void 0!==e&&(e.applyMatrix4(t),n.applyMatrix4(t),e.needsUpdate=!0),null!==this.boundingBox&&this.computeBoundingBox(),null!==this.boundingSphere&&this.computeBoundingSphere(),this}setPositions(t){let e;t instanceof Float32Array?e=t:Array.isArray(t)&&(e=new Float32Array(t));const r=new n.InstancedInterleavedBuffer(e,6,1);return this[i]("instanceStart",new n.InterleavedBufferAttribute(r,3,0)),this[i]("instanceEnd",new n.InterleavedBufferAttribute(r,3,3)),this.computeBoundingBox(),this.computeBoundingSphere(),this}setColors(t){let e;t instanceof Float32Array?e=t:Array.isArray(t)&&(e=new Float32Array(t));const r=new n.InstancedInterleavedBuffer(e,6,1);return this[i]("instanceColorStart",new n.InterleavedBufferAttribute(r,3,0)),this[i]("instanceColorEnd",new n.InterleavedBufferAttribute(r,3,3)),this}fromWireframeGeometry(t){return this.setPositions(t.attributes.position.array),this}fromEdgesGeometry(t){return this.setPositions(t.attributes.position.array),this}fromMesh(t){return this.fromWireframeGeometry(new n.WireframeGeometry(t.geometry)),this}fromLineSegments(t){const e=t.geometry;if(!e.isGeometry)return e.isBufferGeometry&&this.setPositions(e.attributes.position.array),this;console.error("LineSegmentsGeometry no longer supports Geometry. Use THREE.BufferGeometry instead.")}computeBoundingBox(){null===this.boundingBox&&(this.boundingBox=new n.Box3);const t=this.attributes.instanceStart,e=this.attributes.instanceEnd;void 0!==t&&void 0!==e&&(this.boundingBox.setFromBufferAttribute(t),r.setFromBufferAttribute(e),this.boundingBox.union(r))}computeBoundingSphere(){null===this.boundingSphere&&(this.boundingSphere=new n.Sphere),null===this.boundingBox&&this.computeBoundingBox();const t=this.attributes.instanceStart,e=this.attributes.instanceEnd;if(void 0!==t&&void 0!==e){const n=this.boundingSphere.center;this.boundingBox.getCenter(n);let i=0;for(let r=0,a=t.count;r<a;r++)o.fromBufferAttribute(t,r),i=Math.max(i,n.distanceToSquared(o)),o.fromBufferAttribute(e,r),i=Math.max(i,n.distanceToSquared(o));this.boundingSphere.radius=Math.sqrt(i),isNaN(this.boundingSphere.radius)&&console.error("THREE.LineSegmentsGeometry.computeBoundingSphere(): Computed radius is NaN. The instanced position data is likely to have NaN values.",this)}}toJSON(){}applyMatrix(t){return console.warn("THREE.LineSegmentsGeometry: applyMatrix() has been renamed to applyMatrix4()."),this.applyMatrix4(t)}}a.prototype.isLineSegmentsGeometry=!0;const s=window.THREE?window.THREE:{ShaderLib:e.ShaderLib,ShaderMaterial:e.ShaderMaterial,UniformsLib:e.UniformsLib,UniformsUtils:e.UniformsUtils,Vector2:e.Vector2};s.UniformsLib.line={worldUnits:{value:1},linewidth:{value:1},resolution:{value:new s.Vector2(1,1)},dashScale:{value:1},dashSize:{value:1},gapSize:{value:1}},s.ShaderLib.line={uniforms:s.UniformsUtils.merge([s.UniformsLib.common,s.UniformsLib.fog,s.UniformsLib.line]),vertexShader:"\n\t\t#include <common>\n\t\t#include <color_pars_vertex>\n\t\t#include <fog_pars_vertex>\n\t\t#include <logdepthbuf_pars_vertex>\n\t\t#include <clipping_planes_pars_vertex>\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\t\tvarying vec4 worldPos;\n\t\tvarying vec3 worldStart;\n\t\tvarying vec3 worldEnd;\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\tworldStart = start.xyz;\n\t\t\tworldEnd = end.xyz;\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\tvec3 ndcStart = clipStart.xyz / clipStart.w;\n\t\t\tvec3 ndcEnd = clipEnd.xyz / clipEnd.w;\n\n\t\t\t// direction\n\t\t\tvec2 dir = ndcEnd.xy - ndcStart.xy;\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#ifdef WORLD_UNITS\n\n\t\t\t\t// get the offset direction as perpendicular to the view vector\n\t\t\t\tvec3 worldDir = normalize( end.xyz - start.xyz );\n\t\t\t\tvec3 offset;\n\t\t\t\tif ( position.y < 0.5 ) {\n\n\t\t\t\t\toffset = normalize( cross( start.xyz, worldDir ) );\n\n\t\t\t\t} else {\n\n\t\t\t\t\toffset = normalize( cross( end.xyz, worldDir ) );\n\n\t\t\t\t}\n\n\t\t\t\t// sign flip\n\t\t\t\tif ( position.x < 0.0 ) offset *= - 1.0;\n\n\t\t\t\tfloat forwardOffset = dot( worldDir, vec3( 0.0, 0.0, 1.0 ) );\n\n\t\t\t\t// don't extend the line if we're rendering dashes because we\n\t\t\t\t// won't be rendering the endcaps\n\t\t\t\t#ifndef USE_DASH\n\n\t\t\t\t\t// extend the line bounds to encompass endcaps\n\t\t\t\t\tstart.xyz += - worldDir * linewidth * 0.5;\n\t\t\t\t\tend.xyz += worldDir * linewidth * 0.5;\n\n\t\t\t\t\t// shift the position of the quad so it hugs the forward edge of the line\n\t\t\t\t\toffset.xy -= dir * forwardOffset;\n\t\t\t\t\toffset.z += 0.5;\n\n\t\t\t\t#endif\n\n\t\t\t\t// endcaps\n\t\t\t\tif ( position.y > 1.0 || position.y < 0.0 ) {\n\n\t\t\t\t\toffset.xy += dir * 2.0 * forwardOffset;\n\n\t\t\t\t}\n\n\t\t\t\t// adjust for linewidth\n\t\t\t\toffset *= linewidth * 0.5;\n\n\t\t\t\t// set the world position\n\t\t\t\tworldPos = ( position.y < 0.5 ) ? start : end;\n\t\t\t\tworldPos.xyz += offset;\n\n\t\t\t\t// project the worldpos\n\t\t\t\tvec4 clip = projectionMatrix * worldPos;\n\n\t\t\t\t// shift the depth of the projected points so the line\n\t\t\t\t// segements overlap neatly\n\t\t\t\tvec3 clipPose = ( position.y < 0.5 ) ? ndcStart : ndcEnd;\n\t\t\t\tclip.z = clipPose.z * clip.w;\n\n\t\t\t#else\n\n\t\t\tvec2 offset = vec2( dir.y, - dir.x );\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\t#endif\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 <logdepthbuf_vertex>\n\t\t\t#include <clipping_planes_vertex>\n\t\t\t#include <fog_vertex>\n\n\t\t}\n\t\t",fragmentShader:"\n\t\tuniform vec3 diffuse;\n\t\tuniform float opacity;\n\t\tuniform float linewidth;\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\t\tvarying vec4 worldPos;\n\t\tvarying vec3 worldStart;\n\t\tvarying vec3 worldEnd;\n\n\t\t#include <common>\n\t\t#include <color_pars_fragment>\n\t\t#include <fog_pars_fragment>\n\t\t#include <logdepthbuf_pars_fragment>\n\t\t#include <clipping_planes_pars_fragment>\n\n\t\tvarying vec2 vUv;\n\n\t\tvec2 closestLineToLine(vec3 p1, vec3 p2, vec3 p3, vec3 p4) {\n\n\t\t\tfloat mua;\n\t\t\tfloat mub;\n\n\t\t\tvec3 p13 = p1 - p3;\n\t\t\tvec3 p43 = p4 - p3;\n\n\t\t\tvec3 p21 = p2 - p1;\n\n\t\t\tfloat d1343 = dot( p13, p43 );\n\t\t\tfloat d4321 = dot( p43, p21 );\n\t\t\tfloat d1321 = dot( p13, p21 );\n\t\t\tfloat d4343 = dot( p43, p43 );\n\t\t\tfloat d2121 = dot( p21, p21 );\n\n\t\t\tfloat denom = d2121 * d4343 - d4321 * d4321;\n\n\t\t\tfloat numer = d1343 * d4321 - d1321 * d4343;\n\n\t\t\tmua = numer / denom;\n\t\t\tmua = clamp( mua, 0.0, 1.0 );\n\t\t\tmub = ( d1343 + d4321 * ( mua ) ) / d4343;\n\t\t\tmub = clamp( mub, 0.0, 1.0 );\n\n\t\t\treturn vec2( mua, mub );\n\n\t\t}\n\n\t\tvoid main() {\n\n\t\t\t#include <clipping_planes_fragment>\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, dashSize + gapSize ) > dashSize ) discard; // todo - FIX\n\n\t\t\t#endif\n\n\t\t\tfloat alpha = opacity;\n\n\t\t\t#ifdef WORLD_UNITS\n\n\t\t\t\t// Find the closest points on the view ray and the line segment\n\t\t\t\tvec3 rayEnd = normalize( worldPos.xyz ) * 1e5;\n\t\t\t\tvec3 lineDir = worldEnd - worldStart;\n\t\t\t\tvec2 params = closestLineToLine( worldStart, worldEnd, vec3( 0.0, 0.0, 0.0 ), rayEnd );\n\n\t\t\t\tvec3 p1 = worldStart + lineDir * params.x;\n\t\t\t\tvec3 p2 = rayEnd * params.y;\n\t\t\t\tvec3 delta = p1 - p2;\n\t\t\t\tfloat len = length( delta );\n\t\t\t\tfloat norm = len / linewidth;\n\n\t\t\t\t#ifndef USE_DASH\n\n\t\t\t\t\t#ifdef ALPHA_TO_COVERAGE\n\n\t\t\t\t\t\tfloat dnorm = fwidth( norm );\n\t\t\t\t\t\talpha = 1.0 - smoothstep( 0.5 - dnorm, 0.5 + dnorm, norm );\n\n\t\t\t\t\t#else\n\n\t\t\t\t\t\tif ( norm > 0.5 ) {\n\n\t\t\t\t\t\t\tdiscard;\n\n\t\t\t\t\t\t}\n\n\t\t\t\t\t#endif\n\n\t\t\t#endif\n\n\t\t\t#else\n\n\t\t\t\t#ifdef ALPHA_TO_COVERAGE\n\n\t\t\t\t\t// artifacts appear on some hardware if a derivative is taken within a conditional\n\t\t\t\t\tfloat a = vUv.x;\n\t\t\t\t\tfloat b = ( vUv.y > 0.0 ) ? vUv.y - 1.0 : vUv.y + 1.0;\n\t\t\t\t\tfloat len2 = a * a + b * b;\n\t\t\t\t\tfloat dlen = fwidth( len2 );\n\n\t\t\t\t\tif ( abs( vUv.y ) > 1.0 ) {\n\n\t\t\t\t\t\talpha = 1.0 - smoothstep( 1.0 - dlen, 1.0 + dlen, len2 );\n\n\t\t\t\t\t}\n\n\t\t\t\t#else\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\t\t#endif\n\n\t\t\t#endif\n\n\t\t\tvec4 diffuseColor = vec4( diffuse, alpha );\n\n\t\t\t#include <logdepthbuf_fragment>\n\t\t\t#include <color_fragment>\n\n\t\t\tgl_FragColor = vec4( diffuseColor.rgb, alpha );\n\n\t\t\t#include <tonemapping_fragment>\n\t\t\t#include <encodings_fragment>\n\t\t\t#include <fog_fragment>\n\t\t\t#include <premultiplied_alpha_fragment>\n\n\t\t}\n\t\t"};class d extends s.ShaderMaterial{constructor(t){super({type:"LineMaterial",uniforms:s.UniformsUtils.clone(s.ShaderLib.line.uniforms),vertexShader:s.ShaderLib.line.vertexShader,fragmentShader:s.ShaderLib.line.fragmentShader,clipping:!0}),Object.defineProperties(this,{color:{enumerable:!0,get:function(){return this.uniforms.diffuse.value},set:function(t){this.uniforms.diffuse.value=t}},worldUnits:{enumerable:!0,get:function(){return"WORLD_UNITS"in this.defines},set:function(t){!0===t?this.defines.WORLD_UNITS="":delete this.defines.WORLD_UNITS}},linewidth:{enumerable:!0,get:function(){return this.uniforms.linewidth.value},set:function(t){this.uniforms.linewidth.value=t}},dashed:{enumerable:!0,get:function(){return Boolean("USE_DASH"in this.defines)},set(t){Boolean(t)!==Boolean("USE_DASH"in this.defines)&&(this.needsUpdate=!0),!0===t?this.defines.USE_DASH="":delete this.defines.USE_DASH}},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)}},alphaToCoverage:{enumerable:!0,get:function(){return Boolean("ALPHA_TO_COVERAGE"in this.defines)},set:function(t){Boolean(t)!==Boolean("ALPHA_TO_COVERAGE"in this.defines)&&(this.needsUpdate=!0),!0===t?(this.defines.ALPHA_TO_COVERAGE="",this.extensions.derivatives=!0):(delete this.defines.ALPHA_TO_COVERAGE,this.extensions.derivatives=!1)}}}),this.setValues(t)}}d.prototype.isLineMaterial=!0;const l=window.THREE?window.THREE:{Box3:e.Box3,BufferGeometry:e.BufferGeometry,InstancedInterleavedBuffer:e.InstancedInterleavedBuffer,InterleavedBufferAttribute:e.InterleavedBufferAttribute,Line3:e.Line3,MathUtils:e.MathUtils,Matrix4:e.Matrix4,Mesh:e.Mesh,Sphere:e.Sphere,Vector3:e.Vector3,Vector4:e.Vector4};var c=(new l.BufferGeometry).setAttribute?"setAttribute":"addAttribute";const f=new l.Vector3,u=new l.Vector3,p=new l.Vector4,m=new l.Vector4,h=new l.Vector4,v=new l.Vector3,y=new l.Matrix4,g=new l.Line3,x=new l.Vector3,w=new l.Box3,S=new l.Sphere,b=new l.Vector4;class E extends l.Mesh{constructor(t=new a,e=new d({color:16777215*Math.random()})){super(t,e),this.type="LineSegments2"}computeLineDistances(){const t=this.geometry,e=t.attributes.instanceStart,n=t.attributes.instanceEnd,i=new Float32Array(2*e.count);for(let t=0,r=0,o=e.count;t<o;t++,r+=2)f.fromBufferAttribute(e,t),u.fromBufferAttribute(n,t),i[r]=0===r?0:i[r-1],i[r+1]=i[r]+f.distanceTo(u);const r=new l.InstancedInterleavedBuffer(i,2,1);return t[c]("instanceDistanceStart",new l.InterleavedBufferAttribute(r,1,0)),t[c]("instanceDistanceEnd",new l.InterleavedBufferAttribute(r,1,1)),this}raycast(t,e){null===t.camera&&console.error('LineSegments2: "Raycaster.camera" needs to be set in order to raycast against LineSegments2.');const n=void 0!==t.params.Line2&&t.params.Line2.threshold||0,i=t.ray,r=t.camera,o=r.projectionMatrix,a=this.matrixWorld,s=this.geometry,d=this.material,c=d.resolution,f=d.linewidth+n,u=s.attributes.instanceStart,E=s.attributes.instanceEnd,B=-r.near,A=2*Math.max(f/c.width,f/c.height);null===s.boundingSphere&&s.computeBoundingSphere(),S.copy(s.boundingSphere).applyMatrix4(a);const L=Math.max(r.near,S.distanceToPoint(i.origin));b.set(0,0,-L,1).applyMatrix4(r.projectionMatrix),b.multiplyScalar(1/b.w),b.applyMatrix4(r.projectionMatrixInverse);const _=.5*Math.abs(A/b.w);if(S.radius+=_,!1===t.ray.intersectsSphere(S))return;null===s.boundingBox&&s.computeBoundingBox(),w.copy(s.boundingBox).applyMatrix4(a);const M=Math.max(r.near,w.distanceToPoint(i.origin));b.set(0,0,-M,1).applyMatrix4(r.projectionMatrix),b.multiplyScalar(1/b.w),b.applyMatrix4(r.projectionMatrixInverse);const z=.5*Math.abs(A/b.w);if(w.max.x+=z,w.max.y+=z,w.max.z+=z,w.min.x-=z,w.min.y-=z,w.min.z-=z,!1!==t.ray.intersectsBox(w)){i.at(1,h),h.w=1,h.applyMatrix4(r.matrixWorldInverse),h.applyMatrix4(o),h.multiplyScalar(1/h.w),h.x*=c.x/2,h.y*=c.y/2,h.z=0,v.copy(h),y.multiplyMatrices(r.matrixWorldInverse,a);for(let t=0,n=u.count;t<n;t++){if(p.fromBufferAttribute(u,t),m.fromBufferAttribute(E,t),p.w=1,m.w=1,p.applyMatrix4(y),m.applyMatrix4(y),p.z>B&&m.z>B)continue;if(p.z>B){const t=p.z-m.z,e=(p.z-B)/t;p.lerp(m,e)}else if(m.z>B){const t=m.z-p.z,e=(m.z-B)/t;m.lerp(p,e)}p.applyMatrix4(o),m.applyMatrix4(o),p.multiplyScalar(1/p.w),m.multiplyScalar(1/m.w),p.x*=c.x/2,p.y*=c.y/2,m.x*=c.x/2,m.y*=c.y/2,g.start.copy(p),g.start.z=0,g.end.copy(m),g.end.z=0;const n=g.closestPointToPointParameter(v,!0);g.at(n,x);const r=l.MathUtils.lerp(p.z,m.z,n),s=r>=-1&&r<=1,d=v.distanceTo(x)<.5*f;if(s&&d){g.start.fromBufferAttribute(u,t),g.end.fromBufferAttribute(E,t),g.start.applyMatrix4(a),g.end.applyMatrix4(a);const n=new l.Vector3,r=new l.Vector3;i.distanceSqToSegment(g.start,g.end,r,n),e.push({point:r,pointOnLine:n,distance:i.origin.distanceTo(r),object:this,face:null,faceIndex:t,uv:null,uv2:null})}}}}}E.prototype.LineSegments2=!0;class B extends a{constructor(){super(),this.type="LineGeometry"}setPositions(t){for(var e=t.length-3,n=new Float32Array(2*e),i=0;i<e;i+=3)n[2*i]=t[i],n[2*i+1]=t[i+1],n[2*i+2]=t[i+2],n[2*i+3]=t[i+3],n[2*i+4]=t[i+4],n[2*i+5]=t[i+5];return super.setPositions(n),this}setColors(t){for(var e=t.length-3,n=new Float32Array(2*e),i=0;i<e;i+=3)n[2*i]=t[i],n[2*i+1]=t[i+1],n[2*i+2]=t[i+2],n[2*i+3]=t[i+3],n[2*i+4]=t[i+4],n[2*i+5]=t[i+5];return super.setColors(n),this}fromLine(t){var e=t.geometry;if(!e.isGeometry)return e.isBufferGeometry&&this.setPositions(e.attributes.position.array),this;console.error("THREE.LineGeometry no longer supports Geometry. Use THREE.BufferGeometry instead.")}}B.prototype.isLineGeometry=!0;class A extends E{constructor(t=new B,e=new d({color:16777215*Math.random()})){super(t,e),this.type="Line2"}}A.prototype.isLine2=!0,t.Line2=A,t.LineGeometry=B,t.LineMaterial=d,t.LineSegments2=E,t.LineSegmentsGeometry=a,Object.defineProperty(t,"__esModule",{value:!0})})); |
@@ -1,2 +0,2 @@ | ||
import { Box3, BufferGeometry, Float32BufferAttribute, InstancedBufferGeometry, InstancedInterleavedBuffer, InterleavedBufferAttribute, Sphere, Vector3, WireframeGeometry, Vector2, ShaderLib, ShaderMaterial, UniformsLib, UniformsUtils, Line3, MathUtils, Matrix4, Mesh, Vector4 } from 'three'; | ||
import { Box3, BufferGeometry, Float32BufferAttribute, InstancedBufferGeometry, InstancedInterleavedBuffer, InterleavedBufferAttribute, Sphere, Vector3, WireframeGeometry, ShaderLib, ShaderMaterial, UniformsLib, UniformsUtils, Vector2, Line3, MathUtils, Matrix4, Mesh, Vector4 } from 'three'; | ||
@@ -110,3 +110,3 @@ const THREE$2 = window.THREE ? window.THREE // Prefer consumption from global THREE, if exists | ||
romLineSegments(lineSegments) { | ||
fromLineSegments(lineSegments) { | ||
const geometry = lineSegments.geometry; | ||
@@ -196,3 +196,2 @@ | ||
* dashSize: <float>, | ||
* dashOffset: <float>, | ||
* gapSize: <float>, | ||
@@ -211,2 +210,5 @@ * resolution: <Vector2>, // to be set by renderer | ||
THREE$1.UniformsLib.line = { | ||
worldUnits: { | ||
value: 1 | ||
}, | ||
linewidth: { | ||
@@ -216,3 +218,3 @@ value: 1 | ||
resolution: { | ||
value: new Vector2(1, 1) | ||
value: new THREE$1.Vector2(1, 1) | ||
}, | ||
@@ -225,16 +227,12 @@ dashScale: { | ||
}, | ||
dashOffset: { | ||
value: 0 | ||
}, | ||
gapSize: { | ||
value: 1 | ||
}, | ||
// todo FIX - maybe change to totalSize | ||
opacity: { | ||
value: 1 | ||
} | ||
} // todo FIX - maybe change to totalSize | ||
}; | ||
THREE$1.ShaderLib['line'] = { | ||
uniforms: THREE$1.UniformsUtils.merge([THREE$1.UniformsLib.common, THREE$1.UniformsLib.fog, THREE$1.UniformsLib.line]), | ||
vertexShader: ` | ||
vertexShader: | ||
/* glsl */ | ||
` | ||
#include <common> | ||
@@ -256,2 +254,5 @@ #include <color_pars_vertex> | ||
varying vec2 vUv; | ||
varying vec4 worldPos; | ||
varying vec3 worldStart; | ||
varying vec3 worldEnd; | ||
@@ -304,2 +305,5 @@ #ifdef USE_DASH | ||
worldStart = start.xyz; | ||
worldEnd = end.xyz; | ||
// special case for perspective projection, and segments that terminate either in, or behind, the camera plane | ||
@@ -331,7 +335,7 @@ // clearly the gpu firmware has a way of addressing this issue when projecting into ndc space | ||
// ndc space | ||
vec2 ndcStart = clipStart.xy / clipStart.w; | ||
vec2 ndcEnd = clipEnd.xy / clipEnd.w; | ||
vec3 ndcStart = clipStart.xyz / clipStart.w; | ||
vec3 ndcEnd = clipEnd.xyz / clipEnd.w; | ||
// direction | ||
vec2 dir = ndcEnd - ndcStart; | ||
vec2 dir = ndcEnd.xy - ndcStart.xy; | ||
@@ -342,5 +346,61 @@ // account for clip-space aspect ratio | ||
// perpendicular to dir | ||
#ifdef WORLD_UNITS | ||
// get the offset direction as perpendicular to the view vector | ||
vec3 worldDir = normalize( end.xyz - start.xyz ); | ||
vec3 offset; | ||
if ( position.y < 0.5 ) { | ||
offset = normalize( cross( start.xyz, worldDir ) ); | ||
} else { | ||
offset = normalize( cross( end.xyz, worldDir ) ); | ||
} | ||
// sign flip | ||
if ( position.x < 0.0 ) offset *= - 1.0; | ||
float forwardOffset = dot( worldDir, vec3( 0.0, 0.0, 1.0 ) ); | ||
// don't extend the line if we're rendering dashes because we | ||
// won't be rendering the endcaps | ||
#ifndef USE_DASH | ||
// extend the line bounds to encompass endcaps | ||
start.xyz += - worldDir * linewidth * 0.5; | ||
end.xyz += worldDir * linewidth * 0.5; | ||
// shift the position of the quad so it hugs the forward edge of the line | ||
offset.xy -= dir * forwardOffset; | ||
offset.z += 0.5; | ||
#endif | ||
// endcaps | ||
if ( position.y > 1.0 || position.y < 0.0 ) { | ||
offset.xy += dir * 2.0 * forwardOffset; | ||
} | ||
// adjust for linewidth | ||
offset *= linewidth * 0.5; | ||
// set the world position | ||
worldPos = ( position.y < 0.5 ) ? start : end; | ||
worldPos.xyz += offset; | ||
// project the worldpos | ||
vec4 clip = projectionMatrix * worldPos; | ||
// shift the depth of the projected points so the line | ||
// segements overlap neatly | ||
vec3 clipPose = ( position.y < 0.5 ) ? ndcStart : ndcEnd; | ||
clip.z = clipPose.z * clip.w; | ||
#else | ||
vec2 offset = vec2( dir.y, - dir.x ); | ||
// undo aspect ratio adjustment | ||
@@ -378,2 +438,4 @@ dir.x /= aspect; | ||
#endif | ||
gl_Position = clip; | ||
@@ -389,5 +451,8 @@ | ||
`, | ||
fragmentShader: ` | ||
fragmentShader: | ||
/* glsl */ | ||
` | ||
uniform vec3 diffuse; | ||
uniform float opacity; | ||
uniform float linewidth; | ||
@@ -397,3 +462,2 @@ #ifdef USE_DASH | ||
uniform float dashSize; | ||
uniform float dashOffset; | ||
uniform float gapSize; | ||
@@ -404,2 +468,5 @@ | ||
varying float vLineDistance; | ||
varying vec4 worldPos; | ||
varying vec3 worldStart; | ||
varying vec3 worldEnd; | ||
@@ -414,2 +481,31 @@ #include <common> | ||
vec2 closestLineToLine(vec3 p1, vec3 p2, vec3 p3, vec3 p4) { | ||
float mua; | ||
float mub; | ||
vec3 p13 = p1 - p3; | ||
vec3 p43 = p4 - p3; | ||
vec3 p21 = p2 - p1; | ||
float d1343 = dot( p13, p43 ); | ||
float d4321 = dot( p43, p21 ); | ||
float d1321 = dot( p13, p21 ); | ||
float d4343 = dot( p43, p43 ); | ||
float d2121 = dot( p21, p21 ); | ||
float denom = d2121 * d4343 - d4321 * d4321; | ||
float numer = d1343 * d4321 - d1321 * d4343; | ||
mua = numer / denom; | ||
mua = clamp( mua, 0.0, 1.0 ); | ||
mub = ( d1343 + d4321 * ( mua ) ) / d4343; | ||
mub = clamp( mub, 0.0, 1.0 ); | ||
return vec2( mua, mub ); | ||
} | ||
void main() { | ||
@@ -423,6 +519,58 @@ | ||
if ( mod( vLineDistance + dashOffset, dashSize + gapSize ) > dashSize ) discard; // todo - FIX | ||
if ( mod( vLineDistance, dashSize + gapSize ) > dashSize ) discard; // todo - FIX | ||
#endif | ||
float alpha = opacity; | ||
#ifdef WORLD_UNITS | ||
// Find the closest points on the view ray and the line segment | ||
vec3 rayEnd = normalize( worldPos.xyz ) * 1e5; | ||
vec3 lineDir = worldEnd - worldStart; | ||
vec2 params = closestLineToLine( worldStart, worldEnd, vec3( 0.0, 0.0, 0.0 ), rayEnd ); | ||
vec3 p1 = worldStart + lineDir * params.x; | ||
vec3 p2 = rayEnd * params.y; | ||
vec3 delta = p1 - p2; | ||
float len = length( delta ); | ||
float norm = len / linewidth; | ||
#ifndef USE_DASH | ||
#ifdef ALPHA_TO_COVERAGE | ||
float dnorm = fwidth( norm ); | ||
alpha = 1.0 - smoothstep( 0.5 - dnorm, 0.5 + dnorm, norm ); | ||
#else | ||
if ( norm > 0.5 ) { | ||
discard; | ||
} | ||
#endif | ||
#endif | ||
#else | ||
#ifdef ALPHA_TO_COVERAGE | ||
// artifacts appear on some hardware if a derivative is taken within a conditional | ||
float a = vUv.x; | ||
float b = ( vUv.y > 0.0 ) ? vUv.y - 1.0 : vUv.y + 1.0; | ||
float len2 = a * a + b * b; | ||
float dlen = fwidth( len2 ); | ||
if ( abs( vUv.y ) > 1.0 ) { | ||
alpha = 1.0 - smoothstep( 1.0 - dlen, 1.0 + dlen, len2 ); | ||
} | ||
#else | ||
if ( abs( vUv.y ) > 1.0 ) { | ||
@@ -438,8 +586,12 @@ | ||
vec4 diffuseColor = vec4( diffuse, opacity ); | ||
#endif | ||
#endif | ||
vec4 diffuseColor = vec4( diffuse, alpha ); | ||
#include <logdepthbuf_fragment> | ||
#include <color_fragment> | ||
gl_FragColor = vec4( diffuseColor.rgb, diffuseColor.a ); | ||
gl_FragColor = vec4( diffuseColor.rgb, alpha ); | ||
@@ -465,3 +617,2 @@ #include <tonemapping_fragment> | ||
}); | ||
this.dashed = false; | ||
Object.defineProperties(this, { | ||
@@ -477,2 +628,15 @@ color: { | ||
}, | ||
worldUnits: { | ||
enumerable: true, | ||
get: function () { | ||
return 'WORLD_UNITS' in this.defines; | ||
}, | ||
set: function (value) { | ||
if (value === true) { | ||
this.defines.WORLD_UNITS = ''; | ||
} else { | ||
delete this.defines.WORLD_UNITS; | ||
} | ||
} | ||
}, | ||
linewidth: { | ||
@@ -487,2 +651,21 @@ enumerable: true, | ||
}, | ||
dashed: { | ||
enumerable: true, | ||
get: function () { | ||
return Boolean('USE_DASH' in this.defines); | ||
}, | ||
set(value) { | ||
if (Boolean(value) !== Boolean('USE_DASH' in this.defines)) { | ||
this.needsUpdate = true; | ||
} | ||
if (value === true) { | ||
this.defines.USE_DASH = ''; | ||
} else { | ||
delete this.defines.USE_DASH; | ||
} | ||
} | ||
}, | ||
dashScale: { | ||
@@ -552,3 +735,3 @@ enumerable: true, | ||
if (value) { | ||
if (value === true) { | ||
this.defines.ALPHA_TO_COVERAGE = ''; | ||
@@ -746,4 +929,4 @@ this.extensions.derivatives = true; | ||
_start.w = 1; | ||
_end.w = 1; // camera space | ||
_start4.w = 1; | ||
_end4.w = 1; // camera space | ||
@@ -883,3 +1066,3 @@ _start4.applyMatrix4(_mvMatrix); | ||
if (geometry.isGeometry) { | ||
console.error('LineGeometry no longer supports Geometry. Use THREE.BufferGeometry instead.'); | ||
console.error('THREE.LineGeometry no longer supports Geometry. Use THREE.BufferGeometry instead.'); | ||
return; | ||
@@ -894,7 +1077,2 @@ } else if (geometry.isBufferGeometry) { | ||
copy() { | ||
// todo | ||
return this; | ||
} | ||
} | ||
@@ -901,0 +1079,0 @@ |
{ | ||
"name": "three-fatline", | ||
"version": "0.5.0", | ||
"version": "0.5.1", | ||
"description": "A ThreeJS Line object with variable width", | ||
@@ -42,16 +42,16 @@ "unpkg": "dist/three-fatline.min.js", | ||
"devDependencies": { | ||
"@babel/core": "^7.13.16", | ||
"@babel/plugin-proposal-class-properties": "^7.13.0", | ||
"@babel/plugin-proposal-object-rest-spread": "^7.13.8", | ||
"@babel/preset-env": "^7.13.15", | ||
"@babel/core": "^7.15.8", | ||
"@babel/plugin-proposal-class-properties": "^7.14.5", | ||
"@babel/plugin-proposal-object-rest-spread": "^7.15.6", | ||
"@babel/preset-env": "^7.15.8", | ||
"@rollup/plugin-babel": "^5.3.0", | ||
"@rollup/plugin-commonjs": "^18.0.0", | ||
"@rollup/plugin-node-resolve": "^11.2.1", | ||
"@rollup/plugin-commonjs": "^21.0.0", | ||
"@rollup/plugin-node-resolve": "^13.0.5", | ||
"@types/three": ">=0.84.0", | ||
"rimraf": "^3.0.2", | ||
"rollup": "^2.45.2", | ||
"rollup-plugin-dts": "^3.0.1", | ||
"rollup": "^2.58.0", | ||
"rollup-plugin-dts": "^4.0.0", | ||
"rollup-plugin-terser": "^7.0.2", | ||
"typescript": "^4.2.4" | ||
"typescript": "^4.4.4" | ||
} | ||
} |
Sorry, the diff of this file is not supported yet
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
Found 1 instance in 1 package
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
Found 1 instance in 1 package
179553
2477