Humanoid Animation Working Group

Specification for a Standard Humanoid

Version 1.1
The Nodes
Modeling the Humanoid
The Joint Hierarchy
Viewpoints and Navigation
Suggested Practices
Appendix A: Body Dimensions and Levels of Articulation 
Appendix B: Displacer Nodes 
Appendix C: Feature Points for the Human Body 


As the 3D Internet continues to grow, there will be an increasing need to represent human beings in online virtual environments. Achieving that goal will require the creation of libraries of interchangeable humanoids, as well as authoring tools that make it easy to create new humanoids and animate them in various ways.

This document specifies a standard way of representing humanoids in VRML97. This standard will allow humanoids created using authoring tools from one vendor to be animated using tools from another. H-Anim humanoids can be animated using keyframing, inverse kinematics, performance animation systems and other techniques.

Our design goals are as follows:

Much of the design is driven by these three goals. The compatibility requirement has led us to avoid the use of scripting, since the VRML97 specification does not require any particular scripting language to be implemented. The flexibility requirement has led us to make the spec fairly "low-level", in that it allows direct access to the joints of the humanoid's body and the vertices of the individual body segments. The simplicity requirement has led us to focus specifically on humanoids, instead of trying to deal with arbitrary articulated figures.

A. Overview

The human body consists of a number of segments (such as the forearm, hand and foot) which are connected to each other by joints (such as the elbow, wrist and ankle). In order for an application to animate a humanoid, it needs to obtain access to the joints and alter the joint angles. The application may also need to retrieve information about such things as joint limits and segment masses.

Each segment of the body will typically be defined by a mesh of polygons, and an application may need to alter the locations of the vertices in that mesh. The application may also need to obtain information about which vertices should be treated as a group for the purpose of deformation.

An H-Anim file contains a set of Joint nodes that are arranged to form a hierarchy. Each Joint node can contain other Joint nodes, and may also contain a Segment node which describes the body part associated with that joint. Each Segment can also have a number of Site nodes, which define locations relative to the segment. Sites can be used for attaching clothing and jewelry, and can be used as end-effectors for inverse kinematics applications. They can also be used to define eyepoints and viewpoint locations.

Each Segment node can have a number of Displacer nodes, that specify which vertices within the segment correpond to a particular feature or configuration of vertices.

The file also contains a single Humanoid node which stores human-readable data about the humanoid such as author and copyright information. That node also stores references to all the Joint, Segment and Site nodes, and serves as a "wrapper" for the humanoid. In addition, it provides a top-level Transform for positioning the humanoid in its environment.

B. The Nodes

In order to simplify the creation of humanoids, several new node types are introduced. Each node is defined by a PROTO. The basic implementation of all the nodes is very straightforward, yet each provides enough flexibility to allow more advanced techniques to be used.

1. The Joint Node

Each joint in the body is represented by a Joint node, which is used to define the relationship of each body segment to its immediate parent.

A Joint may only be a child of another Joint node or a child within the humanoidBody field in the case of the humanoidRoot Joint (i.e. a Joint may not be a child of a Segment).

The Joint node is also used to store other joint-specific information. In particular, a joint name is provided so that applications can identify each Joint node at runtime. The Joint node may contain hints for inverse-kinematics systems that wish to control the H-Anim figure. These hints include the upper and lower joint limits, the orientation of the joint limits, and a stiffness/resistance value. Note that these limits are not enforced by any mechanism within the scene graph of the humanoid, and are provided for information purposes only. Use of this information and enforcement of the joint limits is up to the application.

The Joint PROTO looks like this:

