2010-09-28 27 views
13

Sé que la rotación 3D está bien documentada en SO y en muchos otros sitios, pero a pesar de leer innumerables explicaciones, todavía no he descubierto dónde me estoy equivocando. Mi formación es en arte y diseño, no en matemática y programación, y nunca estoy realmente seguro de si mi ángulo de ataque (sin juego de palabras) es el correcto. En lugar de pegar un mosaico de mi lóbrego código, incluyo una imagen que describe mi problema. Lo que realmente me gustaría es un desglose pormenorizado paso a paso de cómo resolverlo. El seudocódigo es útil, pero aprenderé más si alguien me apunta en la dirección correcta o señala los peligros comunes.Giro 3D con eje & ángulo


alt text

Rojo = eje X, Verde = eje-y, Azul = Z-Axis

Magenta vectores = origen -> algunos X, Y, Z punto

cubo magenta = promedio de los puntos finales de los dos vectores magenta (¿hay un mejor nombre para esto?)

Blanco vector = producto cruzado de los dos vectores magenta (extendido para displ ay, vector real es normalizada)

Cyan cubo de objeto = rotación fallan


He usado previamente Away3D y Papervision; en estas bibliotecas, la aplicación de ángulos de Euler a las propiedades de rotaciónX, rotaciónY o rotaciónZ de un objeto rotará el objeto localmente, como si estuviera en el origen, independientemente de su posición real. Con Three.js, este no es el caso. La modificación de las propiedades rotation.x y rotation.y de un objeto produce un efecto extraño donde el objeto aparentemente se inclina un poco en el eje Z. Aún más confuso es que esto sucede cuando el objeto descansa en el origen. Pensé que quizás usar Quaternion -> Matrix o Axis/Angle -> funciones de Matrix resolvería mi problema, pero no los dados. Parece que hay un concepto central que no estoy obteniendo.

De todos modos, lo que quiero hacer es orientar el cubo al vector de producto cruzado (blanco), de modo que la parte superior del cubo esté orientada en ese sentido. Entonces me gustaría rotar el cubo a lo largo del mismo eje. La imagen que adjunté muestra el resultado de más horas de las que me gustaría admitir tratando de lograr este resultado. Mi código vagamente se parece a esto:

axis = Vector3.cross(a, b) 
axis.normalize() 
angle = 45 * TO_RADIANS; 
quat = AxisAngle2Quaternion(axis, angle) 
rot = Quaternion2Matrix(quat) 
cube.matrix = rot 

Gracias de antemano,

Casey


Edición: A partir de una recompensa

Tal vez estoy mal entendido cómo se supone que esto trabajo. Aquí está otra imagen:

alt text

Am I incorrecta en el pensamiento de que este vector magenta es el eje, y las flechas de color naranja indican la rotación alrededor de este eje en función del ángulo? De una forma u otra, quiero orientar el cubo cian en función de un vector direccional y girarlo. ¿¡Qué estoy haciendo mal!?

+0

Nadie reacciona, pero en realidad creo que tu pregunta es una de los mejores formulados que vi aquí hasta ahora. Tal vez nadie lo sabe? También me gustaría ver una respuesta aquí. – erikbwork

+0

Tal vez se están alejando del aspecto Three.js ... Esperaba que esto fuera un problema bastante básico – Casey

+0

Pude acercarme con el método "Utils3D.pointTowards()" en Flash: http: // help. adobe.com/en_US/AS3LCR/Flash_10.0/flash/geom/Utils3D.html Pero no sé cómo aplicar la rotación sobre el eje y no puedo encontrar ninguna función comparable OSS – Casey

Respuesta

4

Su enfoque suena correcto pero no muestra qué son los vectores a, b y el ángulo constante, supongo, solo para probar. Hice esto antes, así Desenterré mi código y esta es la matemática que encontré ...

dado:
originalVec = vector unitario que apunta hacia arriba el eje Y (dirección de la parte superior del cubo/normal)
targetVec = vector

Ahora desea el eje y el ángulo que rotará originalVec para alinearse con targetVec. El eje de rotación más directo es perpendicular a ambos vectores de entrada, así que tome su producto cruzado. Ese eje no es un vector unitario así que también normalícelo. El ángulo para rotar (en radianes) es el coseno inverso del producto de puntos.

axis = Vector3.cross(originalVec, targetVec) 
axis.normalise 
angle = inversecos(Vector3.dot(originalVec, targetVec)) 

quat = AxisAngle2Quaternion(axis, angle) 
rot = Quaternion2Matrix(quat) 
cube.matrix = rot 

