JSR-184 Public Review Draft - Apr. 30, 2003.

javax.microedition.m3d
Class Graphics3D

java.lang.Object
  |
  +--javax.microedition.m3d.Graphics3D

public class Graphics3D
extends java.lang.Object

A singleton 3D graphics context that can be bound to a rendering target. All rendering is done through the render methods in this class, including the rendering of World objects. There is no other way to draw anything in this API.

Mode of operation

Initialization:

create the Graphics3D instance
set rendering quality hints (optional)

Per frame:

bind a rendering target
set the viewport (optional)
if not using retained mode
   clear the color buffer (optional)
   clear the depth buffer (if used)
   set up the current camera
   set up the current lights
endif
render everything
release the target

Immediate mode and retained mode rendering

There are three different render methods, operating at different levels of granularity. The first method is for rendering an entire World. When this method is used, we say that the API operates in retained mode. The second method is for rendering scene graph nodes, including Groups. The third method is for rendering an individual submesh. When the latter two methods are used, the API is said to operate in immediate mode.

There is a current camera and an array of current lights in Graphics3D. These are used by the immediate mode rendering methods only. The retained mode rendering method render(World) uses the camera and lights that are specified in the World itself, ignoring the Graphics3D camera and lights. Instead, render(World) replaces the Graphics3D current camera and lights with the active camera and lights in the rendered World. Note that the number of lights in Graphics3D has a fixed limit, typically 4 or 8, while a World may contain an arbitrary number of lights. For this reason, the set of lights in Graphics3D after rendering a World is partially undefined: they can be any lights that were used in rendering the World.

Rendering targets

Before rendering anything or even clearing the screen, the application must bind a rendering target to this Graphics3D, using the bindTarget method. The rendering target can be either a Graphics object or an Image2D. The Graphics object, in turn, can be associated with a Canvas, a mutable Image, or a CustomItem. When finished with rendering a frame, the application must release the rendering target by calling the releaseTarget method. Implementations may queue rendering commands and only execute them when the target is released.

Once a rendering target is bound to the Graphics3D, all rendering will end up in the color buffer of its rendering target until releaseTarget is called. The contents of the rendering target, after releasing it, will be equal to what they were before the target was bound, augmented with any 3D rendering performed while it was bound.

There can be only one rendering target bound to the Graphics3D at a time. Also, a bound rendering target should not be accessed via any other interface than the host Graphics3D. This is not enforced, but the results are unpredictable otherwise. For example, the following scenarios will result in unpredictable output:

The contents of the depth buffer are unspecified after bindTarget, and they are discarded after releaseTarget. In order to clear depth buffer contents (and color buffer contents, if so desired) after binding a rendering target, the application must call the clear method, either explicitly, or implicitly by rendering a World.

2D translations and clipping

The viewport can be positioned freely relative to the rendering target, without releasing and re-binding the target. The position of the viewport is specified relative to the origin of the rendering target: for Graphics targets, this is the origin in effect when calling bindTarget; for Image2D targets, the origin is always in the top left corner.

All 3D rendering is clipped to the intersection of the viewport and the rendering target clip rectangle. That is, rendering operations (including clear) will not touch pixels falling outside of either the viewport or the target clip rectangle. This is illustrated in the figure below.

For Graphics targets, the clipping rectangle is the MIDP clipping rectangle that is in effect when calling bindTarget. Changes to the clipping rectangle of a bound Graphics object have no effect. For Image2D targets, the clipping rectangle comprises all pixels in the target image.

2D translation and clipping are independent of the viewport and projection transformations, as well as rasterization. All other parameters being equal, rendering calls must produce the same pixels (prior to clipping) into the area bounded by the viewport regardless of the position of the viewport or the target clipping rectangle.

Rendering quality hints

In some situations, image quality might be more important for an application than rendering speed or memory usage. Some applications might also want to increase or decrease the image quality based on device capabilities. Some might go so far as to dynamically adjust the quality; for instance, by displaying freeze frames or slow-motion sequences in higher quality.

There are three global options in Graphics3D that allow applications to indicate a preference for higher rendering quality at the expense of slower speed and/or extra memory usage. These are the following:

These settings are merely hints, meaning that implementations may silently ignore them. A request to enable or disable these hints can be made at any time, but implementations may choose not to effect the changes until there is no rendering target bound to the Graphics3D.

Antialiasing is especially useful on displays with relatively large pixels. Dithering and true color rendering are typically used in conjunction with each other, and they are most beneficial on displays with relatively few colors. There are no requirements for how antialiasing or dithering should be implemented, nor is it specified how many bits per pixel are required for "true color".

