tutorial three texture sphere raycaster examples descargar javascript rotation three.js quaternions

javascript - texture - Rotación del cilindro de Object.d de Three.js para alinearse con un vector



three.js tutorial (3)

Desafortunadamente no he trabajado con Quaternions, así que no puedo ayudar mucho. Me parece que es necesaria cierta compensación, ya que el pivote del cilindro está en el centro de la malla, no en un extremo.

Si se juega con matrices un poco, y tengo resultados decentes.

Aquí hay una forma de hacerlo, utilizando el método lookAt () de 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 );

Esto debería dibujar un cilindro que comienza en p1, termina en p2 y está orientado hacia él. La compensación puede necesitar algunos ajustes, pero la geometría sigue la dirección del vector bastante cerca.

También existe la versión más larga de calcular manualmente las matrices, en lugar de confiar en la funcionalidad 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 );

Esto me parece más trabajo que usar quaternion, por lo que veo en tu código. Si el setFromEuler hace la magia para la orientación, la geometría de la malla aún podría necesitar moverse (pivotar desde un extremo en lugar de centrar)

HTH

He buscado por todas partes, pero parece que no puedo entender esta cosa bastante básica. He visto otros ejemplos en stackoverflow y en otros lugares hace un año o dos, pero no funcionan con la última versión de Three.js.

Aquí hay una versión de lo que estoy trabajando: http://medschoolgunners.com/sandbox/3d/ .

Intento que el cono gris se alinee exactamente con el vector rojo sin etiqueta. Es decir. Quiero que la punta del cono esté exactamente alineada con el vector y señale desde el origen en esa dirección.

Aquí está el código que tengo ahora:

//FUNCTION TO CREATE A CYLINDER function create_cylinder(radiusTop,radiusBottom, height, segmentsRadius, segmentsHeight, openEnded, color) { var material = new THREE.MeshLambertMaterial({ color: color, //0x0000ff opacity: 0.2 }); var cylinder = new THREE.Mesh(new THREE.CylinderGeometry(radiusTop,radiusBottom, height, segmentsRadius, segmentsHeight, openEnded), material); cylinder.overdraw = true; return cylinder; } //ALIGN THE CYLINDER TO A GIVEN VECTOR var alignVector=new THREE.Vector3(-50,50,50); //the vector to be aligned with var newcylinder = create_cylinder(0.1, 10, 40, 50, 50, false, "0x0ff0f0"); // the object to be aligned with the vector above var cylinderQuaternion = new THREE.Quaternion(); cylinderQuaternion.setFromEuler(alignVector); newcylinder.useQuaternion = true; newcylinder.quaternion=cylinderQuaternion; scatterPlot.add(newcylinder);


Sé que esta es una vieja pregunta, pero en caso de que alguien todavía se esté preguntando, lo que funcionó para mí fue agregar el vector a la posición de malla y usar lookAt para alinearlo con el vector:

//Mesh to align var material = new THREE.MeshLambertMaterial({color: 0x0000ff}); var cylinder = new THREE.Mesh(new THREE.CylinderGeometry(10, 10, 15), material); //vector to align to var vector = new THREE.Vector3( 5,//x 10,//y 15 //z ); //create a point to lookAt var focalPoint = new THREE.Vector3( cylinder.position.x + vector.x, cylinder.position.y + vector.y, cylinder.position.z + vector.z ); //all that remains is setting the up vector (if needed) and use lookAt cylinder.up = new THREE.Vector3(0,0,1);//Z axis up cylinder.lookAt(focalPoint);


Si tienes un vector arbitrario:

var vector = new THREE.Vector3(100, 60, 20);

Puede alinear un objeto, como un cilindro, con el vector así:

var geometry = new THREE.CylinderGeometry(2, 2, vector.length(), 4, 4); var mesh = new THREE.Mesh(geometry, someMaterial); var axis = new THREE.Vector3(0, 1, 0); mesh.quaternion.setFromUnitVectors(axis, vector.clone().normalize());

Donde axis es la dirección original del cilindro (apuntando hacia arriba).

También puede mover el cilindro para que coincida con la posición del vector de esta manera:

mesh.position.copy(vector.clone().multiplyScalar(0.5));

Esto pone un extremo del cilindro en el 0, 0, 0 y el otro en 100, 60, 20 , y funciona porque vector.length() longitud del cilindro a vector.length() .