- 浏览: 153148 次
- 性别:
- 来自: 上海
文章分类
最新评论
-
lvbolvtian:
楼主最好贴上思路先
给你n个数,其中有且仅有三个数出现了奇数次,其余的数都出现了偶数次。用线性时间常数空间找出出现了奇数次的那三个数(代码)。 -
omooeo:
很好!谢了!
HSSF读取Excel是公式单元格处理 -
独步天下:
Apache Velocity DocBook Framework 转换中文PDF -
ph4nut:
有趣的发现,最近一直等待火炬之光2发布,希望这个版本能补上这个 ...
火炬之光(TorchLight)附魔(Enhance)的设计缺陷 -
andyjojo:
哎证明是O(n)的还真难
Array Puzzle
File Format for Mobile 3D Graphics API
Abstract
This specification defines a 3D Graphics File Format that complements the Mobile 3D Graphics API (M3G). The file format is provided as a compact and standardised way of populating a scene graph.
Contents
1 Important Notes
2 MIME Type and File Extension
3 Data Types
3.1 Fundamental Data Types
3.2 Compound Data Types
4 File Structure
5 File Identifier
6 Section
6.1 CompressionScheme
6.2 TotalSectionLength
6.3 UncompressedLength
6.4 Objects
6.5 Checksum
7 Object Structure
7.1 ObjectType
7.2 Length
7.3 Data
8 Object Ordering
8.1 Object References
8.2 Shared Objects
8.3 Subtree Loading
9 Error Handling
10 Special Object Data
10.1 Header Object
10.2 External Reference
11 Per-Class Data
11.1 AnimationController
11.2 AnimationTrack
11.3 Appearance
11.4 Background
11.5 Camera
11.6 CompositingMode
11.7 Fog
11.8 Graphics3D
11.9 Group
11.10 Image2D
11.11 IndexBuffer
11.12 KeyframeSequence
11.13 Light
11.14 Loader
11.15 Material
11.16 Mesh
11.17 MorphingMesh
11.18 Node
11.19 Object3D
11.20 PolygonMode
11.21 RayIntersection
11.22 SkinnedMesh
11.23 Sprite
11.24 Texture2D
11.25 Transform
11.26 Transformable
11.27 TriangleStripArray
11.28 VertexArray
11.29 VertexBuffer
11.30 World
12 ObjectType Values
1 Important Notes
The data here are not serialized by Java's own serialization mechanism. They are serialized by the M3G serialization mechanism, which produces and loads data streams conforming to the M3G file format specification.
For more details of the mechanisms for loading a M3G compliant file, please refer to the documentation for the Loader class.
2 MIME Type and File Extension
The MIME type for this file format is application/m3g. The file extension (for systems that do not support MIME type queries) is .m3g, to match the lowest level name in the package hierarchy.
3 Data Types
3.1 Fundamental Data Types
There are several data types which are regarded as fundamental. These are as follows:
Type Name
Description
Byte
A single, unsigned 8-bit 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.
3.2 Compound Data Types
In order to avoid having to repeatedly specify sequences of the same types many times, some compound data types are defined for convenience. The composition of these is listed to show both their makeup and the order in which the simple elements are to be serialized. These are as follows:
Type Name
Description
Composition
Vector3D
A 3D vector.
Float32 x;
Float32 y;
Float32 z;
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 15
Float32 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 deserialization 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.
4 File Structure
The file consists of the file identifier, followed by one or more sections. Thus the overall file structure looks like this:
File Identifier
Section 0 File Header Object
Section 1 External Reference Objects
Section 2 Scene Objects
Section 3 Scene Objects
... ...
Section n Scene Objects
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.
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.
If there are external references in the file, then these must all appear in a single section immediately following the header section. This section may be compressed or uncompressed. External references allow scenes to be built up from a collection of separate files, and are discussed in detail in Section 10.2.
Following these are an unspecified number of sections containing scene objects.
The file must contain the header section, plus at least one other non-empty section (containing at least one object). It is possible to have a file consisting solely of external references, or solely of scene objects.
A file containing no objects at all is not a valid M3G file, and must be treated as an error.
5 File Identifier
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:
Byte[12] FileIdentifier = { 0xAB, 0x4A, 0x53, 0x52, 0x31, 0x38, 0x34, 0xBB, 0x0D, 0x0A, 0x1A, 0x0A }
This can also be expressed using C-style character definitions as:
Byte[12] FileIdentifier = { '«', 'J', 'S', 'R', '1', '8', '4', '»', '\r', '\n', '\x1A', '\n' }
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 M3G file and provides for immediate detection of common file-transfer problems.
Byte [0] is chosen as a non-ASCII value to reduce the probability that a text file may be misrecognized as a M3G file.
Byte [0] also catches bad file transfers that clear bit 7.
Bytes [1..6] identify the format, and are the ascii values for the string "JSR184".
Byte [7] is for aesthetic balance with byte 1 (they are a matching pair of double-angle quotation marks).
Bytes [8..9] form a CR-LF sequence which catches bad file transfers that alter newline sequences.
Byte [10] is a control-Z character, which stops file display under MS-DOS, and further reduces the chance that a text file will be falsely recognised.
Byte [11] is a final line feed, which checks for the inverse of the CR-LF translation problem.
A decoder may further verify that the next byte is 0 (this is the first byte of the mandatory uncompressed header section). This will catch bad transfers that drop or alter zero bytes.
6 Section
A section is a data container for one or more objects. The section header determines if the objects are compressed or not, how much object data there is, and also contains a checksum.
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:
Byte CompressionScheme
UInt32 TotalSectionLength
UInt32 UncompressedLength
Byte[TotalSectionLength-13] Objects
UInt32 Checksum
We will now go through the individual parts of the section.
6.1 CompressionScheme
This field tells how the Objects field in this section is compressed. It also specifies what checksum algorithm is used. Currently, only the Adler32 checksum is mandatory. Compression only applies to the Object data, and not to the other fields in the section.
CompressionScheme must be one of the following values:
0 Uncompressed, Adler32 Checksum
1 ZLib compression, 32 k buffer size, Adler32 Checksum
2...255 Reserved
Example:
Byte CompressionScheme = 1;
indicates that the Objects field in the section is compressed using zlib with 32 k buffer size.
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.
6.2 TotalSectionLength
This is the total length of the section in bytes; from the start of this section to the start of the next section.
Example:
UInt32 TotalSectionLength = 2056
indicates that this section, including the CompressionScheme, TotalSectionLength, UncompressedLength, Objects and Checksum fields, will be 2056 bytes in length.
6.3 UncompressedLength
Knowing the size of the decompressed data ahead of time can be used to make Zlib inflation much easier and less memory hungry. Therefore, the size of the compressed part of the section (in bytes) before compression (or after decompression) is serialized as part of the section information. Since it is only the Objects field that can be compressed, UncompressedLength contains the length of the Objects field after decompression. If no compression is specified for this section, this equals the actual number of bytes serialized in the Objects array.
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:
UInt32 UncompressedLength = 4560
Means that in this section, after decompression, the Objects field is 4560 bytes in length.
6.4 Objects
The objects in each section are serialized as an array of bytes, one after the other. This array of bytes will either be compressed (if CompressionScheme is 1) or it will be uncompressed. If it is compressed, it is compressed as a single chunk of data, not as separate objects. Zero bits must be padded in the end to make the Objects field byte aligned.
The structure of each individual object's data is documented in Section 10 and Section 11.
6.5 Checksum
To be able to verify that the section was correctly loaded, there is a 32-bit checksum of all the data in the section. The checksum algorithm is specified by the CompressionScheme field. Currently, only the Adler32 checksum is mandatory. The checksum is calculated using all preceding bytes in the section, i.e. the CompressionScheme,TotalSectionLength, UncompressedLength, and the actual serialized data in the Objects field (i.e. in its compressed form if compression is specified).
Example:
UInt32 Checksum = 0xffe806a3
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.
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 M3G compliant file and must not pass a strict verification test.
7 Object Structure
The object data stored in each section is first decompressed and then interpreted as a sequence of objects. This separates the act of decompression from the interpretation of the data. All data documented in this section is assumed already to be in its uncompressed form.
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[Length] Data
7.1 ObjectType
This field describes what type of object has been serialized. For instance, we could have a Camera node, a Mesh node or a Texture2D object. Section 12 includes a table that shows the correspondence between ObjectType values and the actual object types. The ObjectType field must hold a valid value as defined in Section 12. The reserved object types (values 23..254) must be treated as errors.
The values 0 and 0xFF are special: 0 represents the header object, and 0xFF represents an external reference.
Example:
Byte ObjectType = 14
This means that the current object is a Mesh object (see Section 12).
7.2 Length
This contains the length of the Data array, in bytes. Note that a value of 0 in this field may be legal; some objects require no additional data over and above their mere presence.
Example:
UInt32 Length = 2032
indicates that the Data field of this object spans 2032 bytes in the (decompressed) file.
7.3 Data
This is data that is specific for the object. It is up to the loader to interpret this data according to the object type and populate the object accordingly. Detailed information on the data for each object type is documented in Section 10 and Section 11.
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 deserialization 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. This condition may be difficult to determine on the target platform, but any file which contains "extra" data in object chunks is not a M3G compliant file and must not pass a strict verification test.
8 Object Ordering
All the objects in the scene graph are serialized in leaf-first order, or reference based order as it is also called. Before serializing a specific object, all other objects referenced by that object must already have been serialized. Objects may refer to themselves if this is allowed by the scene data structures.
By definition, the root of the tree will be sent last.
Note that cycles are not allowed in the file format. There is one special case where they are allowed in the run-time scene graph, namely Node alignment. Before a scene graph containing cyclic references can be written into a file, the cycles must be broken. This can be done by inserting dummy target nodes as children of the original alignment targets. For example, if a leaf node is aligned to the World, an empty Group with an identity transformation is inserted as a child of the World, and the alignment redirected to that.
Given a scene graph with no cycles, it is possible to use a "leaves first" strategy for output - 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.)
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.
Each object can then be serialized from the reference table in order.
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:
Identifier File Identifier (see Section 5)
Section 0 Uncompressed File Header Object
Section 1 Uncompressed T1 T2
Section 2 Compressed D B E A
Other orderings are also possible, for instance:
Identifier File Identifier (see Section 5)
Section 0 Uncompressed File Header Object
Section 1 Uncompressed T1 T2
Section 2 Compressed D E B A
or even (with a naive file creator):
Identifier File Identifier (see Section 5)
Section 0 Uncompressed File Header Object
Section 1 Uncompressed T1
Section 2 Compressed D
Section 3 Uncompressed T2
Section 4 Compressed B E 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.
8.1 Object References
Each object serialized, including the header object, is given an index, in order, starting from 1. The 0 index is used to indicate a null reference. This index is unrelated to the user ID for an object.
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.
8.2 Shared Objects
Shared objects are handled the same way as normal objects. We only need to make sure that a shared object is sent before both of the objects that reference it.
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.
8.3 Subtree Loading
With reference based order, it will be more difficult to load an arbitrary subtree from a file than with, e.g., root-first order. However, it is still possible, using two passes of the file. Assume that the subtree is defined as "object number X and all its children". In the first pass, only the node references are decoded, and an empty tree of the complete scene graph is created. From this graph, we find node X and make a list of all its descendants in the subtree. During the second pass, we simply load all the objects in the list. The last object that was loaded will be the root of the subtree.
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.
9 Error Handling
There are several points at which an error may be detected. These include, but are not limited to:
Memory exhaustion
Missing or malformed file identifier
Invalid section type
Invalid file, section, or object length
Invalid section checksum
Invalid object type
Extra or missing object data
Invalid object reference
Invalid enumeration value
Invalid boolean value
Invalid floating point value
Values out of range for property
Attempt to read past end of stream
Aborted download
Error in external reference
In particular, if values read from the loaded file would cause an immediate exception when passed to the API (e.g. all the attenuation parameters on a light are 0.0, or an image is too large for the implementation to handle), then this must be treated as an error.
If combinations of values are read that may cause a deferred exception, (e.g. a material and light are both present, but there are no normals specified), then this must not be treated as an error by the Loader. The application must be given the opportunity to take action after loading, in order to avoid these exceptions.
If any kind of error is detected during loading, the required action is for the Loader to abort this download, and that of any pending external references, clear up any temporary data structures, and throw an exception. If this file is being used as an external reference, then this is also treated as an error in the file that is attempting to load it. (This definition is, of course, recursive.)
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.
10 Special Object Data
The data for the "special" object types is documented here.
10.1 Header Object
Object Type: 00
Superclass data: none
Followed by:
Byte[2] VersionNumber
Boolean hasExternalReferences
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. Due to its position in the file, it will always be assigned object index 1.
VersionNumber is a unique version number identifying variants of the file fomat. Only one variant is currently specified: version number 1.0. This must be indicated by VersionNumber = {1, 0}. The first number is major revision number, followed by minor revision.
hasExternalReferences is a boolean that describes whether this file is self-contained or includes URIs for other files, such as textures or geometries. If this is false, the file is self-contained. If it is true, then it indicates that the immediately following section of the file will contain the external reference objects needed to specify these external links. See Section 10.2 for more details.
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.
10.2 External Reference
ObjectType: 0xFF (255)
Superclass data: none
Followed by:
String URI
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.
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.m3g", indicates another file in the M3G 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.
External references may appear only within their own section within the file. If present, this appears immediately after the file header section. It may be compressed or uncompressed.
In order to facilitate type checking of external references, loading of the externally referenced file must complete before reading any objects which could refer to it. This is one of the main reasons for ensuring that external references are in their own section, which occurs before sections containing objects of other types. 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 can occur only after loading the referred file.
External reference loading must support both M3G and PNG file types in order to satisfy the specification. An external reference to any other type of file must be treated as an error. To stress the point, even if a particular format (e.g., JPEG) is otherwise supported by the Loader, it must still reject any M3G files that reference JPEG images.
For M3G format files, the external reference must be able to load another M3G 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.
In all cases, once loading completes, the single root-level object loaded from the file effectively replaces the external reference object in the object index table. References to that index will then nominate the root-level object.
11 Per-Class Data
The data for each class in the API is now presented in alphabetical order. Where a class is a subclass, the superclass's data is always output first, and this information is taken to be part of the data for the class as a whole.
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.
Any values which would be invalid as arguments to the corresponding methods in the API are also invalid in the file and must be reported as errors. For example, a negative value in the light attenuation fields is disallowed by the API and is therefore also disallowed in the file format.
11.1 AnimationController
ObjectType: 01
Superclass data: Object3D
Followed by:
Float32 speed;
Float32 weight;
Int32 activeIntervalStart;
Int32 activeIntervalEnd;
Float32 referenceSequenceTime;
Int32 referenceWorldTime;
11.2 AnimationTrack
ObjectType: 02
Superclass data: Object3D
Followed by:
ObjectIndex keyframeSequence;
ObjectIndex animationController;
UInt32 propertyID;
The propertyID field must hold a valid enumerated value, as specified in the class definition. Other values must be treated as errors.
11.3 Appearance
ObjectType: 03
Superclass data: Object3D
Followed by:
Byte layer;
ObjectIndex compositingMode;
ObjectIndex fog;
ObjectIndex polygonMode;
ObjectIndex material;
ObjectIndex[] textures;
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. The texture units are loaded sequentially from unit 0. If the implementation supports more texture units than are specified, these are left in their default, inactive state, with a null texture.
If more textures are specified than are supported by the implementation, then this must be treated as an error, as it would be in the API. The application can then decide on an appropriate course of action to handle this case.
11.4 Background
ObjectType: 04
Superclass data: Object3D
Followed by:
ColorRGBA backgroundColor;
ObjectIndex backgroundImage;
Byte backgroundImageModeX;
Byte backgroundImageModeY;
Int32 cropX;
Int32 cropY;
Int32 cropWidth;
Int32 cropHeight;
Boolean depthClearEnabled;
Boolean colorClearEnabled;
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.
11.5 Camera
ObjectType: 05
Superclass data: Node
Followed by:
Byte projectionType;
IF projectionType==GENERIC, THEN
Matrix projectionMatrix;
ELSE
Float32 fovy;
Float32 AspectRatio;
Float32 near;
Float32 far;
END
The projectionType field must hold a valid enumerated value, as specified in the class definition. Other values must be treated as errors.
11.6 CompositingMode
ObjectType: 06
Superclass data: Object3D
Followed by:
Boolean depthTestEnabled;
Boolean depthWriteEnabled;
Boolean colorWriteEnabled;
Boolean alphaWriteEnabled;
Byte blending;
Byte alphaThreshold;
Float32 depthOffsetFactor;
Float32 depthOffsetUnits;
The blending field must hold a valid enumerated value, as specified in the class definition. Other values must be treated as errors.
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).
11.7 Fog
ObjectType: 07
Superclass data: Object3D
Followed by:
ColorRGB color;
Byte mode;
IF mode==EXPONENTIAL, THEN
Float32 density;
ELSE IF mode==LINEAR, THEN
Float32 near;
Float32 far;
END
The mode field must hold a valid enumerated value, as specified in the class definition. Other values must be treated as errors.
11.8 Graphics3D
Not a serializable class.
11.9 Group
ObjectType: 09
Superclass data: Node
Followed by:
ObjectIndex[] children;
11.10 Image2D
ObjectType: 10
Superclass data: Object3D
Followed by:
Byte format;
Boolean isMutable;
UInt32 width;
UInt32 height;
IF isMutable==false, THEN
Byte[] palette;
Byte[] pixels;
END
The format field must hold a valid enumerated value, as specified in the class definition. Other values must be treated as errors.
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:
ALPHA: a single byte per pixel, representing pixel opacity.
LUMINANCE: a single byte per pixel, representing pixel luminance.
LUMINANCE_ALPHA: two bytes per pixel. The first represents luminance, the second alpha.
RGB: three bytes per pixel, representing red, green and blue respectively.
RGBA: four bytes per pixel, representing red, green, blue and alpha respectively.
The meaning of the components is given in the documentation for the Image2D class.
11.11 IndexBuffer
ObjectType: none (abstract base class)
Superclass data: Object3D
Followed by: no data (abstract class)
11.12 KeyframeSequence
ObjectType: 19
Superclass data: Object3D
Followed by:
Byte interpolation;
Byte repeatMode;
Byte encoding;
UInt32 duration;
UInt32 validRangeFirst;
UInt32 validRangeLast;
UInt32 componentCount;
UInt32 keyframeCount;
IF encoding == 0
FOR each key frame...
UInt32 time;
Float32[componentCount] vectorValue;
END
ELSE IF encoding == 1
Float32[componentCount] vectorBias;
Float32[componentCount] vectorScale;
FOR each key frame...
UInt32 time;
Byte[componentCount] vectorValue;
END
ELSE IF encoding == 2
Float32[componentCount] vectorBias;
Float32[componentCount] vectorScale;
FOR each key frame...
UInt32 time;
UInt16[componentCount] vectorValue;
END
END
The interpolation and repeatMode fields must each hold a valid enumerated value, as specified in the class definition. Other values must be treated as errors.
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.
The encoding field indicates the encoding scheme to be used for the keyframe data. Only the nominated values above are allowed. Other values must be treated as errors.
Encoding 0 indicates that the values are stored "raw" as floats.
Encodings 1 and 2 indicate that the values are quantized to 1 or 2 bytes. For each component, a bias and scale are calculated from the sequence of values for that component. The bias is the mimimum value, the scale is the maximum value minus the minimum value. The raw values are then converted to a value 0..1 by subtracting the bias and dividing by the scale. These raw values are then quantized into the range of a Byte or UInt16 by multiplying by 255 or 65535 respectively. The converse operation restores the original value from the quantized values.
11.13 Light
ObjectType: 12
Superclass data: Node
Followed by:
Float32 attenuationConstant;
Float32 attenuationLinear;
Float32 attenuationQuadratic;
ColorRGB color;
Byte mode;
Float32 intensity;
Float32 spotAngle;
Float32 spotExponent;
The mode field must hold a valid enumerated value, as specified in the class definition. Other values must be treated as errors.
11.14 Loader
Not a serializable class.
11.15 Material
ObjectType: 13
Superclass data: Object3D
Followed by:
ColorRGB ambientColor;
ColorRGBA diffuseColor;
ColorRGB emissiveColor;
ColorRGB specularColor;
Float32 shininess;
Boolean vertexColorTrackingEnabled;
11.16 Mesh
ObjectType: 14
Superclass data: Node
Followed by:
ObjectIndex vertexBuffer;
UInt32 submeshCount;
FOR each submesh...
ObjectIndex indexBuffer;
ObjectIndex appearance;
END
11.17 MorphingMesh
ObjectType: 15
Superclass data: Mesh
Followed by:
UInt32 morphTargetCount;
FOR each target buffer...
ObjectIndex morphTarget;
Float32 initialWeight;
END
11.18 Node
ObjectType: none (abstract base class)
Superclass data: Transformable
Followed by:
Boolean enableRendering;
Boolean enablePicking;
Byte alphaFactor;
UInt32 scope;
Boolean hasAlignment;
IF hasAlignment==TRUE, THEN
Byte zTarget;
Byte yTarget;
ObjectIndex zReference;
ObjectIndex yReference;
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.
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).
If the hasAlignment field is false, the omitted fields are initialized to their default values.
11.19 Object3D
ObjectType: none (abstract base class)
Superclass data: none
Followed by:
UInt32 userID;
ObjectIndex[] animationTracks;
UInt32 userParameterCount;
FOR each user parameter...
UInt32 parameterID;
Byte[] parameterValue;
END
The userID field may be any value.
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 must be 0. In this case, the user object in the resulting Object3D instance must be set to 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 getUserObject method.
11.20 PolygonMode
ObjectType: 08
Superclass data: Object3D
Followed by:
Byte culling;
Byte shading;
Byte winding;
Boolean twoSidedLightingEnabled;
Boolean localCameraLightingEnabled;
Boolean perspectiveCorrectionEnabled;
The culling, shading and winding fields must each hold a valid enumerated value, as specified in the class definition. Other values must be treated as errors.
11.21 RayIntersection
Not a serializable class.
11.22 SkinnedMesh
ObjectType: 16
Superclass data: Mesh
Followed by:
ObjectIndex skeleton;
UInt32 transformReferenceCount;
FOR each bone reference...
ObjectIndex transformNode;
UInt32 firstVertex;
UInt32 vertexCount;
Int32 weight;
END
11.23 Sprite
ObjectType: 18
Superclass data: Node
Followed by:
ObjectIndex image;
ObjectIndex appearance;
Boolean isScaled;
Int32 cropX;
Int32 cropY;
Int32 cropWidth;
Int32 cropHeight;
11.24 Texture2D
ObjectType: 17
Superclass data: Transformable
Followed by:
ObjectIndex image;
ColorRGB blendColor;
Byte blending;
Byte wrappingS;
Byte wrappingT;
Byte levelFilter;
Byte imageFilter;
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.
11.25 Transform
Not a serializable class.
11.26 Transformable
ObjectType: none (abstract base class)
Superclass data: Object3D
Followed by:
Boolean hasComponentTransform;
IF hasComponentTransform==TRUE, THEN
Vector3D translation;
Vector3D scale;
Float32 orientationAngle;
Vector3D orientationAxis;
END
Boolean hasGeneralTransform;
IF hasGeneralTransform==TRUE, THEN
Matrix transform;
END
If either hasComponentTransform or hasGeneralTransform is false, the omitted fields will be initialized to their default values (equivalent to an identity transform in both cases).
11.27 TriangleStripArray
ObjectType: 11
Superclass data: IndexBuffer
Followed by:
Byte encoding;
IF encoding == 0, THEN
UInt32 startIndex;
ELSE IF encoding == 1, THEN
Byte startIndex;
ELSE IF encoding == 2, THEN
UInt16 startIndex;
ELSE IF encoding == 128, THEN
UInt32[] indices;
ELSE IF encoding == 129, THEN
Byte[] indices;
ELSE IF encoding == 130, THEN
UInt16[] indices;
END
UInt32[] stripLengths;
Bit 7 of the encoding field is equivalent to the explicit property on the index buffer, and will be 1 if the index buffer was constructed with explicit indices, or 0 if constructed with implicit indices. The other bits indicate the width of each index field. 0 indicates that the "raw" integer values are written, 1 indicates that a single byte will suffice, and 2 indicates that a 16 bit integer is sufficient to hold all the given index values. Values for the encoding field other than those explicitly nominated above are not allowed and must be treated as errors.
11.28 VertexArray
ObjectType: 20
Superclass data: Object3D
Followed by:
Byte componentSize;
Byte componentCount;
Byte encoding;
UInt16 vertexCount;
FOR each vertex...
IF componentSize==1, THEN
IF encoding==0, THEN
Byte[componentCount] components;
ELSE IF encoding==1, THEN
Byte[componentCount] componentDeltas;
END
ELSE
IF encoding==0, THEN
Int16[componentCount] components;
ELSE IF encoding==1, THEN
Int16[componentCount] componentDeltas;
END
END
END
The componentSize and componentCount fields must each hold a valid value, as specified in the constructor definition. Other values must be treated as errors.
The encoding field indicates the encoding scheme to be used for the keyframe data. Only the nominated values above are allowed. Other values must be treated as errors.
Encoding 0 indicates that the values are stored "raw" as bytes or 16 bit integers.
Encoding 1 indicates that the values are stored as differences from the previous value. Each component is treated separately, so that the difference is taken from the corresponding component in the previous vertex. For the first vertex, the previous value is taken to be 0. Decoding proceeds by initializing an accumulator to 0 for each component, and adding each value to the accumulator. In order that the deltas can be represented within the same number of bits as the raw values, the accumulators should be the same length as the values required (i.e. 8 or 16 bites) and be allowed to overflow. This also means that the accumulation is not dependent on the signed or unsigned nature of the deltas. (For example, the 8-bit sequence 0, 127, 126 can equally well be represented using deltas of 0, 127, -1 or 0, 127, 255.)
11.29 VertexBuffer
ObjectType: 21
Superclass data: Object3D
Followed by:
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
If a texture coordinate array has only two components, the corresponding texCoordBias[2] element must be 0.0.
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.
There are as many references in the texture coordinates array as there are active texture units for this geometry. The texture coordinate references are loaded sequentially from texture unit 0. If the implementation supports more texture units than are specified, these are left in their default, inactive state, with a null texture coordinate reference and an undefined bias and scale.
If more texture coordinate references are specified than are supported by the implementation, then this must be treated as an error, as it would be in the API. The application can then decide on an appropriate course of action to handle this case.
11.30 World
ObjectType: 22
Superclass data: Group
Followed by:
ObjectIndex activeCamera;
ObjectIndex background;
12 ObjectType Values
This list shows what object type a specific ObjectType value maps to.
ObjectType value Object Type
00 Header Object
01 AnimationController
02 AnimationTrack
03 Appearance
04 Background
05 Camera
06 CompositingMode
07 Fog
08 PolygonMode
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
Note that Object3D, Transformable, Node, and IndexBuffer are abstract classes and cannot be instantiated directly. They therefore do not appear in this list.
Abstract
This specification defines a 3D Graphics File Format that complements the Mobile 3D Graphics API (M3G). The file format is provided as a compact and standardised way of populating a scene graph.
Contents
1 Important Notes
2 MIME Type and File Extension
3 Data Types
3.1 Fundamental Data Types
3.2 Compound Data Types
4 File Structure
5 File Identifier
6 Section
6.1 CompressionScheme
6.2 TotalSectionLength
6.3 UncompressedLength
6.4 Objects
6.5 Checksum
7 Object Structure
7.1 ObjectType
7.2 Length
7.3 Data
8 Object Ordering
8.1 Object References
8.2 Shared Objects
8.3 Subtree Loading
9 Error Handling
10 Special Object Data
10.1 Header Object
10.2 External Reference
11 Per-Class Data
11.1 AnimationController
11.2 AnimationTrack
11.3 Appearance
11.4 Background
11.5 Camera
11.6 CompositingMode
11.7 Fog
11.8 Graphics3D
11.9 Group
11.10 Image2D
11.11 IndexBuffer
11.12 KeyframeSequence
11.13 Light
11.14 Loader
11.15 Material
11.16 Mesh
11.17 MorphingMesh
11.18 Node
11.19 Object3D
11.20 PolygonMode
11.21 RayIntersection
11.22 SkinnedMesh
11.23 Sprite
11.24 Texture2D
11.25 Transform
11.26 Transformable
11.27 TriangleStripArray
11.28 VertexArray
11.29 VertexBuffer
11.30 World
12 ObjectType Values
1 Important Notes
The data here are not serialized by Java's own serialization mechanism. They are serialized by the M3G serialization mechanism, which produces and loads data streams conforming to the M3G file format specification.
For more details of the mechanisms for loading a M3G compliant file, please refer to the documentation for the Loader class.
2 MIME Type and File Extension
The MIME type for this file format is application/m3g. The file extension (for systems that do not support MIME type queries) is .m3g, to match the lowest level name in the package hierarchy.
3 Data Types
3.1 Fundamental Data Types
There are several data types which are regarded as fundamental. These are as follows:
Type Name
Description
Byte
A single, unsigned 8-bit 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.
3.2 Compound Data Types
In order to avoid having to repeatedly specify sequences of the same types many times, some compound data types are defined for convenience. The composition of these is listed to show both their makeup and the order in which the simple elements are to be serialized. These are as follows:
Type Name
Description
Composition
Vector3D
A 3D vector.
Float32 x;
Float32 y;
Float32 z;
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 15
Float32 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 deserialization 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.
4 File Structure
The file consists of the file identifier, followed by one or more sections. Thus the overall file structure looks like this:
File Identifier
Section 0 File Header Object
Section 1 External Reference Objects
Section 2 Scene Objects
Section 3 Scene Objects
... ...
Section n Scene Objects
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.
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.
If there are external references in the file, then these must all appear in a single section immediately following the header section. This section may be compressed or uncompressed. External references allow scenes to be built up from a collection of separate files, and are discussed in detail in Section 10.2.
Following these are an unspecified number of sections containing scene objects.
The file must contain the header section, plus at least one other non-empty section (containing at least one object). It is possible to have a file consisting solely of external references, or solely of scene objects.
A file containing no objects at all is not a valid M3G file, and must be treated as an error.
5 File Identifier
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:
Byte[12] FileIdentifier = { 0xAB, 0x4A, 0x53, 0x52, 0x31, 0x38, 0x34, 0xBB, 0x0D, 0x0A, 0x1A, 0x0A }
This can also be expressed using C-style character definitions as:
Byte[12] FileIdentifier = { '«', 'J', 'S', 'R', '1', '8', '4', '»', '\r', '\n', '\x1A', '\n' }
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 M3G file and provides for immediate detection of common file-transfer problems.
Byte [0] is chosen as a non-ASCII value to reduce the probability that a text file may be misrecognized as a M3G file.
Byte [0] also catches bad file transfers that clear bit 7.
Bytes [1..6] identify the format, and are the ascii values for the string "JSR184".
Byte [7] is for aesthetic balance with byte 1 (they are a matching pair of double-angle quotation marks).
Bytes [8..9] form a CR-LF sequence which catches bad file transfers that alter newline sequences.
Byte [10] is a control-Z character, which stops file display under MS-DOS, and further reduces the chance that a text file will be falsely recognised.
Byte [11] is a final line feed, which checks for the inverse of the CR-LF translation problem.
A decoder may further verify that the next byte is 0 (this is the first byte of the mandatory uncompressed header section). This will catch bad transfers that drop or alter zero bytes.
6 Section
A section is a data container for one or more objects. The section header determines if the objects are compressed or not, how much object data there is, and also contains a checksum.
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:
Byte CompressionScheme
UInt32 TotalSectionLength
UInt32 UncompressedLength
Byte[TotalSectionLength-13] Objects
UInt32 Checksum
We will now go through the individual parts of the section.
6.1 CompressionScheme
This field tells how the Objects field in this section is compressed. It also specifies what checksum algorithm is used. Currently, only the Adler32 checksum is mandatory. Compression only applies to the Object data, and not to the other fields in the section.
CompressionScheme must be one of the following values:
0 Uncompressed, Adler32 Checksum
1 ZLib compression, 32 k buffer size, Adler32 Checksum
2...255 Reserved
Example:
Byte CompressionScheme = 1;
indicates that the Objects field in the section is compressed using zlib with 32 k buffer size.
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.
6.2 TotalSectionLength
This is the total length of the section in bytes; from the start of this section to the start of the next section.
Example:
UInt32 TotalSectionLength = 2056
indicates that this section, including the CompressionScheme, TotalSectionLength, UncompressedLength, Objects and Checksum fields, will be 2056 bytes in length.
6.3 UncompressedLength
Knowing the size of the decompressed data ahead of time can be used to make Zlib inflation much easier and less memory hungry. Therefore, the size of the compressed part of the section (in bytes) before compression (or after decompression) is serialized as part of the section information. Since it is only the Objects field that can be compressed, UncompressedLength contains the length of the Objects field after decompression. If no compression is specified for this section, this equals the actual number of bytes serialized in the Objects array.
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:
UInt32 UncompressedLength = 4560
Means that in this section, after decompression, the Objects field is 4560 bytes in length.
6.4 Objects
The objects in each section are serialized as an array of bytes, one after the other. This array of bytes will either be compressed (if CompressionScheme is 1) or it will be uncompressed. If it is compressed, it is compressed as a single chunk of data, not as separate objects. Zero bits must be padded in the end to make the Objects field byte aligned.
The structure of each individual object's data is documented in Section 10 and Section 11.
6.5 Checksum
To be able to verify that the section was correctly loaded, there is a 32-bit checksum of all the data in the section. The checksum algorithm is specified by the CompressionScheme field. Currently, only the Adler32 checksum is mandatory. The checksum is calculated using all preceding bytes in the section, i.e. the CompressionScheme,TotalSectionLength, UncompressedLength, and the actual serialized data in the Objects field (i.e. in its compressed form if compression is specified).
Example:
UInt32 Checksum = 0xffe806a3
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.
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 M3G compliant file and must not pass a strict verification test.
7 Object Structure
The object data stored in each section is first decompressed and then interpreted as a sequence of objects. This separates the act of decompression from the interpretation of the data. All data documented in this section is assumed already to be in its uncompressed form.
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[Length] Data
7.1 ObjectType
This field describes what type of object has been serialized. For instance, we could have a Camera node, a Mesh node or a Texture2D object. Section 12 includes a table that shows the correspondence between ObjectType values and the actual object types. The ObjectType field must hold a valid value as defined in Section 12. The reserved object types (values 23..254) must be treated as errors.
The values 0 and 0xFF are special: 0 represents the header object, and 0xFF represents an external reference.
Example:
Byte ObjectType = 14
This means that the current object is a Mesh object (see Section 12).
7.2 Length
This contains the length of the Data array, in bytes. Note that a value of 0 in this field may be legal; some objects require no additional data over and above their mere presence.
Example:
UInt32 Length = 2032
indicates that the Data field of this object spans 2032 bytes in the (decompressed) file.
7.3 Data
This is data that is specific for the object. It is up to the loader to interpret this data according to the object type and populate the object accordingly. Detailed information on the data for each object type is documented in Section 10 and Section 11.
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 deserialization 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. This condition may be difficult to determine on the target platform, but any file which contains "extra" data in object chunks is not a M3G compliant file and must not pass a strict verification test.
8 Object Ordering
All the objects in the scene graph are serialized in leaf-first order, or reference based order as it is also called. Before serializing a specific object, all other objects referenced by that object must already have been serialized. Objects may refer to themselves if this is allowed by the scene data structures.
By definition, the root of the tree will be sent last.
Note that cycles are not allowed in the file format. There is one special case where they are allowed in the run-time scene graph, namely Node alignment. Before a scene graph containing cyclic references can be written into a file, the cycles must be broken. This can be done by inserting dummy target nodes as children of the original alignment targets. For example, if a leaf node is aligned to the World, an empty Group with an identity transformation is inserted as a child of the World, and the alignment redirected to that.
Given a scene graph with no cycles, it is possible to use a "leaves first" strategy for output - 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.)
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.
Each object can then be serialized from the reference table in order.
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:
Identifier File Identifier (see Section 5)
Section 0 Uncompressed File Header Object
Section 1 Uncompressed T1 T2
Section 2 Compressed D B E A
Other orderings are also possible, for instance:
Identifier File Identifier (see Section 5)
Section 0 Uncompressed File Header Object
Section 1 Uncompressed T1 T2
Section 2 Compressed D E B A
or even (with a naive file creator):
Identifier File Identifier (see Section 5)
Section 0 Uncompressed File Header Object
Section 1 Uncompressed T1
Section 2 Compressed D
Section 3 Uncompressed T2
Section 4 Compressed B E 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.
8.1 Object References
Each object serialized, including the header object, is given an index, in order, starting from 1. The 0 index is used to indicate a null reference. This index is unrelated to the user ID for an object.
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.
8.2 Shared Objects
Shared objects are handled the same way as normal objects. We only need to make sure that a shared object is sent before both of the objects that reference it.
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.
8.3 Subtree Loading
With reference based order, it will be more difficult to load an arbitrary subtree from a file than with, e.g., root-first order. However, it is still possible, using two passes of the file. Assume that the subtree is defined as "object number X and all its children". In the first pass, only the node references are decoded, and an empty tree of the complete scene graph is created. From this graph, we find node X and make a list of all its descendants in the subtree. During the second pass, we simply load all the objects in the list. The last object that was loaded will be the root of the subtree.
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.
9 Error Handling
There are several points at which an error may be detected. These include, but are not limited to:
Memory exhaustion
Missing or malformed file identifier
Invalid section type
Invalid file, section, or object length
Invalid section checksum
Invalid object type
Extra or missing object data
Invalid object reference
Invalid enumeration value
Invalid boolean value
Invalid floating point value
Values out of range for property
Attempt to read past end of stream
Aborted download
Error in external reference
In particular, if values read from the loaded file would cause an immediate exception when passed to the API (e.g. all the attenuation parameters on a light are 0.0, or an image is too large for the implementation to handle), then this must be treated as an error.
If combinations of values are read that may cause a deferred exception, (e.g. a material and light are both present, but there are no normals specified), then this must not be treated as an error by the Loader. The application must be given the opportunity to take action after loading, in order to avoid these exceptions.
If any kind of error is detected during loading, the required action is for the Loader to abort this download, and that of any pending external references, clear up any temporary data structures, and throw an exception. If this file is being used as an external reference, then this is also treated as an error in the file that is attempting to load it. (This definition is, of course, recursive.)
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.
10 Special Object Data
The data for the "special" object types is documented here.
10.1 Header Object
Object Type: 00
Superclass data: none
Followed by:
Byte[2] VersionNumber
Boolean hasExternalReferences
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. Due to its position in the file, it will always be assigned object index 1.
VersionNumber is a unique version number identifying variants of the file fomat. Only one variant is currently specified: version number 1.0. This must be indicated by VersionNumber = {1, 0}. The first number is major revision number, followed by minor revision.
hasExternalReferences is a boolean that describes whether this file is self-contained or includes URIs for other files, such as textures or geometries. If this is false, the file is self-contained. If it is true, then it indicates that the immediately following section of the file will contain the external reference objects needed to specify these external links. See Section 10.2 for more details.
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.
10.2 External Reference
ObjectType: 0xFF (255)
Superclass data: none
Followed by:
String URI
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.
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.m3g", indicates another file in the M3G 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.
External references may appear only within their own section within the file. If present, this appears immediately after the file header section. It may be compressed or uncompressed.
In order to facilitate type checking of external references, loading of the externally referenced file must complete before reading any objects which could refer to it. This is one of the main reasons for ensuring that external references are in their own section, which occurs before sections containing objects of other types. 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 can occur only after loading the referred file.
External reference loading must support both M3G and PNG file types in order to satisfy the specification. An external reference to any other type of file must be treated as an error. To stress the point, even if a particular format (e.g., JPEG) is otherwise supported by the Loader, it must still reject any M3G files that reference JPEG images.
For M3G format files, the external reference must be able to load another M3G 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.
In all cases, once loading completes, the single root-level object loaded from the file effectively replaces the external reference object in the object index table. References to that index will then nominate the root-level object.
11 Per-Class Data
The data for each class in the API is now presented in alphabetical order. Where a class is a subclass, the superclass's data is always output first, and this information is taken to be part of the data for the class as a whole.
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.
Any values which would be invalid as arguments to the corresponding methods in the API are also invalid in the file and must be reported as errors. For example, a negative value in the light attenuation fields is disallowed by the API and is therefore also disallowed in the file format.
11.1 AnimationController
ObjectType: 01
Superclass data: Object3D
Followed by:
Float32 speed;
Float32 weight;
Int32 activeIntervalStart;
Int32 activeIntervalEnd;
Float32 referenceSequenceTime;
Int32 referenceWorldTime;
11.2 AnimationTrack
ObjectType: 02
Superclass data: Object3D
Followed by:
ObjectIndex keyframeSequence;
ObjectIndex animationController;
UInt32 propertyID;
The propertyID field must hold a valid enumerated value, as specified in the class definition. Other values must be treated as errors.
11.3 Appearance
ObjectType: 03
Superclass data: Object3D
Followed by:
Byte layer;
ObjectIndex compositingMode;
ObjectIndex fog;
ObjectIndex polygonMode;
ObjectIndex material;
ObjectIndex[] textures;
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. The texture units are loaded sequentially from unit 0. If the implementation supports more texture units than are specified, these are left in their default, inactive state, with a null texture.
If more textures are specified than are supported by the implementation, then this must be treated as an error, as it would be in the API. The application can then decide on an appropriate course of action to handle this case.
11.4 Background
ObjectType: 04
Superclass data: Object3D
Followed by:
ColorRGBA backgroundColor;
ObjectIndex backgroundImage;
Byte backgroundImageModeX;
Byte backgroundImageModeY;
Int32 cropX;
Int32 cropY;
Int32 cropWidth;
Int32 cropHeight;
Boolean depthClearEnabled;
Boolean colorClearEnabled;
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.
11.5 Camera
ObjectType: 05
Superclass data: Node
Followed by:
Byte projectionType;
IF projectionType==GENERIC, THEN
Matrix projectionMatrix;
ELSE
Float32 fovy;
Float32 AspectRatio;
Float32 near;
Float32 far;
END
The projectionType field must hold a valid enumerated value, as specified in the class definition. Other values must be treated as errors.
11.6 CompositingMode
ObjectType: 06
Superclass data: Object3D
Followed by:
Boolean depthTestEnabled;
Boolean depthWriteEnabled;
Boolean colorWriteEnabled;
Boolean alphaWriteEnabled;
Byte blending;
Byte alphaThreshold;
Float32 depthOffsetFactor;
Float32 depthOffsetUnits;
The blending field must hold a valid enumerated value, as specified in the class definition. Other values must be treated as errors.
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).
11.7 Fog
ObjectType: 07
Superclass data: Object3D
Followed by:
ColorRGB color;
Byte mode;
IF mode==EXPONENTIAL, THEN
Float32 density;
ELSE IF mode==LINEAR, THEN
Float32 near;
Float32 far;
END
The mode field must hold a valid enumerated value, as specified in the class definition. Other values must be treated as errors.
11.8 Graphics3D
Not a serializable class.
11.9 Group
ObjectType: 09
Superclass data: Node
Followed by:
ObjectIndex[] children;
11.10 Image2D
ObjectType: 10
Superclass data: Object3D
Followed by:
Byte format;
Boolean isMutable;
UInt32 width;
UInt32 height;
IF isMutable==false, THEN
Byte[] palette;
Byte[] pixels;
END
The format field must hold a valid enumerated value, as specified in the class definition. Other values must be treated as errors.
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:
ALPHA: a single byte per pixel, representing pixel opacity.
LUMINANCE: a single byte per pixel, representing pixel luminance.
LUMINANCE_ALPHA: two bytes per pixel. The first represents luminance, the second alpha.
RGB: three bytes per pixel, representing red, green and blue respectively.
RGBA: four bytes per pixel, representing red, green, blue and alpha respectively.
The meaning of the components is given in the documentation for the Image2D class.
11.11 IndexBuffer
ObjectType: none (abstract base class)
Superclass data: Object3D
Followed by: no data (abstract class)
11.12 KeyframeSequence
ObjectType: 19
Superclass data: Object3D
Followed by:
Byte interpolation;
Byte repeatMode;
Byte encoding;
UInt32 duration;
UInt32 validRangeFirst;
UInt32 validRangeLast;
UInt32 componentCount;
UInt32 keyframeCount;
IF encoding == 0
FOR each key frame...
UInt32 time;
Float32[componentCount] vectorValue;
END
ELSE IF encoding == 1
Float32[componentCount] vectorBias;
Float32[componentCount] vectorScale;
FOR each key frame...
UInt32 time;
Byte[componentCount] vectorValue;
END
ELSE IF encoding == 2
Float32[componentCount] vectorBias;
Float32[componentCount] vectorScale;
FOR each key frame...
UInt32 time;
UInt16[componentCount] vectorValue;
END
END
The interpolation and repeatMode fields must each hold a valid enumerated value, as specified in the class definition. Other values must be treated as errors.
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.
The encoding field indicates the encoding scheme to be used for the keyframe data. Only the nominated values above are allowed. Other values must be treated as errors.
Encoding 0 indicates that the values are stored "raw" as floats.
Encodings 1 and 2 indicate that the values are quantized to 1 or 2 bytes. For each component, a bias and scale are calculated from the sequence of values for that component. The bias is the mimimum value, the scale is the maximum value minus the minimum value. The raw values are then converted to a value 0..1 by subtracting the bias and dividing by the scale. These raw values are then quantized into the range of a Byte or UInt16 by multiplying by 255 or 65535 respectively. The converse operation restores the original value from the quantized values.
11.13 Light
ObjectType: 12
Superclass data: Node
Followed by:
Float32 attenuationConstant;
Float32 attenuationLinear;
Float32 attenuationQuadratic;
ColorRGB color;
Byte mode;
Float32 intensity;
Float32 spotAngle;
Float32 spotExponent;
The mode field must hold a valid enumerated value, as specified in the class definition. Other values must be treated as errors.
11.14 Loader
Not a serializable class.
11.15 Material
ObjectType: 13
Superclass data: Object3D
Followed by:
ColorRGB ambientColor;
ColorRGBA diffuseColor;
ColorRGB emissiveColor;
ColorRGB specularColor;
Float32 shininess;
Boolean vertexColorTrackingEnabled;
11.16 Mesh
ObjectType: 14
Superclass data: Node
Followed by:
ObjectIndex vertexBuffer;
UInt32 submeshCount;
FOR each submesh...
ObjectIndex indexBuffer;
ObjectIndex appearance;
END
11.17 MorphingMesh
ObjectType: 15
Superclass data: Mesh
Followed by:
UInt32 morphTargetCount;
FOR each target buffer...
ObjectIndex morphTarget;
Float32 initialWeight;
END
11.18 Node
ObjectType: none (abstract base class)
Superclass data: Transformable
Followed by:
Boolean enableRendering;
Boolean enablePicking;
Byte alphaFactor;
UInt32 scope;
Boolean hasAlignment;
IF hasAlignment==TRUE, THEN
Byte zTarget;
Byte yTarget;
ObjectIndex zReference;
ObjectIndex yReference;
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.
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).
If the hasAlignment field is false, the omitted fields are initialized to their default values.
11.19 Object3D
ObjectType: none (abstract base class)
Superclass data: none
Followed by:
UInt32 userID;
ObjectIndex[] animationTracks;
UInt32 userParameterCount;
FOR each user parameter...
UInt32 parameterID;
Byte[] parameterValue;
END
The userID field may be any value.
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 must be 0. In this case, the user object in the resulting Object3D instance must be set to 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 getUserObject method.
11.20 PolygonMode
ObjectType: 08
Superclass data: Object3D
Followed by:
Byte culling;
Byte shading;
Byte winding;
Boolean twoSidedLightingEnabled;
Boolean localCameraLightingEnabled;
Boolean perspectiveCorrectionEnabled;
The culling, shading and winding fields must each hold a valid enumerated value, as specified in the class definition. Other values must be treated as errors.
11.21 RayIntersection
Not a serializable class.
11.22 SkinnedMesh
ObjectType: 16
Superclass data: Mesh
Followed by:
ObjectIndex skeleton;
UInt32 transformReferenceCount;
FOR each bone reference...
ObjectIndex transformNode;
UInt32 firstVertex;
UInt32 vertexCount;
Int32 weight;
END
11.23 Sprite
ObjectType: 18
Superclass data: Node
Followed by:
ObjectIndex image;
ObjectIndex appearance;
Boolean isScaled;
Int32 cropX;
Int32 cropY;
Int32 cropWidth;
Int32 cropHeight;
11.24 Texture2D
ObjectType: 17
Superclass data: Transformable
Followed by:
ObjectIndex image;
ColorRGB blendColor;
Byte blending;
Byte wrappingS;
Byte wrappingT;
Byte levelFilter;
Byte imageFilter;
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.
11.25 Transform
Not a serializable class.
11.26 Transformable
ObjectType: none (abstract base class)
Superclass data: Object3D
Followed by:
Boolean hasComponentTransform;
IF hasComponentTransform==TRUE, THEN
Vector3D translation;
Vector3D scale;
Float32 orientationAngle;
Vector3D orientationAxis;
END
Boolean hasGeneralTransform;
IF hasGeneralTransform==TRUE, THEN
Matrix transform;
END
If either hasComponentTransform or hasGeneralTransform is false, the omitted fields will be initialized to their default values (equivalent to an identity transform in both cases).
11.27 TriangleStripArray
ObjectType: 11
Superclass data: IndexBuffer
Followed by:
Byte encoding;
IF encoding == 0, THEN
UInt32 startIndex;
ELSE IF encoding == 1, THEN
Byte startIndex;
ELSE IF encoding == 2, THEN
UInt16 startIndex;
ELSE IF encoding == 128, THEN
UInt32[] indices;
ELSE IF encoding == 129, THEN
Byte[] indices;
ELSE IF encoding == 130, THEN
UInt16[] indices;
END
UInt32[] stripLengths;
Bit 7 of the encoding field is equivalent to the explicit property on the index buffer, and will be 1 if the index buffer was constructed with explicit indices, or 0 if constructed with implicit indices. The other bits indicate the width of each index field. 0 indicates that the "raw" integer values are written, 1 indicates that a single byte will suffice, and 2 indicates that a 16 bit integer is sufficient to hold all the given index values. Values for the encoding field other than those explicitly nominated above are not allowed and must be treated as errors.
11.28 VertexArray
ObjectType: 20
Superclass data: Object3D
Followed by:
Byte componentSize;
Byte componentCount;
Byte encoding;
UInt16 vertexCount;
FOR each vertex...
IF componentSize==1, THEN
IF encoding==0, THEN
Byte[componentCount] components;
ELSE IF encoding==1, THEN
Byte[componentCount] componentDeltas;
END
ELSE
IF encoding==0, THEN
Int16[componentCount] components;
ELSE IF encoding==1, THEN
Int16[componentCount] componentDeltas;
END
END
END
The componentSize and componentCount fields must each hold a valid value, as specified in the constructor definition. Other values must be treated as errors.
The encoding field indicates the encoding scheme to be used for the keyframe data. Only the nominated values above are allowed. Other values must be treated as errors.
Encoding 0 indicates that the values are stored "raw" as bytes or 16 bit integers.
Encoding 1 indicates that the values are stored as differences from the previous value. Each component is treated separately, so that the difference is taken from the corresponding component in the previous vertex. For the first vertex, the previous value is taken to be 0. Decoding proceeds by initializing an accumulator to 0 for each component, and adding each value to the accumulator. In order that the deltas can be represented within the same number of bits as the raw values, the accumulators should be the same length as the values required (i.e. 8 or 16 bites) and be allowed to overflow. This also means that the accumulation is not dependent on the signed or unsigned nature of the deltas. (For example, the 8-bit sequence 0, 127, 126 can equally well be represented using deltas of 0, 127, -1 or 0, 127, 255.)
11.29 VertexBuffer
ObjectType: 21
Superclass data: Object3D
Followed by:
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
If a texture coordinate array has only two components, the corresponding texCoordBias[2] element must be 0.0.
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.
There are as many references in the texture coordinates array as there are active texture units for this geometry. The texture coordinate references are loaded sequentially from texture unit 0. If the implementation supports more texture units than are specified, these are left in their default, inactive state, with a null texture coordinate reference and an undefined bias and scale.
If more texture coordinate references are specified than are supported by the implementation, then this must be treated as an error, as it would be in the API. The application can then decide on an appropriate course of action to handle this case.
11.30 World
ObjectType: 22
Superclass data: Group
Followed by:
ObjectIndex activeCamera;
ObjectIndex background;
12 ObjectType Values
This list shows what object type a specific ObjectType value maps to.
ObjectType value Object Type
00 Header Object
01 AnimationController
02 AnimationTrack
03 Appearance
04 Background
05 Camera
06 CompositingMode
07 Fog
08 PolygonMode
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
Note that Object3D, Transformable, Node, and IndexBuffer are abstract classes and cannot be instantiated directly. They therefore do not appear in this list.
发表评论
-
一道简单题
2011-04-14 23:00 1268You are allowed to pick one num ... -
Array Puzzle
2010-11-21 13:00 1061change array={a1,a2,...,an,b1,b ... -
给你n个数,其中有且仅有三个数出现了奇数次,其余的数都出现了偶数次。用线性时间常数空间找出出现了奇数次的那三个数(代码)。
2010-08-13 10:43 1954public class FindOdd { pu ... -
给你n个数,其中有且仅有三个数出现了奇数次,其余的数都出现了偶数次。用线性时间常数空间找出出现了奇数次的那三个数。
2010-08-12 18:36 1560给你n个数,其中有且仅有三个数出现了奇数次,其余的数都出现了偶 ... -
(P∧R)∨(Q∧R)∨(P∧Q∧R)
2010-05-24 10:17 1484(P∧R)∨(Q∧R)∨(P∧Q∧R) -
C 语言中常用 string 函数简介
2010-03-02 16:55 953@函数名称: strdup 函 ... -
CRC32 查表法 java
2010-02-12 10:52 4455public static int Calc(byt ... -
ZIP文件格式详解
2010-01-07 18:54 1926一个 ZIP 文件由三个部分组成: ... -
CA证书
2009-12-29 16:59 910java 的 Keytool命令生成的证书没有CA字段 使用o ... -
证书各部分的含义
2009-12-29 16:56 2896<FONT face=宋体>V ... -
图的最短路径矩阵算法
2009-01-13 17:21 5219最短路径有很多算法。 ...
相关推荐
M3G文件格式是基于OpenGL ES的,但在资源有限的移动设备上进行了优化,以适应低功耗和内存限制。tk_m3gtk_v4_5这款软件的核心功能就是解析和显示这些M3G文件,允许用户查看模型、纹理、动画等3D元素,这对于游戏开发...
4. **m3g**:这是M3G文件格式的提及,它是JSR 184中定义的一种专为移动设备优化的3D模型格式。这种格式旨在减少存储空间和内存需求,同时保持足够的图形质量,以适应资源有限的移动设备。 在DEMO程序中,`jsr_184_...
M3G文件格式是一种二进制格式,用于存储3D模型、纹理、动画等数据。这种格式优化了数据存储和内存使用,适应了移动设备的限制。开发者通常使用专门的3D建模软件(如3DS Max或Blender)创建M3G模型,然后将其导入到...
在“Mobile3DGraphicsAPI”这个压缩包文件中,通常会包含M3G API的详细说明文档、示例代码、参考手册和可能的开发工具,这些资源可以帮助开发者更深入地理解和使用M3G API。通过阅读这些文档,开发者可以逐步学习并...
M3U8文件包含了播放器需要的视频、音频等资源链接,以及播放顺序和相关信息,使得实时流媒体的传输和播放更为高效和灵活。这种格式特别适用于基于HTTP的自适应流媒体传输,支持各种设备和网络条件下的平滑播放体验。...
在这个上下文中,它可能是指整个M3G API的实现或者是一系列相关文件或库。 在压缩包中,有两个文件: 1. **J2ME_M3G_API.chm**:这是一个CHM(Compiled Help Manual)文件,通常包含Windows帮助文档。用户可以从中...
M3G查看器是一个独立的应用程序,用于查看3D图形文件格式的内容,该格式是对移动3D图形API(M3G)的补充。
只需指定输入的M3G文件和输出的FBX文件路径,即可完成转换。 2. **sbaBrute.exe**:可能是一个辅助工具,用于处理与模型相关的其他任务,比如模型优化或数据提取。具体的用途需要参考readme.txt文件或者开发者提供...
1. **文件格式验证**:确认M3G文件的结构是否符合规范,确保其能被正确解析。 2. **几何对象检查**:检查3D模型的顶点、面片、纹理坐标等数据是否完整无误。 3. **纹理与材质分析**:分析模型使用的纹理图像和材质...
Eclipse M3g Viewer 是一个开源项目,专为Eclipse集成开发环境设计的插件,用于查看M3G文件。M3G,全称为Mobile 3D Graphics,是一种基于Java平台的3D图形标准,主要应用于移动设备上的游戏和应用程序,以提供高质量...
M3G定义了一种中间格式,允许跨平台的3D图形内容交换。它提供了3D模型、纹理、光照、动画等元素的表示,并支持硬件加速渲染,以提高性能。M3G与JSR 184的关系是,JSR 184是Java对M3G标准的实现,使得开发者可以通过...
M3G文件是M3G标准下的一种文件格式,用于存储3D模型、纹理、动画等数据。M3GConverter允许用户将其他常见的3D模型格式(如OBJ、3DS、Collada等)转换为M3G格式,以便在移动设备上运行。这个工具的强大之处在于它能...
- **M3G**:M3G (Mobile 3D Graphics) 是一种专为移动设备设计的3D图形格式。它支持高效的数据压缩和传输,能够有效减少移动网络的带宽需求。M3G还包括了对动画和交互的支持,非常适合移动游戏和其他需要实时3D图形...
分析这些文件并与教程相结合,将有助于你掌握M3G在实际项目中的应用。 总之,【JSR-184】的3D编程指南Part V专注于使用M3G在移动设备上实现基于高度图的地形渲染,涉及图像处理、3D网格构建、纹理映射、光照以及...
标题 "m3e-base.tgz" 提供的信息较少,它很可能是一个包含软件库、模型或者数据集的压缩文件,格式为 tar.gz。这种格式在IT行业中常见于源代码分布、机器学习模型或大数据集的存储,因为它能有效地压缩大量文件。"m3...
被删或格式化文件恢复 在很多情况下,有许多朋友电脑上的东西一不小心被删了,或被格式化了,心痛啊。此软件也许能帮到你恢复一些重要的文件、图片、表格、视频等。。。本人用三台老式机试过,扫描C、D、E、F、G这几...
- M3G是一种针对移动设备优化的3D图形标准,它定义了一组API和文件格式,用于在不同设备之间交换3D模型和场景数据。 - M3G支持动画、光照、纹理贴图等多种高级功能,旨在提供一致且高效的3D图形体验。 ### 实践应用...
ffmpeg -i input.mp4 -c:v libx264 -preset veryfast -crf 22 -g 48 -hls_time 10 -hls_list_size 0 -hls_segment_type mpegts output.m3u8 ``` 这个命令将把`input.mp4`转码为M3U8格式,每个片段时长为10秒。 3...
压缩包中的"ISM43362-M3G-L44_MQTT-main"可能是项目的主要源码文件或者包含主函数的文件。这可能包含了微控制器的初始化代码、MQTT客户端的设置和消息处理逻辑。通过分析这个文件,开发者可以了解如何将ISM43362与...
在本文中,我们将深入探讨如何在IBM X3650M3服务器上安装Linux 5.5系统,并进一步安装Oracle 10g数据库。IBM X3650M3是一款高性能的企业级服务器,适合承载复杂的工作负载,如数据库管理系统。 首先,安装过程的...