在旋转面上构建几何体

Build geometry on a rotated face

我在 Blender 中编写了一个非常基本的脚本,它构建了一组圆形顶点,然后旋转并将它们转换为 3D 中的旋转面 space(请参见下面的代码)。这适用于任何 Z 旋转,但是对于 X 或 Y 旋转,它无处不在。

我知道我在某处遗漏了一步,但目前看不到。所以非常感谢任何帮助。

对于运行代码,场景中只需要有一个立方体。

我的想法是在 (0,0,0) 处构建顶点圆,然后将它们旋转到所需的面法线(我现在随机选择了立方体的面 2),然后我平移顶点到人脸的位置。主要旋转函数在代码底部(rotate_verts_towards_face(..))

注意。这是一个更大项目的一部分,所以我将其编写为一个单独的脚本,仅作为演示,所以它是粗略的代码。

(当前代码的结果)

Face rotation at 0 degrees Z axis

Face rotation at 45 degrees Z axis

Face rotated at 45 degrees X axis

import bpy
import bmesh
import math
from mathutils import Vector


verts_norm = Vector((0, 0, 1))
verts_center = Vector((0, 0, 0))

# FACE BUILDING
def build_face_verts():
    theta = 2 * math.pi / 12
    dx = 0
    dy = 0
    dz = 0
    verts = []
    for i in range(12):
        dx = 1 * math.sin(theta * i)
        dy = 1 * math.cos(theta * i)
        verts.append(Vector((dx, dy, dz)))
    return verts


def update_bm_verts(bm):
    bm.verts.index_update()
    bm.verts.ensure_lookup_table()

def setup_new_obj(name, context):
    obj_name = name
    mesh = bpy.data.meshes.new("mesh")
    obj = bpy.data.objects.new(obj_name, mesh)
    context.scene.collection.objects.link(obj)
    context.view_layer.objects.active = obj
    obj.select_set(True)
    mesh = context.object.data
    bm = bmesh.new()
    return obj, mesh, bm


def build_face(verts, context):
    obj, mesh, bm = setup_new_obj("NEW_FACE", context)

    for v in verts:
        bm.verts.new(v)
    update_bm_verts(bm)

    bm.to_mesh(mesh)
    bm.free()

# ROTATE AND TRANSLATE
def translate(pt, verts):
    for v in verts:
        v[0] += pt[0]
        v[1] += pt[1]
        v[2] += pt[2]


def rotate_verts_towards_face(verts, target, target_norm, target_loc):
    mat_world = target.matrix_world
    trans_verts = []
    
    # transform face verts to target object space
    trans_verts = [mat_world @ v for v in verts] 
    
    # build rotation matrix
    mat = (
        verts_norm.rotation_difference(target_norm).to_matrix().to_4x4()
        
    )

    return [mat @ v for v in trans_verts]


target_obj = bpy.data.objects["Cube"]
target_face_norm = target_obj.data.polygons[2].normal
mat_world = target_obj.matrix_world
target_face_norm = mat_world @ target_face_norm
target_location = target_obj.data.polygons[2].center
 
# rotate verts
r_verts = rotate_verts_towards_face(build_face_verts(), target_obj, target_face_norm, target_location)
# translate verts to face position
translate(target_face_norm, r_verts)
build_face(r_verts, bpy.context)

很抱歉回答我自己的问题,但我想通了。这是一个简单的修复,只涉及通过目标对象的矩阵世界翻译 verts_normal。旋转代码变为:

    norm = mat_world @ verts_norm
    
    # build rotation matrix
    mat = (
        norm.rotation_difference(target_norm).to_matrix().to_4x4()
        
    )