Reference pipelines

The reference geometry and fragment pipelines are shown below. The mapping of Appearance components to the pipeline stages is also shown.

Implementations may optimize their operation by doing things in a different order, but only if the result is exactly the same as it would be with the reference pipelines.

Implementation guidelines

It is intentionally unspecified whether a separate back buffer should be allocated for colors or not. Instead, we leave the implementation to decide which mode of operation is the most efficient, or which produces the best quality, according to the dimensions and speed versus quality preferences given by the application. The decision to allocate any back buffer memory must be made upon first binding of each specific rendering target to the Graphics3D object at the latest. In other words, binding a rendering target that has already been bound to the Graphics3D object must be guaranteed not to incur the performance penalty of allocating back buffer memory, provided that the rendering quality hints remain unchanged.

In a practical implementation, it is probably more efficient to render directly to the target color buffer as a general rule. Therefore, it is strongly recommended that implementations not allocate back buffer memory unnecessarily. If a back buffer is required, it can be allocated when the target that requires it is first bound to the Graphics3D object. Note that in real-world applications, the same render target is likely to be repeatedly bound to the Graphics3D object.

As an example of when a back buffer may be desired, consider a case where the application specifies setDitheringEnable(true) and subsequently binds a Canvas target. If the MIDP native color format is of low precision (such as RGB444), the implementation may wish to render at a higher color precision to a back buffer, then dither down to the MIDP native color format.

See the General documentation conventions for treatment of null input values, etc.

Example:
A code fragment illustrating the usage of Graphics3D.
 public class MyCanvas extends Canvas
{
   Graphics3D g3d;
   World myWorld;
   int currentTime = 0;
    
   public MyCanvas() throws IOException {
   
      // Create the singleton Graphics3D instance and enable all
      // rendering quality enhancements. The rendering quality
      // hints should only be set between frames, that is, when
      // there is no rendering target bound to the Graphics3D.
               
      g3d = Graphics3D.createGraphics3D();
      g3d.setTrueColorEnable(true);
      g3d.setDitheringEnable(true);
      g3d.setAntialiasingEnable(true);
    
      // Load an entire World. Proper exception handling is omitted
      // for clarity; see the class description of Loader for a more
      // elaborate example.
    
      Object3D[] objects = Loader.load("http://www.example.com/myscene.m3d");
      myWorld = (World) objects[0];
   }
    
   // The paint method is called by MIDP after the application has issued
   // a repaint request. We draw a new frame on this Canvas by binding the
   // current Graphics object as the target, then rendering, and finally
   // releasing the target.

   protected void paint(Graphics g) {
   
      // Bind our 3D graphics context to the MIDP Graphics object. The
      // color buffer and depth buffer will have dimensions equal to
      // this Canvas. The viewport will cover the whole Canvas.
    
      g3d.bindTarget(g);
      
      // Apply animations.
      
      myWorld.animate(currentTime);
      g3d.render(myWorld);    // render a view from the active camera
      g3d.releaseTarget();    // flush the rendered image
      currentTime += 50;      // assume we can handle 20 frames per second
   }
}

Field Summary
static int BUF_COLOR
          A parameter to clear, specifying that the color buffer must be cleared according to the settings in the given Background.
static int BUF_DEPTH
          A parameter to clear, specifying that the depth buffer must be cleared.
 
Method Summary
 void bindTarget(java.lang.Object target)
          Binds the given Graphics or mutable Image2D as the rendering target of this Graphics3D.
 void clear(int buffers, Background background)
          Clears the color and/or depth buffer of this Graphics3D.
static Graphics3D createGraphics3D()
          Creates a new Graphics3D instance.
static java.util.Hashtable getProperties()
          Retrieves implementation specific properties.
 void releaseTarget()
          Flushes the rendered 3D image to the currently bound target.
 void render(Node node, Transform transform)
          Renders the given Sprite, Mesh, or Group node with the given transformation from local coordinates to world coordinates.
 void render(VertexBuffer vertices, IndexBuffer triangles, Appearance appearance, Transform transform)
          Renders the given submesh with the given transformation from local coordinates to world coordinates.
 void render(World world)
          Renders an image of world as viewed by the active camera of that World.
 void setAmbientLight(int RGB)
          Sets the ambient light intensity.
 void setAntialiasingEnable(boolean enable)
          Turns the antialiasing hint on or off for subsequent rendering.
 void setCamera(Camera camera, Transform transform)
          Sets the Camera to use in subsequent immediate mode rendering.
 void setDepthBufferEnable(boolean enable)
          Enables or disables the depth buffer for subsequent rendering.
 void setDitheringEnable(boolean enable)
          Turns the dithering hint on or off for subsequent rendering.
 void setLight(int index, Light light, Transform transform)
          Sets or removes a Light to use in subsequent immediate mode rendering.
 void setTrueColorEnable(boolean enable)
          Turns the true color hint on or off for subsequent rendering.
 void setViewport(int x, int y, int width, int height)
          Specifies a rectangular viewport on the currently bound rendering target.
 
