forked from bartvdbraak/blender
d2fb4afb7c
export_cal3d.py - option to export with baked animation from posebones, added popup UI with some options, fixed object scaling, get the meshes armature if its not selected.
138 lines
4.6 KiB
Python
138 lines
4.6 KiB
Python
# This program is free software; you can redistribute it and/or modify
|
|
# it under the terms of the GNU General Public License as published by
|
|
# the Free Software Foundation; either version 2 of the License, or
|
|
# (at your option) any later version.
|
|
#
|
|
# This program is distributed in the hope that it will be useful,
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
# GNU General Public License for more details.
|
|
#
|
|
# You should have received a copy of the GNU General Public License
|
|
# along with this program; if not, write to the Free Software
|
|
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
|
|
import Blender
|
|
import bpy
|
|
def getBakedPoseData(ob_arm, start_frame, end_frame):
|
|
'''
|
|
If you are currently getting IPO's this function can be used to
|
|
return a list of frame aligned bone dictionary's
|
|
|
|
The data in these can be swaped in for the IPO loc and quat
|
|
|
|
If you want to bake an action, this is not as hard and the ipo hack can be removed.
|
|
'''
|
|
|
|
# --------------------------------- Dummy Action! Only for this functon
|
|
backup_action = ob_arm.action
|
|
backup_frame = Blender.Get('curframe')
|
|
|
|
DUMMY_ACTION_NAME = '~DONT_USE~'
|
|
# Get the dummy action if it has no users
|
|
try:
|
|
new_action = bpy.data.actions[DUMMY_ACTION_NAME]
|
|
if new_action.users:
|
|
new_action = None
|
|
except:
|
|
new_action = None
|
|
|
|
if not new_action:
|
|
new_action = bpy.data.actions.new(DUMMY_ACTION_NAME)
|
|
new_action.fakeUser = False
|
|
# ---------------------------------- Done
|
|
|
|
Matrix = Blender.Mathutils.Matrix
|
|
Quaternion = Blender.Mathutils.Quaternion
|
|
Vector = Blender.Mathutils.Vector
|
|
POSE_XFORM= [Blender.Object.Pose.LOC, Blender.Object.Pose.ROT]
|
|
|
|
# Each dict a frame
|
|
bake_data = [{} for i in xrange(1+end_frame-start_frame)]
|
|
|
|
pose= ob_arm.getPose()
|
|
armature_data= ob_arm.getData();
|
|
pose_bones= pose.bones
|
|
|
|
# --------------------------------- Build a list of arma data for reuse
|
|
armature_bone_data = []
|
|
bones_index = {}
|
|
for bone_name, rest_bone in armature_data.bones.items():
|
|
pose_bone = pose_bones[bone_name]
|
|
rest_matrix = rest_bone.matrix['ARMATURESPACE']
|
|
rest_matrix_inv = rest_matrix.copy().invert()
|
|
armature_bone_data.append( [len(bones_index), -1, bone_name, rest_bone, rest_matrix, rest_matrix_inv, pose_bone, None ])
|
|
bones_index[bone_name] = len(bones_index)
|
|
|
|
# Set the parent ID's
|
|
for bone_name, pose_bone in pose_bones.items():
|
|
parent = pose_bone.parent
|
|
if parent:
|
|
bone_index= bones_index[bone_name]
|
|
parent_index= bones_index[parent.name]
|
|
armature_bone_data[ bone_index ][1]= parent_index
|
|
# ---------------------------------- Done
|
|
|
|
|
|
|
|
# --------------------------------- Main loop to collect IPO data
|
|
frame_index = 0
|
|
for current_frame in xrange(start_frame, end_frame+1):
|
|
ob_arm.action = backup_action
|
|
#pose.update() # not needed
|
|
Blender.Set('curframe', current_frame)
|
|
#Blender.Window.RedrawAll()
|
|
#frame_data = bake_data[frame_index]
|
|
ob_arm.action = new_action
|
|
###for i,pose_bone in enumerate(pose_bones):
|
|
|
|
for index, parent_index, bone_name, rest_bone, rest_matrix, rest_matrix_inv, pose_bone, ipo in armature_bone_data:
|
|
matrix= pose_bone.poseMatrix
|
|
|
|
parent_bone= rest_bone.parent
|
|
|
|
if parent_index != -1:
|
|
parent_pose_matrix = armature_bone_data[parent_index][6].poseMatrix
|
|
parent_bone_matrix_inv = armature_bone_data[parent_index][5]
|
|
matrix= matrix * parent_pose_matrix.copy().invert()
|
|
rest_matrix= rest_matrix * parent_bone_matrix_inv
|
|
|
|
matrix=matrix * rest_matrix.copy().invert()
|
|
|
|
pose_bone.quat= matrix.toQuat()
|
|
pose_bone.loc= matrix.translationPart()
|
|
pose_bone.insertKey(ob_arm, 1, POSE_XFORM) # always frame 1
|
|
|
|
# THIS IS A BAD HACK! IT SUCKS BIGTIME BUT THE RESULT ARE NICE
|
|
# - use a temp action and bake into that, always at the same frame
|
|
# so as not to make big IPO's, then collect the result from the IPOs
|
|
|
|
# Now get the data from the IPOs
|
|
if not ipo: ipo = armature_bone_data[index][7] = new_action.getChannelIpo(bone_name)
|
|
|
|
loc = Vector()
|
|
quat = Quaternion()
|
|
|
|
for curve in ipo:
|
|
val = curve.evaluate(1)
|
|
curve_name= curve.name
|
|
if curve_name == 'LocX': loc[0] = val
|
|
elif curve_name == 'LocY': loc[1] = val
|
|
elif curve_name == 'LocZ': loc[2] = val
|
|
elif curve_name == 'QuatW': quat[3] = val
|
|
elif curve_name == 'QuatX': quat[0] = val
|
|
elif curve_name == 'QuatY': quat[1] = val
|
|
elif curve_name == 'QuatZ': quat[2] = val
|
|
|
|
bake_data[frame_index][bone_name] = loc, quat
|
|
|
|
|
|
frame_index+=1
|
|
|
|
ob_arm.action = backup_action
|
|
Blender.Set('curframe', backup_frame)
|
|
return bake_data
|
|
|
|
|
|
|