4
$\begingroup$

I have two files one .bvh and the other is .c3d and I want to convert them to .bvh files if anyone could please advise how to do this as I need to work on bvh only.

$\endgroup$
8
  • $\begingroup$ Can you provide both files for testing? You can import the .c3d into blender and export it as .bvh. stackoverflow.com/questions/20499320/… $\endgroup$ Commented May 14, 2015 at 9:12
  • $\begingroup$ @Jerryno this is the c3d file dropbox.com/s/dfmi0wffsurl0ae/file.c3d?dl=0 and in the link you provided it shows how to import .c3d file into blender (which I already did), my problem is how to convert it into .bvh $\endgroup$
    – Tak
    Commented May 14, 2015 at 9:18
  • $\begingroup$ @batFINGER I've tried it but once I try to unzip the compressed file it needs a password, any thoughts? $\endgroup$
    – Tak
    Commented Mar 14, 2016 at 3:09
  • $\begingroup$ @batFINGER did you have the chance to check my previous comment? $\endgroup$
    – Tak
    Commented Mar 15, 2016 at 9:41
  • $\begingroup$ Yep, sorry looks like a bum steer, both downloading program, or the even bigger zip created from a small sample c3d from c3d.org $\endgroup$
    – batFINGER
    Commented Mar 15, 2016 at 10:11

2 Answers 2

5
$\begingroup$

You can import .c3d file in blender like this:

https://stackoverflow.com/questions/20499320/how-to-import-c3d-files-into-blender

The problem is it won't be an armature, but animated locations of points:

enter image description here

Some points will be dead in the center (marked).

  1. Adjust the frame range to fit the mocap data
  2. Delete the dead markers
  3. Re-build the armature - add armature to scene

    • looks like we have markers from both sides for each leg - that means the bones will be somewhere in between markers

    • Building the armature:

      • select a marker (or two if I want position in between) and align 3D cursor with 'Shift-S > Cursor to Selected'
      • then enter edit-mode of armature and select a joint and 'Shift-S > Selection to Cursor'
      • this way I can place all the bones (joints) precisely

        enter image description here

      • also recalculate the Roll of the bones with 'Ctrl+N > Cursor' with 3D cursor on some reference marker

    • Name the bones properly

    • Constraining location of root bones:

      • use copy_location constraint
      • or two of them with second on 50% influence to get in-between position of two markers
      • similar for center of 3 markers, you get the idea
    • Constraining bones direction

      • use damped_track constraint
      • also multiple of them with adjusted influence for center of group of markers

        enter image description here

  4. Bake the animation to Action with Pose > Animation

    Bake Action: visual_keying_ON, clear_constraints_ON

  5. Export armature as .bvh from the blender main menu (you might need to enable BVH addon).

These steps will result in having a .c3d file converted to a .bvh file. A sample .blend file with rigged markers here:

$\endgroup$
14
  • $\begingroup$ Is it possible to share with me a file with the modified steps so that I can go through them and have a reference? $\endgroup$
    – Tak
    Commented May 15, 2015 at 1:37
  • $\begingroup$ @shepherd yep, I'll rig one leg or something and give the .blend. I suspect this is a dog am I right? (for anatomy reference) $\endgroup$ Commented May 15, 2015 at 5:27
  • $\begingroup$ @shepherd, yep, you only add 1 armature object to the scene and then you add bones to it in edit-mode (Tab). You can extrude a bone from a joint with E or add a new bone to 3D cursor location with Shift-A. This way you end only with 1 object with multiple bones inside.) If you have multiple armatures you can fix it with selecting them and joining them into one with Ctrl-J $\endgroup$ Commented May 16, 2015 at 18:37
  • $\begingroup$ Thank you very much again. I've been using these steps manually but now I need a script as I have many files. I've followed the answer below given by batFINGER and constructed the armature found here dropbox.com/s/nx8xsk4z0pavaxx/ArmatureToTpose.blend?dl=0 then I try to put the armature in Tpose to parent to my mesh with automatic weighting using the batFINGER's answer found here blender.stackexchange.com/a/53981/2517 you will find that the mesh is doesn't look good, kinda twisted and during the animation it get's ugly, I'm not sure why? is it because of the bone roll value? $\endgroup$
    – Tak
    Commented Nov 19, 2016 at 9:31
  • $\begingroup$ so as you suggested, I've used DAMPED_TRACK instead of TRACK_TO used by batFINGER. And the mesh still looks bad using con = pb.constraints.new('DAMPED_TRACK') con.target = bpy.data.objects.get(pb.name) con.track_axis = 'TRACK_Y' con.influence = 1 $\endgroup$
    – Tak
    Commented Nov 19, 2016 at 9:33
1
$\begingroup$

Created a script to create a hierarchal armature and add constraints to animate.

enter image description here

Firstly import the c3d with a prefix, I've chosen "GT_", this makes it easier to clean up.

