⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 context3d.java

📁 --- --- --- 基于J2ME的游戏程序--------很有技巧性的程序
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
// Copyright (c) 2005 Sony Ericsson Mobile Communications AB
//
// This software is provided "AS IS," without a warranty of any kind. 
// ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, 
// INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A 
// PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. 
//
// THIS SOFTWARE IS COMPLEMENTARY OF JAYWAY AB (www.jayway.se)

package bluegammon.gui;

import javax.microedition.lcdui.Graphics;
import javax.microedition.lcdui.Image;
import javax.microedition.m3g.Appearance;
import javax.microedition.m3g.Camera;
import javax.microedition.m3g.Graphics3D;
import javax.microedition.m3g.Image2D;
import javax.microedition.m3g.IndexBuffer;
import javax.microedition.m3g.Light;
import javax.microedition.m3g.Material;
import javax.microedition.m3g.Texture2D;
import javax.microedition.m3g.Transform;
import javax.microedition.m3g.TriangleStripArray;
import javax.microedition.m3g.VertexArray;
import javax.microedition.m3g.VertexBuffer;

import bluegammon.Resources;


/**
 * <p>The 3d context used in this game. Consists of the scene which is
 * a camera with one main headlight; and dice, string or piece objects.
 * Also contains functionality for creating objects and defining materials.
 * We only have one 3d context, thus the singleton pattern.</p>
 * <p>
 * <p>
 * The dice and the piece is constructed mathematically based on the
 * JSR184 specifications.
 * </p>
 * <p>
 * The piece is constructed from a number of predefined pie-slices. The greater amount
 * of slices, the more circular piece - but also the amount of triangles per piece will increase,
 * impacting the performance. Each piece consists of 4 * numberOfSlices triangles.
 * </p>
 * <br><br>
 * <img border="0" align="center" src="Slice3d.png"/><br><br>
 * <p>
 * The dice is calculated using a somewhat more complicated model. Each dice consists of
 * 6 * 6 faces + 8 corners = 44 triangles.</p>
 * <p>
 * A graphical representation of how one face of the dice is calculated is depicted below:<br><br>
 * <img border="0" align="center" src="Dice3d.png"/><br><br>
 * </p> 
 * 
 * @author Peter Andersson
 */
public class Context3D
{
  /** Field of view, degrees on horizontal axis */
  public static final float FOVY = 35f;
  /** Z-axis near clipping plane */
  public static final float NEAR_CLIPPING_PLANE = 1f;
  /** Z-axis far clipping plane */
  public static final float FAR_CLIPPING_PLANE = 512f;
  
  /** The camera of the scene */
  protected Camera m_camera;
  /** The position and direction of the camera */
  protected Transform m_cameraTransform;
  
  /** The light of the scene */
  protected Light m_light;
  /** The position and direction of the light*/
  protected Transform m_lightTransform;
  
  /** Appearence cahce */
  protected Appearance[] m_appearances = new Appearance[2];
  
  /** Texture cache */
  protected Texture2D[] m_textures = new Texture2D[2];
  
  /** Dice vertex buffer cache */
  protected VertexBuffer m_diceVertBuffer;
  /** Dice index buffer cache */
  protected IndexBuffer m_diceIndexBuffer;
  
  /** Piece vertex buffer cache */
  protected VertexBuffer m_pieceVertBuffer;
  /** Piece index buffer cache */
  protected IndexBuffer m_pieceIndexBuffer;
  
  /** Quick and dirty screen to 3d coordinate transformation factor */
  protected double m_scr2ThreeD;
  /** Quick and dirty 3d to screen coordinate transformation factor */
  protected double m_threeD2Scr;
  
  /** Width of screen */
  protected int m_width;
  /** Height of screen */
  protected int m_height;
  /** Half width of screen */
  protected int m_halfWidth;
  /** Half height of screen */
  protected int m_halfHeight;

  /** Singleton instance */
  protected static Context3D m_inst = null;
  
  /** Light source rotation around Y axis */
  protected static final float LIGHT_ROT = 33f;
  /** Tangens for light source rotation */
  protected static final double TAN_LIGHT_ROT = Math.tan(Math.toRadians(LIGHT_ROT));
  /** Number of slices in a piece */
  protected static final int PIECE_SLICES = 10;
  /** Unity value in 3D coordinates */
  protected static final short UNITY = Short.MAX_VALUE / 8;
  
  /**
   * Returns singleton instance.
   * @return The singleton instance.
   */
  public static Context3D getInstance()
  {
    if (m_inst == null)
    {
      m_inst = new Context3D();
    }
    return m_inst;
  }
  
