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
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.
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”.
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>'
SculptData ::= '<SculptData />' | '<SculptData>' TBD '</SculptData>'
TBD
Features tab
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.
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
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…
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.
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.
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.
I can touch my nose with my tongue.
Sincerely, I envy you :-)
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.
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.
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.
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.
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.