IBM®
跳转到主要内容
    中国 [选择]    使用条款
 
 
Select a scope: Search for:    
    首页    产品    服务与解决方案     支持与下载    个性化服务    
跳转到主要内容

developerWorks 中国  >  Java technology | Open source  >

针对 Java 移动设备的 3D 图形,第 1 部分: M3G 的快速模式

使用 JSR 184 创建 3D 场景

developerWorks


返回文章


/*
 * Sample code for M3G article on IBM developerWorks.
 * http://www.ibm.com/developerworks/
 */
package m3gsamples1;
import javax.microedition.lcdui.*;
import javax.microedition.m3g.*;
/**
 * Sample displaying a lit cube with material properties.
 *
 * @author Claus Hoefele
 */
public class LightingMaterialsSample 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, // 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, // right
    -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, // top
    -1, -1, -1,    1, -1, -1,   -1, -1,  1,    1, -1,  1  // bottom
  };
  /** The cube"s normals. */
  private static final byte[] VERTEX_NORMALS = {
    0, 0,  127,   0, 0,  127,   0, 0,  127,   0, 0,  127, // front
    0, 0, -128,   0, 0, -128,   0, 0, -128,   0, 0, -128, // back
     127, 0, 0,    127, 0, 0,    127, 0, 0,    127, 0, 0, // right
    -128, 0, 0,   -128, 0, 0,   -128, 0, 0,   -128, 0, 0, // left
    0,  127, 0,   0,  127, 0,   0,  127, 0,   0,  127, 0, // top
    0, -128, 0,   0, -128, 0,   0, -128, 0,   0, -128, 0, // bottom
  };
  /** Indices that define how to connect the vertices to build 
   * triangles. */
  private static final int[] TRIANGLE_INDICES = {
     0,  1,  2,  3,   // front
     4,  5,  6,  7,   // back
     8,  9, 10, 11,   // right
    12, 13, 14, 15,   // left
    16, 17, 18, 19,   // top
    20, 21, 22, 23,   // bottom
  };
  /** Lengths of triangle strips in TRIANGLE_INDICES. */
  private static int[] TRIANGLE_LENGTHS = {
    4, 4, 4, 4, 4, 4
  };
  /** The cube"s vertex data. */
  private VertexBuffer _cubeVertexData;
  /** The cube"s triangles defined as triangle strips. */
  private TriangleStripArray _cubeTriangles;
  /** The cube"s transformation. */
  private Transform _cubeTransform;
  /** The cube"s appearance. */
  private Appearance _cubeAppearance;
  /** Light for the scene. */
  private Light _light;
  /** Graphics singleton used for rendering. */
  private Graphics3D _graphics3d;
  /** Light mode ambient (0). */
  private static final int LIGHT_AMBIENT      = 0;
  /** Light mode directional (1). */
  private static final int LIGHT_DIRECTIONAL  = 1;
  /** Light mode omni (2). */
  private static final int LIGHT_OMNI         = 2;
  /** Light mode spot (3). */
  private static final int LIGHT_SPOT         = 3;
  /** Current light mode. */
  private int _lightMode;
  /** Color target default (0). */
  private static final int COLOR_DEFAULT      = 0;
  /** Color target ambient (1). */
  private static final int COLOR_AMBIENT      = 1;
  /** Color target diffuse (2). */
  private static final int COLOR_DIFFUSE      = 2;
  /** Color target emissive (3). */
  private static final int COLOR_EMISSIVE     = 3;
  /** Color target specular (4). */
  private static final int COLOR_SPECULAR     = 4;
  /** Current color target. */
  private int _colorTarget;
  /**
   * 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);
    VertexArray vertexNormals =
        new VertexArray(VERTEX_NORMALS.length/3, 3, 1);
    vertexNormals.set(0, VERTEX_NORMALS.length/3, VERTEX_NORMALS);
    _cubeVertexData.setNormals(vertexNormals);
    // Create the triangles that define the cube; the indices point to
    // vertices in VERTEX_POSITIONS.
    _cubeTriangles = new TriangleStripArray(TRIANGLE_INDICES,
        TRIANGLE_LENGTHS);
    // Create a camera with perspective projection.
    Camera camera = new Camera();
    float aspect = (float) getWidth() / (float) getHeight();
    camera.setPerspective(30.0f, aspect, 1.0f, 1000.0f);
    Transform cameraTransform = new Transform();
    cameraTransform.postTranslate(0.0f, 0.0f, 10.0f);
    _graphics3d.setCamera(camera, cameraTransform);
    // Rotate the cube so we can see 3 sides.
    _cubeTransform = new Transform();
    _cubeTransform.postRotate(45.0f, 1.0f, 0.0f, 0.0f);
    _cubeTransform.postRotate(45.0f, 0.0f, 1.0f, 0.0f);
    // Create appearance and the material.
    _cubeAppearance = new Appearance();
    _colorTarget = COLOR_DEFAULT;
    setMaterial(_cubeAppearance, _colorTarget);
    // Create light.
    _light = new Light();
    _lightMode = LIGHT_OMNI;
    setLightMode(_light, _lightMode);
    Transform lightTransform = new Transform();
    lightTransform.postTranslate(0.0f, 0.0f, 3.0f);
    _graphics3d.resetLights();
    _graphics3d.addLight(_light, lightTransform);
  }
  /**
   * Sets the light mode.
   *
   * @param light light to be modified.
   * @param mode light mode.
   */
  protected void setLightMode(Light light, int mode)
  {
    switch (mode)
    {
      case LIGHT_AMBIENT:
        light.setMode(Light.AMBIENT);
        light.setIntensity(2.0f);
        break;
      case LIGHT_DIRECTIONAL:
        light.setMode(Light.DIRECTIONAL);
        light.setIntensity(1.0f);
        break;
      case LIGHT_OMNI:
        light.setMode(Light.OMNI);
        light.setIntensity(2.0f);
        break;
      case LIGHT_SPOT:
        light.setMode(Light.SPOT);
        light.setSpotAngle(20.0f);
        light.setIntensity(2.0f);
        break;
      // no default
    }
  }
  /**
   * Sets the material according to the given target.
   *
   * @param appearance appearance to be modified.
   * @param colorTarget target color.
   */
  protected void setMaterial(Appearance appearance, int colorTarget)
  {
    Material material = new Material();
    switch (colorTarget)
    {
      case COLOR_DEFAULT:
        break;
      case COLOR_AMBIENT:
        material.setColor(Material.AMBIENT, 0x00FF0000);
        break;
      case COLOR_DIFFUSE:
        material.setColor(Material.DIFFUSE, 0x00FF0000);
        break;
      case COLOR_EMISSIVE:
        material.setColor(Material.EMISSIVE, 0x00FF0000);
        break;
      case COLOR_SPECULAR:
        material.setColor(Material.SPECULAR, 0x00FF0000);
        material.setShininess(2);
        break;
      // no default
    }
    appearance.setMaterial(material);
  }
  /**
   * Renders the sample on the screen.
   *
   * @param graphics the graphics object to draw on.
   */
  protected void paint(Graphics graphics)
  {
    _graphics3d.bindTarget(graphics);
    _graphics3d.clear(null);
    _graphics3d.render(_cubeVertexData, _cubeTriangles,
        _cubeAppearance, _cubeTransform);
    _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);
    height += fontHeight;
    graphics.drawString(
        getKeyName(getKeyCode(LEFT)) + "/" +
        getKeyName(getKeyCode(RIGHT)) + ": Rotate y ", 0, height, 0);
    // Lower half menu.
    height = getHeight() - fontHeight;
    switch (_light.getMode())
    {
      case Light.AMBIENT:
        graphics.drawString(getKeyName(getKeyCode(GAME_B)) +
            ": Light: ambient", 0, height, 0);
        break;
      case Light.DIRECTIONAL:
        graphics.drawString(getKeyName(getKeyCode(GAME_B)) +
            ": Light: directional", 0, height, 0);
        break;
      case Light.OMNI:
        graphics.drawString(getKeyName(getKeyCode(GAME_B)) +
            ": Light: omni", 0, height, 0);
        break;
      case Light.SPOT:
        graphics.drawString(getKeyName(getKeyCode(GAME_B)) +
            ": Light: spot", 0, height, 0);
        break;
      // no default
    }
    height -= fontHeight;
    switch (_colorTarget)
    {
      case COLOR_AMBIENT:
        graphics.drawString(getKeyName(getKeyCode(GAME_A)) +
            ": Color: ambient", 0, height, 0);
        break;
      case COLOR_DEFAULT:
        graphics.drawString(getKeyName(getKeyCode(GAME_A)) +
            ": Color: default", 0, height, 0);
        break;
      case COLOR_DIFFUSE:
        graphics.drawString(getKeyName(getKeyCode(GAME_A)) +
            ": Color: diffuse", 0, height, 0);
        break;
      case COLOR_EMISSIVE:
        graphics.drawString(getKeyName(getKeyCode(GAME_A)) +
            ": Color: emissive", 0, height, 0);
        break;
      case COLOR_SPECULAR:
        graphics.drawString(getKeyName(getKeyCode(GAME_A)) +
            ": Color: specular", 0, height, 0);
        break;
      // no default
    }
  }
  /**
   * Handles key presses.
   *
   * @param keyCode key code.
   */
  protected void keyPressed(int keyCode)
  {
    switch (getGameAction(keyCode))
    {
      case LEFT:
        _cubeTransform.postRotate(-10.0f, 0.0f, 1.0f, 0.0f);
        break;
      case RIGHT:
        _cubeTransform.postRotate(10.0f, 0.0f, 1.0f, 0.0f);
        break;
      case FIRE:
        init();
        break;
      case GAME_A:
        _colorTarget++;
        _colorTarget %= 5;
        setMaterial(_cubeAppearance, _colorTarget);
        break;
      case GAME_B:
        _lightMode++;
        _lightMode %= 4;
        setLightMode(_light, _lightMode);
        break;
      // no default
    }
    repaint();
  }
  /**
   * 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);
  }
  /**
   * 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 "Lighting and Materials";
  }
}

返回文章


    关于 IBM 隐私条约 联系 IBM 使用条款