diff options
Diffstat (limited to 'ui/imports/lib/d3three.js')
-rw-r--r-- | ui/imports/lib/d3three.js | 789 |
1 files changed, 0 insertions, 789 deletions
diff --git a/ui/imports/lib/d3three.js b/ui/imports/lib/d3three.js deleted file mode 100644 index 51493f2..0000000 --- a/ui/imports/lib/d3three.js +++ /dev/null @@ -1,789 +0,0 @@ -///////////////////////////////////////////////////////////////////////////////////////// -// Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) and others / -// / -// All rights reserved. This program and the accompanying materials / -// are made available under the terms of the Apache License, Version 2.0 / -// which accompanies this distribution, and is available at / -// http://www.apache.org/licenses/LICENSE-2.0 / -///////////////////////////////////////////////////////////////////////////////////////// -var chartOffset = 0; - -// D3.layout.force3d.js -// (C) 2012 ziggy.jonsson.nyc@gmail.com -// BSD license (http://opensource.org/licenses/BSD-3-Clause) - -d3.layout.force3d = function() { - var forceXY = d3.layout.force() - ,forceZ = d3.layout.force() - ,zNodes = {} - ,zLinks = {} - ,nodeID = 1 - ,linkID = 1 - ,tickFunction = Object - - var force3d = {} - - Object.keys(forceXY).forEach(function(d) { - force3d[d] = function() { - var result = forceXY[d].apply(this,arguments) - if (d !="nodes" && d!="links") forceZ[d].apply(this,arguments) - return (result == forceXY) ? force3d : result - } - }) - - - force3d.on = function(name,fn) { - tickFunction = fn - return force3d - } - - - forceXY.on("tick",function() { - - // Refresh zNodes add new, delete removed - var _zNodes = {} - forceXY.nodes().forEach(function(d,i) { - if (!d.id) d.id = nodeID++ - _zNodes[d.id] = zNodes[d.id] || {x:d.z,px:d.z,py:d.z,y:d.z,id:d.id} - d.z = _zNodes[d.id].x - }) - zNodes = _zNodes - - // Refresh zLinks add new, delete removed - var _zLinks = {} - forceXY.links().forEach(function(d) { - var nytt = false - if (!d.linkID) { d.linkID = linkID++;nytt=true} - _zLinks[d.linkID] = zLinks[d.linkID] || {target:zNodes[d.target.id],source:zNodes[d.source.id]} - - }) - zLinks = _zLinks - - // Update the nodes/links in forceZ - forceZ.nodes(d3.values(zNodes)) - forceZ.links(d3.values(zLinks)) - forceZ.start() // Need to kick forceZ so we don't lose the update mechanism - - // And run the user defined function, if defined - tickFunction() - }) - - // Expose the sub-forces for debugging purposes - force3d.xy = forceXY - force3d.z = forceZ - - return force3d -} -// end of d3.layout.force3d.js - -// Override default functions for d3 -THREE.Object3D.prototype.appendChild = function (c) { - this.add(c); - return c; -}; -THREE.Object3D.prototype.querySelectorAll = function () { return []; }; - -// this one is to use D3's .attr() on THREE's objects -THREE.Object3D.prototype.setAttribute = function (name, value) { - var chain = name.split('.'); - var object = this; - for (var i = 0; i < chain.length - 1; i++) { - object = object[chain[i]]; - } - object[chain[chain.length - 1]] = value; -} - -// d3three object -D3THREE = function(singleton) { - this.labelGroup = new THREE.Object3D(); - this.maxY = 0; - this.axisObjects = {}; - - this.running = true; - - if (singleton) { - if (typeof(d3three) !== 'undefined') { - d3three.stop(); - } - d3three = this; - } - - //if (!singleton) { - // d3threes.push(this); - //} -} - -D3THREE.prototype.init = function(divId) { - // standard THREE stuff, straight from examples - this.renderer = new THREE.WebGLRenderer({antialias: true, alpha : true, preserveDrawingBuffer: true}); - this.renderer.shadowMap.enabled = true; - this.renderer.shadowMap.type = THREE.PCFSoftShadow; - this.renderer.shadowMapSoft = true; - this.renderer.shadowCameraNear = 1000; - this.renderer.shadowCameraFar = 10000; - this.renderer.shadowCameraFov = 50; - this.renderer.shadowMapBias = 0.0039; - this.renderer.shadowMapDarkness = 0.25; - this.renderer.shadowMapWidth = 10000; - this.renderer.shadowMapHeight = 10000; - this.renderer.physicallyBasedShading = true; - - this.divId = divId; - this.width = document.getElementById(divId).offsetWidth; - this.height = document.getElementById(divId).offsetHeight; - - this.renderer.setSize( this.width, this.height ); - - document.getElementById(divId).appendChild( this.renderer.domElement ); - - this.camera = new THREE.PerspectiveCamera( 30, this.width / this.height, 1, 100000 ); - this.camera.position.z = -1000; - this.camera.position.x = -800; - this.camera.position.y = 600; - - this.controls = new THREE.OrbitControls( this.camera, this.renderer.domElement ); - - this.scene = new THREE.Scene(); - - this.defaultLight = new THREE.AmbientLight( 0xbbbbb ); // soft white light - this.scene.add( this.defaultLight ); - - this.scene.add(this.labelGroup); - - var self = this; - window.addEventListener( 'resize', self.onWindowResize.bind(self), false ); -} - -D3THREE.prototype.onWindowResize = function() { - var self = this; - self.camera.aspect = self.width / self.height; - self.camera.updateProjectionMatrix(); - - self.renderer.setSize( self.width, self.height ); -} - -D3THREE.prototype.animate = function() { - var self = this; - if (this.running) { - setTimeout( function() { - this.requestId = requestAnimationFrame( self.animate.bind(self) ); - }, 1000 / 15 ); - - self.renderer.render( self.scene, self.camera ); - self.controls.update(); - - self.labelGroup.children.forEach(function(l){ - l.rotation.setFromRotationMatrix(self.camera.matrix, "YXZ"); - l.rotation.x = 0; - l.rotation.z = 0; - }); - } else { - window.removeEventListener( 'resize', self.onWindowResize.bind(self) ); - while (self.scene.children.length > 0) { - var childObject = self.scene.children[0]; - if (childObject.geometry) { - childObject.geometry.dispose(); - } - if (childObject.material) { - childObject.material.dispose(); - } - self.scene.remove(childObject); - delete(childObject); - } - - self.renderer.context = null; - self.renderer.domElement = null; - self.renderer = null; - - self.camera = null; - self.controls = null; - self.scene = null; - self.labelGroup = null; - - cancelAnimationFrame(self.requestId); - } -} - -D3THREE.prototype.stop = function() { - this.running = false; -} - -D3THREE.prototype.render = function(element, data) { - element.render(data); -} - -D3THREE.createAxis = function(dt) { - return new D3THREE.Axis(dt); -} - -// d3three axis -D3THREE.Axis = function(dt) { - this._scale = d3.scale.linear(); - this._orient = "x"; - this._tickFormat = function(d) { return d }; - this._dt = dt; -} - -D3THREE.Axis.prototype.orient = function(o) { - if (o) { - this._dt.axisObjects[o] = this; - this._orient = o; - } - return this; -} - -D3THREE.Axis.prototype.scale = function(s) { - if (s) { - this._scale = s; - } - return this; -} - -D3THREE.Axis.prototype.tickFormat = function(f) { - if (f) { - this._tickFormat = f; - } - return this; -} - -D3THREE.Axis.prototype.interval = function() { - var interval; - if (typeof(this._scale.rangeBand) === 'function') { - // ordinal scale - interval = this._scale.range()[1]; - } else { - interval = this._scale.range()[1] / (this._scale.ticks().length - 1); - } - return interval; -} - -D3THREE.Axis.prototype.ticks = function() { - var ticks; - if (typeof(this._scale.rangeBand) === 'function') { - // ordinal scale - ticks = this._scale.domain(); - } else { - ticks = this._scale.ticks(); - } - return ticks; -} - -D3THREE.Axis.prototype.getRotationShift = function() { - return this.interval() * (this.ticks().length - 1) / 2; -} - -D3THREE.Axis.prototype.render = function() { - var material = new THREE.LineBasicMaterial({ - color: 0xbbbbbb, - linewidth: 2 - }); - - var tickMaterial = new THREE.LineBasicMaterial({ - color: 0xbbbbbb, - linewidth: 1 - }); - - var geometry = new THREE.Geometry(); - - interval = this.interval(); - - var interval = this.interval(), ticks = this.ticks(); - - // x,y axis shift, so rotation is from center of screen - var xAxisShift = this._dt.axisObjects.x.getRotationShift(), - yAxisShift = this._dt.axisObjects.y.getRotationShift(); - - for (var i = 0; i < ticks.length; i++) { - var tickMarGeometry = new THREE.Geometry(); - - var shape = new THREE.TextGeometry(this._tickFormat(ticks[i]), - { - size: 5, - height: 1, - curveSegments: 20 - }); - var wrapper = new THREE.MeshBasicMaterial({color: 0xbbbbbb}); - var words = new THREE.Mesh(shape, wrapper); - - if (this._orient === "y") { - // tick - geometry.vertices.push(new THREE.Vector3(i * interval - yAxisShift, chartOffset, 0 - xAxisShift)); - - tickMarGeometry.vertices.push(new THREE.Vector3(i * interval - yAxisShift, chartOffset, 0 - xAxisShift)); - tickMarGeometry.vertices.push(new THREE.Vector3(i * interval - yAxisShift, -10 + chartOffset, 0 - xAxisShift)); - var tickLine = new THREE.Line(tickMarGeometry, tickMaterial); - this._dt.scene.add(tickLine); - - if (i * interval > this._dt.maxY) { - this._dt.maxY = i * interval; - } - - words.position.set(i * interval - yAxisShift, -20 + chartOffset, 0 - xAxisShift); - } else if (this._orient === "z") { - // tick - geometry.vertices.push(new THREE.Vector3(0 + this._dt.maxY - yAxisShift, i * interval + chartOffset, 0 - xAxisShift)); - - tickMarGeometry.vertices.push(new THREE.Vector3(0 + this._dt.maxY - yAxisShift, i * interval + chartOffset, 0 - xAxisShift)); - tickMarGeometry.vertices.push(new THREE.Vector3(10 + this._dt.maxY - yAxisShift, i * interval + chartOffset, 0 - xAxisShift)); - var tickLine = new THREE.Line(tickMarGeometry, tickMaterial); - this._dt.scene.add(tickLine); - - words.position.set(20 + this._dt.maxY - yAxisShift, i * interval + chartOffset, 0 - xAxisShift); - } else if (this._orient === "x") { - // tick - geometry.vertices.push(new THREE.Vector3(0 - yAxisShift, chartOffset, i * interval - xAxisShift)); - - tickMarGeometry.vertices.push(new THREE.Vector3(0 - yAxisShift, 0 + chartOffset, i * interval - xAxisShift)); - tickMarGeometry.vertices.push(new THREE.Vector3(0 - yAxisShift, -10 + chartOffset, i * interval - xAxisShift)); - var tickLine = new THREE.Line(tickMarGeometry, tickMaterial); - this._dt.scene.add(tickLine); - - words.position.set(0 - yAxisShift, -20 + chartOffset, i * interval - xAxisShift); - } - - this._dt.labelGroup.add(words); - } - - var line = new THREE.Line(geometry, material); - - this._dt.scene.add(line); -} - -// Chart object -D3THREE.Chart = function() { -} - -D3THREE.Chart.prototype.config = function(c) { - this._config = $.extend(this._config, c); -} - -D3THREE.Chart.prototype.init = function(dt) { - this._dt = dt; - // mouse move - var self = this; - this._dt.renderer.domElement.addEventListener( 'mousemove', function(e) { - self.onDocumentMouseMove(e); - }, false ); -} - -var cumulativeOffset = function(element) { - var top = 0, left = 0; - do { - top += element.offsetTop || 0; - left += element.offsetLeft || 0; - element = element.offsetParent; - } while(element); - - return { - top: top, - left: left - }; -}; - -D3THREE.Chart.prototype.detectNodeHover = function(e) { - var boundingRect = this._dt.renderer.domElement.getBoundingClientRect(); - - var vector = new THREE.Vector3(); - vector.x = ( (e.clientX - boundingRect.left) / this._dt.renderer.domElement.width ) * 2 - 1; - vector.y = 1 - ( (e.clientY - boundingRect.top) / this._dt.renderer.domElement.height ) * 2; - vector.z = 1; - - // create a check ray - vector.unproject( this._dt.camera ); - var ray = new THREE.Raycaster( this._dt.camera.position, - vector.sub( this._dt.camera.position ).normalize() ); - - var intersects = ray.intersectObjects( this._nodeGroup.children ); - - for (var i = 0; i < this._nodeGroup.children.length; i++) { - this._nodeGroup.children[i].material.opacity = 1; - } - - if (intersects.length > 0) { - var obj = intersects[0].object; - obj.material.opacity = 0.5; - - var html = ""; - - html += "<div class=\"tooltip_kv\">"; - html += "<span>"; - html += "x: " + this._dt.axisObjects.x._tickFormat(obj.userData.x); - html += "</span><br>"; - html += "<span>"; - html += "y: " + this._dt.axisObjects.y._tickFormat(obj.userData.y); - html += "</span><br>"; - html += "<span>"; - html += "z: " + this._dt.axisObjects.z._tickFormat(obj.userData.z); - html += "</span><br>"; - html += "</div>"; - - document.getElementById("tooltip-container").innerHTML = html; - document.getElementById("tooltip-container").style.display = "block"; - - document.getElementById("tooltip-container").style.top = (e.pageY + 10) + "px"; - document.getElementById("tooltip-container").style.left = (e.pageX + 10) + "px"; - } else { - document.getElementById("tooltip-container").style.display = "none"; - } -} - -// Scatter plot -D3THREE.Scatter = function(dt) { - this.init(dt); - - this._nodeGroup = new THREE.Object3D(); - - this._config = {color: 0x4682B4, pointRadius: 5}; -} - -D3THREE.Scatter.prototype = new D3THREE.Chart(); - -D3THREE.Scatter.prototype.onDocumentMouseMove = function(e) { - // detect intersected spheres - this.detectNodeHover(e); -} - -D3THREE.Scatter.prototype.render = function(data) { - var geometry = new THREE.SphereGeometry( this._config.pointRadius, 32, 32 ); - - this._dt.scene.add(this._nodeGroup); - - // x,y axis shift, so rotation is from center of screen - var xAxisShift = this._dt.axisObjects.x.getRotationShift(), - yAxisShift = this._dt.axisObjects.y.getRotationShift(); - - var self = this; - d3.select(this._nodeGroup) - .selectAll() - .data(data) - .enter().append( function(d) { - var material = new THREE.MeshBasicMaterial( { - color: self._config.color } ); - var mesh = new THREE.Mesh( geometry, material ); - mesh.userData = {x: d.x, y: d.y, z: d.z}; - return mesh; - } ) - .attr("position.z", function(d) { - return self._dt.axisObjects.x._scale(d.x) - xAxisShift; - }) - .attr("position.x", function(d) { - return self._dt.axisObjects.y._scale(d.y) - yAxisShift; - }) - .attr("position.y", function(d) { - return self._dt.axisObjects.z._scale(d.z) + chartOffset; - }); -} - -// Surface plot -D3THREE.Surface = function(dt) { - this.init(dt); - - this._nodeGroup = new THREE.Object3D(); - - this._config = {color: 0x4682B4, pointColor: 0xff7f0e, pointRadius: 2}; -} - -D3THREE.Surface.prototype = new D3THREE.Chart(); - -D3THREE.Surface.prototype.onDocumentMouseMove = function(e) { - // detect intersected spheres - var boundingRect = this._dt.renderer.domElement.getBoundingClientRect(); - - var vector = new THREE.Vector3(); - vector.x = ( (e.clientX - boundingRect.left) / this._dt.renderer.domElement.width ) * 2 - 1; - vector.y = 1 - ( (e.clientY - boundingRect.top) / this._dt.renderer.domElement.height ) * 2; - vector.z = 1; - - // create a check ray - vector.unproject( this._dt.camera ); - var ray = new THREE.Raycaster( this._dt.camera.position, - vector.sub( this._dt.camera.position ).normalize() ); - - var meshIntersects = ray.intersectObjects( [this._meshSurface] ); - - if (meshIntersects.length > 0) { - for (var i = 0; i < this._nodeGroup.children.length; i++) { - this._nodeGroup.children[i].visible = true; - this._nodeGroup.children[i].material.opacity = 1; - } - - this.detectNodeHover(e); - } else { - // hide nodes - for (var i = 0; i < this._nodeGroup.children.length; i++) { - this._nodeGroup.children[i].visible = false; - } - } -} - -D3THREE.Surface.prototype.render = function(threeData) { - /* render data points */ - var geometry = new THREE.SphereGeometry( this._config.pointRadius, 32, 32 ); - - this._dt.scene.add(this._nodeGroup); - - // x,y axis shift, so rotation is from center of screen - var xAxisShift = this._dt.axisObjects.x.getRotationShift(), - yAxisShift = this._dt.axisObjects.y.getRotationShift(); - - var self = this; - d3.select(this._nodeGroup) - .selectAll() - .data(threeData) - .enter().append( function(d) { - var material = new THREE.MeshBasicMaterial( { - color: self._config.pointColor } ); - var mesh = new THREE.Mesh( geometry, material ); - mesh.userData = {x: d.x, y: d.y, z: d.z}; - mesh.visible = false; - return mesh; - } ) - .attr("position.z", function(d) { - return self._dt.axisObjects.x._scale(d.x) - xAxisShift; - }) - .attr("position.x", function(d) { - return self._dt.axisObjects.y._scale(d.y) - yAxisShift; - }) - .attr("position.y", function(d) { - return self._dt.axisObjects.z._scale(d.z) + chartOffset; - }); - - /* custom surface */ - function distance (v1, v2) - { - var dx = v1.x - v2.x; - var dy = v1.y - v2.y; - var dz = v1.z - v2.z; - - return Math.sqrt(dx*dx+dz*dz); - } - - var vertices = []; - var holes = []; - var triangles, mesh; - var geometry = new THREE.Geometry(); - var material = new THREE.MeshBasicMaterial({color: this._config.color}); - - for (var i = 0; i < threeData.length; i++) { - vertices.push(new THREE.Vector3( - self._dt.axisObjects.y._scale(threeData[i].y) - yAxisShift, - self._dt.axisObjects.z._scale(threeData[i].z) + chartOffset, - self._dt.axisObjects.x._scale(threeData[i].x) - xAxisShift)); - } - - geometry.vertices = vertices; - - for (var i = 0; i < vertices.length; i++) { - // find three closest vertices to generate surface - var v1, v2, v3; - var distances = []; - - // find vertices in same y or y + 1 row - var minY = Number.MAX_VALUE; - for (var j = i + 1; j < vertices.length; j++) { - if (i !== j && vertices[j].x > vertices[i].x) { - if (vertices[j].x < minY) { - minY = vertices[j].x; - } - } - } - - var rowVertices = [], row2Vertices = []; - for (var j = i + 1; j < vertices.length; j++) { - if (i !== j && (vertices[j].x === vertices[i].x)) { - rowVertices.push({index: j, v: vertices[j]}); - } - if (i !== j && (vertices[j].x === minY)) { - row2Vertices.push({index: j, v: vertices[j]}); - } - } - - if (rowVertices.length >= 1 && row2Vertices.length >= 2) { - // find smallest x - rowVertices.sort(function(a, b) { - if (a.v.z < b.v.z) { - return -1; - } else if (a.v.z === b.v.z) { - return 0; - } else { - return 1; - } - }); - - v1 = rowVertices[0].index; - - row2Vertices.sort(function(a, b) { - if (a.v.z < b.v.z) { - return -1; - } else if (a.v.z === b.v.z) { - return 0; - } else { - return 1; - } - }); - - v2 = row2Vertices[0].index; - v3 = row2Vertices[1].index; - - var fv = [i, v1, v2, v3]; - fv = fv.sort(function(a, b) { - if (a < b) return -1; - else if (a === b) return 0; - else return 1; - }); - - geometry.faces.push( new THREE.Face3(fv[1], fv[0], fv[3])); - geometry.faces.push( new THREE.Face3(fv[0], fv[2], fv[3])); - } - } - - this._meshSurface = new THREE.Mesh( geometry, material ); - this._dt.scene.add(this._meshSurface); -} - -// Bar plot -D3THREE.Bar = function(dt) { - this.init(dt); - - this._nodeGroup = new THREE.Object3D(); - - this._config = {color: 0x4682B4, barSize: 5}; -} - -D3THREE.Bar.prototype = new D3THREE.Chart(); - -D3THREE.Bar.prototype.onDocumentMouseMove = function(e) { - this.detectNodeHover(e); -} - -D3THREE.Bar.prototype.render = function(threeData) { - /* render data points */ - this._dt.scene.add(this._nodeGroup); - - // x,y axis shift, so rotation is from center of screen - var xAxisShift = this._dt.axisObjects.x.getRotationShift(), - yAxisShift = this._dt.axisObjects.y.getRotationShift(); - - var self = this; - d3.select(this._nodeGroup) - .selectAll() - .data(threeData) - .enter().append( function(d) { - var height = self._dt.axisObjects.z._scale(d.z) + chartOffset; - var geometry = new THREE.BoxGeometry( self._config.barSize, height, self._config.barSize ); - var material = new THREE.MeshBasicMaterial( { - color: self._config.color } ); - var mesh = new THREE.Mesh( geometry, material ); - mesh.userData = {x: d.x, y: d.y, z: d.z}; - return mesh; - } ) - .attr("position.z", function(d) { - return self._dt.axisObjects.x._scale(d.x) - xAxisShift; - }) - .attr("position.x", function(d) { - return self._dt.axisObjects.y._scale(d.y) - yAxisShift; - }) - .attr("position.y", function(d) { - var height = self._dt.axisObjects.z._scale(d.z) + chartOffset; - return height / 2; - }); -} - -// Force layout plot -D3THREE.Force = function(dt) { - this.init(dt); - - this._nodeGroup = new THREE.Object3D(); - - this._config = {color: 0x4682B4, linkColor: 0xcccccc, linkWidth: 1}; -} - -D3THREE.Force.prototype = new D3THREE.Chart(); - -D3THREE.Force.prototype.onDocumentMouseMove = function(e) { -} - -D3THREE.Force.prototype.render = function(threeData) { - var spheres = [], three_links = []; - // Define the 3d force - var force = d3.layout.force3d() - .nodes(sort_data=[]) - .links(links=[]) - .size([50, 50]) - .gravity(0.3) - .charge(-400) - - var DISTANCE = 1; - - for (var i = 0; i < threeData.nodes.length; i++) { - sort_data.push({x:threeData.nodes.x + DISTANCE,y:threeData.nodes.y + DISTANCE,z:0}) - - // set up the sphere vars - var radius = 5, - segments = 16, - rings = 16; - - // create the sphere's material - var sphereMaterial = new THREE.MeshLambertMaterial({ color: this._config.color }); - - var sphere = new THREE.Mesh( - new THREE.SphereGeometry( - radius, - segments, - rings), - sphereMaterial); - - spheres.push(sphere); - - // add the sphere to the scene - this._dt.scene.add(sphere); - } - - for (var i = 0; i < threeData.links.length; i++) { - links.push({target:sort_data[threeData.links[i].target],source:sort_data[threeData.links[i].source]}); - - var material = new THREE.LineBasicMaterial({ color: this._config.linkColor, - linewidth: this._config.linkWidth}); - var geometry = new THREE.Geometry(); - - geometry.vertices.push( new THREE.Vector3( 0, 0, 0 ) ); - geometry.vertices.push( new THREE.Vector3( 0, 0, 0 ) ); - var line = new THREE.Line( geometry, material ); - line.userData = { source: threeData.links[i].source, - target: threeData.links[i].target }; - three_links.push(line); - this._dt.scene.add(line); - - force.start(); - } - - // set up the axes - var x = d3.scale.linear().domain([0, 350]).range([0, 10]), - y = d3.scale.linear().domain([0, 350]).range([0, 10]), - z = d3.scale.linear().domain([0, 350]).range([0, 10]); - - var self = this; - force.on("tick", function(e) { - for (var i = 0; i < sort_data.length; i++) { - spheres[i].position.set(x(sort_data[i].x) * 40 - 40, y(sort_data[i].y) * 40 - 40,z(sort_data[i].z) * 40 - 40); - - for (var j = 0; j < three_links.length; j++) { - var line = three_links[j]; - var vi = -1; - if (line.userData.source === i) { - vi = 0; - } - if (line.userData.target === i) { - vi = 1; - } - - if (vi >= 0) { - line.geometry.vertices[vi].x = x(sort_data[i].x) * 40 - 40; - line.geometry.vertices[vi].y = y(sort_data[i].y) * 40 - 40; - line.geometry.vertices[vi].z = y(sort_data[i].z) * 40 - 40; - line.geometry.verticesNeedUpdate = true; - } - } - } - }); -} |