Methods inherited from class java.lang.Object
equals, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
 

Field Detail

BUF_COLOR

public static final int BUF_COLOR

A parameter to clear, specifying that the color buffer must be cleared according to the settings in the given Background. The format and bit depth of the color buffer are implementation defined and are not known to the application.

See Also:
Constant Field Values

BUF_DEPTH

public static final int BUF_DEPTH

A parameter to clear, specifying that the depth buffer must be cleared.

See Also:
Constant Field Values
Method Detail

createGraphics3D

public static final Graphics3D createGraphics3D()

Creates a new Graphics3D instance. Since Graphics3D is a singleton, the application may only call this method once. Attempting to call it multiple times is an exception.

The new Graphics3D will be initialized with the following default values:

Returns:
a new Graphics3D instance
Throws:
java.lang.IllegalStateException - if a Graphics3D instance already exists

bindTarget

public void bindTarget(java.lang.Object target)

Binds the given Graphics or mutable Image2D as the rendering target of this Graphics3D. The type of the Graphics object depends on the Java profile that this specification is implemented on, as follows:

The viewport is set to cover the target clipping rectangle entirely.

Parameters:
target - the Image2D or Graphics object to receive the rendered image
Throws:
java.lang.IllegalStateException - if this Graphics3D already has a rendering target
java.lang.IllegalArgumentException - if target is not a mutable Image2D object or a Graphics object appropriate to the underlying Java profile
See Also:
releaseTarget()

releaseTarget

public void releaseTarget()

Flushes the rendered 3D image to the currently bound target. This ensures that the 3D image is actually made visible on the target that was set in bindTarget. Otherwise, the image may or may not become visible. See the class description for discussion on the semantics of mixing 2D rendering with 3D rendering.

Throws:
java.lang.IllegalStateException - if this Graphics3D does not have a rendering target

setViewport

public void setViewport(int x,
                        int y,
                        int width,
                        int height)

Specifies a rectangular viewport on the currently bound rendering target. The viewport is the area where the view of the current camera will appear. Any parts of the viewport that lie outside the boundaries of the target clipping rectangle are silently clipped off; however, this must simply discard the pixels without affecting projection. The viewport upper left corner (x, y) is given relative to the upper left corner of the target clipping rectangle.

After bindTarget, the viewport is set to cover the target clipping rectangle in full, but nothing more. That is, the upper left corner of the viewport will be at (0, 0) and its width and height will be equal to those of the target clipping rectangle.

The viewport mapping transforms vertices from normalized device coordinates (xd, yd, zd) to window coordinates (xw, yw, zw) as follows:

xw = 0.5 × xd × w + ox
yw = 0.5 × yd × h + oy
zw = 0.5 × zd + 0.5

where w and h are the width and height of the viewport, specified in pixels, and (ox, oy) is the center of the viewport, also in pixels. The center of the viewport is obtained from the (x, y) coordinates of the top left corner as follows:

ox = x + (w / 2)
oy = y + (h / 2)

Parameters:
x - X coordinate of the viewport upper left corner, in pixels
y - Y coordinate of the viewport upper left corner, in pixels
width - width of the viewport, in pixels
height - height of the viewport, in pixels
Throws:
java.lang.IllegalArgumentException - if width or height is negative or zero (note that x and y may have any value)
java.lang.IllegalArgumentException - if width or height exceeds the implementation defined maximum

clear

public void clear(int buffers,
                  Background background)

Clears the color and/or depth buffer of this Graphics3D. The buffers to be cleared are specified as an OR mask of BUF_COLOR and BUF_DEPTH. If depth buffering is disabled, the request to clear it will be silently ignored.

The color buffer is cleared either with a single color or a background image, as specified in the given Background. If background is null, the default background color (transparent black) is used. The depth buffer is cleared with the maximum depth value.

