forked from bartvdbraak/blender
improved euler conversion, make sure new eulers are always compatible with the previous ones, means it doesnt result in bad interpolation.
This commit is contained in:
parent
5dd8d10336
commit
dd04e25a14
@ -77,9 +77,8 @@ MATRIX_IDENTITY_3x3 = Matrix([1,0,0],[0,1,0],[0,0,1])
|
|||||||
MATRIX_IDENTITY_4x4 = Matrix([1,0,0,0],[0,1,0,0],[0,0,1,0],[0,0,0,1])
|
MATRIX_IDENTITY_4x4 = Matrix([1,0,0,0],[0,1,0,0],[0,0,1,0],[0,0,0,1])
|
||||||
|
|
||||||
def eulerRotate(x,y,z, rot_order):
|
def eulerRotate(x,y,z, rot_order):
|
||||||
|
|
||||||
# Clamp all values between 0 and 360, values outside this raise an error.
|
# Clamp all values between 0 and 360, values outside this raise an error.
|
||||||
mats=[RotationMatrix(radians(x % 360), 3, 'X'), RotationMatrix(radians(y % 360),3,'Y'), RotationMatrix(radians(z % 360), 3, 'Z')]
|
mats=[RotationMatrix(x, 3, 'X'), RotationMatrix(y, 3,'Y'), RotationMatrix(z, 3, 'Z')]
|
||||||
# print rot_order
|
# print rot_order
|
||||||
# Standard BVH multiplication order, apply the rotation in the order Z,X,Y
|
# Standard BVH multiplication order, apply the rotation in the order Z,X,Y
|
||||||
|
|
||||||
@ -87,7 +86,7 @@ def eulerRotate(x,y,z, rot_order):
|
|||||||
#eul = (mats[rot_order[2]]*(mats[rot_order[1]]* (mats[rot_order[0]]* MATRIX_IDENTITY_3x3))).to_euler()
|
#eul = (mats[rot_order[2]]*(mats[rot_order[1]]* (mats[rot_order[0]]* MATRIX_IDENTITY_3x3))).to_euler()
|
||||||
eul = (MATRIX_IDENTITY_3x3*mats[rot_order[0]]*(mats[rot_order[1]]* (mats[rot_order[2]]))).to_euler()
|
eul = (MATRIX_IDENTITY_3x3*mats[rot_order[0]]*(mats[rot_order[1]]* (mats[rot_order[2]]))).to_euler()
|
||||||
|
|
||||||
eul = math.degrees(eul.x), math.degrees(eul.y), math.degrees(eul.z)
|
eul = eul.x, eul.y, eul.z
|
||||||
|
|
||||||
return eul
|
return eul
|
||||||
|
|
||||||
@ -187,7 +186,7 @@ def read_bvh(context, file_path, ROT_MODE='XYZ', GLOBAL_SCALE=1.0):
|
|||||||
# Account for an end node
|
# Account for an end node
|
||||||
if file_lines[lineIdx][0].lower() == 'end' and file_lines[lineIdx][1].lower() == 'site': # There is somtimes a name after 'End Site' but we will ignore it.
|
if file_lines[lineIdx][0].lower() == 'end' and file_lines[lineIdx][1].lower() == 'site': # There is somtimes a name after 'End Site' but we will ignore it.
|
||||||
lineIdx += 2 # Incriment to the next line (Offset)
|
lineIdx += 2 # Incriment to the next line (Offset)
|
||||||
rest_tail = Vector( GLOBAL_SCALE*float(file_lines[lineIdx][1]), GLOBAL_SCALE*float(file_lines[lineIdx][2]), GLOBAL_SCALE*float(file_lines[lineIdx][3]))
|
rest_tail = Vector(float(file_lines[lineIdx][1]), float(file_lines[lineIdx][2]), float(file_lines[lineIdx][3])) * GLOBAL_SCALE
|
||||||
|
|
||||||
bvh_nodes_serial[-1].rest_tail_world = bvh_nodes_serial[-1].rest_head_world + rest_tail
|
bvh_nodes_serial[-1].rest_tail_world = bvh_nodes_serial[-1].rest_head_world + rest_tail
|
||||||
bvh_nodes_serial[-1].rest_tail_local = bvh_nodes_serial[-1].rest_head_local + rest_tail
|
bvh_nodes_serial[-1].rest_tail_local = bvh_nodes_serial[-1].rest_head_local + rest_tail
|
||||||
@ -235,19 +234,9 @@ def read_bvh(context, file_path, ROT_MODE='XYZ', GLOBAL_SCALE=1.0):
|
|||||||
rx, ry, rz = float(line[channels[3]]), float(line[channels[4]]), float(line[channels[5]])
|
rx, ry, rz = float(line[channels[3]]), float(line[channels[4]]), float(line[channels[5]])
|
||||||
|
|
||||||
if ROT_MODE != 'NATIVE':
|
if ROT_MODE != 'NATIVE':
|
||||||
rx, ry, rz = eulerRotate(rx, ry, rz, bvh_node.rot_order)
|
rx, ry, rz = eulerRotate(radians(rx), radians(ry), radians(rz), bvh_node.rot_order)
|
||||||
|
else:
|
||||||
# Make interpolation not cross between 180d, thjis fixes sub frame interpolation and time scaling.
|
rx, ry, rz = radians(rx), radians(ry), radians(rz)
|
||||||
# Will go from (355d to 365d) rather then to (355d to 5d) - inbetween these 2 there will now be a correct interpolation.
|
|
||||||
|
|
||||||
while anim_data[-1][3] - rx > 180: rx+=360
|
|
||||||
while anim_data[-1][3] - rx < -180: rx-=360
|
|
||||||
|
|
||||||
while anim_data[-1][4] - ry > 180: ry+=360
|
|
||||||
while anim_data[-1][4] - ry < -180: ry-=360
|
|
||||||
|
|
||||||
while anim_data[-1][5] - rz > 180: rz+=360
|
|
||||||
while anim_data[-1][5] - rz < -180: rz-=360
|
|
||||||
|
|
||||||
# Done importing motion data #
|
# Done importing motion data #
|
||||||
anim_data.append((lx, ly, lz, rx, ry, rz))
|
anim_data.append((lx, ly, lz, rx, ry, rz))
|
||||||
@ -276,8 +265,8 @@ def read_bvh(context, file_path, ROT_MODE='XYZ', GLOBAL_SCALE=1.0):
|
|||||||
# raise 'error, bvh node has no end and no children. bad file'
|
# raise 'error, bvh node has no end and no children. bad file'
|
||||||
|
|
||||||
# Removed temp for now
|
# Removed temp for now
|
||||||
rest_tail_world = Vector(0, 0, 0)
|
rest_tail_world = Vector(0.0, 0.0, 0.0)
|
||||||
rest_tail_local = Vector(0, 0, 0)
|
rest_tail_local = Vector(0.0, 0.0, 0.0)
|
||||||
for bvh_node_child in bvh_node.children:
|
for bvh_node_child in bvh_node.children:
|
||||||
rest_tail_world += bvh_node_child.rest_head_world
|
rest_tail_world += bvh_node_child.rest_head_world
|
||||||
rest_tail_local += bvh_node_child.rest_head_local
|
rest_tail_local += bvh_node_child.rest_head_local
|
||||||
@ -339,9 +328,9 @@ def bvh_node_dict2objects(context, bvh_nodes, IMPORT_START_FRAME= 1, IMPORT_LOOP
|
|||||||
lx, ly, lz, rx, ry, rz = bvh_node.anim_data[current_frame]
|
lx, ly, lz, rx, ry, rz = bvh_node.anim_data[current_frame]
|
||||||
|
|
||||||
rest_head_local= bvh_node.rest_head_local
|
rest_head_local= bvh_node.rest_head_local
|
||||||
bvh_node.temp.loc= rest_head_local.x+lx, rest_head_local.y+ly, rest_head_local.z+lz
|
bvh_node.temp.loc= rest_head_local + Vector(lx, ly, lz)
|
||||||
|
|
||||||
bvh_node.temp.rot= radians(rx), radians(ry), radians(rz)
|
bvh_node.temp.rot= rx, ry, rz
|
||||||
|
|
||||||
bvh_node.temp.insertIpoKey(Blender.Object.IpoKeyTypes.LOCROT) # XXX invalid
|
bvh_node.temp.insertIpoKey(Blender.Object.IpoKeyTypes.LOCROT) # XXX invalid
|
||||||
|
|
||||||
@ -521,6 +510,9 @@ def bvh_node_dict2armature(context, bvh_nodes, ROT_MODE='XYZ', IMPORT_START_FRAM
|
|||||||
# KEYFRAME METHOD, SLOW, USE IPOS DIRECT
|
# KEYFRAME METHOD, SLOW, USE IPOS DIRECT
|
||||||
# TODO: use f-point samples instead (Aligorith)
|
# TODO: use f-point samples instead (Aligorith)
|
||||||
|
|
||||||
|
if ROT_MODE != 'QUATERNION':
|
||||||
|
prev_euler = [Euler() for i in range(len(bvh_nodes))]
|
||||||
|
|
||||||
# Animate the data, the last used bvh_node will do since they all have the same number of frames
|
# Animate the data, the last used bvh_node will do since they all have the same number of frames
|
||||||
for current_frame in range(len(bvh_node.anim_data)-1): # skip the first frame (rest frame)
|
for current_frame in range(len(bvh_node.anim_data)-1): # skip the first frame (rest frame)
|
||||||
# print current_frame
|
# print current_frame
|
||||||
@ -529,17 +521,20 @@ def bvh_node_dict2armature(context, bvh_nodes, ROT_MODE='XYZ', IMPORT_START_FRAM
|
|||||||
# break
|
# break
|
||||||
|
|
||||||
# Dont neet to set the current frame
|
# Dont neet to set the current frame
|
||||||
for bvh_node in bvh_nodes.values():
|
for i, bvh_node in enumerate(bvh_nodes.values()):
|
||||||
pose_bone, bone, bone_rest_matrix, bone_rest_matrix_inv= bvh_node.temp
|
pose_bone, bone, bone_rest_matrix, bone_rest_matrix_inv= bvh_node.temp
|
||||||
lx, ly, lz, rx, ry, rz = bvh_node.anim_data[current_frame + 1]
|
lx, ly, lz, rx, ry, rz = bvh_node.anim_data[current_frame + 1]
|
||||||
|
|
||||||
if bvh_node.has_rot:
|
if bvh_node.has_rot:
|
||||||
bone_rotation_matrix= Euler(radians(rx), radians(ry), radians(rz)).to_matrix()
|
bone_rotation_matrix = Euler(rx, ry, rz).to_matrix().resize4x4()
|
||||||
bone_rotation_matrix.resize4x4()
|
bone_rotation_matrix = bone_rest_matrix_inv * bone_rotation_matrix * bone_rest_matrix
|
||||||
|
|
||||||
if ROT_MODE == 'QUATERNION':
|
if ROT_MODE == 'QUATERNION':
|
||||||
pose_bone.rotation_quaternion= (bone_rest_matrix_inv * bone_rotation_matrix * bone_rest_matrix).to_quat()
|
pose_bone.rotation_quaternion = bone_rotation_matrix.to_quat()
|
||||||
else:
|
else:
|
||||||
pose_bone.rotation_euler= (bone_rest_matrix_inv * bone_rotation_matrix * bone_rest_matrix).to_euler(pose_bone.rotation_mode)
|
euler = bone_rotation_matrix.to_euler('XYZ', prev_euler[i]) # pose_bone.rotation_mode # TODO, XYZ default for now
|
||||||
|
pose_bone.rotation_euler = euler
|
||||||
|
prev_euler[i] = euler
|
||||||
|
|
||||||
if bvh_node.has_loc:
|
if bvh_node.has_loc:
|
||||||
pose_bone.location= (bone_rest_matrix_inv * TranslationMatrix(Vector(lx, ly, lz) - bvh_node.rest_head_local)).translation_part()
|
pose_bone.location= (bone_rest_matrix_inv * TranslationMatrix(Vector(lx, ly, lz) - bvh_node.rest_head_local)).translation_part()
|
||||||
@ -556,22 +551,12 @@ def bvh_node_dict2armature(context, bvh_nodes, ROT_MODE='XYZ', IMPORT_START_FRAM
|
|||||||
# bpy.ops.anim.keyframe_insert_menu(type=-4) # XXX - -4 ???
|
# bpy.ops.anim.keyframe_insert_menu(type=-4) # XXX - -4 ???
|
||||||
bpy.ops.screen.frame_offset(delta=1)
|
bpy.ops.screen.frame_offset(delta=1)
|
||||||
|
|
||||||
# First time, set the IPO's to linear
|
|
||||||
#XXX #TODO
|
|
||||||
if 0:
|
|
||||||
if current_frame == 0:
|
|
||||||
for ipo in action.getAllChannelIpos().values():
|
|
||||||
if ipo:
|
|
||||||
for cur in ipo:
|
|
||||||
cur.interpolation = Blender.IpoCurve.InterpTypes.LINEAR
|
|
||||||
if IMPORT_LOOP:
|
|
||||||
cur.extend = Blender.IpoCurve.ExtendTypes.CYCLIC
|
|
||||||
|
|
||||||
|
|
||||||
else:
|
|
||||||
for cu in action.fcurves:
|
for cu in action.fcurves:
|
||||||
|
if IMPORT_LOOP:
|
||||||
|
pass # 2.5 doenst have cyclic now?
|
||||||
|
|
||||||
for bez in cu.keyframe_points:
|
for bez in cu.keyframe_points:
|
||||||
bez.interpolation = 'CONSTANT'
|
bez.interpolation = 'LINEAR'
|
||||||
|
|
||||||
return arm_ob
|
return arm_ob
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user