Developing Mobile 3D Graphics for J2ME (JSR-184)
- Apr 15, 2005
Example
We'll develop a very simple 3D application that rotates a polygon. The polygon is a cube and its texture is a photo of an old car. Listing 1 shows the midlet's main class—the central class of the application. It creates the application and sets the timer to run MyCanvas.
Listing 1. MIDletMain class
import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;
import java.util.*;
public class MIDletMain extends MIDlet {
static MIDletMain midlet;
MyCanvas d = new MyCanvas();
Timer iTimer = new Timer();
public MIDletMain() {
this.midlet = this;
}
public void startApp() {
Display.getDisplay(this).setCurrent(d);
iTimer.schedule( new MyTimerTask(), 0, 40 );
}
public void pauseApp() {
}
public void destroyApp(boolean unconditional) {
}
public static void quitApp() {
midlet.destroyApp(true);
midlet.notifyDestroyed();
midlet = null;
}
class MyTimerTask extends TimerTask {
public void run() {
if( d != null ) {
d.repaint();
}
}
}
}
Listing 2 shows the MyCanvas class, which contains all the graphical logic of the application. In init() method the vertices are created, the texture file is loaded, and the texture is set. The appearance and the background are also set. The paint() method paints and rotates the cube. The Figure 1 shows the actual application running in an emulator.
Listing 2. MyCanvas class
import javax.microedition.lcdui.*;
import javax.microedition.m3g.*;
public class MyCanvas extends Canvas {
private Graphics3D graphics3d;
private Camera camera;
private Light light;
private float angle = 0.0f;
private Transform transform = new Transform();
private Background background = new Background();
private VertexBuffer vbuffer;
private IndexBuffer indexbuffer;
private Appearance appearance;
private Material material = new Material();
private Image image;
public MyCanvas() {
// set up this Displayable to listen to command events
setCommandListener(new CommandListener() {
public void commandAction(Command c, Displayable d) {
if (c.getCommandType() == Command.EXIT) {
MIDletMain.quitApp();}}
});
try { init();}
catch(Exception e) { e.printStackTrace();}
}
/**
* Component initialization.
*/
private void init() throws Exception {
addCommand(new Command("Exit", Command.EXIT, 1));
graphics3d = Graphics3D.getInstance();
camera = new Camera();
camera.setPerspective( 60.0f,
(float)getWidth()/ (float)getHeight(),
1.0f,
1000.0f );
light = new Light();
light.setColor(0xffffff);
light.setIntensity(1.25f);
short[] vert = {
5, 5, 5, -5, 5, 5, 5,-5, 5, -5,-5, 5,
-5, 5,-5, 5, 5,-5, -5,-5,-5, 5,-5,-5,
-5, 5, 5, -5, 5,-5, -5,-5, 5, -5,-5,-5,
5, 5,-5, 5, 5, 5, 5,-5,-5, 5,-5, 5,
5, 5,-5, -5, 5,-5, 5, 5, 5, -5, 5, 5,
5,-5, 5, -5,-5, 5, 5,-5,-5, -5,-5,-5 };
VertexArray vertArray = new VertexArray(vert.length / 3, 3, 2);
vertArray.set(0, vert.length/3, vert);
// The per-vertex normals for the cube
byte[] norm = {
0, 0, 127, 0, 0, 127, 0, 0, 127, 0, 0, 127,
0, 0,-127, 0, 0,-127, 0, 0,-127, 0, 0,-127,
-127, 0, 0, -127, 0, 0, -127, 0, 0, -127, 0, 0,
127, 0, 0, 127, 0, 0, 127, 0, 0, 127, 0, 0,
0, 127, 0, 0, 127, 0, 0, 127, 0, 0, 127, 0,
0,-127, 0, 0,-127, 0, 0,-127, 0, 0,-127, 0 };
VertexArray normArray = new VertexArray(norm.length / 3, 3, 1);
normArray.set(0, norm.length/3, norm);
// per vertex texture coordinates
short[] tex = {
1, 0, 0, 0, 1, 1, 0, 1,
1, 0, 0, 0, 1, 1, 0, 1,
1, 0, 0, 0, 1, 1, 0, 1,
1, 0, 0, 0, 1, 1, 0, 1,
1, 0, 0, 0, 1, 1, 0, 1,
1, 0, 0, 0, 1, 1, 0, 1 };
VertexArray texArray = new VertexArray(tex.length / 2, 2, 2);
texArray.set(0, tex.length/2, tex);
int[] stripLen = { 4, 4, 4, 4, 4, 4 };
// the VertexBuffer for our object
VertexBuffer vb = vbuffer = new VertexBuffer();
vb.setPositions(vertArray, 1.0f, null);
vb.setNormals(normArray);
vb.setTexCoords(0, texArray, 1.0f, null);
indexbuffer = new TriangleStripArray( 0, stripLen );
// the image for the texture
image = Image.createImage( "/pic1.png" );
Image2D image2D = new Image2D( Image2D.RGB, image );
Texture2D texture = new Texture2D( image2D );
texture.setFiltering(Texture2D.FILTER_NEAREST,
Texture2D.FILTER_NEAREST);
texture.setWrapping(Texture2D.WRAP_CLAMP,
Texture2D.WRAP_CLAMP);
texture.setBlending(Texture2D.FUNC_MODULATE);
// create the appearance
appearance = new Appearance();
appearance.setTexture(0, texture);
appearance.setMaterial(material);
material.setColor(Material.DIFFUSE, 0xFFFFFFFF);
material.setColor(Material.SPECULAR, 0xFFFFFFFF);
material.setShininess(100.0f);
background.setColor(0xffffcc);
}
protected void paint(Graphics g) {
graphics3d.bindTarget(g, true,
Graphics3D.DITHER |
Graphics3D.TRUE_COLOR);
graphics3d.clear(background);
// Set the camera
Transform transform = new Transform();
transform.postTranslate(0.0f, 0.0f, 30.0f);
graphics3d.setCamera(camera, transform);
// Set light
graphics3d.resetLights();
graphics3d.addLight(light, transform);
// set rotation
angle += 1.0f;
transform.setIdentity();
transform.postRotate(angle, 1.0f, 1.0f, 1.0f);
graphics3d.render(vbuffer, indexbuffer, appearance, transform);
graphics3d.releaseTarget();
}
}
Figure 1 The application running in an emulator




Account Sign In
View your cart