mascot-vis 1.7.4 → 1.7.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/mascot-min.js +21 -21
- package/dist/mascot.js +1254 -28
- package/package.json +1 -1
package/dist/mascot.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
/* eslint-disable */
|
|
2
|
-
// version: 1.7.
|
|
2
|
+
// version: 1.7.5
|
|
3
3
|
(function (global, factory) {
|
|
4
|
-
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('d3'), require('pixi.js')) :
|
|
5
|
-
typeof define === 'function' && define.amd ? define(['exports', 'd3', 'pixi.js'], factory) :
|
|
6
|
-
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.msc = {}, global.d3, global.PIXI));
|
|
7
|
-
}(this, (function (exports, d3, PIXI) { 'use strict';
|
|
4
|
+
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('d3'), require('three'), require('pixi.js')) :
|
|
5
|
+
typeof define === 'function' && define.amd ? define(['exports', 'd3', 'three', 'pixi.js'], factory) :
|
|
6
|
+
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.msc = {}, global.d3, global.THREE, global.PIXI));
|
|
7
|
+
}(this, (function (exports, d3, THREE, PIXI) { 'use strict';
|
|
8
8
|
|
|
9
9
|
function _interopNamespace(e) {
|
|
10
10
|
if (e && e.__esModule) return e;
|
|
@@ -27,6 +27,7 @@
|
|
|
27
27
|
}
|
|
28
28
|
|
|
29
29
|
var d3__namespace = /*#__PURE__*/_interopNamespace(d3);
|
|
30
|
+
var THREE__namespace = /*#__PURE__*/_interopNamespace(THREE);
|
|
30
31
|
var PIXI__namespace = /*#__PURE__*/_interopNamespace(PIXI);
|
|
31
32
|
|
|
32
33
|
class Rectangle {
|
|
@@ -1980,12 +1981,36 @@
|
|
|
1980
1981
|
}
|
|
1981
1982
|
|
|
1982
1983
|
contains(x, y) {
|
|
1984
|
+
let svgData = this.getSVGPathData();
|
|
1985
|
+
if (svgData !== "") {
|
|
1986
|
+
let ctx = CanvasProvider.getContext(),
|
|
1987
|
+
p = new Path2D(svgData);
|
|
1988
|
+
ctx.lineWidth = Math.max(this.strokeWidth, 2.5);
|
|
1989
|
+
ctx.stroke(p);
|
|
1990
|
+
return ctx.isPointInPath(p, x, y);
|
|
1991
|
+
}
|
|
1983
1992
|
if (!this._bounds) {
|
|
1984
1993
|
this._updateBounds();
|
|
1985
1994
|
}
|
|
1986
1995
|
return this._bounds.contains(x, y);
|
|
1987
1996
|
}
|
|
1988
1997
|
|
|
1998
|
+
getSVGPathData() {
|
|
1999
|
+
let d = "";
|
|
2000
|
+
for (let i of this.children) {
|
|
2001
|
+
if (i.getSVGPathData)
|
|
2002
|
+
d += i.getSVGPathData();
|
|
2003
|
+
else if (i.bounds) {
|
|
2004
|
+
let b = i.bounds;
|
|
2005
|
+
d += ["M", b.left, b.top].join(" ");
|
|
2006
|
+
d += ["L", b.right, b.top].join(" ");
|
|
2007
|
+
d += ["L", b.right, b.bottom].join(" ");
|
|
2008
|
+
d += ["L", b.left, b.bottom, "Z"].join(" ");
|
|
2009
|
+
}
|
|
2010
|
+
}
|
|
2011
|
+
return d;
|
|
2012
|
+
}
|
|
2013
|
+
|
|
1989
2014
|
toJSON() {
|
|
1990
2015
|
let json = {};
|
|
1991
2016
|
json.type = this.type;
|
|
@@ -2738,7 +2763,8 @@
|
|
|
2738
2763
|
case ItemType.Ring:
|
|
2739
2764
|
return _doRingDivide(scene, compnt, orientation, f, datatable);
|
|
2740
2765
|
case ItemType.Pie:
|
|
2741
|
-
|
|
2766
|
+
case ItemType.Arc:
|
|
2767
|
+
return _doArcDivide(scene, compnt, orientation, f, datatable);
|
|
2742
2768
|
}
|
|
2743
2769
|
|
|
2744
2770
|
}
|
|
@@ -2936,7 +2962,7 @@
|
|
|
2936
2962
|
return toReturn;
|
|
2937
2963
|
}
|
|
2938
2964
|
|
|
2939
|
-
function
|
|
2965
|
+
function _doArcDivide(scene, compnt, o, field, datatable) {
|
|
2940
2966
|
let toReturn, orientation = o ? o : Orientation.Radial;
|
|
2941
2967
|
let peers = getPeers(compnt, scene);
|
|
2942
2968
|
let collClassId;
|
|
@@ -3986,9 +4012,6 @@
|
|
|
3986
4012
|
|
|
3987
4013
|
encoding._map = function() {
|
|
3988
4014
|
switch (this.datatable.getFieldType(this.field)) {
|
|
3989
|
-
case DataType.Date:
|
|
3990
|
-
break;
|
|
3991
|
-
|
|
3992
4015
|
case DataType.Boolean:
|
|
3993
4016
|
if (!this.scale) {
|
|
3994
4017
|
this.scale = createScale("ordinalColor");
|
|
@@ -4012,7 +4035,7 @@
|
|
|
4012
4035
|
}
|
|
4013
4036
|
break;
|
|
4014
4037
|
|
|
4015
|
-
default: //
|
|
4038
|
+
default: //number or date
|
|
4016
4039
|
if (this.scale) {
|
|
4017
4040
|
if (!this._mapping) {
|
|
4018
4041
|
let values = this.scale.domain.concat(this.data);
|
|
@@ -4241,10 +4264,11 @@
|
|
|
4241
4264
|
if (channel === "width" || channel === "height") {
|
|
4242
4265
|
let closestLayout = getClosestLayout(this.areas[0]);
|
|
4243
4266
|
if (closestLayout) {
|
|
4244
|
-
let vidx = 0;
|
|
4245
|
-
for (let area of this.areas) {
|
|
4246
|
-
let cb =
|
|
4247
|
-
|
|
4267
|
+
let vidx = 0, cellBounds = this.areas.map(d => getCellBoundsInLayout(d)), layouts = this.areas.map(d => getClosestLayout(d));
|
|
4268
|
+
for (let [aidx, area] of this.areas.entries()) {
|
|
4269
|
+
let cb = cellBounds[aidx], layout = layouts[aidx];
|
|
4270
|
+
// let cb = getCellBoundsInLayout(area),
|
|
4271
|
+
// layout = getClosestLayout(area);
|
|
4248
4272
|
for (let i = 0; i < area.vertices.length; i++) {
|
|
4249
4273
|
let v = this._vertices[i + vidx],
|
|
4250
4274
|
dx, dy;
|
|
@@ -4633,7 +4657,7 @@
|
|
|
4633
4657
|
switch (this.channel) {
|
|
4634
4658
|
case "width":
|
|
4635
4659
|
case "height": {
|
|
4636
|
-
let vertices = getPeers(item.firstVertex, this.scene);
|
|
4660
|
+
let vertices = this._vertices; // getPeers(item.firstVertex, this.scene);
|
|
4637
4661
|
let offset = alignment ? Math.max(...vertices.map(d => d["y"])) : Math.min(...vertices.map(d => d["y"]));
|
|
4638
4662
|
return alignment ? [offset, offset - this.scale.rangeExtent] : [offset + this.scale.rangeExtent, offset];
|
|
4639
4663
|
}
|
|
@@ -6608,6 +6632,7 @@
|
|
|
6608
6632
|
case DataType.String:
|
|
6609
6633
|
this._createCategoricalColorLegend(scene, f);
|
|
6610
6634
|
break;
|
|
6635
|
+
case DataType.Date:
|
|
6611
6636
|
case DataType.Number:
|
|
6612
6637
|
case DataType.Integer:
|
|
6613
6638
|
this._createNumericalColorLegend(scene, f);
|
|
@@ -6662,21 +6687,27 @@
|
|
|
6662
6687
|
});
|
|
6663
6688
|
}
|
|
6664
6689
|
} else {
|
|
6665
|
-
let domain = this.encoding.scale.domain;
|
|
6666
|
-
let stops = [], uniqueVals = uniqueNumbers(this.encoding.data);
|
|
6690
|
+
let domain = this.encoding.scale.domain, dt = this.encoding.datatable, ft = dt.getFieldType(f);
|
|
6691
|
+
let stops = [], uniqueVals = ft === DataType.Date? dt.getUniqueFieldValues(f) : uniqueNumbers(this.encoding.data);
|
|
6667
6692
|
if (uniqueVals.length <= 10){
|
|
6668
6693
|
stops = uniqueVals;
|
|
6669
6694
|
stops.sort((a, b) => a - b);
|
|
6670
6695
|
} else {
|
|
6671
|
-
|
|
6672
|
-
|
|
6673
|
-
|
|
6674
|
-
|
|
6675
|
-
|
|
6676
|
-
interval
|
|
6677
|
-
|
|
6696
|
+
if (ft === DataType.Date) {
|
|
6697
|
+
uniqueVals.sort((a, b) => a - b);
|
|
6698
|
+
for (let i = 0; i < uniqueVals.length; i+= Math.ceil(uniqueVals.length/10))
|
|
6699
|
+
stops.push(uniqueVals[i]);
|
|
6700
|
+
} else {
|
|
6701
|
+
let interval = (domain[1] - domain[0])/9;
|
|
6702
|
+
for (let i = 0; i < 10; i++)
|
|
6703
|
+
stops.push(domain[0] + i * interval);
|
|
6704
|
+
let decimalPlaces = 0;
|
|
6705
|
+
while (interval < 1) {
|
|
6706
|
+
interval *= 10;
|
|
6707
|
+
decimalPlaces++;
|
|
6708
|
+
}
|
|
6709
|
+
stops = stops.map(d => d.toFixed(decimalPlaces));
|
|
6678
6710
|
}
|
|
6679
|
-
stops = stops.map(d => d.toFixed(decimalPlaces));
|
|
6680
6711
|
}
|
|
6681
6712
|
if (this._orientation == Orientation.Vertical) {
|
|
6682
6713
|
gradient = new LinearGradient({x1: 0, y1: 100, x2: 0, y2: 0});
|
|
@@ -6685,7 +6716,7 @@
|
|
|
6685
6716
|
gradient.addStop(p*100, this.encoding.scale.map(d), 1.0);
|
|
6686
6717
|
let tk = scene.mark("line", {"x1": this._x + wd, "x2": this._x + wd + tickSize, "y1": this._y + ht - p * ht + titleSize, "y2": this._y + ht - p * ht + titleSize, "strokeColor": this._strokeColor});
|
|
6687
6718
|
ticks.push(tk);
|
|
6688
|
-
let t = scene.mark("text", {fillColor: this._textColor, "text": d, x: this._x + wd + offset + tickSize, y: this._y + ht - p * ht + titleSize, "anchor": ["left", "middle"]});
|
|
6719
|
+
let t = scene.mark("text", {fillColor: this._textColor, "text": ft === DataType.Date? dt.getRawValue(f, d) : d, x: this._x + wd + offset + tickSize, y: this._y + ht - p * ht + titleSize, "anchor": ["left", "middle"]});
|
|
6689
6720
|
texts.push(t);
|
|
6690
6721
|
});
|
|
6691
6722
|
} else {
|
|
@@ -6695,7 +6726,7 @@
|
|
|
6695
6726
|
gradient.addStop(p*100, this.encoding.scale.map(d), 1.0);
|
|
6696
6727
|
let tk = scene.mark("line", {"x1": this._x + p * wd, "x2": this._x + p * wd, "y1": this._y + ht + titleSize, "y2": this._y + ht + tickSize + titleSize, "strokeColor": this._strokeColor});
|
|
6697
6728
|
ticks.push(tk);
|
|
6698
|
-
let t = scene.mark("text", {fillColor: this._textColor, "text": d, x: this._x + p * wd, y: this._y + ht + offset + titleSize, "anchor": ["center", "top"]});
|
|
6729
|
+
let t = scene.mark("text", {fillColor: this._textColor, "text": ft === DataType.Date? dt.getRawValue(f, d) : d, x: this._x + p * wd, y: this._y + ht + offset + titleSize, "anchor": ["center", "top"]});
|
|
6699
6730
|
texts.push(t);
|
|
6700
6731
|
});
|
|
6701
6732
|
}
|
|
@@ -9084,6 +9115,7 @@
|
|
|
9084
9115
|
}
|
|
9085
9116
|
|
|
9086
9117
|
let layout = getClosestLayout(item);
|
|
9118
|
+
if (!layout || (layout.type !== LayoutType.Grid && layout.type !== LayoutType.Stack)) return;
|
|
9087
9119
|
|
|
9088
9120
|
if (layout && (channel == "x" || channel == "y")) {
|
|
9089
9121
|
let group = layout.group,
|
|
@@ -11576,6 +11608,1200 @@
|
|
|
11576
11608
|
}
|
|
11577
11609
|
}
|
|
11578
11610
|
|
|
11611
|
+
const _box$1 = new THREE__namespace.Box3();
|
|
11612
|
+
|
|
11613
|
+
const _vector = new THREE__namespace.Vector3();
|
|
11614
|
+
|
|
11615
|
+
class LineSegmentsGeometry extends THREE__namespace.InstancedBufferGeometry {
|
|
11616
|
+
|
|
11617
|
+
constructor() {
|
|
11618
|
+
|
|
11619
|
+
super();
|
|
11620
|
+
this.type = 'LineSegmentsGeometry';
|
|
11621
|
+
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 ];
|
|
11622
|
+
const uvs = [ - 1, 2, 1, 2, - 1, 1, 1, 1, - 1, - 1, 1, - 1, - 1, - 2, 1, - 2 ];
|
|
11623
|
+
const index = [ 0, 2, 1, 2, 3, 1, 2, 4, 3, 4, 5, 3, 4, 6, 5, 6, 7, 5 ];
|
|
11624
|
+
this.setIndex( index );
|
|
11625
|
+
this.setAttribute( 'position', new THREE__namespace.Float32BufferAttribute( positions, 3 ) );
|
|
11626
|
+
this.setAttribute( 'uv', new THREE__namespace.Float32BufferAttribute( uvs, 2 ) );
|
|
11627
|
+
|
|
11628
|
+
}
|
|
11629
|
+
|
|
11630
|
+
applyMatrix4( matrix ) {
|
|
11631
|
+
|
|
11632
|
+
const start = this.attributes.instanceStart;
|
|
11633
|
+
const end = this.attributes.instanceEnd;
|
|
11634
|
+
|
|
11635
|
+
if ( start !== undefined ) {
|
|
11636
|
+
|
|
11637
|
+
start.applyMatrix4( matrix );
|
|
11638
|
+
end.applyMatrix4( matrix );
|
|
11639
|
+
start.needsUpdate = true;
|
|
11640
|
+
|
|
11641
|
+
}
|
|
11642
|
+
|
|
11643
|
+
if ( this.boundingBox !== null ) {
|
|
11644
|
+
|
|
11645
|
+
this.computeBoundingBox();
|
|
11646
|
+
|
|
11647
|
+
}
|
|
11648
|
+
|
|
11649
|
+
if ( this.boundingSphere !== null ) {
|
|
11650
|
+
|
|
11651
|
+
this.computeBoundingSphere();
|
|
11652
|
+
|
|
11653
|
+
}
|
|
11654
|
+
|
|
11655
|
+
return this;
|
|
11656
|
+
|
|
11657
|
+
}
|
|
11658
|
+
|
|
11659
|
+
setPositions( array ) {
|
|
11660
|
+
|
|
11661
|
+
let lineSegments;
|
|
11662
|
+
|
|
11663
|
+
if ( array instanceof Float32Array ) {
|
|
11664
|
+
|
|
11665
|
+
lineSegments = array;
|
|
11666
|
+
|
|
11667
|
+
} else if ( Array.isArray( array ) ) {
|
|
11668
|
+
|
|
11669
|
+
lineSegments = new Float32Array( array );
|
|
11670
|
+
|
|
11671
|
+
}
|
|
11672
|
+
|
|
11673
|
+
const instanceBuffer = new THREE__namespace.InstancedInterleavedBuffer( lineSegments, 6, 1 ); // xyz, xyz
|
|
11674
|
+
|
|
11675
|
+
this.setAttribute( 'instanceStart', new THREE__namespace.InterleavedBufferAttribute( instanceBuffer, 3, 0 ) ); // xyz
|
|
11676
|
+
|
|
11677
|
+
this.setAttribute( 'instanceEnd', new THREE__namespace.InterleavedBufferAttribute( instanceBuffer, 3, 3 ) ); // xyz
|
|
11678
|
+
//
|
|
11679
|
+
|
|
11680
|
+
this.computeBoundingBox();
|
|
11681
|
+
this.computeBoundingSphere();
|
|
11682
|
+
return this;
|
|
11683
|
+
|
|
11684
|
+
}
|
|
11685
|
+
|
|
11686
|
+
setColors( array ) {
|
|
11687
|
+
|
|
11688
|
+
let colors;
|
|
11689
|
+
|
|
11690
|
+
if ( array instanceof Float32Array ) {
|
|
11691
|
+
|
|
11692
|
+
colors = array;
|
|
11693
|
+
|
|
11694
|
+
} else if ( Array.isArray( array ) ) {
|
|
11695
|
+
|
|
11696
|
+
colors = new Float32Array( array );
|
|
11697
|
+
|
|
11698
|
+
}
|
|
11699
|
+
|
|
11700
|
+
const instanceColorBuffer = new THREE__namespace.InstancedInterleavedBuffer( colors, 6, 1 ); // rgb, rgb
|
|
11701
|
+
|
|
11702
|
+
this.setAttribute( 'instanceColorStart', new THREE__namespace.InterleavedBufferAttribute( instanceColorBuffer, 3, 0 ) ); // rgb
|
|
11703
|
+
|
|
11704
|
+
this.setAttribute( 'instanceColorEnd', new THREE__namespace.InterleavedBufferAttribute( instanceColorBuffer, 3, 3 ) ); // rgb
|
|
11705
|
+
|
|
11706
|
+
return this;
|
|
11707
|
+
|
|
11708
|
+
}
|
|
11709
|
+
|
|
11710
|
+
fromWireframeGeometry( geometry ) {
|
|
11711
|
+
|
|
11712
|
+
this.setPositions( geometry.attributes.position.array );
|
|
11713
|
+
return this;
|
|
11714
|
+
|
|
11715
|
+
}
|
|
11716
|
+
|
|
11717
|
+
fromEdgesGeometry( geometry ) {
|
|
11718
|
+
|
|
11719
|
+
this.setPositions( geometry.attributes.position.array );
|
|
11720
|
+
return this;
|
|
11721
|
+
|
|
11722
|
+
}
|
|
11723
|
+
|
|
11724
|
+
fromMesh( mesh ) {
|
|
11725
|
+
|
|
11726
|
+
this.fromWireframeGeometry( new THREE__namespace.WireframeGeometry( mesh.geometry ) ); // set colors, maybe
|
|
11727
|
+
|
|
11728
|
+
return this;
|
|
11729
|
+
|
|
11730
|
+
}
|
|
11731
|
+
|
|
11732
|
+
fromLineSegments( lineSegments ) {
|
|
11733
|
+
|
|
11734
|
+
const geometry = lineSegments.geometry;
|
|
11735
|
+
|
|
11736
|
+
if ( geometry.isGeometry ) {
|
|
11737
|
+
|
|
11738
|
+
console.error( 'THREE.LineSegmentsGeometry no longer supports Geometry. Use THREE.BufferGeometry instead.' );
|
|
11739
|
+
return;
|
|
11740
|
+
|
|
11741
|
+
} else if ( geometry.isBufferGeometry ) {
|
|
11742
|
+
|
|
11743
|
+
this.setPositions( geometry.attributes.position.array ); // assumes non-indexed
|
|
11744
|
+
|
|
11745
|
+
} // set colors, maybe
|
|
11746
|
+
|
|
11747
|
+
|
|
11748
|
+
return this;
|
|
11749
|
+
|
|
11750
|
+
}
|
|
11751
|
+
|
|
11752
|
+
computeBoundingBox() {
|
|
11753
|
+
|
|
11754
|
+
if ( this.boundingBox === null ) {
|
|
11755
|
+
|
|
11756
|
+
this.boundingBox = new THREE__namespace.Box3();
|
|
11757
|
+
|
|
11758
|
+
}
|
|
11759
|
+
|
|
11760
|
+
const start = this.attributes.instanceStart;
|
|
11761
|
+
const end = this.attributes.instanceEnd;
|
|
11762
|
+
|
|
11763
|
+
if ( start !== undefined && end !== undefined ) {
|
|
11764
|
+
|
|
11765
|
+
this.boundingBox.setFromBufferAttribute( start );
|
|
11766
|
+
|
|
11767
|
+
_box$1.setFromBufferAttribute( end );
|
|
11768
|
+
|
|
11769
|
+
this.boundingBox.union( _box$1 );
|
|
11770
|
+
|
|
11771
|
+
}
|
|
11772
|
+
|
|
11773
|
+
}
|
|
11774
|
+
|
|
11775
|
+
computeBoundingSphere() {
|
|
11776
|
+
|
|
11777
|
+
if ( this.boundingSphere === null ) {
|
|
11778
|
+
|
|
11779
|
+
this.boundingSphere = new THREE__namespace.Sphere();
|
|
11780
|
+
|
|
11781
|
+
}
|
|
11782
|
+
|
|
11783
|
+
if ( this.boundingBox === null ) {
|
|
11784
|
+
|
|
11785
|
+
this.computeBoundingBox();
|
|
11786
|
+
|
|
11787
|
+
}
|
|
11788
|
+
|
|
11789
|
+
const start = this.attributes.instanceStart;
|
|
11790
|
+
const end = this.attributes.instanceEnd;
|
|
11791
|
+
|
|
11792
|
+
if ( start !== undefined && end !== undefined ) {
|
|
11793
|
+
|
|
11794
|
+
const center = this.boundingSphere.center;
|
|
11795
|
+
this.boundingBox.getCenter( center );
|
|
11796
|
+
let maxRadiusSq = 0;
|
|
11797
|
+
|
|
11798
|
+
for ( let i = 0, il = start.count; i < il; i ++ ) {
|
|
11799
|
+
|
|
11800
|
+
_vector.fromBufferAttribute( start, i );
|
|
11801
|
+
|
|
11802
|
+
maxRadiusSq = Math.max( maxRadiusSq, center.distanceToSquared( _vector ) );
|
|
11803
|
+
|
|
11804
|
+
_vector.fromBufferAttribute( end, i );
|
|
11805
|
+
|
|
11806
|
+
maxRadiusSq = Math.max( maxRadiusSq, center.distanceToSquared( _vector ) );
|
|
11807
|
+
|
|
11808
|
+
}
|
|
11809
|
+
|
|
11810
|
+
this.boundingSphere.radius = Math.sqrt( maxRadiusSq );
|
|
11811
|
+
|
|
11812
|
+
if ( isNaN( this.boundingSphere.radius ) ) {
|
|
11813
|
+
|
|
11814
|
+
console.error( 'THREE.LineSegmentsGeometry.computeBoundingSphere(): Computed radius is NaN. The instanced position data is likely to have NaN values.', this );
|
|
11815
|
+
|
|
11816
|
+
}
|
|
11817
|
+
|
|
11818
|
+
}
|
|
11819
|
+
|
|
11820
|
+
}
|
|
11821
|
+
|
|
11822
|
+
toJSON() { // todo
|
|
11823
|
+
}
|
|
11824
|
+
|
|
11825
|
+
applyMatrix( matrix ) {
|
|
11826
|
+
|
|
11827
|
+
console.warn( 'THREE.LineSegmentsGeometry: applyMatrix() has been renamed to applyMatrix4().' );
|
|
11828
|
+
return this.applyMatrix4( matrix );
|
|
11829
|
+
|
|
11830
|
+
}
|
|
11831
|
+
|
|
11832
|
+
}
|
|
11833
|
+
|
|
11834
|
+
LineSegmentsGeometry.prototype.isLineSegmentsGeometry = true;
|
|
11835
|
+
|
|
11836
|
+
class LineGeometry extends LineSegmentsGeometry {
|
|
11837
|
+
|
|
11838
|
+
constructor() {
|
|
11839
|
+
|
|
11840
|
+
super();
|
|
11841
|
+
this.type = 'LineGeometry';
|
|
11842
|
+
|
|
11843
|
+
}
|
|
11844
|
+
|
|
11845
|
+
setPositions( array ) {
|
|
11846
|
+
|
|
11847
|
+
// converts [ x1, y1, z1, x2, y2, z2, ... ] to pairs format
|
|
11848
|
+
var length = array.length - 3;
|
|
11849
|
+
var points = new Float32Array( 2 * length );
|
|
11850
|
+
|
|
11851
|
+
for ( var i = 0; i < length; i += 3 ) {
|
|
11852
|
+
|
|
11853
|
+
points[ 2 * i ] = array[ i ];
|
|
11854
|
+
points[ 2 * i + 1 ] = array[ i + 1 ];
|
|
11855
|
+
points[ 2 * i + 2 ] = array[ i + 2 ];
|
|
11856
|
+
points[ 2 * i + 3 ] = array[ i + 3 ];
|
|
11857
|
+
points[ 2 * i + 4 ] = array[ i + 4 ];
|
|
11858
|
+
points[ 2 * i + 5 ] = array[ i + 5 ];
|
|
11859
|
+
}
|
|
11860
|
+
|
|
11861
|
+
super.setPositions( points );
|
|
11862
|
+
return this;
|
|
11863
|
+
|
|
11864
|
+
}
|
|
11865
|
+
|
|
11866
|
+
setColors( array ) {
|
|
11867
|
+
|
|
11868
|
+
// converts [ r1, g1, b1, r2, g2, b2, ... ] to pairs format
|
|
11869
|
+
var length = array.length - 3;
|
|
11870
|
+
var colors = new Float32Array( 2 * length );
|
|
11871
|
+
|
|
11872
|
+
for ( var i = 0; i < length; i += 3 ) {
|
|
11873
|
+
|
|
11874
|
+
colors[ 2 * i ] = array[ i ];
|
|
11875
|
+
colors[ 2 * i + 1 ] = array[ i + 1 ];
|
|
11876
|
+
colors[ 2 * i + 2 ] = array[ i + 2 ];
|
|
11877
|
+
colors[ 2 * i + 3 ] = array[ i + 3 ];
|
|
11878
|
+
colors[ 2 * i + 4 ] = array[ i + 4 ];
|
|
11879
|
+
colors[ 2 * i + 5 ] = array[ i + 5 ];
|
|
11880
|
+
|
|
11881
|
+
}
|
|
11882
|
+
|
|
11883
|
+
super.setColors( colors );
|
|
11884
|
+
return this;
|
|
11885
|
+
|
|
11886
|
+
}
|
|
11887
|
+
|
|
11888
|
+
fromLine( line ) {
|
|
11889
|
+
|
|
11890
|
+
var geometry = line.geometry;
|
|
11891
|
+
|
|
11892
|
+
if ( geometry.isGeometry ) {
|
|
11893
|
+
|
|
11894
|
+
console.error( 'THREE.LineGeometry no longer supports Geometry. Use THREE.BufferGeometry instead.' );
|
|
11895
|
+
return;
|
|
11896
|
+
|
|
11897
|
+
} else if ( geometry.isBufferGeometry ) {
|
|
11898
|
+
|
|
11899
|
+
this.setPositions( geometry.attributes.position.array ); // assumes non-indexed
|
|
11900
|
+
|
|
11901
|
+
} // set colors, maybe
|
|
11902
|
+
|
|
11903
|
+
|
|
11904
|
+
return this;
|
|
11905
|
+
|
|
11906
|
+
}
|
|
11907
|
+
|
|
11908
|
+
}
|
|
11909
|
+
|
|
11910
|
+
LineGeometry.prototype.isLineGeometry = true;
|
|
11911
|
+
|
|
11912
|
+
/**
|
|
11913
|
+
* parameters = {
|
|
11914
|
+
* color: <hex>,
|
|
11915
|
+
* linewidth: <float>,
|
|
11916
|
+
* dashed: <boolean>,
|
|
11917
|
+
* dashScale: <float>,
|
|
11918
|
+
* dashSize: <float>,
|
|
11919
|
+
* gapSize: <float>,
|
|
11920
|
+
* resolution: <Vector2>, // to be set by renderer
|
|
11921
|
+
* }
|
|
11922
|
+
*/
|
|
11923
|
+
THREE__namespace.UniformsLib.line = {
|
|
11924
|
+
worldUnits: {
|
|
11925
|
+
value: 1
|
|
11926
|
+
},
|
|
11927
|
+
linewidth: {
|
|
11928
|
+
value: 1
|
|
11929
|
+
},
|
|
11930
|
+
resolution: {
|
|
11931
|
+
value: new THREE__namespace.Vector2( 1, 1 )
|
|
11932
|
+
},
|
|
11933
|
+
dashScale: {
|
|
11934
|
+
value: 1
|
|
11935
|
+
},
|
|
11936
|
+
dashSize: {
|
|
11937
|
+
value: 1
|
|
11938
|
+
},
|
|
11939
|
+
gapSize: {
|
|
11940
|
+
value: 1
|
|
11941
|
+
} // todo FIX - maybe change to totalSize
|
|
11942
|
+
|
|
11943
|
+
};
|
|
11944
|
+
|
|
11945
|
+
THREE__namespace.ShaderLib[ 'line' ] = {
|
|
11946
|
+
uniforms: THREE__namespace.UniformsUtils.merge( [ THREE__namespace.UniformsLib.common, THREE__namespace.UniformsLib.fog, THREE__namespace.UniformsLib.line ] ),
|
|
11947
|
+
vertexShader:
|
|
11948
|
+
/* glsl */
|
|
11949
|
+
`
|
|
11950
|
+
#include <common>
|
|
11951
|
+
#include <color_pars_vertex>
|
|
11952
|
+
#include <fog_pars_vertex>
|
|
11953
|
+
#include <logdepthbuf_pars_vertex>
|
|
11954
|
+
#include <clipping_planes_pars_vertex>
|
|
11955
|
+
|
|
11956
|
+
uniform float linewidth;
|
|
11957
|
+
uniform vec2 resolution;
|
|
11958
|
+
|
|
11959
|
+
attribute vec3 instanceStart;
|
|
11960
|
+
attribute vec3 instanceEnd;
|
|
11961
|
+
|
|
11962
|
+
attribute vec3 instanceColorStart;
|
|
11963
|
+
attribute vec3 instanceColorEnd;
|
|
11964
|
+
|
|
11965
|
+
varying vec2 vUv;
|
|
11966
|
+
varying vec4 worldPos;
|
|
11967
|
+
varying vec3 worldStart;
|
|
11968
|
+
varying vec3 worldEnd;
|
|
11969
|
+
|
|
11970
|
+
#ifdef USE_DASH
|
|
11971
|
+
|
|
11972
|
+
uniform float dashScale;
|
|
11973
|
+
attribute float instanceDistanceStart;
|
|
11974
|
+
attribute float instanceDistanceEnd;
|
|
11975
|
+
varying float vLineDistance;
|
|
11976
|
+
|
|
11977
|
+
#endif
|
|
11978
|
+
|
|
11979
|
+
void trimSegment( const in vec4 start, inout vec4 end ) {
|
|
11980
|
+
|
|
11981
|
+
// trim end segment so it terminates between the camera plane and the near plane
|
|
11982
|
+
|
|
11983
|
+
// conservative estimate of the near plane
|
|
11984
|
+
float a = projectionMatrix[ 2 ][ 2 ]; // 3nd entry in 3th column
|
|
11985
|
+
float b = projectionMatrix[ 3 ][ 2 ]; // 3nd entry in 4th column
|
|
11986
|
+
float nearEstimate = - 0.5 * b / a;
|
|
11987
|
+
|
|
11988
|
+
float alpha = ( nearEstimate - start.z ) / ( end.z - start.z );
|
|
11989
|
+
|
|
11990
|
+
end.xyz = mix( start.xyz, end.xyz, alpha );
|
|
11991
|
+
|
|
11992
|
+
}
|
|
11993
|
+
|
|
11994
|
+
void main() {
|
|
11995
|
+
|
|
11996
|
+
#ifdef USE_COLOR
|
|
11997
|
+
|
|
11998
|
+
vColor.xyz = ( position.y < 0.5 ) ? instanceColorStart : instanceColorEnd;
|
|
11999
|
+
|
|
12000
|
+
#endif
|
|
12001
|
+
|
|
12002
|
+
#ifdef USE_DASH
|
|
12003
|
+
|
|
12004
|
+
vLineDistance = ( position.y < 0.5 ) ? dashScale * instanceDistanceStart : dashScale * instanceDistanceEnd;
|
|
12005
|
+
|
|
12006
|
+
#endif
|
|
12007
|
+
|
|
12008
|
+
float aspect = resolution.x / resolution.y;
|
|
12009
|
+
|
|
12010
|
+
vUv = uv;
|
|
12011
|
+
|
|
12012
|
+
// camera space
|
|
12013
|
+
vec4 start = modelViewMatrix * vec4( instanceStart, 1.0 );
|
|
12014
|
+
vec4 end = modelViewMatrix * vec4( instanceEnd, 1.0 );
|
|
12015
|
+
|
|
12016
|
+
worldStart = start.xyz;
|
|
12017
|
+
worldEnd = end.xyz;
|
|
12018
|
+
|
|
12019
|
+
// special case for perspective projection, and segments that terminate either in, or behind, the camera plane
|
|
12020
|
+
// clearly the gpu firmware has a way of addressing this issue when projecting into ndc space
|
|
12021
|
+
// but we need to perform ndc-space calculations in the shader, so we must address this issue directly
|
|
12022
|
+
// perhaps there is a more elegant solution -- WestLangley
|
|
12023
|
+
|
|
12024
|
+
bool perspective = ( projectionMatrix[ 2 ][ 3 ] == - 1.0 ); // 4th entry in the 3rd column
|
|
12025
|
+
|
|
12026
|
+
if ( perspective ) {
|
|
12027
|
+
|
|
12028
|
+
if ( start.z < 0.0 && end.z >= 0.0 ) {
|
|
12029
|
+
|
|
12030
|
+
trimSegment( start, end );
|
|
12031
|
+
|
|
12032
|
+
} else if ( end.z < 0.0 && start.z >= 0.0 ) {
|
|
12033
|
+
|
|
12034
|
+
trimSegment( end, start );
|
|
12035
|
+
|
|
12036
|
+
}
|
|
12037
|
+
|
|
12038
|
+
}
|
|
12039
|
+
|
|
12040
|
+
// clip space
|
|
12041
|
+
vec4 clipStart = projectionMatrix * start;
|
|
12042
|
+
vec4 clipEnd = projectionMatrix * end;
|
|
12043
|
+
|
|
12044
|
+
// ndc space
|
|
12045
|
+
vec3 ndcStart = clipStart.xyz / clipStart.w;
|
|
12046
|
+
vec3 ndcEnd = clipEnd.xyz / clipEnd.w;
|
|
12047
|
+
|
|
12048
|
+
// direction
|
|
12049
|
+
vec2 dir = ndcEnd.xy - ndcStart.xy;
|
|
12050
|
+
|
|
12051
|
+
// account for clip-space aspect ratio
|
|
12052
|
+
dir.x *= aspect;
|
|
12053
|
+
dir = normalize( dir );
|
|
12054
|
+
|
|
12055
|
+
#ifdef WORLD_UNITS
|
|
12056
|
+
|
|
12057
|
+
// get the offset direction as perpendicular to the view vector
|
|
12058
|
+
vec3 worldDir = normalize( end.xyz - start.xyz );
|
|
12059
|
+
vec3 offset;
|
|
12060
|
+
if ( position.y < 0.5 ) {
|
|
12061
|
+
|
|
12062
|
+
offset = normalize( cross( start.xyz, worldDir ) );
|
|
12063
|
+
|
|
12064
|
+
} else {
|
|
12065
|
+
|
|
12066
|
+
offset = normalize( cross( end.xyz, worldDir ) );
|
|
12067
|
+
|
|
12068
|
+
}
|
|
12069
|
+
|
|
12070
|
+
// sign flip
|
|
12071
|
+
if ( position.x < 0.0 ) offset *= - 1.0;
|
|
12072
|
+
|
|
12073
|
+
float forwardOffset = dot( worldDir, vec3( 0.0, 0.0, 1.0 ) );
|
|
12074
|
+
|
|
12075
|
+
// don't extend the line if we're rendering dashes because we
|
|
12076
|
+
// won't be rendering the endcaps
|
|
12077
|
+
#ifndef USE_DASH
|
|
12078
|
+
|
|
12079
|
+
// extend the line bounds to encompass endcaps
|
|
12080
|
+
start.xyz += - worldDir * linewidth * 0.5;
|
|
12081
|
+
end.xyz += worldDir * linewidth * 0.5;
|
|
12082
|
+
|
|
12083
|
+
// shift the position of the quad so it hugs the forward edge of the line
|
|
12084
|
+
offset.xy -= dir * forwardOffset;
|
|
12085
|
+
offset.z += 0.5;
|
|
12086
|
+
|
|
12087
|
+
#endif
|
|
12088
|
+
|
|
12089
|
+
// endcaps
|
|
12090
|
+
if ( position.y > 1.0 || position.y < 0.0 ) {
|
|
12091
|
+
|
|
12092
|
+
offset.xy += dir * 2.0 * forwardOffset;
|
|
12093
|
+
|
|
12094
|
+
}
|
|
12095
|
+
|
|
12096
|
+
// adjust for linewidth
|
|
12097
|
+
offset *= linewidth * 0.5;
|
|
12098
|
+
|
|
12099
|
+
// set the world position
|
|
12100
|
+
worldPos = ( position.y < 0.5 ) ? start : end;
|
|
12101
|
+
worldPos.xyz += offset;
|
|
12102
|
+
|
|
12103
|
+
// project the worldpos
|
|
12104
|
+
vec4 clip = projectionMatrix * worldPos;
|
|
12105
|
+
|
|
12106
|
+
// shift the depth of the projected points so the line
|
|
12107
|
+
// segements overlap neatly
|
|
12108
|
+
vec3 clipPose = ( position.y < 0.5 ) ? ndcStart : ndcEnd;
|
|
12109
|
+
clip.z = clipPose.z * clip.w;
|
|
12110
|
+
|
|
12111
|
+
#else
|
|
12112
|
+
|
|
12113
|
+
vec2 offset = vec2( dir.y, - dir.x );
|
|
12114
|
+
// undo aspect ratio adjustment
|
|
12115
|
+
dir.x /= aspect;
|
|
12116
|
+
offset.x /= aspect;
|
|
12117
|
+
|
|
12118
|
+
// sign flip
|
|
12119
|
+
if ( position.x < 0.0 ) offset *= - 1.0;
|
|
12120
|
+
|
|
12121
|
+
// endcaps
|
|
12122
|
+
if ( position.y < 0.0 ) {
|
|
12123
|
+
|
|
12124
|
+
offset += - dir;
|
|
12125
|
+
|
|
12126
|
+
} else if ( position.y > 1.0 ) {
|
|
12127
|
+
|
|
12128
|
+
offset += dir;
|
|
12129
|
+
|
|
12130
|
+
}
|
|
12131
|
+
|
|
12132
|
+
// adjust for linewidth
|
|
12133
|
+
offset *= linewidth;
|
|
12134
|
+
|
|
12135
|
+
// adjust for clip-space to screen-space conversion // maybe resolution should be based on viewport ...
|
|
12136
|
+
offset /= resolution.y;
|
|
12137
|
+
|
|
12138
|
+
// select end
|
|
12139
|
+
vec4 clip = ( position.y < 0.5 ) ? clipStart : clipEnd;
|
|
12140
|
+
|
|
12141
|
+
// back to clip space
|
|
12142
|
+
offset *= clip.w;
|
|
12143
|
+
|
|
12144
|
+
clip.xy += offset;
|
|
12145
|
+
|
|
12146
|
+
#endif
|
|
12147
|
+
|
|
12148
|
+
gl_Position = clip;
|
|
12149
|
+
|
|
12150
|
+
vec4 mvPosition = ( position.y < 0.5 ) ? start : end; // this is an approximation
|
|
12151
|
+
|
|
12152
|
+
#include <logdepthbuf_vertex>
|
|
12153
|
+
#include <clipping_planes_vertex>
|
|
12154
|
+
#include <fog_vertex>
|
|
12155
|
+
|
|
12156
|
+
}
|
|
12157
|
+
` ,
|
|
12158
|
+
fragmentShader:
|
|
12159
|
+
/* glsl */
|
|
12160
|
+
`
|
|
12161
|
+
uniform vec3 diffuse;
|
|
12162
|
+
uniform float opacity;
|
|
12163
|
+
uniform float linewidth;
|
|
12164
|
+
|
|
12165
|
+
#ifdef USE_DASH
|
|
12166
|
+
|
|
12167
|
+
uniform float dashSize;
|
|
12168
|
+
uniform float gapSize;
|
|
12169
|
+
|
|
12170
|
+
#endif
|
|
12171
|
+
|
|
12172
|
+
varying float vLineDistance;
|
|
12173
|
+
varying vec4 worldPos;
|
|
12174
|
+
varying vec3 worldStart;
|
|
12175
|
+
varying vec3 worldEnd;
|
|
12176
|
+
|
|
12177
|
+
#include <common>
|
|
12178
|
+
#include <color_pars_fragment>
|
|
12179
|
+
#include <fog_pars_fragment>
|
|
12180
|
+
#include <logdepthbuf_pars_fragment>
|
|
12181
|
+
#include <clipping_planes_pars_fragment>
|
|
12182
|
+
|
|
12183
|
+
varying vec2 vUv;
|
|
12184
|
+
|
|
12185
|
+
vec2 closestLineToLine(vec3 p1, vec3 p2, vec3 p3, vec3 p4) {
|
|
12186
|
+
|
|
12187
|
+
float mua;
|
|
12188
|
+
float mub;
|
|
12189
|
+
|
|
12190
|
+
vec3 p13 = p1 - p3;
|
|
12191
|
+
vec3 p43 = p4 - p3;
|
|
12192
|
+
|
|
12193
|
+
vec3 p21 = p2 - p1;
|
|
12194
|
+
|
|
12195
|
+
float d1343 = dot( p13, p43 );
|
|
12196
|
+
float d4321 = dot( p43, p21 );
|
|
12197
|
+
float d1321 = dot( p13, p21 );
|
|
12198
|
+
float d4343 = dot( p43, p43 );
|
|
12199
|
+
float d2121 = dot( p21, p21 );
|
|
12200
|
+
|
|
12201
|
+
float denom = d2121 * d4343 - d4321 * d4321;
|
|
12202
|
+
|
|
12203
|
+
float numer = d1343 * d4321 - d1321 * d4343;
|
|
12204
|
+
|
|
12205
|
+
mua = numer / denom;
|
|
12206
|
+
mua = clamp( mua, 0.0, 1.0 );
|
|
12207
|
+
mub = ( d1343 + d4321 * ( mua ) ) / d4343;
|
|
12208
|
+
mub = clamp( mub, 0.0, 1.0 );
|
|
12209
|
+
|
|
12210
|
+
return vec2( mua, mub );
|
|
12211
|
+
|
|
12212
|
+
}
|
|
12213
|
+
|
|
12214
|
+
void main() {
|
|
12215
|
+
|
|
12216
|
+
#include <clipping_planes_fragment>
|
|
12217
|
+
|
|
12218
|
+
#ifdef USE_DASH
|
|
12219
|
+
|
|
12220
|
+
if ( vUv.y < - 1.0 || vUv.y > 1.0 ) discard; // discard endcaps
|
|
12221
|
+
|
|
12222
|
+
if ( mod( vLineDistance, dashSize + gapSize ) > dashSize ) discard; // todo - FIX
|
|
12223
|
+
|
|
12224
|
+
#endif
|
|
12225
|
+
|
|
12226
|
+
float alpha = opacity;
|
|
12227
|
+
|
|
12228
|
+
#ifdef WORLD_UNITS
|
|
12229
|
+
|
|
12230
|
+
// Find the closest points on the view ray and the line segment
|
|
12231
|
+
vec3 rayEnd = normalize( worldPos.xyz ) * 1e5;
|
|
12232
|
+
vec3 lineDir = worldEnd - worldStart;
|
|
12233
|
+
vec2 params = closestLineToLine( worldStart, worldEnd, vec3( 0.0, 0.0, 0.0 ), rayEnd );
|
|
12234
|
+
|
|
12235
|
+
vec3 p1 = worldStart + lineDir * params.x;
|
|
12236
|
+
vec3 p2 = rayEnd * params.y;
|
|
12237
|
+
vec3 delta = p1 - p2;
|
|
12238
|
+
float len = length( delta );
|
|
12239
|
+
float norm = len / linewidth;
|
|
12240
|
+
|
|
12241
|
+
#ifndef USE_DASH
|
|
12242
|
+
|
|
12243
|
+
#ifdef ALPHA_TO_COVERAGE
|
|
12244
|
+
|
|
12245
|
+
float dnorm = fwidth( norm );
|
|
12246
|
+
alpha = 1.0 - smoothstep( 0.5 - dnorm, 0.5 + dnorm, norm );
|
|
12247
|
+
|
|
12248
|
+
#else
|
|
12249
|
+
|
|
12250
|
+
if ( norm > 0.5 ) {
|
|
12251
|
+
|
|
12252
|
+
discard;
|
|
12253
|
+
|
|
12254
|
+
}
|
|
12255
|
+
|
|
12256
|
+
#endif
|
|
12257
|
+
|
|
12258
|
+
#endif
|
|
12259
|
+
|
|
12260
|
+
#else
|
|
12261
|
+
|
|
12262
|
+
#ifdef ALPHA_TO_COVERAGE
|
|
12263
|
+
|
|
12264
|
+
// artifacts appear on some hardware if a derivative is taken within a conditional
|
|
12265
|
+
float a = vUv.x;
|
|
12266
|
+
float b = ( vUv.y > 0.0 ) ? vUv.y - 1.0 : vUv.y + 1.0;
|
|
12267
|
+
float len2 = a * a + b * b;
|
|
12268
|
+
float dlen = fwidth( len2 );
|
|
12269
|
+
|
|
12270
|
+
if ( abs( vUv.y ) > 1.0 ) {
|
|
12271
|
+
|
|
12272
|
+
alpha = 1.0 - smoothstep( 1.0 - dlen, 1.0 + dlen, len2 );
|
|
12273
|
+
|
|
12274
|
+
}
|
|
12275
|
+
|
|
12276
|
+
#else
|
|
12277
|
+
|
|
12278
|
+
if ( abs( vUv.y ) > 1.0 ) {
|
|
12279
|
+
|
|
12280
|
+
float a = vUv.x;
|
|
12281
|
+
float b = ( vUv.y > 0.0 ) ? vUv.y - 1.0 : vUv.y + 1.0;
|
|
12282
|
+
float len2 = a * a + b * b;
|
|
12283
|
+
|
|
12284
|
+
if ( len2 > 1.0 ) discard;
|
|
12285
|
+
|
|
12286
|
+
}
|
|
12287
|
+
|
|
12288
|
+
#endif
|
|
12289
|
+
|
|
12290
|
+
#endif
|
|
12291
|
+
|
|
12292
|
+
vec4 diffuseColor = vec4( diffuse, alpha );
|
|
12293
|
+
|
|
12294
|
+
#include <logdepthbuf_fragment>
|
|
12295
|
+
#include <color_fragment>
|
|
12296
|
+
|
|
12297
|
+
gl_FragColor = vec4( diffuseColor.rgb, alpha );
|
|
12298
|
+
|
|
12299
|
+
#include <tonemapping_fragment>
|
|
12300
|
+
#include <encodings_fragment>
|
|
12301
|
+
#include <fog_fragment>
|
|
12302
|
+
#include <premultiplied_alpha_fragment>
|
|
12303
|
+
|
|
12304
|
+
}
|
|
12305
|
+
`
|
|
12306
|
+
};
|
|
12307
|
+
|
|
12308
|
+
class LineMaterial extends THREE__namespace.ShaderMaterial {
|
|
12309
|
+
|
|
12310
|
+
constructor( parameters ) {
|
|
12311
|
+
|
|
12312
|
+
super( {
|
|
12313
|
+
type: 'LineMaterial',
|
|
12314
|
+
uniforms: THREE__namespace.UniformsUtils.clone( THREE__namespace.ShaderLib[ 'line' ].uniforms ),
|
|
12315
|
+
vertexShader: THREE__namespace.ShaderLib[ 'line' ].vertexShader,
|
|
12316
|
+
fragmentShader: THREE__namespace.ShaderLib[ 'line' ].fragmentShader,
|
|
12317
|
+
clipping: true // required for clipping support
|
|
12318
|
+
|
|
12319
|
+
} );
|
|
12320
|
+
Object.defineProperties( this, {
|
|
12321
|
+
color: {
|
|
12322
|
+
enumerable: true,
|
|
12323
|
+
get: function () {
|
|
12324
|
+
|
|
12325
|
+
return this.uniforms.diffuse.value;
|
|
12326
|
+
|
|
12327
|
+
},
|
|
12328
|
+
set: function ( value ) {
|
|
12329
|
+
|
|
12330
|
+
this.uniforms.diffuse.value = value;
|
|
12331
|
+
|
|
12332
|
+
}
|
|
12333
|
+
},
|
|
12334
|
+
worldUnits: {
|
|
12335
|
+
enumerable: true,
|
|
12336
|
+
get: function () {
|
|
12337
|
+
|
|
12338
|
+
return 'WORLD_UNITS' in this.defines;
|
|
12339
|
+
|
|
12340
|
+
},
|
|
12341
|
+
set: function ( value ) {
|
|
12342
|
+
|
|
12343
|
+
if ( value === true ) {
|
|
12344
|
+
|
|
12345
|
+
this.defines.WORLD_UNITS = '';
|
|
12346
|
+
|
|
12347
|
+
} else {
|
|
12348
|
+
|
|
12349
|
+
delete this.defines.WORLD_UNITS;
|
|
12350
|
+
|
|
12351
|
+
}
|
|
12352
|
+
|
|
12353
|
+
}
|
|
12354
|
+
},
|
|
12355
|
+
linewidth: {
|
|
12356
|
+
enumerable: true,
|
|
12357
|
+
get: function () {
|
|
12358
|
+
|
|
12359
|
+
return this.uniforms.linewidth.value;
|
|
12360
|
+
|
|
12361
|
+
},
|
|
12362
|
+
set: function ( value ) {
|
|
12363
|
+
|
|
12364
|
+
this.uniforms.linewidth.value = value;
|
|
12365
|
+
|
|
12366
|
+
}
|
|
12367
|
+
},
|
|
12368
|
+
dashed: {
|
|
12369
|
+
enumerable: true,
|
|
12370
|
+
get: function () {
|
|
12371
|
+
|
|
12372
|
+
return Boolean( 'USE_DASH' in this.defines );
|
|
12373
|
+
|
|
12374
|
+
},
|
|
12375
|
+
|
|
12376
|
+
set( value ) {
|
|
12377
|
+
|
|
12378
|
+
if ( Boolean( value ) !== Boolean( 'USE_DASH' in this.defines ) ) {
|
|
12379
|
+
|
|
12380
|
+
this.needsUpdate = true;
|
|
12381
|
+
|
|
12382
|
+
}
|
|
12383
|
+
|
|
12384
|
+
if ( value === true ) {
|
|
12385
|
+
|
|
12386
|
+
this.defines.USE_DASH = '';
|
|
12387
|
+
|
|
12388
|
+
} else {
|
|
12389
|
+
|
|
12390
|
+
delete this.defines.USE_DASH;
|
|
12391
|
+
|
|
12392
|
+
}
|
|
12393
|
+
|
|
12394
|
+
}
|
|
12395
|
+
|
|
12396
|
+
},
|
|
12397
|
+
dashScale: {
|
|
12398
|
+
enumerable: true,
|
|
12399
|
+
get: function () {
|
|
12400
|
+
|
|
12401
|
+
return this.uniforms.dashScale.value;
|
|
12402
|
+
|
|
12403
|
+
},
|
|
12404
|
+
set: function ( value ) {
|
|
12405
|
+
|
|
12406
|
+
this.uniforms.dashScale.value = value;
|
|
12407
|
+
|
|
12408
|
+
}
|
|
12409
|
+
},
|
|
12410
|
+
dashSize: {
|
|
12411
|
+
enumerable: true,
|
|
12412
|
+
get: function () {
|
|
12413
|
+
|
|
12414
|
+
return this.uniforms.dashSize.value;
|
|
12415
|
+
|
|
12416
|
+
},
|
|
12417
|
+
set: function ( value ) {
|
|
12418
|
+
|
|
12419
|
+
this.uniforms.dashSize.value = value;
|
|
12420
|
+
|
|
12421
|
+
}
|
|
12422
|
+
},
|
|
12423
|
+
dashOffset: {
|
|
12424
|
+
enumerable: true,
|
|
12425
|
+
get: function () {
|
|
12426
|
+
|
|
12427
|
+
return this.uniforms.dashOffset.value;
|
|
12428
|
+
|
|
12429
|
+
},
|
|
12430
|
+
set: function ( value ) {
|
|
12431
|
+
|
|
12432
|
+
this.uniforms.dashOffset.value = value;
|
|
12433
|
+
|
|
12434
|
+
}
|
|
12435
|
+
},
|
|
12436
|
+
gapSize: {
|
|
12437
|
+
enumerable: true,
|
|
12438
|
+
get: function () {
|
|
12439
|
+
|
|
12440
|
+
return this.uniforms.gapSize.value;
|
|
12441
|
+
|
|
12442
|
+
},
|
|
12443
|
+
set: function ( value ) {
|
|
12444
|
+
|
|
12445
|
+
this.uniforms.gapSize.value = value;
|
|
12446
|
+
|
|
12447
|
+
}
|
|
12448
|
+
},
|
|
12449
|
+
opacity: {
|
|
12450
|
+
enumerable: true,
|
|
12451
|
+
get: function () {
|
|
12452
|
+
|
|
12453
|
+
return this.uniforms.opacity.value;
|
|
12454
|
+
|
|
12455
|
+
},
|
|
12456
|
+
set: function ( value ) {
|
|
12457
|
+
|
|
12458
|
+
this.uniforms.opacity.value = value;
|
|
12459
|
+
|
|
12460
|
+
}
|
|
12461
|
+
},
|
|
12462
|
+
resolution: {
|
|
12463
|
+
enumerable: true,
|
|
12464
|
+
get: function () {
|
|
12465
|
+
|
|
12466
|
+
return this.uniforms.resolution.value;
|
|
12467
|
+
|
|
12468
|
+
},
|
|
12469
|
+
set: function ( value ) {
|
|
12470
|
+
|
|
12471
|
+
this.uniforms.resolution.value.copy( value );
|
|
12472
|
+
|
|
12473
|
+
}
|
|
12474
|
+
},
|
|
12475
|
+
alphaToCoverage: {
|
|
12476
|
+
enumerable: true,
|
|
12477
|
+
get: function () {
|
|
12478
|
+
|
|
12479
|
+
return Boolean( 'ALPHA_TO_COVERAGE' in this.defines );
|
|
12480
|
+
|
|
12481
|
+
},
|
|
12482
|
+
set: function ( value ) {
|
|
12483
|
+
|
|
12484
|
+
if ( Boolean( value ) !== Boolean( 'ALPHA_TO_COVERAGE' in this.defines ) ) {
|
|
12485
|
+
|
|
12486
|
+
this.needsUpdate = true;
|
|
12487
|
+
|
|
12488
|
+
}
|
|
12489
|
+
|
|
12490
|
+
if ( value === true ) {
|
|
12491
|
+
|
|
12492
|
+
this.defines.ALPHA_TO_COVERAGE = '';
|
|
12493
|
+
this.extensions.derivatives = true;
|
|
12494
|
+
|
|
12495
|
+
} else {
|
|
12496
|
+
|
|
12497
|
+
delete this.defines.ALPHA_TO_COVERAGE;
|
|
12498
|
+
this.extensions.derivatives = false;
|
|
12499
|
+
|
|
12500
|
+
}
|
|
12501
|
+
|
|
12502
|
+
}
|
|
12503
|
+
}
|
|
12504
|
+
} );
|
|
12505
|
+
this.setValues( parameters );
|
|
12506
|
+
|
|
12507
|
+
}
|
|
12508
|
+
|
|
12509
|
+
}
|
|
12510
|
+
|
|
12511
|
+
LineMaterial.prototype.isLineMaterial = true;
|
|
12512
|
+
|
|
12513
|
+
const _start = new THREE__namespace.Vector3();
|
|
12514
|
+
|
|
12515
|
+
const _end = new THREE__namespace.Vector3();
|
|
12516
|
+
|
|
12517
|
+
const _start4 = new THREE__namespace.Vector4();
|
|
12518
|
+
|
|
12519
|
+
const _end4 = new THREE__namespace.Vector4();
|
|
12520
|
+
|
|
12521
|
+
const _ssOrigin = new THREE__namespace.Vector4();
|
|
12522
|
+
|
|
12523
|
+
const _ssOrigin3 = new THREE__namespace.Vector3();
|
|
12524
|
+
|
|
12525
|
+
const _mvMatrix = new THREE__namespace.Matrix4();
|
|
12526
|
+
|
|
12527
|
+
const _line = new THREE__namespace.Line3();
|
|
12528
|
+
|
|
12529
|
+
const _closestPoint = new THREE__namespace.Vector3();
|
|
12530
|
+
|
|
12531
|
+
const _box = new THREE__namespace.Box3();
|
|
12532
|
+
|
|
12533
|
+
const _sphere = new THREE__namespace.Sphere();
|
|
12534
|
+
|
|
12535
|
+
const _clipToWorldVector = new THREE__namespace.Vector4();
|
|
12536
|
+
|
|
12537
|
+
class LineSegments2 extends THREE__namespace.Mesh {
|
|
12538
|
+
|
|
12539
|
+
constructor( geometry = new LineSegmentsGeometry(), material = new LineMaterial( {
|
|
12540
|
+
color: Math.random() * 0xffffff
|
|
12541
|
+
} ) ) {
|
|
12542
|
+
|
|
12543
|
+
super( geometry, material );
|
|
12544
|
+
this.type = 'LineSegments2';
|
|
12545
|
+
|
|
12546
|
+
} // for backwards-compatability, but could be a method of THREE.LineSegmentsGeometry...
|
|
12547
|
+
|
|
12548
|
+
computeLineDistances() {
|
|
12549
|
+
|
|
12550
|
+
const geometry = this.geometry;
|
|
12551
|
+
const instanceStart = geometry.attributes.instanceStart;
|
|
12552
|
+
const instanceEnd = geometry.attributes.instanceEnd;
|
|
12553
|
+
const lineDistances = new Float32Array( 2 * instanceStart.count );
|
|
12554
|
+
|
|
12555
|
+
for ( let i = 0, j = 0, l = instanceStart.count; i < l; i ++, j += 2 ) {
|
|
12556
|
+
|
|
12557
|
+
_start.fromBufferAttribute( instanceStart, i );
|
|
12558
|
+
|
|
12559
|
+
_end.fromBufferAttribute( instanceEnd, i );
|
|
12560
|
+
|
|
12561
|
+
lineDistances[ j ] = j === 0 ? 0 : lineDistances[ j - 1 ];
|
|
12562
|
+
lineDistances[ j + 1 ] = lineDistances[ j ] + _start.distanceTo( _end );
|
|
12563
|
+
|
|
12564
|
+
}
|
|
12565
|
+
|
|
12566
|
+
const instanceDistanceBuffer = new THREE__namespace.InstancedInterleavedBuffer( lineDistances, 2, 1 ); // d0, d1
|
|
12567
|
+
|
|
12568
|
+
geometry.setAttribute( 'instanceDistanceStart', new THREE__namespace.InterleavedBufferAttribute( instanceDistanceBuffer, 1, 0 ) ); // d0
|
|
12569
|
+
|
|
12570
|
+
geometry.setAttribute( 'instanceDistanceEnd', new THREE__namespace.InterleavedBufferAttribute( instanceDistanceBuffer, 1, 1 ) ); // d1
|
|
12571
|
+
|
|
12572
|
+
return this;
|
|
12573
|
+
|
|
12574
|
+
}
|
|
12575
|
+
|
|
12576
|
+
raycast( raycaster, intersects ) {
|
|
12577
|
+
|
|
12578
|
+
if ( raycaster.camera === null ) {
|
|
12579
|
+
|
|
12580
|
+
console.error( 'LineSegments2: "Raycaster.camera" needs to be set in order to raycast against LineSegments2.' );
|
|
12581
|
+
|
|
12582
|
+
}
|
|
12583
|
+
|
|
12584
|
+
const threshold = raycaster.params.Line2 !== undefined ? raycaster.params.Line2.threshold || 0 : 0;
|
|
12585
|
+
const ray = raycaster.ray;
|
|
12586
|
+
const camera = raycaster.camera;
|
|
12587
|
+
const projectionMatrix = camera.projectionMatrix;
|
|
12588
|
+
const matrixWorld = this.matrixWorld;
|
|
12589
|
+
const geometry = this.geometry;
|
|
12590
|
+
const material = this.material;
|
|
12591
|
+
const resolution = material.resolution;
|
|
12592
|
+
const lineWidth = material.linewidth + threshold;
|
|
12593
|
+
const instanceStart = geometry.attributes.instanceStart;
|
|
12594
|
+
const instanceEnd = geometry.attributes.instanceEnd; // camera forward is negative
|
|
12595
|
+
|
|
12596
|
+
const near = - camera.near; // clip space is [ - 1, 1 ] so multiply by two to get the full
|
|
12597
|
+
// width in clip space
|
|
12598
|
+
|
|
12599
|
+
const ssMaxWidth = 2.0 * Math.max( lineWidth / resolution.width, lineWidth / resolution.height ); //
|
|
12600
|
+
// check if we intersect the sphere bounds
|
|
12601
|
+
|
|
12602
|
+
if ( geometry.boundingSphere === null ) {
|
|
12603
|
+
|
|
12604
|
+
geometry.computeBoundingSphere();
|
|
12605
|
+
|
|
12606
|
+
}
|
|
12607
|
+
|
|
12608
|
+
_sphere.copy( geometry.boundingSphere ).applyMatrix4( matrixWorld );
|
|
12609
|
+
|
|
12610
|
+
const distanceToSphere = Math.max( camera.near, _sphere.distanceToPoint( ray.origin ) ); // get the w component to scale the world space line width
|
|
12611
|
+
|
|
12612
|
+
_clipToWorldVector.set( 0, 0, - distanceToSphere, 1.0 ).applyMatrix4( camera.projectionMatrix );
|
|
12613
|
+
|
|
12614
|
+
_clipToWorldVector.multiplyScalar( 1.0 / _clipToWorldVector.w );
|
|
12615
|
+
|
|
12616
|
+
_clipToWorldVector.applyMatrix4( camera.projectionMatrixInverse ); // increase the sphere bounds by the worst case line screen space width
|
|
12617
|
+
|
|
12618
|
+
|
|
12619
|
+
const sphereMargin = Math.abs( ssMaxWidth / _clipToWorldVector.w ) * 0.5;
|
|
12620
|
+
_sphere.radius += sphereMargin;
|
|
12621
|
+
|
|
12622
|
+
if ( raycaster.ray.intersectsSphere( _sphere ) === false ) {
|
|
12623
|
+
|
|
12624
|
+
return;
|
|
12625
|
+
|
|
12626
|
+
} //
|
|
12627
|
+
// check if we intersect the box bounds
|
|
12628
|
+
|
|
12629
|
+
|
|
12630
|
+
if ( geometry.boundingBox === null ) {
|
|
12631
|
+
|
|
12632
|
+
geometry.computeBoundingBox();
|
|
12633
|
+
|
|
12634
|
+
}
|
|
12635
|
+
|
|
12636
|
+
_box.copy( geometry.boundingBox ).applyMatrix4( matrixWorld );
|
|
12637
|
+
|
|
12638
|
+
const distanceToBox = Math.max( camera.near, _box.distanceToPoint( ray.origin ) ); // get the w component to scale the world space line width
|
|
12639
|
+
|
|
12640
|
+
_clipToWorldVector.set( 0, 0, - distanceToBox, 1.0 ).applyMatrix4( camera.projectionMatrix );
|
|
12641
|
+
|
|
12642
|
+
_clipToWorldVector.multiplyScalar( 1.0 / _clipToWorldVector.w );
|
|
12643
|
+
|
|
12644
|
+
_clipToWorldVector.applyMatrix4( camera.projectionMatrixInverse ); // increase the sphere bounds by the worst case line screen space width
|
|
12645
|
+
|
|
12646
|
+
|
|
12647
|
+
const boxMargin = Math.abs( ssMaxWidth / _clipToWorldVector.w ) * 0.5;
|
|
12648
|
+
_box.max.x += boxMargin;
|
|
12649
|
+
_box.max.y += boxMargin;
|
|
12650
|
+
_box.max.z += boxMargin;
|
|
12651
|
+
_box.min.x -= boxMargin;
|
|
12652
|
+
_box.min.y -= boxMargin;
|
|
12653
|
+
_box.min.z -= boxMargin;
|
|
12654
|
+
|
|
12655
|
+
if ( raycaster.ray.intersectsBox( _box ) === false ) {
|
|
12656
|
+
|
|
12657
|
+
return;
|
|
12658
|
+
|
|
12659
|
+
} //
|
|
12660
|
+
// pick a point 1 unit out along the ray to avoid the ray origin
|
|
12661
|
+
// sitting at the camera origin which will cause "w" to be 0 when
|
|
12662
|
+
// applying the projection matrix.
|
|
12663
|
+
|
|
12664
|
+
|
|
12665
|
+
ray.at( 1, _ssOrigin ); // ndc space [ - 1.0, 1.0 ]
|
|
12666
|
+
|
|
12667
|
+
_ssOrigin.w = 1;
|
|
12668
|
+
|
|
12669
|
+
_ssOrigin.applyMatrix4( camera.matrixWorldInverse );
|
|
12670
|
+
|
|
12671
|
+
_ssOrigin.applyMatrix4( projectionMatrix );
|
|
12672
|
+
|
|
12673
|
+
_ssOrigin.multiplyScalar( 1 / _ssOrigin.w ); // screen space
|
|
12674
|
+
|
|
12675
|
+
|
|
12676
|
+
_ssOrigin.x *= resolution.x / 2;
|
|
12677
|
+
_ssOrigin.y *= resolution.y / 2;
|
|
12678
|
+
_ssOrigin.z = 0;
|
|
12679
|
+
|
|
12680
|
+
_ssOrigin3.copy( _ssOrigin );
|
|
12681
|
+
|
|
12682
|
+
_mvMatrix.multiplyMatrices( camera.matrixWorldInverse, matrixWorld );
|
|
12683
|
+
|
|
12684
|
+
for ( let i = 0, l = instanceStart.count; i < l; i ++ ) {
|
|
12685
|
+
|
|
12686
|
+
_start4.fromBufferAttribute( instanceStart, i );
|
|
12687
|
+
|
|
12688
|
+
_end4.fromBufferAttribute( instanceEnd, i );
|
|
12689
|
+
|
|
12690
|
+
_start4.w = 1;
|
|
12691
|
+
_end4.w = 1; // camera space
|
|
12692
|
+
|
|
12693
|
+
_start4.applyMatrix4( _mvMatrix );
|
|
12694
|
+
|
|
12695
|
+
_end4.applyMatrix4( _mvMatrix ); // skip the segment if it's entirely behind the camera
|
|
12696
|
+
|
|
12697
|
+
|
|
12698
|
+
var isBehindCameraNear = _start4.z > near && _end4.z > near;
|
|
12699
|
+
|
|
12700
|
+
if ( isBehindCameraNear ) {
|
|
12701
|
+
|
|
12702
|
+
continue;
|
|
12703
|
+
|
|
12704
|
+
} // trim the segment if it extends behind camera near
|
|
12705
|
+
|
|
12706
|
+
|
|
12707
|
+
if ( _start4.z > near ) {
|
|
12708
|
+
|
|
12709
|
+
const deltaDist = _start4.z - _end4.z;
|
|
12710
|
+
const t = ( _start4.z - near ) / deltaDist;
|
|
12711
|
+
|
|
12712
|
+
_start4.lerp( _end4, t );
|
|
12713
|
+
|
|
12714
|
+
} else if ( _end4.z > near ) {
|
|
12715
|
+
|
|
12716
|
+
const deltaDist = _end4.z - _start4.z;
|
|
12717
|
+
const t = ( _end4.z - near ) / deltaDist;
|
|
12718
|
+
|
|
12719
|
+
_end4.lerp( _start4, t );
|
|
12720
|
+
|
|
12721
|
+
} // clip space
|
|
12722
|
+
|
|
12723
|
+
|
|
12724
|
+
_start4.applyMatrix4( projectionMatrix );
|
|
12725
|
+
|
|
12726
|
+
_end4.applyMatrix4( projectionMatrix ); // ndc space [ - 1.0, 1.0 ]
|
|
12727
|
+
|
|
12728
|
+
|
|
12729
|
+
_start4.multiplyScalar( 1 / _start4.w );
|
|
12730
|
+
|
|
12731
|
+
_end4.multiplyScalar( 1 / _end4.w ); // screen space
|
|
12732
|
+
|
|
12733
|
+
|
|
12734
|
+
_start4.x *= resolution.x / 2;
|
|
12735
|
+
_start4.y *= resolution.y / 2;
|
|
12736
|
+
_end4.x *= resolution.x / 2;
|
|
12737
|
+
_end4.y *= resolution.y / 2; // create 2d segment
|
|
12738
|
+
|
|
12739
|
+
_line.start.copy( _start4 );
|
|
12740
|
+
|
|
12741
|
+
_line.start.z = 0;
|
|
12742
|
+
|
|
12743
|
+
_line.end.copy( _end4 );
|
|
12744
|
+
|
|
12745
|
+
_line.end.z = 0; // get closest point on ray to segment
|
|
12746
|
+
|
|
12747
|
+
const param = _line.closestPointToPointParameter( _ssOrigin3, true );
|
|
12748
|
+
|
|
12749
|
+
_line.at( param, _closestPoint ); // check if the intersection point is within clip space
|
|
12750
|
+
|
|
12751
|
+
|
|
12752
|
+
const zPos = THREE__namespace.MathUtils.lerp( _start4.z, _end4.z, param );
|
|
12753
|
+
const isInClipSpace = zPos >= - 1 && zPos <= 1;
|
|
12754
|
+
const isInside = _ssOrigin3.distanceTo( _closestPoint ) < lineWidth * 0.5;
|
|
12755
|
+
|
|
12756
|
+
if ( isInClipSpace && isInside ) {
|
|
12757
|
+
|
|
12758
|
+
_line.start.fromBufferAttribute( instanceStart, i );
|
|
12759
|
+
|
|
12760
|
+
_line.end.fromBufferAttribute( instanceEnd, i );
|
|
12761
|
+
|
|
12762
|
+
_line.start.applyMatrix4( matrixWorld );
|
|
12763
|
+
|
|
12764
|
+
_line.end.applyMatrix4( matrixWorld );
|
|
12765
|
+
|
|
12766
|
+
const pointOnLine = new THREE__namespace.Vector3();
|
|
12767
|
+
const point = new THREE__namespace.Vector3();
|
|
12768
|
+
ray.distanceSqToSegment( _line.start, _line.end, point, pointOnLine );
|
|
12769
|
+
intersects.push( {
|
|
12770
|
+
point: point,
|
|
12771
|
+
pointOnLine: pointOnLine,
|
|
12772
|
+
distance: ray.origin.distanceTo( point ),
|
|
12773
|
+
object: this,
|
|
12774
|
+
face: null,
|
|
12775
|
+
faceIndex: i,
|
|
12776
|
+
uv: null,
|
|
12777
|
+
uv2: null
|
|
12778
|
+
} );
|
|
12779
|
+
|
|
12780
|
+
}
|
|
12781
|
+
|
|
12782
|
+
}
|
|
12783
|
+
|
|
12784
|
+
}
|
|
12785
|
+
|
|
12786
|
+
}
|
|
12787
|
+
|
|
12788
|
+
LineSegments2.prototype.LineSegments2 = true;
|
|
12789
|
+
|
|
12790
|
+
class Line2 extends LineSegments2 {
|
|
12791
|
+
|
|
12792
|
+
constructor( geometry = new THREE__namespace.LineGeometry(), material = new THREE__namespace.LineMaterial( {
|
|
12793
|
+
color: Math.random() * 0xffffff
|
|
12794
|
+
} ) ) {
|
|
12795
|
+
|
|
12796
|
+
super( geometry, material );
|
|
12797
|
+
this.type = 'Line2';
|
|
12798
|
+
|
|
12799
|
+
}
|
|
12800
|
+
|
|
12801
|
+
}
|
|
12802
|
+
|
|
12803
|
+
Line2.prototype.isLine2 = true;
|
|
12804
|
+
|
|
11579
12805
|
let DEG2RAD = Math.PI / 180;
|
|
11580
12806
|
class WebGLRenderer {
|
|
11581
12807
|
|