M3G 1.1 -- Jun 22, 2005

javax.microedition.m3g
Class Loader

java.lang.Object
  extended byjavax.microedition.m3g.Loader

public class Loader
extends java.lang.Object

Downloads and deserializes scene graph nodes and node components, as well as entire scene graphs. Downloading ready-made pieces of 3D content from an M3G file is generally the most convenient way for an application to create and populate a 3D scene.

Supported data types

The Loader can deserialize instances of any class derived from Object3D. These include scene graph nodes such as World, Group, Camera and Light; attribute classes such as Material, Appearance and Texture2D; animation classes such as AnimationTrack and KeyframeSequence; and so on. No other types of objects are supported.

The data to be loaded must constitute a valid M3G file. Alternatively, it may be a PNG image file, in which case a single, immutable Image2D object is returned, with the pixel format of the Image2D corresponding to the color type of the PNG. Some implementations may support other formats as well. If the data is not in a supported format, is otherwise invalid, or can not be loaded for some other reason, an exception is thrown.

Using the Loader

The Loader class cannot be instantiated, and its only members are the two static load methods. The methods are otherwise identical, but one of them takes in a byte array, while the other takes a named resource, such as a URI or an individual file in the JAR package. Named resources must always have an absolute path, otherwise the results are undefined. For example, loading "foobar.m3g" produces undefined results, whereas loading "/foobar.m3g" is well-defined. Furthermore, named resources are treated as case-sensitive. For example, "foobar.m3g" is not the same file as "foobar.M3G".

Any external references in the given file or byte array are followed recursively. When using the load variant that takes in a URI, the references may be absolute or relative, but when using the byte array variant, only absolute references are allowed. External references are also treated as case-sensitive.

The load methods only return once the entire contents of the given file (or byte array) have been loaded, including any referenced files. This means that displaying content while downloading (progressive loading) is not supported.

Managing the loaded objects

The load methods return an array of Object3Ds. These are the root level objects in the file; in other words, those objects that are not referenced by any other objects. The array is guaranteed not to contain any null objects, but the order of the objects in the array is undefined.

The non-root objects (often the majority) can be found by following references recursively, starting from the root objects. This can be done conveniently with the getReferences method in Object3D. Another way to find a specific object is to tag it with a known user ID at the authoring stage, and search for that among the loaded objects using the find method.. See the class description for Object3D for more information.

Since the root-level objects are returned in an Object3D array, the application must find out their concrete types before using their full functionality. In the typical case, when the content is developed in conjunction with the application code and deployed in the same JAR file, the application should know what the root-level objects are. If this information is not available, or there is a need to check that the objects are as expected, the application can use the run-time type information that is built into Java. For example, a simple animation player application might want to check that the downloaded object is indeed a World, and display an appropriate error message otherwise.

Validity of the loaded objects

The set of objects returned by the Loader, comprising the root level objects as well as their descendants, is guaranteed to be valid and consistent with the API. In other words, it should be possible to construct the same scene graph using the API with no exceptions being thrown. For example, if a Mesh object is returned, the application can rest assured that it is in a state that can be reached via the API.

However, it is not guaranteed that the loaded content is renderable. Conditions that cause deferred exceptions are not checked for, and may exist within the loaded objects. This allows fragmentary scene graphs, which are invalid for rendering, to be loaded and assembled by the application into a valid scene graph.

Implementation guidelines

Implementations must not rely on the file extension (such as ".png") to determine the type of the file that is to be loaded. Instead, if the MIME type is available, that should be used to screen out unrecognized files without examining the contents. If the MIME type is not available (such as when loading from a byte array), or it does indicate a supported format, the implementation must ascertain the file type based on its contents. M3G files can be recognized from the file identifier, and PNG files from their corresponding signature.

Implementations must conform to the requirements set forth in the PNG specification, section Conformance of PNG decoders. In addition, the tRNS chunk (transparency information) must be fully supported. The implementation may also support other ancillary chunks. The pixel format of the resulting Image2D must be determined from the color type and transparency information contained in the PNG file, as specified in the table below.