PROTO Joint [
    exposedField     SFVec3f      center              0 0 0
    exposedField     MFNode       children            []
    exposedField     MFFloat      llimit              []
    exposedField     SFRotation   limitOrientation    0 0 1 0
    exposedField     SFString     name                ""
    exposedField     SFRotation   rotation            0 0 1 0
    exposedField     SFVec3f      scale               1 1 1
    exposedField     SFRotation   scaleOrientation    0 0 1 0
    exposedField     MFFloat      stiffness           [ 0 0 0 ]
    exposedField     SFVec3f      translation         0 0 0
    exposedField     MFFloat      ulimit              []
Notice that most of the fields correspond to those of the Transform node. This is because the typical implementation of the Joint PROTO will be:
    Transform {
        center           IS center
        children         IS children
        rotation         IS rotation
        scale            IS scale
        scaleOrientation IS scaleOrientation
        translation      IS translation
Other implementations are certainly possible. The only requirement is that a Joint be able to accept the events listed above. Humanoid authors and tools are free to implement the Joint node however they choose. In particular, they may choose to use a single polygonal mesh to represent a humanoid, rather than having a separate IndexedFaceSet for each body segment. In such a case, a Joint would be responsible for moving the vertices that correspond to a particular body segment and all the segments descended from it.

The center exposedField gives the position of the Joint's center of rotation, relative to the root of the overall humanoid body description. Note that the center field is not intended to receive events. The locations of the joint centers are available by reading the center fields of the Joints (see Modeling the Humanoid for details).

Since the locations of the joint centers are all in the same coordinate frame, the length of any segment can be determined by calculating the distance between the parent's Joint center and the child's Joint center. The exception will be segments at the ends of the fingers and toes, for which the end effector Site locations within the Segment must be used (see the description of Sites below for details).

The ulimit and llimit fields of the Joint PROTO specify the upper and lower joint rotation limits. Both fields are three-element MFFloats containing separate values for the X, Y and Z rotation limits. The ulimit field stores the upper (i.e. maximum) values for rotation around the X, Y and Z axes. The llimit field stores the lower (i.e. minimum) values for rotation around those axes. Note that the default values for each of these fields is [], which means that the joint is assumed to be unconstrained.

The limitOrientation exposedField gives the orientation of the coordinate frame in which the ulimit and llimit values are to be interpreted. The limitOrientation describes the orientation of a local coordinate frame, relative to the Joint center position described by the center exposedField.

The stiffness exposedField, if present, contains values ranging between 0.0 and 1.0 which give the inverse kinematics system hints about the "willingness" of a joint to move in a particular degree of freedom. For example, a Joint node's stiffness can be used in an arm joint chain to give preference to moving the left wrist and left elbow over moving the left shoulder, or it can be used within a single Joint node with multiple degrees of freedom to give preference to individual degrees of freedom. The larger the stiffness value, the more the joint will resist movement in the corresponding axis (X, Y, or Z for entries 0, 1 and 2 of the stiffness MFFloat field).

Each Joint should have a DEF name that matches the name field for that Joint, but with a distinguishing prefix in front of it. That prefix can be anything, but must be the same for all the Joints in a particular humanoid. The distinguishing prefix is useful in the case of static routing to the Joints of multiple humanoids in the same file. If only a single humanoid is stored in a file, the prefix should be "hanim_" (for Humanoid Animation). For example, the left shoulder would have a DEF name of "hanim_l_shoulder".

The DEF name is used for static routing, which would typically connect OrientationInterpolators in the humanoid file to the joints. The name field is used for identifying the joints at runtime, since a DEF name would not necessarily be available. The name field must be present, so that applications are able to identify the Joint at runtime. All the other fields are optional.

It will occasionally be useful for the person creating a humanoid to be able to add additional joints to the body. The body remains humanoid in form, and is still generally expected to have the basic joints described later in this document. However, they may be thought of as a minimal set to which extensions may be added (such as a prehensile tail). See the section on Non-standard Joints and Segments. If necessary, some of the joints (such as the many vertebrae) may be omitted. See Appendix A for details.

2. The Segment Node

Each body segment is stored in a Segment node. The Segment node will typically be implemented as a Group node, which would contain either a number of Shapes or perhaps Transform nodes that position the body part within its coordinate system (see Modeling the Humanoid for details). The use of LOD nodes is recommended if the geometry of the Segment is complex.
PROTO Segment [
    field           SFVec3f     bboxCenter        0 0 0
    field           SFVec3f     bboxSize          -1 -1 -1
    exposedField    SFVec3f     centerOfMass      0 0 0
    exposedField    MFNode      children          [ ]
    exposedField    SFNode      coord             NULL
    exposedField    MFNode      displacers        [ ]
    exposedField    SFFloat     mass              0 
    exposedField    MFFloat     momentsOfInertia  [ 0 0 0 0 0 0 0 0 0 ]
    exposedField    SFString    name              ""
    eventIn         MFNode      addChildren
    eventIn         MFNode      removeChildren
This will typically be implemented as follows:
    Group {
        addChildren    IS addChildren
        bboxCenter     IS bboxCenter
        bboxSize       IS bboxSize
        children       IS children
        removeChildren IS removeChildren
The name must be present, so that the Segment can be identified at runtime. All the other fields are optional.

The mass is the total mass of the segment, and the centerOfMass is the location within the segment of its center of mass. Note that a zero value was chosen for the mass in order to give a clear indication that no mass value is available. The momentsOfInertia field contains the moment of inertia matrix. The first three elements are the first row of the 3x3 matrix, the next three elements are the second row, and the final three elements are the third row.

Humanoids that are modeled as a continuous mesh will still have Segment nodes, in order to store per-segment information. In such a case, the Segment wouldn't necessarily contain any geometry, though it should still be a child of a Joint node.

For Segments that have deformable meshes, the coord field should contain a Coordinate node that is USEd in the IndexedFaceSet for the Segment. The Coordinate node should be given the same name DEF name as the Segment, but with a "_coords" appended (e.g. "skull_coords").

3. The Site Node

A Site node serves three purposes. The first is to define an "end effector" location which can be used by an inverse kinematics system. The second is to define an attachment point for accessories such as jewelry and clothing. The third is to define a location for a virtual camera in the reference frame of a Segment (such as a view "through the eyes" of the humanoid for use in multi-user worlds).

Sites are stored within the children exposedField of a Segment node. The rotation and translation fields of the Site node define the location and orientation of the end effector within the coordinate frame of the Segment. The children field is used to store any accessories that can be attached to the segment.

The Site PROTO looks like this:

PROTO Site [
    exposedField    SFVec3f     center           0 0 0
    exposedField    MFNode      children         []
    exposedField    SFString    name             ""
    exposedField    SFRotation  rotation         0 0 1 0
    exposedField    SFVec3f     scale            1 1 1
    exposedField    SFRotation  scaleOrientation 0 0 1 0
    exposedField    SFVec3f     translation      0 0 0
    eventIn         MFNode      addChildren 
    eventIn         MFNode      removeChildren
The typical implementation for a Site will be:
    Transform {
        addChildren      IS addChildren
        center           IS center 
        children         IS children
        removeChildren   IS removeChildren
        rotation         IS rotation
        scale            IS scale
        scaleOrientation IS scaleOrientation
        translation      IS translation
The name must be present, so that the Site can be identified at runtime. All the other fields are optional.

If used as an end effector, the Site node should have a name consisting of the name of the Segment to which it's attached, with a "_tip" suffix appended. For example, the end effector Site on the right index finger would be named "r_index_distal_tip", and the Site node would be a child of the "r_index_distal" Segment. Sites that are used to define camera locations should have a "_view" suffix appended. Sites that are not end effectors and not camera locations should have a "_pt" suffix. Sites that are required by an application but are not defined in this specification should be prefixed with "x_".

Sites that are intended to be used as attachment points for Viewpoint nodes (such as the left and right eyes) should be oriented so that they face in the direction the camera should be looking. In other words, attaching the following Viewpoint to the Site at the left eye will result in a view looking out from the humanoid's left eye:

Viewpoint {
    position 0 0 0
Note that the default position for the Viewpoint node is 0 0 10, and the default orientation is 0 0 1 0, which is why Viewpoints that are attached to Sites must specify non-default values.

A list of recommended Sites can be found in Appendix A along with the body dimensions and levels of articulation.

4. The Displacer Node

Applications may need to alter the shape of individual Segments. At the most basic level, this is done by writing to the point field of the Coordinate node that's found in the coord field of the Segment node.

In some cases, the application may need to be able to identify specific groups of vertices within a Segment. For example, the application may need to know which vertices within the skull Segment comprise the left eyebrow. It may also require "hints" as to the direction in which each vertex should move. That information is stored in a node called a Displacer. The Displacers for a particular Segment are stored in the displacers field of that Segment.

The Displacer PROTO looks like this:

PROTO Displacer [
    exposedField MFInt32  coordIndex     [ ]
    exposedField MFVec3f  displacements  [ ]
    exposedField SFString name           ""
The name field provides a name for the Displacer, by which it can be identified by an application at runtime. That name should also be used as the DEF name of the Displacer node itself. The name field must be present, so that the Displacer can be identified at runtime. All the other fields are optional.

The coordIndex field contains the indices into the coordinate array for the Segment of the vertices that are affected by the displacer. For example,

Displacer {
    coordIndex [ 7, 12, 21, 18 ]
    name "l_eyebrow_feature"
would mean that vertices 7, 12, 21 and 18 of the Segment form the left eyebrow.

The displacements field, if present, provides a set of 3D values that should be added to the neutral or resting position of each of the vertices referenced in the coordIndex field of the Segment. These values correspond one to one with the values in the coordIndex array. The values should be maximum displacements, and the application is free to scale them as needed before adding them to the neutral vertex positions. For example,

Displacer {
    coordIndex [ 7, 12, 21, 18 ]
    displacements [ 0 0.0025 0, 0 0.005 0, 0 0.0025 0, 0 0.001 0 ]
    name "l_eyebrow_raiser_action"
would raise the four vertices of the left eyebrow in a vertical direction. Vertex number 7 would be displaced up to 2.5 millimeters in the vertical (Y) direction, vertex number 12 would be displaced up to 5 millimeters, vertex 21 would be displaced up to 2.5 millimeters, and vertex number 18 would be displaced by just one millimeter. The application may choose to uniformly scale those displacements.

A Displacer can be used in three different ways. At its most basic level, it can simply be used to identify the vertices corresponding to a particular feature on the Segment, which the application can then displace as it sees fit. At the next level, it can be used to represent a particular muscular action which displaces the vertices in various directions (linearly or radially).

The third way in which a Displacer can be used is to represent a complete configuration of the vertices in a Segment. For example, in the case of a face, there might be a Displacer for each facial expression.

Displacers that are used to identify features should have a name with a "_feature" suffix. Displacers that are used to move a feature should be given a name with an "_action" suffix, usually with an additional pre-suffix to indicate the kind of motion (such as "l_eyebrow_raiser_action"). Displacers that correspond to a particular configuration of the vertices should have a "_config" suffix.

Note that while Displacers are most often used to control the shape of the face, they can certainly be used for other body parts as well. For example, they may be used to control the changing shape of an arm Segment as the arm flexes, simulating the effect of muscle inflation.

A basic list of suggested Displacers is given in Appendix B.

5. The Humanoid Node

The Humanoid node is used to store human-readable data such as author and copyright information, as well as to store references to the joints, segments and views and to serve as a container for the entire humanoid. It also provides a convenient way of moving the humanoid through its environment.
PROTO Humanoid [
    field           SFVec3f    bboxCenter            0 0 0
    field           SFVec3f    bboxSize              -1 -1 -1
    exposedField    SFVec3f    center                0 0 0
    exposedField    MFNode     humanoidBody          [ ]
    exposedField    MFString   info                  [ ]
    exposedField    MFNode     joints                [ ]
    exposedField    SFString   name                  ""
    exposedField    SFRotation rotation              0 0 1 0
    exposedField    SFVec3f    scale                 1 1 1
    exposedField    SFRotation scaleOrientation      0 0 1 0
    exposedField    MFNode     segments              [ ]
    exposedField    MFNode     sites                 [ ]
    exposedField    SFVec3f    translation           0 0 0
    exposedField    SFString   version               "1.1"
    exposedField    MFNode     viewpoints            [ ]
The Humanoid node is typically implemented as follows:
  Transform {
    bboxCenter       IS bboxCenter
    bboxSize         IS bboxSize
    center           IS center
    rotation         IS rotation
    scale            IS scale
    scaleOrientation IS scaleOrientation
    translation      IS translation
    children [
      Group {
        children IS viewpoints
      Group {
        children IS humanoidBody 
The name field must be present, so that the Humanoid can be identified at runtime. All the other fields are optional.

The Humanoid node can be used to position the humanoid in space. Note that the HumanoidRoot Joint is typically used to handle animations within the local coordinate system of the humanoid, such as jumping or walking. For example, while walking, the overall movement of the body (such as a swagger) would affect the HumanoidRoot Joint, while the average linear velocity through the scene would affect the Humanoid node.

The humanoidBody field contains the HumanoidRoot node.

The version field stores the version of this specification that the Humanoid file conforms to. The document you're now reading describes version "1.1" of the specification.

The info field consists of an array of strings, each of which is of the form "tag=value". The following tags are defined so far:

Additional tag=value pairs can be included as needed.

The humanoidVersion tag refers to the version of the humanoid being used, in order to track revisions to the data. It is not the same as the version field of the Humanoid node, which refers to the version of the H-Anim specification which was used when building the humanoid.

The joints field contains references (i.e. USEs) of each of the Joint nodes in the body. Each of the referenced joints should be a Joint node. The order in which they are listed is irrelevant, since the names of the joints are stored in the joints themselves. Similarly, the segments field contains references to each of the Segment nodes of the body, the viewpoints field contains references to the Viewpoint nodes in the file, and the sites field contains references to the Site nodes in the file.

The Humanoid node should be given a DEF name of "Humanoid", in order to make it easy to access using the External Authoring Interface.

C. Modeling the Humanoid

The humanoid should be modeled in a standing position, facing in the +Z direction with +Y up and +X to the humanoid's left. The origin (0, 0, 0) should be located at ground level, between the humanoid's feet.

The feet should be flat on the ground, spaced apart about the same distance as the width of the hips. The bottom of the feet should be at Y=0. The arms should be straight and parallel to the sides of the body with the palms of the hands facing inwards towards the thighs. The hands should be flat, with the axes of joints "1" through "3" of the fingers being parallel to the Y axis and the axis of the thumb being angled up at 45 degrees towards the +Z direction. Note that the coordinate system for each joint in the thumb is still oriented to align with that of the overall humanoid.

Movement of the "0" joints of the fingers is typically quite limited, and the rigidity of those articulations varies from finger to finger. Further details about the placement, orientation and movement of the "0" joints can be obtained from any anatomy reference text.

The face should be modeled with the eyebrows at rest, the mouth closed and the eyes wide open.

The humanoid should be built with actual human size ranges in mind. All dimensions are in meters. A typical human is roughly 1.75 meters tall.

This is the default position of the humanoid:

(illustration courtesy of the SNHC group)
(note that in the diagram above, the thumb is shown in a slightly different position than required by this specification)

In this position, all the joint angles should be zero. In other words, all the rotation fields in all the Joint nodes should be left at their default value of (0 0 1 0). In addition, the translation fields should be left at their default value of (0 0 0) and the scale factors should be left at their default value of (1 1 1). The only field which should have a non-default value is center, which is used to specify the point around which the joint (and its attached children and body segment if any) will rotate. Sending the default values for translation, rotation and scaling to all the Joints in the body must return the body to the neutral position described above.

The center field of each joint should be placed so that the joints rotate in the same way that they would on a real human body.

The following diagram shows the orientation of the hand. The crosshairs simply suggest possible locations for the joint centers and finger tips.

It is suggested, but not required, that all of the body segments should be built in place. That is, they should require no translation, rotation, or scaling to be connected with their neighbors. For example, the hand should be built so that it's in the correct position in relation to the forearm. The forearm should be built so that it's in the correct position in relation to the upper arm, and so on. All the body's coordinates will share a common origin, which is that of the humanoid itself. If this proves difficult for an authoring tool to implement, it is acceptable to use a Transform node inside each Segment, or even several Transforms, in order to position the geometry for that segment correctly.

Note that the coordinate system for each Joint is oriented to align with that of the overall humanoid.

D. The Joint Hierarchy

The body is typically built as a series of nested Joints, each of which may have a Segment associated with it. For example:
DEF hanim_l_shoulder Joint {  name "l_shoulder"
  center 0.167 1.36 -0.0518
  children    [
    DEF hanim_l_elbow Joint {  name "l_elbow"
      center 0.196 1.07 -0.0518
      children        [
        DEF hanim_l_wrist Joint {  name "l_wrist"
          center 0.213 0.811 -0.0338
          children    [
            DEF hanim_l_hand Segment {  name "l_hand"
        DEF hanim_l_forearm Segment {  name "l_forearm"
    DEF hanim_l_upperarm Segment {  name "l_upperarm"
Sample humanoids in the correct format are available from the H-Anim web site (

1. The Body

The names of the Joint nodes for the body are listed in the following table:
l_hip l_knee l_ankle l_subtalar l_midtarsal l_metatarsal
r_hip r_knee r_ankle r_subtalar r_midtarsal r_metatarsal
vl5 vl4 vl3 vl2 vl1
vt12 vt11 vt10 vt9 vt8 vt7
vt6 vt5 vt4 vt3 vt2 vt1
vc7 vc6 vc5 vc4 vc3 vc2 vc1
l_sternoclavicular l_acromioclavicular l_shoulder l_elbow l_wrist
r_sternoclavicular r_acromioclavicular r_shoulder r_elbow r_wrist
HumanoidRoot sacroiliac (pelvis) skullbase

The vl5 and sacroiliac Joints are children of the HumanoidRoot. The HumanoidRoot is stored in the humanoidBody field of the Humanoid node, but all other Joints are descended from either vl5 or sacroiliac. If those Joints are missing, lower-level Joints can be children of the HumanoidRoot.

2. The Hands

The hands, if present, should use the following naming convention:
l_pinky0 l_pinky1 l_pinky2 l_pinky3 l_ring0 l_ring1 l_ring2 l_ring3
l_middle0 l_middle1 l_middle2 l_middle3 l_index0 l_index1 l_index2 l_index3
l_thumb1 l_thumb2 l_thumb3
r_pinky0 r_pinky1 r_pinky2 r_pinky3 r_ring0 r_ring1 r_ring2 r_ring3
r_middle0 r_middle1 r_middle2 r_middle3 r_index0 r_index1 r_index2 r_index3
r_thumb1 r_thumb2 r_thumb3

3. The Face

Many humanoid implementations have made use of jointed facial structures to simulate facial expression. These work in a fashion similar to the facial parts of a ventriloquist's dummy. The following is a basic set of facial joints and segments that support this type of facial animation.

The suffix "_joint" is used here because in reality most of these features are controlled by muscle groups instead of actual joints, the exception being the temporomandibular joint. The "_joint" suffix provides a distinction between the joint name and the name of the corresponding segment.

All facial joints are children of the skullbase joint. The center of rotation of the eye and the eyelid is the geometric center of the eyeball. The eyelid rotation defaults to zero, and a positive rotation of PI radians will completely close the eyelid. The eyebrows are at zero degrees rotation by default, and can be rotated around the middle of the eyebrow. The mouth is closed when the temporomandibular joint is at zero degrees.

l_eyeball_joint r_eyeball_joint
l_eyebrow_joint r_eyebrow_joint
l_eyelid_joint r_eyelid_joint
It's possible that additional facial joints may be required. See the section on Non-standard Joints and Segments. It is strongly recommended that these joints be identified as early in the project as possible, and be used in the construction of all the humanoids used in the project.

4. Hierarchy

The complete hierarchy is as follows, with the segment names listed beside the joints to which they're attached:
HumanoidRoot : sacrum
  sacroiliac : pelvis
  |   l_hip : l_thigh
  |     l_knee : l_calf
  |       l_ankle : l_hindfoot
  |         l_subtalar : l_midproximal
  |           l_midtarsal : l_middistal
  |             l_metatarsal : l_forefoot
  |   r_hip : r_thigh
  |     r_knee : r_calf
  |       r_ankle : r_hindfoot
  |         r_subtalar :  r_midproximal
  |           r_midtarsal : r_middistal
  |             r_metatarsal : r_forefoot
  vl5  : l5
    vl4 : l4
      vl3  : l3
        vl2 : l2
          vl1  : l1
            vt12 : t12
              vt11 : t11
                vt10  : t10
                  vt9 : t9
                    vt8 : t8
                      vt7 : t7
                        vt6  : t6
                          vt5 : t5
                            vt4 : t4
                              vt3 : t3
                                vt2 : t2
                                  vt1  : t1
                                    vc7 : c7
                                    | vc6 : c6
                                    |   vc5 : c5
                                    |     vc4  : c4
                                    |       vc3 : c3
                                    |         vc2  : c2
                                    |           vc1 : c1
                                    |             skullbase : skull
                                    |               l_eyelid_joint : l_eyelid
                                    |               r_eyelid_joint : r_eyelid
                                    |               l_eyeball_joint : l_eyeball
                                    |               r_eyeball_joint : r_eyeball
                                    |               l_eyebrow_joint : l_eyebrow
                                    |               r_eyebrow_joint : r_eyebrow
                                    |               temporomandibular : jaw 
                                    l_sternoclavicular : l_clavicle
                                    | l_acromioclavicular : l_scapula
                                    |   l_shoulder : l_upperarm
                                    |     l_elbow : l_forearm
                                    |       l_wrist : l_hand
                                    |         l_thumb1 : l_thumb_metacarpal
                                    |           l_thumb2 : l_thumb_proximal
                                    |               l_thumb3 : l_thumb_distal
                                    |         l_index0 : l_index_metacarpal
                                    |           l_index1 : l_index_proximal
                                    |             l_index2 : l_index_middle
                                    |                 l_index3 : l_index_distal
                                    |         l_middle0 : l_middle_metacarpal
                                    |           l_middle1 : l_middle_proximal
                                    |             l_middle2 : l_middle_middle
                                    |               l_middle3 : l_middle_distal
                                    |         l_ring0 : l_ring_metacarpal
                                    |           l_ring1 : l_ring_proximal
                                    |             l_ring2 l_ring_middle
                                    |               l_ring3 : l_ring_distal
                                    |         l_pinky0 : l_pinky_metacarpal
                                    |           l_pinky1 : l_pinky_proximal
                                    |             l_pinky2 : l_pinky_middle
                                    |               l_pinky3 : l_pinky_distal
                                    r_sternoclavicular : r_clavicle
                                      r_acromioclavicular : r_scapula
                                        r_shoulder : r_upperarm
                                          r_elbow : r_forearm
                                            r_wrist : r_hand
                                              r_thumb1 : r_thumb_metacarpal
                                                r_thumb2 : r_thumb_proximal
                                                  r_thumb3 : r_thumb_distal
                                              r_index0 : r_index_metacarpal
                                                r_index1 : r_index_proximal
                                                  r_index2 : r_index_middle
                                                    r_index3 : r_index_distal
                                              r_middle0 : r_middle_metacarpal
                                                r_middle1 : r_middle_proximal
                                                  r_middle2 : r_middle_middle
                                                    r_middle3 : r_middle_distal
                                              r_ring0 : r_ring_metacarpal
                                                r_ring1 : r_ring_proximal
                                                  r_ring2 : r_ring_middle
                                                    r_ring3 : r_ring_distal
                                              r_pinky0 : r_pinky_metacarpal
                                                r_pinky1 : r_pinky_proximal
                                                  r_pinky2 : r_pinky_middle
                                                    r_pinky3 : r_pinky_distal
A diagram has been prepared that illustrates the preceeding hierarchy.

5. Non-standard Joints and Segments

Additional non-standard joints and body segments may be defined. There are only three requirements. The first is that the joints listed in the tables above, if present, must use the specified names. The second is that no new joints are allowed within the "chain" of the standard Joint hierarchy. For example, an additional elbow cannot be added to the arm. However, new appendages (such as hair, tails, etc.) can be added to a humanoid by creating new joints which exist as children of other joints. These non-standard joints may be children of either standard joints or other non-standard joints. The third requirement is that these non-standard joints must be added in such as way as to not interfere with the movement of standard joints, even if no animation is available for them.

Animations for standard joints should not be dependent upon animations of any non-standard joints (or their children) that may be parented to them. Inverse kinematic systems may consider non-standard joints when performing calculations but are not required to do so.

Non-standard joints should be given the prefix "x_" (e.g. hanim_x_pigtails). to distinguish them from standard joints that may have similar names.

E. Viewpoints and Navigation

In order to make it easy for a humanoid to be examined in a VRML97 browser, several Viewpoints and a NavigationInfo node may be included in the file.

1. Viewpoints

Certain types of application may require particular views of the humanoid. There are two ways of doing this. The first is for the author of the humanoid to create Sites in suitable locations. An application can then create a Viewpoint node, and attach it to any of the Sites. This allows the Viewpoint to track the motion of the humanoid's body parts.

The other technique is to place actual Viewpoint nodes in the viewpoints field of the Humanoid node, which will create a view of the Humanoid that tracks its motion through space without being affected by the movement of any of the body's Segments. Viewpoints that are placed in that field will also be available whenever the humanoid is loaded into a browser, and are therefore useful for previewing the character.

There are several specific viewpoints that may be included in the file. The Front_view should face in the -Z direction, the Side_view should face in the -X direction, the Top_view should face in the -Y direction, the Inclined_view should face towards (-1 0 -1), and the Best_view can provide a view from any direction which best highlights an individual humanoid's unique characteristics. All these Sites should be displaced from the center of the humanoid by a sufficient distance to show the entire humanoid from that view.

Additional views are possible. All Viewpoints for a humanoid should be listed in the Humanoid node's viewpoints field. Using this convention, systems which use several models in the same scene may choose to disable all the extra viewpoints by sending an empty MFNode event into the humanoid's viewpoints field.

2. Navigation

A NavigationInfo node can be included at the top of the file to put the VRML97 browser into Examine mode. The type field should always include "EXAMINE" first and "ANY" second:
NavigationInfo { type ["EXAMINE", "ANY"] }
This makes it easy to examine the humanoid from all angles.

F. Suggested Practices

There are a number of issues surrounding the use of H-Anim Humanoids that are beyond the scope of this proposal.  However, some of those issues are worth addressing here. Note that these are suggested practices only, not a requirement of this specification.

1. Multiple Humanoids Per File

There are some cases in which it's useful to have multiple humanoids in the same file, perhaps alongside other elements of a 3D world. In such a case, it is recommended that the humanoids be assigned unique DEF names (rather than "DEF Humanoid") and that those names be referenced as the children of a Group node named "HumanoidGroup".

In other words,

DEF Fred Humanoid { ... }
DEF Jane Humanoid { ... }
DEF Sally Humanoid { ... }
DEF HumanoidGroup Group { children [ USE Fred, USE Jane, Use Sally ] }
An EAI-based application can obtain a reference to the HumanoidGroup for the scene, and by iterating over the children of that group it can obtain references to the individual humanoids.

2. Minimal Required Support

Not all applications which import virtual humans will necessarily be VRML97 browsers. However, any application that wishes to support the H-Anim specification is required to support at least the following nodes:
Transform Group Viewpoint
Shape Appearance Material
ImageTexture TextureTransform TextureCoordinate
Coordinate Color Normal
IndexedFaceSet IndexedLineSet Box
Cone Cylinder Sphere
NavigationInfo WorldInfo

All H-Anim applications must correctly parse the complete VRML97 utf8 encoded syntax for these nodes even if not all the functionality can be implemented. Applications which are unable to implement PROTOs must support the H-Anim nodes (Joint, Segment, Site, Displacer and Humanoid) as if they were built in.

This document can be found at
The appendices can be found at
The home page of the VRML Humanoid Animation Working Group is