Desrote un polígono cuadrado con Python: los 3 ejes
Tengo un polígono cuadrado girado. Y quiero 'desrotarlo' para que sus ejes normales coincidan con los ejes del mundo.
Puedo anular la rotación en el eje Z usando la cara normal y la diferencia de rotación (no me importa la traslación en este punto):
quaternion = Vector((0,0,1)).rotation_difference(face_normal)
rotation = ( +quaternion ).to_matrix().inverted()
obj.matrix_world = rotation.to_4x4()
Pero por el amor de Dios, no puedo averiguar cómo agregar también la rotación de caras X e Y a la mezcla.
Resultado deseado:
Respuestas
Usa los bordes.
El módulo bmesh tiene algunos métodos para que las caras calculen el vector tangente de la cara en función de sus bordes. Por ejemplo, sake utilizará el vector tangente creado a partir de dos aristas no conectadas más largas.
Usando la cara normal, la cara tangente y el producto cruzado de los dos pueden crear una matriz de rotación a partir de los tres vectores ortogonales.
Los ejes son las columnas de una matriz, por lo que una matriz de rotación con ejes vectoriales unitarios x, y, and zpodría ser
Matrix((x, y, z)).transposed()
si recuerda del álgebra lineal, la transposición de una matriz ortogonal también es su inversa.
Prueba de guión, alinea la cara cero según la matriz creada como arriba.
import bpy
import bmesh
from mathutils import Matrix, Quaternion
ob = bpy.context.object
me = ob.data
bm = bmesh.from_edit_mesh(me)
face = bm.faces[0]
n = face.normal
t = face.calc_tangent_edge_pair().normalized()
c = face.calc_center_median()
M = (
Matrix.Translation(c) @
Matrix((t.cross(n).normalized(), t, n)).to_4x4() @
Matrix.Translation(-c)
)
bmesh.ops.transform(
bm,
matrix=M,
verts=bm.verts,
)
bmesh.update_edit_mesh(me)