LightDemoCanvas.java
资源名称:J2ME&Game.rar [点击查看]
上传用户:gyyuli
上传日期:2013-07-09
资源大小:3050k
文件大小:12k
源码类别:
J2ME
开发平台:
Java
- import javax.microedition.lcdui.*;
- import javax.microedition.lcdui.game.*;
- import javax.microedition.m3g.*;
- class LightDemoCanvas extends GameCanvas implements Runnable,CommandListener{
- private Graphics3D g3d; // Graphics object used to render the world.
- private World world; // This world contains the camera and the pyramidMesh.
- private Camera camera; // the camera in the scene
- private Mesh icosahedronMesh; // the icosahedron in the scene
- private Light light;
- private int lightIndex = 0;
- private javax.microedition.midlet.MIDlet midlet;
- private Image SwitchImage = null;
- private final int SCREEN_WIDTH;
- private final int SCREEN_HEIGHT;
- private Command AMBIENT_Cmd = new Command("环境光", Command.SCREEN, 1);
- private Command DIRECTIONAL_Cmd = new Command("镜面光", Command.SCREEN, 1);
- private Command OMNI_Cmd = new Command("漫射光", Command.SCREEN, 1);
- private Command SPOT_Cmd = new Command("散射光", Command.SCREEN, 1);
- private Command EXIT_Cmd = new Command("退出", Command.SCREEN, 1);
- public LightDemoCanvas(javax.microedition.midlet.MIDlet m){
- super(false);
- midlet = m;
- this.addCommand(AMBIENT_Cmd);
- this.addCommand(DIRECTIONAL_Cmd);
- this.addCommand(OMNI_Cmd);
- this.addCommand(SPOT_Cmd);
- this.addCommand(EXIT_Cmd);
- this.setCommandListener(this);
- SCREEN_WIDTH = getWidth();
- SCREEN_HEIGHT = getHeight();
- g3d = Graphics3D.getInstance();
- world = new World();
- camera = new Camera();
- world.addChild(camera); // add the camera to the world.
- light = new Light(); // Create a new light
- light.translate(0.0f, 0.0f, -1.0f); // The light position
- light.setMode(Light.AMBIENT); // Light Mode
- light.setColor(0x000000); // The color of the light 'WHITE'
- light.setSpotExponent(10.0f); // splot light concentration 0 to 128
- world.addChild(light); // Add the light to the world to be rendered.
- // Constructs a perspective projection matrix and sets that as the current projection matrix.
- camera.setPerspective(60.0f, (float)SCREEN_WIDTH / (float)SCREEN_HEIGHT, 0.1f, 50f);
- icosahedronMesh = createIcosahedron(); // create our Icosahedron.
- icosahedronMesh.setTranslation(0.0f, 0.0f, -3.0f); // move the icosahedron 3 units into the screen.
- world.addChild(icosahedronMesh);
- world.setActiveCamera(camera);
- Thread t = new Thread(this);
- t.start();
- }
- /*
- * Change the Light Mode to be used.
- */
- public void nextLight(){
- switch(lightIndex){
- case 0:
- light.setMode(Light.AMBIENT);
- break;
- case 1:
- light.setMode(Light.DIRECTIONAL);
- break;
- case 2:
- light.setMode(Light.OMNI);
- break;
- case 3:
- light.setMode(Light.SPOT);
- break;
- }
- }
- public void draw3D(Graphics g){
- g.setColor(0x0000FF);
- g.fillRect(0, 0, getWidth(), getHeight());
- try{
- g3d.bindTarget(g); // Binds the given Graphics or mutable Image2D as the rendering target of this Graphics3D
- g3d.render(world); // Render the world
- }finally{
- g3d.releaseTarget();
- }
- }
- private void draw2D(Graphics g){
- g.setColor(0xFFFFFF);
- switch(lightIndex){
- case 0:
- g.drawString("环境光(Ambient)", 0, 0, 0);
- break;
- case 1:
- g.drawString("镜面光(Directional)", 0, 0, 0);
- break;
- case 2:
- g.drawString("漫射光(Omni)", 0, 0, 0);
- break;
- case 3:
- g.drawString("散射光(Spot)", 0, 0, 0);
- break;
- }
- }
- public void run() {
- Graphics g = getGraphics();
- while(true){
- icosahedronMesh.postRotate(1.0f, 0.0f, 1.0f, 0.0f);
- light.postRotate(1.0f, 1.0f, 0.0f, 0.0f); //enable this to make the light rotate around it's x-axis
- draw3D(g);
- draw2D(g);
- flushGraphics();
- }
- }
- public void commandAction(Command cmd, Displayable disp) {
- if(cmd == EXIT_Cmd){
- midlet.notifyDestroyed();
- }else if(cmd == AMBIENT_Cmd){
- lightIndex = 0;
- nextLight();
- }else if(cmd == DIRECTIONAL_Cmd){
- lightIndex = 1;
- nextLight();
- }else if(cmd == OMNI_Cmd){
- lightIndex = 2;
- nextLight();
- }else if(cmd == SPOT_Cmd){
- lightIndex = 3;
- nextLight();
- }
- }
- private Mesh createIcosahedron(){
- final short X = 525;
- final short Z = 850;
- short[]ORG_POINTS = new short[] {-X, 0, Z, X, 0, Z, -X, 0, -Z, X, 0, -Z,
- 0, Z, X, 0, Z, -X, 0, -Z, X, 0, -Z, -X,
- Z, X, 0, -Z, X, 0, Z, -X, 0, -Z, -X, 0};
- int []ORG_INDICES = new int[] {0,4, 1, 0,9,4, 9,5,4, 4,5,8, 4,8,1,
- 8,10,1, 8,3,10, 5,3,8, 5,2,3, 2,7,3,
- 7,10,3, 7,6,10, 7,11,6, 11,0,6, 0,1,6,
- 6,1,10, 9,0,11, 9,11,2, 9,2,5, 7,2,11};
- short[]POINTS = new short[72*3];
- int []INDICES = new int[80*3+80];
- for(int i=0; i<36; i++){
- POINTS[i] = ORG_POINTS[i];
- }
- for(int i=0; i<60; i++){
- INDICES[i] = ORG_INDICES[i];
- }
- // Start sub deviding
- // every triangle should become 4 triangles.
- VEK v12, v23, v31;
- int pointIndex = 36;
- int numPoints = 12;
- int indiceIndex = 60;
- for(int i=0; i<60; i+=3){
- VEK v1 = new VEK(POINTS[INDICES[i]*3], POINTS[INDICES[i]*3+1], POINTS[INDICES[i]*3+2]);
- VEK v2 = new VEK(POINTS[INDICES[i+1]*3], POINTS[INDICES[i+1]*3+1], POINTS[INDICES[i+1]*3+2]);
- VEK v3 = new VEK(POINTS[INDICES[i+2]*3], POINTS[INDICES[i+2]*3+1], POINTS[INDICES[i+2]*3+2]);
- v12 = new VEK(v1.X + v2.X, v1.Y + v2.Y, v1.Z+v2.Z);
- v23 = new VEK(v2.X + v3.X, v2.Y + v3.Y, v2.Z+v3.Z);
- v31 = new VEK(v3.X + v1.X, v3.Y + v1.Y, v3.Z+v1.Z);
- v12 = MATH.vekNormalizePoint(v12);
- v23 = MATH.vekNormalizePoint(v23);
- v31 = MATH.vekNormalizePoint(v31);
- // 3 new points
- POINTS[pointIndex] = v12.X; // numPoints
- POINTS[pointIndex+1] = v12.Y;
- POINTS[pointIndex+2] = v12.Z;
- POINTS[pointIndex+3] = v23.X; // numPoints + 1
- POINTS[pointIndex+4] = v23.Y;
- POINTS[pointIndex+5] = v23.Z;
- POINTS[pointIndex+6] = v31.X; // numPoints + 2
- POINTS[pointIndex+7] = v31.Y;
- POINTS[pointIndex+8] = v31.Z;
- pointIndex+=9;
- // 4 new triangles
- INDICES[indiceIndex] = INDICES[i];
- INDICES[indiceIndex+1] = numPoints;
- INDICES[indiceIndex+2] = numPoints+2;
- INDICES[indiceIndex+3] = INDICES[i+1];
- INDICES[indiceIndex+4] = numPoints+1;
- INDICES[indiceIndex+5] = numPoints;
- INDICES[indiceIndex+6] = INDICES[i+2];
- INDICES[indiceIndex+7] = numPoints+2;
- INDICES[indiceIndex+8] = numPoints+1;
- INDICES[indiceIndex+9] = numPoints;
- INDICES[indiceIndex+10] = numPoints+1;
- INDICES[indiceIndex+11] = numPoints+2;
- indiceIndex += 12;
- numPoints +=3;
- }
- // a normal is created for every point.
- short[] NORMALS = new short[POINTS.length];
- VEK a, b, c;
- for(int i=0; i<NORMALS.length; i+=3){
- a = new VEK(POINTS[i], POINTS[i+1], POINTS[i+2]);
- VEK v = MATH.vekNormalizeNormal(a);
- NORMALS[i] = v.X;
- NORMALS[i+1] = v.Y;
- NORMALS[i+2] = v.Z;
- }
- int []LENGTH = new int[100];// {3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3};
- for(int i=0; i<100; i++){
- LENGTH[i] = 3;
- }
- VertexArray POSITION_ARRAY, NORMAL_ARRAY;
- IndexBuffer INDEX_BUFFER;
- // Create a VertexArray to be used by the VertexBuffer
- POSITION_ARRAY = new VertexArray(POINTS.length / 3, 3, 2);
- POSITION_ARRAY.set(0, POINTS.length / 3, POINTS);
- NORMAL_ARRAY = new VertexArray(NORMALS.length / 3, 3, 2);
- NORMAL_ARRAY.set(0, NORMALS.length / 3, NORMALS);
- INDEX_BUFFER = new TriangleStripArray(INDICES, LENGTH);
- // VertexBuffer holds references to VertexArrays that contain the positions, colors, normals,
- // and texture coordinates for a set of vertices
- VertexBuffer vertexBuffer = new VertexBuffer();
- vertexBuffer.setPositions(POSITION_ARRAY,(1.0f/1000.0f), null);
- vertexBuffer.setNormals(NORMAL_ARRAY);
- // Create the 3D object defined as a polygonal surface
- Mesh mesh = new Mesh(vertexBuffer, INDEX_BUFFER, null);
- Appearance appearance = new Appearance(); // A set of component objects that define the rendering attributes of a Mesh
- PolygonMode polygonMode = new PolygonMode(); // An Appearance component encapsulating polygon-level attributes
- polygonMode.setPerspectiveCorrectionEnable(true);
- polygonMode.setCulling(PolygonMode.CULL_FRONT); // Use CULL_FRONT for performance
- appearance.setPolygonMode(polygonMode);
- Material material = new Material();
- material.setColor(Material.AMBIENT, 0xFF0000);
- material.setVertexColorTrackingEnable(true);
- appearance.setMaterial(material);
- mesh.setAppearance(0, appearance); // Set the appearance to the 3D object
- return mesh;
- }
- }
- class VEK{
- public short X;
- public short Y;
- public short Z;
- public VEK(){
- X=Y=Z=0;
- }
- public VEK(int x, int y, int z){
- X = (short)x;
- Y = (short)y;
- Z = (short)z;
- }
- public String toString(){
- return "X=" + X + " Y=" + Y + " Z=" + Z;
- }
- }
- /*
- * A few extra math methods used to create the Icosahedron
- */
- class MATH{
- public static VEK vekCalculateNormal(VEK v1, VEK v2, VEK v3) // calculate the normal for a triangle
- {
- VEK q = new VEK(v2.X - v1.X, v2.Y- v1.Y, v2.Z -v1.Z);
- VEK p = new VEK(v3.X - v1.X, v3.Y- v1.Y, v3.Z -v1.Z);
- VEK c = new VEK(p.Y*q.Z - p.Z * q.Y, p.Z*q.X - p.X*q.Z, p.X*q.Y - p.Y*q.X);
- return c;
- }
- public static double vekLength(VEK u) // return the length of the vektor
- {
- return Math.sqrt((u.X*u.X) + (u.Y*u.Y) + (u.Z*u.Z));
- }
- public static VEK vekNormalizeNormal(VEK u) // Normalize a NORMAL
- {
- double length = vekLength(u);
- if(length==0){
- u.X=u.Y=u.Z=0;
- return u;
- }
- double a, b, c;
- a = u.X / length;
- b = u.Y / length;
- c = u.Z / length;
- a *= 127;
- b *= 127;
- c *= 127;
- u.X = (short)(a);
- u.Y = (short)(b);
- u.Z = (short)(c);
- return u;
- }
- public static VEK vekNormalizePoint(VEK u) // Normalize a POINT
- {
- double length = vekLength(u);
- if(length==0){
- u.X=u.Y=u.Z=0;
- return u;
- }
- double a, b, c;
- a = u.X / length;
- b = u.Y / length;
- c = u.Z / length;
- a *= 1000;
- b *= 1000;
- c *= 1000;
- u.X = (short)(a);
- u.Y = (short)(b);
- u.Z = (short)(c);
- return u;
- }
- }