2013-03-09 2 views
7

Я это, чтобы создать линию между 2 точками:Линия вектора Three.js к цилиндру?

var geometry = new THREE.Geometry(); 
geometry.vertices.push(new THREE.Vector3(0, 0, 0)); 
geometry.vertices.push(new THREE.Vector3(20, 100, 55)); 
var line = new THREE.Line(geometry, material, parameters = { linewidth: 400 }); 
scene.add(line); 

(ширина линии, не имеет никакого эффекта.)

Мой вопрос, как я могу превратить это в цилиндр? Я хочу создать цилиндр между двумя точками.

+0

это, кажется, очень похожий вопрос, что один: [отображать цилиндр между 2 векторами] [1] [1]: http://stackoverflow.com/questions/ 15139649/three-js-two-points-one-cylinder-align-issue/15160850 # 15160850 – jdregister

+0

Это дубликат http://stackoverflow.com/questions/9038465/three-js-object3d-rotation-to-align -to-a-vector/31987883 # 31987883 – peterjwest

ответ

7

У меня была точно такая же проблема - в WebGL ширина линии всегда 1. Так вот функция, которую я написал, что будет принимать два объекта VEctor3 и произвести цилиндр сетки:

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; 
} 
+1

Это должны быть '.subVectors (pointY, pointX)' и '.addVectors (pointX, direction.multiplyScalar (0.5))' – mrdoob

+0

Изменено - спасибо за указание! –

+0

Кажется, не имеет никакого эффекта. Думаю, я допустил ошибку. Появляется векторная строка, но нет цилиндра и ошибок нет. Вот код, который я использовал: http://pastie.org/private/znr7wa4d4delrjifxbegq –

2

ArrowHelper начиная с pull request #3307 основаны на кватернионах.

Это работает в three.js R58:

var cylinderMesh = function(point1, point2, material) 
    { 
     var direction = new THREE.Vector3().subVectors(point2, point1); 
     var arrow = new THREE.ArrowHelper(direction.clone().normalize(), point1); 

     var rotation = new THREE.Vector3().setEulerFromQuaternion(arrow.quaternion); 

     var edgeGeometry = new THREE.CylinderGeometry(2, 2, direction.length(), 10, 4); 

     var edge = new THREE.Mesh(edgeGeometry, material); 
     edge.rotation = rotation.clone(); 
     edge.position = new THREE.Vector3().addVectors(point1, direction.multiplyScalar(0.5)); 

     return edge; 
    } 
+0

Спасибо за обновленный код! –

4

На самом деле не из других ответов работал для меня, но отдать я использовал код, который регулирует положение края и работает отлично.

Использование частей this answer и глядя на источник threejs я в конечном итоге к следующему

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; 
} 

Возможное улучшение является добавление edgeGeometry и материал в качестве параметров, так что кто-то может повторно использовать те же объекты, а не создавать новый в каждом звонке

+0

Работы от Oct 2017 - другие решения на этой странице устарели. – David

+0

Это не сработало для меня на r84. Я должен был сначала создать Matrix4, а затем установить на нем параметры. Пример: var m = new THREE.Matrix4(); m.set (1,0,0,0,0,0,1,0,0, -1,0,0,0,0,0,1); orientation.multiply (м); –

1

Я решил, что опубликую это, так как ответы не получили меня на 100%. Я заметил, что цилиндры были правильно ориентированы, но они были расположены относительно источника. Следующий код (по другим ответам на этот вопрос) работал на меня:

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(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; 
} 

Надеюсь, это поможет кому-то!

2

Остановился работает для меня в версии 70, но с этим обновлением он делает :)

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

Я могу подтвердить, что это также работает для r71 – ChrisRich

-1

я обнаружил, что только одна точка может быть согласована, так что я изменить его (изменить к точке х заостренный), как показано ниже, и он работает

edge.position = new 
THREE.Vector3().addVectors(pointY,direction.multiplyScalar(0.5)); 
1

Для поворота ориентации, вы можете использовать

edge.rotateX(Math.PI/2); 

Или

edge.rotateY(Math.PI/2); 

Или

edge.rotateZ(Math.PI/2); 

По координатам, которые вы хотите повернуть. Следовательно, код, указанный выше, с:

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)); 

Не требуется.

Смежные вопросы