  /**
   * Sets up our viewport, camera, lighting - everyting needed for the scene
   * @param width	The width of the viewport
   * @param height	The height of the viewport
   */
  public void init(int width, int height)
  {
    m_width = width;
    m_height = height;
    m_halfWidth = width / 2 - 1;
    m_halfHeight = height / 2 - 1;
    // create a camera
    m_camera = new Camera();
    m_camera.setPerspective(
      FOVY, 						// field of view
      (float)width / (float)height, // aspectRatio
      NEAR_CLIPPING_PLANE,
      FAR_CLIPPING_PLANE);

    // camera transform matrix
    m_cameraTransform = new Transform();
    m_cameraTransform.setIdentity();
    m_cameraTransform.postTranslate(0f, 0f, 1f);
    
    // create a light
    m_light = new Light();
    m_light.setColor(0xffffff);
    m_light.setIntensity(1.1f);
    m_light.setMode(Light.DIRECTIONAL);
    
    // ligth transform matrix - shine from near right to far left
    m_lightTransform = new Transform();
    m_lightTransform.setIdentity();
    m_lightTransform.postTranslate(0f, 0f, 10f);
    m_lightTransform.postRotate(LIGHT_ROT, 0f, 1f, 0f);
    
    // transformation factors
    double factor = 2.15;	// Magic 3d factor, works for K750 when calculating
    						// 2d-3d and 3d-2d coordinate transformations.
    						// This factor might need to be altered on bigger screens.
    double tanFovY = Math.tan(Math.toRadians(FOVY));
    m_threeD2Scr = factor * (double)height / (2d * tanFovY);
    m_scr2ThreeD = 2d * tanFovY / (factor * (double)height);
  }
  
  /**
   * Recalculates a x 3d coordinate to a screen x coordinate.
   * @param coordinate3D	The 3d x coordinate
   * @param z				The depth of the 3d coordinate
   * @return				The screen coordinate
   */
  public float toScreenCoordinateX(float coordinate3D, float z)
  {
    return (float)(-coordinate3D * m_threeD2Scr / z);
  }
  
  /**
   * Recalculates a screen x coordinate to a 3d x coordinate.
   * @param coordinateScreen	The screen x coordinate
   * @param z				    The depth of the 3d coordinate
   * @return				    The 3d x coordinate
   */
  public float to3DCoordinateX(float coordinateScreen, float z)
  {
    return (float)((-coordinateScreen + m_halfWidth) * m_scr2ThreeD * z);
  }
  
  /**
   * Recalculates a 3d y coordinate to a screen y coordinate.
   * @param coordinate3D	The 3d y coordinate
   * @param z				The depth of the 3d coordinate
   * @return				The screen y coordinate
   */
  public float toScreenCoordinateY(float coordinate3D, float z)
  {
    return (float)(coordinate3D * m_threeD2Scr / z);
  }
  
  /**
   * Recalculates a screen y coordinate to a 3d y coordinate.
   * @param coordinateScreen	The screen y coordinate
   * @param z				    The depth of the 3d coordinate
   * @return			     	The 3d y coordinate
   */
  public float to3DCoordinateY(float coordinateScreen, float z)
  {
    return (float)((coordinateScreen - m_halfHeight) * m_scr2ThreeD * z);
  }
  
  /**
   * Returns delta x coordinate of shadow position given
   * specified delta z between object and projection plane.
   * @param deltaZ	The difference in z between object
   * 				and shadow projecton plane.
   * @return	Delta x coordinate in 3d units.
   */
  public float getShadowProjectionDeltaX(float deltaZ)
  {
    if (deltaZ == 0)
    {
      return 0;
    }
    else
    {
      return (float)(Math.abs(deltaZ) * TAN_LIGHT_ROT);
    }
  }
  
  /**
   * Binds a graphics context and set up the common 
   * 3d environment used in this game.
   * 
   * @param g	The graphics environment to render upon.
   * @return	A Graphics3D object with common 3d environment settings.
   */
  public Graphics3D bindScene(Graphics g)
  {
    Graphics3D g3d = Graphics3D.getInstance();
    // Use dithering and true-color, no z-buffering
    g3d.bindTarget(g, false, Graphics3D.DITHER | Graphics3D.TRUE_COLOR);
    g3d.setCamera(m_camera, m_cameraTransform);

    g3d.resetLights();
    g3d.addLight(m_light, m_lightTransform);
    
    return g3d;
  }
  
