|
JSR-184 Public Review Draft - Apr. 30, 2003 | |||||||||
PREV NEXT | FRAMES NO FRAMES |
For more details of the mechanisms for loading a JSR-184 compliant file, please refer to the documentation for the Loader class.
Type Name Description Byte A single, unsigned byte. Int16 A signed 16 bit value, stored as two bytes, lower byte first. UInt16 An unsigned 16 bit value, stored as two bytes, lower byte first. Int32 A signed 32 bit value, stored as four bytes, lowest byte first. UInt32 An unsigned 32 bit value, stored as four bytes, lowest byte first. Float32 A single precision floating point value, in 32-bit format as defined by IEEE-754. This is stored as four bytes, with the least significant byte of the mantissa first, and the exponent byte last.
Note that only normal numeric values and positive 0 can be stored. Special values such as denormals, infinities, NaNs, negative 0, and indefinite values are disallowed and must be treated as errors. String A null-terminated Unicode string, coded as UTF-8. Boolean A single byte with the value 0 (false) or 1 (true). Other values are disallowed and must be treated as errors.
Type Name Description Composition Vector2D A 2D vector.Float32 x;
Float32 y; Vector3D A 3D vector.Float32 x;
Float32 y;
Float32 z; Quaternion A unit quaternion. Although only the three imaginary elements strictly need to be output (the real element can be calculated knowing that the overall magnitude of the vector is 1.0), all four elements are in fact presented. This reduces the load on the loader, and can optionally be used as a validity check.Float32 i;
Float32 j;
Float32 k;
Float32 real; Matrix A 4x4 generalized matrix. The 16 elements of the matrix are output in the same order as they are retrieved using the API Transform.get method. In other words, in this order:0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15Float32 elements[16]; ColorRGB A color, with no alpha information. Each component is scaled so that 0x00 is 0.0, and 0xFF is 1.0.Byte red;
Byte green;
Byte blue; ColorRGBA A color, with alpha information. Each component is scaled so that 0x00 is 0.0, and 0xFF is 1.0. The alpha value is scaled so that 0x00 is completely transparent, and 0xFF is completely opaque.Byte red;
Byte green;
Byte blue;
Byte alpha; ObjectIndex The index of a previously encountered object in the file. Although this is serialized as a single unsigned integer, it is included in the compound type list because of the additional semantic information embodied in its type. A value of 0 is reserved to indicate a null reference; actual object indices start from 1. Object indices must refer only to null or to an object which has already been created during the input serialization of a file - they must be less than or equal to the index of the object in which they appear. Other values are disallowed and must be treated as errors.UInt32 index; Type[] A variable-length array of any type is always output in a counted form, with the count first. Each element is then output in index order, starting from 0. The last element has index (count-1). If the array is empty, then only a 0 count is output.UInt32 count;
Type arrayValue[0];
Type arrayValue[1];
...etc. Type[count] Arrays with an explicit length are either always have the same constant number of elements, or this count is specified elsewhere, so only the elements are output. Each element is then output in index order, starting from 0. The last element has index (length-1). If the array is empty, then nothing is output.Type arrayValue[0];
Type arrayValue[1];
...etc.
The reason for having different sections is that some of the objects, such as the mesh objects, should be compressed to reduce file size, whereas other objects, such as the header object, should not be compressed. The header object must be kept uncompressed since it should be easy to read quickly .
File Identifier Section 0 File Header Object Section 1 Scene Objects Section 2 Scene Objects ... ... Section n Scene Objects
The first section, Section 0, must be present, must be uncompressed and must contain only the header object. This object contains information about the file as a whole, and is discussed in detail in Section 10.1.
There must be at least one other non-empty section in the file, containing at least one object. A file containing no objects is therefore not a valid JSR184 file, and must be treated as an error.
The file identifier is a unique set of bytes that will differentiate the file from other types of files. It consists of 12 bytes, as follows:
This can also be expressed using C-style character definitions as:Byte[12] FileIdentifier = { 0xAB, 0x4A, 0x53, 0x52, 0x31, 0x38, 0x34, 0xBB, 0x0D, 0x0A, 0x1A, 0x0A }
The rationale behind the choice values in the identifier is based on the rationale for the identifier in the PNG specification. This identifier both identifies the file as a JSR184 file and provides for immediate detection of common file-transfer problems.Byte[12] FileIdentifier = { '«', 'J', 'S', 'R', '1', '8', '4', '»', '\r', '\n', '\x1A', '\n' }
In this document, we will talk about "sections that are compressed" and "sections that are uncompressed". In reality, we will mean "sections where the objects are compressed", and "sections where the objects are uncompressed".
Each section has the following structure:
We will now go through the individual parts of the section.Byte CompressionScheme UInt32 TotalSectionLength UInt32 UncompressedLength Byte[] Objects UInt32 Checksum
CompressionScheme must be one of the following values:
Example:
0 Uncompressed, Adler32 Checksum 1 ZLib compression, 32 k buffer size, Adler32 Checksum 2...255 Reserved
indicates that the Objects field in the section is compressed using zlib with 32 k buffer size.Byte CompressionScheme = 1;
The values 2...255 are reserved for future releases and are disallowed. A loader that follows the specification must report an error if they are found.
Example:
indicates that this section, including the CompressionScheme, TotalSectionLength, UncompressedLength, Objects and Checksum fields, will be 2056 bytes in length.UInt32 TotalSectionLength = 2056
A value of 0 in this field is legal - the section is simply ignored. However, it is recommended that any process that creates a file should check for 0 length sections and eliminate them to reduce file size.
Example:
Means that in this section, after decompression, the Objects field is 4560 bytes in length.UInt32 UncompressedLength = 4560
The structure of each individual object's data is documented in Section 10 and Section 11.
Example:
On limited devices, we might not be able to afford to load an entire section before interpreting it. Thus the loader may start interpreting the objects before knowing that the section as a whole is correct. However, the checksums are still useful in that we at least know afterwards that there was an otherwise undetected error if the checksums differed.UInt32 Checksum = 0xffe806a3
Even on a system that can afford to load an entire section before loading it, it is possible to have errors in the file. The content creation program can have a defect, the transmission of the file could be error-prone, or the file could have been altered as part of a deliberate attack on the device. Thus it is important that the loader tries to detect errors also in files that have correct checksums.
The loader implementation may decide not to compute (and/or check) the checksum. Thus, a file with erroneous checksums is not guaranteed to be rejected. However, a file with erroneous checksums is not a JSR 184 compliant file and must not pass a strict verification test.
Each object in the file represents one object in the scene graph tree, and is stored in a chunk. The structure of an object chunk is as follows:
Byte ObjectType UInt32 Length Byte[] Data
The values 0 and 0xFF are special: 0 represents the header object, and 0xFF represents an external reference.
Example:
This means that the current object is a TexturingMode object (see Section 12).Byte ObjectType = 18
Example:
indicates that the Data field of this object spans 2032 bytes in the (decompressed) file.UInt32 Length = 2032
For instance, if the object just contained a single color, the Data would be a 3 byte long array, where the first byte represents the red component, the second byte the green component, and the third byte the blue component.
Attempts to read off the end of an object's data are disallowed and must be signalled as errors. An example of this would be an object with a reported length of 32 bytes, but which internally specifies an array with 65537 members.
Conversely, the serialization code for each object may also check that each byte of the data belongs to a valid interpretation. Additional bytes after the end of an object's valid data are disallowed. Depending on the implementation, this may be difficult to determine this condition on the target platform, but any file which contains "extra" data in object chunks is not a JSR 184 compliant file and must not pass a strict verification test.
By definition, the root of the tree will be sent last.
For output, it is possible to use a "leaves first" strategy - start by serializing all the objects that do not reference other objects, and then all the objects that refer to the objects already sent, and so it continues until all objects are sent.
Alternatively, a "depth first" strategy can be used, where each object recursively applies the following procedure, to build up a table of references in the correct order. (It is assumed that the table is initially empty.)
Each object can then be serialized from the reference table in order.BuildReferenceTable: for each reference in this object, call BuildReferenceTable on the referred object if this object is not already in the reference table, append this object to the reference table.
For example, assume that we have the following tree structure:
One valid ordering of the objects is C D F B E A. This is the ordering that occurs if the "leaves first" method is used. Note that other leaf-first orderings are also valid, for instance F D C E B A.
The "depth-first" method produces valid orderings where interior nodes in the graph may be sent before all the leaves have been sent. An ordering produced by the depth-first method discussed above might be C D B F E A.
The only important thing is that any objects referenced by a particular object are sent before the object itself.
With this flexibility, the ordering of references can be forced by the file creator if this is advantageous. For example, if we wish textures to be sent in a separate section that is uncompressed. Thus, if we have the following tree:
where T1 and T2 are textures, we can send the scene graph using, for instance:
Other orderings are also possible, for instance:
Identifier "JSR184" Section 0 Uncompressed File Header Object Section 1 Uncompressed T1 T2 Section 2 Compressed D B E A
or even (with a naive file creator):
Identifier "JSR184" Section 0 Uncompressed File Header Object Section 1 Uncompressed T1 T2 Section 2 Compressed D E B A
Because multiple root-level objects are allowed in the file format, there is no obvious end point in the data. In order that the loader can determine that the file has ended, the total length of the file is stored in the header. Reading from the file is ended when the total number of bytes is reached. At this point, any objects not yet linked into the scene graph are treated as root-level objects and returned to the application.
Identifier "JSR184" Section 0 Uncompressed File Header Object Section 1 Uncompressed T1 Section 2 Compressed D Section 3 Uncompressed T2 Section 4 Compressed B E A
A reference to an object is serialized as an integer containing its index within the file. The serialization order constraint can be expressed as follows:
For an object with index i, a reference index r within it is only valid if r <= i. Invalid reference indices must be treated as an error.
An object reference must refer to an object of a valid type for the reference involved. For example, the reference from an Appearance object to a Material object must actually refer to a Material object. If the referred object type is incorrect, this must be treated as an error.
For instance, for the following tree of references, where X is a shared object
A possible ordering would be D X B E A. Both the leaves-first and the depth-first algorithms described above will generate valid orderings.
In the case where rewinding the stream is not possible, it is also possible to do subtree loading in just one pass. This is achieved by loading everything up until the root node of the desired subtree, and then letting the garbage collection remove everything that is not referred to by the subtree. However, such an implementation would consume more memory than the two-pass implementation above. In the worst case, this is no different from loading the entire scene. For example, if the file contains a 3D map of the whole world and all you want is a specific house, you may still need to load the entire world and then delete everything but the house, if the house is the last object in the file.
The practical upshot of this is that any error detected in any of the files that may make up a world being loaded must result in a safe abort of the loading process and the throwing of a single exception to the main application.
It is up to the application what action, if any, is taken in the event of a loading error. Options range from an apologetic alert to the user ("Download failed!"), up through sophisticated error recovery schemes involving alternate file locations, or even different content in extreme cases.
Byte[2] VersionNumber Boolean ExternalLinks UInt32 TotalFileSize UInt32 ApproximateContentSize String AuthoringField
There must be exactly one Header object in a file, and it must be the only object in the first section of the file, which in turn must be uncompressed.
VersionNumber is a unique version number identifying variants of the file fomat. For instance, the Java Specification version numbering scheme. Only one variant is currently specified: version number 1.00. This must be indicated by VersionNumber = {1, 0}. The first number is major revision number, followed by minor revision.
ExternalLinks is a boolean that describes whether this file is self-contained or includes URIs for other files, such as textures or geometries.
TotalFileSize is the total size of the file, from the start to the end. It will be used in the loading, so it must be correct. (That is, it is not a hint.) For example, a file of size 6783 would define this field as TotalFileSize = 6783.
ApproximateContentSize contains the total number of bytes required to dowload the entire scene, including external links such as textures and geometry. This is provided as a hint, so that the user can know how much data he/she will pay for before loading the entire scene. The ApproximateContentSize field is also necessary in order to produce a good progress bar during the loading of the scene.
It should be noted that this information is only a hint. For instance, the file sizes of the objects that this file is linked to might have changed. Due to this, it is called "approximate" content size. Note that ApproximateContentSize should be equal to TotalFileSize if ExternalFiles is false.
For example, a file of 6083 bytes, with an external reference to another file of 10700 bytes would set ApproximateContentSize = 16783.
AuthoringField consists of a single nul-terminated UTF-8 string. The content of the string is not defined, and may include any information that the authoring environment wishes to place into it. Its most common purpose is mainly to make it possible to put a copyright note on the file, for example: AuthoringField = "Blast4Fun (C) 2003 Extreme Games Inc."
Note that, if the string just contains numbers and letters from the English alphabet, the UTF-8 encoding will be the same as ASCII encoding.
Instead of storing an object in-place, it is possible to have an external reference, in the form of a URI. This is stored in the object data as a single, nul-terminated UTF-8 string.String URI
Relative URIs are relative to the file in which they are found, as usual. For example, a URI of "http://www.gamesforfun.com/objs/redcar.m3d", indicates another file in the JSR184 file format, at an absolute address, and "bluecartexture.png" indicates a PNG file in the same location as the current file.
If an external reference cannot be loaded, this will result in an error, causing the parent file to be "unloadable".
Loops of external references (e.g. file A references file B which in turn references file A again) are illegal and will result in a loading error.
The loader must only indicate that the loading of a file is complete when all external references within it have also been successfully loaded and the references type checked.
Type checking of an external reference is deferred until the external reference has been loaded. Only at this point is it possible to check that the loaded object is of the correct type to be used in place of the external reference. For example, if the external reference is referred to as if it were an Appearance object, then the check that it is indeed an Appearance must be deferred until after loading the referred file.
External reference loading must support both M3D and PNG file types in order to satisfy the specification.
For M3D format files, the external reference must be able to load another JSR184 format file containing a single root-level object. If more than one root-level object is defined, then the first root-level object will be used, and the other objects and their descendants discarded.
For PNG format files, the external reference must be able to reference a valid PNG file, in which case the object created is a single instance of Image2D. PNG loaders are not required to support 48-bit pixel formats.
References to other types of file may be loadable on some implementations, but any file containing them is not considered JSR184 compliant and must not pass a strict conformance check.
Classes without a serialized form (e.g. Graphics3D) are shown here for completeness, but are indicated as "not a serializable class".
Detailed information about each field is not given - it should be assumed that the data have the same meanings as those assigned in the API. Where data is serialized in a form which is different from the way it is specified in the API, this alternate form is documented here.
Float32 speed; Int32 weight; Int32 activeIntervalStart; Int32 activeIntervalEnd;
The propertyID field must hold a valid enumerated value, as specified in the class definition. Other values must be treated as errors.ObjectIndex keyframeSequence; ObjectIndex animationController; UInt32 propertyID;
These are simply references to each of the objects aggregated together to form an appearance. There are as many texture objects in the textures array as there are active texture units for this appearance.Byte layer; ObjectIndex compositingMode; ObjectIndex fog; ObjectIndex geometryMode; ObjectIndex material; ObjectIndex[] textures;
The backgroundImageModeX and backgroundImageModeY fields must each hold a valid enumerated value, as specified in the class definition. Other values must be treated as errors.ColorRGBA backgroundColor; ObjectIndex backgroundImage; Byte backgroundImageModeX; Byte backgroundImageModeY; Float32 backgroundImageOffsetX; Float32 backgroundImageOffsetY;
The projectionType field must hold a valid enumerated value, as specified in the class definition. Other values must be treated as errors.Byte projectionType; IF projectionType==GENERIC, THEN Matrix projectionMatrix; ELSE IF projectionType==PERSPECTIVE, THEN Float32 fovy; Float32 AspectRatio; Float32 near; Float32 far; ELSE Float32 height; Float32 AspectRatio; Float32 near; Float32 far; END
The blending field must hold a valid enumerated value, as specified in the class definition. Other values must be treated as errors.Boolean depthTestEnabled; Boolean depthWriteEnabled; Boolean colorWriteEnabled; Byte blending; Byte alphaThreshold; Float32 depthOffsetFactor; Float32 depthOffsetUnits;
The alphaThreshold field is stored as a byte to save space. It is mapped so that 0x00 is equivalent to 0.0 (completely transparent), and 0xFF is equivalent to 1.0 (completely opaque).
The mode field must hold a valid enumerated value, as specified in the class definition. Other values must be treated as errors.ColorRGB color; Byte mode; IF mode==FOG_EXPONENTIAL, THEN Float32 density; ELSE IF mode==FOG_LINEAR, THEN Float32 near; Float32 far; END
The modes field must hold a valid enumerated value, as specified in the class definition. Other values must be treated as errors.UInt16 modes; Boolean localCameraLightingEnabled; Boolean perspectiveCorrectionEnabled;
ObjectIndex[] children;
The format field must hold a valid enumerated value, as specified in the class definition. Other values must be treated as errors.Byte format; Boolean isMutable; UInt32 width; UInt32 height; IF isMutable==false, THEN Byte[] palette; Byte[] pixels;END
For a palettised format, the pixels array contains a single palette index per pixel, and the palette array will contain up to 256 entries, each consisting of a pixel specifier appropriate to the format chosen.
For a non-palettised format, the palette array will be empty, and the pixels array contains a pixel specifier appropriate to the format chosen.
In a pixel specifier, each byte is scaled such that 0 represents the value 0.0 and 255 represents the value 1.0. The different formats require different data to be serialized, as follows:
The interpolation field must hold a valid enumerated value, as specified in the class definition. Other values must be treated as errors.Byte interpolation; Boolean isClosed; UInt32 duration; UInt32 validRangeFirst; UInt32 validRangeLast; UInt32 componentCount; UInt32 keyframeCount; FOR each key frame... Int32 time; Float32[componentCount] vectorValue; END
All of the vectorValue arrays are the same size, so a separate count is stored outside the individual keyframe's data rather than with each array.
After serialization in, the KeyframeSequence object must be validated according to the values in validRangeFirst and validRangeLast so that it is possible to use the sequence immediately.
Float32 attenuationConstant; Float32 attenuationLinear; Float32 attenuationQuadratic; ColorRGB color; Boolean directional; Float32 intensity; Float32 spotAngle; Float32 spotExponent; UInt32 scopeMask;
ColorRGBA ambientColor; ColorRGBA diffuseColor; ColorRGBA emissiveColor; ColorRGBA specularColor; Float32 shininess; Boolean vertexColorTrackingEnabled;
ObjectIndex vertexBuffer; UInt32 submeshCount; FOR each submesh... ObjectIndex indexBuffer; ObjectIndex appearance; END
UInt32 morphTargetCount; FOR each target buffer... ObjectIndex morphTarget; Float32 initialWeight; END
The zTarget and yTarget fields must each hold a valid enumerated value, as specified in the class definition. Other values must be treated as errors.Boolean enable; Byte alphaFactor; UInt32 scopeID; Boolean isGeneralTransform; IF isGeneralTransform===TRUE, THEN Matrix transform; ELSE Vector3D translation; Vector3D scale; Quaternion orientation; END Byte zTarget; Byte yTarget; ObjectIndex zReference; ObjectIndex yReference;
The alphaFactor field is stored as a byte to save space. It is mapped so that 0x00 is equivalent to 0.0 (fully transparent), and 255 is equivalent to 1.0 (fully opaque).
The userID field may be any value.UInt32 userID; ObjectIndex[] animationTracks; UInt32 userParameterCount; FOR each user parameter... UInt32 parameterID; Byte[] parameterValue; END
The user parameter data contains enough data to create a java.util.HashTable object. This contains key/value pairs, with the key being the parameterID, and the value being the parameterValue byte array. The meanings of the IDs, and the contents of the byte arrays, are defined by the application and may have any value.
The behaviour of the java.util.HashTable class does not allow multiple objects with the same key. Therefore, duplicate parameterID values are not allowed and must be reported as an error.
If an object has no user parameters, the userParameterCount field should be 0, and the userObject field in the resulting Object3D instance will be null, rather than indicating a HashTable object with no content. The HashTable containing the parameters, if it exists, can be retrieved through the API using the userObject public field.
ObjectIndex skeleton; UInt32 transformReferenceCount; FOR each bone reference... ObjectIndex transformGroup; UInt32 firstVertex; UInt32 vertexCount; Int32 weight; END
ObjectIndex image; ObjectIndex appearance; Boolean isScaled; Int32 cropX; Int32 cropY; Int32 cropWidth; Int32 cropHeight;
The levelFilter, imageFilter, wrappingS, wrappingT, and blending fields must each hold a valid enumerated value, as specified in the class definition. Other values must be treated as errors.ObjectIndex image; ColorRGB blendColor; Byte blending; Matrix transform; Byte wrappingS; Byte wrappingT; Byte levelFilter; Byte imageFilter;
The explicit field will be true if the index buffer was constructed with explicit indices, and true if constructed with implicit indices.Boolean explicit; IF explicit == true, THEN UInt32[] indices; ELSE UInt32 startIndex; END UInt32[] stripLengths;
The componentSize and componentCount fields must each hold a valid value, as specified in the constructor definition. Other values must be treated as errors.Byte componentSize; Byte componentCount; UInt16 vertexCount; FOR each vertex... IF componentSize==1, THEN Byte[componentCount] components; ELSE Int16[componentCount] components; END END
If a texture coordinate array has only two components, the corresponding texCoordBias[2] element must be 0.0.ColorRGBA defaultColor; ObjectIndex positions; Float32[3] positionBias; Float32 positionScale; ObjectIndex normals; ObjectIndex colors; UInt32 texcoordArrayCount; FOR each texture coordinate array... ObjectIndex texCoords; Float32[3] texCoordBias; Float32 texCoordScale; END
Null texture coordinate arrays are never serialized, regardless of their position. A single texture coordinate array will therefore always be serialized as belonging to texturing unit 0, regardless of its original unit it was assigned to.
ObjectIndex activeCamera; ObjectIndex background; ColorRGB ambient;
Note that IndexBuffer, Node, and Object3D are abstract classes and cannot be instantiated directly. They therefore do not appear in this list.
ObjectType value Object Type 00 Header Object 01 AnimationController 02 AnimationTrack 03 Appearance 04 Background 05 Camera 06 CompositingMode 07 Fog 08 GeometryMode 09 Group 10 Image2D 11 TriangleStripArray 12 Light 13 Material 14 Mesh 15 MorphingMesh 16 SkinnedMesh 17 Texture2D 18 Sprite 19 KeyframeSequence 20 VertexArray 21 VertexBuffer 22 World 23 ... 254 Reserved for use in future versions of the file format 255 External Reference
|
JSR-184 Public Review Draft - Apr. 30, 2003 | |||||||||
PREV NEXT | FRAMES NO FRAMES |