Bootstrap

骑砍战团MOD开发(52)-使用BrfExporter&Blender制作BRF文件

一.Blender模型导出为BRF文件

import bpy
import struct

class BrfFile:
    def __init__(self):
        self.meshes = []
        self.bodies = []

class Mesh:
    def __init__(self):
        self.name = ''
        self.material_name = ''
        self.vertices = []
        self.morph_keys = []
        self.vertices_fvf = []
        self.faces = []

class Vertex:
    def __init__(self):
        self.x = 0.000
        self.y = 0.000
        self.z = 0.000
        
class VertexFvf:
    def __init__(self):
        self.vertex_index = 0
        self.vertex_color = -1
        self.normal_x = 0.000
        self.normal_y = 0.000        
        self.normal_z = 0.000
        self.uv_x = 0.000
        self.uv_y = 0.000
        
class Face:
    def __init__(self):
        self.vertex_fvf_indices = []
        
def write_brf_file(brf_file, f):
    #write meshes
    f.write(struct.pack('i', len('mesh')))
    f.write(b'mesh')
    f.write(struct.pack('i', len(brf_file.meshes)))
    for mesh in brf_file.meshes:
        write_mesh(mesh, f)
        
    f.write(struct.pack('i', len('end')))
    f.write(b'end')

def write_mesh(mesh, f):
    f.write(struct.pack('i', len(mesh.name)))
    f.write(mesh.name.encode())
    f.write(struct.pack('i', 0))
    f.write(struct.pack('i', len(mesh.material_name)))
    f.write(mesh.material_name.encode())
    
    #write vertices
    f.write(struct.pack('i', len(mesh.vertices)))
    for vertex in mesh.vertices:
        f.write(struct.pack('f', vertex.x))
        f.write(struct.pack('f', vertex.y))
        f.write(struct.pack('f', vertex.z))
        
    #write morph keys
    f.write(struct.pack('i', 0))
    f.write(struct.pack('i', 0))
    
    #write vertices_fvf
    f.write(struct.pack('i', len(mesh.vertices_fvf)))
    for vertex_fvf in mesh.vertices_fvf:
        f.write(struct.pack('i', vertex_fvf.vertex_index))
        f.write(struct.pack('i', vertex_fvf.vertex_color))
        f.write(struct.pack('f', vertex_fvf.normal_x))
        f.write(struct.pack('f', vertex_fvf.normal_y))
        f.write(struct.pack('f', vertex_fvf.normal_z))
        f.write(struct.pack('f', vertex_fvf.uv_x))
        f.write(struct.pack('f', vertex_fvf.uv_y))
        f.write(struct.pack('f', vertex_fvf.uv_x))
        f.write(struct.pack('f', vertex_fvf.uv_y))
        
    #write faces
    f.write(struct.pack('i', len(mesh.faces)))
    for face in mesh.faces:
        for vertex_fvf_index in face.vertex_fvf_indices:
            f.write(struct.pack('i', vertex_fvf_index))
      
