diff options
author | Sybren A. Stüvel <sybren@stuvel.eu> | 2015-11-07 15:23:29 +0300 |
---|---|---|
committer | Sybren A. Stüvel <sybren@stuvel.eu> | 2015-11-07 15:23:29 +0300 |
commit | 91715100aa8145edc21e5448e79b19ee88603662 (patch) | |
tree | a9f6ca947bcd45fd87f57a9b2d24514603e9bdd0 | |
parent | 407d0ea752b3af73d3f13ba072671bd09eefecb1 (diff) |
BVH import: added option to update scene from the BVH.
This commit adds two options to the BVH importer to adjust the scene's
frame rate and duration to that of the BVH file. Since different BVHs
have different frame rates, this makes it possible to import BVH files
for inspection in Blender without having to manually open the BVH file
to find its frame rate and duration. The scene is only extended to fit
the BVH file, and never shortened.
There already exists an option for the opposite, to scale the BVH
animation data to the scene's frame rate. This did not take into account
the scene.render.fps_base property, which is also fixed by this commit.
This closes task T34919.
Reviewers: campbellbarton
Reviewed By: campbellbarton
Maniphest Tasks: T34919
Differential Revision: https://developer.blender.org/D1608
-rw-r--r-- | io_anim_bvh/__init__.py | 12 | ||||
-rw-r--r-- | io_anim_bvh/import_bvh.py | 52 |
2 files changed, 57 insertions, 7 deletions
diff --git a/io_anim_bvh/__init__.py b/io_anim_bvh/__init__.py index 57f879c0..85534048 100644 --- a/io_anim_bvh/__init__.py +++ b/io_anim_bvh/__init__.py @@ -92,6 +92,18 @@ class ImportBVH(bpy.types.Operator, ImportHelper, ImportBVHOrientationHelper): "BVH frame maps directly to a Blender frame"), default=False, ) + update_scene_fps = BoolProperty( + name="Update scene framerate", + description="Sets the scene framerate to that of the BVH file. Note that this " + "nullifies the 'Scale FPS' option, as the scale will be 1:1", + default=False + ) + update_scene_duration = BoolProperty( + name="Update scene duration", + description="Extend the scene's duration to the BVH duration. Does not shorten scene " + "when the BVH fits in its entirety", + default=False, + ) use_cyclic = BoolProperty( name="Loop", description="Loop the animation playback", diff --git a/io_anim_bvh/import_bvh.py b/io_anim_bvh/import_bvh.py index 08f7cb5b..9aa562f0 100644 --- a/io_anim_bvh/import_bvh.py +++ b/io_anim_bvh/import_bvh.py @@ -20,7 +20,7 @@ # Script copyright (C) Campbell Barton -from math import radians +from math import radians, ceil import bpy from mathutils import Vector, Euler, Matrix @@ -114,6 +114,7 @@ def read_bvh(context, file_path, rotate_mode='XYZ', global_scale=1.0): bvh_nodes = {None: None} bvh_nodes_serial = [None] + bvh_frame_count = None bvh_frame_time = None channelIndex = -1 @@ -205,8 +206,13 @@ def read_bvh(context, file_path, rotate_mode='XYZ', global_scale=1.0): # Frames: n # Frame Time: dt if len(file_lines[lineIdx]) == 1 and file_lines[lineIdx][0].lower() == 'motion': - lineIdx += 2 # Read frame rate. + lineIdx += 1 # Read frame count. + if (len(file_lines[lineIdx]) == 2 and + file_lines[lineIdx][0].lower() == 'frames:'): + bvh_frame_count = int(file_lines[lineIdx][1]) + + lineIdx += 1 # Read frame rate. if (len(file_lines[lineIdx]) == 3 and file_lines[lineIdx][0].lower() == 'frame' and file_lines[lineIdx][1].lower() == 'time:'): @@ -292,7 +298,7 @@ def read_bvh(context, file_path, rotate_mode='XYZ', global_scale=1.0): bvh_node.rest_tail_local.y = bvh_node.rest_tail_local.y + global_scale / 10 bvh_node.rest_tail_world.y = bvh_node.rest_tail_world.y + global_scale / 10 - return bvh_nodes, bvh_frame_time + return bvh_nodes, bvh_frame_time, bvh_frame_count def bvh_node_dict2objects(context, bvh_name, bvh_nodes, rotate_mode='NATIVE', frame_start=1, IMPORT_LOOP=False): @@ -611,13 +617,15 @@ def load(operator, frame_start=1, global_matrix=None, use_fps_scale=False, + update_scene_fps=False, + update_scene_duration=False ): import time t1 = time.time() print('\tparsing bvh %r...' % filepath, end="") - bvh_nodes, bvh_frame_time = read_bvh(context, filepath, + bvh_nodes, bvh_frame_time, bvh_frame_count = read_bvh(context, filepath, rotate_mode=rotate_mode, global_scale=global_scale) @@ -625,9 +633,39 @@ def load(operator, scene = context.scene frame_orig = scene.frame_current - fps = scene.render.fps - if bvh_frame_time is None: - bvh_frame_time = 1.0 / scene.render.fps + scene_fps = scene.render.fps / scene.render.fps_base + + if update_scene_fps: + # Update the scene's FPS settings from the BVH, but only if the BVH contains enough info. + if bvh_frame_time is None: + raise ValueError('Unable to update scene frame time, as the BVH file does not ' + 'contain the frame duration in its MOTION section.') + + new_fps = 1.0 / bvh_frame_time + if scene.render.fps != new_fps or scene.render.fps_base != 1.0: + print(' updating scene FPS (was %f) to BVH FPS (%f)' % (scene_fps, new_fps)) + scene.render.fps = new_fps + scene.render.fps_base = 1.0 + + # Now that we have a 1-to-1 mapping of Blender frames and BVH frames, there is no need + # to scale the FPS any more. It's even better not to, to prevent roundoff errors. + use_fps_scale = False + else: + if bvh_frame_time is None: + print('BVH did not contain frame duration in its MOTION section, using scene FPS.') + bvh_frame_time = 1.0 / scene_fps + + if update_scene_duration: + if use_fps_scale: + if bvh_frame_count is None: + raise ValueError('Unable to extend the scene duration, as the BVH file does not ' + 'contain the number of frames in its MOTION section.') + scaled_frame_count = int(ceil(bvh_frame_count * bvh_frame_time * scene_fps)) + bvh_last_frame = frame_start + scaled_frame_count + else: + bvh_last_frame = frame_start + bvh_frame_count + if context.scene.frame_end < bvh_last_frame: + context.scene.frame_end = bvh_last_frame t1 = time.time() print('\timporting to blender...', end="") |