Parameters:
buffers - buffers to clear; an OR mask of BUF_COLOR and BUF_DEPTH
background - background color or image to clear the color buffer with, or null to clear with transparent black
Throws:
java.lang.IllegalArgumentException - if buffers is not one of BUF_COLOR, BUF_DEPTH, and BUF_COLOR | BUF_DEPTH
java.lang.IllegalStateException - if this Graphics3D does not have a rendering target

render

public void render(World world)

Renders an image of world as viewed by the active camera of that World. The current camera and lights set in this Graphics3D are ignored. Contrary to the immediate mode render variants, the color and depth buffers are automatically cleared, as per the Background object of the World. If there is no Background object, the depth buffer is cleared as usual, but the color buffer is not cleared at all.

The given World must be be self-contained in the sense that there must not be references to nodes outside of that world. Illegal references may arise from transform references in SkinnedMesh or from node alignment. This rule is to avoid ambiguity as to what to consider the "root" coordinate system between separate worlds.

Parameters:
world - the World to render
Throws:
java.lang.IllegalStateException - if this Graphics3D does not have a rendering target
java.lang.IllegalStateException - if world has no active camera, or the active camera is not in world
java.lang.IllegalStateException - if world is not self-contained
java.lang.IllegalStateException - if any Mesh in world violates the constraints defined in Mesh, MorphingMesh, SkinnedMesh, VertexBuffer, or IndexBuffer

render

public void render(Node node,
                   Transform transform)

Renders the given Sprite, Mesh, or Group node with the given transformation from local coordinates to world coordinates. The transformation of the node is ignored, as well as its alignment to anything but the current camera. Any ancestors of the node are also ignored, including their transformations and all other properties that they may have. In the case of a Group node, its renderable descendants are treated as usual. If there are any Camera or Light nodes among the descendants, they are ignored; the current camera and lights of this Graphics3D are used instead.

The set of nodes to be rendered, which includes the given node and its renderable descendants, must be self-contained in the sense that there must not be references to nodes outside of that set. Illegal references may arise from transform references in SkinnedMesh, or from alignment of any of the descendants (recall that alignment of the root node is ignored). This rule is to avoid ambiguity as to what to consider the "root" coordinate system between separate groups.

This method does not clear the color and depth buffers; the application must explicitly clear them with the clear method and/or draw any background graphics beforehand.

Parameters:
node - the Sprite, Mesh, or Group to render
transform - the transformation from the local coordinate system of node to world space, or null to indicate the identity matrix
Throws:
java.lang.IllegalArgumentException - if node is not a Sprite, Mesh, or Group
java.lang.IllegalStateException - if this Graphics3D does not have a rendering target
java.lang.IllegalStateException - if this Graphics3D does not have a current camera
java.lang.IllegalStateException - if node is not self-contained
java.lang.IllegalStateException - if any Mesh that is to be rendered violates the constraints defined in Mesh, MorphingMesh, SkinnedMesh, VertexBuffer, or IndexBuffer

render

public void render(VertexBuffer vertices,
                   IndexBuffer triangles,
                   Appearance appearance,
                   Transform transform)

Renders the given submesh with the given transformation from local coordinates to world coordinates. The composite transformation from object coordinates to camera space (the modelview transformation) is computed internally by left-multiplying the given transformation with the inverse of the current camera transformation (see setCamera).

Upon rendering the submesh, the vertex positions are transformed with the modelview transformation and the normal vectors with its inverse transpose. If the modelview matrix is not invertible, the results of lighting calculations are undefined. The scope masks of the active Lights are ignored.

Parameters:
vertices - a VertexBuffer defining the vertex attributes
triangles - an IndexBuffer defining the triangle strips
appearance - an Appearance defining the surface properties
transform - the transformation from the local coordinate system of vertices to world space, or null to indicate the identity matrix
Throws:
java.lang.IllegalStateException - if this Graphics3D does not have a rendering target
java.lang.IllegalStateException - if this Graphics3D does not have a current camera
java.lang.IllegalStateException - if vertices or triangles violates the constraints defined in VertexBuffer and IndexBuffer, respectively

setCamera

public void setCamera(Camera camera,
                      Transform transform)

Sets the Camera to use in subsequent immediate mode rendering. The given transformation is from the Camera's local coordinate system to the world space. The transformation is copied in, so any further changes to it will not be reflected in this Graphics3D. The node transformation of the Camera is ignored. If the Camera has any ancestors, they are also ignored.

Parameters:
camera - the Camera to use in immediate mode rendering
transform - transformation to world space for the Camera node, or null to indicate the identity matrix

setLight

