在旋转面上构建几何体
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()
)
我在 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()
)