I'm trying to obtain the selected face vertex locations for an animated Object as x,y co-ordinates relative to f.calc_center_median() as the origin center [0,0] (assuming a planar face). The way I've approached it at the moment is by moving the origin point to the face center and rotating according to the face, but I'm running into a number of issues...
- The vertex locations are still coming through as local, even when multiplied with the matrix world?
- Non-uniform scale messes up the face rotation matrix (tried to avoid this by applying the bmesh but that also messes the rotation matrix)
- For an 'even edged' face (eg. a cube face) I can't work out how to avoid the x,y rotation from flipping randomly over the duration of the animation?
Any suggestions on fixes, or alternative ways to approach this? This is what I have so far (in the final function I don't want the object to actually move, just moving for testing)...
import bpy
import bmesh
import mathutils
ob = bpy.context.edit_object
frame_start = bpy.context.scene.frame_start
frame_end = bpy.context.scene.frame_end
ob_faces = {}
for fr in range(frame_start,frame_end):
bpy.context.scene.frame_set(fr)
mw = ob.matrix_world
me = ob.data
bm = bmesh.new()
dg = bpy.context.evaluated_depsgraph_get()
bm.from_object(ob, dg)
bm.transform(mw)
bm.normal_update()
# bm = bmesh.from_edit_mesh(me)
selverts = [v.co for v in bm.verts if v.select]
if len(selverts):
pt = sum(selverts, mathutils.Vector()) / len(selverts)
#T = Matrix.Translation(-pt)
bmesh.ops.translate(bm, vec=-pt, verts=bm.verts)
# mw.translation = mw @ pt
mw.translation = [0,0,0]
for f in bm.faces:
if not f.select:
continue
n = f.normal
t = f.calc_tangent_edge_pair().normalized()
bt = n.cross(t).normalized()
M = mathutils.Matrix([t, bt, n]).transposed().to_4x4()
M.translation = f.calc_center_median()
ob.rotation_euler = M.inverted().to_euler()
bmesh.update_edit_mesh(me)
new_w = ob.matrix_world
for v in f.verts:
key = "face_" + str(f.index)
print (mw @ v.co)
ob_faces[key] = ob_faces.get(key, []) + [new_w @ v.co]
# ob_faces[key].append(mw @ v.co)
print("\n", ob_faces)
rotation_difference(up)is that essentially the 2D projection point… setting the face back to flat with normal (0,0,1)? – Dan Sep 18 '21 at 00:51rotation_differencewhen creating the matrix basically resets the rotation. – Dan Sep 20 '21 at 00:15