PNG color type Image2D pixel format
Greyscale (type 0) LUMINANCE
Greyscale (type 0) + tRNS LUMINANCE_ALPHA
Truecolor (type 2) RGB
Truecolor (type 2) + tRNS RGBA
Indexed-color (type 3) RGB
Indexed-color (type 3) + tRNS RGBA
Greyscale with alpha (type 4) LUMINANCE_ALPHA
Truecolor with alpha (type 6) RGBA

See Also:
M3G (JSR-184) file format, PNG file format
Example:
A code fragment illustrating the use of Loader and find.
Object3D[] roots=null;

try {
    // Load a World and an individual Mesh over http.

    roots = Loader.load("http://www.example.com/myscene.m3g");
} catch(IOException e) {
    // couldn't open the connection, or invalid data in the file
}

// The root objects must be cast from Object3D to their immediate types
// (Mesh and World) before their full functionality can be used. Since
// the relative ordering of the root objects is unspecified, we can't
// assume that the World object is always at index 0, for example. Instead,
// we identify the World by its user ID of 1, which we have assigned to it
// at the authoring stage.

World myWorld;                      // contains our entire scene graph
Mesh myMesh;                        // an individual mesh for immediate mode

if (roots[0].getUserID() == 1) {    // our World has a user ID of 1
    myWorld = (World) roots[0];
    myMesh = (Mesh) roots[1];
} else {
    myWorld = (World) roots[1];
    myMesh = (Mesh) roots[0];
}

// Turn on perspective correction for the Mesh.

Appearance a = myMesh.getAppearance(0);  // get the appearance of the mesh
PolygonMode p = a.getPolygonMode();      // get its polygon attributes
p.setPerspectiveCorrectionEnable(true);  // enable perspective correction

// Find a specific Camera node in the World, and set it as the currently
// active camera in the world. We've previously assigned the userID "10"
// to that camera node.

Camera myCamera = (Camera) myWorld.find(10);
myWorld.setActiveCamera(myCamera);

// Load an individual PNG file.

Image2D textureImage=null;

try {
     textureImage = (Image2D)Loader.load("/texture.png")[0];
} catch(IOException e) {
     // couldn't load the PNG file
}

Method Summary
static Object3D[] load(byte[] data, int offset)
          Deserializes Object3D instances from the given byte array, starting at the given offset.
static Object3D[] load(java.lang.String name)
          Deserializes Object3D instances from the named resource.
   

Method Detail

load

public static Object3D[] load(java.lang.String name)
                       throws java.io.IOException

Deserializes Object3D instances from the named resource. The name of the resource is as defined by Class.getResourceAsStream(name), or a URI. The types of data that can be loaded with this method are defined in the class description.

Parameters:
name - name of the resource to load from
Returns:
an array of newly created Object3D instances
Throws:
java.lang.NullPointerException - if name is null
java.io.IOException - if name, or any resource referenced from it, cannot be resolved or accessed
java.io.IOException - if the data in name, or in any resource referenced from it, is not in accordance with the M3G and PNG file format specifications
java.lang.SecurityException - if the application does not have the security permission to open a connection to load the data

load

public static Object3D[] load(byte[] data,
                              int offset)
                       throws java.io.IOException

Deserializes Object3D instances from the given byte array, starting at the given offset. The types of data that can be loaded with this method are defined in the class description. The byte array must not contain any relative references (such as "/pics/texture.png"), but complete URIs are allowed.

Parameters:
data - byte array containing the serialized objects to load
offset - index at which to start reading the data array
Returns:
an array of newly created Object3D instances
Throws:
java.lang.NullPointerException - if data is null
java.lang.IndexOutOfBoundsException - if (offset < 0) || (offset >= data.length)
java.io.IOException - if any external references in data cannot be resolved or accessed
java.io.IOException - if the data in data, or in any resource referenced from it, is not in accordance with the M3G and PNG file format specifications
java.lang.SecurityException - if the application does not have the security permission to open a connection to load an external reference

M3G 1.1 -- Jun 22, 2005

Copyright © 2005 Nokia Corporation. See the Copyright Notice for details.