一.创建形变动画morph_key

import bpy
import math
 
objects = bpy.context.scene.objects
mesh_name = 'p51_propeller'
morph_key_cnt = 13
 
for morph_key_index in range(morph_key_cnt):
    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()
    
    if morph_key_index == 0:
        blender_obj.name = mesh_name + '_morph_key_base'
    else:
        blender_obj.name = mesh_name + '_morph_key_' + str(morph_key_index)
    blender_obj_rotation = (0, 2 * morph_key_index * math.pi / (morph_key_cnt -1), 0)
    blender_obj.rotation_euler = blender_obj_rotation
    
    bpy.context.collection.objects.link(blender_obj)
 
for obj in objects:
     if obj.type == 'MESH':
        mesh_name_x = obj.name + '_mesh'
        obj.data.name = mesh_name_x
        material_name = obj.name + '_mat'
        obj.data.materials[0].name = material_name

 二.获取点线面并分离为独立物体

import bpy
import math

#polygon format [polygon_index]
polygon_start_index = 5;
 
objects = bpy.context.scene.objects
mesh = objects['Cube'].data
points = mesh.vertices
faces = mesh.polygons
 
vert_coords = []
polygon_faces = []
polygon_face = []
 
for point in points:
    vert_coords.append((point.co.x, point.co.y, point.co.z))
 
for face in faces:
    name = 'polygon_' + str(polygon_start_index)
    mymesh = bpy.data.meshes.new(name)
    myobject = bpy.data.objects.new(name, mymesh)  
    bpy.context.collection.objects.link(myobject)
    
    for vertice_index in face.vertices:
        polygon_face.append(vertice_index)
        
    polygon_faces.append(polygon_face)
    mymesh.from_pydata(vert_coords, [], polygon_faces)
    polygon_start_index = polygon_start_index + 1
    polygon_faces = []
    polygon_face = []

三.翻转面法线

import bpy
import math
 
objects = bpy.context.scene.objects
for index in range(6, 12):
    target_name = 'polygon_' + str(index)
    objects[target_name].select_set(True)
    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)
Logo

腾讯云面向开发者汇聚海量精品云计算使用和开发经验,营造开放的云计算技术生态圈。

更多推荐