从Blender导出OGRE模型
Blender Python API
导出的动画名字默认为 my_animation
同个骨架内的子网格所带的骨骼和动画都一样, 即skeleton文件相同(请验证)
导出很多无用文件, 未进行删除(只保证skeleton文件正确)
动画过长的情况, 请调整模型骨骼动画去除空帧或手动导出
导出动画骨骼文件(skeleton)以fbx文件名命名
import bpy
import sys
import os
import re
from os.path import join, split
in_dir = "C:\\Users\\Ian\\Desktop\\data"
filters = ["ss.fbx"]
io_ogre = "D:\\blender2ogre\\io_ogre"
path = "C:\\Users\\Ian\\Desktop\\tmp"
action_list = []
def reset_blend():
candidate_list = [item.name for item in bpy.data.objects]
for object_name in candidate_list:
bpy.data.objects[object_name].select = True
bpy.ops.object.delete()
for item in bpy.data.meshes:
bpy.data.meshes.remove(item)
def export(name):
namestr = name
if name.find('_ogre') != -1:
namestr = name[0:name.find('_ogre')]
bpy.ops.object.mode_set(mode='OBJECT', toggle=False)
for ob in bpy.data.objects:
if ob.type != 'MESH':
continue
print(ob.name + 'type:' + ob.type + ' set mesh scale')
bpy.ops.object.select_all(action='DESELECT')
ob.select = True
bpy.context.scene.objects.active = ob
bpy.ops.object.transform_apply(
location=False, scale=True, rotation=False)
ob.select = False
bpy.ops.object.select_all(action='DESELECT')
for ob in bpy.data.objects:
if ob.type != 'ARMATURE':
continue
print(ob.name + 'type:' + ob.type + ' set armature trans')
bpy.ops.object.select_all(action='DESELECT')
ob.select = True
bpy.context.scene.objects.active = ob
bpy.ops.object.transform_apply(
location=True, scale=False, rotation=True)
ob.select = False
bpy.ops.object.select_all(action='DESELECT')
for ob in bpy.data.objects:
if ob.type != 'MESH':
continue
print(ob.name + 'type:' + ob.type + ' set armature trans')
bpy.ops.object.select_all(action='DESELECT')
ob.select = True
bpy.context.scene.objects.active = ob
bpy.ops.object.transform_apply(
location=True, scale=False, rotation=True)
ob.select = False
bpy.ops.object.select_all(action='DESELECT')
for ob in bpy.data.objects:
if ob.type != 'MESH' or len(ob.material_slots) == 0:
continue
bpy.ops.object.select_all(action='DESELECT')
ob.select = True
bpy.context.scene.objects.active = ob
matslots = len(ob.material_slots)
print("# Object", ob.name, "has", matslots, "material slot(s)")
if ob.find_armature():
ob.data.name = namestr
for i in range(0, matslots):
bpy.context.object.active_material_index = i
bpy.ops.object.material_slot_remove()
bpy.ops.object.select_all(action='DESELECT')
first_frame = 0
last_frame = -9999
for action in bpy.data.actions :
if action.name in action_list:
continue
print(action.name, action.frame_range[0], action.frame_range[1])
action_list.append(action.name)
if action.frame_range[1] > last_frame:
last_frame = action.frame_range[1]
#if action.frame_range[0] < first_frame :
#first_frame = action.frame_range[0]
print ("first frame : ",first_frame, "\nlast frame : ", last_frame,"\nduration : ",last_frame-first_frame)
scn = bpy.context.scene
scn.frame_start = first_frame
scn.frame_end = last_frame
filepath = path+"\\"+namestr+"_"+str(last_frame)
os.makedirs(filepath, exist_ok=True, mode=0o775)
dot_scene(filepath)
reset_blend()
def convert(path, filters):
need_file_items = []
need_file_names = []
filterDict = {
}
for item in filters:
filterDict[item] = True
file_lst = os.listdir(path)
for item in file_lst:
fileName, fileExtension = os.path.splitext(item)
if fileExtension == ".fbx" or ".FBX" and (not item in filterDict):
need_file_items.append(item)
need_file_names.append(fileName)
n = len(need_file_items)
for i in range(n):
item = need_file_items[i]
itemName = need_file_names[i]
ufilename = path + "\\" + item
bpy.ops.import_scene.fbx(
filepath=ufilename, directory=path, filter_glob="*.fbx")
export(itemName)
sys.path.append(io_ogre)
from io_ogre.ogre.skeleton import dot_skeleton
from io_ogre.ogre.mesh import dot_mesh
from io_ogre.ogre.scene import dot_scene
from io_ogre import config
reset_blend()
convert(in_dir, filters)
print('Success!')