math - superficies - superponer graficas en matlab
Procesamiento de gráficos en 3D: cómo calcular la matriz de modelos (2)
Esta respuesta es probablemente mucho más larga de lo que necesita ser. Vaya al final de los 2 párrafos más o menos si ya entiende la mayoría de las matemáticas matriciales.
Puede ser más fácil comenzar mirando un problema de una dimensión. En 1D, tenemos puntos en una línea. Podemos escalarlos o podemos traducirlos. Considere tres puntos i, j, k y la matriz de transformación M.
M = [ s t ]
[ 0 1 ]
i = [1] j = [-2] k = [0]
[1] [ 1] [1]
j k i
─┴──┴──┴──┴──┴─
-2 -1 0 1 2
Cuando multiplicamos por M , obtenemos:
i'' = Mi = [ s t ][ 1] = [ s+t ]
[ 0 1 ][ 1] [ 1 ]
j'' = Mj = [ s t ][-2] = [-2s+t]
[ 0 1 ][ 1] [ 1 ]
k'' = Mk = [ s t ][ 0] = [ t ]
[ 0 1 ][ 1] [ 1 ]
Entonces, si asignamos valores a s y t , entonces obtenemos varias transformaciones en nuestro 1D ''triángulo''. La escala cambia la distancia entre los "puntos", mientras que la traducción pura los mueve con respecto al origen manteniendo el espacio constante:
s=1 t=0 s=2 t=1 s=1 t=2
j k i j k i j k i
─┴──┴──┴──┴──┴─ ─┴──┴──┴──┴──┴─ ─┴──┴──┴──┴──┴─
-2 -1 0 1 2 -3 -1 1 3 5 0 1 2 3 4
Es importante notar que el orden de las transformaciones es crítico. Estas transformaciones 1D se escalan y luego se traducen. Si fueras a traducir primero, entonces el ''punto'' estaría a una distancia diferente del origen y, por lo tanto, el factor de escala lo afectaría de manera diferente. Por esta razón, las transformaciones a menudo se mantienen en matrices separadas para que el orden sea claro.
Si pasamos a 2D, obtenemos la matriz N :
[1 0 tx][ cos(a) sin(a) 0][sx 0 0] [ sx*cos(a) sx*sin(a) tx ]
N =[0 1 ty][-sin(a) cos(a) 0][ 0 sy 0]=[-sy*sin(a) sy*cos(a) ty ]
[0 0 1 ][ 0 0 1][ 0 0 1] [ 0 0 1 ]
Esta matriz: 1) escalará un punto mediante sx, sy , 2) rotará el punto alrededor del origen en grados, y luego 3 trasladará el punto por tx, ty . Tenga en cuenta que esta matriz se construye bajo la suposición de que los puntos se representan como vectores de columna y que la multiplicación tendrá lugar como Np . Como dijo el hombre de las tinieblas, si quieres usar una representación vectorial de puntos de fila pero aplicar la misma transformación, puedes transponer todo e intercambiar el orden. Esta es una propiedad general de la multiplicación de matrices: (AB) ^ T = (B ^ T) (A ^ T) .
Dicho esto, podemos hablar de transformaciones en términos de coordenadas de objeto, mundo y ojo. Si el ojo está sentado en el origen del mundo, mirando hacia abajo el eje z negativo del mundo, con + x hacia la derecha y + y hacia arriba y el objeto, un cubo, está sentado 10 unidades hacia abajo -z (centrado en la z eje), con un ancho de 2 a lo largo de la x del mundo, una profundidad de 3 a lo largo de la z y una altura de 4 a lo largo del mundo y. Luego, si el centro del cubo es el marco de referencia local del objeto y sus ejes locales se alinean convenientemente con los ejes del mundo. Entonces los vértices del cuadro en las coordenadas del objeto son las variaciones en [+/-1,+/-2,+/-1.5]^T
El vértice cercano, superior, derecho (desde el punto de vista del ojo) tiene coordenadas del objeto [1,2,1.5]^T
, en coordenadas mundiales , el mismo vértice es [1,2,-8.5]^T
(1.5 -10 = -8.5). Debido a dónde está el ojo, hacia dónde apunta, y el hecho de que definimos nuestro ojo de la misma manera que OpenGL, ese vértice tiene las mismas coordenadas oculares que las coordenadas del mundo . Así que vamos a mover y rotar el ojo de manera que la x del ojo esté derecha (rt) y la y del ojo esté arriba y el ojo -z se vea (lk) y el ojo esté posicionado en [eyeright(ex) eyeup(ey) eyelook(ez)]^T
Como queremos que las coordenadas de los objetos se transformen en coordenadas oculares (lo que significa que trataremos al ojo como el origen), tomaremos el inverso de estas transformaciones y las aplicaremos a los vértices de los objetos (después de que se hayan transformado en coordenadas mundiales). Entonces tendremos:
ep = [WORLD_TO_EYE]*[OBJECT_TO_WORLD]*wp;
Más específicamente, para nuestro vértice de interés, tendremos:
[ rt.x rt.y rt.z 0][1 0 0 -ex][1 0 0 0 ][ 1 ]
[ up.x up.y up.z 0][0 1 0 -ey][0 1 0 0 ][ 2 ]
[-lk.x -lk.y -lk.z 0][0 0 1 -ez][0 0 1 -10][1.5]
[ 0 0 0 1][0 0 0 1 ][0 0 0 1 ][ 1 ]
Para mayor comodidad, he separado la traducción y la rotación del ojo lo afecta. En realidad, ahora que he escrito mucho, este puede ser el punto de confusión. La matriz que diste rotará y luego traducirá. Supuse que la traducción del ojo estaba en coordenadas mundiales. Pero como lo escribió en su pregunta, en realidad está realizando la traducción en coordenadas oculares. También he negado a lk porque hemos definido el ojo para mirar hacia abajo el eje z negativo, pero para hacer una matriz de rotación estándar, queremos usar valores positivos.
De todos modos, puedo seguir, pero tal vez esto ya responde tu pregunta.
Continuo:
Explicando lo anterior un poco más allá, separando la transformación del ojo en dos componentes también hace que sea mucho más fácil encontrar el inverso. Es fácil ver que si la traducción tx mueve el ojo a algún lugar en relación con los objetos en el mundo, podemos mantener las mismas posiciones relativas entre el ojo y los puntos en el mundo moviendo todo en el mundo por -tx y manteniendo el ojo fijo .
Del mismo modo, considere la orientación del ojo como se define por sus vectores predeterminados de derecha , arriba y de aspecto :
[1] [0] [ 0]
d_rt=[0] d_up=[1] d_lk=[ 0]
[0] [0] [-1]
Crear una matriz de rotación que apunte a estos tres vectores en una nueva dirección es fácil. Simplemente alineamos nuestros tres nuevos ejes rt , up , lk (como vectores de columna):
[rt.x up.x -lk.x 0]
[rt.y up.y -lk.y 0]
[rt.z up.z -lk.z 0]
[ 0 0 0 1]
Es fácil ver que si aumentas d_rt, d_up y d_lk y multiplicas por la matriz anterior, obtienes la rt , la altura y la lk, respectivamente. Entonces aplicamos la transformación que queríamos. Para ser una rotación adecuada, los tres vectores deben ser ortonormales. Esto es realmente solo un cambio de bases. Debido a ese hecho, podemos encontrar el inverso de esta matriz de manera bastante conveniente al tomar su transposición. Eso es lo que hice arriba. Si aplica esa matriz transpuesta a todos los puntos en las coordenadas mundiales y deja la mirada inmóvil, los puntos mantendrán la misma posición, en relación con el ojo, como si el ojo hubiera girado.
Por ejemplo:
Asignar (en coordenadas mundiales):
[ 0] [0] [-1] [-2] [1.5]
rt=[ 0] up=[1] lk=[ 0] eye=[ 0] obj=[ 0 ]
[-1] [0] [ 0] [ 1] [-3 ]
Tengo problemas para entender las matemáticas para convertir el espacio de objetos para ver el espacio. Estoy haciendo esto en hardware y tengo la matriz Atranspose a continuación:
ATranspose =
[rightx upx lookx 0]
[righty upy looky 0]
[rightz upz lookz 0]
[-eyeright -eyeup -eyelook 1]
Entonces para encontrar el punto que haríamos:
[x,y,z,1] = [x'',y'',z'',1]*ATranspose
xnew = xold*rightx + xold*righty + xold*rightz + xold*(-eyeright)
pero no estoy seguro de si esto es correcto.
También podría ser
[x,y,z,1]=atranspose*[x'',y'',z'',1]T
¿Alguien puede explicarme esto? No puedo encontrar nada en línea sobre eso que no esté directamente relacionado con código abierto. Solo quiero entender la matemática detrás de la transformación de los puntos de las coordenadas del objeto a las coordenadas del ojo.
Si transpone ATranspose en la segunda variante, es decir
[x,y,z,w]^T = ATranspose^T * [x'',y'',z'',w'']^T
Por cierto, ^T
significa transponer por lo que el autor original probablemente quiso decir
[x,y,z,w] = [x'',y'',z'',w''] * A^T
y reescrito
[x,y,z,w]^T = A^T * [x'',y'',z'',w'']^T
entonces todas estas formulaciones son igualmente correctas.