M3G 1.1 -- Jun 22, 2005

javax.microedition.m3g
Class Sprite3D

java.lang.Object
  extended byjavax.microedition.m3g.Object3D
      extended byjavax.microedition.m3g.Transformable
          extended byjavax.microedition.m3g.Node
              extended byjavax.microedition.m3g.Sprite3D

public class Sprite3D
extends Node

A scene graph node that represents a 2-dimensional image with a 3D position.

Sprite3D is a fast, but functionally restricted alternative to textured geometry. A Sprite3D is rendered as a screen-aligned rectangular array of pixels with a constant depth. The apparent size of a sprite may be specified directly in pixels (an unscaled sprite) or indirectly using the transformation from the Sprite3D node to the camera space (a scaled sprite).

The structure of a Sprite3D object is shown in the figure below.

Sprite image data

The sprite image is stored as a reference to an Image2D. The image may be in any of the formats defined in Image2D. The width and height of the image are not limited in any way; in particular, they need not be powers of two. However, there is an implementation defined maximum size for the crop rectangle (the area of the sprite that is actually displayed). This can be queried with getProperties.

The displayed sprite image can be mirrored with respect to the X and/or Y axes by specifying a crop rectangle with a negative width and/or height, respectively.

If the referenced Image2D is mutable and is modified while it is bound to a Sprite3D, or a new Image2D is bound as the sprite image, the modifications are immediately reflected in the Sprite3D. Be aware, however, that changing or updating the sprite image may trigger time-consuming operations.

Sprite positioning and scaling

The position of a sprite on screen is determined by projecting the origin of its coordinate system to screen coordinates. The resulting 2D position is used as the center of the displayed pixel array. If this causes any part of the sprite to be placed off screen, then the sprite is clipped to the visible portion of the viewport as usual (refer to Graphics3D).

The depth value of a sprite is constant across the image, and is the depth of the origin of the Sprite3D coordinate system.

The width and height of an unscaled sprite on screen are measured in pixels, and they are equal to the (absolute) width and height of the crop rectangle. Recall that the crop rectangle dimensions may be negative to flip the pixels; this has no effect on the size of the sprite.

The width and height of a scaled sprite on screen are computed basically as if the sprite were a rectangle with unit-length sides, lying on the XY plane of its local coordinate system and centered at its origin. The contents of the crop rectangle are scaled to fill the projected unit rectangle. See the Implementation guidelines below for the details.

Because a sprite is always displayed as a screen-aligned rectangle, the effects of other than rigid-body transformations on sprites may not be immediately intuitive, even though they are well-defined. It is advised that, for example, non-uniform scaling and skewing be avoided in sprite modelview matrices. Similarly, oblique projections should be used with caution when sprites are present in the displayed scene.

Sprite rendering attributes

The rendering attributes for a Sprite3D are determined by its Appearance, as is the case with Mesh objects. There are a number of properties in Appearance, however, that do not have a meaningful interpretation in this context. Thus, only the CompositingMode and Fog components and the layer index are taken into account when rendering a sprite. The rest of the components are ignored. This implies, in particular, that lighting does not apply for sprites.

Sprite picking

Only scaled sprites can be picked. This is because the dimensions of an unscaled sprite are only defined in screen space, that is, after the viewport transformation. Since the viewport parameters are not available to the pick method, the dimensions of an unscaled sprite can not be computed.

Picking of scaled sprites is analogous to how they are rendered. Picking is done in normalized device coordinates (after projection, before viewport transformation), where the position, depth value and dimensions of scaled sprites are well defined. See the Implementation guidelines for how to calculate these.

Since the sprite size calculation requires a Camera, sprites are only pickable through the viewing plane, not from an arbitrary position in the scene. That is, of the two pick variants in Group, only the one that takes in a Camera as a parameter can be used in sprite picking. The other variant simply ignores all sprite nodes.

If a sprite is intersected by the pick ray, the pixel in the sprite image at the intersection point will be further tested for transparency. If the pixel is fully transparent, the sprite is not picked and the pick ray will continue towards objects that are further away. If the pixel is not fully transparent, the sprite is picked. A pixel is defined to be fully transparent if and only if it fails the alpha test (see CompositingMode.setAlphaThreshold) prior to applying the alpha factor.

Implementation guidelines

Sprites do not provide any functionality that would not be available otherwise; they can always be substituted with textured meshes. However, the existence of the sprite primitive acts as a signal to the renderer that a very specific subset of functionality is required. This allows the rendering pipeline to avoid the overhead of transforming and lighting full geometry. It also allows the rasterizer to select an optimized drawing routine to place the pixels on the screen, without the potentially complex interpolation of parameters across the rectangle. This can be used to make sprites very much faster than textured meshes (especially in software) which in turn increases the richness of content that can be offered at the low end.

