Zonja Capalini

Partial documentation for SceneObjectGroup serialization in XML2 format

Warning: This is a work-in progress. I’m publishing this article now to see whether it generates interest and which kind of feedback I get. The material published here is incomplete, and contains for sure errors, ommisions and inaccuracies. I plan on extensively modifying it during the following days. Please take that into account when reading it.

The XML2 format

The XML2 format is used in Opensim to serialize objects or linksets (called “SceneObjectGroups” in the Opensim parlance). XML2 dumps of objects can be obtained using the ‘save xml2’ or ‘save prims xml2’ console commands, and are used internally to serialize objects in Opensim Archive (OAR) and Inventory Archive (IAR) files. For example, OARs are gzipped tar files containing a directory called ‘objects’ with one XML2 file for each linkset in the region.

XML2 files are standard XML files using an ASCII encoding and no whitespace. This means that there’s no extra indenting or formatting between tags to make the file more pleasant to the eye. You can use any XML editor (including Internet Explorer) to display an XML2 file with some additional prettyprinting and formatting.

XML2 is practically undocumented, but the fact that it’s undocumented is itself (informally) documented :-), in comments scattered through the Opensim wiki and in the Opensim-dev and Opensim-users lists. Essentially, what this means is that the format is subject to change, but not much change: attributes (i.e., new tags) may be added to the format without breaking it — the developers program the classes taking this possibility into account and storing default values when an attribute is expected but not present (for example, if you’re loading an old OAR file which does not have the ‘AllowedDrop’ attribute into a newer installation which does have this attribute).

In this article I document partially the structure of XML2 files using a variant of the BNF notation. I include the productions for most of the format, interspersing comments wherever I have some idea of the meaning of the tag contents. I’ve obtained this information by manually looking at the XML2 files when developing the simple OAR editor I called ZOE and in recent modifications to that editor. I’ve also taken a look at the source code for Opensim and at the code for libopenmetaverse. There may be errors and there are for sure omissions; any kind of comment, addition, correction or clarification would be greatly appreciated.

The whole SceneObjectGroup/SceneObjectPart model is about to be heavily refactored to be able to include very cool things like hyerarchical objects or meshes, and this will most probably require a new format (XML3?) to serialize Opensim objects. I am writing this article as a way to teach myself, and I’m making it public in case somebody else can find its contents useful. Please keep in mind at all times that this is not official documentation :-) — that’s one of the reasons why this appears as a blog article instead as a page in the Opensim wiki, the other being that I’d prefer to get some feedback before writing such a complicated wiki page, in case it’s considered useful to have it.

SceneObjectGroups

An Opensim “object” or “linkset” is a linked collection of “parts” (prims or prim-like objects, like Linden trees), called a “SceneObjectGroup”. This collection cannot be empty, i.e., it contains always at least one part, but it might contain several, in which case there is a distinguished part called the “root” part. The XML2 representation of a SceneObjectGroup, thus, contains the root part, the (possibly empty) collection of the other parts, and (optionally) the saved states of the scripts running in the linkset, so that a “load oar” is as equivalent as possible to a region restart.

  SceneObjectGroup ::= '<SceneObjectGroup>'
                            RootPart
                            OtherParts
                           [GroupScriptStates]
                       '</SceneObjectGroup>'

Parts are technically called “SceneObjectPart”s.

  RootPart ::= SceneObjectPart

When there is only a part, an empty “OtherParts” tag is used; otherwise, the sequence of the other parts are is enclosed between matching “OtherParts” tags.

  OtherParts ::= '<OtherParts />'
               | '<OtherParts>' SceneObjectPart+ '</OtherParts>'

The GroupScriptStates section may be absent; when present, a sequence of SavedScriptStates is enclosed between matching “GroupScripStates” tags:

  GroupScriptStates ::= '<GroupScriptStates>'
                            SavedScriptState+
                        '</GroupScriptStates>'

SavedScriptStates are, for the moment, undocumented, and will probably remain so until some changes are made in the Opensim script engine:

  SavedScriptState ::= TBD

Basic types and non-terminals

