[Bf-extensions-cvs] [9171510] master: BVH import: added option to update scene from the BVH.

Sybren A. Stüvel noreply at git.blender.org
Sat Nov 7 13:23:41 CET 2015


Commit: 91715100aa8145edc21e5448e79b19ee88603662
Author: Sybren A. Stüvel
Date:   Sat Nov 7 13:23:29 2015 +0100
Branches: master
https://developer.blender.org/rBA91715100aa8145edc21e5448e79b19ee88603662

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

===================================================================

M	io_anim_bvh/__init__.py
M	io_anim_bvh/import_bvh.py

===================================================================

diff --git a/io_anim_bvh/__init__.py b/io_anim_bvh/__init__.py
index 57f879c..8553404 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 08f7cb5..9aa562f 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="")



More information about the Bf-extensions-cvs mailing list