def create_blender_mesh(blender_object_name):
    blender_mesh = bpy.context.scene.objects[blender_object_name].data
    blender_uv = blender_mesh.uv_layers.active.data
    blender_loops = blender_mesh.loops
    mesh = Mesh()
    mesh.name = blender_mesh.name
    mesh.material_name = blender_mesh.materials[0].name
    
    #create vetex
    for blender_vertex in blender_mesh.vertices:
        vertex = Vertex()
        vertex.x = round(blender_vertex.co.x, 6)
        vertex.y = round(blender_vertex.co.y, 6)
        vertex.z = round(blender_vertex.co.z, 6)
        mesh.vertices.append(vertex)
    
    #create fvf and faces
    for blender_face in blender_mesh.polygons:
        vertex_indices = blender_face.vertices
        loop_indices = blender_face.loop_indices
        face = Face()
        for loop_index, vertex_index in enumerate(vertex_indices):
            vertex_normal_x = round(blender_loops[loop_indices[loop_index]].normal.x, 4)
            vertex_normal_y = round(blender_loops[loop_indices[loop_index]].normal.y, 4)
            vertex_normal_z = round(blender_loops[loop_indices[loop_index]].normal.z, 4)
            vertex_uv_x = round(blender_uv[loop_indices[loop_index]].uv.x, 4)
            vertex_uv_y = round(blender_uv[loop_indices[loop_index]].uv.y, 4)
            
            vertex_fvf = VertexFvf()
            vertex_fvf.vertex_index = vertex_index
            vertex_fvf.normal_x = vertex_normal_x
            vertex_fvf.normal_y = vertex_normal_y
            vertex_fvf.normal_z = vertex_normal_z
            vertex_fvf.uv_x = vertex_uv_x
            vertex_fvf.uv_y = vertex_uv_y
            vertex_fvf_index = get_vertex_fvf_index(vertex_fvf, mesh.vertices_fvf)
            if vertex_fvf_index == -1:
                mesh.vertices_fvf.append(vertex_fvf)
                vertex_fvf_index = len(mesh.vertices_fvf) - 1
            face.vertex_fvf_indices.append(vertex_fvf_index)     
        mesh.faces.append(face)
    return mesh

def get_vertex_fvf_index(vertex_fvf, vertices_fvf):
    vertex_fvf_index = -1
    for index, element in enumerate(vertices_fvf):
        if element.vertex_index == vertex_fvf.vertex_index and round(element.normal_x, 3) == round(vertex_fvf.normal_x, 3) and round(element.normal_y, 3) == round(vertex_fvf.normal_y, 3) and round(element.normal_z, 3) == round(vertex_fvf.normal_z, 3) and round(element.uv_x, 3) == round(vertex_fvf.uv_x, 3) and round(element.uv_y, 3) == round(vertex_fvf.uv_y, 3):
            vertex_fvf_index = index
            break
    return vertex_fvf_index
    
      

brf_export_path = 'D:/work/Tool/MB_Warband/BrfExporter/building.brf'
brf_file = BrfFile()
mesh = create_blender_mesh('89_hushi_tank_cheti')
brf_file.meshes.append(mesh)

print('vertex count: ' + str(len(brf_file.meshes[0].vertices)))
print('vertex fvf count: ' + str(len(brf_file.meshes[0].vertices_fvf)))
print('face count: ' + str(len(brf_file.meshes[0].faces)))

with open(brf_export_path, 'wb') as f:
    write_brf_file(brf_file, f)

二.Blender顶点动画导出为BRF文件

import bpy
import struct

class BrfFile:
    def __init__(self):
        self.meshes = []
        self.bodies = []

class Mesh:
    def __init__(self):
        self.name = ''
        self.material_name = ''
        self.vertices = []
        self.morph_keys = []
        self.vertices_fvf = []
        self.faces = []

class Vertex:
    def __init__(self):
        self.x = 0.000
        self.y = 0.000
        self.z = 0.000
        
class MorphKey:
    def __init__(self):
        self.morph_time = 0
        self.vertices = []
        self.vertices_fvf = []
        
class VertexFvf:
    def __init__(self):
        self.vertex_index = 0
        self.vertex_color = -1
        self.normal_x = 0.000
        self.normal_y = 0.000        
        self.normal_z = 0.000
        self.uv_x = 0.000
        self.uv_y = 0.000
        
class Face:
    def __init__(self):
        self.vertex_fvf_indices = []
        
def write_brf_file(brf_file, f):
    #write meshes
    f.write(struct.pack('i', len('mesh')))
    f.write(b'mesh')
    f.write(struct.pack('i', len(brf_file.meshes)))
    for mesh in brf_file.meshes:
        write_mesh(mesh, f)
        
    f.write(struct.pack('i', len('end')))
    f.write(b'end')

