Blender Python开发:如何在指定Vector上创建正交正方形并输出顶点
Python(Blender)开发:创建与指定Vector正交的正方形
嘿,我来帮你搞定这个问题!你想要在指定Vector上方生成一个和它正交的正方形,但目前代码里的正方形始终和世界xy轴平行,根本没贴合目标Vector的朝向——问题出在你固定使用了世界空间的x、y轴方向来计算顶点,完全没考虑给定Vector的方向。
先看看你当前的代码:
def create_verts_around_point(radius, vert): # given Vector vec = np.array([vert[0], vert[1], vert[2]]) # side_length of square side_length = radius # Vctor x-direction (1,0,0) x_vec = np.array([1,0,0]) # Vekctor y-direction (0,1,0) y_vec = np.array([0,1,0]) # Vector z-direction (0,0,1) z_vec = np.array([0,0,1]) p1 = vec + (side_length/2) * x_vec + (side_length/2) * y_vec + (side_length/2) * z_vec p2 = vec - (side_length/2) * x_vec + (side_length/2) * y_vec + (side_length/2) * z_vec p3 = vec - (side_length/2) * x_vec - (side_length/2) * y_vec + (side_length/2) * z_vec p4 = vec + (side_length/2) * x_vec - (side_length/2) * y_vec + (side_length/2) * z_vec
你这里用x_vec和y_vec作为正方形的边方向,不管给定的vec朝向哪里,生成的正方形都会和世界xy平面平行,自然达不到和vec正交的效果。
解决思路
要生成和指定Vector正交的正方形,核心是得到两个互相垂直且都垂直于目标Vector的方向向量,用这两个方向作为正方形的边。具体步骤:
- 先把目标Vector归一化,确保它是单位长度的法向量;
- 通过叉乘生成第一个垂直于法向量的方向(找一个和法向量不共线的向量来叉乘,比如优先用z轴,不行就用x轴);
- 再用叉乘生成第二个垂直于法向量和第一个方向的向量;
- 用这两个方向向量计算正方形的四个顶点。
修改后的可运行代码
import bpy import numpy as np def create_verts_around_point(radius, vert): # 转换给定的Vector为numpy数组,确保浮点类型 vec = np.array(vert, dtype=np.float64) # 归一化目标Vector,避免长度影响方向计算(如果向量为零则默认用z轴) vec_norm = vec / np.linalg.norm(vec) if np.linalg.norm(vec) > 1e-6 else np.array([0, 0, 1]) side_length = radius half_side = side_length / 2 # 生成第一个垂直于目标Vector的方向向量 # 优先和z轴叉乘,若目标Vector是z轴则和x轴叉乘 if not np.allclose(vec_norm, [0,0,1]) and not np.allclose(vec_norm, [0,0,-1]): ortho1 = np.cross(vec_norm, [0, 0, 1]) else: ortho1 = np.cross(vec_norm, [1, 0, 0]) # 归一化第一个正交方向 ortho1_norm = ortho1 / np.linalg.norm(ortho1) # 生成第二个正交方向(同时垂直于目标Vector和ortho1) ortho2 = np.cross(vec_norm, ortho1_norm) ortho2_norm = ortho2 / np.linalg.norm(ortho2) # 计算正方形的四个顶点 p1 = vec + half_side * ortho1_norm + half_side * ortho2_norm p2 = vec - half_side * ortho1_norm + half_side * ortho2_norm p3 = vec - half_side * ortho1_norm - half_side * ortho2_norm p4 = vec + half_side * ortho1_norm - half_side * ortho2_norm # 打印顶点到控制台 print("顶点A:", p1) print("顶点B:", p2) print("顶点C:", p3) print("顶点D:", p4) # 可选:在Blender场景中创建可视化的正方形网格 mesh = bpy.data.meshes.new("OrthogonalSquare") obj = bpy.data.objects.new("OrthogonalSquare", mesh) bpy.context.collection.objects.link(obj) vertices = [tuple(p1), tuple(p2), tuple(p3), tuple(p4)] edges = [(0,1), (1,2), (2,3), (3,0)] faces = [(0,1,2,3)] mesh.from_pydata(vertices, edges, faces) mesh.update() return p1, p2, p3, p4 # 测试调用:比如传入一个朝向(1,1,1)的Vector,边长为2 create_verts_around_point(2, (1, 1, 1))
关键说明
- 归一化处理:确保目标Vector的长度不会影响方向计算,避免出现奇怪的偏移;
- 正交向量生成:通过叉乘得到的两个方向,保证了正方形平面完全垂直于目标Vector;
- Blender可视化:代码里附带了创建网格的逻辑,运行后你能直接在Blender里看到生成的正方形效果;
- 顶点打印:控制台会输出四个顶点的坐标,满足你打印顶点的需求。
内容的提问来源于stack exchange,提问作者Luca Moser
相关产品推荐
相关产品推荐

