3D Graphics in J2ME
An Introduction |
Prof. David Bernstein |
Computer Science Department |
bernstdh@jmu.edu |
Graphics3D
class has a
getInstance()
method that returns the
singleton Graphics3D
object
render()
method renders a
VertexBuffer
containing a shape
setCamera()
method is used to set
the position of the viewer
setLight()
method is used to
bind/unbind lights
VertexArray
:
VertexArray
contains positions, colors,
normals, or texture coordinates for vertices
VertexBuffer
:
VertexBuffer
holds references
to the VertexArray
objects (one of each "type")
needed to define a shape
Transform
:
Camera
:
Material
:
Texture2D
:
Appearance
:
Material
object, Texture2D
object, etc...
Light
:
package java3d; import javax.microedition.lcdui.*; import javax.microedition.m3g.*; import drivers.*; /** * A simple example of immediate mode rendering using the * Mobile 3D Graphics API for J2ME * * @author Prof. David Bernstein, James Madison University * @version 1.0 */ public class CubeCanvas extends Canvas implements AnimatorObserver { private Appearance appearance; private Background background; private float angle; private Graphics3D g3; private IndexBuffer indexBuffer; private Transform rotation; private VertexBuffer cube; // The vertices for the cube using a triangle strip that is organized // as follows: // // 1 0 // o-------o // | \ | // | \ | // | \ | // o-------o // 3 2 // private static short[] vertices = { 1, 1, 1, -1, 1, 1, 1,-1, 1, -1,-1, 1, // Front -1, 1,-1, 1, 1,-1, -1,-1,-1, 1,-1,-1, // Back -1, 1, 1, -1, 1,-1, -1,-1, 1, -1,-1,-1, // Left 1, 1,-1, 1, 1, 1, 1,-1,-1, 1,-1, 1, // Right 1, 1,-1, -1, 1,-1, 1, 1, 1, -1, 1, 1, // Top 1,-1, 1, -1,-1, 1, 1,-1,-1, -1,-1,-1 // Bottom }; private static int[] stripLengths = { 4, 4, 4, 4, 4, 4 }; // The normals private static byte[] normals = { 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, // Front 0, 0,-1, 0, 0,-1, 0, 0,-1, 0, 0,-1, // Back -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, // Left 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, // Right 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, // Top 0,-1, 0, 0,-1, 0, 0,-1, 0, 0,-1, 0 // Bottom }; /** * Default Constructor */ public CubeCanvas() { // Add the Exit command to the menu addCommand(new Command("Exit", Command.EXIT, 1)); // Initalize the rendering engine init(); // Initialize the cube createCube(); } /** * Handle a "tick" from the Animator */ public void animate() { repaint(); } /** * Create a cube */ private void createCube() { Material material; VertexArray normalArray, vertexArray; // Create a VertexArray for the vertices vertexArray = new VertexArray(vertices.length/3, 3, 2); vertexArray.set(0, vertices.length/3, vertices); // Create a VertexArray for the normals normalArray = new VertexArray(normals.length/3, 3, 1); normalArray.set(0, normals.length/3, normals); // Create the VertexBuffer for the cube cube = new VertexBuffer(); cube.setPositions(vertexArray, 1.0f, null); cube.setNormals(normalArray); // Create the IndexBuffer for the cube indexBuffer = new TriangleStripArray( 0, stripLengths ); // Create the Material for the cube material = new Material(); material.setColor(Material.DIFFUSE, 0xC2A14D); // JMU Gold material.setColor(Material.SPECULAR, 0xFFFFFFFF); // White material.setShininess(100.0f); // Create the Appearance for the cube appearance = new Appearance(); appearance.setMaterial(material); } /** * Initialize the rendering engine */ private void init() { Camera camera; float aspect; Light light; Transform cameraTranslation; angle = 0.0f; // Create the Background background = new Background(); background.setColor(0x450084); // JMU Purple // Create the rotational transform rotation = new Transform(); // get the singleton Graphics3D instance g3 = Graphics3D.getInstance(); // Create the Camera aspect = (float)getWidth()/ (float)getHeight(); camera = new Camera(); camera.setPerspective(60.0f, // Field of View (Vertical) aspect, // Aspect Ratio 1.0f, // Near Clipping Plane 1000.0f ); // Far Clipping Plane // Move the camera cameraTranslation = new Transform(); cameraTranslation.postTranslate(0.0f, 0.0f, 3.0f); g3.setCamera(camera, cameraTranslation); // Create a light at the camera position g3.resetLights(); light = new Light(); light.setColor(0xFFFFFF); light.setIntensity(1.0f); g3.addLight(light, cameraTranslation); } /** * Render this component * * @param g The underlying rendering engine */ protected void paint(Graphics g) { // Bind the Graphics object to the Graphics3D object g3.bindTarget(g, true, Graphics3D.DITHER |Graphics3D.TRUE_COLOR); // Clear the pixel and depth buffers g3.clear(background); // Rotate the cube angle += 1.0f; rotation.setIdentity(); rotation.postRotate(angle, 1.0f, 0.0f, 0.0f); // Rotate around the x-axis // Render the cube g3.render(cube, indexBuffer, appearance, rotation); // Flush the rendering engine g3.releaseTarget(); } }
MIDlet
package drivers; import java.util.*; import javax.microedition.midlet.*; import javax.microedition.lcdui.*; import java3d.*; /** * A simple example of immediate mode rendering using the * Mobile 3D Graphics API for J2ME * * @author Prof. David Bernstein, James Madison University * @version 1.0 */ public class CubeDriver extends MIDlet implements CommandListener { Animator animator; CubeCanvas canvas; Timer timer; /** * Default Constructor */ public CubeDriver() { // Construct the Displayable canvas = new CubeCanvas(); canvas.setCommandListener(this); // Construct the Timer timer = new Timer(); // Construct the Timer "callback" animator = new Animator(canvas); } /** * Handle commandAction events * (required by CommandListener) * * @param c The Command * @param d The Displayable that generated the event */ public void commandAction(Command c, Displayable d) { if (c.getCommandType() == Command.EXIT) { destroyApp(true); } } /** * Destroy this MIDlet */ public void destroyApp(boolean unconditional) { } /** * Entry point */ public void startApp() { Display.getDisplay(this).setCurrent(canvas); timer.schedule(animator, 0, 40 ); } /** * Pause this MIDlet */ public void pauseApp() { } }
World
class
Group
class
AnimationController
AnimationTrack
KeyframeSequence