def write_mesh(mesh, f):
    f.write(struct.pack('i', len(mesh.name)))
    f.write(mesh.name.encode())
    f.write(struct.pack('i', 0))
    f.write(struct.pack('i', len(mesh.material_name)))
    f.write(mesh.material_name.encode())
    
    #write vertices
    f.write(struct.pack('i', len(mesh.vertices)))
    for vertex in mesh.vertices:
        f.write(struct.pack('f', vertex.x))
        f.write(struct.pack('f', vertex.y))
        f.write(struct.pack('f', vertex.z))
        
    #non rigged mesh
    f.write(struct.pack('i', 0))
    
    #write morph keys
    f.write(struct.pack('i', len(mesh.morph_keys)))
    for morph_key in mesh.morph_keys:
        write_morph_key(morph_key, f)
    
    #write vertices_fvf
    f.write(struct.pack('i', len(mesh.vertices_fvf)))
    for vertex_fvf in mesh.vertices_fvf:
        f.write(struct.pack('i', vertex_fvf.vertex_index))
        f.write(struct.pack('i', vertex_fvf.vertex_color))
        f.write(struct.pack('f', vertex_fvf.normal_x))
        f.write(struct.pack('f', vertex_fvf.normal_y))
        f.write(struct.pack('f', vertex_fvf.normal_z))
        f.write(struct.pack('f', vertex_fvf.uv_x))
        f.write(struct.pack('f', vertex_fvf.uv_y))
        f.write(struct.pack('f', vertex_fvf.uv_x))
        f.write(struct.pack('f', vertex_fvf.uv_y))
        
    #write faces
    f.write(struct.pack('i', len(mesh.faces)))
    for face in mesh.faces:
        for vertex_fvf_index in face.vertex_fvf_indices:
            f.write(struct.pack('i', vertex_fvf_index))
            
def write_morph_key(morph_key, f):
    f.write(struct.pack('i', morph_key.morph_time))
    #write vertices
    f.write(struct.pack('i', len(morph_key.vertices)))
    for vertex in morph_key.vertices:
        f.write(struct.pack('f', vertex.x))
        f.write(struct.pack('f', vertex.y))
        f.write(struct.pack('f', vertex.z))
        
    #write vertices_fvf
    f.write(struct.pack('i', len(morph_key.vertices_fvf)))
    for vertex_fvf in morph_key.vertices_fvf:
        f.write(struct.pack('f', vertex_fvf.normal_x))
        f.write(struct.pack('f', vertex_fvf.normal_y))
        f.write(struct.pack('f', vertex_fvf.normal_z))
     
def create_blender_mesh(blender_object_name):
    blender_mesh = bpy.context.scene.objects[blender_object_name].data
    blender_uv = blender_mesh.uv_layers.active.data
    blender_loops = blender_mesh.loops
    mesh = Mesh()
    mesh.name = blender_mesh.name
    mesh.material_name = blender_mesh.materials[0].name
    
    #create vetex
    for blender_vertex in blender_mesh.vertices:
        vertex = Vertex()
        vertex.x = round(blender_vertex.co.x, 6)
        vertex.y = round(blender_vertex.co.y, 6)
        vertex.z = round(blender_vertex.co.z, 6)
        mesh.vertices.append(vertex)
    
    #create fvf and faces
    for blender_face in blender_mesh.polygons:
        vertex_indices = blender_face.vertices
        loop_indices = blender_face.loop_indices
        face = Face()
        for loop_index, vertex_index in enumerate(vertex_indices):
            vertex_normal_x = round(blender_loops[loop_indices[loop_index]].normal.x, 3)
            vertex_normal_y = round(blender_loops[loop_indices[loop_index]].normal.y, 3)
            vertex_normal_z = round(blender_loops[loop_indices[loop_index]].normal.z, 3)
            vertex_uv_x = round(blender_uv[loop_indices[loop_index]].uv.x, 3)
            vertex_uv_y = round(blender_uv[loop_indices[loop_index]].uv.y, 3)
            
            vertex_fvf = VertexFvf()
            vertex_fvf.vertex_index = vertex_index
            vertex_fvf.normal_x = vertex_normal_x
            vertex_fvf.normal_y = vertex_normal_y
            vertex_fvf.normal_z = vertex_normal_z
            vertex_fvf.uv_x = vertex_uv_x
            vertex_fvf.uv_y = vertex_uv_y
            vertex_fvf_index = get_vertex_fvf_index(vertex_fvf, mesh.vertices_fvf)
            if vertex_fvf_index == -1:
                mesh.vertices_fvf.append(vertex_fvf)
                vertex_fvf_index = len(mesh.vertices_fvf) - 1
            face.vertex_fvf_indices.append(vertex_fvf_index)     
        mesh.faces.append(face)
    return mesh  