import bpy
context = bpy.context
scene = context.scene
prefix = "GT_"
# select all imported with prefix GT_
obs = [o for o in scene.objects if o.name.startswith(prefix)]
root = "RootDog"

# clean up unwanted objects could look for flat action sum.

text = bpy.data.texts.get("C3D_bones")
if not text:
    text = bpy.data.texts.new("C3D_bones")

text.clear()

bones = {}    
for o in obs:
    if o.location.length < 0.0000001:
        scene.objects.unlink(o)
        bpy.data.objects.remove(o)
    else:
        name = o.name[3:]
        print(bones)
        bones[name] = {"parent":None,
                       "tail":root}

names = sorted(bones.keys())
text.write("%s\n" % root)
for name in names: 
    if name == root:
        continue    
    text.write("\t%s\n" % name)   

It creates a text object with a simple structure. Tabs must be used to indent. Like

RootDog
    LBackElbow
    LBackLeg
    LBackPaw

Which was quite simple to edit into, and I renamed to "C3DBones.txt" to avoid overwriting with previous script.

RootDog
    RFrontWaistDog
        RBackWaistDog
            RBackElbow
                RBackLeg
                    RBackPaw
    LFrontWaistDog
        LBackWaistDog
            LBackElbow
                LBackLeg
                    LBackPaw
    LowBackDog
        MidbackDog
            TopSpineDog
                RFShoulderDog
                    RElbowDog
                        RForeLeg
                            RPaw
                LFhoulderDog
                    LElbowDog
                        LForeLeg
                            LPaw                    
                MidDoghead
                    LeftDogHead
                    RightDogHead

Lastly, the hierarchy is used to create a rig and add constraints.

import bpy
from mathutils import Vector
context = bpy.context
scene = context.scene

text = bpy.data.texts.get("C3D_bones.txt")
prefix = "GT_"
parent_level = 0
parents = [None] * 16


arm = bpy.data.armatures.new("Armature")

rig = bpy.data.objects.new("C3DRig", arm)
scene.objects.link(rig)
scene.objects.active = rig
scene.update()
bpy.ops.object.mode_set(mode='EDIT')

for l in text.lines:

    body = l.body
    level = 0
    while body.startswith("\t"):
        body = body[1:]
        level += 1
    print(l.body, level)
    body = "%s%s" % (prefix, body)
    bone = arm.edit_bones.new(body)

    o = scene.objects.get(body)
    if not o:
        print("No %s" % body)
        continue

    bone.tail = o.location
    parent_level = max(level-1, 0)
    parents[level] = o
    parent = parents[parent_level]

    bone.parent = arm.edit_bones.get(parent.name)
    if bone.parent:
        bone.head = bone.parent.tail

bone = arm.edit_bones.get(parents[0].name)
if bone:    
    bone.head = bone.tail + Vector([0, 0, 1])
    bpy.ops.object.mode_set(mode='OBJECT')
else:
    print("no root bone")    

# do something with pose bones

for pb in rig.pose.bones:
    con = pb.constraints.new('COPY_LOCATION')
    if not pb.parent:
        con.target = bpy.data.objects.get(pb.name) 
        continue

    con.target = bpy.data.objects.get(pb.parent.name)
    con = pb.constraints.new('TRACK_TO')
    con.target = bpy.data.objects.get(pb.name)

$\endgroup$
7
  • $\begingroup$ Thanks for that. Could you send me a link of the blend file please? $\endgroup$
    – Tak
    Commented Mar 23, 2016 at 2:25
  • 1
    $\begingroup$ Done, note it only creates a rig and animates it off the c3d empties. Connect bones where desired and add limit rot constraints etc to fix bone roll, or use the methods suggested by @Jerryno. Also the root bone loc is kinda crap. Might need to add a constrained empty half way between the waists and use that instead of RootDog. Once that is done I'd pose into a rest position, and change to this rest pos. (currently has the rest pose of the pose of the frame on which the 2nd script is run) $\endgroup$
    – batFINGER
    Commented Mar 23, 2016 at 3:52
  • 1
    $\begingroup$ Sample with tween waist empty as root. pasteall.org/blend/41189 $\endgroup$
    – batFINGER
    Commented Mar 23, 2016 at 5:59
  • $\begingroup$ Is it possible to make the constructed root bone very small so it's not visible? I've tried doing this from the 3d view and it looks like this can be done by going to editmode then selecting the tail of it and then translating it by -1 along the Z-axis. $\endgroup$
    – Tak
    Commented Nov 14, 2016 at 11:58
  • $\begingroup$ I was able to solve it using context.object.data.edit_bones[0].select_head = True then bpy.ops.transform.translate(value=(0, 0, -0.99), constraint_axis=(False, False, True), constraint_orientation='GLOBAL', mirror=False, proportional='DISABLED', proportional_edit_falloff='SMOOTH', proportional_size=1) {'FINISHED'} $\endgroup$
    – Tak
    Commented Nov 14, 2016 at 12:42

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .