Three.js line vector to cylinder?

后端 未结 9 1825
粉色の甜心
粉色の甜心 2020-12-14 23:53

I have this to create a line between 2 points:

var geometry = new THREE.Geometry();
geometry.vertices.push(new THREE.Vector3(0, 0, 0));
geometry.vertices.pus         


        
相关标签:
9条回答
  • 2020-12-14 23:57

    I've had the exact same problem -- in WebGL the line width is always 1. So here's a function I wrote that will take two Vector3 objects and produce a cylinder mesh:

    var cylinderMesh = function( pointX, pointY )
    {
        // edge from X to Y
        var direction = new THREE.Vector3().subVectors( pointY, pointX );
        var arrow = new THREE.ArrowHelper( direction, pointX );
    
        // cylinder: radiusAtTop, radiusAtBottom, 
        //     height, radiusSegments, heightSegments
        var edgeGeometry = new THREE.CylinderGeometry( 2, 2, direction.length(), 6, 4 );
    
        var edge = new THREE.Mesh( edgeGeometry, 
            new THREE.MeshBasicMaterial( { color: 0x0000ff } ) );
        edge.rotation = arrow.rotation.clone();
        edge.position = new THREE.Vector3().addVectors( pointX, direction.multiplyScalar(0.5) );
        return edge;
    }
    
    0 讨论(0)
  • 2020-12-15 00:02

    Actually non of the other answers worked for me but to give credit I used the code that adjusts the position of edge and works fine.

    Using parts of this answer and looking at the source of threejs I ended up to the following

    var cylinderMesh = function( pointX, pointY )
    {
        /* edge from X to Y */
        var direction = new THREE.Vector3().subVectors( pointY, pointX );
        var orientation = new THREE.Matrix4();
        /* THREE.Object3D().up (=Y) default orientation for all objects */
        orientation.lookAt(pointX, pointY, new THREE.Object3D().up);
        /* rotation around axis X by -90 degrees 
         * matches the default orientation Y 
         * with the orientation of looking Z */
        orientation.multiply(new THREE.Matrix4(1,0,0,0,
                                                0,0,1,0, 
                                                0,-1,0,0,
                                                0,0,0,1));
    
        /* cylinder: radiusAtTop, radiusAtBottom, 
            height, radiusSegments, heightSegments */
        var edgeGeometry = new THREE.CylinderGeometry( 2, 2, direction.length(), 8, 1);
        var edge = new THREE.Mesh( edgeGeometry, 
                new THREE.MeshBasicMaterial( { color: 0x0000ff } ) );
    
        edge.applyMatrix(orientation)
        edge.position = new THREE.Vector3().addVectors( pointX, direction.multiplyScalar(0.5) );
        return edge;
    }
    

    A possible improvement is to add edgeGeometry and material as parameters so that someone can reuse the same objects and not create a new one in every call

    0 讨论(0)
  • 2020-12-15 00:03

    Old question, but still relevant today. Building on Lee Stemkoski's answer, this is what i ended up getting to work:

    const cylinderMesh = function( pointX, pointY )
    {
        // edge from X to Y
        const direction = new THREE.Vector3().subVectors( pointY, pointX );
        const arrow = new THREE.ArrowHelper( direction.clone().normalize(), pointY );
    
        // cylinder: radiusAtTop, radiusAtBottom, 
        //     height, radiusSegments, heightSegments
        const edgeGeometry = new THREE.CylinderGeometry( 2, 2, direction.length(), 6, 4 );
    
        const edge = new THREE.Mesh( edgeGeometry, 
            new THREE.MeshBasicMaterial( { color: 0x0000ff } ) );
        edge.rotation = arrow.rotation.clone();
        edge.position = new THREE.Vector3().addVectors( pointX, direction.multiplyScalar(0.5) );
        return edge;
    }
    

    Note the main difference: you have to normalize the direction vector and take the origin to be pointY. Normalizing the direction vector requires a .clone() in order to allow you to use it later on in the position calculation

    0 讨论(0)
  • 2020-12-15 00:11

    Stopped working for me in version 70, but with this update it does :)

    function cylinderMesh(pointX, pointY, material) {
                var direction = new THREE.Vector3().subVectors(pointY, pointX);
                var orientation = new THREE.Matrix4();
                orientation.lookAt(pointX, pointY, new THREE.Object3D().up);
                orientation.multiply(new THREE.Matrix4().set(1, 0, 0, 0,
                    0, 0, 1, 0,
                    0, -1, 0, 0,
                    0, 0, 0, 1));
                var edgeGeometry = new THREE.CylinderGeometry(2, 2, direction.length(), 8, 1);
                var edge = new THREE.Mesh(edgeGeometry, material);
                edge.applyMatrix(orientation);
                // position based on midpoints - there may be a better solution than this
                edge.position.x = (pointY.x + pointX.x) / 2;
                edge.position.y = (pointY.y + pointX.y) / 2;
                edge.position.z = (pointY.z + pointX.z) / 2;
                return edge;
            }
    
    0 讨论(0)
  • 2020-12-15 00:15

    For rotating the orientation, you can use

    edge.rotateX(Math.PI / 2);
    

    Or

    edge.rotateY(Math.PI / 2);
    

    Or

    edge.rotateZ(Math.PI / 2);
    

    As per the coordinates you wish to rotate. Hence, the code posted above with:

    var orientation = new THREE.Matrix4();
    /* THREE.Object3D().up (=Y) default orientation for all objects */
    orientation.lookAt(pointX, pointY, new THREE.Object3D().up);
    /* rotation around axis X by -90 degrees 
     * matches the default orientation Y 
     * with the orientation of looking Z */
    orientation.multiply(new THREE.Matrix4(1,0,0,0,
                                           0,0,1,0, 
                                           0,-1,0,0,
                                           0,0,0,1));
    

    Will not be required.

    0 讨论(0)
  • 2020-12-15 00:16

    A solution working with r94:

    function cylindricalSegment(A, B, radius, material) {
      var vec = B.clone(); vec.sub(A);
      var h = vec.length();
      vec.normalize();
      var quaternion = new THREE.Quaternion();
      quaternion.setFromUnitVectors(new THREE.Vector3(0, 1, 0), vec);
      var geometry = new THREE.CylinderGeometry(radius, radius, h, 32);
      geometry.translate(0, h / 2, 0);
      var cylinder = new THREE.Mesh(geometry, material);
      cylinder.applyQuaternion(quaternion);
      cylinder.position.set(A.x, A.y, A.z);
      return cylinder;
    }
    
    0 讨论(0)
提交回复
热议问题