def add_morph_key_to_blender_mesh(blender_object_name, morph_time, mesh):
    blender_mesh = bpy.context.scene.objects[blender_object_name].data
    blender_loops = blender_mesh.loops
    morph_key = MorphKey()
    #create vetex
    for blender_vertex in blender_mesh.vertices:
        vertex = Vertex()
        vertex.x = round(blender_vertex.co.x, 6)
        vertex.y = round(blender_vertex.co.y, 6)
        vertex.z = round(blender_vertex.co.z, 6)
        morph_key.vertices.append(vertex)
        
    #create fvf normals
    for i in range(0, len(mesh.vertices_fvf)):
        fvf = VertexFvf()
        morph_key.vertices_fvf.append(fvf)
        
    for blender_face_index, blender_face in enumerate(blender_mesh.polygons):
        vertex_indices = blender_face.vertices
        loop_indices = blender_face.loop_indices
        for loop_index, vertex_index in enumerate(vertex_indices):
            vertex_fvf_index = mesh.faces[blender_face_index].vertex_fvf_indices[loop_index]
            vertex_normal_x = round(blender_loops[loop_indices[loop_index]].normal.x, 3)
            vertex_normal_y = round(blender_loops[loop_indices[loop_index]].normal.y, 3)
            vertex_normal_z = round(blender_loops[loop_indices[loop_index]].normal.z, 3)
            morph_key.vertices_fvf[vertex_fvf_index].normal_x = vertex_normal_x
            morph_key.vertices_fvf[vertex_fvf_index].normal_y = vertex_normal_y
            morph_key.vertices_fvf[vertex_fvf_index].normal_z = vertex_normal_z
    #set morph time
    morph_key.morph_time = morph_time
    mesh.morph_keys.append(morph_key)
    return mesh

def get_vertex_fvf_index(vertex_fvf, vertices_fvf):
    vertex_fvf_index = -1
    for index, element in enumerate(vertices_fvf):
        if element.vertex_index == vertex_fvf.vertex_index and round(element.normal_x, 3) == round(vertex_fvf.normal_x, 3) and round(element.normal_y, 3) == round(vertex_fvf.normal_y, 3) and round(element.normal_z, 3) == round(vertex_fvf.normal_z, 3) and round(element.uv_x, 3) == round(vertex_fvf.uv_x, 3) and round(element.uv_y, 3) == round(vertex_fvf.uv_y, 3):
            vertex_fvf_index = index
            break
    return vertex_fvf_index
    
      

brf_export_path = 'D:/work/Tool/MB_Warband/BlenderBrfExporter/building.brf'
brf_file = BrfFile()
mesh = create_blender_mesh('jap_car_wheel_morph_key_base')
for morph_key_index in range(0, 12):
    add_morph_key_to_blender_mesh('jap_car_wheel_morph_key_' + str(morph_key_index + 1), morph_key_index + 1, mesh)
brf_file.meshes.append(mesh)

print('vertex count: ' + str(len(brf_file.meshes[0].vertices)))
print('vertex morph key count: ' + str(len(brf_file.meshes[0].morph_keys)))
print('vertex fvf count: ' + str(len(brf_file.meshes[0].vertices_fvf)))
print('face count: ' + str(len(brf_file.meshes[0].faces)))

with open(brf_export_path, 'wb') as f:
    write_brf_file(brf_file, f)

三.Blender绑骨模型导出为BRF文件

;