JSR 184, the Mobile 3D Graphics (M3G) API, gives MIDlets the ability to show 3D content. It is a scaled-down version of the desktop Java platform 3D API.
The M3G API is a scene graph API, which means it knows how to render scenes that are described as a hierarchy of groups and objects. The API includes all the classes and methods you need to create scenes from the ground up.
A much more likely alternative is that a graphic artist will create a 3D scene. Then your job becomes a lot easier because you just have to display the scene. JSR 184 specifies a comprehensive file format. An entire 3D scene, including lights, cameras, and animation, can be designed by an artist and saved in an M3G file.
The M3G API is contained in a single package, javax.microedition.m3g
.
The simplest case is that you want to display some 3D content created by your graphic designer. In this case, you don’t need to know anything about 3D graphics. This use of the M3G API is retained mode.
Your graphic designer can use standard modeling tools like 3ds Max, Lightwave, or Blender. 3ds Max can export to M3G directly, but other packages might need plug-ins or additional tools. Here are some of the available M3G tools:
Mascot Capsule M3GConverter
http://www.mascotcapsule.com/toolkit/m3g/en/
Blender M3G Exporter
http://www.nelson-games.de/bl2m3g/default.html
M3GToolkit
http://www.java4ever.com/index.php?section=j2me&project=m3gtoolkit&menu=main&lang=_en
M3G Exporter for 3ds Max 5.1 and 6.0
http://www.m3gexporter.com
Use Loader
to retrieve a 3D scene from a file. The static load()
method retrieves an array of Object3D
s from a file. In most cases, the array contains a single element, an instance of World
.
M3G files can contain animations. You can control the animation by passing a time value to the animate()
method that World
inherits from Object3D
. Usually the time value is specified as milliseconds, but it can be any unit that the graphic designer and developer agree upon. Calling animate()
updates everything in the scene to be correct for a certain point in time.
A Graphics3D
knows how to draw a scene on the display. You can retrieve a Graphics3D
from its static factory method.
When it comes time to paint your Canvas
, you must bind the Graphics3D
to the Graphics
you are using for painting. Then pass the scene to render()
. When you’re done with 3D drawing, unbind the Graphics3D
by calling releaseTarget()
.
If the M3G file you’re displaying is created correctly, this is the whole story. You don’t have to understand anything about meshes or cameras or lights. All that information is contained in the M3G file.
Here is a MIDlet and Canvas
that take advantage of the Game API (Chapter 11) to animate a World
. It also demonstrates that you can choose to animate a world to any point in time. After animating forward for 2 seconds, it animates in reverse for 2 seconds. You can adjust the cycle time with the cycle
variable in the tick()
method of SimpleM3GCanvas
.
Copy the swerve.m3g
file from the Demo3D
example that comes with the Sun Java Wireless Toolkit. On Sun’s emulator, SimpleM3GPlayer
looks like Figure 13.1.
Figure 13.1. The SimpleM3GPlayer
example
For data visualization or other applications, use the M3G API’s immediate mode to create 3D objects on the fly.
An entire scene consists of a hierarchy of 3D nodes. A node can be an object, a camera, or a light.
Your own objects will be created from instances of Mesh
. Ultimately, a Mesh
is assembled from many triangles. A Mesh
contains information about every vertex (corner) in your object, how those corners are connected to create triangles, and information about the color and light properties of the vertices.
I won’t cover all of this material in great detail, because most of it is standard 3D graphics information. However, to get things rolling for you, I’ll walk through an example of creating a cube Mesh
and provide sample code for the cube and a sphere.
Consider a cube as shown in Figure 13.2.
Figure 13.2. The SimpleM3GPlayer
example
Starting from the bottom, then, you could define the eight vertices of a cube like this:
Each face of the cube is defined by a triangle strip consisting of two triangles. The two triangles are fully defined by four vertices, so each face of the cube is defined by a triangle strip with four vertices.
Triangle strips are defined by specifying the indices of the corresponding vertices. For example, a single triangle ABD
would be defined by the indices 0
, 1
, and 3
. A triangle strip containing ABDC
defines two triangles, ABD
and DBC
. (You might think it would be ABD
and BDC
, but the odd-numbered triangles in the strip swap the first two vertices.) All six faces of the cube can be defined like this:
The ordering is a little tricky because the triangles have to be defined correctly so that the device knows which side of the triangle is the outside.
Finally, you can define a color for each vertex by creating an array that has three bytes of RGB color information per vertex.
The vertex positions and vertex colors can be assembled into a VertexBuffer
like this:
The indices into the vertices are likewise assembled in a TriangleStripArray
, which is a type of IndexBuffer
:
With the vertices and indices all nicely packaged, you can now create a Mesh
to contain everything. An Appearance
object specifies the light properties of the object. This example uses a default Appearance
.
Once you’ve got a Mesh
, it can be added to your World
just like any other 3D object. Here the mesh is added to a Group
and then to a World
:
The following class, CubeMeshGenerator
, encapsulates most of this code. Call generate()
to create a cube. Pass in the length of a side.
The result is a colorful cube, as in Figure 13.3.
Figure 13.3. The result of CubeMeshGenerator
And here is a MIDlet and Canvas
that display the cube and spin it around. They look very similar to the MIDlet and Canvas
you used before to play an M3G file.
You should also notice that MeshMIDlet
also contains some code to create a sphere using SphereMeshGenerator
. I won’t reproduce the class here, because it’s a lot of trigonometry and index twiddling, but you can find it in the source code download if you want to take a look. For fun, try using peppermintColors
instead of rainbowColors
in SphereMeshGenerator
’s createVertexColors()
method. Figure 13.4 shows MeshMIDlet
in action.
Figure 13.4. A cube and a sphere
The M3G API is a scene graph 3D graphics API. A graphic designer can use a 3D authoring package to create a 3D scene in an M3G file. Loading and showing an M3G file (retained mode) is relatively easy. Applications that need to generate 3D scenes at runtime can use immediate mode to create a complete scene.
Sony Ericsson has lots of information on the JSR 184 M3G API here:
3.144.97.187