К сожалению, я не работал с кватернионами, поэтому ничего не могу поделать.Мне кажется, что необходимо некоторое смещение, поскольку шарнир цилиндра находится в центре сетки, а не на одном конце.
Если немного поиграть с матрицами, и я получу приличные результаты.
Вот один из способов, используя метод lookAt () Mesh:
var HALF_PI = -Math.PI * .5;
var p1 = new THREE.Vector3(Math.random()-.5,Math.random()-.5,Math.random()-.5).multiplyScalar(30);
var p2 = new THREE.Vector3(Math.random(),Math.random(),Math.random()).multiplyScalar(300);
var halfLength = diff.length() * .5;
var c = new THREE.CylinderGeometry(10, 10, halfLength * 2, 12, 1, false );
var orientation = new THREE.Matrix4();
orientation.setRotationFromEuler(new THREE.Vector3(HALF_PI,0,0));//rotate on X 90 degrees
orientation.setPosition(new THREE.Vector3(0,0,halfLength));//move half way on Z, since default pivot is at centre
c.applyMatrix(orientation);//apply transformation for geometry
var m = new THREE.Mesh( c, new THREE.MeshLambertMaterial( { color: 0x009900, wireframe: true, shading: THREE.FlatShading } ) );
scene.add(m);
m.lookAt(p2);//tell mesh to orient itself towards p2
//just for debugging - to illustrate orientation
m.add(new THREE.Axes());
//visualize p1,p2 vectors
var PI2 = Math.PI * 2;
var program = function ( context ) {
context.beginPath();
context.arc( 0, 0, 1, 0, PI2, true );
context.closePath();
context.fill();
}
particleMaterial = new THREE.ParticleCanvasMaterial( { color: 0x990000, program: program } );
var pp1 = new THREE.Particle( new THREE.ParticleCanvasMaterial( { color: 0x990000, program: program } ) );
pp1.scale.multiplyScalar(10);
pp1.position.copy(p1);
scene.add( pp1 );
var pp2 = new THREE.Particle( new THREE.ParticleCanvasMaterial( { color: 0x009900, program: program } ) );
pp2.scale.multiplyScalar(10);
pp2.position.copy(p2);
scene.add( pp2 );
Это должно нарисовать цилиндр, который начинается в p1, заканчивается в p2 и ориентирован на него.Смещение может потребовать некоторой настройки, но геометрия следует за векторным направлением довольно близко.
Существует также более длинная версия ручного вычисления матриц, в отличие от использования функции lookAt ():
plane.add(getCylinderBetweenPoints(p1,p2,new THREE.MeshLambertMaterial( { color: 0x009900, wireframe: true, shading: THREE.FlatShading } )));
function getCylinderBetweenPoints(point1,point2,material){
var HALF_PI = -Math.PI * .5;
var diff = new THREE.Vector3().sub(point1,point2);//delta vector
var halfLength = diff.length() * .5;
var c = new THREE.CylinderGeometry(10, 10, halfLength * 2, 12, 1, 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(point1,point2,new THREE.Vector3(0,1,0));//look at destination
offsetRotation.setRotationX(HALF_PI);//rotate 90 degs on X
offsetPosition.setPosition(new THREE.Vector3(-point1.x,diff.length()*.5+point1.z,point1.y*.5));//move by pivot offset on Y
orientation.multiplySelf(offsetRotation);//combine orientation with rotation transformations
orientation.multiplySelf(offsetPosition);//combine orientation with position transformations
c.applyMatrix(orientation);//apply the final matrix
var m = new THREE.Mesh( c, material );
m.add(new THREE.Axes());
return m;
}
var PI2 = Math.PI * 2;
var program = function ( context ) {
context.beginPath();
context.arc( 0, 0, 1, 0, PI2, true );
context.closePath();
context.fill();
}
//visualize p1,p2 vectors
particleMaterial = new THREE.ParticleCanvasMaterial( { color: 0x990000, program: program } );
var pp1 = new THREE.Particle( new THREE.ParticleCanvasMaterial( { color: 0x990000, program: program } ) );
pp1.scale.multiplyScalar(10);
pp1.position.copy(p1);
plane.add( pp1 );
var pp2 = new THREE.Particle( new THREE.ParticleCanvasMaterial( { color: 0x009900, program: program } ) );
pp2.scale.multiplyScalar(10);
pp2.position.copy(p2);
plane.add( pp2 );
Похоже, я больше работаю, чем использую кватернион, из того, что я вижу в вашем коде.Если setFromEuler использует магию для ориентации, геометрия сетки все еще может нуждаться в перемещении (поворот от одного конца, а не от центра)
HTH