(stackoverflow的新手,webgl / three.js的新手,......)
我正在使用three.js r54来绘制力导向图。节点之间的边缘是THREE.Lines,很好,但是用raycaster不能选择线条。所以我的目标是采用圆柱代替(或连同)线(也因为我可以做更多的东西:使用纹理,......)
这就是我要放置气缸的方法:
// init reference vector
var upVec = new THREE.Vector3(0,1,0);
//---withhin a loop---
// get direction
var direction = startPoint.subSelf(endPoint).clone();
// half length for cylinder height
var halfLength = direction.length() * 0.5;
// get offset
var offset = endPoint.clone().addSelf(direction.clone().multiplyScalar(0.5));
// normalize direc
direction.normalize();
//newUpVec = upVec - (upVec *(dot) direction) * direction - projection of direction
var newUpVec = upVec.clone().subSelf(direction.clone().multiplyScalar(upVec.dot(direction.clone()))).normalize();
var right = newUpVec.clone().crossSelf(direction.clone());
//build rotation matrix
var rot = new THREE.Matrix4(right.x, right.y, right.z, 0,
newUpVec.x, newUpVec.y, newUpVec.z, 0,
direction.x, direction.y, direction.z,0,
0,0,0,1);
//build translation matrix
var transla = new THREE.Matrix4(1, 0, 0, offset.x,
0, 1, 0, offset.y,
0, 0, 1, offset.z,
0, 0, 0, 1);
//build transformation matrix
var transfo = new THREE.Matrix4().multiply(transla, rot);
// create geometry
var cylgeo = new THREE.CylinderGeometry(2, 2, halfLength * 2, 12, 1, false);
cylgeo.applyMatrix(transfo);
var cylMesh = new THREE.Mesh(cylgeo, new THREE.MeshLambertMaterial({color:0x000000,
wireframe: true, shading: THREE.FlatShading}));
(描述于:http://www.fastgraph.com/makegames/3drotation/ )
因此,气缸放置在右侧偏移处并以某种方式对齐,但不是与边缘的两个点(起点,终点)对齐。
任何建议将不胜感激!
答案 0 :(得分:5)
使用: object3d-rotation-to-align-to-a-vector
给出2个Vector3和一个场景:
function drawCylinder(vstart, vend,scene){
var HALF_PI = +Math.PI * .5;
var distance = vstart.distanceTo(vend);
var position = vend.clone().addSelf(vstart).divideScalar(2);
var material = new THREE.MeshLambertMaterial({color:0x0000ff});
var cylinder = new THREE.CylinderGeometry(10,10,distance,10,10,false);
var orientation = new THREE.Matrix4();//a new orientation matrix to offset pivot
var offsetRotation = new THREE.Matrix4();//a matrix to fix pivot rotation
var offsetPosition = new THREE.Matrix4();//a matrix to fix pivot position
orientation.lookAt(vstart,vend,new THREE.Vector3(0,1,0));//look at destination
offsetRotation.rotateX(HALF_PI);//rotate 90 degs on X
orientation.multiplySelf(offsetRotation);//combine orientation with rotation transformations
cylinder.applyMatrix(orientation)
var mesh = new THREE.Mesh(cylinder,material);
mesh.position=position;
scene.add(mesh);
}
r58 +代码:
function drawCylinder(vstart, vend,scene){
var HALF_PI = Math.PI * .5;
var distance = vstart.distanceTo(vend);
var position = vend.clone().add(vstart).divideScalar(2);
var material = new THREE.MeshLambertMaterial({color:0x0000ff});
var cylinder = new THREE.CylinderGeometry(10,10,distance,10,10,false);
var orientation = new THREE.Matrix4();//a new orientation matrix to offset pivot
var offsetRotation = new THREE.Matrix4();//a matrix to fix pivot rotation
var offsetPosition = new THREE.Matrix4();//a matrix to fix pivot position
orientation.lookAt(vstart,vend,new THREE.Vector3(0,1,0));//look at destination
offsetRotation.makeRotationX(HALF_PI);//rotate 90 degs on X
orientation.multiply(offsetRotation);//combine orientation with rotation transformations
cylinder.applyMatrix(orientation)
var mesh = new THREE.Mesh(cylinder,material);
mesh.position=position;
scene.add(mesh);
}
答案 1 :(得分:0)
@ jdregister的回答在R77中对我来说并不合适,因为气缸最终以vstart的中心结束(旋转,看起来还不错)。
对R58 +答案的倒数第二行的这种修改起到了作用:
mesh.position.set(position.x, position.y, position.z);
答案 2 :(得分:0)
在R87中,“vend.clone()。add(vstart).divideScalar(2);”不工作
您可以像这样定位项目
mesh.position.copy(start);
mesh.position.lerp(end, 0.5);
R58的所有其他人都很好:)
答案 3 :(得分:0)
这里有一个非常简洁的答案:https://stackoverflow.com/a/44346439/1556416
我在这里解释一下:
function drawCylinder(vstart, vend, radius){
var cylLength = new THREE.Vector3().subVectors(vend, vstart).length();
var cylGeom = new THREE.CylinderGeometry(radius, radius, cylLength, 16);
cylGeom.translate(0, cylLength / 2, 0);
cylGeom.rotateX(Math.PI / 2);
var material = new THREE.MeshLambertMaterial({color: "blue"})
var cyl = new THREE.Mesh(cylGeom, material);
cyl.position.copy(vstart);
cyl.lookAt(vend); // and do the trick with orienation
return cyl
}