three-fatline
Advanced tools
Comparing version 0.4.2 to 0.4.3
@@ -7,7 +7,3 @@ 'use strict'; | ||
/** | ||
* @author WestLangley / http://github.com/WestLangley | ||
* | ||
*/ | ||
const THREE = window.THREE ? window.THREE // Prefer consumption from global THREE, if exists | ||
const THREE$2 = window.THREE ? window.THREE // Prefer consumption from global THREE, if exists | ||
: { | ||
@@ -25,30 +21,28 @@ Box3: three.Box3, | ||
var setAttributeFn = new THREE.BufferGeometry().setAttribute ? 'setAttribute' : 'addAttribute'; | ||
var setAttributeFn$1 = new THREE$2.BufferGeometry().setAttribute ? 'setAttribute' : 'addAttribute'; | ||
var LineSegmentsGeometry = function () { | ||
THREE.InstancedBufferGeometry.call(this); | ||
this.type = 'LineSegmentsGeometry'; | ||
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[setAttributeFn]('position', new THREE.Float32BufferAttribute(positions, 3)); | ||
this[setAttributeFn]('uv', new THREE.Float32BufferAttribute(uvs, 2)); | ||
}; | ||
const _box$1 = new THREE$2.Box3(); | ||
LineSegmentsGeometry.prototype = Object.assign(Object.create(THREE.InstancedBufferGeometry.prototype), { | ||
constructor: LineSegmentsGeometry, | ||
isLineSegmentsGeometry: true, | ||
applyMatrix: function (matrix) { | ||
console.warn('THREE.LineSegmentsGeometry: applyMatrix() has been renamed to applyMatrix4().'); | ||
return this.applyMatrix4(matrix); | ||
}, | ||
applyMatrix4: function (matrix) { | ||
var start = this.attributes.instanceStart; | ||
var end = this.attributes.instanceEnd; | ||
const _vector = new THREE$2.Vector3(); | ||
class LineSegmentsGeometry extends THREE$2.InstancedBufferGeometry { | ||
constructor() { | ||
super(); | ||
this.type = 'LineSegmentsGeometry'; | ||
const 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]; | ||
const uvs = [-1, 2, 1, 2, -1, 1, 1, 1, -1, -1, 1, -1, -1, -2, 1, -2]; | ||
const index = [0, 2, 1, 2, 3, 1, 2, 4, 3, 4, 5, 3, 4, 6, 5, 6, 7, 5]; | ||
this.setIndex(index); | ||
this[setAttributeFn$1]('position', new THREE$2.Float32BufferAttribute(positions, 3)); | ||
this[setAttributeFn$1]('uv', new THREE$2.Float32BufferAttribute(uvs, 2)); | ||
} | ||
applyMatrix4(matrix) { | ||
const start = this.attributes.instanceStart; | ||
const end = this.attributes.instanceEnd; | ||
if (start !== undefined) { | ||
matrix.applyToBufferAttribute(start); | ||
matrix.applyToBufferAttribute(end); | ||
start.data.needsUpdate = true; | ||
start.applyMatrix4(matrix); | ||
end.applyMatrix4(matrix); | ||
start.needsUpdate = true; | ||
} | ||
@@ -65,6 +59,7 @@ | ||
return this; | ||
}, | ||
setPositions: function (array) { | ||
var lineSegments; | ||
} | ||
setPositions(array) { | ||
let lineSegments; | ||
if (array instanceof Float32Array) { | ||
@@ -76,7 +71,7 @@ lineSegments = array; | ||
var instanceBuffer = new THREE.InstancedInterleavedBuffer(lineSegments, 6, 1); // xyz, xyz | ||
const instanceBuffer = new THREE$2.InstancedInterleavedBuffer(lineSegments, 6, 1); // xyz, xyz | ||
this[setAttributeFn]('instanceStart', new THREE.InterleavedBufferAttribute(instanceBuffer, 3, 0)); // xyz | ||
this[setAttributeFn$1]('instanceStart', new THREE$2.InterleavedBufferAttribute(instanceBuffer, 3, 0)); // xyz | ||
this[setAttributeFn]('instanceEnd', new THREE.InterleavedBufferAttribute(instanceBuffer, 3, 3)); // xyz | ||
this[setAttributeFn$1]('instanceEnd', new THREE$2.InterleavedBufferAttribute(instanceBuffer, 3, 3)); // xyz | ||
// | ||
@@ -87,6 +82,7 @@ | ||
return this; | ||
}, | ||
setColors: function (array) { | ||
var colors; | ||
} | ||
setColors(array) { | ||
let colors; | ||
if (array instanceof Float32Array) { | ||
@@ -98,30 +94,35 @@ colors = array; | ||
var instanceColorBuffer = new THREE.InstancedInterleavedBuffer(colors, 6, 1); // rgb, rgb | ||
const instanceColorBuffer = new THREE$2.InstancedInterleavedBuffer(colors, 6, 1); // rgb, rgb | ||
this[setAttributeFn]('instanceColorStart', new THREE.InterleavedBufferAttribute(instanceColorBuffer, 3, 0)); // rgb | ||
this[setAttributeFn$1]('instanceColorStart', new THREE$2.InterleavedBufferAttribute(instanceColorBuffer, 3, 0)); // rgb | ||
this[setAttributeFn]('instanceColorEnd', new THREE.InterleavedBufferAttribute(instanceColorBuffer, 3, 3)); // rgb | ||
this[setAttributeFn$1]('instanceColorEnd', new THREE$2.InterleavedBufferAttribute(instanceColorBuffer, 3, 3)); // rgb | ||
return this; | ||
}, | ||
fromWireframeGeometry: function (geometry) { | ||
} | ||
fromWireframeGeometry(geometry) { | ||
this.setPositions(geometry.attributes.position.array); | ||
return this; | ||
}, | ||
fromEdgesGeometry: function (geometry) { | ||
} | ||
fromEdgesGeometry(geometry) { | ||
this.setPositions(geometry.attributes.position.array); | ||
return this; | ||
}, | ||
fromMesh: function (mesh) { | ||
this.fromWireframeGeometry(new THREE.WireframeGeometry(mesh.geometry)); // set colors, maybe | ||
} | ||
fromMesh(mesh) { | ||
this.fromWireframeGeometry(new THREE$2.WireframeGeometry(mesh.geometry)); // set colors, maybe | ||
return this; | ||
}, | ||
fromLineSegements: function (lineSegments) { | ||
var geometry = lineSegments.geometry; | ||
} | ||
romLineSegments(lineSegments) { | ||
const geometry = lineSegments.geometry; | ||
if (geometry.isGeometry) { | ||
this.setPositions(geometry.vertices); | ||
console.error('LineSegmentsGeometry no longer supports Geometry. Use THREE.BufferGeometry instead.'); | ||
return; | ||
} else if (geometry.isBufferGeometry) { | ||
this.setPositions(geometry.position.array); // assumes non-indexed | ||
this.setPositions(geometry.attributes.position.array); // assumes non-indexed | ||
} // set colors, maybe | ||
@@ -131,69 +132,69 @@ | ||
return this; | ||
}, | ||
computeBoundingBox: function () { | ||
var box = new THREE.Box3(); | ||
return function computeBoundingBox() { | ||
if (this.boundingBox === null) { | ||
this.boundingBox = new THREE.Box3(); | ||
} | ||
} | ||
var start = this.attributes.instanceStart; | ||
var end = this.attributes.instanceEnd; | ||
computeBoundingBox() { | ||
if (this.boundingBox === null) { | ||
this.boundingBox = new THREE$2.Box3(); | ||
} | ||
if (start !== undefined && end !== undefined) { | ||
this.boundingBox.setFromBufferAttribute(start); | ||
box.setFromBufferAttribute(end); | ||
this.boundingBox.union(box); | ||
} | ||
}; | ||
}(), | ||
computeBoundingSphere: function () { | ||
var vector = new THREE.Vector3(); | ||
return function computeBoundingSphere() { | ||
if (this.boundingSphere === null) { | ||
this.boundingSphere = new THREE.Sphere(); | ||
} | ||
const start = this.attributes.instanceStart; | ||
const end = this.attributes.instanceEnd; | ||
if (this.boundingBox === null) { | ||
this.computeBoundingBox(); | ||
} | ||
if (start !== undefined && end !== undefined) { | ||
this.boundingBox.setFromBufferAttribute(start); | ||
var start = this.attributes.instanceStart; | ||
var end = this.attributes.instanceEnd; | ||
_box$1.setFromBufferAttribute(end); | ||
if (start !== undefined && end !== undefined) { | ||
var center = this.boundingSphere.center; | ||
this.boundingBox.getCenter(center); | ||
var maxRadiusSq = 0; | ||
this.boundingBox.union(_box$1); | ||
} | ||
} | ||
for (var i = 0, il = start.count; i < il; i++) { | ||
vector.fromBufferAttribute(start, i); | ||
maxRadiusSq = Math.max(maxRadiusSq, center.distanceToSquared(vector)); | ||
vector.fromBufferAttribute(end, i); | ||
maxRadiusSq = Math.max(maxRadiusSq, center.distanceToSquared(vector)); | ||
} | ||
computeBoundingSphere() { | ||
if (this.boundingSphere === null) { | ||
this.boundingSphere = new THREE$2.Sphere(); | ||
} | ||
this.boundingSphere.radius = Math.sqrt(maxRadiusSq); | ||
if (this.boundingBox === null) { | ||
this.computeBoundingBox(); | ||
} | ||
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); | ||
} | ||
const start = this.attributes.instanceStart; | ||
const end = this.attributes.instanceEnd; | ||
if (start !== undefined && end !== undefined) { | ||
const center = this.boundingSphere.center; | ||
this.boundingBox.getCenter(center); | ||
let maxRadiusSq = 0; | ||
for (let i = 0, il = start.count; i < il; i++) { | ||
_vector.fromBufferAttribute(start, i); | ||
maxRadiusSq = Math.max(maxRadiusSq, center.distanceToSquared(_vector)); | ||
_vector.fromBufferAttribute(end, i); | ||
maxRadiusSq = Math.max(maxRadiusSq, center.distanceToSquared(_vector)); | ||
} | ||
}; | ||
}(), | ||
toJSON: function () {// todo | ||
}, | ||
clone: function () {// todo | ||
}, | ||
copy: function () | ||
/* source */ | ||
{ | ||
// todo | ||
return this; | ||
this.boundingSphere.radius = Math.sqrt(maxRadiusSq); | ||
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); | ||
} | ||
} | ||
} | ||
}); | ||
toJSON() {// todo | ||
} | ||
applyMatrix(matrix) { | ||
console.warn('THREE.LineSegmentsGeometry: applyMatrix() has been renamed to applyMatrix4().'); | ||
return this.applyMatrix4(matrix); | ||
} | ||
} | ||
LineSegmentsGeometry.prototype.isLineSegmentsGeometry = true; | ||
/** | ||
* @author WestLangley / http://github.com/WestLangley | ||
* | ||
* parameters = { | ||
@@ -449,108 +450,116 @@ * color: <hex>, | ||
var LineMaterial = function (parameters) { | ||
THREE$1.ShaderMaterial.call(this, { | ||
type: 'LineMaterial', | ||
uniforms: THREE$1.UniformsUtils.clone(THREE$1.ShaderLib['line'].uniforms), | ||
vertexShader: THREE$1.ShaderLib['line'].vertexShader, | ||
fragmentShader: THREE$1.ShaderLib['line'].fragmentShader, | ||
clipping: true // required for clipping support | ||
class LineMaterial extends THREE$1.ShaderMaterial { | ||
constructor(parameters) { | ||
super({ | ||
type: 'LineMaterial', | ||
uniforms: THREE$1.UniformsUtils.clone(THREE$1.ShaderLib['line'].uniforms), | ||
vertexShader: THREE$1.ShaderLib['line'].vertexShader, | ||
fragmentShader: THREE$1.ShaderLib['line'].fragmentShader, | ||
clipping: true // required for clipping support | ||
}); | ||
this.dashed = false; | ||
Object.defineProperties(this, { | ||
color: { | ||
enumerable: true, | ||
get: function () { | ||
return this.uniforms.diffuse.value; | ||
}); | ||
this.dashed = false; | ||
Object.defineProperties(this, { | ||
color: { | ||
enumerable: true, | ||
get: function () { | ||
return this.uniforms.diffuse.value; | ||
}, | ||
set: function (value) { | ||
this.uniforms.diffuse.value = value; | ||
} | ||
}, | ||
set: function (value) { | ||
this.uniforms.diffuse.value = value; | ||
} | ||
}, | ||
linewidth: { | ||
enumerable: true, | ||
get: function () { | ||
return this.uniforms.linewidth.value; | ||
linewidth: { | ||
enumerable: true, | ||
get: function () { | ||
return this.uniforms.linewidth.value; | ||
}, | ||
set: function (value) { | ||
this.uniforms.linewidth.value = value; | ||
} | ||
}, | ||
set: function (value) { | ||
this.uniforms.linewidth.value = value; | ||
} | ||
}, | ||
dashScale: { | ||
enumerable: true, | ||
get: function () { | ||
return this.uniforms.dashScale.value; | ||
dashScale: { | ||
enumerable: true, | ||
get: function () { | ||
return this.uniforms.dashScale.value; | ||
}, | ||
set: function (value) { | ||
this.uniforms.dashScale.value = value; | ||
} | ||
}, | ||
set: function (value) { | ||
this.uniforms.dashScale.value = value; | ||
} | ||
}, | ||
dashSize: { | ||
enumerable: true, | ||
get: function () { | ||
return this.uniforms.dashSize.value; | ||
dashSize: { | ||
enumerable: true, | ||
get: function () { | ||
return this.uniforms.dashSize.value; | ||
}, | ||
set: function (value) { | ||
this.uniforms.dashSize.value = value; | ||
} | ||
}, | ||
set: function (value) { | ||
this.uniforms.dashSize.value = value; | ||
} | ||
}, | ||
dashOffset: { | ||
enumerable: true, | ||
get: function () { | ||
return this.uniforms.dashOffset.value; | ||
dashOffset: { | ||
enumerable: true, | ||
get: function () { | ||
return this.uniforms.dashOffset.value; | ||
}, | ||
set: function (value) { | ||
this.uniforms.dashOffset.value = value; | ||
} | ||
}, | ||
set: function (value) { | ||
this.uniforms.dashOffset.value = value; | ||
} | ||
}, | ||
gapSize: { | ||
enumerable: true, | ||
get: function () { | ||
return this.uniforms.gapSize.value; | ||
gapSize: { | ||
enumerable: true, | ||
get: function () { | ||
return this.uniforms.gapSize.value; | ||
}, | ||
set: function (value) { | ||
this.uniforms.gapSize.value = value; | ||
} | ||
}, | ||
set: function (value) { | ||
this.uniforms.gapSize.value = value; | ||
} | ||
}, | ||
opacity: { | ||
enumerable: true, | ||
get: function () { | ||
return this.uniforms.opacity.value; | ||
opacity: { | ||
enumerable: true, | ||
get: function () { | ||
return this.uniforms.opacity.value; | ||
}, | ||
set: function (value) { | ||
this.uniforms.opacity.value = value; | ||
} | ||
}, | ||
set: function (value) { | ||
this.uniforms.opacity.value = value; | ||
} | ||
}, | ||
resolution: { | ||
enumerable: true, | ||
get: function () { | ||
return this.uniforms.resolution.value; | ||
resolution: { | ||
enumerable: true, | ||
get: function () { | ||
return this.uniforms.resolution.value; | ||
}, | ||
set: function (value) { | ||
this.uniforms.resolution.value.copy(value); | ||
} | ||
}, | ||
set: function (value) { | ||
this.uniforms.resolution.value.copy(value); | ||
alphaToCoverage: { | ||
enumerable: true, | ||
get: function () { | ||
return Boolean('ALPHA_TO_COVERAGE' in this.defines); | ||
}, | ||
set: function (value) { | ||
if (Boolean(value) !== Boolean('ALPHA_TO_COVERAGE' in this.defines)) { | ||
this.needsUpdate = true; | ||
} | ||
if (value) { | ||
this.defines.ALPHA_TO_COVERAGE = ''; | ||
this.extensions.derivatives = true; | ||
} else { | ||
delete this.defines.ALPHA_TO_COVERAGE; | ||
this.extensions.derivatives = false; | ||
} | ||
} | ||
} | ||
} | ||
}); | ||
this.setValues(parameters); | ||
}; | ||
}); | ||
this.setValues(parameters); | ||
} | ||
LineMaterial.prototype = Object.create(THREE$1.ShaderMaterial.prototype); | ||
LineMaterial.prototype.constructor = LineMaterial; | ||
} | ||
LineMaterial.prototype.isLineMaterial = true; | ||
LineMaterial.prototype.copy = function (source) { | ||
THREE$1.ShaderMaterial.prototype.copy.call(this, source); | ||
this.color.copy(source.color); | ||
this.linewidth = source.linewidth; | ||
this.resolution = source.resolution; // todo | ||
return this; | ||
}; | ||
/** | ||
* @author WestLangley / http://github.com/WestLangley | ||
* | ||
*/ | ||
const THREE$2 = window.THREE ? window.THREE // Prefer consumption from global THREE, if exists | ||
const THREE = window.THREE ? window.THREE // Prefer consumption from global THREE, if exists | ||
: { | ||
Box3: three.Box3, | ||
BufferGeometry: three.BufferGeometry, | ||
@@ -563,2 +572,3 @@ InstancedInterleavedBuffer: three.InstancedInterleavedBuffer, | ||
Mesh: three.Mesh, | ||
Sphere: three.Sphere, | ||
Vector3: three.Vector3, | ||
@@ -568,160 +578,260 @@ Vector4: three.Vector4 | ||
var setAttributeFn$1 = new THREE$2.BufferGeometry().setAttribute ? 'setAttribute' : 'addAttribute'; | ||
var setAttributeFn = new THREE.BufferGeometry().setAttribute ? 'setAttribute' : 'addAttribute'; | ||
var LineSegments2 = function (geometry, material) { | ||
if (geometry === undefined) geometry = new LineSegmentsGeometry(); | ||
if (material === undefined) material = new LineMaterial({ | ||
const _start = new THREE.Vector3(); | ||
const _end = new THREE.Vector3(); | ||
const _start4 = new THREE.Vector4(); | ||
const _end4 = new THREE.Vector4(); | ||
const _ssOrigin = new THREE.Vector4(); | ||
const _ssOrigin3 = new THREE.Vector3(); | ||
const _mvMatrix = new THREE.Matrix4(); | ||
const _line = new THREE.Line3(); | ||
const _closestPoint = new THREE.Vector3(); | ||
const _box = new THREE.Box3(); | ||
const _sphere = new THREE.Sphere(); | ||
const _clipToWorldVector = new THREE.Vector4(); | ||
class LineSegments2 extends THREE.Mesh { | ||
constructor(geometry = new LineSegmentsGeometry(), material = new LineMaterial({ | ||
color: Math.random() * 0xffffff | ||
}); | ||
THREE$2.Mesh.call(this, geometry, material); | ||
this.type = 'LineSegments2'; | ||
}; | ||
})) { | ||
super(geometry, material); | ||
this.type = 'LineSegments2'; | ||
} // for backwards-compatability, but could be a method of LineSegmentsGeometry... | ||
LineSegments2.prototype = Object.assign(Object.create(THREE$2.Mesh.prototype), { | ||
constructor: LineSegments2, | ||
isLineSegments2: true, | ||
computeLineDistances: function () { | ||
// for backwards-compatability, but could be a method of LineSegmentsGeometry... | ||
var start = new THREE$2.Vector3(); | ||
var end = new THREE$2.Vector3(); | ||
return function computeLineDistances() { | ||
var geometry = this.geometry; | ||
var instanceStart = geometry.attributes.instanceStart; | ||
var instanceEnd = geometry.attributes.instanceEnd; | ||
var lineDistances = new Float32Array(2 * instanceStart.data.count); | ||
for (var i = 0, j = 0, l = instanceStart.data.count; i < l; i++, j += 2) { | ||
start.fromBufferAttribute(instanceStart, i); | ||
end.fromBufferAttribute(instanceEnd, i); | ||
lineDistances[j] = j === 0 ? 0 : lineDistances[j - 1]; | ||
lineDistances[j + 1] = lineDistances[j] + start.distanceTo(end); | ||
} | ||
computeLineDistances() { | ||
const geometry = this.geometry; | ||
const instanceStart = geometry.attributes.instanceStart; | ||
const instanceEnd = geometry.attributes.instanceEnd; | ||
const lineDistances = new Float32Array(2 * instanceStart.count); | ||
var instanceDistanceBuffer = new THREE$2.InstancedInterleavedBuffer(lineDistances, 2, 1); // d0, d1 | ||
for (let i = 0, j = 0, l = instanceStart.count; i < l; i++, j += 2) { | ||
_start.fromBufferAttribute(instanceStart, i); | ||
geometry[setAttributeFn$1]('instanceDistanceStart', new THREE$2.InterleavedBufferAttribute(instanceDistanceBuffer, 1, 0)); // d0 | ||
_end.fromBufferAttribute(instanceEnd, i); | ||
geometry[setAttributeFn$1]('instanceDistanceEnd', new THREE$2.InterleavedBufferAttribute(instanceDistanceBuffer, 1, 1)); // d1 | ||
lineDistances[j] = j === 0 ? 0 : lineDistances[j - 1]; | ||
lineDistances[j + 1] = lineDistances[j] + _start.distanceTo(_end); | ||
} | ||
return this; | ||
}; | ||
}(), | ||
raycast: function () { | ||
var start = new THREE$2.Vector4(); | ||
var end = new THREE$2.Vector4(); | ||
var ssOrigin = new THREE$2.Vector4(); | ||
var ssOrigin3 = new THREE$2.Vector3(); | ||
var mvMatrix = new THREE$2.Matrix4(); | ||
var line = new THREE$2.Line3(); | ||
var closestPoint = new THREE$2.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.'); | ||
} | ||
const instanceDistanceBuffer = new THREE.InstancedInterleavedBuffer(lineDistances, 2, 1); // d0, d1 | ||
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; // 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. | ||
geometry[setAttributeFn]('instanceDistanceStart', new THREE.InterleavedBufferAttribute(instanceDistanceBuffer, 1, 0)); // d0 | ||
ray.at(1, ssOrigin); // ndc space [ - 1.0, 1.0 ] | ||
geometry[setAttributeFn]('instanceDistanceEnd', new THREE.InterleavedBufferAttribute(instanceDistanceBuffer, 1, 1)); // d1 | ||
ssOrigin.w = 1; | ||
ssOrigin.applyMatrix4(camera.matrixWorldInverse); | ||
ssOrigin.applyMatrix4(projectionMatrix); | ||
ssOrigin.multiplyScalar(1 / ssOrigin.w); // screen space | ||
return this; | ||
} | ||
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); | ||
raycast(raycaster, intersects) { | ||
if (raycaster.camera === null) { | ||
console.error('LineSegments2: "Raycaster.camera" needs to be set in order to raycast against LineSegments2.'); | ||
} | ||
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 | ||
const threshold = raycaster.params.Line2 !== undefined ? raycaster.params.Line2.threshold || 0 : 0; | ||
const ray = raycaster.ray; | ||
const camera = raycaster.camera; | ||
const projectionMatrix = camera.projectionMatrix; | ||
const matrixWorld = this.matrixWorld; | ||
const geometry = this.geometry; | ||
const material = this.material; | ||
const resolution = material.resolution; | ||
const lineWidth = material.linewidth + threshold; | ||
const instanceStart = geometry.attributes.instanceStart; | ||
const instanceEnd = geometry.attributes.instanceEnd; // camera forward is negative | ||
start.applyMatrix4(mvMatrix); | ||
end.applyMatrix4(mvMatrix); // clip space | ||
const near = -camera.near; // clip space is [ - 1, 1 ] so multiply by two to get the full | ||
// width in clip space | ||
start.applyMatrix4(projectionMatrix); | ||
end.applyMatrix4(projectionMatrix); // ndc space [ - 1.0, 1.0 ] | ||
const ssMaxWidth = 2.0 * Math.max(lineWidth / resolution.width, lineWidth / resolution.height); // | ||
// check if we intersect the sphere bounds | ||
start.multiplyScalar(1 / start.w); | ||
end.multiplyScalar(1 / end.w); // skip the segment if it's outside the camera near and far planes | ||
if (geometry.boundingSphere === null) { | ||
geometry.computeBoundingSphere(); | ||
} | ||
var isBehindCameraNear = start.z < -1 && end.z < -1; | ||
var isPastCameraFar = start.z > 1 && end.z > 1; | ||
_sphere.copy(geometry.boundingSphere).applyMatrix4(matrixWorld); | ||
if (isBehindCameraNear || isPastCameraFar) { | ||
continue; | ||
} // screen space | ||
const distanceToSphere = Math.max(camera.near, _sphere.distanceToPoint(ray.origin)); // get the w component to scale the world space line width | ||
_clipToWorldVector.set(0, 0, -distanceToSphere, 1.0).applyMatrix4(camera.projectionMatrix); | ||
start.x *= resolution.x / 2; | ||
start.y *= resolution.y / 2; | ||
end.x *= resolution.x / 2; | ||
end.y *= resolution.y / 2; // create 2d segment | ||
_clipToWorldVector.multiplyScalar(1.0 / _clipToWorldVector.w); | ||
line.start.copy(start); | ||
line.start.z = 0; | ||
line.end.copy(end); | ||
line.end.z = 0; // get closest point on ray to segment | ||
_clipToWorldVector.applyMatrix4(camera.projectionMatrixInverse); // increase the sphere bounds by the worst case line screen space width | ||
var param = line.closestPointToPointParameter(ssOrigin3, true); | ||
line.at(param, closestPoint); // check if the intersection point is within clip space | ||
var zPos = THREE$2.MathUtils.lerp(start.z, end.z, param); | ||
var isInClipSpace = zPos >= -1 && zPos <= 1; | ||
var isInside = ssOrigin3.distanceTo(closestPoint) < lineWidth * 0.5; | ||
const sphereMargin = Math.abs(ssMaxWidth / _clipToWorldVector.w) * 0.5; | ||
_sphere.radius += sphereMargin; | ||
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$2.Vector3(); | ||
var point = new THREE$2.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 | ||
}); | ||
} | ||
if (raycaster.ray.intersectsSphere(_sphere) === false) { | ||
return; | ||
} // | ||
// check if we intersect the box bounds | ||
if (geometry.boundingBox === null) { | ||
geometry.computeBoundingBox(); | ||
} | ||
_box.copy(geometry.boundingBox).applyMatrix4(matrixWorld); | ||
const distanceToBox = Math.max(camera.near, _box.distanceToPoint(ray.origin)); // get the w component to scale the world space line width | ||
_clipToWorldVector.set(0, 0, -distanceToBox, 1.0).applyMatrix4(camera.projectionMatrix); | ||
_clipToWorldVector.multiplyScalar(1.0 / _clipToWorldVector.w); | ||
_clipToWorldVector.applyMatrix4(camera.projectionMatrixInverse); // increase the sphere bounds by the worst case line screen space width | ||
const boxMargin = Math.abs(ssMaxWidth / _clipToWorldVector.w) * 0.5; | ||
_box.max.x += boxMargin; | ||
_box.max.y += boxMargin; | ||
_box.max.z += boxMargin; | ||
_box.min.x -= boxMargin; | ||
_box.min.y -= boxMargin; | ||
_box.min.z -= boxMargin; | ||
if (raycaster.ray.intersectsBox(_box) === false) { | ||
return; | ||
} // | ||
// 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); | ||
_mvMatrix.multiplyMatrices(camera.matrixWorldInverse, matrixWorld); | ||
for (let i = 0, l = instanceStart.count; i < l; i++) { | ||
_start4.fromBufferAttribute(instanceStart, i); | ||
_end4.fromBufferAttribute(instanceEnd, i); | ||
_start.w = 1; | ||
_end.w = 1; // camera space | ||
_start4.applyMatrix4(_mvMatrix); | ||
_end4.applyMatrix4(_mvMatrix); // skip the segment if it's entirely behind the camera | ||
var isBehindCameraNear = _start4.z > near && _end4.z > near; | ||
if (isBehindCameraNear) { | ||
continue; | ||
} // trim the segment if it extends behind camera near | ||
if (_start4.z > near) { | ||
const deltaDist = _start4.z - _end4.z; | ||
const t = (_start4.z - near) / deltaDist; | ||
_start4.lerp(_end4, t); | ||
} else if (_end4.z > near) { | ||
const deltaDist = _end4.z - _start4.z; | ||
const t = (_end4.z - near) / deltaDist; | ||
_end4.lerp(_start4, t); | ||
} // clip space | ||
_start4.applyMatrix4(projectionMatrix); | ||
_end4.applyMatrix4(projectionMatrix); // ndc space [ - 1.0, 1.0 ] | ||
_start4.multiplyScalar(1 / _start4.w); | ||
_end4.multiplyScalar(1 / _end4.w); // screen space | ||
_start4.x *= resolution.x / 2; | ||
_start4.y *= resolution.y / 2; | ||
_end4.x *= resolution.x / 2; | ||
_end4.y *= resolution.y / 2; // create 2d segment | ||
_line.start.copy(_start4); | ||
_line.start.z = 0; | ||
_line.end.copy(_end4); | ||
_line.end.z = 0; // get closest point on ray to segment | ||
const param = _line.closestPointToPointParameter(_ssOrigin3, true); | ||
_line.at(param, _closestPoint); // check if the intersection point is within clip space | ||
const zPos = THREE.MathUtils.lerp(_start4.z, _end4.z, param); | ||
const isInClipSpace = zPos >= -1 && zPos <= 1; | ||
const 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); | ||
const pointOnLine = new THREE.Vector3(); | ||
const 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 | ||
* | ||
*/ | ||
} | ||
var LineGeometry = function () { | ||
LineSegmentsGeometry.call(this); | ||
this.type = 'LineGeometry'; | ||
}; | ||
LineSegments2.prototype.LineSegments2 = true; | ||
LineGeometry.prototype = Object.assign(Object.create(LineSegmentsGeometry.prototype), { | ||
constructor: LineGeometry, | ||
isLineGeometry: true, | ||
setPositions: function (array) { | ||
class LineGeometry extends LineSegmentsGeometry { | ||
constructor() { | ||
super(); | ||
this.type = 'LineGeometry'; | ||
} | ||
setPositions(array) { | ||
// converts [ x1, y1, z1, x2, y2, z2, ... ] to pairs format | ||
@@ -740,6 +850,7 @@ var length = array.length - 3; | ||
LineSegmentsGeometry.prototype.setPositions.call(this, points); | ||
super.setPositions(points); | ||
return this; | ||
}, | ||
setColors: function (array) { | ||
} | ||
setColors(array) { | ||
// converts [ r1, g1, b1, r2, g2, b2, ... ] to pairs format | ||
@@ -758,12 +869,14 @@ var length = array.length - 3; | ||
LineSegmentsGeometry.prototype.setColors.call(this, colors); | ||
super.setColors(colors); | ||
return this; | ||
}, | ||
fromLine: function (line) { | ||
} | ||
fromLine(line) { | ||
var geometry = line.geometry; | ||
if (geometry.isGeometry) { | ||
this.setPositions(geometry.vertices); | ||
console.error('LineGeometry no longer supports Geometry. Use THREE.BufferGeometry instead.'); | ||
return; | ||
} else if (geometry.isBufferGeometry) { | ||
this.setPositions(geometry.position.array); // assumes non-indexed | ||
this.setPositions(geometry.attributes.position.array); // assumes non-indexed | ||
} // set colors, maybe | ||
@@ -773,36 +886,25 @@ | ||
return this; | ||
}, | ||
copy: function () | ||
/* source */ | ||
{ | ||
} | ||
copy() { | ||
// todo | ||
return this; | ||
} | ||
}); | ||
/** | ||
* @author WestLangley / http://github.com/WestLangley | ||
* | ||
*/ | ||
} | ||
var Line2 = function (geometry, material) { | ||
LineSegments2.call(this); | ||
this.type = 'Line2'; | ||
this.geometry = geometry !== undefined ? geometry : new LineGeometry(); | ||
this.material = material !== undefined ? material : new LineMaterial({ | ||
LineGeometry.prototype.isLineGeometry = true; | ||
class Line2 extends LineSegments2 { | ||
constructor(geometry = new LineGeometry(), material = new LineMaterial({ | ||
color: Math.random() * 0xffffff | ||
}); | ||
}; | ||
Line2.prototype = Object.assign(Object.create(LineSegments2.prototype), { | ||
constructor: Line2, | ||
isLine2: true, | ||
copy: function () | ||
/* source */ | ||
{ | ||
// todo | ||
return this; | ||
})) { | ||
super(geometry, material); | ||
this.type = 'Line2'; | ||
} | ||
}); | ||
} | ||
Line2.prototype.isLine2 = true; | ||
exports.Line2 = Line2; | ||
@@ -809,0 +911,0 @@ exports.LineGeometry = LineGeometry; |
import { InstancedBufferGeometry, Matrix4, WireframeGeometry, LineSegments, Mesh, EdgesGeometry, Line, ShaderMaterial, Color, Vector2, MaterialParameters } from 'three'; | ||
declare class LineSegmentsGeometry extends InstancedBufferGeometry { | ||
constructor(); | ||
isLineSegmentsGeometry: boolean; | ||
readonly isLineSegmentsGeometry: true; | ||
applyMatrix( matrix: Matrix4 ): this; | ||
applyMatrix4( matrix: Matrix4 ): this; | ||
applyMatrix4(matrix: Matrix4): this; | ||
computeBoundingBox(): void; | ||
computeBoundingSphere(): void; | ||
fromEdgesGeometry( geometry: WireframeGeometry ): this; | ||
fromLineSegements( lineSegments: LineSegments ): this; | ||
fromMesh( mesh: Mesh ): this; | ||
fromWireframeGeometry( geometry: EdgesGeometry ): this; | ||
setColors( array: number[] | Float32Array ): this; | ||
setPositions( array: number[] | Float32Array ): this; | ||
fromEdgesGeometry(geometry: WireframeGeometry): this; | ||
fromLineSegments(lineSegments: LineSegments): this; | ||
fromMesh(mesh: Mesh): this; | ||
fromWireframeGeometry(geometry: EdgesGeometry): this; | ||
setColors(array: number[] | Float32Array): this; | ||
setPositions(array: number[] | Float32Array): this; | ||
} | ||
declare class LineGeometry extends LineSegmentsGeometry { | ||
constructor(); | ||
isLineGeometry: boolean; | ||
readonly isLineGeometry: true; | ||
fromLine( line: Line ): this; | ||
fromLine(line: Line): this; | ||
} | ||
@@ -42,4 +37,3 @@ | ||
declare class LineMaterial extends ShaderMaterial { | ||
constructor( parameters?: LineMaterialParameters ); | ||
constructor(parameters?: LineMaterialParameters); | ||
color: Color; | ||
@@ -55,24 +49,23 @@ dashed: boolean; | ||
resolution: Vector2; | ||
alphaToCoverage: boolean; | ||
} | ||
declare class LineSegments2 extends Mesh { | ||
geometry: LineSegmentsGeometry; | ||
material: LineMaterial; | ||
constructor( geometry?: LineSegmentsGeometry, material?: LineMaterial ); | ||
constructor(geometry?: LineSegmentsGeometry, material?: LineMaterial); | ||
readonly isLineSegments2: true; | ||
computeLineDistances(): this; | ||
} | ||
declare class Line2 extends LineSegments2 { | ||
geometry: LineGeometry; | ||
material: LineMaterial; | ||
constructor( geometry?: LineGeometry, material?: LineMaterial ); | ||
isLine2: boolean; | ||
constructor(geometry?: LineGeometry, material?: LineMaterial); | ||
readonly isLine2: true; | ||
} | ||
export { Line2, LineGeometry, LineMaterial, LineSegments2, LineSegmentsGeometry }; |
@@ -1,2 +0,2 @@ | ||
// Version 0.4.2 three-fatline - https://github.com/vasturiano/three-fatline | ||
// Version 0.4.3 three-fatline - https://github.com/vasturiano/three-fatline | ||
(function (global, factory) { | ||
@@ -8,7 +8,3 @@ typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('three')) : | ||
/** | ||
* @author WestLangley / http://github.com/WestLangley | ||
* | ||
*/ | ||
const THREE = window.THREE ? window.THREE // Prefer consumption from global THREE, if exists | ||
const THREE$2 = window.THREE ? window.THREE // Prefer consumption from global THREE, if exists | ||
: { | ||
@@ -26,30 +22,28 @@ Box3: three.Box3, | ||
var setAttributeFn = new THREE.BufferGeometry().setAttribute ? 'setAttribute' : 'addAttribute'; | ||
var setAttributeFn$1 = new THREE$2.BufferGeometry().setAttribute ? 'setAttribute' : 'addAttribute'; | ||
var LineSegmentsGeometry = function () { | ||
THREE.InstancedBufferGeometry.call(this); | ||
this.type = 'LineSegmentsGeometry'; | ||
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[setAttributeFn]('position', new THREE.Float32BufferAttribute(positions, 3)); | ||
this[setAttributeFn]('uv', new THREE.Float32BufferAttribute(uvs, 2)); | ||
}; | ||
const _box$1 = new THREE$2.Box3(); | ||
LineSegmentsGeometry.prototype = Object.assign(Object.create(THREE.InstancedBufferGeometry.prototype), { | ||
constructor: LineSegmentsGeometry, | ||
isLineSegmentsGeometry: true, | ||
applyMatrix: function (matrix) { | ||
console.warn('THREE.LineSegmentsGeometry: applyMatrix() has been renamed to applyMatrix4().'); | ||
return this.applyMatrix4(matrix); | ||
}, | ||
applyMatrix4: function (matrix) { | ||
var start = this.attributes.instanceStart; | ||
var end = this.attributes.instanceEnd; | ||
const _vector = new THREE$2.Vector3(); | ||
class LineSegmentsGeometry extends THREE$2.InstancedBufferGeometry { | ||
constructor() { | ||
super(); | ||
this.type = 'LineSegmentsGeometry'; | ||
const 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]; | ||
const uvs = [-1, 2, 1, 2, -1, 1, 1, 1, -1, -1, 1, -1, -1, -2, 1, -2]; | ||
const index = [0, 2, 1, 2, 3, 1, 2, 4, 3, 4, 5, 3, 4, 6, 5, 6, 7, 5]; | ||
this.setIndex(index); | ||
this[setAttributeFn$1]('position', new THREE$2.Float32BufferAttribute(positions, 3)); | ||
this[setAttributeFn$1]('uv', new THREE$2.Float32BufferAttribute(uvs, 2)); | ||
} | ||
applyMatrix4(matrix) { | ||
const start = this.attributes.instanceStart; | ||
const end = this.attributes.instanceEnd; | ||
if (start !== undefined) { | ||
matrix.applyToBufferAttribute(start); | ||
matrix.applyToBufferAttribute(end); | ||
start.data.needsUpdate = true; | ||
start.applyMatrix4(matrix); | ||
end.applyMatrix4(matrix); | ||
start.needsUpdate = true; | ||
} | ||
@@ -66,6 +60,7 @@ | ||
return this; | ||
}, | ||
setPositions: function (array) { | ||
var lineSegments; | ||
} | ||
setPositions(array) { | ||
let lineSegments; | ||
if (array instanceof Float32Array) { | ||
@@ -77,7 +72,7 @@ lineSegments = array; | ||
var instanceBuffer = new THREE.InstancedInterleavedBuffer(lineSegments, 6, 1); // xyz, xyz | ||
const instanceBuffer = new THREE$2.InstancedInterleavedBuffer(lineSegments, 6, 1); // xyz, xyz | ||
this[setAttributeFn]('instanceStart', new THREE.InterleavedBufferAttribute(instanceBuffer, 3, 0)); // xyz | ||
this[setAttributeFn$1]('instanceStart', new THREE$2.InterleavedBufferAttribute(instanceBuffer, 3, 0)); // xyz | ||
this[setAttributeFn]('instanceEnd', new THREE.InterleavedBufferAttribute(instanceBuffer, 3, 3)); // xyz | ||
this[setAttributeFn$1]('instanceEnd', new THREE$2.InterleavedBufferAttribute(instanceBuffer, 3, 3)); // xyz | ||
// | ||
@@ -88,6 +83,7 @@ | ||
return this; | ||
}, | ||
setColors: function (array) { | ||
var colors; | ||
} | ||
setColors(array) { | ||
let colors; | ||
if (array instanceof Float32Array) { | ||
@@ -99,30 +95,35 @@ colors = array; | ||
var instanceColorBuffer = new THREE.InstancedInterleavedBuffer(colors, 6, 1); // rgb, rgb | ||
const instanceColorBuffer = new THREE$2.InstancedInterleavedBuffer(colors, 6, 1); // rgb, rgb | ||
this[setAttributeFn]('instanceColorStart', new THREE.InterleavedBufferAttribute(instanceColorBuffer, 3, 0)); // rgb | ||
this[setAttributeFn$1]('instanceColorStart', new THREE$2.InterleavedBufferAttribute(instanceColorBuffer, 3, 0)); // rgb | ||
this[setAttributeFn]('instanceColorEnd', new THREE.InterleavedBufferAttribute(instanceColorBuffer, 3, 3)); // rgb | ||
this[setAttributeFn$1]('instanceColorEnd', new THREE$2.InterleavedBufferAttribute(instanceColorBuffer, 3, 3)); // rgb | ||
return this; | ||
}, | ||
fromWireframeGeometry: function (geometry) { | ||
} | ||
fromWireframeGeometry(geometry) { | ||
this.setPositions(geometry.attributes.position.array); | ||
return this; | ||
}, | ||
fromEdgesGeometry: function (geometry) { | ||
} | ||
fromEdgesGeometry(geometry) { | ||
this.setPositions(geometry.attributes.position.array); | ||
return this; | ||
}, | ||
fromMesh: function (mesh) { | ||
this.fromWireframeGeometry(new THREE.WireframeGeometry(mesh.geometry)); // set colors, maybe | ||
} | ||
fromMesh(mesh) { | ||
this.fromWireframeGeometry(new THREE$2.WireframeGeometry(mesh.geometry)); // set colors, maybe | ||
return this; | ||
}, | ||
fromLineSegements: function (lineSegments) { | ||
var geometry = lineSegments.geometry; | ||
} | ||
romLineSegments(lineSegments) { | ||
const geometry = lineSegments.geometry; | ||
if (geometry.isGeometry) { | ||
this.setPositions(geometry.vertices); | ||
console.error('LineSegmentsGeometry no longer supports Geometry. Use THREE.BufferGeometry instead.'); | ||
return; | ||
} else if (geometry.isBufferGeometry) { | ||
this.setPositions(geometry.position.array); // assumes non-indexed | ||
this.setPositions(geometry.attributes.position.array); // assumes non-indexed | ||
} // set colors, maybe | ||
@@ -132,69 +133,69 @@ | ||
return this; | ||
}, | ||
computeBoundingBox: function () { | ||
var box = new THREE.Box3(); | ||
return function computeBoundingBox() { | ||
if (this.boundingBox === null) { | ||
this.boundingBox = new THREE.Box3(); | ||
} | ||
} | ||
var start = this.attributes.instanceStart; | ||
var end = this.attributes.instanceEnd; | ||
computeBoundingBox() { | ||
if (this.boundingBox === null) { | ||
this.boundingBox = new THREE$2.Box3(); | ||
} | ||
if (start !== undefined && end !== undefined) { | ||
this.boundingBox.setFromBufferAttribute(start); | ||
box.setFromBufferAttribute(end); | ||
this.boundingBox.union(box); | ||
} | ||
}; | ||
}(), | ||
computeBoundingSphere: function () { | ||
var vector = new THREE.Vector3(); | ||
return function computeBoundingSphere() { | ||
if (this.boundingSphere === null) { | ||
this.boundingSphere = new THREE.Sphere(); | ||
} | ||
const start = this.attributes.instanceStart; | ||
const end = this.attributes.instanceEnd; | ||
if (this.boundingBox === null) { | ||
this.computeBoundingBox(); | ||
} | ||
if (start !== undefined && end !== undefined) { | ||
this.boundingBox.setFromBufferAttribute(start); | ||
var start = this.attributes.instanceStart; | ||
var end = this.attributes.instanceEnd; | ||
_box$1.setFromBufferAttribute(end); | ||
if (start !== undefined && end !== undefined) { | ||
var center = this.boundingSphere.center; | ||
this.boundingBox.getCenter(center); | ||
var maxRadiusSq = 0; | ||
this.boundingBox.union(_box$1); | ||
} | ||
} | ||
for (var i = 0, il = start.count; i < il; i++) { | ||
vector.fromBufferAttribute(start, i); | ||
maxRadiusSq = Math.max(maxRadiusSq, center.distanceToSquared(vector)); | ||
vector.fromBufferAttribute(end, i); | ||
maxRadiusSq = Math.max(maxRadiusSq, center.distanceToSquared(vector)); | ||
} | ||
computeBoundingSphere() { | ||
if (this.boundingSphere === null) { | ||
this.boundingSphere = new THREE$2.Sphere(); | ||
} | ||
this.boundingSphere.radius = Math.sqrt(maxRadiusSq); | ||
if (this.boundingBox === null) { | ||
this.computeBoundingBox(); | ||
} | ||
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); | ||
} | ||
const start = this.attributes.instanceStart; | ||
const end = this.attributes.instanceEnd; | ||
if (start !== undefined && end !== undefined) { | ||
const center = this.boundingSphere.center; | ||
this.boundingBox.getCenter(center); | ||
let maxRadiusSq = 0; | ||
for (let i = 0, il = start.count; i < il; i++) { | ||
_vector.fromBufferAttribute(start, i); | ||
maxRadiusSq = Math.max(maxRadiusSq, center.distanceToSquared(_vector)); | ||
_vector.fromBufferAttribute(end, i); | ||
maxRadiusSq = Math.max(maxRadiusSq, center.distanceToSquared(_vector)); | ||
} | ||
}; | ||
}(), | ||
toJSON: function () {// todo | ||
}, | ||
clone: function () {// todo | ||
}, | ||
copy: function () | ||
/* source */ | ||
{ | ||
// todo | ||
return this; | ||
this.boundingSphere.radius = Math.sqrt(maxRadiusSq); | ||
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); | ||
} | ||
} | ||
} | ||
}); | ||
toJSON() {// todo | ||
} | ||
applyMatrix(matrix) { | ||
console.warn('THREE.LineSegmentsGeometry: applyMatrix() has been renamed to applyMatrix4().'); | ||
return this.applyMatrix4(matrix); | ||
} | ||
} | ||
LineSegmentsGeometry.prototype.isLineSegmentsGeometry = true; | ||
/** | ||
* @author WestLangley / http://github.com/WestLangley | ||
* | ||
* parameters = { | ||
@@ -450,108 +451,116 @@ * color: <hex>, | ||
var LineMaterial = function (parameters) { | ||
THREE$1.ShaderMaterial.call(this, { | ||
type: 'LineMaterial', | ||
uniforms: THREE$1.UniformsUtils.clone(THREE$1.ShaderLib['line'].uniforms), | ||
vertexShader: THREE$1.ShaderLib['line'].vertexShader, | ||
fragmentShader: THREE$1.ShaderLib['line'].fragmentShader, | ||
clipping: true // required for clipping support | ||
class LineMaterial extends THREE$1.ShaderMaterial { | ||
constructor(parameters) { | ||
super({ | ||
type: 'LineMaterial', | ||
uniforms: THREE$1.UniformsUtils.clone(THREE$1.ShaderLib['line'].uniforms), | ||
vertexShader: THREE$1.ShaderLib['line'].vertexShader, | ||
fragmentShader: THREE$1.ShaderLib['line'].fragmentShader, | ||
clipping: true // required for clipping support | ||
}); | ||
this.dashed = false; | ||
Object.defineProperties(this, { | ||
color: { | ||
enumerable: true, | ||
get: function () { | ||
return this.uniforms.diffuse.value; | ||
}); | ||
this.dashed = false; | ||
Object.defineProperties(this, { | ||
color: { | ||
enumerable: true, | ||
get: function () { | ||
return this.uniforms.diffuse.value; | ||
}, | ||
set: function (value) { | ||
this.uniforms.diffuse.value = value; | ||
} | ||
}, | ||
set: function (value) { | ||
this.uniforms.diffuse.value = value; | ||
} | ||
}, | ||
linewidth: { | ||
enumerable: true, | ||
get: function () { | ||
return this.uniforms.linewidth.value; | ||
linewidth: { | ||
enumerable: true, | ||
get: function () { | ||
return this.uniforms.linewidth.value; | ||
}, | ||
set: function (value) { | ||
this.uniforms.linewidth.value = value; | ||
} | ||
}, | ||
set: function (value) { | ||
this.uniforms.linewidth.value = value; | ||
} | ||
}, | ||
dashScale: { | ||
enumerable: true, | ||
get: function () { | ||
return this.uniforms.dashScale.value; | ||
dashScale: { | ||
enumerable: true, | ||
get: function () { | ||
return this.uniforms.dashScale.value; | ||
}, | ||
set: function (value) { | ||
this.uniforms.dashScale.value = value; | ||
} | ||
}, | ||
set: function (value) { | ||
this.uniforms.dashScale.value = value; | ||
} | ||
}, | ||
dashSize: { | ||
enumerable: true, | ||
get: function () { | ||
return this.uniforms.dashSize.value; | ||
dashSize: { | ||
enumerable: true, | ||
get: function () { | ||
return this.uniforms.dashSize.value; | ||
}, | ||
set: function (value) { | ||
this.uniforms.dashSize.value = value; | ||
} | ||
}, | ||
set: function (value) { | ||
this.uniforms.dashSize.value = value; | ||
} | ||
}, | ||
dashOffset: { | ||
enumerable: true, | ||
get: function () { | ||
return this.uniforms.dashOffset.value; | ||
dashOffset: { | ||
enumerable: true, | ||
get: function () { | ||
return this.uniforms.dashOffset.value; | ||
}, | ||
set: function (value) { | ||
this.uniforms.dashOffset.value = value; | ||
} | ||
}, | ||
set: function (value) { | ||
this.uniforms.dashOffset.value = value; | ||
} | ||
}, | ||
gapSize: { | ||
enumerable: true, | ||
get: function () { | ||
return this.uniforms.gapSize.value; | ||
gapSize: { | ||
enumerable: true, | ||
get: function () { | ||
return this.uniforms.gapSize.value; | ||
}, | ||
set: function (value) { | ||
this.uniforms.gapSize.value = value; | ||
} | ||
}, | ||
set: function (value) { | ||
this.uniforms.gapSize.value = value; | ||
} | ||
}, | ||
opacity: { | ||
enumerable: true, | ||
get: function () { | ||
return this.uniforms.opacity.value; | ||
opacity: { | ||
enumerable: true, | ||
get: function () { | ||
return this.uniforms.opacity.value; | ||
}, | ||
set: function (value) { | ||
this.uniforms.opacity.value = value; | ||
} | ||
}, | ||
set: function (value) { | ||
this.uniforms.opacity.value = value; | ||
} | ||
}, | ||
resolution: { | ||
enumerable: true, | ||
get: function () { | ||
return this.uniforms.resolution.value; | ||
resolution: { | ||
enumerable: true, | ||
get: function () { | ||
return this.uniforms.resolution.value; | ||
}, | ||
set: function (value) { | ||
this.uniforms.resolution.value.copy(value); | ||
} | ||
}, | ||
set: function (value) { | ||
this.uniforms.resolution.value.copy(value); | ||
alphaToCoverage: { | ||
enumerable: true, | ||
get: function () { | ||
return Boolean('ALPHA_TO_COVERAGE' in this.defines); | ||
}, | ||
set: function (value) { | ||
if (Boolean(value) !== Boolean('ALPHA_TO_COVERAGE' in this.defines)) { | ||
this.needsUpdate = true; | ||
} | ||
if (value) { | ||
this.defines.ALPHA_TO_COVERAGE = ''; | ||
this.extensions.derivatives = true; | ||
} else { | ||
delete this.defines.ALPHA_TO_COVERAGE; | ||
this.extensions.derivatives = false; | ||
} | ||
} | ||
} | ||
} | ||
}); | ||
this.setValues(parameters); | ||
}; | ||
}); | ||
this.setValues(parameters); | ||
} | ||
LineMaterial.prototype = Object.create(THREE$1.ShaderMaterial.prototype); | ||
LineMaterial.prototype.constructor = LineMaterial; | ||
} | ||
LineMaterial.prototype.isLineMaterial = true; | ||
LineMaterial.prototype.copy = function (source) { | ||
THREE$1.ShaderMaterial.prototype.copy.call(this, source); | ||
this.color.copy(source.color); | ||
this.linewidth = source.linewidth; | ||
this.resolution = source.resolution; // todo | ||
return this; | ||
}; | ||
/** | ||
* @author WestLangley / http://github.com/WestLangley | ||
* | ||
*/ | ||
const THREE$2 = window.THREE ? window.THREE // Prefer consumption from global THREE, if exists | ||
const THREE = window.THREE ? window.THREE // Prefer consumption from global THREE, if exists | ||
: { | ||
Box3: three.Box3, | ||
BufferGeometry: three.BufferGeometry, | ||
@@ -564,2 +573,3 @@ InstancedInterleavedBuffer: three.InstancedInterleavedBuffer, | ||
Mesh: three.Mesh, | ||
Sphere: three.Sphere, | ||
Vector3: three.Vector3, | ||
@@ -569,160 +579,260 @@ Vector4: three.Vector4 | ||
var setAttributeFn$1 = new THREE$2.BufferGeometry().setAttribute ? 'setAttribute' : 'addAttribute'; | ||
var setAttributeFn = new THREE.BufferGeometry().setAttribute ? 'setAttribute' : 'addAttribute'; | ||
var LineSegments2 = function (geometry, material) { | ||
if (geometry === undefined) geometry = new LineSegmentsGeometry(); | ||
if (material === undefined) material = new LineMaterial({ | ||
const _start = new THREE.Vector3(); | ||
const _end = new THREE.Vector3(); | ||
const _start4 = new THREE.Vector4(); | ||
const _end4 = new THREE.Vector4(); | ||
const _ssOrigin = new THREE.Vector4(); | ||
const _ssOrigin3 = new THREE.Vector3(); | ||
const _mvMatrix = new THREE.Matrix4(); | ||
const _line = new THREE.Line3(); | ||
const _closestPoint = new THREE.Vector3(); | ||
const _box = new THREE.Box3(); | ||
const _sphere = new THREE.Sphere(); | ||
const _clipToWorldVector = new THREE.Vector4(); | ||
class LineSegments2 extends THREE.Mesh { | ||
constructor(geometry = new LineSegmentsGeometry(), material = new LineMaterial({ | ||
color: Math.random() * 0xffffff | ||
}); | ||
THREE$2.Mesh.call(this, geometry, material); | ||
this.type = 'LineSegments2'; | ||
}; | ||
})) { | ||
super(geometry, material); | ||
this.type = 'LineSegments2'; | ||
} // for backwards-compatability, but could be a method of LineSegmentsGeometry... | ||
LineSegments2.prototype = Object.assign(Object.create(THREE$2.Mesh.prototype), { | ||
constructor: LineSegments2, | ||
isLineSegments2: true, | ||
computeLineDistances: function () { | ||
// for backwards-compatability, but could be a method of LineSegmentsGeometry... | ||
var start = new THREE$2.Vector3(); | ||
var end = new THREE$2.Vector3(); | ||
return function computeLineDistances() { | ||
var geometry = this.geometry; | ||
var instanceStart = geometry.attributes.instanceStart; | ||
var instanceEnd = geometry.attributes.instanceEnd; | ||
var lineDistances = new Float32Array(2 * instanceStart.data.count); | ||
for (var i = 0, j = 0, l = instanceStart.data.count; i < l; i++, j += 2) { | ||
start.fromBufferAttribute(instanceStart, i); | ||
end.fromBufferAttribute(instanceEnd, i); | ||
lineDistances[j] = j === 0 ? 0 : lineDistances[j - 1]; | ||
lineDistances[j + 1] = lineDistances[j] + start.distanceTo(end); | ||
} | ||
computeLineDistances() { | ||
const geometry = this.geometry; | ||
const instanceStart = geometry.attributes.instanceStart; | ||
const instanceEnd = geometry.attributes.instanceEnd; | ||
const lineDistances = new Float32Array(2 * instanceStart.count); | ||
var instanceDistanceBuffer = new THREE$2.InstancedInterleavedBuffer(lineDistances, 2, 1); // d0, d1 | ||
for (let i = 0, j = 0, l = instanceStart.count; i < l; i++, j += 2) { | ||
_start.fromBufferAttribute(instanceStart, i); | ||
geometry[setAttributeFn$1]('instanceDistanceStart', new THREE$2.InterleavedBufferAttribute(instanceDistanceBuffer, 1, 0)); // d0 | ||
_end.fromBufferAttribute(instanceEnd, i); | ||
geometry[setAttributeFn$1]('instanceDistanceEnd', new THREE$2.InterleavedBufferAttribute(instanceDistanceBuffer, 1, 1)); // d1 | ||
lineDistances[j] = j === 0 ? 0 : lineDistances[j - 1]; | ||
lineDistances[j + 1] = lineDistances[j] + _start.distanceTo(_end); | ||
} | ||
return this; | ||
}; | ||
}(), | ||
raycast: function () { | ||
var start = new THREE$2.Vector4(); | ||
var end = new THREE$2.Vector4(); | ||
var ssOrigin = new THREE$2.Vector4(); | ||
var ssOrigin3 = new THREE$2.Vector3(); | ||
var mvMatrix = new THREE$2.Matrix4(); | ||
var line = new THREE$2.Line3(); | ||
var closestPoint = new THREE$2.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.'); | ||
} | ||
const instanceDistanceBuffer = new THREE.InstancedInterleavedBuffer(lineDistances, 2, 1); // d0, d1 | ||
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; // 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. | ||
geometry[setAttributeFn]('instanceDistanceStart', new THREE.InterleavedBufferAttribute(instanceDistanceBuffer, 1, 0)); // d0 | ||
ray.at(1, ssOrigin); // ndc space [ - 1.0, 1.0 ] | ||
geometry[setAttributeFn]('instanceDistanceEnd', new THREE.InterleavedBufferAttribute(instanceDistanceBuffer, 1, 1)); // d1 | ||
ssOrigin.w = 1; | ||
ssOrigin.applyMatrix4(camera.matrixWorldInverse); | ||
ssOrigin.applyMatrix4(projectionMatrix); | ||
ssOrigin.multiplyScalar(1 / ssOrigin.w); // screen space | ||
return this; | ||
} | ||
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); | ||
raycast(raycaster, intersects) { | ||
if (raycaster.camera === null) { | ||
console.error('LineSegments2: "Raycaster.camera" needs to be set in order to raycast against LineSegments2.'); | ||
} | ||
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 | ||
const threshold = raycaster.params.Line2 !== undefined ? raycaster.params.Line2.threshold || 0 : 0; | ||
const ray = raycaster.ray; | ||
const camera = raycaster.camera; | ||
const projectionMatrix = camera.projectionMatrix; | ||
const matrixWorld = this.matrixWorld; | ||
const geometry = this.geometry; | ||
const material = this.material; | ||
const resolution = material.resolution; | ||
const lineWidth = material.linewidth + threshold; | ||
const instanceStart = geometry.attributes.instanceStart; | ||
const instanceEnd = geometry.attributes.instanceEnd; // camera forward is negative | ||
start.applyMatrix4(mvMatrix); | ||
end.applyMatrix4(mvMatrix); // clip space | ||
const near = -camera.near; // clip space is [ - 1, 1 ] so multiply by two to get the full | ||
// width in clip space | ||
start.applyMatrix4(projectionMatrix); | ||
end.applyMatrix4(projectionMatrix); // ndc space [ - 1.0, 1.0 ] | ||
const ssMaxWidth = 2.0 * Math.max(lineWidth / resolution.width, lineWidth / resolution.height); // | ||
// check if we intersect the sphere bounds | ||
start.multiplyScalar(1 / start.w); | ||
end.multiplyScalar(1 / end.w); // skip the segment if it's outside the camera near and far planes | ||
if (geometry.boundingSphere === null) { | ||
geometry.computeBoundingSphere(); | ||
} | ||
var isBehindCameraNear = start.z < -1 && end.z < -1; | ||
var isPastCameraFar = start.z > 1 && end.z > 1; | ||
_sphere.copy(geometry.boundingSphere).applyMatrix4(matrixWorld); | ||
if (isBehindCameraNear || isPastCameraFar) { | ||
continue; | ||
} // screen space | ||
const distanceToSphere = Math.max(camera.near, _sphere.distanceToPoint(ray.origin)); // get the w component to scale the world space line width | ||
_clipToWorldVector.set(0, 0, -distanceToSphere, 1.0).applyMatrix4(camera.projectionMatrix); | ||
start.x *= resolution.x / 2; | ||
start.y *= resolution.y / 2; | ||
end.x *= resolution.x / 2; | ||
end.y *= resolution.y / 2; // create 2d segment | ||
_clipToWorldVector.multiplyScalar(1.0 / _clipToWorldVector.w); | ||
line.start.copy(start); | ||
line.start.z = 0; | ||
line.end.copy(end); | ||
line.end.z = 0; // get closest point on ray to segment | ||
_clipToWorldVector.applyMatrix4(camera.projectionMatrixInverse); // increase the sphere bounds by the worst case line screen space width | ||
var param = line.closestPointToPointParameter(ssOrigin3, true); | ||
line.at(param, closestPoint); // check if the intersection point is within clip space | ||
var zPos = THREE$2.MathUtils.lerp(start.z, end.z, param); | ||
var isInClipSpace = zPos >= -1 && zPos <= 1; | ||
var isInside = ssOrigin3.distanceTo(closestPoint) < lineWidth * 0.5; | ||
const sphereMargin = Math.abs(ssMaxWidth / _clipToWorldVector.w) * 0.5; | ||
_sphere.radius += sphereMargin; | ||
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$2.Vector3(); | ||
var point = new THREE$2.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 | ||
}); | ||
} | ||
if (raycaster.ray.intersectsSphere(_sphere) === false) { | ||
return; | ||
} // | ||
// check if we intersect the box bounds | ||
if (geometry.boundingBox === null) { | ||
geometry.computeBoundingBox(); | ||
} | ||
_box.copy(geometry.boundingBox).applyMatrix4(matrixWorld); | ||
const distanceToBox = Math.max(camera.near, _box.distanceToPoint(ray.origin)); // get the w component to scale the world space line width | ||
_clipToWorldVector.set(0, 0, -distanceToBox, 1.0).applyMatrix4(camera.projectionMatrix); | ||
_clipToWorldVector.multiplyScalar(1.0 / _clipToWorldVector.w); | ||
_clipToWorldVector.applyMatrix4(camera.projectionMatrixInverse); // increase the sphere bounds by the worst case line screen space width | ||
const boxMargin = Math.abs(ssMaxWidth / _clipToWorldVector.w) * 0.5; | ||
_box.max.x += boxMargin; | ||
_box.max.y += boxMargin; | ||
_box.max.z += boxMargin; | ||
_box.min.x -= boxMargin; | ||
_box.min.y -= boxMargin; | ||
_box.min.z -= boxMargin; | ||
if (raycaster.ray.intersectsBox(_box) === false) { | ||
return; | ||
} // | ||
// 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); | ||
_mvMatrix.multiplyMatrices(camera.matrixWorldInverse, matrixWorld); | ||
for (let i = 0, l = instanceStart.count; i < l; i++) { | ||
_start4.fromBufferAttribute(instanceStart, i); | ||
_end4.fromBufferAttribute(instanceEnd, i); | ||
_start.w = 1; | ||
_end.w = 1; // camera space | ||
_start4.applyMatrix4(_mvMatrix); | ||
_end4.applyMatrix4(_mvMatrix); // skip the segment if it's entirely behind the camera | ||
var isBehindCameraNear = _start4.z > near && _end4.z > near; | ||
if (isBehindCameraNear) { | ||
continue; | ||
} // trim the segment if it extends behind camera near | ||
if (_start4.z > near) { | ||
const deltaDist = _start4.z - _end4.z; | ||
const t = (_start4.z - near) / deltaDist; | ||
_start4.lerp(_end4, t); | ||
} else if (_end4.z > near) { | ||
const deltaDist = _end4.z - _start4.z; | ||
const t = (_end4.z - near) / deltaDist; | ||
_end4.lerp(_start4, t); | ||
} // clip space | ||
_start4.applyMatrix4(projectionMatrix); | ||
_end4.applyMatrix4(projectionMatrix); // ndc space [ - 1.0, 1.0 ] | ||
_start4.multiplyScalar(1 / _start4.w); | ||
_end4.multiplyScalar(1 / _end4.w); // screen space | ||
_start4.x *= resolution.x / 2; | ||
_start4.y *= resolution.y / 2; | ||
_end4.x *= resolution.x / 2; | ||
_end4.y *= resolution.y / 2; // create 2d segment | ||
_line.start.copy(_start4); | ||
_line.start.z = 0; | ||
_line.end.copy(_end4); | ||
_line.end.z = 0; // get closest point on ray to segment | ||
const param = _line.closestPointToPointParameter(_ssOrigin3, true); | ||
_line.at(param, _closestPoint); // check if the intersection point is within clip space | ||
const zPos = THREE.MathUtils.lerp(_start4.z, _end4.z, param); | ||
const isInClipSpace = zPos >= -1 && zPos <= 1; | ||
const 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); | ||
const pointOnLine = new THREE.Vector3(); | ||
const 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 | ||
* | ||
*/ | ||
} | ||
var LineGeometry = function () { | ||
LineSegmentsGeometry.call(this); | ||
this.type = 'LineGeometry'; | ||
}; | ||
LineSegments2.prototype.LineSegments2 = true; | ||
LineGeometry.prototype = Object.assign(Object.create(LineSegmentsGeometry.prototype), { | ||
constructor: LineGeometry, | ||
isLineGeometry: true, | ||
setPositions: function (array) { | ||
class LineGeometry extends LineSegmentsGeometry { | ||
constructor() { | ||
super(); | ||
this.type = 'LineGeometry'; | ||
} | ||
setPositions(array) { | ||
// converts [ x1, y1, z1, x2, y2, z2, ... ] to pairs format | ||
@@ -741,6 +851,7 @@ var length = array.length - 3; | ||
LineSegmentsGeometry.prototype.setPositions.call(this, points); | ||
super.setPositions(points); | ||
return this; | ||
}, | ||
setColors: function (array) { | ||
} | ||
setColors(array) { | ||
// converts [ r1, g1, b1, r2, g2, b2, ... ] to pairs format | ||
@@ -759,12 +870,14 @@ var length = array.length - 3; | ||
LineSegmentsGeometry.prototype.setColors.call(this, colors); | ||
super.setColors(colors); | ||
return this; | ||
}, | ||
fromLine: function (line) { | ||
} | ||
fromLine(line) { | ||
var geometry = line.geometry; | ||
if (geometry.isGeometry) { | ||
this.setPositions(geometry.vertices); | ||
console.error('LineGeometry no longer supports Geometry. Use THREE.BufferGeometry instead.'); | ||
return; | ||
} else if (geometry.isBufferGeometry) { | ||
this.setPositions(geometry.position.array); // assumes non-indexed | ||
this.setPositions(geometry.attributes.position.array); // assumes non-indexed | ||
} // set colors, maybe | ||
@@ -774,36 +887,25 @@ | ||
return this; | ||
}, | ||
copy: function () | ||
/* source */ | ||
{ | ||
} | ||
copy() { | ||
// todo | ||
return this; | ||
} | ||
}); | ||
/** | ||
* @author WestLangley / http://github.com/WestLangley | ||
* | ||
*/ | ||
} | ||
var Line2 = function (geometry, material) { | ||
LineSegments2.call(this); | ||
this.type = 'Line2'; | ||
this.geometry = geometry !== undefined ? geometry : new LineGeometry(); | ||
this.material = material !== undefined ? material : new LineMaterial({ | ||
LineGeometry.prototype.isLineGeometry = true; | ||
class Line2 extends LineSegments2 { | ||
constructor(geometry = new LineGeometry(), material = new LineMaterial({ | ||
color: Math.random() * 0xffffff | ||
}); | ||
}; | ||
Line2.prototype = Object.assign(Object.create(LineSegments2.prototype), { | ||
constructor: Line2, | ||
isLine2: true, | ||
copy: function () | ||
/* source */ | ||
{ | ||
// todo | ||
return this; | ||
})) { | ||
super(geometry, material); | ||
this.type = 'Line2'; | ||
} | ||
}); | ||
} | ||
Line2.prototype.isLine2 = true; | ||
exports.Line2 = Line2; | ||
@@ -810,0 +912,0 @@ exports.LineGeometry = LineGeometry; |
@@ -1,2 +0,2 @@ | ||
// Version 0.4.2 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,r,a=(new n.BufferGeometry).setAttribute?"setAttribute":"addAttribute",o=function(){n.InstancedBufferGeometry.call(this),this.type="LineSegmentsGeometry";this.setIndex([0,2,1,2,3,1,2,4,3,4,5,3,4,6,5,6,7,5]),this[a]("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[a]("uv",new n.Float32BufferAttribute([-1,2,1,2,-1,1,1,1,-1,-1,1,-1,-1,-2,1,-2],2))};o.prototype=Object.assign(Object.create(n.InstancedBufferGeometry.prototype),{constructor:o,isLineSegmentsGeometry:!0,applyMatrix:function(t){return console.warn("THREE.LineSegmentsGeometry: applyMatrix() has been renamed to applyMatrix4()."),this.applyMatrix4(t)},applyMatrix4: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 i=new n.InstancedInterleavedBuffer(e,6,1);return this[a]("instanceStart",new n.InterleavedBufferAttribute(i,3,0)),this[a]("instanceEnd",new n.InterleavedBufferAttribute(i,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 i=new n.InstancedInterleavedBuffer(e,6,1);return this[a]("instanceColorStart",new n.InterleavedBufferAttribute(i,3,0)),this[a]("instanceColorEnd",new n.InterleavedBufferAttribute(i,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 n.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:(r=new n.Box3,function(){null===this.boundingBox&&(this.boundingBox=new n.Box3);var 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:(i=new n.Vector3,function(){null===this.boundingSphere&&(this.boundingSphere=new n.Sphere),null===this.boundingBox&&this.computeBoundingBox();var t=this.attributes.instanceStart,e=this.attributes.instanceEnd;if(void 0!==t&&void 0!==e){var r=this.boundingSphere.center;this.boundingBox.getCenter(r);for(var a=0,o=0,s=t.count;o<s;o++)i.fromBufferAttribute(t,o),a=Math.max(a,r.distanceToSquared(i)),i.fromBufferAttribute(e,o),a=Math.max(a,r.distanceToSquared(i));this.boundingSphere.radius=Math.sqrt(a),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:function(){},clone:function(){},copy:function(){return this}});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"};var c=function(t){s.ShaderMaterial.call(this,{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)}}}),this.setValues(t)};(c.prototype=Object.create(s.ShaderMaterial.prototype)).constructor=c,c.prototype.isLineMaterial=!0,c.prototype.copy=function(t){return s.ShaderMaterial.prototype.copy.call(this,t),this.color.copy(t.color),this.linewidth=t.linewidth,this.resolution=t.resolution,this};const u=window.THREE?window.THREE:{BufferGeometry:e.BufferGeometry,InstancedInterleavedBuffer:e.InstancedInterleavedBuffer,InterleavedBufferAttribute:e.InterleavedBufferAttribute,Line3:e.Line3,MathUtils:e.MathUtils,Matrix4:e.Matrix4,Mesh:e.Mesh,Vector3:e.Vector3,Vector4:e.Vector4};var f,l,d=(new u.BufferGeometry).setAttribute?"setAttribute":"addAttribute",p=function(t,e){void 0===t&&(t=new o),void 0===e&&(e=new c({color:16777215*Math.random()})),u.Mesh.call(this,t,e),this.type="LineSegments2"};p.prototype=Object.assign(Object.create(u.Mesh.prototype),{constructor:p,isLineSegments2:!0,computeLineDistances:(f=new u.Vector3,l=new u.Vector3,function(){for(var t=this.geometry,e=t.attributes.instanceStart,n=t.attributes.instanceEnd,i=new Float32Array(2*e.data.count),r=0,a=0,o=e.data.count;r<o;r++,a+=2)f.fromBufferAttribute(e,r),l.fromBufferAttribute(n,r),i[a]=0===a?0:i[a-1],i[a+1]=i[a]+f.distanceTo(l);var s=new u.InstancedInterleavedBuffer(i,2,1);return t[d]("instanceDistanceStart",new u.InterleavedBufferAttribute(s,1,0)),t[d]("instanceDistanceEnd",new u.InterleavedBufferAttribute(s,1,1)),this}),raycast:function(){var t=new u.Vector4,e=new u.Vector4,n=new u.Vector4,i=new u.Vector3,r=new u.Matrix4,a=new u.Line3,o=new u.Vector3;return function(s,c){null===s.camera&&console.error('LineSegments2: "Raycaster.camera" needs to be set in order to raycast against LineSegments2.');var f=void 0!==s.params.Line2&&s.params.Line2.threshold||0,l=s.ray,d=s.camera,p=d.projectionMatrix,h=this.geometry,m=this.material,v=m.resolution,y=m.linewidth+f,b=h.attributes.instanceStart,g=h.attributes.instanceEnd;l.at(1,n),n.w=1,n.applyMatrix4(d.matrixWorldInverse),n.applyMatrix4(p),n.multiplyScalar(1/n.w),n.x*=v.x/2,n.y*=v.y/2,n.z=0,i.copy(n);var S=this.matrixWorld;r.multiplyMatrices(d.matrixWorldInverse,S);for(var x=0,w=b.count;x<w;x++){t.fromBufferAttribute(b,x),e.fromBufferAttribute(g,x),t.w=1,e.w=1,t.applyMatrix4(r),e.applyMatrix4(r),t.applyMatrix4(p),e.applyMatrix4(p),t.multiplyScalar(1/t.w),e.multiplyScalar(1/e.w);var B=t.z<-1&&e.z<-1,E=t.z>1&&e.z>1;if(!B&&!E){t.x*=v.x/2,t.y*=v.y/2,e.x*=v.x/2,e.y*=v.y/2,a.start.copy(t),a.start.z=0,a.end.copy(e),a.end.z=0;var A=a.closestPointToPointParameter(i,!0);a.at(A,o);var M=u.MathUtils.lerp(t.z,e.z,A),L=M>=-1&&M<=1,_=i.distanceTo(o)<.5*y;if(L&&_){a.start.fromBufferAttribute(b,x),a.end.fromBufferAttribute(g,x),a.start.applyMatrix4(S),a.end.applyMatrix4(S);var z=new u.Vector3,I=new u.Vector3;l.distanceSqToSegment(a.start,a.end,I,z),c.push({point:I,pointOnLine:z,distance:l.origin.distanceTo(I),object:this,face:null,faceIndex:x,uv:null,uv2:null})}}}}}()});var h=function(){o.call(this),this.type="LineGeometry"};h.prototype=Object.assign(Object.create(o.prototype),{constructor:h,isLineGeometry:!0,setPositions:function(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 o.prototype.setPositions.call(this,n),this},setColors:function(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 o.prototype.setColors.call(this,n),this},fromLine:function(t){var e=t.geometry;return e.isGeometry?this.setPositions(e.vertices):e.isBufferGeometry&&this.setPositions(e.position.array),this},copy:function(){return this}});var m=function(t,e){p.call(this),this.type="Line2",this.geometry=void 0!==t?t:new h,this.material=void 0!==e?e:new c({color:16777215*Math.random()})};m.prototype=Object.assign(Object.create(p.prototype),{constructor:m,isLine2:!0,copy:function(){return this}}),t.Line2=m,t.LineGeometry=h,t.LineMaterial=c,t.LineSegments2=p,t.LineSegmentsGeometry=o,Object.defineProperty(t,"__esModule",{value:!0})})); | ||
// Version 0.4.3 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})})); |
import { Box3, BufferGeometry, Float32BufferAttribute, InstancedBufferGeometry, InstancedInterleavedBuffer, InterleavedBufferAttribute, Sphere, Vector3, WireframeGeometry, Vector2, ShaderLib, ShaderMaterial, UniformsLib, UniformsUtils, Line3, MathUtils, Matrix4, Mesh, Vector4 } from 'three'; | ||
/** | ||
* @author WestLangley / http://github.com/WestLangley | ||
* | ||
*/ | ||
const THREE = window.THREE ? window.THREE // Prefer consumption from global THREE, if exists | ||
const THREE$2 = window.THREE ? window.THREE // Prefer consumption from global THREE, if exists | ||
: { | ||
@@ -20,30 +16,28 @@ Box3, | ||
var setAttributeFn = new THREE.BufferGeometry().setAttribute ? 'setAttribute' : 'addAttribute'; | ||
var setAttributeFn$1 = new THREE$2.BufferGeometry().setAttribute ? 'setAttribute' : 'addAttribute'; | ||
var LineSegmentsGeometry = function () { | ||
THREE.InstancedBufferGeometry.call(this); | ||
this.type = 'LineSegmentsGeometry'; | ||
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[setAttributeFn]('position', new THREE.Float32BufferAttribute(positions, 3)); | ||
this[setAttributeFn]('uv', new THREE.Float32BufferAttribute(uvs, 2)); | ||
}; | ||
const _box$1 = new THREE$2.Box3(); | ||
LineSegmentsGeometry.prototype = Object.assign(Object.create(THREE.InstancedBufferGeometry.prototype), { | ||
constructor: LineSegmentsGeometry, | ||
isLineSegmentsGeometry: true, | ||
applyMatrix: function (matrix) { | ||
console.warn('THREE.LineSegmentsGeometry: applyMatrix() has been renamed to applyMatrix4().'); | ||
return this.applyMatrix4(matrix); | ||
}, | ||
applyMatrix4: function (matrix) { | ||
var start = this.attributes.instanceStart; | ||
var end = this.attributes.instanceEnd; | ||
const _vector = new THREE$2.Vector3(); | ||
class LineSegmentsGeometry extends THREE$2.InstancedBufferGeometry { | ||
constructor() { | ||
super(); | ||
this.type = 'LineSegmentsGeometry'; | ||
const 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]; | ||
const uvs = [-1, 2, 1, 2, -1, 1, 1, 1, -1, -1, 1, -1, -1, -2, 1, -2]; | ||
const index = [0, 2, 1, 2, 3, 1, 2, 4, 3, 4, 5, 3, 4, 6, 5, 6, 7, 5]; | ||
this.setIndex(index); | ||
this[setAttributeFn$1]('position', new THREE$2.Float32BufferAttribute(positions, 3)); | ||
this[setAttributeFn$1]('uv', new THREE$2.Float32BufferAttribute(uvs, 2)); | ||
} | ||
applyMatrix4(matrix) { | ||
const start = this.attributes.instanceStart; | ||
const end = this.attributes.instanceEnd; | ||
if (start !== undefined) { | ||
matrix.applyToBufferAttribute(start); | ||
matrix.applyToBufferAttribute(end); | ||
start.data.needsUpdate = true; | ||
start.applyMatrix4(matrix); | ||
end.applyMatrix4(matrix); | ||
start.needsUpdate = true; | ||
} | ||
@@ -60,6 +54,7 @@ | ||
return this; | ||
}, | ||
setPositions: function (array) { | ||
var lineSegments; | ||
} | ||
setPositions(array) { | ||
let lineSegments; | ||
if (array instanceof Float32Array) { | ||
@@ -71,7 +66,7 @@ lineSegments = array; | ||
var instanceBuffer = new THREE.InstancedInterleavedBuffer(lineSegments, 6, 1); // xyz, xyz | ||
const instanceBuffer = new THREE$2.InstancedInterleavedBuffer(lineSegments, 6, 1); // xyz, xyz | ||
this[setAttributeFn]('instanceStart', new THREE.InterleavedBufferAttribute(instanceBuffer, 3, 0)); // xyz | ||
this[setAttributeFn$1]('instanceStart', new THREE$2.InterleavedBufferAttribute(instanceBuffer, 3, 0)); // xyz | ||
this[setAttributeFn]('instanceEnd', new THREE.InterleavedBufferAttribute(instanceBuffer, 3, 3)); // xyz | ||
this[setAttributeFn$1]('instanceEnd', new THREE$2.InterleavedBufferAttribute(instanceBuffer, 3, 3)); // xyz | ||
// | ||
@@ -82,6 +77,7 @@ | ||
return this; | ||
}, | ||
setColors: function (array) { | ||
var colors; | ||
} | ||
setColors(array) { | ||
let colors; | ||
if (array instanceof Float32Array) { | ||
@@ -93,30 +89,35 @@ colors = array; | ||
var instanceColorBuffer = new THREE.InstancedInterleavedBuffer(colors, 6, 1); // rgb, rgb | ||
const instanceColorBuffer = new THREE$2.InstancedInterleavedBuffer(colors, 6, 1); // rgb, rgb | ||
this[setAttributeFn]('instanceColorStart', new THREE.InterleavedBufferAttribute(instanceColorBuffer, 3, 0)); // rgb | ||
this[setAttributeFn$1]('instanceColorStart', new THREE$2.InterleavedBufferAttribute(instanceColorBuffer, 3, 0)); // rgb | ||
this[setAttributeFn]('instanceColorEnd', new THREE.InterleavedBufferAttribute(instanceColorBuffer, 3, 3)); // rgb | ||
this[setAttributeFn$1]('instanceColorEnd', new THREE$2.InterleavedBufferAttribute(instanceColorBuffer, 3, 3)); // rgb | ||
return this; | ||
}, | ||
fromWireframeGeometry: function (geometry) { | ||
} | ||
fromWireframeGeometry(geometry) { | ||
this.setPositions(geometry.attributes.position.array); | ||
return this; | ||
}, | ||
fromEdgesGeometry: function (geometry) { | ||
} | ||
fromEdgesGeometry(geometry) { | ||
this.setPositions(geometry.attributes.position.array); | ||
return this; | ||
}, | ||
fromMesh: function (mesh) { | ||
this.fromWireframeGeometry(new THREE.WireframeGeometry(mesh.geometry)); // set colors, maybe | ||
} | ||
fromMesh(mesh) { | ||
this.fromWireframeGeometry(new THREE$2.WireframeGeometry(mesh.geometry)); // set colors, maybe | ||
return this; | ||
}, | ||
fromLineSegements: function (lineSegments) { | ||
var geometry = lineSegments.geometry; | ||
} | ||
romLineSegments(lineSegments) { | ||
const geometry = lineSegments.geometry; | ||
if (geometry.isGeometry) { | ||
this.setPositions(geometry.vertices); | ||
console.error('LineSegmentsGeometry no longer supports Geometry. Use THREE.BufferGeometry instead.'); | ||
return; | ||
} else if (geometry.isBufferGeometry) { | ||
this.setPositions(geometry.position.array); // assumes non-indexed | ||
this.setPositions(geometry.attributes.position.array); // assumes non-indexed | ||
} // set colors, maybe | ||
@@ -126,69 +127,69 @@ | ||
return this; | ||
}, | ||
computeBoundingBox: function () { | ||
var box = new THREE.Box3(); | ||
return function computeBoundingBox() { | ||
if (this.boundingBox === null) { | ||
this.boundingBox = new THREE.Box3(); | ||
} | ||
} | ||
var start = this.attributes.instanceStart; | ||
var end = this.attributes.instanceEnd; | ||
computeBoundingBox() { | ||
if (this.boundingBox === null) { | ||
this.boundingBox = new THREE$2.Box3(); | ||
} | ||
if (start !== undefined && end !== undefined) { | ||
this.boundingBox.setFromBufferAttribute(start); | ||
box.setFromBufferAttribute(end); | ||
this.boundingBox.union(box); | ||
} | ||
}; | ||
}(), | ||
computeBoundingSphere: function () { | ||
var vector = new THREE.Vector3(); | ||
return function computeBoundingSphere() { | ||
if (this.boundingSphere === null) { | ||
this.boundingSphere = new THREE.Sphere(); | ||
} | ||
const start = this.attributes.instanceStart; | ||
const end = this.attributes.instanceEnd; | ||
if (this.boundingBox === null) { | ||
this.computeBoundingBox(); | ||
} | ||
if (start !== undefined && end !== undefined) { | ||
this.boundingBox.setFromBufferAttribute(start); | ||
var start = this.attributes.instanceStart; | ||
var end = this.attributes.instanceEnd; | ||
_box$1.setFromBufferAttribute(end); | ||
if (start !== undefined && end !== undefined) { | ||
var center = this.boundingSphere.center; | ||
this.boundingBox.getCenter(center); | ||
var maxRadiusSq = 0; | ||
this.boundingBox.union(_box$1); | ||
} | ||
} | ||
for (var i = 0, il = start.count; i < il; i++) { | ||
vector.fromBufferAttribute(start, i); | ||
maxRadiusSq = Math.max(maxRadiusSq, center.distanceToSquared(vector)); | ||
vector.fromBufferAttribute(end, i); | ||
maxRadiusSq = Math.max(maxRadiusSq, center.distanceToSquared(vector)); | ||
} | ||
computeBoundingSphere() { | ||
if (this.boundingSphere === null) { | ||
this.boundingSphere = new THREE$2.Sphere(); | ||
} | ||
this.boundingSphere.radius = Math.sqrt(maxRadiusSq); | ||
if (this.boundingBox === null) { | ||
this.computeBoundingBox(); | ||
} | ||
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); | ||
} | ||
const start = this.attributes.instanceStart; | ||
const end = this.attributes.instanceEnd; | ||
if (start !== undefined && end !== undefined) { | ||
const center = this.boundingSphere.center; | ||
this.boundingBox.getCenter(center); | ||
let maxRadiusSq = 0; | ||
for (let i = 0, il = start.count; i < il; i++) { | ||
_vector.fromBufferAttribute(start, i); | ||
maxRadiusSq = Math.max(maxRadiusSq, center.distanceToSquared(_vector)); | ||
_vector.fromBufferAttribute(end, i); | ||
maxRadiusSq = Math.max(maxRadiusSq, center.distanceToSquared(_vector)); | ||
} | ||
}; | ||
}(), | ||
toJSON: function () {// todo | ||
}, | ||
clone: function () {// todo | ||
}, | ||
copy: function () | ||
/* source */ | ||
{ | ||
// todo | ||
return this; | ||
this.boundingSphere.radius = Math.sqrt(maxRadiusSq); | ||
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); | ||
} | ||
} | ||
} | ||
}); | ||
toJSON() {// todo | ||
} | ||
applyMatrix(matrix) { | ||
console.warn('THREE.LineSegmentsGeometry: applyMatrix() has been renamed to applyMatrix4().'); | ||
return this.applyMatrix4(matrix); | ||
} | ||
} | ||
LineSegmentsGeometry.prototype.isLineSegmentsGeometry = true; | ||
/** | ||
* @author WestLangley / http://github.com/WestLangley | ||
* | ||
* parameters = { | ||
@@ -444,108 +445,116 @@ * color: <hex>, | ||
var LineMaterial = function (parameters) { | ||
THREE$1.ShaderMaterial.call(this, { | ||
type: 'LineMaterial', | ||
uniforms: THREE$1.UniformsUtils.clone(THREE$1.ShaderLib['line'].uniforms), | ||
vertexShader: THREE$1.ShaderLib['line'].vertexShader, | ||
fragmentShader: THREE$1.ShaderLib['line'].fragmentShader, | ||
clipping: true // required for clipping support | ||
class LineMaterial extends THREE$1.ShaderMaterial { | ||
constructor(parameters) { | ||
super({ | ||
type: 'LineMaterial', | ||
uniforms: THREE$1.UniformsUtils.clone(THREE$1.ShaderLib['line'].uniforms), | ||
vertexShader: THREE$1.ShaderLib['line'].vertexShader, | ||
fragmentShader: THREE$1.ShaderLib['line'].fragmentShader, | ||
clipping: true // required for clipping support | ||
}); | ||
this.dashed = false; | ||
Object.defineProperties(this, { | ||
color: { | ||
enumerable: true, | ||
get: function () { | ||
return this.uniforms.diffuse.value; | ||
}); | ||
this.dashed = false; | ||
Object.defineProperties(this, { | ||
color: { | ||
enumerable: true, | ||
get: function () { | ||
return this.uniforms.diffuse.value; | ||
}, | ||
set: function (value) { | ||
this.uniforms.diffuse.value = value; | ||
} | ||
}, | ||
set: function (value) { | ||
this.uniforms.diffuse.value = value; | ||
} | ||
}, | ||
linewidth: { | ||
enumerable: true, | ||
get: function () { | ||
return this.uniforms.linewidth.value; | ||
linewidth: { | ||
enumerable: true, | ||
get: function () { | ||
return this.uniforms.linewidth.value; | ||
}, | ||
set: function (value) { | ||
this.uniforms.linewidth.value = value; | ||
} | ||
}, | ||
set: function (value) { | ||
this.uniforms.linewidth.value = value; | ||
} | ||
}, | ||
dashScale: { | ||
enumerable: true, | ||
get: function () { | ||
return this.uniforms.dashScale.value; | ||
dashScale: { | ||
enumerable: true, | ||
get: function () { | ||
return this.uniforms.dashScale.value; | ||
}, | ||
set: function (value) { | ||
this.uniforms.dashScale.value = value; | ||
} | ||
}, | ||
set: function (value) { | ||
this.uniforms.dashScale.value = value; | ||
} | ||
}, | ||
dashSize: { | ||
enumerable: true, | ||
get: function () { | ||
return this.uniforms.dashSize.value; | ||
dashSize: { | ||
enumerable: true, | ||
get: function () { | ||
return this.uniforms.dashSize.value; | ||
}, | ||
set: function (value) { | ||
this.uniforms.dashSize.value = value; | ||
} | ||
}, | ||
set: function (value) { | ||
this.uniforms.dashSize.value = value; | ||
} | ||
}, | ||
dashOffset: { | ||
enumerable: true, | ||
get: function () { | ||
return this.uniforms.dashOffset.value; | ||
dashOffset: { | ||
enumerable: true, | ||
get: function () { | ||
return this.uniforms.dashOffset.value; | ||
}, | ||
set: function (value) { | ||
this.uniforms.dashOffset.value = value; | ||
} | ||
}, | ||
set: function (value) { | ||
this.uniforms.dashOffset.value = value; | ||
} | ||
}, | ||
gapSize: { | ||
enumerable: true, | ||
get: function () { | ||
return this.uniforms.gapSize.value; | ||
gapSize: { | ||
enumerable: true, | ||
get: function () { | ||
return this.uniforms.gapSize.value; | ||
}, | ||
set: function (value) { | ||
this.uniforms.gapSize.value = value; | ||
} | ||
}, | ||
set: function (value) { | ||
this.uniforms.gapSize.value = value; | ||
} | ||
}, | ||
opacity: { | ||
enumerable: true, | ||
get: function () { | ||
return this.uniforms.opacity.value; | ||
opacity: { | ||
enumerable: true, | ||
get: function () { | ||
return this.uniforms.opacity.value; | ||
}, | ||
set: function (value) { | ||
this.uniforms.opacity.value = value; | ||
} | ||
}, | ||
set: function (value) { | ||
this.uniforms.opacity.value = value; | ||
} | ||
}, | ||
resolution: { | ||
enumerable: true, | ||
get: function () { | ||
return this.uniforms.resolution.value; | ||
resolution: { | ||
enumerable: true, | ||
get: function () { | ||
return this.uniforms.resolution.value; | ||
}, | ||
set: function (value) { | ||
this.uniforms.resolution.value.copy(value); | ||
} | ||
}, | ||
set: function (value) { | ||
this.uniforms.resolution.value.copy(value); | ||
alphaToCoverage: { | ||
enumerable: true, | ||
get: function () { | ||
return Boolean('ALPHA_TO_COVERAGE' in this.defines); | ||
}, | ||
set: function (value) { | ||
if (Boolean(value) !== Boolean('ALPHA_TO_COVERAGE' in this.defines)) { | ||
this.needsUpdate = true; | ||
} | ||
if (value) { | ||
this.defines.ALPHA_TO_COVERAGE = ''; | ||
this.extensions.derivatives = true; | ||
} else { | ||
delete this.defines.ALPHA_TO_COVERAGE; | ||
this.extensions.derivatives = false; | ||
} | ||
} | ||
} | ||
} | ||
}); | ||
this.setValues(parameters); | ||
}; | ||
}); | ||
this.setValues(parameters); | ||
} | ||
LineMaterial.prototype = Object.create(THREE$1.ShaderMaterial.prototype); | ||
LineMaterial.prototype.constructor = LineMaterial; | ||
} | ||
LineMaterial.prototype.isLineMaterial = true; | ||
LineMaterial.prototype.copy = function (source) { | ||
THREE$1.ShaderMaterial.prototype.copy.call(this, source); | ||
this.color.copy(source.color); | ||
this.linewidth = source.linewidth; | ||
this.resolution = source.resolution; // todo | ||
return this; | ||
}; | ||
/** | ||
* @author WestLangley / http://github.com/WestLangley | ||
* | ||
*/ | ||
const THREE$2 = window.THREE ? window.THREE // Prefer consumption from global THREE, if exists | ||
const THREE = window.THREE ? window.THREE // Prefer consumption from global THREE, if exists | ||
: { | ||
Box3, | ||
BufferGeometry, | ||
@@ -558,2 +567,3 @@ InstancedInterleavedBuffer, | ||
Mesh, | ||
Sphere, | ||
Vector3, | ||
@@ -563,160 +573,260 @@ Vector4 | ||
var setAttributeFn$1 = new THREE$2.BufferGeometry().setAttribute ? 'setAttribute' : 'addAttribute'; | ||
var setAttributeFn = new THREE.BufferGeometry().setAttribute ? 'setAttribute' : 'addAttribute'; | ||
var LineSegments2 = function (geometry, material) { | ||
if (geometry === undefined) geometry = new LineSegmentsGeometry(); | ||
if (material === undefined) material = new LineMaterial({ | ||
const _start = new THREE.Vector3(); | ||
const _end = new THREE.Vector3(); | ||
const _start4 = new THREE.Vector4(); | ||
const _end4 = new THREE.Vector4(); | ||
const _ssOrigin = new THREE.Vector4(); | ||
const _ssOrigin3 = new THREE.Vector3(); | ||
const _mvMatrix = new THREE.Matrix4(); | ||
const _line = new THREE.Line3(); | ||
const _closestPoint = new THREE.Vector3(); | ||
const _box = new THREE.Box3(); | ||
const _sphere = new THREE.Sphere(); | ||
const _clipToWorldVector = new THREE.Vector4(); | ||
class LineSegments2 extends THREE.Mesh { | ||
constructor(geometry = new LineSegmentsGeometry(), material = new LineMaterial({ | ||
color: Math.random() * 0xffffff | ||
}); | ||
THREE$2.Mesh.call(this, geometry, material); | ||
this.type = 'LineSegments2'; | ||
}; | ||
})) { | ||
super(geometry, material); | ||
this.type = 'LineSegments2'; | ||
} // for backwards-compatability, but could be a method of LineSegmentsGeometry... | ||
LineSegments2.prototype = Object.assign(Object.create(THREE$2.Mesh.prototype), { | ||
constructor: LineSegments2, | ||
isLineSegments2: true, | ||
computeLineDistances: function () { | ||
// for backwards-compatability, but could be a method of LineSegmentsGeometry... | ||
var start = new THREE$2.Vector3(); | ||
var end = new THREE$2.Vector3(); | ||
return function computeLineDistances() { | ||
var geometry = this.geometry; | ||
var instanceStart = geometry.attributes.instanceStart; | ||
var instanceEnd = geometry.attributes.instanceEnd; | ||
var lineDistances = new Float32Array(2 * instanceStart.data.count); | ||
for (var i = 0, j = 0, l = instanceStart.data.count; i < l; i++, j += 2) { | ||
start.fromBufferAttribute(instanceStart, i); | ||
end.fromBufferAttribute(instanceEnd, i); | ||
lineDistances[j] = j === 0 ? 0 : lineDistances[j - 1]; | ||
lineDistances[j + 1] = lineDistances[j] + start.distanceTo(end); | ||
} | ||
computeLineDistances() { | ||
const geometry = this.geometry; | ||
const instanceStart = geometry.attributes.instanceStart; | ||
const instanceEnd = geometry.attributes.instanceEnd; | ||
const lineDistances = new Float32Array(2 * instanceStart.count); | ||
var instanceDistanceBuffer = new THREE$2.InstancedInterleavedBuffer(lineDistances, 2, 1); // d0, d1 | ||
for (let i = 0, j = 0, l = instanceStart.count; i < l; i++, j += 2) { | ||
_start.fromBufferAttribute(instanceStart, i); | ||
geometry[setAttributeFn$1]('instanceDistanceStart', new THREE$2.InterleavedBufferAttribute(instanceDistanceBuffer, 1, 0)); // d0 | ||
_end.fromBufferAttribute(instanceEnd, i); | ||
geometry[setAttributeFn$1]('instanceDistanceEnd', new THREE$2.InterleavedBufferAttribute(instanceDistanceBuffer, 1, 1)); // d1 | ||
lineDistances[j] = j === 0 ? 0 : lineDistances[j - 1]; | ||
lineDistances[j + 1] = lineDistances[j] + _start.distanceTo(_end); | ||
} | ||
return this; | ||
}; | ||
}(), | ||
raycast: function () { | ||
var start = new THREE$2.Vector4(); | ||
var end = new THREE$2.Vector4(); | ||
var ssOrigin = new THREE$2.Vector4(); | ||
var ssOrigin3 = new THREE$2.Vector3(); | ||
var mvMatrix = new THREE$2.Matrix4(); | ||
var line = new THREE$2.Line3(); | ||
var closestPoint = new THREE$2.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.'); | ||
} | ||
const instanceDistanceBuffer = new THREE.InstancedInterleavedBuffer(lineDistances, 2, 1); // d0, d1 | ||
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; // 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. | ||
geometry[setAttributeFn]('instanceDistanceStart', new THREE.InterleavedBufferAttribute(instanceDistanceBuffer, 1, 0)); // d0 | ||
ray.at(1, ssOrigin); // ndc space [ - 1.0, 1.0 ] | ||
geometry[setAttributeFn]('instanceDistanceEnd', new THREE.InterleavedBufferAttribute(instanceDistanceBuffer, 1, 1)); // d1 | ||
ssOrigin.w = 1; | ||
ssOrigin.applyMatrix4(camera.matrixWorldInverse); | ||
ssOrigin.applyMatrix4(projectionMatrix); | ||
ssOrigin.multiplyScalar(1 / ssOrigin.w); // screen space | ||
return this; | ||
} | ||
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); | ||
raycast(raycaster, intersects) { | ||
if (raycaster.camera === null) { | ||
console.error('LineSegments2: "Raycaster.camera" needs to be set in order to raycast against LineSegments2.'); | ||
} | ||
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 | ||
const threshold = raycaster.params.Line2 !== undefined ? raycaster.params.Line2.threshold || 0 : 0; | ||
const ray = raycaster.ray; | ||
const camera = raycaster.camera; | ||
const projectionMatrix = camera.projectionMatrix; | ||
const matrixWorld = this.matrixWorld; | ||
const geometry = this.geometry; | ||
const material = this.material; | ||
const resolution = material.resolution; | ||
const lineWidth = material.linewidth + threshold; | ||
const instanceStart = geometry.attributes.instanceStart; | ||
const instanceEnd = geometry.attributes.instanceEnd; // camera forward is negative | ||
start.applyMatrix4(mvMatrix); | ||
end.applyMatrix4(mvMatrix); // clip space | ||
const near = -camera.near; // clip space is [ - 1, 1 ] so multiply by two to get the full | ||
// width in clip space | ||
start.applyMatrix4(projectionMatrix); | ||
end.applyMatrix4(projectionMatrix); // ndc space [ - 1.0, 1.0 ] | ||
const ssMaxWidth = 2.0 * Math.max(lineWidth / resolution.width, lineWidth / resolution.height); // | ||
// check if we intersect the sphere bounds | ||
start.multiplyScalar(1 / start.w); | ||
end.multiplyScalar(1 / end.w); // skip the segment if it's outside the camera near and far planes | ||
if (geometry.boundingSphere === null) { | ||
geometry.computeBoundingSphere(); | ||
} | ||
var isBehindCameraNear = start.z < -1 && end.z < -1; | ||
var isPastCameraFar = start.z > 1 && end.z > 1; | ||
_sphere.copy(geometry.boundingSphere).applyMatrix4(matrixWorld); | ||
if (isBehindCameraNear || isPastCameraFar) { | ||
continue; | ||
} // screen space | ||
const distanceToSphere = Math.max(camera.near, _sphere.distanceToPoint(ray.origin)); // get the w component to scale the world space line width | ||
_clipToWorldVector.set(0, 0, -distanceToSphere, 1.0).applyMatrix4(camera.projectionMatrix); | ||
start.x *= resolution.x / 2; | ||
start.y *= resolution.y / 2; | ||
end.x *= resolution.x / 2; | ||
end.y *= resolution.y / 2; // create 2d segment | ||
_clipToWorldVector.multiplyScalar(1.0 / _clipToWorldVector.w); | ||
line.start.copy(start); | ||
line.start.z = 0; | ||
line.end.copy(end); | ||
line.end.z = 0; // get closest point on ray to segment | ||
_clipToWorldVector.applyMatrix4(camera.projectionMatrixInverse); // increase the sphere bounds by the worst case line screen space width | ||
var param = line.closestPointToPointParameter(ssOrigin3, true); | ||
line.at(param, closestPoint); // check if the intersection point is within clip space | ||
var zPos = THREE$2.MathUtils.lerp(start.z, end.z, param); | ||
var isInClipSpace = zPos >= -1 && zPos <= 1; | ||
var isInside = ssOrigin3.distanceTo(closestPoint) < lineWidth * 0.5; | ||
const sphereMargin = Math.abs(ssMaxWidth / _clipToWorldVector.w) * 0.5; | ||
_sphere.radius += sphereMargin; | ||
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$2.Vector3(); | ||
var point = new THREE$2.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 | ||
}); | ||
} | ||
if (raycaster.ray.intersectsSphere(_sphere) === false) { | ||
return; | ||
} // | ||
// check if we intersect the box bounds | ||
if (geometry.boundingBox === null) { | ||
geometry.computeBoundingBox(); | ||
} | ||
_box.copy(geometry.boundingBox).applyMatrix4(matrixWorld); | ||
const distanceToBox = Math.max(camera.near, _box.distanceToPoint(ray.origin)); // get the w component to scale the world space line width | ||
_clipToWorldVector.set(0, 0, -distanceToBox, 1.0).applyMatrix4(camera.projectionMatrix); | ||
_clipToWorldVector.multiplyScalar(1.0 / _clipToWorldVector.w); | ||
_clipToWorldVector.applyMatrix4(camera.projectionMatrixInverse); // increase the sphere bounds by the worst case line screen space width | ||
const boxMargin = Math.abs(ssMaxWidth / _clipToWorldVector.w) * 0.5; | ||
_box.max.x += boxMargin; | ||
_box.max.y += boxMargin; | ||
_box.max.z += boxMargin; | ||
_box.min.x -= boxMargin; | ||
_box.min.y -= boxMargin; | ||
_box.min.z -= boxMargin; | ||
if (raycaster.ray.intersectsBox(_box) === false) { | ||
return; | ||
} // | ||
// 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); | ||
_mvMatrix.multiplyMatrices(camera.matrixWorldInverse, matrixWorld); | ||
for (let i = 0, l = instanceStart.count; i < l; i++) { | ||
_start4.fromBufferAttribute(instanceStart, i); | ||
_end4.fromBufferAttribute(instanceEnd, i); | ||
_start.w = 1; | ||
_end.w = 1; // camera space | ||
_start4.applyMatrix4(_mvMatrix); | ||
_end4.applyMatrix4(_mvMatrix); // skip the segment if it's entirely behind the camera | ||
var isBehindCameraNear = _start4.z > near && _end4.z > near; | ||
if (isBehindCameraNear) { | ||
continue; | ||
} // trim the segment if it extends behind camera near | ||
if (_start4.z > near) { | ||
const deltaDist = _start4.z - _end4.z; | ||
const t = (_start4.z - near) / deltaDist; | ||
_start4.lerp(_end4, t); | ||
} else if (_end4.z > near) { | ||
const deltaDist = _end4.z - _start4.z; | ||
const t = (_end4.z - near) / deltaDist; | ||
_end4.lerp(_start4, t); | ||
} // clip space | ||
_start4.applyMatrix4(projectionMatrix); | ||
_end4.applyMatrix4(projectionMatrix); // ndc space [ - 1.0, 1.0 ] | ||
_start4.multiplyScalar(1 / _start4.w); | ||
_end4.multiplyScalar(1 / _end4.w); // screen space | ||
_start4.x *= resolution.x / 2; | ||
_start4.y *= resolution.y / 2; | ||
_end4.x *= resolution.x / 2; | ||
_end4.y *= resolution.y / 2; // create 2d segment | ||
_line.start.copy(_start4); | ||
_line.start.z = 0; | ||
_line.end.copy(_end4); | ||
_line.end.z = 0; // get closest point on ray to segment | ||
const param = _line.closestPointToPointParameter(_ssOrigin3, true); | ||
_line.at(param, _closestPoint); // check if the intersection point is within clip space | ||
const zPos = THREE.MathUtils.lerp(_start4.z, _end4.z, param); | ||
const isInClipSpace = zPos >= -1 && zPos <= 1; | ||
const 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); | ||
const pointOnLine = new THREE.Vector3(); | ||
const 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 | ||
* | ||
*/ | ||
} | ||
var LineGeometry = function () { | ||
LineSegmentsGeometry.call(this); | ||
this.type = 'LineGeometry'; | ||
}; | ||
LineSegments2.prototype.LineSegments2 = true; | ||
LineGeometry.prototype = Object.assign(Object.create(LineSegmentsGeometry.prototype), { | ||
constructor: LineGeometry, | ||
isLineGeometry: true, | ||
setPositions: function (array) { | ||
class LineGeometry extends LineSegmentsGeometry { | ||
constructor() { | ||
super(); | ||
this.type = 'LineGeometry'; | ||
} | ||
setPositions(array) { | ||
// converts [ x1, y1, z1, x2, y2, z2, ... ] to pairs format | ||
@@ -735,6 +845,7 @@ var length = array.length - 3; | ||
LineSegmentsGeometry.prototype.setPositions.call(this, points); | ||
super.setPositions(points); | ||
return this; | ||
}, | ||
setColors: function (array) { | ||
} | ||
setColors(array) { | ||
// converts [ r1, g1, b1, r2, g2, b2, ... ] to pairs format | ||
@@ -753,12 +864,14 @@ var length = array.length - 3; | ||
LineSegmentsGeometry.prototype.setColors.call(this, colors); | ||
super.setColors(colors); | ||
return this; | ||
}, | ||
fromLine: function (line) { | ||
} | ||
fromLine(line) { | ||
var geometry = line.geometry; | ||
if (geometry.isGeometry) { | ||
this.setPositions(geometry.vertices); | ||
console.error('LineGeometry no longer supports Geometry. Use THREE.BufferGeometry instead.'); | ||
return; | ||
} else if (geometry.isBufferGeometry) { | ||
this.setPositions(geometry.position.array); // assumes non-indexed | ||
this.setPositions(geometry.attributes.position.array); // assumes non-indexed | ||
} // set colors, maybe | ||
@@ -768,36 +881,25 @@ | ||
return this; | ||
}, | ||
copy: function () | ||
/* source */ | ||
{ | ||
} | ||
copy() { | ||
// todo | ||
return this; | ||
} | ||
}); | ||
/** | ||
* @author WestLangley / http://github.com/WestLangley | ||
* | ||
*/ | ||
} | ||
var Line2 = function (geometry, material) { | ||
LineSegments2.call(this); | ||
this.type = 'Line2'; | ||
this.geometry = geometry !== undefined ? geometry : new LineGeometry(); | ||
this.material = material !== undefined ? material : new LineMaterial({ | ||
LineGeometry.prototype.isLineGeometry = true; | ||
class Line2 extends LineSegments2 { | ||
constructor(geometry = new LineGeometry(), material = new LineMaterial({ | ||
color: Math.random() * 0xffffff | ||
}); | ||
}; | ||
Line2.prototype = Object.assign(Object.create(LineSegments2.prototype), { | ||
constructor: Line2, | ||
isLine2: true, | ||
copy: function () | ||
/* source */ | ||
{ | ||
// todo | ||
return this; | ||
})) { | ||
super(geometry, material); | ||
this.type = 'Line2'; | ||
} | ||
}); | ||
} | ||
Line2.prototype.isLine2 = true; | ||
export { Line2, LineGeometry, LineMaterial, LineSegments2, LineSegmentsGeometry }; |
{ | ||
"name": "three-fatline", | ||
"version": "0.4.2", | ||
"version": "0.4.3", | ||
"description": "A ThreeJS Line object with variable width", | ||
@@ -42,16 +42,16 @@ "unpkg": "dist/three-fatline.min.js", | ||
"devDependencies": { | ||
"@babel/core": "^7.12.10", | ||
"@babel/plugin-proposal-class-properties": "^7.12.1", | ||
"@babel/plugin-proposal-object-rest-spread": "^7.12.1", | ||
"@babel/preset-env": "^7.12.11", | ||
"@rollup/plugin-babel": "^5.2.2", | ||
"@rollup/plugin-commonjs": "^17.0.0", | ||
"@rollup/plugin-node-resolve": "^11.1.0", | ||
"@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", | ||
"@rollup/plugin-babel": "^5.3.0", | ||
"@rollup/plugin-commonjs": "^18.0.0", | ||
"@rollup/plugin-node-resolve": "^11.2.1", | ||
"@types/three": ">=0.84.0", | ||
"rimraf": "^3.0.2", | ||
"rollup": "^2.38.0", | ||
"rollup-plugin-dts": "^2.0.1", | ||
"rollup": "^2.45.2", | ||
"rollup-plugin-dts": "^3.0.1", | ||
"rollup-plugin-terser": "^7.0.2", | ||
"typescript": "^4.1.3" | ||
"typescript": "^4.2.4" | ||
} | ||
} |
Sorry, the diff of this file is not supported yet
156889
2097