如何拖动Threejs指向

时间:2017-08-07 06:24:42

标签: graph three.js graph-visualization

我正在尝试使用threejs r86(最新的主版本)进行巨大的图形可视化,为了显示600,000个节点,我发现了一种比使用带有THREE.points的网格更快地绘制它们的方法,但是知道我需要让它们可拖动搜索我发现raycast找到了最接近鼠标点的对象,但我遇到了一个问题,因为所有的taht点都只是一个对象,不能单独更改。

function Graph3(Nodes, Edges) {
this.renderer = new THREE.WebGLRenderer({ alpha: true});
var width = window.innerWidth , height = window.innerHeight;
this.renderer.setSize(width, height, false);
document.body.appendChild(this.renderer.domElement);
this.scene = new THREE.Scene(),
this.camera = new THREE.PerspectiveCamera(100, width / height, 0.1, 3000),
this.controls = new THREE.OrbitControls(this.camera);
this.controls.enableKeys = true;
this.controls.enableRotate = false;

var material, geometry;
self = this;
material = new THREE.LineBasicMaterial({color: '#ccc'});

geometry = new THREE.Geometry();
geometry.vertices = Nodes.map(function(item){return new THREE.Vector3(item.pos.x,item.pos.y,item.pos.z);});
// this.vertices = geometry.vertices;


this.line = new THREE.LineSegments(geometry, material);
this.scene.add(this.line);

var Node = new THREE.Group();

material = new THREE.PointsMaterial( { color:0x000060 ,size:1 } );

this.particles = new THREE.Mesh(geometry,material)
this.particles = new THREE.Points( geometry, material);
this.scene.add( this.particles );

dragControls = new THREE.DragControls([this.particles], this.camera/*,this.scene*/, this.renderer.domElement);

this.camera.position.z = 200;

var raycaster = new THREE.Raycaster();
var mouse = new THREE.Vector2();

document.addEventListener( 'click', function ( event ) {

    // calculate mouse position in normalized device coordinates
    // (-1 to +1) for both components

    mouse.x = ( event.clientX / window.innerWidth ) * 2 - 1;
    mouse.y = - ( event.clientY / window.innerHeight ) * 2 + 1;
    console.log(mouse);

}, false );


stats = new Stats();
document.body.appendChild(stats.dom);

this.animate = function()
{

    raycaster.setFromCamera( mouse, self.camera );
    var intersections = raycaster.intersectObject( self.particles );
    intersection = ( intersections.length ) > 0 ? intersections[ 0 ] : null;

    if ( intersection !== null) {
        console.log(intersection);
    }

    requestAnimationFrame( self.animate );
    stats.update();

    self.renderer.render(self.scene, self.camera);
}
this.animate();}

我能够使用dragControls更改所有点,但不能单独移动它们 我找到了EventsControls.js文件来帮助我们处理事件,但我无法使用它

2 个答案:

答案 0 :(得分:0)

在这里,您可以检查如何使用raycaster定位缓冲区几何体的各个部分: https://github.com/mrdoob/three.js/blob/master/examples/webgl_interactive_buffergeometry.html

至于移动它们,请参阅此问题并回答: How to quickly update a large BufferGeometry?

答案 1 :(得分:0)

感谢您在上一个问题中帮助我。 我在2d平面(z = 0)中制作我的点,我可以使用bufferGeometry和RawShaderMaterial制作它们,但是现在我还有另一个拖动它们的问题,raycaster怎么办?它需要vec3位置,但我已经为了性能目的而改变它。

var Geo = new THREE.BufferGeometry();

            var position = new Float32Array( NodeCount * 2 );
            var colors = new Float32Array( NodeCount * 3 );
            var sizes = new Float32Array( NodeCount );

            for ( var i = 0; i < NodeCount; i++ ) {

                position[ 2*i ]     = (Math.random() - 0.5) * 10;
                position[ 2*i + 1 ] = (Math.random() - 0.5) * 10;


                colors[ 3*i ] = Math.random();
                colors[3*i+1] = Math.random();
                colors[3*i+2] = Math.random();

                // sizes

                sizes[i] = Math.random() * 5 ;

            }

            Geo.addAttribute( 'position', new THREE.BufferAttribute( position, 2 ) );
            Geo.addAttribute( 'color', new THREE.BufferAttribute( colors, 3 ) );
            Geo.addAttribute( 'size', new THREE.BufferAttribute( sizes, 1 ) );



            points = new THREE.Points( Geo, new THREE.RawShaderMaterial({
                vertexShader:`
                precision highp float;

                uniform mat4 modelViewMatrix;
                uniform mat4 projectionMatrix;
                uniform vec3 cameraPosition;
                attribute vec2 position;  /// reason of problem

                varying vec3 vColor;
                attribute vec3 color;
                attribute float size;

                void main() {
                    vColor = color;

                    gl_PointSize = size;
                    gl_Position = projectionMatrix * modelViewMatrix * vec4( position , 0, 1 );
                }`,
                fragmentShader:`
                precision highp float;
                varying vec3 vColor;
                void main() {
                    gl_FragColor = vec4( vColor, 1.0 ) ;
                }`
            }) );
            scene.add( points );

和我使用raycaster:

    function mouseDown(e) {
                e.preventDefault();

                var mouse = new THREE.Vector2();
                mouse.x = ( event.clientX / window.innerWidth ) * 2 - 1;
                mouse.y = - ( event.clientY / window.innerHeight ) * 2 + 1;
//                mouse.z = 0;
                raycaster.setFromCamera(mouse, camera);
                raycaster.far = camera.position.z + 3;
                const intersect = raycaster.intersectObject(points);
                console.log(intersect);
                if (intersect.length > 0) {
                    controls.enabled = false;
                    console.log(intersect);
                    selection = intersect[0].index;
                }
            }

        function mouseUp(e) {
            controls.enabled = true;
            var vector = new THREE.Vector3();
            vector.x = (( event.clientX / window.innerWidth ) * 2 - 1);
            vector.y = (- ( event.clientY / window.innerHeight ) * 2 + 1);
            vector.z = 1.0;
            console.log(camera.position.z);
            vector.unproject( camera );

            var dir = vector.sub( camera.position ).normalize();

            var distance = - camera.position.z / dir.z;

            var temp = camera.position.clone().add( dir.multiplyScalar( distance ) );
            var pos = points.geometry.attributes.position;
            pos.setXY(selection, temp.x, temp.y);
            pos.updateRange.offset = selection; // where to start updating
            pos.updateRange.count = 1; // how many vertices to update
            pos.needsUpdate = true;
            selection = undefined;
        }