1

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...

  1. The vertex locations are still coming through as local, even when multiplied with the matrix world?
  2. Non-uniform scale messes up the face rotation matrix (tried to avoid this by applying the bmesh but that also messes the rotation matrix)
  3. 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)

Dan
  • 951
  • 6
  • 21
  • Related https://blender.stackexchange.com/a/203355/15543 – batFINGER Sep 17 '21 at 19:22
  • Thanks, I’m studying through it… when you create the matrix using 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:51
  • @batFINGER (meant to tag you in that previous comment)... I've been thinking through it more and will do some testing. I think I understand now that the applying the rotation_difference when creating the matrix basically resets the rotation. – Dan Sep 20 '21 at 00:15
  • Mapping to a space where tri lies in the $XY$ plane, where the normal is $Z$ axis – batFINGER Sep 20 '21 at 10:15
  • Feel this is going a bit XY Problem Added an answer to one of your prior questions re using the instancer to get a "consistently" calculated face normal. – batFINGER Sep 25 '21 at 06:04
  • Haha, yes I see your point, thanks again @batFINGER, I’ll have a look asap! In this case it’s me learning more efficient ways of solving a problem over time… this question/method will essentially solve a bunch of things I was doing in separate stages previously. Tricky thing to know what to ask when learning, getting there slowly but trying to do a lot more testing before asking now. – Dan Sep 25 '21 at 11:49

0 Answers0