Difference between revisions of "Avatar Appearance"
Chaser Zaks (talk | contribs) (→File Structure: newview/llvoavatardefines.h has been renamed) |
|||
(28 intermediate revisions by 10 users not shown) | |||
Line 1: | Line 1: | ||
{{KBcaution|'''[http://bit.ly/aczoWU See this if you're looking for general Appearance Editor help for Viewer 2.1.]'''}} | |||
{{ProtocolNav}} | {{ProtocolNav}} | ||
[[Category:Viewer Architecture]] | |||
<br/> | |||
For a good introduction to the elements of 3D character graphics, including meshes, morphs, bones, rendering, quaternions, and more see [http://www.gup.uni-linz.ac.at/~gk/Diplom/CART-Martin.pdf Martin Garstenauer's thesis].<br/><br/> | |||
== Appearance Components == | |||
SL Avatar has "wearables" plus "attachments" for static appearance, and "animations". | |||
=== Wearables === | |||
Wearables encompass both clothing and body parts – represent customizations of the basic avatar mesh via parameterized changes and textures. | |||
Clothing can be taken off, but body parts cannot. Otherwise, they are similar. | |||
Wearables are created by the viewer when appearance is edited and the results are saved; changed parts of appearance (clothing, bodyparts) are saved as new wearables which are uploaded as assets. There is no support for directly importing or exporting wearables. | |||
=== Attachments === | |||
An "attachment" is an object ("linked set of primitives") which is rooted in the scene graph on an attachment point on an avatar. They are otherwise the same as other objects in SL, and can contain and execute scripts, inventory, maintain state, etc. | |||
Attachments are heavily used for hair, some parts of clothing (dresses, cuffs) and accessories (jewelery, weapons). Some avatars may use attachments to completely obscure the underlying humanoid avatar mesh. | |||
Attachments are never serialized as files on the viewer, and there is no import/export support. Attachments are only transmitted to/from the viewer as ObjectUpdate messages which describe the constantly updating scene graph of the simulation. Attachments are created/modified using the "build" tools in the viewer; modifications are transmitted from the viewer to the simulator as editing messages. The simulator then broadcasts the changes to other users as ObjectUpdates. When an attachment is saved to inventory, the linked set of prims structure is serialized to a structure that includes script state. | |||
=== Animations === | |||
Animations are BVH files ('''B'''io'''V'''ision '''H'''eirarchical data), a format developed by Biovision, a motion capture services company. Animations can be added to a scripted object to be played (e.g. a "poseball"), or incorporated into a gesture (a sequence of actions including text, sounds and animations invoked manually or triggered by a keyword). However, animations are often thought of as parts of avatars when they are controlled by an attachment to alter the avatar's default animations. | |||
One common case is as an "Animation Override" script. These are used along with creative animations to deform the skeleton. Sometimes these override only some of the default animations (e.g. directed attention), sometimes everything is overridden. For example, "tinies" are created by folding the skeleton's limbs back on themselves. Non-humanoid avatars often use "meatballs" animations that compress the avatar to such an extent that it can be hidden inside an attachment. See [[Avatar deformation]] for more information. | |||
Animations can be created in third party tools (e.g. Poser, QAvimator) and uploaded via File > Upload Animation (L$10). The animation is added to the inventory, and can then be incorporated into a script or gesture. | |||
==Packets== | ==Packets== | ||
Line 15: | Line 45: | ||
* [[AgentCachedTexture]] | * [[AgentCachedTexture]] | ||
* [[AgentCachedTextureResponse]] | * [[AgentCachedTextureResponse]] | ||
==Linden avatar definition file== | |||
==Linden avatar | |||
The parameters affecting avatar appearance are defined in an XML file | The parameters affecting avatar appearance are defined in an XML file | ||
Line 26: | Line 53: | ||
and in the source code at | and in the source code at | ||
: linden\indra\newview\character\avatar_lad.xml | : linden\indra\newview\character\avatar_lad.xml | ||
With a few exceptions | |||
: genepool.xml | |||
: rouge_alpha.tga | |||
: underpants_trial_female.tga | |||
: underpants_trial_male.tga | |||
: undershirt_trial_female.tga | |||
: upperbodyfreckles_alpha.tga | |||
all of the other files in the same directory are referenced by avatar_lad.xml. These include the mesh files (.llm), the texture files (.tga) and the avatar_skeleton.xml file (see below). | |||
genepool.xml contains parameter sets for wearable types WT_SHAPE, WT_SKIN, WT_HAIR, and WT_EYES for several archetypal avatar definitions. This file supported the Randomize feature in the appearance editor. The functionality was removed in viewer 1.23, but a vestigial copy of genepool.xml may still be present. You can see the current parameter set for your own avatar by invoking the debug menus (Ctrl-Alt-D) and selecting | |||
Client->Character->Character Tests->Appearance To XML. This will create a file | |||
: SecondLife\character\new archetype.xml | |||
in the same format as genepool.xml. | |||
The avatar definition file affects the appearances on your viewer only. Any change to the file will not affect how others see the avatars. You can set value_default="1" for "Express_Tongue_Out" to make the avatars on your viewer give you the raspberries, but no one else will notice. | |||
The interesting thing is that this file defines parameters that can be used in animations. | |||
===File structure=== | ===File structure=== | ||
Line 35: | Line 82: | ||
: '''<skeleton file_name="avatar_skeleton.xml">''' | : '''<skeleton file_name="avatar_skeleton.xml">''' | ||
:: '''''<attachment_point'' id="1" group="6" name="Chest" joint="mChest"''' | :: '''''<attachment_point'' id="1" group="6" name="Chest" joint="mChest"''' | ||
:: | :: position="0.15 0 -0.1" rotation="0 90 90" visible_in_first_person="true" | ||
:: pie_slice="2" hud="true" max_attachment_offset="1.5" '''''/>''''' | :: pie_slice="2" hud="true" max_attachment_offset="1.5" '''''/>''''' | ||
:: '''''<param ... >''''' | :: '''''<param ... >''''' | ||
Line 46: | Line 93: | ||
:Sets of | :Sets of | ||
: '''<mesh type="hairMesh" lod="0" file_name="avatar_hair.llm" min_pixel_width="320">''' | : '''<mesh type="hairMesh" lod="0" file_name="avatar_hair.llm"''' | ||
: min_pixel_width="320" min_pixel_area="0.1" '''>''' | |||
:: '''''<param ... >''''' | :: '''''<param ... >''''' | ||
::: '''<param_morph />''' | ::: '''<param_morph />''' | ||
:::or | :::or | ||
::: '''<param_morph>''' | ::: '''<param_morph>''' | ||
:::: '''''<volume_morph'' name="HEAD" scale="-0.008 -0.006 0.015" | :::: '''''<volume_morph''''' name="HEAD" scale="-0.008 -0.006 0.015" | ||
:::: pos="0.07 0 -0.07" '''''/>''''' | :::: pos="0.07 0 -0.07" '''''/>''''' | ||
::: '''</param_morph>''' | ::: '''</param_morph>''' | ||
Line 57: | Line 105: | ||
: '''</mesh>''' | : '''</mesh>''' | ||
: ''<mesh'' '''type="hairMesh" lod="1" file_name="avatar_hair_1.llm"''' | : ''<mesh'' '''type="hairMesh" lod="1" file_name="avatar_hair_1.llm"''' | ||
: | : min_pixel_width="160" min_pixel_area="0.1" '''reference="avatar_hair.llm"'''''>'' | ||
: ''</mesh>'' | : ''</mesh>'' | ||
Line 73: | Line 121: | ||
: clear_alpha="false" alpha_tga_file="head_alpha.tga" '''''>''''' | : clear_alpha="false" alpha_tga_file="head_alpha.tga" '''''>''''' | ||
:: '''''<layer'' name="head bump definition" render_pass="bump" | :: '''''<layer'' name="head bump definition"''' render_pass="bump" | ||
:: global_color="hair_color" fixed_color="128,128,128,255" | :: global_color="hair_color" fixed_color="128,128,128,255" | ||
:: write_all_channels="true" '''''>''''' | :: write_all_channels="true" '''''>''''' | ||
Line 81: | Line 129: | ||
::: <texture '''tga_file="bump_head_base.tga"''' file_is_mask="FALSE" /> | ::: <texture '''tga_file="bump_head_base.tga"''' file_is_mask="FALSE" /> | ||
::: ''<morph_mask | ::: ''<morph_mask'' morph_name="Displace_Loose_Upperbody" invert="FALSE" ''/>'' | ||
::: ''<param ... >'' | ::: ''<param ... >'' | ||
:::: '''<param_alpha | :::: '''<param_alpha''' tga_file="bump_face_wrinkles.tga" skip_if_zero="true" | ||
:::: multiply_blend="false" domain="0" '''/>''' | |||
:::: multiply_blend="false" | |||
::::or | ::::or | ||
:::: '''<param_color''' operation="multiply" '''>''' | :::: '''<param_color''' operation="multiply" '''>''' | ||
Line 106: | Line 153: | ||
'''</linden_avatar>''' | '''</linden_avatar>''' | ||
where '''bold''' text indicates required tags or parameters, ''italics'' | where '''bold''' text indicates required tags or parameters, standard text | ||
indicates a tag that can occur zero or one time, ''italics'' | |||
indicates that the tag can be repeated zero or more times, and '''''bold italics''''' indicates | indicates that the tag can be repeated zero or more times, and '''''bold italics''''' indicates | ||
that at least one is required but more are possible | that at least one is required but more are possible. | ||
Note that the values shown for parameters here may not be consistent. They are shown only | Note that the values shown for parameters here may not be consistent. They are shown only | ||
to indicate the value type. | to indicate the value type. | ||
===Parameter detail=== | ===Parameter detail=== | ||
Line 118: | Line 166: | ||
<param ... > is | <param ... > is | ||
: '''<param id="32" group="1" name="Male_Skeleton" | : '''<param id="32"''' group="1" name="Male_Skeleton" | ||
: | : value_min="0" value_max="1" value_default="0" | ||
: edit_group="shape_body" edit_group_order="1" | : edit_group="shape_body" edit_group_order="1" | ||
: label="Skeleton" label_min="Female" label_max="Male" | : label="Skeleton" label_min="Female" label_max="Male" | ||
Line 125: | Line 173: | ||
: show_simple="true" simple_percent_min="40" simple_percent_max="100" | : show_simple="true" simple_percent_min="40" simple_percent_max="100" | ||
: camera_distance="2.2" camera_elevation=".1" camera_angle="0" '''>''' | : camera_distance="2.2" camera_elevation=".1" camera_angle="0" '''>''' | ||
Parameters are parsed in LLViewerVisualParamInfo::parseXml and LLVisualParamInfo::parseXml and are used by LLViewerVisualParam and LLVisualParam respectively when LLVOAvatar::loadAvatar is called. | |||
Fields parsed in LLVisualParamInfo are used to describe the meaning of the parameters. | |||
;id -- mID | |||
;name -- mName | |||
:default "" | |||
;group -- mGroup | |||
:"0" is VISUAL_PARAM_GROUP_TWEAKABLE | |||
:"1" is VISUAL_PARAM_GROUP_ANIMATABLE | |||
:default "0" | |||
;value_min -- mMinWeight | |||
:default 0. | |||
;value_max -- mMaxWeight | |||
:default 1. | |||
;value_default -- mDefaultWeight | |||
:default 0. | |||
;sex -- mSex | |||
{| | |||
| || || "both" || SEX_BOTH | |||
|- | |||
| || || "male" || SEX_MALE | |||
|- | |||
| || || "female" || SEX_FEMALE | |||
|- | |||
| || || default || SEX_BOTH | |||
|} | |||
;label -- mDisplayName | |||
:default is name | |||
;label_min -- mMinName | |||
:default is "Less" | |||
;label_max -- mMaxName | |||
:default is "More" | |||
;shared | |||
:Used only by mesh params. Indicates that the param affects more than one mesh | |||
Fields parsed in LLViewerVisualParamInfo describe the appearance of the entries on the Edit->Appearance editing panel. | |||
;wearable -- mWearableType | |||
{| | |||
| || || "shape" || WT_SHAPE | |||
|- | |||
| || || "skin" || WT_SKIN | |||
|- | |||
| || || "hair" || WT_HAIR | |||
|- | |||
| || || "eyes" || WT_EYES | |||
|- | |||
| || || "shirt" || WT_SHIRT | |||
|- | |||
| || || "pants" || WT_PANTS | |||
|- | |||
| || || "shoes" || WT_SHOES | |||
|- | |||
| || || "socks" || WT_SOCKS | |||
|- | |||
| || || "jacket" || WT_JACKET | |||
|- | |||
| || || "gloves" || WT_GLOVES | |||
|- | |||
| || || "undershirt" || WT_UNDERSHIRT | |||
|- | |||
| || || "underpants" || WT_UNDERPANTS | |||
|- | |||
| || || "skirt" || WT_SKIRT | |||
|- | |||
| || || default || WT_INVALID | |||
|} | |||
;edit_group -- mEditGroup | |||
:default "" | |||
;edit_group_order -- mEditGroupDisplayOrder | |||
:By default, value 0, parameters are displayed in the order in which they appear in the xml file. "edit_group_order" overriddes this. | |||
Optional camera offsets from the current joint center. Used for generating "hints" (thumbnails). | |||
;camera_distance -- mCamDist | |||
:default 0.5 | |||
;camera_angle -- mCamAngle | |||
:default 0. | |||
;camera_elevation -- mCamElevation | |||
:default 0. | |||
;show_simple -- mShowSimple : value is ignored | |||
:default FALSE | |||
;simple_percent_min -- mSimpleMin : value is ignored | |||
:default 0. | |||
;simple_percent_max -- mSimpleMax : value is ignored | |||
:default 100. | |||
===Loading the file=== | |||
The file is parsed in LLVOAvatar::initClass() primarily by calls to LLVOAvatarInfo. Both classes are defined in indra\newview\llvoavatar.h(.cpp). | |||
There is one method for each of the major XML nodes | |||
:LLVOAvatarInfo::parseXmlSkeletonNode | |||
:LLVOAvatarInfo::parseXmlMeshNodes | |||
:LLVOAvatarInfo::parseXmlColorNodes | |||
:LLVOAvatarInfo::parseXmlLayerNodes | |||
:LLVOAvatarInfo::parseXmlDriverNodes | |||
This data is then used to create instances of LLVOAvatar in LLVOAvatar::loadAvatar() | |||
which invokes LLVOAvatar::loadSkeletonNode() and LLVOAvatar::loadMeshNodes(). | |||
==LLVisualParam== | |||
The avatar visual parameters are divided into those that define the avatar's appearance and those that are used in animations. Theoretically, they all could be used for animations, but the animations would have to start and end at the settings defined for the avatar rather than at the default values. | |||
The group field of the <param> tag identifies those that are directly set in Edit->Appearance and sent in [[AgentSetAppearance]] messages as VISUAL_PARAM_GROUP_TWEAKABLE. The rest are identified as VISUAL_PARAM_GROUP_ANIMATABLE, but this is a bit misleading because it includes all of the driven parameters defined in the <driver_parameters> stanza. These are set by the driver parameters which are themselves directly tweakable. | |||
Those that are not directly or indirectly tweakable include the emotes | |||
:* 300 Express_Closed_Mouth | |||
:* 301 Express_Tongue_Out | |||
:* 302 Express_Surprise_Emote | |||
:* 303 Express_Wink_Emote | |||
:* 304 Express_Embarrassed_Emote | |||
:* 305 Express_Shrug_Emote | |||
:* 306 Express_Kiss | |||
:* 307 Express_Bored_Emote | |||
:* 308 Express_Repulsed_Emote | |||
:* 309 Express_Disdain | |||
:* 310 Express_Afraid_Emote | |||
:* 311 Express_Worry_Emote | |||
:* 312 Express_Cry_Emote | |||
:* 313 Express_Sad_Emote | |||
:* 314 Express_Anger_Emote | |||
:* 315 Express_Frown | |||
:* 316 Express_Laugh_Emote | |||
:* 317 Express_Toothsmile | |||
:* 318 Express_Smile | |||
:* 632 Express_Open_Mouth | |||
the hand morphs | |||
:* 101 Hands_Relaxed | |||
:* 102 Hands_Point | |||
:* 103 Hands_Fist | |||
:* 666 Hands_Relaxed_L | |||
:* 667 Hands_Point_L | |||
:* 668 Hands_Fist_L | |||
:* 669 Hands_Relaxed_R | |||
:* 670 Hands_Point_R | |||
:* 671 Hands_Fist_R | |||
:* 672 Hands_Typing | |||
:* 766 Hands_Salute_R | |||
:* 791 Hands_Peace_R | |||
:* 792 Hands_Spread_R | |||
and blinking eyes | |||
:* 58 Blink_Left | |||
:* 59 Blink_Right | |||
The remaining visual params include a few useful for animations | |||
:* 51 Furrowed_Eyebrows | |||
:* 53 Surprised_Eyebrows | |||
:* 54 Worried_Eyebrows | |||
:* 55 Frown_Mouth | |||
:* 57 Smile_Mouth | |||
and a couple that seem to have been abandoned | |||
:* 41 Old | |||
:* 128 Wrinkles | |||
==Linden skeleton definition file== | |||
The skeletal structure is defined in an XML file located in the executable at | |||
: SecondLife\character\avatar_skeleton.xml | |||
and in the source code at | |||
: linden\indra\newview\character\avatar_skeleton.xml | |||
It is referenced through the avatar definition file (see above) and can be | |||
considered to be part of the avatar definition. | |||
===File structure=== | |||
'''<?xml version="1.0" encoding="US-ASCII" standalone="yes"?>''' | |||
'''<linden_skeleton version="1.0" num_bones="46" num_collision_volumes="19">''' | |||
: '''<bone name="mPelvis" pos="0.000 0.000 1.067" rot="0.000000 0.000000 0.000000" | |||
: '''scale="1.000 1.000 1.000" pivot="0.000000 0.000000 1.067015">''' | |||
:: <collision_volume '''name="PELVIS" pos = "-0.01 0 -0.02"''' | |||
:: '''rot="0.000000 8.00000 0.000000" scale="0.12 0.16 0.17"'''/> | |||
:: ''<bone ...>'' | |||
:: ''</bone>'' | |||
: '''</bone>''' | |||
'''</linden_skeleton>''' | |||
where '''bold''' text indicates required tags or parameters, standard text | |||
indicates a tag that can occur zero or one time, and ''italics'' | |||
indicates that the tag can be repeated zero or more times. | |||
The <bone ...> tag above is to indicate that the structure is recursive. | |||
The "46" for num_bones is actually a typo in the file. There are only 26 bones defined. | |||
===Loading the file=== | |||
The file is parsed in LLVOAvatar::initClass() using LLVOAvatarSkeletonInfo::parseXml. Both classes are defined in indra\newview\llvoavatar.h(.cpp). | |||
This data is then used to create instances of LLVOAvatar in LLVOAvatar::loadAvatar() | |||
which invokes LLVOAvatar::buildSkeleton(). A special-purpose "screen" joint named "mScreen" is also created. | |||
==Linden binary mesh file== | |||
Meshes are defined in binary files located in the executable at | |||
: SecondLife\character\*.llm | |||
and in the source code at | |||
: linden\indra\newview\character\*.llm | |||
They are referenced through the avatar definition file (see above) and can be | |||
considered to be part of the avatar definition. | |||
The morphName in the binary mesh file matches the name field of the visual params with <param_morph> tags in the <mesh> stanzas. There are a few morphs defined in the mesh files that are not used by the avatar definition file | |||
:* Blink_Both | |||
:* Fingernails_Long | |||
:* Wide_Lips | |||
There are two types of mesh files: the base mesh definition and the level of detail (LOD) mesh definition, which always references a base mesh definition file. LOD meshes are used to simplify the rendering when the avatar is distant from the camera. There are several LOD meshes with progressively decreasing resolution. | |||
The vertex information referenced by the LOD meshes is stored at the beginning of the base mesh vertex information. | |||
===File structure=== | |||
====Base mesh==== | |||
:char[24] "Linden Binary Mesh 1.0" | |||
:U8 hasWeights | |||
:U8 hasDetailTexCoords | |||
:LLVector3 position | |||
:LLVector3 rotationAngles | |||
:U8 rotationOrder (ignored, set to 0) | |||
:LLVector3 scale | |||
:U16 numVertices | |||
:LLVector3[ numVertices ] baseCoords | |||
:LLVector3[ numVertices ] baseNormals | |||
:LLVector3[ numVertices ] baseBinormals | |||
:LLVector2[ numVertices ] texCoords | |||
:if (hasDetailTexCoords) | |||
::LLVector2[ numVertices ] detailTexCoords | |||
:if (hasWeights) | |||
::F32[ numVertices ] weights | |||
:U16 numFaces | |||
:struct faces[ numFaces ] | |||
:{ | |||
::S16[3] face | |||
:} | |||
:if ( hasWeights ) | |||
:{ | |||
::U16 numSkinJoints | |||
::struct skinJoints[ numSkinJoints ] | |||
::{ | |||
:::char[64] jointName | |||
::} | |||
:} | |||
:struct morph [] | |||
:{ | |||
::char[64] morphName | |||
::S32 numVertices | |||
::struct vertices[ numVertices ] | |||
::{ | |||
:::U32 vertexIndex | |||
:::LLVector3 coord | |||
:::LLVector3 normal | |||
:::LLVector3 binormal | |||
:::LLVector2 texCoord | |||
::} | |||
:} | |||
:char[64] "End Morphs" | |||
:S32 numRemaps (or EOF) | |||
:struct vertexRemap[ numRemaps ] | |||
:{ | |||
::S32 remapSource | |||
::S32 remapDestination | |||
:} | |||
where standart '''morphName''' for '''avatar_upper_body.llm''' is: | |||
Big_Belly_Torso, Big_Chest, Breast_Female_Cleavage, Breast_Gravity, Chest_Male_No_Pecs, Displace_Loose_Upperbody, Fat_Torso, Fingernails_Long, Hands_Fist, Hands_Fist_L, Hands_Fist_R, Hands_Peace_R, Hands_Point, Hands_Point_L, Hands_Point_R, Hands_Relaxed, Hands_Relaxed_L, Hands_Relaxed_R, Hands_Salute_R, Hands_Spread_R, Hands_Typing, Love_Handles, Male_Torso, Muscular_Torso, No_Chest, Scrawny_Torso, Scrawny_Torso_Male, Shirtsleeve_flair, Small_Chest, default_upperbodyParallel | |||
and standart '''morphName''' for '''avatar_lower_body.llm''' is: | |||
Big_Belly_Legs, Big_Butt_Legs, Bowed_Legs, Displace_Loose_Lowerbody, Fat_Legs, Foot_Size, Leg_Longcuffs, Leg_Pantflair, Low_Crotch, Male_Legs, Male_Package, Muscular_Legs, Saddlebags, Scrawny_Legs, Shoe_Heel_Height, Shoe_Heel_Point, Shoe_Heel_Thick, Shoe_Platform_Height, Shoe_Platform_Width, Shoe_Toe_Point, Shoe_Toe_Square, Shoe_Toe_Thick, Small_Butt, default_lowerbodyParallel | |||
====Level Of Detail (LOD) mesh==== | |||
:char[24] "Linden Binary Mesh 1.0" | |||
:U8 hasWeights | |||
:U8 hasDetailTexCoords | |||
:LLVector3 position | |||
:LLVector3 rotationAngles | |||
:U8 rotationOrder (ignored, set to 0) | |||
:LLVector3 scale | |||
:U16 numFaces | |||
:struct faces[ numFaces ] | |||
:{ | |||
::S16[3] face | |||
:} | |||
where LLVector2 and LLVector3 are 2 and 3 floats respectively, and all numbers are little endian. Integers are 8, 16, or 32 bits signed (S) or unsigned (U). | |||
The LOD .llm files actually contain fields for (if hasWeights) numSkinJoints set to zero, char[64] "End Morphs", and numRemaps set to zero, but these are not read by the viewer. | |||
Each weight actually contains two pieces of information. The number to the left of the decimal point is the index of the joint and also implicitly indexes to the following joint. The actual weight is to the right of the decimal point and interpolates between these two joints. The index is into an "expanded" list of joints, not just a linear array of the joints as defined in the skeleton file. In particular, any joint that has more than one child will be repeated in the list for each of its children. | |||
===Loading the file=== | |||
This data is used to create instances of LLVOAvatar in LLVOAvatar::loadAvatar() | |||
through LLVOAvatar::loadMeshNodes, LLPolyMesh::getMesh, LLPolyMeshSharedData::loadMesh, and LLPolyMorphData::loadBinary. These are found in indra\newview\llvoavatar.h(.cpp), indra\newview\llpolymesh.h(.cpp), and indra\newview\llpolymorph.h(.cpp), and indra\llappearance\llpolymorph.h(cpp). | |||
== Linden wearable definition file == | |||
The format is used for client/server communication - wearable assets are downloaded to cache/uploaded on creation. No import/export ability currently exists, although wearables are manipulated as files both on the viewer and server. | |||
=== Source References === | |||
* <code>newview/llwearable.h</code> | |||
** <code>enum EWearableType</code> | |||
* <code>newview/llwearable.cpp</code> | |||
** <code>LLWearable::importFile</code> – parses assets when "worn" from inventory, after download to cache | |||
** <code>LLWearable::exportFile</code> – called by <code>LLWearable::saveNewAsset</code> when created, does upload to asset system | |||
* <code>newview/llvoavatardefines.h</code> | |||
** <code>enum ETextureIndex</code> | |||
=== File Structure === | |||
Details: | |||
* The file is line-oriented. UNIX line endings (LF 0x0A) are expected. | |||
* File encoding for strings is implicitly UTF-8. No byte-order mark is allowed. | |||
* Whitespace is used as delimiters. Spaces (0x20) and tabs (0x09) are considered whitespace, and any number may be used. | |||
The file consists of the following blocks, which must occur in the specified order: | |||
* Format/Version | |||
* Name | |||
* Description | |||
* Permissions | |||
* Sale Info | |||
* Wearable type | |||
* Parameters | |||
* Textures | |||
'''Format/Version''' | |||
The string <code>LLWearable version</code> followed by the version number (currently <code>22</code>) | |||
Example: | |||
LLWearable version 22 | |||
'''Name''' | |||
A single line string, terminated with a UNIX newline (LF 0x0A). Maximum length is 2047 bytes, not counting the newline. Encoding is UTF-8. A blank line is used to indicate the absence of a name. | |||
Example: | |||
Space Cadet Shirt | |||
'''Description''' | |||
A single line string, terminated with a UNIX newline (LF 0x0A). Maximum length is 2047 bytes, not counting the newline. Encoding is UTF-8. A blank line is used to indicate the absence of a description. | |||
Example: | |||
This is my awesome shirt! | |||
'''Permissions block''' | |||
* First line: The token <code>permissions</code> followed by the permission block version <code>0</code> | |||
* Second line: open brace <code>{</code> | |||
* A sequence of permission name/value pairs, each on its own line | |||
* Final line: close brace <code>}</code> | |||
The permission name/value pairs are: | |||
* <code>base_mask</code>, with 8-digit hexadecimal value | |||
* <code>owner_mask</code>, with 8-digit hexadecimal value | |||
* <code>group_mask</code>, with 8-digit hexadecimal value | |||
* <code>everyone_mask</code>, with 8-digit hexadecimal value | |||
* <code>next_owner_mask</code>, with 8-digit hexadecimal value | |||
* <code>creator_id</code>, with agent UUID in hexadecimal 8-4-4-4-12 format | |||
* <code>owner_id</code>, with agent UUID in hexadecimal 8-4-4-4-12 format | |||
* <code>last_owner_id</code>, with agent UUID in hexadecimal 8-4-4-4-12 format | |||
* <code>group_id</code>, with group UUID in hexadecimal 8-4-4-4-12 format | |||
* <code>group_owned</code>, with <code>0</code> (false) or <code>1</code> (true) flag | |||
If a name/value is missing, a default value is assumed. For maximum compatibility, everything should be explicitly specified except <code>group_owned</code> when false. | |||
Flags are defined in <code>llinventory/llpermissionsflags.h</code>: | |||
* <code>PERM_TRANSFER</code> = 0x00002000 | |||
* <code>PERM_MODIFY</code> = 0x00004000 | |||
* <code>PERM_COPY</code> = 0x00008000 | |||
* <code>PERM_MOVE</code> = 0x00080000 | |||
Common masks are: | |||
* <code>PERM_NONE</code> 0x00000000 | |||
* <code>PERM_ALL</code> 0x7FFFFFFF | |||
And common values are: | |||
* no modify: <code>PERM_ALL & ~PERM_MODIFY</code> = 0x7fffbfff | |||
* no copy: <code>PERM_ALL & ~PERM_COPY</code> = 0x7fff7fff | |||
* no modify or copy: = 0x7fff3fff | |||
* no transfer: <code>PERM_ALL & ~PERM_TRANSFER</code> = 0x7fffdfff | |||
* no modify, no transfer = 0x7fff9fff | |||
Example: | |||
permissions 0 | |||
{ | |||
base_mask 7fffffff | |||
owner_mask 7fffffff | |||
group_mask 00000000 | |||
everyone_mask 7fffbfff | |||
next_owner_mask 7fffffff | |||
creator_id d929385f-41e3-4a34-a04e-f1fc39f24f12 | |||
owner_id ff9a71eb-7414-4bf8-866e-a70ddeb7c3cf | |||
last_owner_id ff9a71eb-7414-4bf8-866e-a70ddeb7c3cf | |||
group_id 00000000-0000-0000-0000-000000000000 | |||
} | |||
'''Sale Info block''' | |||
* First line: The token <code>sale_info</code> followed by the sale_info block version <code>0</code> | |||
* Second line: open brace <code>{</code> | |||
* A sequence of sale info name/value pairs, each on its own line | |||
* Final line: close brace <code>}</code> | |||
The sale info name/value pairs are: | |||
* <code>sale_type</code>: one of: | |||
** <code>not</code> - not for sale | |||
** <code>orig</code> - the original is purchased | |||
** <code>copy</code> - a copy is purchased | |||
** <code>cntn</code> - the content is purchased | |||
* <code>sale_price</code> - price in L$ | |||
Example: | |||
sale_info 0 | |||
{ | |||
sale_type not | |||
sale_price 10 | |||
} | |||
'''Wearable Type''' | |||
* A single line with the token <code>type</code> followed by the wearable type as a decimal integer | |||
The type is defined in the <code>EWearableType</code> enumeration in <code>newview/llwearable.h</code>: | |||
* Bodyparts | |||
** <code>WT_SHAPE</code> = 0 | |||
** <code>WT_SKIN</code> = 1 | |||
** <code>WT_HAIR</code> = 2 | |||
** <code>WT_EYES</code> = 3 | |||
* Clothing | |||
** <code>WT_SHIRT</code> = 4 | |||
** <code>WT_PANTS</code> = 5 | |||
** <code>WT_SHOES</code> = 6 | |||
** <code>WT_SOCKS</code> = 7 | |||
** <code>WT_JACKET</code> = 8 | |||
** <code>WT_GLOVES</code> = 9 | |||
** <code>WT_UNDERSHIRT</code> = 10 | |||
** <code>WT_UNDERPANTS</code> = 11 | |||
** <code>WT_SKIRT</code> = 12 | |||
Example: | |||
type 4 | |||
'''Parameters''' | |||
* A line with the token <code>parameters</code> followed by the number of parameter ID/value pairs as a decimal integer | |||
* A sequence of parameter/ID value pairs, each on its own line | |||
** Parameter ID from the [[#Linden avatar definition file]], a decimal integer | |||
** Parameter value (or weight) is a decimal floating point value | |||
Example: | |||
parameters 10 | |||
781 1 | |||
800 .92 | |||
801 1 | |||
802 1 | |||
803 1 | |||
804 1 | |||
805 1 | |||
828 .18 | |||
840 0 | |||
868 .27 | |||
'''Texture''' | |||
* A line with the token <code>textures</code> followed by the number of texture index/ID pairs as a decimal integer | |||
* A sequence of texture index/ID pairs, each on its own line | |||
** Texture index is defined in the <code>ETextureIndex</code> enumeration in <code>indra/llappearance/llavatarappearancedefines.h</code> | |||
** Texture ID is the texture's UUID in hexadecimal 8-4-4-4-12 format | |||
Texture indexes: | |||
* <code>TEX_HEAD_BODYPAINT</code> = 0 | |||
* <code>TEX_UPPER_SHIRT</code> = 1 | |||
* <code>TEX_LOWER_PANTS</code> = 2 | |||
* <code>TEX_EYES_IRIS</code> = 3 | |||
* <code>TEX_HAIR</code> = 4 | |||
* <code>TEX_UPPER_BODYPAINT</code> = 5 | |||
* <code>TEX_LOWER_BODYPAINT</code> = 6 | |||
* <code>TEX_LOWER_SHOES</code> = 7 | |||
* <code>TEX_HEAD_BAKED</code> = 8 (* See below) | |||
* <code>TEX_UPPER_BAKED</code> = 9 (* See below) | |||
* <code>TEX_LOWER_BAKED</code> = 10 (* See below) | |||
* <code>TEX_EYES_BAKED</code> = 11 (* See below) | |||
* <code>TEX_LOWER_SOCKS</code> = 12 | |||
* <code>TEX_UPPER_JACKET</code> = 13 | |||
* <code>TEX_LOWER_JACKET</code> = 14 | |||
* <code>TEX_UPPER_GLOVES</code> = 15 | |||
* <code>TEX_UPPER_UNDERSHIRT</code> = 16 | |||
* <code>TEX_LOWER_UNDERPANTS</code> = 17 | |||
* <code>TEX_SKIRT</code> = 18 | |||
* <code>TEX_SKIRT_BAKED</code> = 19 (* See below) | |||
* <code>TEX_HAIR_BAKED</code> = 20 (* See below) | |||
''* When the avatar changes a wearable, the simulator requests that the viewer rebake the *_BAKED textures; these are then uploaded as new temporary assets to the system so that the individual assets do not need to be downloaded. The *_BAKED textures are not referenced by wearables.'' | |||
Example: | |||
textures 1 | |||
1 08115557-ad4d-09ed-6b39-2ffc1f2b58b2 |
Latest revision as of 01:42, 2 February 2018
Important: See this if you're looking for general Appearance Editor help for Viewer 2.1. |
For a good introduction to the elements of 3D character graphics, including meshes, morphs, bones, rendering, quaternions, and more see Martin Garstenauer's thesis.
Appearance Components
SL Avatar has "wearables" plus "attachments" for static appearance, and "animations".
Wearables
Wearables encompass both clothing and body parts – represent customizations of the basic avatar mesh via parameterized changes and textures.
Clothing can be taken off, but body parts cannot. Otherwise, they are similar.
Wearables are created by the viewer when appearance is edited and the results are saved; changed parts of appearance (clothing, bodyparts) are saved as new wearables which are uploaded as assets. There is no support for directly importing or exporting wearables.
Attachments
An "attachment" is an object ("linked set of primitives") which is rooted in the scene graph on an attachment point on an avatar. They are otherwise the same as other objects in SL, and can contain and execute scripts, inventory, maintain state, etc.
Attachments are heavily used for hair, some parts of clothing (dresses, cuffs) and accessories (jewelery, weapons). Some avatars may use attachments to completely obscure the underlying humanoid avatar mesh.
Attachments are never serialized as files on the viewer, and there is no import/export support. Attachments are only transmitted to/from the viewer as ObjectUpdate messages which describe the constantly updating scene graph of the simulation. Attachments are created/modified using the "build" tools in the viewer; modifications are transmitted from the viewer to the simulator as editing messages. The simulator then broadcasts the changes to other users as ObjectUpdates. When an attachment is saved to inventory, the linked set of prims structure is serialized to a structure that includes script state.
Animations
Animations are BVH files (BioVision Heirarchical data), a format developed by Biovision, a motion capture services company. Animations can be added to a scripted object to be played (e.g. a "poseball"), or incorporated into a gesture (a sequence of actions including text, sounds and animations invoked manually or triggered by a keyword). However, animations are often thought of as parts of avatars when they are controlled by an attachment to alter the avatar's default animations.
One common case is as an "Animation Override" script. These are used along with creative animations to deform the skeleton. Sometimes these override only some of the default animations (e.g. directed attention), sometimes everything is overridden. For example, "tinies" are created by folding the skeleton's limbs back on themselves. Non-humanoid avatars often use "meatballs" animations that compress the avatar to such an extent that it can be hidden inside an attachment. See Avatar deformation for more information.
Animations can be created in third party tools (e.g. Poser, QAvimator) and uploaded via File > Upload Animation (L$10). The animation is added to the inventory, and can then be incorporated into a script or gesture.
Packets
- AgentWearablesRequest
- This is where it starts. The viewer asks the simulator what it is wearing, and an AgentWearablesUpdate packet is returned.
- AgentWearablesUpdate
- A mapping of wearable types to asset IDs and item IDs is returned to the client. There are currently 13 different wearable types and all 13 will always be returned in this packet. If your avatar is not wearing a wearable type the asset ID and item ID for that type will be null IDs (all zeros). The next step is to request an asset transfer for all of the non-null asset IDs and download the wearable assets.
- AgentIsNowWearing
- Like the AgentWearablesUpdate packet but in the other direction. The viewer sends a list of the 13 wearable types and their associated item IDs, or null if nothing is being worn in that wearable slot. This is typically sent right before AgentSetAppearance.
- AgentSetAppearance
- Serves two purposes, to tell the server how our avatar mesh is deformed (with visual parameters) and what textures we are wearing. There are currently 218 VisualParam blocks sent with each AgentSetAppearance describing everything from the color of the avatar eyes to the gender slider. A TextureEntry is also sent that uses the same TextureEntry format objects use, but each "face" is hard-coded to describe a particular texture. This may or may not include baked textures for the five different baked layers (head, upper, lower, eyes, and skirt).
- The ParamValue fields do not have parameter IDs associated with them in the packet, as it's assumed all viewers have the same parameter map in the same sequence. The parameters are stored internally as a floating point integer, and are converted to a single byte by inputting the value along with minimum and maximum weights for that parameter to a conversion function.
Linden avatar definition file
The parameters affecting avatar appearance are defined in an XML file located in the executable at
- SecondLife\character\avatar_lad.xml
and in the source code at
- linden\indra\newview\character\avatar_lad.xml
With a few exceptions
- genepool.xml
- rouge_alpha.tga
- underpants_trial_female.tga
- underpants_trial_male.tga
- undershirt_trial_female.tga
- upperbodyfreckles_alpha.tga
all of the other files in the same directory are referenced by avatar_lad.xml. These include the mesh files (.llm), the texture files (.tga) and the avatar_skeleton.xml file (see below).
genepool.xml contains parameter sets for wearable types WT_SHAPE, WT_SKIN, WT_HAIR, and WT_EYES for several archetypal avatar definitions. This file supported the Randomize feature in the appearance editor. The functionality was removed in viewer 1.23, but a vestigial copy of genepool.xml may still be present. You can see the current parameter set for your own avatar by invoking the debug menus (Ctrl-Alt-D) and selecting Client->Character->Character Tests->Appearance To XML. This will create a file
- SecondLife\character\new archetype.xml
in the same format as genepool.xml.
The avatar definition file affects the appearances on your viewer only. Any change to the file will not affect how others see the avatars. You can set value_default="1" for "Express_Tongue_Out" to make the avatars on your viewer give you the raspberries, but no one else will notice.
The interesting thing is that this file defines parameters that can be used in animations.
File structure
<?xml version="1.0" encoding="US-ASCII" standalone="yes"?>
<linden_avatar version="1.0" wearable_definition_version="22">
- <skeleton file_name="avatar_skeleton.xml">
- <attachment_point id="1" group="6" name="Chest" joint="mChest"
- position="0.15 0 -0.1" rotation="0 90 90" visible_in_first_person="true"
- pie_slice="2" hud="true" max_attachment_offset="1.5" />
- <param ... >
- <param_skeleton>
- <bone name="mNeck" scale="0 0 .2" offset="0 0 .004" />
- </param_skeleton>
- <param_skeleton>
- </param>
- </skeleton>
- Sets of
- <mesh type="hairMesh" lod="0" file_name="avatar_hair.llm"
- min_pixel_width="320" min_pixel_area="0.1" >
- <param ... >
- <param_morph />
- or
- <param_morph>
- <volume_morph name="HEAD" scale="-0.008 -0.006 0.015"
- pos="0.07 0 -0.07" />
- </param_morph>
- </param>
- <param ... >
- </mesh>
- <mesh type="hairMesh" lod="1" file_name="avatar_hair_1.llm"
- min_pixel_width="160" min_pixel_area="0.1" reference="avatar_hair.llm">
- </mesh>
- <global_color name="skin_color">
- <param ... >
- <param_color operation="blend" >
- <value color="252, 215, 200, 255" />
- </param_color>
- <param_color operation="blend" >
- </param>
- <param ... >
- </global_color>
- <layer_set body_region="head" width="512" height="512"
- clear_alpha="false" alpha_tga_file="head_alpha.tga" >
- <layer name="head bump definition" render_pass="bump"
- global_color="hair_color" fixed_color="128,128,128,255"
- write_all_channels="true" >
- <texture local_texture="lower_jacket" local_texture_alpha_only="true" />
- and if not fixed_color
- <texture tga_file="bump_head_base.tga" file_is_mask="FALSE" />
- <morph_mask morph_name="Displace_Loose_Upperbody" invert="FALSE" />
- <param ... >
- <param_alpha tga_file="bump_face_wrinkles.tga" skip_if_zero="true"
- multiply_blend="false" domain="0" />
- or
- <param_color operation="multiply" >
- <value color="0, 0, 0, 0" />
- </param_color>
- </param>
- <param ... >
- </layer>
- </layer_set>
- <driver_parameters>
- <param ... >
- <param_driver>
- <driven id="628" min1="0.1" max1="0.5" max2="1" min2="1" />
- </param_driver>
- <param_driver>
- </param>
- <param ... >
- </driver_parameters>
</linden_avatar>
where bold text indicates required tags or parameters, standard text indicates a tag that can occur zero or one time, italics indicates that the tag can be repeated zero or more times, and bold italics indicates that at least one is required but more are possible.
Note that the values shown for parameters here may not be consistent. They are shown only to indicate the value type.
Parameter detail
<param ... > is
- <param id="32" group="1" name="Male_Skeleton"
- value_min="0" value_max="1" value_default="0"
- edit_group="shape_body" edit_group_order="1"
- label="Skeleton" label_min="Female" label_max="Male"
- wearable="shape" clothing_morph="true" sex="male" shared="1"
- show_simple="true" simple_percent_min="40" simple_percent_max="100"
- camera_distance="2.2" camera_elevation=".1" camera_angle="0" >
Parameters are parsed in LLViewerVisualParamInfo::parseXml and LLVisualParamInfo::parseXml and are used by LLViewerVisualParam and LLVisualParam respectively when LLVOAvatar::loadAvatar is called.
Fields parsed in LLVisualParamInfo are used to describe the meaning of the parameters.
- id -- mID
- name -- mName
- default ""
- group -- mGroup
- "0" is VISUAL_PARAM_GROUP_TWEAKABLE
- "1" is VISUAL_PARAM_GROUP_ANIMATABLE
- default "0"
- value_min -- mMinWeight
- default 0.
- value_max -- mMaxWeight
- default 1.
- value_default -- mDefaultWeight
- default 0.
- sex -- mSex
"both" | SEX_BOTH | ||
"male" | SEX_MALE | ||
"female" | SEX_FEMALE | ||
default | SEX_BOTH |
- label -- mDisplayName
- default is name
- label_min -- mMinName
- default is "Less"
- label_max -- mMaxName
- default is "More"
- shared
- Used only by mesh params. Indicates that the param affects more than one mesh
Fields parsed in LLViewerVisualParamInfo describe the appearance of the entries on the Edit->Appearance editing panel.
- wearable -- mWearableType
"shape" | WT_SHAPE | ||
"skin" | WT_SKIN | ||
"hair" | WT_HAIR | ||
"eyes" | WT_EYES | ||
"shirt" | WT_SHIRT | ||
"pants" | WT_PANTS | ||
"shoes" | WT_SHOES | ||
"socks" | WT_SOCKS | ||
"jacket" | WT_JACKET | ||
"gloves" | WT_GLOVES | ||
"undershirt" | WT_UNDERSHIRT | ||
"underpants" | WT_UNDERPANTS | ||
"skirt" | WT_SKIRT | ||
default | WT_INVALID |
- edit_group -- mEditGroup
- default ""
- edit_group_order -- mEditGroupDisplayOrder
- By default, value 0, parameters are displayed in the order in which they appear in the xml file. "edit_group_order" overriddes this.
Optional camera offsets from the current joint center. Used for generating "hints" (thumbnails).
- camera_distance -- mCamDist
- default 0.5
- camera_angle -- mCamAngle
- default 0.
- camera_elevation -- mCamElevation
- default 0.
- show_simple -- mShowSimple
- value is ignored
- default FALSE
- simple_percent_min -- mSimpleMin
- value is ignored
- default 0.
- simple_percent_max -- mSimpleMax
- value is ignored
- default 100.
Loading the file
The file is parsed in LLVOAvatar::initClass() primarily by calls to LLVOAvatarInfo. Both classes are defined in indra\newview\llvoavatar.h(.cpp). There is one method for each of the major XML nodes
- LLVOAvatarInfo::parseXmlSkeletonNode
- LLVOAvatarInfo::parseXmlMeshNodes
- LLVOAvatarInfo::parseXmlColorNodes
- LLVOAvatarInfo::parseXmlLayerNodes
- LLVOAvatarInfo::parseXmlDriverNodes
This data is then used to create instances of LLVOAvatar in LLVOAvatar::loadAvatar() which invokes LLVOAvatar::loadSkeletonNode() and LLVOAvatar::loadMeshNodes().
LLVisualParam
The avatar visual parameters are divided into those that define the avatar's appearance and those that are used in animations. Theoretically, they all could be used for animations, but the animations would have to start and end at the settings defined for the avatar rather than at the default values.
The group field of the <param> tag identifies those that are directly set in Edit->Appearance and sent in AgentSetAppearance messages as VISUAL_PARAM_GROUP_TWEAKABLE. The rest are identified as VISUAL_PARAM_GROUP_ANIMATABLE, but this is a bit misleading because it includes all of the driven parameters defined in the <driver_parameters> stanza. These are set by the driver parameters which are themselves directly tweakable.
Those that are not directly or indirectly tweakable include the emotes
- 300 Express_Closed_Mouth
- 301 Express_Tongue_Out
- 302 Express_Surprise_Emote
- 303 Express_Wink_Emote
- 304 Express_Embarrassed_Emote
- 305 Express_Shrug_Emote
- 306 Express_Kiss
- 307 Express_Bored_Emote
- 308 Express_Repulsed_Emote
- 309 Express_Disdain
- 310 Express_Afraid_Emote
- 311 Express_Worry_Emote
- 312 Express_Cry_Emote
- 313 Express_Sad_Emote
- 314 Express_Anger_Emote
- 315 Express_Frown
- 316 Express_Laugh_Emote
- 317 Express_Toothsmile
- 318 Express_Smile
- 632 Express_Open_Mouth
the hand morphs
- 101 Hands_Relaxed
- 102 Hands_Point
- 103 Hands_Fist
- 666 Hands_Relaxed_L
- 667 Hands_Point_L
- 668 Hands_Fist_L
- 669 Hands_Relaxed_R
- 670 Hands_Point_R
- 671 Hands_Fist_R
- 672 Hands_Typing
- 766 Hands_Salute_R
- 791 Hands_Peace_R
- 792 Hands_Spread_R
and blinking eyes
- 58 Blink_Left
- 59 Blink_Right
The remaining visual params include a few useful for animations
- 51 Furrowed_Eyebrows
- 53 Surprised_Eyebrows
- 54 Worried_Eyebrows
- 55 Frown_Mouth
- 57 Smile_Mouth
and a couple that seem to have been abandoned
- 41 Old
- 128 Wrinkles
Linden skeleton definition file
The skeletal structure is defined in an XML file located in the executable at
- SecondLife\character\avatar_skeleton.xml
and in the source code at
- linden\indra\newview\character\avatar_skeleton.xml
It is referenced through the avatar definition file (see above) and can be considered to be part of the avatar definition.
File structure
<?xml version="1.0" encoding="US-ASCII" standalone="yes"?>
<linden_skeleton version="1.0" num_bones="46" num_collision_volumes="19">
- <bone name="mPelvis" pos="0.000 0.000 1.067" rot="0.000000 0.000000 0.000000"
- scale="1.000 1.000 1.000" pivot="0.000000 0.000000 1.067015">
- <collision_volume name="PELVIS" pos = "-0.01 0 -0.02"
- rot="0.000000 8.00000 0.000000" scale="0.12 0.16 0.17"/>
- <bone ...>
- </bone>
- </bone>
</linden_skeleton>
where bold text indicates required tags or parameters, standard text indicates a tag that can occur zero or one time, and italics indicates that the tag can be repeated zero or more times.
The <bone ...> tag above is to indicate that the structure is recursive.
The "46" for num_bones is actually a typo in the file. There are only 26 bones defined.
Loading the file
The file is parsed in LLVOAvatar::initClass() using LLVOAvatarSkeletonInfo::parseXml. Both classes are defined in indra\newview\llvoavatar.h(.cpp).
This data is then used to create instances of LLVOAvatar in LLVOAvatar::loadAvatar() which invokes LLVOAvatar::buildSkeleton(). A special-purpose "screen" joint named "mScreen" is also created.
Linden binary mesh file
Meshes are defined in binary files located in the executable at
- SecondLife\character\*.llm
and in the source code at
- linden\indra\newview\character\*.llm
They are referenced through the avatar definition file (see above) and can be considered to be part of the avatar definition.
The morphName in the binary mesh file matches the name field of the visual params with <param_morph> tags in the <mesh> stanzas. There are a few morphs defined in the mesh files that are not used by the avatar definition file
- Blink_Both
- Fingernails_Long
- Wide_Lips
There are two types of mesh files: the base mesh definition and the level of detail (LOD) mesh definition, which always references a base mesh definition file. LOD meshes are used to simplify the rendering when the avatar is distant from the camera. There are several LOD meshes with progressively decreasing resolution.
The vertex information referenced by the LOD meshes is stored at the beginning of the base mesh vertex information.
File structure
Base mesh
- char[24] "Linden Binary Mesh 1.0"
- U8 hasWeights
- U8 hasDetailTexCoords
- LLVector3 position
- LLVector3 rotationAngles
- U8 rotationOrder (ignored, set to 0)
- LLVector3 scale
- U16 numVertices
- LLVector3[ numVertices ] baseCoords
- LLVector3[ numVertices ] baseNormals
- LLVector3[ numVertices ] baseBinormals
- LLVector2[ numVertices ] texCoords
- if (hasDetailTexCoords)
- LLVector2[ numVertices ] detailTexCoords
- if (hasWeights)
- F32[ numVertices ] weights
- U16 numFaces
- struct faces[ numFaces ]
- {
- S16[3] face
- }
- if ( hasWeights )
- {
- U16 numSkinJoints
- struct skinJoints[ numSkinJoints ]
- {
- char[64] jointName
- }
- }
- struct morph []
- {
- char[64] morphName
- S32 numVertices
- struct vertices[ numVertices ]
- {
- U32 vertexIndex
- LLVector3 coord
- LLVector3 normal
- LLVector3 binormal
- LLVector2 texCoord
- }
- }
- char[64] "End Morphs"
- S32 numRemaps (or EOF)
- struct vertexRemap[ numRemaps ]
- {
- S32 remapSource
- S32 remapDestination
- }
where standart morphName for avatar_upper_body.llm is:
Big_Belly_Torso, Big_Chest, Breast_Female_Cleavage, Breast_Gravity, Chest_Male_No_Pecs, Displace_Loose_Upperbody, Fat_Torso, Fingernails_Long, Hands_Fist, Hands_Fist_L, Hands_Fist_R, Hands_Peace_R, Hands_Point, Hands_Point_L, Hands_Point_R, Hands_Relaxed, Hands_Relaxed_L, Hands_Relaxed_R, Hands_Salute_R, Hands_Spread_R, Hands_Typing, Love_Handles, Male_Torso, Muscular_Torso, No_Chest, Scrawny_Torso, Scrawny_Torso_Male, Shirtsleeve_flair, Small_Chest, default_upperbodyParallel
and standart morphName for avatar_lower_body.llm is:
Big_Belly_Legs, Big_Butt_Legs, Bowed_Legs, Displace_Loose_Lowerbody, Fat_Legs, Foot_Size, Leg_Longcuffs, Leg_Pantflair, Low_Crotch, Male_Legs, Male_Package, Muscular_Legs, Saddlebags, Scrawny_Legs, Shoe_Heel_Height, Shoe_Heel_Point, Shoe_Heel_Thick, Shoe_Platform_Height, Shoe_Platform_Width, Shoe_Toe_Point, Shoe_Toe_Square, Shoe_Toe_Thick, Small_Butt, default_lowerbodyParallel
Level Of Detail (LOD) mesh
- char[24] "Linden Binary Mesh 1.0"
- U8 hasWeights
- U8 hasDetailTexCoords
- LLVector3 position
- LLVector3 rotationAngles
- U8 rotationOrder (ignored, set to 0)
- LLVector3 scale
- U16 numFaces
- struct faces[ numFaces ]
- {
- S16[3] face
- }
where LLVector2 and LLVector3 are 2 and 3 floats respectively, and all numbers are little endian. Integers are 8, 16, or 32 bits signed (S) or unsigned (U).
The LOD .llm files actually contain fields for (if hasWeights) numSkinJoints set to zero, char[64] "End Morphs", and numRemaps set to zero, but these are not read by the viewer.
Each weight actually contains two pieces of information. The number to the left of the decimal point is the index of the joint and also implicitly indexes to the following joint. The actual weight is to the right of the decimal point and interpolates between these two joints. The index is into an "expanded" list of joints, not just a linear array of the joints as defined in the skeleton file. In particular, any joint that has more than one child will be repeated in the list for each of its children.
Loading the file
This data is used to create instances of LLVOAvatar in LLVOAvatar::loadAvatar() through LLVOAvatar::loadMeshNodes, LLPolyMesh::getMesh, LLPolyMeshSharedData::loadMesh, and LLPolyMorphData::loadBinary. These are found in indra\newview\llvoavatar.h(.cpp), indra\newview\llpolymesh.h(.cpp), and indra\newview\llpolymorph.h(.cpp), and indra\llappearance\llpolymorph.h(cpp).
Linden wearable definition file
The format is used for client/server communication - wearable assets are downloaded to cache/uploaded on creation. No import/export ability currently exists, although wearables are manipulated as files both on the viewer and server.
Source References
newview/llwearable.h
enum EWearableType
newview/llwearable.cpp
LLWearable::importFile
– parses assets when "worn" from inventory, after download to cacheLLWearable::exportFile
– called byLLWearable::saveNewAsset
when created, does upload to asset system
newview/llvoavatardefines.h
enum ETextureIndex
File Structure
Details:
- The file is line-oriented. UNIX line endings (LF 0x0A) are expected.
- File encoding for strings is implicitly UTF-8. No byte-order mark is allowed.
- Whitespace is used as delimiters. Spaces (0x20) and tabs (0x09) are considered whitespace, and any number may be used.
The file consists of the following blocks, which must occur in the specified order:
- Format/Version
- Name
- Description
- Permissions
- Sale Info
- Wearable type
- Parameters
- Textures
Format/Version
The string LLWearable version
followed by the version number (currently 22
)
Example:
LLWearable version 22
Name
A single line string, terminated with a UNIX newline (LF 0x0A). Maximum length is 2047 bytes, not counting the newline. Encoding is UTF-8. A blank line is used to indicate the absence of a name.
Example:
Space Cadet Shirt
Description
A single line string, terminated with a UNIX newline (LF 0x0A). Maximum length is 2047 bytes, not counting the newline. Encoding is UTF-8. A blank line is used to indicate the absence of a description.
Example:
This is my awesome shirt!
Permissions block
- First line: The token
permissions
followed by the permission block version0
- Second line: open brace
{
- A sequence of permission name/value pairs, each on its own line
- Final line: close brace
}
The permission name/value pairs are:
base_mask
, with 8-digit hexadecimal valueowner_mask
, with 8-digit hexadecimal valuegroup_mask
, with 8-digit hexadecimal valueeveryone_mask
, with 8-digit hexadecimal valuenext_owner_mask
, with 8-digit hexadecimal valuecreator_id
, with agent UUID in hexadecimal 8-4-4-4-12 formatowner_id
, with agent UUID in hexadecimal 8-4-4-4-12 formatlast_owner_id
, with agent UUID in hexadecimal 8-4-4-4-12 formatgroup_id
, with group UUID in hexadecimal 8-4-4-4-12 formatgroup_owned
, with0
(false) or1
(true) flag
If a name/value is missing, a default value is assumed. For maximum compatibility, everything should be explicitly specified except group_owned
when false.
Flags are defined in llinventory/llpermissionsflags.h
:
PERM_TRANSFER
= 0x00002000PERM_MODIFY
= 0x00004000PERM_COPY
= 0x00008000PERM_MOVE
= 0x00080000
Common masks are:
PERM_NONE
0x00000000PERM_ALL
0x7FFFFFFF
And common values are:
- no modify:
PERM_ALL & ~PERM_MODIFY
= 0x7fffbfff - no copy:
PERM_ALL & ~PERM_COPY
= 0x7fff7fff - no modify or copy: = 0x7fff3fff
- no transfer:
PERM_ALL & ~PERM_TRANSFER
= 0x7fffdfff - no modify, no transfer = 0x7fff9fff
Example:
permissions 0 { base_mask 7fffffff owner_mask 7fffffff group_mask 00000000 everyone_mask 7fffbfff next_owner_mask 7fffffff creator_id d929385f-41e3-4a34-a04e-f1fc39f24f12 owner_id ff9a71eb-7414-4bf8-866e-a70ddeb7c3cf last_owner_id ff9a71eb-7414-4bf8-866e-a70ddeb7c3cf group_id 00000000-0000-0000-0000-000000000000 }
Sale Info block
- First line: The token
sale_info
followed by the sale_info block version0
- Second line: open brace
{
- A sequence of sale info name/value pairs, each on its own line
- Final line: close brace
}
The sale info name/value pairs are:
sale_type
: one of:not
- not for saleorig
- the original is purchasedcopy
- a copy is purchasedcntn
- the content is purchased
sale_price
- price in L$
Example:
sale_info 0 { sale_type not sale_price 10 }
Wearable Type
- A single line with the token
type
followed by the wearable type as a decimal integer
The type is defined in the EWearableType
enumeration in newview/llwearable.h
:
- Bodyparts
WT_SHAPE
= 0WT_SKIN
= 1WT_HAIR
= 2WT_EYES
= 3
- Clothing
WT_SHIRT
= 4WT_PANTS
= 5WT_SHOES
= 6WT_SOCKS
= 7WT_JACKET
= 8WT_GLOVES
= 9WT_UNDERSHIRT
= 10WT_UNDERPANTS
= 11WT_SKIRT
= 12
Example:
type 4
Parameters
- A line with the token
parameters
followed by the number of parameter ID/value pairs as a decimal integer - A sequence of parameter/ID value pairs, each on its own line
- Parameter ID from the #Linden avatar definition file, a decimal integer
- Parameter value (or weight) is a decimal floating point value
Example:
parameters 10 781 1 800 .92 801 1 802 1 803 1 804 1 805 1 828 .18 840 0 868 .27
Texture
- A line with the token
textures
followed by the number of texture index/ID pairs as a decimal integer - A sequence of texture index/ID pairs, each on its own line
- Texture index is defined in the
ETextureIndex
enumeration inindra/llappearance/llavatarappearancedefines.h
- Texture ID is the texture's UUID in hexadecimal 8-4-4-4-12 format
- Texture index is defined in the
Texture indexes:
TEX_HEAD_BODYPAINT
= 0TEX_UPPER_SHIRT
= 1TEX_LOWER_PANTS
= 2TEX_EYES_IRIS
= 3TEX_HAIR
= 4TEX_UPPER_BODYPAINT
= 5TEX_LOWER_BODYPAINT
= 6TEX_LOWER_SHOES
= 7TEX_HEAD_BAKED
= 8 (* See below)TEX_UPPER_BAKED
= 9 (* See below)TEX_LOWER_BAKED
= 10 (* See below)TEX_EYES_BAKED
= 11 (* See below)TEX_LOWER_SOCKS
= 12TEX_UPPER_JACKET
= 13TEX_LOWER_JACKET
= 14TEX_UPPER_GLOVES
= 15TEX_UPPER_UNDERSHIRT
= 16TEX_LOWER_UNDERPANTS
= 17TEX_SKIRT
= 18TEX_SKIRT_BAKED
= 19 (* See below)TEX_HAIR_BAKED
= 20 (* See below)
* When the avatar changes a wearable, the simulator requests that the viewer rebake the *_BAKED textures; these are then uploaded as new temporary assets to the system so that the individual assets do not need to be downloaded. The *_BAKED textures are not referenced by wearables.
Example:
textures 1 1 08115557-ad4d-09ed-6b39-2ffc1f2b58b2