SmartBody, first steps



SmartBody is a character animation platform originally developed at the University of Southern California Institute for Creative Technologies. SmartBody provides locomotion, steering, object manipulation, lip syncing, gazing and nonverbal behavior in real time.
SmartBody is written in C++ and can be incorporated into most game and simulation engines. SmartBody is a Behavioral Markup Language (BML) realization engine that transforms BML behavior descriptions into realtime animations. SmartBody runs on Windows, Linux, OSx as well as the iPhone and Android devices.

I want to use this to control the character animations for a video game made in Unity3D.

 The package does say this it can work with

  • Unity
  • Ogre
  • Unreal
  • Panda3D
  • GameBryo
However it supports Unity and Ogre actively. 

Goal: To send BML messages to a control characters in SmartBody via TCP or UDP messages.

Tasks:
  1. Get and Compile SmartBody ( For Windows and Linux )
  2. Familiarize self with SmartBody examples
  3. Learn how to use TCP in Python.
  4. Produce code to control SmartBody character from python code combining what was learned from 2 and 3.



    import random

    import select
    import socket
    import sys

    service = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

    # Connect the socket to the port where the server is listening
    server_address = ('localhost', 3850)
    print >> sys.stderr, 'connecting to %s port %s' % server_address
    service.connect(server_address)


    print "|--------------------------------------------|"
    print "|       Starting Locomotion Type Demo        |"
    print "|--------------------------------------------|"

    smartBodyRelitivePath = "../../smartbody/data/"

    # Add asset paths
    scene.addAssetPath('script',smartBodyRelitivePath + 'sbm-common/scripts')
    scene.addAssetPath('mesh', smartBodyRelitivePath + 'mesh')
    scene.addAssetPath('mesh', smartBodyRelitivePath + 'retarget/mesh')
    scene.addAssetPath('motion', smartBodyRelitivePath + 'ChrBrad')
    scene.addAssetPath('motion', smartBodyRelitivePath + 'ChrRachel')
    scene.addAssetPath('motion', smartBodyRelitivePath + 'retarget\motion')
    scene.addAssetPath('motion', smartBodyRelitivePath + 'sbm-common/common-sk')
    scene.loadAssets()


    # Set scene parameters and camera
    print 'Configuring scene parameters and camera'
    scene.setScale(1.0)
    scene.setBoolAttribute('internalAudio', True)
    scene.run('default-viewer.py')
    camera = getCamera()
    camera.setEye(0, 2.87, 11.67)
    camera.setCenter(0, 2.14, 9.81)
    camera.setUpVector(SrVec(0, 1, 0))
    camera.setScale(1)
    camera.setFov(1.0472)
    camera.setFarPlane(100)
    camera.setNearPlane(0.1)
    camera.setAspectRatio(0.966897)
    scene.getPawn('camera').setPosition(SrVec(0, -5, 0))

    # Set joint map for Brad
    print 'Setting up joint map for Brad'
    scene.run('zebra2-map.py')
    zebra2Map = scene.getJointMapManager().getJointMap('zebra2')
    bradSkeleton = scene.getSkeleton('ChrBrad.sk')
    zebra2Map.applySkeleton(bradSkeleton)
    zebra2Map.applyMotionRecurse('ChrBrad')

    # Retarget setup
    scene.run('motion-retarget.py')
    # Animation setup
    scene.run('init-param-animation.py')

    # Set up 3 Brads
    print 'Adding characters into scene'
    posX = -200
    for i in range(1): # Only add one brad
        baseName = 'ChrBrad%s' % i
        brad = scene.createCharacter(baseName, '')
        bradSkeleton = scene.createSkeleton('ChrBrad.sk')
        brad.setSkeleton(bradSkeleton)
        # Set position
        bradPos = SrVec((posX + (i * 200))/100, 0, 0)
        brad.setPosition(bradPos)
        # Set up standard controllers
        brad.createStandardControllers()
        # Set deformable mesh
        brad.setDoubleAttribute('deformableMeshScale', .01)
        brad.setStringAttribute('deformableMesh', 'ChrBrad')
        # Play idle animation
        bml.execBML(baseName, '')
        # Retarget character
        retargetCharacter(baseName, 'ChrBrad.sk', False)

    # Turn on GPU deformable geometry for all
    for name in scene.getCharacterNames():
        scene.command("char %s viewer deformableGPU" % name)

    # Whether character has reached its target
    brad1Reached = True

    # Paths for characters
    brad1Path = [SrVec(-2, 8, 0), SrVec(-2, -8, 0)]

    bradCur = 0
    pathAmt = 2


    class LocomotionDemo(SBScript):
        def update(self, time):
            # Select is a creative way of checking to see if a service has data ready to read,
            # ready to write to or an exceptional condition.
            r, w, e = select.select([service], [], [], 0.0)
            if r: # There is something to read
                data = service.recv(256)
                character = 'ChrBrad0'
                # The last 0 in the target is zero just so the character stays on the plane
                bmlMessage = ''
               
                print "BML Message for " + character + ": " + bmlMessage
                bml.execBML(character, bmlMessage)
           

    # Run the update script
    scene.removeScript('locomotiondemo')
    locomotiondemo = LocomotionDemo()
    scene.addScript('locomotiondemo', locomotiondemo)