gl-line3d
Advanced tools
Comparing version 1.0.5 to 1.1.0
350
lines.js
@@ -5,23 +5,23 @@ 'use strict' | ||
var createBuffer = require('gl-buffer') | ||
var createVAO = require('gl-vao') | ||
var createBuffer = require('gl-buffer') | ||
var createVAO = require('gl-vao') | ||
var createTexture = require('gl-texture2d') | ||
var unpackFloat = require('glsl-read-float') | ||
var bsearch = require('binary-search-bounds') | ||
var ndarray = require('ndarray') | ||
var shaders = require('./lib/shaders') | ||
var unpackFloat = require('glsl-read-float') | ||
var bsearch = require('binary-search-bounds') | ||
var ndarray = require('ndarray') | ||
var shaders = require('./lib/shaders') | ||
var createShader = shaders.createShader | ||
var createPickShader = shaders.createPickShader | ||
var createShader = shaders.createShader | ||
var createPickShader = shaders.createPickShader | ||
var identity = [1,0,0,0, | ||
0,1,0,0, | ||
0,0,1,0, | ||
0,0,0,1] | ||
var identity = [1, 0, 0, 0, | ||
0, 1, 0, 0, | ||
0, 0, 1, 0, | ||
0, 0, 0, 1] | ||
function distance(a, b) { | ||
function distance (a, b) { | ||
var s = 0.0 | ||
for(var i=0; i<3; ++i) { | ||
for (var i = 0; i < 3; ++i) { | ||
var d = a[i] - b[i] | ||
s += d*d | ||
s += d * d | ||
} | ||
@@ -31,5 +31,5 @@ return Math.sqrt(s) | ||
function filterClipBounds(bounds) { | ||
var result = [[-1e6,-1e6,-1e6], [1e6,1e6,1e6]] | ||
for(var i=0; i<3; ++i) { | ||
function filterClipBounds (bounds) { | ||
var result = [[-1e6, -1e6, -1e6], [1e6, 1e6, 1e6]] | ||
for (var i = 0; i < 3; ++i) { | ||
result[0][i] = Math.max(bounds[0][i], result[0][i]) | ||
@@ -41,28 +41,29 @@ result[1][i] = Math.min(bounds[1][i], result[1][i]) | ||
function PickResult(tau, position, index, dataCoordinate) { | ||
function PickResult (tau, position, index, dataCoordinate) { | ||
this.arcLength = tau | ||
this.position = position | ||
this.index = index | ||
this.position = position | ||
this.index = index | ||
this.dataCoordinate = dataCoordinate | ||
} | ||
function LinePlot(gl, shader, pickShader, buffer, vao, texture) { | ||
this.gl = gl | ||
this.shader = shader | ||
this.pickShader = pickShader | ||
this.buffer = buffer | ||
this.vao = vao | ||
this.clipBounds = [[-Infinity,-Infinity,-Infinity], | ||
[ Infinity, Infinity, Infinity]] | ||
this.points = [] | ||
this.arcLength = [] | ||
this.vertexCount = 0 | ||
this.bounds = [[0,0,0],[0,0,0]] | ||
this.pickId = 0 | ||
this.lineWidth = 1 | ||
this.texture = texture | ||
this.dashScale = 1 | ||
this.opacity = 1 | ||
this.dirty = true | ||
this.pixelRatio = 1 | ||
function LinePlot (gl, shader, pickShader, buffer, vao, texture) { | ||
this.gl = gl | ||
this.shader = shader | ||
this.pickShader = pickShader | ||
this.buffer = buffer | ||
this.vao = vao | ||
this.clipBounds = [ | ||
[ -Infinity, -Infinity, -Infinity ], | ||
[ Infinity, Infinity, Infinity ]] | ||
this.points = [] | ||
this.arcLength = [] | ||
this.vertexCount = 0 | ||
this.bounds = [[0, 0, 0], [0, 0, 0]] | ||
this.pickId = 0 | ||
this.lineWidth = 1 | ||
this.texture = texture | ||
this.dashScale = 1 | ||
this.opacity = 1 | ||
this.dirty = true | ||
this.pixelRatio = 1 | ||
} | ||
@@ -72,7 +73,7 @@ | ||
proto.isTransparent = function() { | ||
proto.isTransparent = function () { | ||
return this.opacity < 1 | ||
} | ||
proto.isOpaque = function() { | ||
proto.isOpaque = function () { | ||
return this.opacity >= 1 | ||
@@ -83,21 +84,21 @@ } | ||
proto.setPickBase = function(id) { | ||
proto.setPickBase = function (id) { | ||
this.pickId = id | ||
} | ||
proto.drawTransparent = proto.draw = function(camera) { | ||
var gl = this.gl | ||
var shader = this.shader | ||
var vao = this.vao | ||
proto.drawTransparent = proto.draw = function (camera) { | ||
var gl = this.gl | ||
var shader = this.shader | ||
var vao = this.vao | ||
shader.bind() | ||
shader.uniforms = { | ||
model: camera.model || identity, | ||
view: camera.view || identity, | ||
projection: camera.projection || identity, | ||
clipBounds: filterClipBounds(this.clipBounds), | ||
dashTexture: this.texture.bind(), | ||
dashScale: this.dashScale / this.arcLength[this.arcLength.length-1], | ||
opacity: this.opacity, | ||
screenShape: [gl.drawingBufferWidth, gl.drawingBufferHeight], | ||
pixelRatio: this.pixelRatio | ||
model: camera.model || identity, | ||
view: camera.view || identity, | ||
projection: camera.projection || identity, | ||
clipBounds: filterClipBounds(this.clipBounds), | ||
dashTexture: this.texture.bind(), | ||
dashScale: this.dashScale / this.arcLength[this.arcLength.length - 1], | ||
opacity: this.opacity, | ||
screenShape: [gl.drawingBufferWidth, gl.drawingBufferHeight], | ||
pixelRatio: this.pixelRatio | ||
} | ||
@@ -108,15 +109,15 @@ vao.bind() | ||
proto.drawPick = function(camera) { | ||
var gl = this.gl | ||
var shader = this.pickShader | ||
var vao = this.vao | ||
proto.drawPick = function (camera) { | ||
var gl = this.gl | ||
var shader = this.pickShader | ||
var vao = this.vao | ||
shader.bind() | ||
shader.uniforms = { | ||
model: camera.model || identity, | ||
view: camera.view || identity, | ||
model: camera.model || identity, | ||
view: camera.view || identity, | ||
projection: camera.projection || identity, | ||
pickId: this.pickId, | ||
pickId: this.pickId, | ||
clipBounds: filterClipBounds(this.clipBounds), | ||
screenShape: [gl.drawingBufferWidth, gl.drawingBufferHeight], | ||
pixelRatio: this.pixelRatio | ||
screenShape: [gl.drawingBufferWidth, gl.drawingBufferHeight], | ||
pixelRatio: this.pixelRatio | ||
} | ||
@@ -127,9 +128,13 @@ vao.bind() | ||
proto.update = function(options) { | ||
proto.update = function (options) { | ||
var i, j | ||
this.dirty = true | ||
if('dashScale' in options) { | ||
var connectGaps = !!options.connectGaps | ||
if ('dashScale' in options) { | ||
this.dashScale = options.dashScale | ||
} | ||
if('opacity' in options) { | ||
if ('opacity' in options) { | ||
this.opacity = +options.opacity | ||
@@ -139,23 +144,25 @@ } | ||
var positions = options.position || options.positions | ||
if(!positions) { | ||
if (!positions) { | ||
return | ||
} | ||
//Default color | ||
var colors = options.color || options.colors || [0,0,0,1] | ||
// Default color | ||
var colors = options.color || options.colors || [0, 0, 0, 1] | ||
var lineWidth = options.lineWidth || 1 | ||
//Recalculate buffer data | ||
var buffer = [] | ||
var arcLengthArray = [] | ||
var pointArray = [] | ||
var arcLength = 0.0 | ||
var vertexCount = 0 | ||
var bounds = [[ Infinity, Infinity, Infinity], | ||
[-Infinity,-Infinity,-Infinity]] | ||
// Recalculate buffer data | ||
var buffer = [] | ||
var arcLengthArray = [] | ||
var pointArray = [] | ||
var arcLength = 0.0 | ||
var vertexCount = 0 | ||
var bounds = [ | ||
[ Infinity, Infinity, Infinity ], | ||
[ -Infinity, -Infinity, -Infinity ]] | ||
var hadGap = false | ||
fill_loop: | ||
for(var i=1; i<positions.length; ++i) { | ||
var a = positions[i-1] | ||
fill_loop: | ||
for (i = 1; i < positions.length; ++i) { | ||
var a = positions[i - 1] | ||
var b = positions[i] | ||
@@ -166,5 +173,14 @@ | ||
for(var j=0; j<3; ++j) { | ||
if(isNaN(a[j]) || isNaN(b[j]) || | ||
for (j = 0; j < 3; ++j) { | ||
if (isNaN(a[j]) || isNaN(b[j]) || | ||
!isFinite(a[j]) || !isFinite(b[j])) { | ||
if (!connectGaps && buffer.length > 0) { | ||
for (var k = 0; k < 24; ++k) { | ||
buffer.push(buffer[buffer.length - 12]) | ||
} | ||
vertexCount += 2 | ||
hadGap = true | ||
} | ||
continue fill_loop | ||
@@ -177,4 +193,4 @@ } | ||
var acolor, bcolor | ||
if(Array.isArray(colors[0])) { | ||
acolor = colors[i-1] | ||
if (Array.isArray(colors[0])) { | ||
acolor = colors[i - 1] | ||
bcolor = colors[i] | ||
@@ -184,15 +200,14 @@ } else { | ||
} | ||
if(acolor.length === 3) { | ||
if (acolor.length === 3) { | ||
acolor = [acolor[0], acolor[1], acolor[2], 1] | ||
} | ||
if(bcolor.length === 3) { | ||
if (bcolor.length === 3) { | ||
bcolor = [bcolor[0], bcolor[1], bcolor[2], 1] | ||
} | ||
var w0, w1 | ||
if(Array.isArray(lineWidth)) { | ||
w0 = lineWidth[i-1] | ||
w1 = lineWidht[i] | ||
var w0 | ||
if (Array.isArray(lineWidth)) { | ||
w0 = lineWidth[i - 1] | ||
} else { | ||
w0 = w1 = lineWidth | ||
w0 = lineWidth | ||
} | ||
@@ -203,6 +218,15 @@ | ||
if (hadGap) { | ||
for (j = 0; j < 2; ++j) { | ||
buffer.push( | ||
a[0], a[1], a[2], b[0], b[1], b[2], t0, w0, acolor[0], acolor[1], acolor[2], acolor[3]) | ||
} | ||
vertexCount += 2 | ||
hadGap = false | ||
} | ||
buffer.push( | ||
a[0], a[1], a[2], b[0], b[1], b[2], t0, w0, acolor[0], acolor[1], acolor[2], acolor[3], | ||
a[0], a[1], a[2], b[0], b[1], b[2], t0,-w0, acolor[0], acolor[1], acolor[2], acolor[3], | ||
b[0], b[1], b[2], a[0], a[1], a[2], arcLength,-w0, bcolor[0], bcolor[1], bcolor[2], bcolor[3], | ||
a[0], a[1], a[2], b[0], b[1], b[2], t0, -w0, acolor[0], acolor[1], acolor[2], acolor[3], | ||
b[0], b[1], b[2], a[0], a[1], a[2], arcLength, -w0, bcolor[0], bcolor[1], bcolor[2], bcolor[3], | ||
b[0], b[1], b[2], a[0], a[1], a[2], arcLength, w0, bcolor[0], bcolor[1], bcolor[2], bcolor[3]) | ||
@@ -215,3 +239,3 @@ | ||
arcLengthArray.push(arcLength) | ||
pointArray.push(positions[positions.length-1].slice()) | ||
pointArray.push(positions[positions.length - 1].slice()) | ||
@@ -225,21 +249,21 @@ this.bounds = bounds | ||
if('dashes' in options) { | ||
if ('dashes' in options) { | ||
var dashArray = options.dashes | ||
//Calculate prefix sum | ||
// Calculate prefix sum | ||
var prefixSum = dashArray.slice() | ||
prefixSum.unshift(0) | ||
for(var i=1; i<prefixSum.length; ++i) { | ||
prefixSum[i] = prefixSum[i-1] + prefixSum[i] | ||
for (i = 1; i < prefixSum.length; ++i) { | ||
prefixSum[i] = prefixSum[i - 1] + prefixSum[i] | ||
} | ||
var dashTexture = ndarray(new Array(256*4), [256, 1, 4]) | ||
for(var i=0; i<256; ++i) { | ||
for(var j=0; j<4; ++j) { | ||
dashTexture.set(i,0,j, 0) | ||
var dashTexture = ndarray(new Array(256 * 4), [256, 1, 4]) | ||
for (i = 0; i < 256; ++i) { | ||
for (j = 0; j < 4; ++j) { | ||
dashTexture.set(i, 0, j, 0) | ||
} | ||
if(bsearch.le(prefixSum, prefixSum[prefixSum.length-1]*i/255.0) & 1) { | ||
dashTexture.set(i,0,0, 0) | ||
if (bsearch.le(prefixSum, prefixSum[prefixSum.length - 1] * i / 255.0) & 1) { | ||
dashTexture.set(i, 0, 0, 0) | ||
} else { | ||
dashTexture.set(i,0,0, 255) | ||
dashTexture.set(i, 0, 0, 255) | ||
} | ||
@@ -252,3 +276,3 @@ } | ||
proto.dispose = function() { | ||
proto.dispose = function () { | ||
this.shader.dispose() | ||
@@ -259,7 +283,7 @@ this.vao.dispose() | ||
proto.pick = function(selection) { | ||
if(!selection) { | ||
proto.pick = function (selection) { | ||
if (!selection) { | ||
return null | ||
} | ||
if(selection.id !== this.pickId) { | ||
if (selection.id !== this.pickId) { | ||
return null | ||
@@ -273,20 +297,20 @@ } | ||
var index = bsearch.le(this.arcLength, tau) | ||
if(index < 0) { | ||
if (index < 0) { | ||
return null | ||
} | ||
if(index === this.arcLength.length-1) { | ||
if (index === this.arcLength.length - 1) { | ||
return new PickResult( | ||
this.arcLength[this.arcLength.length-1], | ||
this.points[this.points.length-1].slice(), | ||
this.arcLength[this.arcLength.length - 1], | ||
this.points[this.points.length - 1].slice(), | ||
index) | ||
} | ||
var a = this.points[index] | ||
var b = this.points[Math.min(index+1, this.points.length-1)] | ||
var t = (tau - this.arcLength[index]) / (this.arcLength[index+1] - this.arcLength[index]) | ||
var b = this.points[Math.min(index + 1, this.points.length - 1)] | ||
var t = (tau - this.arcLength[index]) / (this.arcLength[index + 1] - this.arcLength[index]) | ||
var ti = 1.0 - t | ||
var x = [0,0,0] | ||
for(var i=0; i<3; ++i) { | ||
var x = [0, 0, 0] | ||
for (var i = 0; i < 3; ++i) { | ||
x[i] = ti * a[i] + t * b[i] | ||
} | ||
var dataIndex = Math.min((t < 0.5) ? index : (index+1), this.points.length-1) | ||
var dataIndex = Math.min((t < 0.5) ? index : (index + 1), this.points.length - 1) | ||
return new PickResult( | ||
@@ -299,56 +323,56 @@ tau, | ||
function createLinePlot(options) { | ||
function createLinePlot (options) { | ||
var gl = options.gl || (options.scene && options.scene.gl) | ||
var shader = createShader(gl) | ||
shader.attributes.position.location = 0 | ||
shader.attributes.position.location = 0 | ||
shader.attributes.nextPosition.location = 1 | ||
shader.attributes.arcLength.location = 2 | ||
shader.attributes.lineWidth.location = 3 | ||
shader.attributes.color.location = 4 | ||
shader.attributes.arcLength.location = 2 | ||
shader.attributes.lineWidth.location = 3 | ||
shader.attributes.color.location = 4 | ||
var pickShader = createPickShader(gl) | ||
pickShader.attributes.position.location = 0 | ||
pickShader.attributes.position.location = 0 | ||
pickShader.attributes.nextPosition.location = 1 | ||
pickShader.attributes.arcLength.location = 2 | ||
pickShader.attributes.lineWidth.location = 3 | ||
pickShader.attributes.color.location = 4 | ||
pickShader.attributes.arcLength.location = 2 | ||
pickShader.attributes.lineWidth.location = 3 | ||
pickShader.attributes.color.location = 4 | ||
var buffer = createBuffer(gl) | ||
var vao = createVAO(gl, [ | ||
{ | ||
'buffer': buffer, | ||
'size': 3, | ||
'offset': 0, | ||
'stride': 48 | ||
}, | ||
{ | ||
'buffer': buffer, | ||
'size': 3, | ||
'offset': 12, | ||
'stride': 48 | ||
}, | ||
{ | ||
'buffer': buffer, | ||
'size': 1, | ||
'offset': 24, | ||
'stride': 48 | ||
}, | ||
{ | ||
'buffer': buffer, | ||
'size': 1, | ||
'offset': 28, | ||
'stride': 48 | ||
}, | ||
{ | ||
'buffer': buffer, | ||
'size': 4, | ||
'offset': 32, | ||
'stride': 48 | ||
} | ||
]) | ||
{ | ||
'buffer': buffer, | ||
'size': 3, | ||
'offset': 0, | ||
'stride': 48 | ||
}, | ||
{ | ||
'buffer': buffer, | ||
'size': 3, | ||
'offset': 12, | ||
'stride': 48 | ||
}, | ||
{ | ||
'buffer': buffer, | ||
'size': 1, | ||
'offset': 24, | ||
'stride': 48 | ||
}, | ||
{ | ||
'buffer': buffer, | ||
'size': 1, | ||
'offset': 28, | ||
'stride': 48 | ||
}, | ||
{ | ||
'buffer': buffer, | ||
'size': 4, | ||
'offset': 32, | ||
'stride': 48 | ||
} | ||
]) | ||
//Create texture for dash pattern | ||
var defaultTexture = ndarray(new Array(256*4), [256,1,4]) | ||
for(var i=0; i<256*4; ++i) { | ||
// Create texture for dash pattern | ||
var defaultTexture = ndarray(new Array(256 * 4), [256, 1, 4]) | ||
for (var i = 0; i < 256 * 4; ++i) { | ||
defaultTexture.data[i] = 255 | ||
@@ -355,0 +379,0 @@ } |
{ | ||
"name": "gl-line3d", | ||
"version": "1.0.5", | ||
"version": "1.1.0", | ||
"description": "3D line plot", | ||
@@ -5,0 +5,0 @@ "main": "lines.js", |
17058
406