Blender常用功能Python实现
本文介绍了Blender中网格创建与修改的Python脚本实现方法,主要包括:1)创建基础网格并设置材质;2)调整网格坐标和旋转;3)复制网格对象;4)添加UV贴图和顶点颜色属性;5)翻转面法线;6)创建指定尺寸的地形平面;7)导入/导出PFM格式高度图数据;8)调整骨骼显示方式。这些脚本涵盖了从基础网格创建到高级地形处理的多个方面,展现了Blender Python API在3D建模和数据处理中
·
一.创建网格
mesh_name = ''
mesh_material_name = ''
vertices = []
faces = []
blender_mesh = bpy.data.meshes.new(mesh_name)
blender_mesh.from_pydata(vertices, [], faces)
blender_object = bpy.data.objects.new(mesh_name, blender_mesh)
blender_object.data.materials.append(bpy.data.materials.new(name=mesh_material_name))
bpy.context.collection.objects.link(blender_object)
二.设置网格坐标&旋转
bpy.context.scene.objects['mesh'].rotation = (0, 0, 0)
三.复制网格
objects = bpy.context.scene.objects
blender_obj = objects[mesh_name].copy()
blender_obj.data = objects[mesh_name].data.copy()
blender_obj.data.materials[0] = objects[mesh_name].data.materials[0].copy()
blender_obj.rotation_euler = objects[mesh_name].rotation_euler.copy()
blender_obj.name = mesh_name
blender_obj_rotation = (0, 0, 0)
bpy.context.collection.objects.link(blender_obj)
四.创建网格UV&顶点颜色&其他属性
blender_object = bpy.context.scene.objects['mesh']
blender_object.data.uv_layers.new(name="UVMap")
blender_object.data.uv_layers.new(name="UVMap2")
blender_object.data.attributes.new(name="rgb", domain='POINT', type='FLOAT_COLOR')
五.获取网格点&面&面拐
六.翻转面法线
faces = objects[target_name].data.polygons
for face in faces:
face.flip()
七.创建指定长宽的地形平面高度网格
import bpy
import math
#terrain params
terrain_x_size = 946
terrain_y_size = 938
polygon_size = 5
blender_unit_size = 0.1
#calculate terrain_x_node_count, terrain_y_node_count
terrain_x_node_count = (int)(terrain_x_size / polygon_size)
terrain_y_node_count = (int)(terrain_y_size / polygon_size)
#calculate terrain_min_x terrain_min_y
terrain_min_x = terrain_x_node_count * blender_unit_size / -2
terrain_min_y = terrain_x_node_count * blender_unit_size / -2
#fill terrain verts
terrain_verts = []
for y in range(0, terrain_y_node_count + 1):
for x in range(0, terrain_x_node_count + 1):
coord_x = x * blender_unit_size + terrain_min_x
coord_y = y * blender_unit_size + terrain_min_y
coord_z = 0
terrain_verts.append((coord_x, coord_y, coord_z))
#fill terrain faces
terrain_faces = []
for y in range(0, terrain_y_node_count):
for x in range(0, terrain_x_node_count):
face_index_1 = y * (terrain_x_node_count + 1) + x
face_index_2 = face_index_1 + 1
face_index_3 = face_index_2 + terrain_x_node_count + 1
face_index_4 = face_index_3 - 1
terrain_faces.append((face_index_1, face_index_2, face_index_3, face_index_4))
#create terrain plane
name = 'terrain_plane'
mymesh = bpy.data.meshes.new(name)
myobject = bpy.data.objects.new(name, mymesh)
bpy.context.collection.objects.link(myobject)
mymesh.from_pydata(terrain_verts, [], terrain_faces)
myobject["terrain_x_size"] = terrain_x_size
myobject["terrain_y_size"] = terrain_y_size
myobject["polygon_size"] = polygon_size
myobject["blender_unit_size"] = blender_unit_size
八.导入PFM格式文件
import bpy
import math
import numpy as np
import struct
#terrain params
terrain_x_size = 234
terrain_y_size = 233
polygon_size = 3
blender_unit_size = 0.1
#pfm height_map[height][width]
def read_pfm(file_name):
global terrain_x_node_count
global terrain_y_node_count
with open(file_name, "rb") as file:
header = file.readline().decode('utf-8').rstrip()
if header != 'Pf':
raise Exception('Not a pfm file.')
width, height = map(int, file.readline().decode('utf-8').rstrip().split())
scale = float(file.readline().decode('utf-8').rstrip())
data = np.fromfile(file, np.float32)
shape = (height, width, 1)
data = np.reshape(data, shape)
return data
#read pfm
height_map = read_pfm("D:\layer_ground_elevation.pfm")
terrain_x_node_count = len(height_map[0]) - 1
terrain_y_node_count = len(height_map) - 1
terrain_min_x = terrain_x_node_count * blender_unit_size / -2
terrain_min_y = terrain_x_node_count * blender_unit_size / -2
#fill terrain verts
terrain_verts = []
for y in range(0, terrain_y_node_count + 1):
for x in range(0, terrain_x_node_count + 1):
coord_x = x * blender_unit_size + terrain_min_x
coord_y = y * blender_unit_size + terrain_min_y
coord_z = height_map[y][x] * blender_unit_size
terrain_verts.append((coord_x, coord_y, coord_z))
#fill terrain faces
terrain_faces = []
for y in range(0, terrain_y_node_count):
for x in range(0, terrain_x_node_count):
face_index_1 = y * (terrain_x_node_count + 1) + x
face_index_2 = face_index_1 + 1
face_index_3 = face_index_2 + terrain_x_node_count + 1
face_index_4 = face_index_3 - 1
terrain_faces.append((face_index_1, face_index_2, face_index_3, face_index_4))
#create terrain plane
name = 'terrain_plane'
mymesh = bpy.data.meshes.new(name)
myobject = bpy.data.objects.new(name, mymesh)
bpy.context.collection.objects.link(myobject)
mymesh.from_pydata(terrain_verts, [], terrain_faces)
myobject["terrain_x_size"] = terrain_x_size
myobject["terrain_y_size"] = terrain_y_size
myobject["polygon_size"] = polygon_size
myobject["blender_unit_size"] = blender_unit_size
九.导出PFM格式文件
import bpy
import math
import numpy as np
import struct
#pfm height_map[terrain_y_node_count][terrain_x_node_count]
def write_pfm(file, height_map):
file = open(file, 'wb')
terrain_x_node_count = len(height_map[0])
terrain_y_node_count = len(height_map)
file.write('Pf\n'.encode('ascii'))
file.write('%d %d\n'.encode('ascii') % (terrain_x_node_count, terrain_y_node_count))
file.write('%.3f\n'.encode('ascii') % (-1))
for row in height_map:
for pixel in row:
file.write(struct.pack('f', pixel))
file.close()
height_map = []
objects = bpy.context.scene.objects
mesh = objects['terrain_plane'].data
points = mesh.vertices
terrain_x_size = int(objects['terrain_plane']["terrain_x_size"])
terrain_y_size = int(objects['terrain_plane']["terrain_y_size"])
polygon_size = int(objects['terrain_plane']["polygon_size"])
blender_unit_size = objects['terrain_plane']["blender_unit_size"]
#calculate terrain_x_node_count, terrain_y_node_count
terrain_x_node_count = (int)(terrain_x_size / polygon_size)
terrain_y_node_count = (int)(terrain_y_size / polygon_size)
#sort vertex x,y
points_array = []
for vertex in points:
points_array.append((vertex.co.x, vertex.co.y, vertex.co.z))
points_array.sort(key=lambda x: (x[1], x[0]))
for y in range(0, terrain_y_node_count + 1):
row = []
for x in range(0, terrain_x_node_count + 1):
vertex_index = y * (terrain_x_node_count + 1) + x
coord_z = points_array[vertex_index][2] / blender_unit_size
row.append(coord_z)
height_map.append(row)
write_pfm('D:\layer_ground_elevation.pfm', height_map)
十.调整骨骼显示方式
bpy.context.object.pose.bones["r_calf"].custom_shape = bpy.data.objects["球体"]

GitCode 天启AI是一款由 GitCode 团队打造的智能助手,基于先进的LLM(大语言模型)与多智能体 Agent 技术构建,致力于为用户提供高效、智能、多模态的创作与开发支持。它不仅支持自然语言对话,还具备处理文件、生成 PPT、撰写分析报告、开发 Web 应用等多项能力,真正做到“一句话,让 Al帮你完成复杂任务”。
更多推荐
所有评论(0)