We will now need a set of basic non-terminals so that we don’t have to include BNF for things that don’t interest us at this stage, like real numbers, integers or text strings:

  bool       ::= 'true' | 'false';
  byte       ::= (* a natural number >= 0 and <= 255 *);
  sbyte      ::= (* a whole number >= -128 and <= 127 *);
  ushort     ::= (* a natural number >= 0 and <= 65,535 *);
  int        ::= (* a whole number >= –2,147,483,648 and <= 2,147,483,647 *);
  uint       ::= (* a natural number >= 0 and <= 4,294,967,295 *);
  ulong      ::= (* a natural number >= 0 and <= 18,446,744,073,709,551,615 *);
  uuid       ::= (* see http://en.wikipedia.org/wiki/Universally_Unique_Identifier *);
  float      ::= (* a real number, 7 digits of precision,
                 between 1.5 x 10–45 and 3.4 x 1038 *);
  string     ::= (* a descriptive string *);
  TBD        ::= (* To Be Documented *);
  Vector3    ::= '<X>' float '</X>'
                 '<Y>' float '</Y>'
                 '<Z>' float '</Z>';
  Quaternion ::= '<X>' float '</X>'
                 '<Y>' float '</Y>'
                 '<Z>' float '</Z>'
                 '<W>' float '</W>';

SceneObjectParts

Please refer to SceneObjectPart.cs in the Opensim source for details.

  SceneObjectPart ::= SOPStart SOPContents SOPEnd
  SOPStart ::= '<SceneObjectPart'
               ' xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance'
               ' xmlns:xsd="http://www.w3.org/2001/XMLSchema">'
  SOPEnd ::= '</SceneObjectPart>'

The extra attributes in the “<SceneObjectPart>” start tag are due to the fact that SceneObjectParts are serialized automatically by the .NET/Mono runtime (while SceneObjectGroups are serialized manually).

  SOPContents ::= [AllowedDrop] CreatorID FolderID InventorySerial
                  TaskInventory ObjectFlags UUID LocalId Name Material
                  PassTouches RegionHandle ScriptAccessPin GroupPosition
                  OffsetPosition RotationOffset Velocity AngularVelocity
                  Acceleration Description Color Text SitName TouchName
                  LinkNum ClickAction Shape Scale UpdateFlag
                  SitTargetOrientation SitTargetPosition SitTargetPositionLL
                  SitTargetOrientationLL ParentID CreationDate Category
                  SalePrice ObjectSaleType OwnershipCost GroupID
                  OwnerID LastOwnerID BaseMask OwnerMask GroupMask
                  EveryoneMask NextOwnerMask Flags CollisionSound
                  CollisionSoundVolume

Remember that the list of attributes of a SceneObjectPart can change between different releases of Opensim. For example, older version 0.2 OARs don’t include an AllowedDrop attribute (that’s why I have marked it as optional), and newer SceneObjectParts may include new attributes not specified here.

Most attributes are represented by the basic types defined above, exceptuating TaskInventory, which is a list of TaskInventoryItems representing the contents of a prim (i.e., what’s on its “Contents” tab) and Shape, which is itself a structured attribute with many subattributes (please refer to PrimitiveBaseShape.cs in the Opensim source for details:

  Shape ::= '<Shape>'
      ProfileCurve TextureEntry ExtraParams PathBegin PathCurve
      PathEnd PathRadiusOffset PathRevolutions PathScaleX PathScaleY
      PathShearX PathShearY PathSkew PathTaperX PathTaperY PathTwist
      PathTwistBegin PCode ProfileBegin ProfileEnd ProfileHollow
      Scale State ProfileShape HollowShape SculptTexture SculptType
      SculptData FlexiSoftness FlexiTension FlexiDrag FlexiWind
      FlexiForceX FlexiForceY FlexiForceZ LightColorR LightColorG
      LightColorB LightColorA LightRadius LightFalloff LightIntensity
      FlexiEntry LightEntry SculptEntry
    '</Shape>'

For our purposes, the attributes of the SceneObjectPart and the attributes of its Shape attribute can be treated as a homogeneous set. You will notice that there is a Scale attribute both in the SceneObjectPart and in its Shape attribute; these are one and the same (i.e., they have always the same value). We will classify the combined set of attributes following the tabs of the standard object editor in the Second Life type of viewers.

General tab
Object tab
Features tab
Texture tab
Content tab
Other attributes

General tab

0816 - The 'General' tab, 1

  Name ::= '<Name />'
         | '<Name>'
              string
           '</Name>'

Name of this part. If this is the root part, this is also the name of the whole SceneObjectGroup.

  Description ::= '<Description />'
                | '<Description>'
                     string
                  '</Description>'

A (possibly empty) description for the part. If the part is the root part, this is also the description for the whole SceneObjectGroup.

  CreatorID ::= '<CreatorID><Guid>' uuid '</Guid></CreatorID>'

Uuid of the creator of this part.

  OwnerID ::= '<OwnerID><Guid>' uuid '</Guid></OwnerID>'

Uuid of the owner of this part (and therefore of the whole SceneObjectGroup).

  LastOwnerID ::= '<LastOwnerID><Guid>' uuid '</Guid></LastOwnerID>'

Uuid of the last owner of this part. Useful when returning objects.

  GroupID ::= '<GroupID><Guid>' uuid '</Guid></GroupID>'

Uuid of the group this part (and therefore the whole SceneObjectGroup) is assigned or deeded to.

0817 - The 'General' tab,2

  BaseMask ::= '<BaseMask>' uint '</BaseMask>'

See the PermissionMask enum in Permissions.cs in the libopenmetaverse source. The following information was adapted from http://opensimulator.org/wiki/OpenSim:Permissions:

 public enum PermissionMask : uint
 {
    None        = 0;
    Transfer    = 1 << 13, //0x00002000
    Modify      = 1 << 14, //0x00004000
    Copy        = 1 << 15, //0x00008000
 // EnterParcel = 1 << 16, //0x00010000 -- Obsolete
 // Terraform   = 1 << 17, //0x00020000 -- Obsolete
 // OwnerDebit  = 1 << 18, //0x00040000 -- Obsolete
    Move        = 1 << 19, //0x00080000
    Damage      = 1 << 20, //0x00100000
    All         = 0x7FFFFFFF
 }

Default: PermissionMask.All. This field represents the highest amount of permissions the owner of an object can have. For example, if you set next permissions as ‘No transfer’ for an object and transfer it, the NextOwnerMask will have the Transfer bit unset (see below), this will ANDed to the BaseMask, and thus the new BaseMask will also have the Transfer bit unset, so that the new owner cannot transfer the object or make it transferable again.

  OwnerMask ::= '<OwnerMask>' uint '</OwnerMask>'

Default: PermissionMask.All. These are the current owner’s permissions for the object.

  GroupMask ::= '<GroupMask>' uint '</GroupMask>'

Default: PermissionMask.None.

  EveryoneMask ::= '<EveryoneMask>' uint '</EveryoneMask>'

Default: PermissionMask.None. These are the permissions that the general public have on the object. When the ‘Move’ flag is set, this is a ‘Anyone can Move’ object; similarly, when the ‘Copy’ flag is set, this is a ‘Anyone can Copy’ object.

  NextOwnerMask ::= '<NextOwnerMask>' uint '</NextOwnerMask>'

Default: PermissionMask.All. These are the permissions that the owner sets with the Modify, Copy and Transfer checkboxes.

BaseMask, OwnerBask and EveryoneMask  have their flags ANDed with the NextOwnerMask when the object is transferred.

  Flags ::= '<Flags>' flag [flag]* '</Flags>';

  flag ::= 'None' | 'CreateSelected' | 'ObjectModify' | 'ObjectCopy'
         | 'ObjectAnyOwner' | 'ObjectYouOwner' | 'Scripted' | 'Touch'
         | 'ObjectMove' | 'Money' | 'Phantom' | 'InventoryEmpty'
         | 'JointHinge' | 'JointP2P' | 'JointLP2P' | 'JointWheel'
         | 'AllowInventoryDrop' | 'ObjectTransfer' | 'ObjectGroupOwned' | 'ObjectYouOfficer' 
         | 'CameraDecoupled' | 'AnimSource' | 'CameraSource' | 'CastShadows'
         | 'ObjectOwnerModify' | 'TemporaryOnRez' | 'Temporary' | 'ZlibCompressed'

A set of flags. See the PrimFlags enum in Primitive.cs in the libopenmetaverse source. The following information was adapted from http://opensimulator.org/wiki/OpenSim:Permissions:

 public enum ObjectFlags : uint
 {
 None = 0,
            Physics = 0x00000001, CreateSelected = 0x00000002,     ObjectModify = 0x00000004,       ObjectCopy = 0x00000008,
     ObjectAnyOwner = 0x00000010, ObjectYouOwner = 0x00000020,         Scripted = 0x00000040,            Touch = 0x00000080,
         ObjectMove = 0x00000100,          Money = 0x00000200,          Phantom = 0x00000400,   InventoryEmpty = 0x00000800,
         JointHinge = 0x00001000,       JointP2P = 0x00002000,        JointLP2P = 0x00004000,       JointWheel = 0x00008000,
 AllowInventoryDrop = 0x00010000, ObjectTransfer = 0x00020000, ObjectGroupOwned = 0x00040000, ObjectYouOfficer = 0x00080000,
    CameraDecoupled = 0x00100000,     AnimSource = 0x00200000,     CameraSource = 0x00400000,      CastShadows = 0x00800000,
  //not defined yet   0x01000000,                  0x02000000,                    0x04000000,                    0x08000000,
  ObjectOwnerModify = 0x10000000, TemporaryOnRez = 0x20000000,        Temporary = 0x40000000,   ZlibCompressed = 0x80000000
 }

Default: ObjectFlags.None (0).

These bits are different from the previous masks, in the sense that they contain the ‘actual’ or ‘calculated’ values for the object (and many more options, to store, for example, whether the object is physical, phantom, or touch).

  SalePrice ::= '<SalePrice>' int '</SalePrice>'

Sale price.

  ObjectSaleType ::= '<ObjectSaleType>' byte '</ObjectSaleType>'

TBD

  OwnershipCost ::== '<OwnershipCost>' int '</OwnershipCost>'

TBD

Object tab

  GroupPosition ::= '<GroupPosition>' Vector3 '</GroupPosition>'

A vector defining the position of the whole SceneObjectGroup, that is, of its root part. It has the same value for all the SceneObjectParts — each individual part individualizes its position by defining an OffsetPosition (i.e., for each part, its position = GroupPosition + OffsetPosition).

  OffsetPosition ::= '<OffsetPosition>' Vector3 ''</OffsetPosition>'

Offset of this part, relative to the position (GroupPosition) of the root part. See GroupPosition.

  Scale ::= '<Scale>' Vector3 '</Scale>'

Size of the part. Please note that the Scale attribute of the SceneObjectPart and the Scale attribute of its Shape attribute have always the same value.

  RotationOffset ::= '<RotationOffset>' Quaternion '</RotationOffset>'

Rotation of the SceneObjectPart, relative to the region if this is the root part, or relative to the root part if this is not the root part.

  ProfileCurve ::= '<ProfileCurve>' byte '</ProfileCurve>'

A logical OR of the byte values of the HollowShape and ProfileShape attributes.

  ProfileBegin ::= '<ProfileBegin>' ushort '</ProfileBegin>'

[See Opensim.Region.ScriptEngine.Shared.Api.LSL_Api,  SetPrimitiveBlockShapeParams and SetPrimitiveShapeParams.]

When Building Block Type is “Box”, “Cylinder”, “Prism”, “Torus”,”Tube”, “Ring”: (ushort) (50,000 * (Value of “Path Cut Begin”))
When Building Block Type is “Sphere”: (ushort) (50,000 * (Value of “Dimple Begin”)).
When Building Block Type is “Sculpted”: 0.

  ProfileEnd ::= '<ProfileEnd>' ushort '</ProfileEnd>'

[See Opensim.Region.ScriptEngine.Shared.Api.LSL_Api,  SetPrimitiveBlockShapeParams and SetPrimitiveShapeParams.]

When Building Block Type is “Box”, “Cylinder”, “Prism”, “Torus”, “Tube”, “Ring”: (ushort) (50,000 * (1 – (Value of “Path Cut End”))).
When Building Block Type is “Sphere”: (ushort) (50,000 * (1 – (Value of “Dimple End”))).
When Building Block Type is “Sculpted”: 0.

  ProfileShape ::= '<ProfileShape>'
                      ( 'Circle' | 'Square' | 'IsometricTriangle' |
                        'EquilateralTriangle' | 'RightTriangle' |
                        'HalfCircle'
                      )
                   '</ProfileShape>'

Where Circle = 0, Square = 1, IsometricTriangle = 2, EquilateralTriangle = 3, RightTriangle = 4, HalfCircle = 5, but the name is stored, not the value.

When Building Block Type is “Box”, “Tube”: “Square”.
When Building Block Type is “Cylinder”, “Torus”, “Sculpted”: “Circle”.
When Building Block Type is “Prism”, “Ring”: “Equilateraltriangle”.
When Building Block Type is “Sphere”: “HalfCircle”.

0771 - Hollow

Hollow attributes: ProfileHollow and HollowShape

  ProfileHollow ::= '<ProfileHollow>' ushort '</ProfileHollow>'

[See Opensim.Region.ScriptEngine.Shared.Api.LSL_Api,  SetPrimitiveBlockShapeParams and SetPrimitiveShapeParams.]

When Building Block Type is “Box”, “Cylinder”, “Prism”, “Sphere”, “Torus”, “Tube”, “Ring”: (ushort) (50,000 *  (Value of “Hollow”)).
When Building Block Type is “Sculpted”: 0.

  HollowShape ::= '<HollowShape>'
                     ( 'Same' | 'Circle' | 'Square' | 'Triangle' )
                  '</HollowShape>'

Where Same = 0, Circle = 16, Square = 32, Triangle = 48, but the name is stored, not the value.

  PathBegin ::= '<PathBegin>' ushort '</PathBegin>'

When Building Block Type is “Sphere”, “Torus”, “Tube”, “Ring”: (ushort) (50,000 * (Value of “Path Cut Begin”)).

  PathCurve ::= '<PathCurve>' byte '</PathCurve>'

Byte value (mask?) of the enum “Extrusion” in PrimitiveBaseShape.cs: Straight = 16, Curve1 = 32,  Curve2 = 48, Flexible = 128.

When Building Block Type is “Box”, “Cylinder”, “Prism”: Extrusion.Straight.
When Building Block Type is “Sphere”, “Torus”, “Tube”, “Ring”, “Sculpted”: Extrusion.Curve1.

  PathEnd ::= '<PathEnd>' ushort '</PathEnd>'

[See Opensim.Region.ScriptEngine.Shared.Api.LSL_Api,  SetPrimitiveBlockShapeParams and SetPrimitiveShapeParams.]

When Building Block Type is “Sphere”, “Torus”, “Tube”, “Ring”: (ushort) (50,000 * (1 – (Value of “Path Cut End”))).
Zero otherwise.

  PathRadiusOffset ::= '<PathRadiusOffset>' sbyte '</PathRadiusOffset>'

[See Opensim.Region.ScriptEngine.Shared.Api.LSL_Api,  SetPrimitiveBlockShapeParams and SetPrimitiveShapeParams.]

When Building Block Type is “Torus”, “Tube”, “Ring”: (byte) (100 * (Value of “Radius”)).
Zero otherwise.

  PathRevolutions ::= '<PathRevolutions>' byte '</PathRevolutions>'

[See Opensim.Region.ScriptEngine.Shared.Api.LSL_Api,  SetPrimitiveBlockShapeParams and SetPrimitiveShapeParams.]

When Building Block Type is “Torus”, “Tube”, “Ring”: (byte) (100 * (Value of “Revolutions”)).
Zero otherwise.

  PathScaleX ::= '<PathScaleX>' byte '</PathScaleX>'

[See Opensim.Region.ScriptEngine.Shared.Api.LSL_Api,  SetPrimitiveBlockShapeParams and SetPrimitiveShapeParams.]

When Building Block Type is “Box”, “Cylinder”, “Prism”: (byte) (100 * (2.0 –  (Value of “Taper X”))).
When Building Block Type is “Torus”, “Tube”, “Ring”: (byte) (100 * (2.0 –  (Value of “Hole Size X”))).
When Building Block Type is “Sphere”, “Sculpted”: 0.

  PathScaleY ::= '<PathScaleY>' byte '</PathScaleY>'

[See Opensim.Region.ScriptEngine.Shared.Api.LSL_Api,  SetPrimitiveBlockShapeParams and SetPrimitiveShapeParams.]

When Building Block Type is “Box”, “Cylinder”, “Prism”: (byte) (100 * (2.0 –  (Value of “Taper Y”))).
When Building Block Type is “Torus”, “Tube”, “Ring”: (byte) (100 * (2.0 –  (Value of “Hole size Y”))).
When Building Block Type is “Sphere”, “Sculpted”: 0.

  PathShearX ::= '<PathShearX>' byte '</PathShearX>'

[See Opensim.Region.ScriptEngine.Shared.Api.LSL_Api,  SetPrimitiveBlockShapeParams and SetPrimitiveShapeParams.]

When Building Block Type is “Box”, “Cylinder”, “Prism”, “Torus”, “Tube”, “Ring”: (byte) (100 * (Value of “Top Shear X”)).
Otherwise: 0.

  PathShearY ::= '<PathShearY>' byte '</PathShearY>'

[See Opensim.Region.ScriptEngine.Shared.Api.LSL_Api,  SetPrimitiveBlockShapeParams and SetPrimitiveShapeParams.]

When Building Block Type is “Box”, “Cylinder”, “Prism”, “Torus”, “Tube”, “Ring”: (byte) (100 * (Value of “Top Shear Y”)).
Otherwise: 0.

  PathSkew ::= '<PathSkew>' sbyte '</PathSkew>'

[See Opensim.Region.ScriptEngine.Shared.Api.LSL_Api,  SetPrimitiveBlockShapeParams and SetPrimitiveShapeParams.]

When Building Block Type is “Torus”, “Tube”, “Ring”: (byte) (100 * (Value of “Skew”)).
Otherwise: 0.

  PathTaperX ::= '<PathTaperX>' sbyte '</PathTaperX>'

[See Opensim.Region.ScriptEngine.Shared.Api.LSL_Api,  SetPrimitiveBlockShapeParams and SetPrimitiveShapeParams.]

When Building Block Type is “Torus”, “Tube”, “Ring”: (byte) (100 * (Value of “Taper X”)).
Otherwise: 0.

  PathTaperY ::= '<PathTaperY>' sbyte '</PathTaperY>'

[See Opensim.Region.ScriptEngine.Shared.Api.LSL_Api,  SetPrimitiveBlockShapeParams and SetPrimitiveShapeParams.]

When Building Block Type is “Torus”, “Tube”, “Ring”: (byte) (100 * (Value of “Taper Y”)).
Otherwise: 0.

  PathTwist ::= '<PathTwist>' sbyte '</PathTwist>'

[See Opensim.Region.ScriptEngine.Shared.Api.LSL_Api,  SetPrimitiveBlockShapeParams and SetPrimitiveShapeParams.]

When Building Block Type is “Box”, “Cylinder”, “Prism”, “Sphere”, “Torus”, “Tube”, “Ring”: (sbyte) (100 *  (Value of “Twist End”)).
Otherwise: 0.

  PathTwistBegin ::= '<PathTwistBegin>' sbyte '</PathTwistBegin>'

[See Opensim.Region.ScriptEngine.Shared.Api.LSL_Api,  SetPrimitiveBlockShapeParams and SetPrimitiveShapeParams.]

When Building Block Type is “Box”, “Cylinder”, “Prism”, “Sphere”, “Torus”, “Tube”, “Ring”: (sbyte) (100 *  (Value of “Twist Begin”)).
Otherwise: 0.

  SculptEntry ::= '<SculptEntry>' bool '</SculptEntry>'

This SceneObjectPart is sculpted.

  SculptTexture ::= '<SculptTexture><Guid>' uuid '</Guid></SculptTexture>'

The uuid of the sculpt texture, or the null uuid (“00000000-0000-0000-0000-000000000000”) when this part is not a sculpty.

  SculptType ::= '<SculptType>' byte '</SculptType>'
Zero for non-sculpts, or one of PRIM_SCULPT_TYPE_SPHERE = 1, PRIM_SCULPT_TYPE_TORUS = 2, PRIM_SCULPT_TYPE_PLANE = 3, PRIM_SCULPT_TYPE_CYLINDER = 4.
  SculptData ::= '<SculptData />' | '<SculptData>' TBD '</SculptData>'

TBD

Features tab

0769 - Flexi

Flexible path attributes.

  FlexiEntry ::= '<FlexiEntry>' bool '</FlexiEntry>'

Whether this part has a flexible path.

  FlexiSoftness ::= '<FlexiSoftness>' int '</FlexiSoftness>'

Flexible path softness, as in the ‘Features’ tab.

  FlexiGravity ::= '<FlexiGravity>' float '</FlexiGravity>'

Flexible path gravity, as in the ‘Features’ tab.

  FlexiDrag ::= '<FlexiDrag>' float '</FlexiDrag>'

Flexible path drag, as in the ‘Features’ tab.

  FlexiWind ::= '<FlexiWind>' float '</FlexiWind>'

Flexible path wind, as in the ‘Features’ tab.

  FlexiTension ::= '<FlexiTension>' float '</FlexiTension>'

Flexible path tension, as in the ‘Features’ tab.

  FlexiForceX ::= '<FlexiForceX>' float '</FlexiForceX>'

Flexible path force X, as in the ‘Features’ tab.

  FlexiForceY ::= '<FlexiForceY>' float '</FlexiForceY>'

Flexible path force Y, as in the ‘Features’ tab.

  FlexiForceZ ::= '<FlexiForceZ>' float '</FlexiForceZ>'

Flexible path force Z, as in the ‘Features’ tab.

Partial documentation for SceneObjectGroup serialization in XML2 format

Light attributes

  LightEntry ::= '<LightEntry>' bool '</LightEntry>'

Whether this part emits light.

  LightColorR ::= '<LightColorR>' float '</LightColorR>'

The ‘Red’ component of the light color, between 0.0 and 1.0.

  LightColorG ::= '<LightColorG>' float '</LightColorG>'

The ‘Green’ component of the light color, between 0.0 and 1.0.

  LightColorB ::= '<LightColorB>' float '</LightColorB>'

The ‘Blue’ component of the light color, between 0.0 and 1.0.

  LightColorA ::= '<LightColorA>' float '</LightColorA>'

The Alpha value of the light color, between 0.0 and 1.0.

  LightIntensity ::= '<LightIntensity>' float '</LightIntensity>'

Light intensity, as in the ‘Features’ tab.

  LightRadius ::= '<LightRadius>' float '</LightRadius>'

Light radius, as in the ‘Features’ tab.

  LightFalloff ::= '<LightFalloff>' float '</LightFalloff>'

Light falloff, as in the ‘Features’ tab.

  LightCutoff ::= '<LightCutoff>' float '</LightCutoff>'

TBD

Texture tab

  TextureEntry ::= '<TextureEntry>' string '</TextureEntry>'

A Base64 encoded string. TBD.

  ExtraParams ::= '<ExtraParams>' string '</ExtraParams>'

A Base64 encoded string. TBD.

Content tab

  TaskInventory ::= '<TaskInventory />'
                  | '<TaskInventory>'
                       TaskInventoryItem+
                    '</TaskInventory>'

List of items contained in this part (i.e., what’s on the ‘Contents’ tab for an object’s settings).

Other attributes

  AllowedDrop ::= '<AllowedDrop>' bool '</AllowedDrop>'

TBD

  FolderID  ::= '<FolderID><Guid>' uuid '</Guid></FolderID>'

Same as UUID (except for very old prims).

  InventorySerial ::= '<InventorySerial>' uint '</InventorySerial>'

TBD

  ObjectFlags ::= '<ObjectFlags>' uint '</ObjectFlags>'

Flags of type OpenMetaverse.PrimFlags. See http://openmetaverse.org/viewvc/index.cgi/omf/libopenmetaverse/trunk/OpenMetaverse/Primitives/Primitive.cs?view=markup for details.

  UUID ::= '<UUID><Guid>' uuid '</Guid></UUID>'

Uuid of the part.

  LocalId ::= '<LocalId>' uint '</LocalId>'

TBD

  Material ::= '<Material>' byte '</Material>'

Semantics: Material type for a primitive. Value range: One of 0 (Stone), 1 (Metal), 2 (Glass), 3 (Wood), 4 (Flesh), 5 (Plastic), 6 (Rubber), 7 (Light). [Source: The Material enum in Primitive.cs]

  PassTouches ::= '<PassTouches>' bool '</PassTouches>'

TBD

  RegionHandle ::= '<RegionHandle>' ulong '</RegionHandle>'

TBD

  ScriptAccessPin ::= '<ScriptAccessPin>' int '</ScriptAccessPin>'

Pin for remote loading of scripts.

  Velocity ::= '<Velocity>' Vector3 '</Velocity>'

Physics-related attribute. The velocity of the prim.

  AngularVelocity ::= '<AngularVelocity>' Vector3 ''</AngularVelocity>'

Physics-related attribute. The angular velocity of the prim.

  Acceleration ::= '<Acceleration>' Vector3 '</Acceleration>'

Physics-related attribute. The acceleration of the prim.

  Color ::= '<Color />'
          | '<Color>'
               color
            '</Color>'

TBD

  Text ::= '<Text />'
         | '<Text>'
              string
           '</Text>'

Maximum length = 255, truncated otherwise. TBD

  SitName ::= '<SitName />'
            | '<SitName>'
                 string
              '</SitName>'

TBD

  TouchName ::= '<TouchName />'
              | '<TouchName>'
                   string
                '</TouchName>'

TBD

  LinkNum ::= '<LinkNum>' int '</LinkNum>'

This is a sequential number that defines the order in which parts are linked: it’s always zero for the root part, 1 for the next part, etc.

  ClickAction ::= '<ClickAction>' byte '</ClickAction>'

TBD

  UpdateFlag ::= '<UpdateFlag>' byte '</UpdateFlag>'

TBD

  SitTargetOrientation ::= '<SitTargetOrientation>'
                              Quaternion
                           '</SitTargetOrientation>'

TBD

  SitTargetPosition ::= '<SitTargetPosition>'
                           Vector3
                        '</SitTargetPosition>'

TBD

  SitTargetPositionLL ::= '<SitTargetPositionLL>'
                             Vector3
                          '</SitTargetPositionLL>'

Same as SitTargetPosition.

  SitTargetOrientationLL ::= '<SitTargetOrientationLL>'
                                Quaternion
                             '</SitTargetOrientationLL>'

Same as SitTargetOrientation.

  ParentID ::= '<ParentID>' uint '</ParentID>'

TBD

  CreationDate ::= '<CreationDate>' int '</CreationDate>'

The date this prim was created, in TBD format.

  Category ::= '<Category>' uint '</Category>'

TBD

  CollisionSound ::= '<CollisionSound><Guid>'
                        uuid
                     '</Guid></CollisionSound>'

Uuid of TBD, or the zero uuid (“00000000-0000-0000-0000-000000000000”) when TBD.

  CollisionSoundVolume ::= '<CollisionSoundVolume>'
                              float
                           '</CollisionSoundVolume>'

TBD

  PCode ::= '<PCode>' byte '</PCode>'

Semantics: Type of primitive. Value range: One of: 9 (Prim: a Primitive), 47 (Avatar: An Avatar), 95 (Grass: Linden grass), 111 (NewTree: Linden tree), 143 (ParticleSystem: A primitive that acts as the source for a particle stream), 255 (Tree: A Linden tree). [Source: The PCode enum in Primitive.cs]

  State ::= '<State>' byte '</State>'

TBD

January 25, 2010 - Posted by | OpenSim, Tech News | ,

11 Comments »

  1. For the love of God…I plead with you. document it, partially document it, don’t document it. Whatever.

    But *name* it. And *don’t* name it “XML2”. Do you know how many XML document formats there are? Me neither, but it’s way more than two. Make up a cool name, so it can be found in Google searches of the future…

    Comment by MaggieL | January 25, 2010

  2. Wow! That’s what I’d call a vehement comment! :-)

    I’ve not named the format — that’s the responsibility of the Opensim developers, who probably have their own reasons to pick such a name. But I understand your concern: I’ve changed the name of the article to “Partial documentation for SceneObjectGroup serialization in XML2 format” — but not the url, in case somebody has already shared it, sorry about that.

    Comment by Zonja Capalini | January 26, 2010

  3. Zonja,
    thank you for this much-needed effort. I will look back here now ant then to see what I can do to help flesh it out. First, one should note that the shape values in the object fields (taper, PathScale et c) represent what is sent ‘on the wire’ thru the LL protocol, and that those values more or less each have their own conversion algorithm when compared to what is seen in the SL Viewer edit GUI. I would recommend you to try and locate where the llSetPrimParams function call is executed; I think the conversion algorithms are in there.

    Comment by Stefan Andersson | January 26, 2010

  4. Many thanks for the info. I’ve now located llSetPrimitiveParams and I’m reading it — I will update the information presented here as soon as I’ve digested the source.

    Comment by Zonja Capalini | January 26, 2010

  5. I can touch my nose with my tongue.

    Comment by Kasumi | January 26, 2010

  6. Sincerely, I envy you :-)

    Comment by Zonja Capalini | January 26, 2010

  7. Zonja,

    regarding the permissions masks (basemask, ownermask et c) have a look at

    http://opensimulator.org/wiki/OpenSim:Permissions

    a page I instigated a long time ago, when we were trying to figure the whole thing out. Yes, as late as circa 0.5 permissions were still fubar.

    Comment by Stefan Andersson | January 27, 2010

  8. The “TextureEntry” is a base64 binary serialization of the LibOMV TextureEntry.cs class. I believe this to be an unfortunate early decision not to ‘expand’ it into xml.

    The “ExtraParams” is binary add-on data mainly concerning flexis, lights and sculpties.

    See http://wiki.secondlife.com/wiki/ObjectUpdate for even more goodness.

    Comment by Stefan Andersson | January 27, 2010

  9. By the way; the prim shape is constructed by having a PathShape in the bottom, then ‘extruding’ it over a PathCurve. It helps to know that the prim types you see in the LL GUI is nothing like what it’s represented “under the hood”. A torus is a circlethat is extruded as a circle. A cylinder is a circle that is extruded ‘straight’ OR a rectangle that is extruded as a circle; what you choose will give different meaning to PathBegin adn PathEnd.

    Comment by Stefan Andersson | January 27, 2010

  10. And on another note; for example the PathTaperX/Y values are DIFFERENT in the SL GUI and LSL. Yes, thatiscorrect; there are parameters where LL aren’t consistent even with themselves. The value for taper that is referenced in the SetParams conversions are the values you would supply via LSL, not the values you would supply in the GUI.

    Comment by Stefan Andersson | January 27, 2010

  11. Many thanks for all these pointers, wow! :-)

    “Regarding the permissions masks (basemask, ownermask et c) have a look at

    http://opensimulator.org/wiki/OpenSim:Permissions

    a page I instigated a long time ago, when we were trying to figure the whole thing out. Yes, as late as circa 0.5 permissions were still fubar.”

    Thanks! I’ve cannibalized the wiki page, included two additional images, clarified the descriptions, corrected an error where “Flags” was a uint instead of a set of flags, and updated the wiki page in the process to point to the current sources (‘LLObject.cs’ is now ‘Primitive.cs’, and so on).

    I’ll reply to your other comments immediately after processing them.

    Comment by Zonja Capalini | February 14, 2010


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: