Body Application


This page will tell you enough to go away and build the Body application. It describes the build and running of the clock application, and also gives an annotation of the code to explain how the application works.

You should compare and contrast this with the UCL Dive/Tcl animated body.


Build and Run

Build

Run

You have built a program called "bodydiva". This is a replacement for "diva", and you should use it exactly like diva. That is, if you make a symbollic link to it called "vishnu" then diva loads "vishnu_init.tcl" from the command line.

You will need an appropriate avatar that follows the conventions for animation. "ucl_virman_static.vr" is a simple avatar that can be animated by bodydiva. The body hierarchy is very simple, the head and animated arm objects are defined as direct descendants of "top", and the rest of the body is scaled to fit under the head.

The crucial lines in the body file are:

    prop "enable_body_limbs" TYPE_INT 7 GLOBAL_PROP
    prop "head_height"   TYPE_FLOAT HeadHeight  GLOBAL_PROP
    prop "total_height"  TYPE_FLOAT TotalHeight GLOBAL_PROP
    prop "arm_length"    TYPE_FLOAT ArmLength   GLOBAL_PROP
These define parameters that are passed to the animation routines.

The command line is thus:

vishnu -body ucl_virman_static.vr
Once the program is running, you (or other peopl) can pick up your hands and head to animate the body. If you were running with 3D tracker support on then the body would animate continuously.

Code

bodydiva.c is a very slight modification of diva.c. The only difference is the following line which we added just after the main initialisation phase (i.e. after all the modules are initialised and before the body is created). It registers the function "body_init" to be called when my own process creates an "ACTOR" object.
  callback_register_filter(ENTITY_NEW_EVENT, body_init, ACTOR_MASK,
			   NULL, NULL, CALLBACK_SENDER, NULL);

All the body animation code is contained in "bodyfunc.c". body_init is called from diva when the actor (and thus their avatar) have been created.

The phases for initialisation are:

  1. Do
      top_entity = find_assoc(actor_obj, "top");
    
    this gets us the top virtual object in the hiearchy of the avatar.
  2. This top object contain the properties that were noted above from ucl_virman_static. The main one (enable_body_limbs) tells us what limbs to animate. We retrieve it with this line:
      enable_body_limbs = (int *)property_get(top_entity, 
    					  enable_body_limbs_prop_id,
    					  GLOBAL_PROP);
    
  3. We then fetch the avatar height, head size, and arm length in a similiar manner.
  4. Next we pick out the objects to animate in 3 setts, animation of the head and body, animation of the left hand and animation of the right hand. Using head as an example:
  5. We do the same for the left and right hands.
  6. We return to Dive and wait for our limb movement callbacks head_move , righthand_move and lefthand_move. These do the animation of the body and arms whenever the dependent joints move. The important consideration are that we must determine current joint positions and be able to set new joint positions.

    To read:

      hand_pt = diveobj_T0(find_object(hand), time);
    

    To write:

      distr_abs_transform(upper, tmp_mx, &tmp_pt, WORLD_C, NULL, NULL);
    


Discussion

The animation is very crude, but works well for immersed participants where it is important that the animation results are returned instantly.

The supporting math libraries really should be tidied up, but you can of course use your own.

Compare this with the Tcl version. The two are very similar, except for in tcl the code is associated with the objects it animates directly. Thus there is not so much searching for objects (of course the searching only happens once).

This code is not checked for the situation where you change avatar during the dive session. If the code looks very long then bear in mind that 50% of it is error checking!


Anthony Steed, A.Steed@cs.ucl.ac.uk