forked from bartvdbraak/blender
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
|
||
|
|
||
|
|
||
|
|