Desfaça a rotação de um polígono quadrado com Python: todos os 3 eixos
Eu tenho um polígono quadrado girado. E eu quero 'cancelar a rotação' para que seus eixos normais coincidam com os eixos mundiais.
Consigo cancelar a rotação no eixo Z usando a diferença de rotação e normal da face (não me importo com a translação neste ponto):
quaternion = Vector((0,0,1)).rotation_difference(face_normal)
rotation = ( +quaternion ).to_matrix().inverted()
obj.matrix_world = rotation.to_4x4()
Mas, pelo amor de Deus, não consigo descobrir como adicionar rotação de face X e Y à mistura.
Resultado desejado:
Respostas
Use as bordas.
O módulo bmesh tem alguns métodos para faces para calcular o vetor tangente da face com base em suas arestas. Por exemplo, sake usará o vetor tangente criado a partir de duas arestas não conectadas mais longas.
Usando a normal da face, a tangente da face e o produto vetorial das duas podem criar uma matriz de rotação a partir dos três vetores ortogonais.
Os eixos são as colunas de uma matriz, portanto, uma matriz de rotação com eixos vetoriais unitários x, y, and zpode ser
Matrix((x, y, z)).transposed()
se você se lembra da álgebra linear, a transposição de uma matriz ortogonal também é sua inversa.
O script de teste alinha a face zero com base na matriz criada como acima.
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)