Filtering of scaled sprites can be implemented with the simple nearest neighbor algorithm, but implementations are recommended to apply a more sophisticated scheme, such as bilinear filtering with mipmapping. No application control over the filtering behavior is provided, however; if that is required, the application should use textured rectangles instead. For unscaled sprites, the implementation should ensure that rounding errors or similar do not yield unwelcome artifacts, such as pixel columns appearing and disappearing depending on the screen position of the sprite. This is particularly important for text labels.

Implementing with textures

Sprite3D can be implemented with textured rectangles. To facilitate that, implementations are allowed to upscale or downscale the sprite image to power-of-two dimensions, preferably using bilinear filtering or better. Images exceeding the maximum texture size may be downscaled to the maximum size. However, implementations striving for best image quality would keep the large original image around, texturing the rectangle with the crop rectangle contents only. Note that if the sprite image is mutable, the original image must be kept around in any case.

The sprite alpha factor can be trivially implemented with the MODULATE texture blending mode, by setting the fragment alpha equal to the effective alpha factor and the fragment color components to 1.0. Another option is to premultiply the alpha factor into the alpha channel of the sprite image; however, the implementation must then make sure that the original alpha values can always be recovered intact.

Computing the position and size

The position of a sprite on the viewport is simply the projected location of the Sprite3D node's origin. Similarly, the depth of the sprite is the projected depth of the origin.

The size of a sprite, in pixels, depends on whether the sprite is scaled or not. An unscaled sprite is the same size as its crop rectangle. Calculating the size of a scaled sprite is slightly more complicated. In principle, it only involves projecting the Sprite3D node's X and Y axes into screen space and computing their length, but to make the calculation well defined under arbitrary transformations, a few additional steps are required. The exact formula is given below.

Let us define M and P as the current modelview and projection matrices. The modelview matrix M is the concatenated transformation from the Sprite3D node into camera space (taking into account all of the transformation components of the Sprite3D, including the user-settable static matrix), and P is the projection matrix of the current camera.

Let us first transform the origin and two reference points, corresponding to the X and Y axes, from the Sprite3D node's coordinate system into camera space:

We then compute the distances from the origin to the X and Y reference points. If the bottom row of the modelview matrix is not (0 0 0 1), the transformed points may have W values different from each other. The points are thus brought into an equal scale (W = 1) before computing the distance.

Note that the W components of the homogeneous points cancel out in the subtraction, and the lengths computed are those of the 3D vectors. We then define (new) X and Y reference points that lie on the X and Y axes of the camera and whose distances from the origin are dx and dy, respectively. Applying the projection matrix, we transform the origin and the reference points into clip space:

Again, we compute the distances from the origin to the X and Y reference points. This gives us the dimensions of the sprite in normalized device coordinates.

These dimensions are used when testing the sprite for an intersection with a pick ray. For rendering the sprite, we need to apply the viewport transformation (see Graphics3D) to obtain the final on-screen size in pixels:

where wvp and hvp are the dimensions of the viewport.

The pixels within the crop rectangle are mapped onto the resulting rectangle. If both the crop width and height are positive, then the top left pixel of the crop rectangle maps to the top left pixel of the rectangle as displayed. Negating the height or width will flip or mirror the sprite as described in setCrop.

Note that this formula may produce unintuitive results if the modelview matrix M incorporates, for example, non-uniform scaling and/or skewing components. However, the size computation is well-defined and predictable.

Also note that in the equations above, we transform and project the X and Y axes of the sprite node as two homogeneous points each; implementations may obtain the same result by transforming them differently.

See Also:
Binary format

Field Summary
 
Fields inherited from class javax.microedition.m3g.Node
NONE, ORIGIN, X_AXIS, Y_AXIS, Z_AXIS
 
Constructor Summary
Sprite3D(boolean scaled, Image2D image, Appearance appearance)
          Constructs a new Sprite3D with the given scaling mode, image and appearance.
 
Method Summary
 Appearance getAppearance()
          Gets the current Appearance of this Sprite3D.
 int getCropHeight()
          Gets the current cropping rectangle height within the source image.
 int getCropWidth()
          Gets the current cropping rectangle width within the source image.
 int getCropX()
          Retrieves the current cropping rectangle X offset relative to the source image top left corner.
 int getCropY()
          Retrieves the current cropping rectangle Y offset relative to the source image top left corner.
 Image2D getImage()
          Gets the current Sprite3D image.
 boolean isScaled()
          Returns the automatic scaling status of this Sprite3D.
 void setAppearance(Appearance appearance)
          Sets the Appearance of this Sprite3D.
 void setCrop(int cropX, int cropY, int width, int height)
          Sets a cropping rectangle within the source image.
 void setImage(Image2D image)
          Sets the sprite image to display.
 
Methods inherited from class javax.microedition.m3g.Node
align, getAlignmentReference, getAlignmentTarget, getAlphaFactor, getParent, getScope, getTransformTo, isPickingEnabled, isRenderingEnabled, setAlignment, setAlphaFactor, setPickingEnable, setRenderingEnable, setScope
 
