/*
* Sample code for M3G article on IBM developerWorks.
* http://www.ibm.com/developerworks/
*/
package m3gsamples1;
import javax.microedition.lcdui.*;
import javax.microedition.m3g.*;
/**
* Sample demonstrating depth buffer and projection.
*
* @author Claus Hoefele
*/
public class DepthBufferProjectionSample extends Canvas
implements Sample
{
/** The cube"s vertex positions (x, y, z). */
private static final byte[] VERTEX_POSITIONS = {
-1, -1, 1, 1, -1, 1, -1, 1, 1, 1, 1, 1,
-1, -1, -1, 1, -1, -1, -1, 1, -1, 1, 1, -1
};
/** Indices that define how to connect the vertices to build
* triangles. */
private static int[] TRIANGLE_INDICES = {
0, 1, 2, 3, 7, 1, 5, 4, 7, 6, 2, 4, 0, 1
};
/** The cube"s vertex data. */
private VertexBuffer _cubeVertexData;
/** The cube"s triangles defined as triangle strips. */
private TriangleStripArray _cubeTriangles;
/** Graphics singleton used for rendering. */
private Graphics3D _graphics3d;
/** Camera with perspective projection. */
private Camera _cameraPerspective;
/** The camera"s transformation. */
private Transform _cameraTransform;
/** Camera with parallel projection. */
private Camera _cameraParallel;
/** Flag whether perspective or parallel projection is used. */
private boolean _isPerspective;
/** Flag whether depth buffer is enabled. */
private boolean _isDepthBufferEnabled;
/**
* Called when this sample is displayed.
*/
public void showNotify()
{
init();
}
/**
* Initializes the sample.
*/
protected void init()
{
// Get the singleton for 3D rendering.
_graphics3d = Graphics3D.getInstance();
// Create vertex data.
_cubeVertexData = new VertexBuffer();
VertexArray vertexPositions =
new VertexArray(VERTEX_POSITIONS.length/3, 3, 1);
vertexPositions.set(0, VERTEX_POSITIONS.length/3, VERTEX_POSITIONS);
_cubeVertexData.setPositions(vertexPositions, 1.0f, null);
// Create the triangles that define the cube; the indices point to
// vertices in VERTEX_POSITIONS.
_cubeTriangles = new TriangleStripArray(TRIANGLE_INDICES,
new int[] {TRIANGLE_INDICES.length});
// Create parallel and perspective cameras.
_cameraPerspective = new Camera();
float aspect = (float) getWidth() / (float) getHeight();
_cameraPerspective.setPerspective(30.0f, aspect, 1.0f, 1000.0f);
_cameraTransform = new Transform();
_cameraTransform.postTranslate(0.0f, 0.0f, 10.0f);
_cameraParallel = new Camera();
_cameraParallel.setParallel(5.0f, aspect, 1.0f, 1000.0f);
_graphics3d.setCamera(_cameraPerspective, _cameraTransform);
_isPerspective = true;
// Enable depth buffer.
_isDepthBufferEnabled = true;
}
/**
* Renders the sample on the screen.
*
* @param graphics the graphics object to draw on.
*/
protected void paint(Graphics graphics)
{
// Create transformation objects for the cubes.
Transform origin = new Transform();
Transform behindOrigin = new Transform(origin);
behindOrigin.postTranslate(-1.0f, 0.0f, -1.0f);
Transform inFrontOfOrigin = new Transform(origin);
inFrontOfOrigin.postTranslate(1.0f, 0.0f, 1.0f);
// Disable or enable depth buffering when target is bound.
_graphics3d.bindTarget(graphics, _isDepthBufferEnabled, 0);
_graphics3d.clear(null);
// Draw cubes front to back. If the depth buffer is enabled,
// they will be drawn according to their z coordinate. Otherwise,
// according to the order of rendering.
_cubeVertexData.setDefaultColor(0x00FF0000);
_graphics3d.render(_cubeVertexData, _cubeTriangles,
new Appearance(), inFrontOfOrigin);
_cubeVertexData.setDefaultColor(0x0000FF00);
_graphics3d.render(_cubeVertexData, _cubeTriangles,
new Appearance(), origin);
_cubeVertexData.setDefaultColor(0x000000FF);
_graphics3d.render(_cubeVertexData, _cubeTriangles,
new Appearance(), behindOrigin);
_graphics3d.releaseTarget();
drawMenu(graphics);
}
/**
* Draws a menu on the screen.
*
* @param graphics graphics context.
*/
protected void drawMenu(Graphics graphics)
{
graphics.setColor(0xFFFFFFFF);
int fontHeight = graphics.getFont().getHeight();
// Upper half menu.
int height = 0;
graphics.drawString(getKeyName(getKeyCode(FIRE)) + ": Reset",
0, height, 0);
// Lower half menu.
height = getHeight() - fontHeight;
if (_isDepthBufferEnabled)
{
graphics.drawString(getKeyName(getKeyCode(GAME_B)) +
": Depth Buffer: on", 0, height, 0);
}
else
{
graphics.drawString(getKeyName(getKeyCode(GAME_B)) +
": Depth Buffer: off", 0, height, 0);
}
height -= fontHeight;
if (_isPerspective)
{
graphics.drawString(getKeyName(getKeyCode(GAME_A)) +
": Projection: perspective", 0, height, 0);
}
else
{
graphics.drawString(getKeyName(getKeyCode(GAME_A)) +
": Projection: parallel", 0, height, 0);
}
}
/**
* Handles key presses.
*
* @param keyCode key code.
*/
protected void keyPressed(int keyCode)
{
switch (getGameAction(keyCode))
{
case GAME_A:
_isPerspective = !_isPerspective;
if (_isPerspective)
{
_graphics3d.setCamera(_cameraPerspective, _cameraTransform);
}
else
{
_graphics3d.setCamera(_cameraParallel, _cameraTransform);
}
break;
case GAME_B:
_isDepthBufferEnabled = !_isDepthBufferEnabled;
break;
case FIRE:
init();
break;
// no default
}
repaint();
}
/**
* Returns the <code>Displayable</code> used to display this sample.
*
* @return display
*/
public Displayable getDisplayable()
{
return this;
}
/**
* Returns the display name of this sample.
*
* @return name
*/
public String getName()
{
return "Depth Buffer and View Projection";
}
}
|