
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:
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.
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.
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").
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.
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.
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:
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.
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:


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.
...
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 (http://H-Anim.org/).
| 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 |
| 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 |
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 |
| temporomandibular |
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
The letter 'l' is for Lumbar, the letter 't' is for Thorasic, and the letter 'c' is for Cervical.
The term "proximal" means "the nearer" segment, and "distal" means "the farther" segment.
The l_sternoclavicular and r_sternoclavicular joints are children of vt1, and siblings of vc7.
The skullbase joint is technically the "atlanto-occipital" joint.
The left and right metatarsals are technically the left and right "tarsometatarsal" joints.
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.
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.
NavigationInfo { type ["EXAMINE", "ANY"] }
This makes it easy to examine the humanoid from all angles.
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.
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 http://H-Anim.org/Specifications/H-Anim1.1.
The appendices can be found at http://H-Anim.org/Specifications/H-Anim1.1/appendices.html.
The home page of the VRML Humanoid Animation Working
Group is http://H-Anim.org.