  /**
   * Creates an rgb buffer rendered a shadow that is transparant.
   * 
   * @param size Shadow size
   * @param sizeDim  Blank border.
   * @return An rgb buffer containing a transparant shadow
   */
  public static int[] createShadowRGB(int size, int sizeDim)
  {
    int[] shadow = new int[size * size];
    Image shadowImg = Image.createImage(size, size);
    Graphics g = shadowImg.getGraphics();
    g.setColor(0xff0000);
    g.fillRect(0, 0, size * 2, size * 2);
    for (int i = 0; i < 4; i++)
    {
      g.setColor((i + 1) << 4);
      g.fillArc(i + sizeDim, i + sizeDim,
          	 size - 2 * (i + sizeDim),
          	 size - 2 * (i + sizeDim),
          	 0, 360);
    }
    shadowImg.getRGB(shadow, 0, size,
        0, 0, size, size);
    for (int i = 0; i < shadow.length; i++)
    {
      if ((shadow[i] & 0x00ffffff) == 0xff0000)
      {
        shadow[i] = 0x00000000; //  totally transparant
      }
      else
      {
        // calculate semitransparancy depending on shadow color
        int trans = ((shadow[i] & 0x000000ff) << 56) & 0xff000000;
        shadow[i] = trans;
      }
    }
    return shadow;
  }
  
  /**
   * Returns the appearance (texture and material) for a piece.
   * @param white true for white appearance, false for black appearance.
   * @return	The piece appearance.
   */
  public Appearance getPieceAppearance(boolean white)
  {
    return getDiceAppearance(white);	// Pieces and dices are of the same material
  }
  
  /**
   * Returns the appearance (texture and material) for a dice.
   * @param white true for white appearance, false for black appearance.
   * @return	The dice appearance.
   */
  public Appearance getDiceAppearance(boolean white)
  {
    int index = white ? 0:1;
    if (m_appearances[index] == null)
    {
      Material material = new Material();
      material.setColor(Material.AMBIENT, 0x606060);
      material.setColor(Material.DIFFUSE, 0xf0e8e0);
      material.setColor(Material.SPECULAR, 0xffffff);
      material.setShininess(50.0f);
      m_appearances[index] = new Appearance();
      m_appearances[index].setTexture(0, getTexture(white));
      m_appearances[index].setMaterial(material);
    }
    return m_appearances[index];
  }
  
  /**
   * Returns the textures used within this game.
   * @param white true for white textures, false for black textures.
   * @return the texture.
   */
  public Texture2D getTexture(boolean white)
  {
    int index = white ? 0:1;
    if (m_textures[index] == null)
    {
      Image2D image2D = null;
      if (white)
      {
        image2D = new Image2D(Image2D.RGB, Resources.getImage(Resources.IMG_WHITE_TEXTURES));
      }
      else
      {
        image2D = new Image2D(Image2D.RGB, Resources.getImage(Resources.IMG_BLACK_TEXTURES));
      }

      // create the Texture2D and enable mipmapping
      // texture color is to be modulated with the lit material color
      m_textures[index] = new Texture2D(image2D);
      m_textures[index].setFiltering(Texture2D.FILTER_LINEAR, Texture2D.FILTER_LINEAR);
      m_textures[index].setWrapping(Texture2D.WRAP_CLAMP, Texture2D.WRAP_CLAMP);
      m_textures[index].setBlending(Texture2D.FUNC_MODULATE);
    }
    return m_textures[index];
  }
  
  /**
   * Returns vertexbuffer for a piece.
   * @return a piece vertex buffer
   */
  public VertexBuffer getPieceVertexBuffer()
  {
    if (m_pieceVertBuffer == null)
    {
      calculatePieceBuffers();
    }
    return m_pieceVertBuffer;
  }
  
  /**
   * Returns indexbuffer for a piece.
   * @return a piece index buffer
   */
  public IndexBuffer getPieceIndexBuffer()
  {
    if (m_pieceIndexBuffer == null)
    {
      calculatePieceBuffers();
    }
    return m_pieceIndexBuffer;
  }
  
  /**
   * Returns vertexbuffer for a dice.
   * @return a dice vertex buffer
   */
  public VertexBuffer getDiceVertexBuffer()
  {
    if (m_diceVertBuffer == null)
    {
      calculateDiceBuffers();
    }
    return m_diceVertBuffer;
  }
  
  /**
   * Returns index buffer for a dice.
   * @return a dice index buffer
   */
  public IndexBuffer getDiceIndexBuffer()
  {
    if (m_diceIndexBuffer == null)
    {
      calculateDiceBuffers();
    }
    return m_diceIndexBuffer;
  }
  
  /**
   * Calculates piece vertex- and indexbuffers.
   */
  protected void calculatePieceBuffers()
  {
    int slices = PIECE_SLICES;
    short I = UNITY;			// Unit value
    short H = (short)(I / 8);	// Heigth of piece is 2*diameter/8

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -