/*
* Sample code for M3G article on IBM developerWorks.
* http://www.ibm.com/developerworks/
*/
package m3gsamples2;
import javax.microedition.lcdui.*;
import javax.microedition.m3g.*;
/**
* Alignment of nodes and picking.
*
* @author Claus Hoefele
*/
public class AlignmentPickingSample extends Canvas implements Sample
{
/** Name of the M3G file. */
private static final String M3G_FILE_NAME = "/blender.m3g";
/** User ID to identify the text mesh (1).*/
private static final int USER_ID_TEXT = 1;
/** Crosshair image file name (off).*/
private static String CROSS_HAIR_OFF = "/crosshair_off.png";
/** Crosshair image file name (on).*/
private static String CROSS_HAIR_ON = "/crosshair_on.png";
/** State of crosshair.*/
private boolean _crossHairOn;
/** Image object for crosshair (on).*/
private Image _crossHairImageOn;
/** Image object for crosshair (off).*/
private Image _crossHairImageOff;
/** Object that represents the 3D world. */
private World _world;
/** Graphics singleton used for rendering. */
private Graphics3D _graphics3d;
/**
* 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();
try
{
// Load World from M3G binary file.
Object3D[] objects = Loader.load(M3G_FILE_NAME);
_world = (World) objects[0];
// Change the camera's properties to match the current device.
Camera camera = _world.getActiveCamera();
float aspect = (float) getWidth() / (float) getHeight();
camera.setPerspective(60.0f, aspect, 1.0f, 1000.0f);
// Align the text with the camera.
Mesh text = (Mesh) _world.find(USER_ID_TEXT);
text.setAlignment(camera, Node.Y_AXIS, null, Node.NONE);
text.align(null);
// Load crosshair images.
try
{
_crossHairImageOn = Image.createImage(CROSS_HAIR_ON);
_crossHairImageOff = Image.createImage(CROSS_HAIR_OFF);
}
catch (Exception e) {}
}
catch (Exception e)
{
e.printStackTrace();
}
}
/**
* Renders the sample on the screen.
*
* @param graphics the graphics object to draw on.
*/
protected void paint(Graphics graphics)
{
_graphics3d.bindTarget(graphics);
_graphics3d.render(_world);
_graphics3d.releaseTarget();
// Draw crosshair.
if ((_crossHairImageOff != null) && (_crossHairImageOn != null))
{
graphics.drawImage(_crossHairOn ? _crossHairImageOn : _crossHairImageOff,
getWidth()/2, getHeight()/2, Graphics.VCENTER | Graphics.HCENTER);
}
drawMenu(graphics);
}
/**
* Draws a menu on the screen.
*
* @param graphics graphics context.
*/
private void drawMenu(Graphics graphics)
{
graphics.setColor(0xFFFFFFFF);
int fontHeight = graphics.getFont().getHeight();
int height = getHeight() - fontHeight;
graphics.drawString(getKeyName(getKeyCode(LEFT)) + ": Rotate left", 0,
height, 0);
height -= fontHeight;
graphics.drawString(getKeyName(getKeyCode(RIGHT)) + ": Rotate right", 0,
height, 0);
height -= fontHeight;
graphics.drawString(getKeyName(getKeyCode(FIRE)) + ": Reset", 0,
height, 0);
}
/**
* Handles key repeat events for phones that support them. Redirects
* all key input to <code>keyPressed()</code>.
*
* @param keyCode key code.
*/
protected void keyRepeated(int keyCode)
{
keyPressed(keyCode);
}
/**
* Handles key presses.
*
* @param keyCode key code.
*/
protected void keyPressed(int keyCode)
{
Mesh text = (Mesh) _world.find(USER_ID_TEXT);
switch (getGameAction(keyCode))
{
case LEFT:
text.postRotate(2.0f, 0.0f, 0.0f, 1.0f);
break;
case RIGHT:
text.postRotate(-2.0f, 0.0f, 0.0f, 1.0f);
break;
case FIRE:
init();
break;
// no default
}
// Check whether ray cast by crosshair intersects with the text.
_crossHairOn = isHit();
repaint();
}
/**
* Checks whether a ray that orginates in the middle of the viewport and has
* the same direction as the active camera intersects with the text.
*
* @return true if there's an intersection.
*/
private boolean isHit()
{
boolean isHit = false;
RayIntersection rayIntersection = new RayIntersection();
Mesh mesh = (Mesh) _world.find(USER_ID_TEXT);
if (_world.pick(-1, 0.5f, 0.5f, _world.getActiveCamera(), rayIntersection))
{
if (rayIntersection.getIntersected() == mesh)
{
isHit = true;
}
}
return isHit;
}
/**
* 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 "Alignment and Picking";
}
}
|