En lugar de reemplazar la matriz del cubo Creo que se quiere componer con el nuevo transformar ...

cube.matrix.multiplyBy(rot) 

... pero no estoy 100% seguro de eso. Además, he visto implementaciones donde AxisAngle2Quaternion toma un ángulo en grados. Cuando los vectores de entrada son paralelos u opuestos, el eje es < 0,0,0>, por lo que debe probarse. Si el cubo gira en sentido contrario, los parámetros del vector de productos cruzados están en el orden incorrecto, nunca recuerdo cuál y solo pruebo ambos. hth.

Editar
que he tenido la oportunidad de jugar con Three.js y cortado uno de los ejemplos para orientar un cubo. Los comentarios muestran dónde agregué las cosas y todas las matemáticas de orientación ocurren en alignCube().
Align and Spin example
Mover hacia arriba/abajo mueve la línea de destino. Mover giros a la izquierda/derecha en la línea.

Los objetos de escena en Three.js parecen todos heredar de Object3D que tiene una propiedad autoUpdateMatrix establecida verdadera de forma predeterminada. Esto necesita establecerse como falso; de lo contrario, se llama a la función updateMatrix, que vuelve a calcular la matriz desde la posición de los objetos, las propiedades de escala y rotación. Alternativamente, podría asignar una función updateMatrix diferente.

Sería bueno si Tres.js tenían algún tipo de documentación :)

+0

Gracias - es bueno saber que estoy en el camino correcto. Lamentablemente, no lo he hecho funcionar. Estoy reemplazando la matriz del cubo porque estoy tratando de simplificar las cosas por ahora y hacer que esto funcione en el origen. ¿Está bien o solo está presentando problemas? – Casey

+0

¡Este ejemplo es asombroso! No tengo tiempo para hacerlo bien en este momento, pero sospecho que recibirás la recompensa :) ¡Gracias! – Casey

+0

Eso funciona, dulce. No entendí cómo funcionan las matrices de eje/ángulo. Intentaba hacerlo todo con una sola matriz. Estoy publicando la función de alineación a continuación para cualquier persona que esté interesada. – Casey

0

Como nadie tiene una solución realmente buena, al menos puedo aconsejarle sobre cómo acercarse.

Hay 3 posibles problemas y usted tiene uno de ellos:

  1. La matemática no es correcto, o que no lo entienden. (No debería haber tanto problema aquí)
  2. Puntos flotantes Los aritméticos son siempre un problema para las computadoras (tampoco debería ser un problema, porque es bastante básico. Si su marco no puede ofrecer una solución, entonces el marco tiene ningún valor para la programación 3d)
  3. Usted no utiliza el marco adecuado

Debido a que es muy probable que en el número 3 es el caso, trate de encontrar una lista de correo o foro de soporte o lo que sea para el marco y hablar con la gente de allí. Deberían poder explicarte lo que haces mal con su marco. ¡Entonces regresa y publica la solución aquí!

+0

Gracias por la sugerencia: me he puesto en contacto con el autor del framework y voy a ver si un código similar arroja un resultado similar en Away3D – Casey

+0

claramente estoy haciendo algo mal, no puedo hacer que funcione en Flash tampoco . – Casey

+0

¡Mira el enlace de ejemplo de Trochoid, funciona bien! – Casey

3

del ejemplo de trocoidal, aquí está la función que utilizo para lograr la alineación y el giro de la segunda imagen:

//object, normalized direction vector, rotation in radians 
function align(target, dir, rot) { 
    //Three.js uses a Y up coordinate system, so the cube inits with this vector 
    var up = new THREE.Vector3(0, 1, 0); 

    //euler angle between direction vector and up vector 
    var angle = Math.acos(up.dot(dir)); 

    //cross product of the up vector and direction vector 
    var axis = new THREE.Vector3(); 
    axis.cross(up, dir); 
    axis.normalize(); 

    //rotation to aligns the target with the direction vector 
    var rotate = THREE.Matrix4.rotationAxisAngleMatrix(axis, angle); 

    //rotation around direction vector 
    var revolve = THREE.Matrix4.rotationAxisAngleMatrix(dir, rot); 

    //compose the rotations (order matters, can be done other ways) 
    revolve.multiplySelf(rotate); 

    //assign matrix (autoUpdateMatrix = false) 
    target.matrix = revolve; 
} 
+0

¡Estoy feliz de que hayas encontrado la manera de hacerlo funcionar! – erikbwork