public void setLight(int index,
                     Light light,
                     Transform transform)

Sets or removes a Light to use in subsequent immediate mode rendering. The given transformation is from the Light's local coordinate system to the world space. The transformation is copied in, so any further changes to it will not be reflected in this Graphics3D. The node transformation of the Light is ignored. If the Light has any ancestors, they are also ignored. The scope mask of the Light is respected when rendering Nodes. It has no effect when rendering an individual submesh, because submeshes do not have a scope ID.

The number of simultaneous lights supported by the implementation can be queried with the getProperties method.

Parameters:
index - index of the light to set; must be [0, maxLights-1]
light - the Light to set, or null to remove the light at index
transform - transformation for the Light node, or null to indicate the identity matrix
Throws:
java.lang.IllegalArgumentException - if index is not within the range [0, maxLights-1], where maxLights is the maximum number of simultaneous lights supported by the implementation

setAntialiasingEnable

public void setAntialiasingEnable(boolean enable)

Turns the antialiasing hint on or off for subsequent rendering. This method provides applications with a means to indicate a preference for higher rendering quality at the expense of rendering speed and memory usage, or vice versa.

The method of antialiasing is defined by the implementation and is not known to the application. Implementations may also disregard this hint and do antialiasing at their own discretion. For example, antialiasing might be done automatically, at no extra cost, on some devices.

The request to enable or disable antialiasing can be made at any time, but implementations may choose not to effect the change until there is no rendering target bound to the Graphics3D.

Parameters:
enable - true to turn the antialiasing hint on; false to turn it off

setDitheringEnable

public void setDitheringEnable(boolean enable)

Turns the dithering hint on or off for subsequent rendering. This method provides applications with a means to indicate a preference for higher rendering quality at the expense of rendering speed and memory usage, or vice versa.

The method of dithering is defined by the implementation and is not known to the application. Implementations may also disregard this hint and do dithering at their own discretion. For example, dithering might not be necessary at all on some devices.

The request to enable or disable dithering can be made at any time, but implementations may choose not to effect the change until there is no rendering target bound to the Graphics3D.

Parameters:
enable - true to turn dithering on, false to turn it off

setTrueColorEnable

public void setTrueColorEnable(boolean enable)

Turns the true color hint on or off for subsequent rendering. This method provides applications with a means to indicate a preference for higher rendering quality at the expense of rendering speed, or vice versa.

The request to enable or disable true color rendering can be made at any time, but implementations may choose not to effect the change until there is no rendering target bound to the Graphics3D.

Parameters:
enable - true to turn dithering on, false to turn it off

setDepthBufferEnable

public void setDepthBufferEnable(boolean enable)

Enables or disables the depth buffer for subsequent rendering. If the depth buffer is disabled, depth testing and depth writing are implicitly disabled for all objects, regardless of their individual settings. If the depth buffer is enabled, on the other hand, the settings of each individual submesh or sprite are respected.

The format and bit depth of the depth buffer are specific to each implementation and are not known to the application. The contents of the depth buffer are never exposed through the API, so implementations may choose not to use a conventional depth buffer at all. However, all conforming implementations are guaranteed to behave as if they were using an ordinary depth buffer.

Note that the depth buffer can not be turned on or off while a rendering target is bound to the Graphics3D.

Parameters:
enable - true to enable the depth buffer; false to disable it
Throws:
java.lang.IllegalStateException - if this Graphics3D is bound to a rendering target

getProperties

public static final java.util.Hashtable getProperties()

Retrieves implementation specific properties. The properties are stored in a Hashtable that is keyed by String values. The Hashtable will always contain the entries listed in the table below, but there may also be other entries specific to each implementation.

Key (String) Value type Possible values
specVersion String "1.0"
supportFSAA Boolean true/false
supportTrueColor Boolean true/false
supportDither Boolean true/false
supportMipmap Boolean true/false
supportPerspectiveCorrection Boolean true/false
maxLights Integer 4 or greater
maxViewportDimension Integer 64 or greater
maxTextureDimension Integer 64 or greater
maxSpriteCropDimension Integer 64 or greater
numTextureUnits Integer 2 or greater
maxTransformsPerVertex Integer 2 or greater

Returns:
a Hashtable defining properties specific to this implementation

setAmbientLight

public void setAmbientLight(int RGB)

Sets the ambient light intensity. The high order byte of the color value is ignored.

Parameters:
RGB - the new global ambient light in 0x00RRGGBB format

JSR-184 Public Review Draft - Apr. 30, 2003.

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