Methods inherited from class javax.microedition.m3g.Transformable
getCompositeTransform, getOrientation, getScale, getTransform, getTranslation, postRotate, preRotate, scale, setOrientation, setScale, setTransform, setTranslation, translate
 
Methods inherited from class javax.microedition.m3g.Object3D
addAnimationTrack, animate, duplicate, find, getAnimationTrack, getAnimationTrackCount, getReferences, getUserID, getUserObject, removeAnimationTrack, setUserID, setUserObject
   

Constructor Detail

Sprite3D

public Sprite3D(boolean scaled,
                Image2D image,
                Appearance appearance)

Constructs a new Sprite3D with the given scaling mode, image and appearance. The sprite image and appearance can be changed at any time, but the scaling mode is fixed at construction. If the appearance is null, rendering and picking of the sprite is disabled.

The crop rectangle is set such that its top left corner is at the top left corner of the image, and its width and height are equal to the dimensions of the image. However, if the width (or height) of the crop rectangle would exceed the implementation defined maximum, the width (or height) is set to the maximum value instead. The maximum crop rectangle size can be queried with getProperties.

Parameters:
scaled - true to make this Sprite3D scaled; false to disable scaling
image - pixel data and image properties to use to draw this Sprite3D
appearance - the Appearance to use for this Sprite3D, or null to disable this sprite initially
Throws:
java.lang.NullPointerException - if image is null
Method Detail

isScaled

public boolean isScaled()

Returns the automatic scaling status of this Sprite3D. Note that the scaling mode cannot be changed after construction.

Returns:
true if this sprite is scaled; false if it is unscaled

setAppearance

public void setAppearance(Appearance appearance)

Sets the Appearance of this Sprite3D. Note that the PolygonMode, Texture and Material components of the Appearance are ignored.

Parameters:
appearance - the Appearance to set, or null to disable this sprite
See Also:
getAppearance

getAppearance

public Appearance getAppearance()

Gets the current Appearance of this Sprite3D.

Returns:
the current Appearance of this sprite
See Also:
setAppearance

setImage

public void setImage(Image2D image)

Sets the sprite image to display. The crop rectangle is reset in the same way as in the constructor.

Parameters:
image - pixel data and image properties to use to draw this sprite
Throws:
java.lang.NullPointerException - if image is null
See Also:
getImage

getImage

public Image2D getImage()

Gets the current Sprite3D image.

Returns:
the Image2D object used to draw this sprite
See Also:
setImage

setCrop

public void setCrop(int cropX,
                    int cropY,
                    int width,
                    int height)

Sets a cropping rectangle within the source image. This allows a subsection of the image to be used as the source for the pixels of the sprite. This can be used for selection of individual frames of animation, scrolling of captions, or other effects.

The position of the upper left corner of the crop rectangle is given in pixels, relative to the upper left corner of the Image2D. Note that the relative position may be negative in either or both axes.

If the crop rectangle has zero width or height, the sprite is not rendered or picked. If, on the other hand, the width and/or height are negative, the sprite image is flipped in the X and/or Y axes, respectively. Note that the crop rectangle remains in the same position within the source image regardless of the signs of the width and height; only the drawing order of the pixels is changed.

The absolute values of the crop width and height are limited to an implementation defined maximum that can be queried from Graphics3D.

Wrapping of the source image is not supported. If the crop rectangle lies completely or partially outside of the image boundaries, the (imaginary) pixels outside of the image are treated as if failing the alpha test. In other words, they are not rendered, but the on-screen size and pixel zoom factor of the sprite remain the same as if the crop rectangle were completely inside the image.

Parameters:
cropX - the X position of the top left of the crop rectangle, in pixels
cropY - the Y position of the top left of the crop rectangle, in pixels
width - the width of the crop rectangle, in pixels
height - the height of the crop rectangle, in pixels
Throws:
java.lang.IllegalArgumentException - if width or height exceeds the implementation defined maximum

getCropX

public int getCropX()

Retrieves the current cropping rectangle X offset relative to the source image top left corner.

Returns:
the X offset of the cropping rectangle
See Also:
setCrop

getCropY

public int getCropY()

Retrieves the current cropping rectangle Y offset relative to the source image top left corner.

Returns:
the Y offset of the cropping rectangle
See Also:
setCrop

getCropWidth

public int getCropWidth()

Gets the current cropping rectangle width within the source image. The width may be negative, in which case the image data is flipped in the X axis.

Returns:
the width of the cropping rectangle
See Also:
setCrop

getCropHeight

public int getCropHeight()

Gets the current cropping rectangle height within the source image. The height may be negative, in which case the image data is flipped in the Y axis.

Returns:
the height of the cropping rectangle
See Also:
setCrop

M3G 1.1 -- Jun 22, 2005

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