LightDemoCanvas.java
上传用户:gyyuli
上传日期:2013-07-09
资源大小:3050k
文件大小:12k
源码类别:

J2ME

开发平台:

Java

  1. import javax.microedition.lcdui.*;
  2. import javax.microedition.lcdui.game.*;
  3. import javax.microedition.m3g.*;
  4. class LightDemoCanvas extends GameCanvas implements Runnable,CommandListener{
  5.   
  6.     private Graphics3D g3d; // Graphics object used to render the world.
  7.     private World world; // This world contains the camera and the pyramidMesh.
  8.     private Camera camera; // the camera in the scene
  9.     private Mesh icosahedronMesh; // the icosahedron in the scene
  10.     private Light light;
  11.     private int lightIndex = 0;
  12.     private javax.microedition.midlet.MIDlet midlet;
  13.     private Image SwitchImage = null;
  14.     private final int SCREEN_WIDTH;
  15.     private final int SCREEN_HEIGHT;
  16.     private Command  AMBIENT_Cmd = new Command("环境光", Command.SCREEN, 1);
  17.     private Command  DIRECTIONAL_Cmd = new Command("镜面光", Command.SCREEN, 1);
  18.     private Command  OMNI_Cmd = new Command("漫射光", Command.SCREEN, 1);
  19.     private Command  SPOT_Cmd = new Command("散射光", Command.SCREEN, 1);
  20.     private Command  EXIT_Cmd = new Command("退出", Command.SCREEN, 1);
  21.     public LightDemoCanvas(javax.microedition.midlet.MIDlet m){
  22.         super(false);
  23.         midlet = m;
  24.         this.addCommand(AMBIENT_Cmd);
  25.         this.addCommand(DIRECTIONAL_Cmd);
  26.         this.addCommand(OMNI_Cmd);
  27.         this.addCommand(SPOT_Cmd);
  28.         this.addCommand(EXIT_Cmd);
  29.         this.setCommandListener(this);
  30.         SCREEN_WIDTH = getWidth();
  31.         SCREEN_HEIGHT = getHeight(); 
  32.         g3d = Graphics3D.getInstance();
  33.         world = new World();
  34.         camera = new Camera();
  35.         world.addChild(camera); // add the camera to the world.
  36.         light = new Light();                    // Create a new light
  37.         light.translate(0.0f, 0.0f, -1.0f); // The light position
  38.         light.setMode(Light.AMBIENT);   // Light Mode
  39.         light.setColor(0x000000);           // The color of the light 'WHITE'
  40.         light.setSpotExponent(10.0f); // splot light concentration 0 to 128
  41.         world.addChild(light);                // Add the light to the world to be rendered.
  42.         // Constructs a perspective projection matrix and sets that as the current projection matrix.
  43.         camera.setPerspective(60.0f, (float)SCREEN_WIDTH / (float)SCREEN_HEIGHT, 0.1f, 50f);
  44.         icosahedronMesh = createIcosahedron(); // create our Icosahedron.
  45.         icosahedronMesh.setTranslation(0.0f, 0.0f, -3.0f); // move the icosahedron 3 units into the screen.
  46.         world.addChild(icosahedronMesh);
  47.         world.setActiveCamera(camera);
  48.         Thread t = new Thread(this);
  49.         t.start();
  50.     }
  51.  
  52.     /*
  53.      * Change the Light Mode to be used.
  54.      */
  55.     public void nextLight(){
  56.         switch(lightIndex){
  57.             case 0:
  58.                 light.setMode(Light.AMBIENT);
  59.                 break;
  60.             case 1:
  61.                 light.setMode(Light.DIRECTIONAL);
  62.                 break;
  63.             case 2:
  64.                 light.setMode(Light.OMNI);
  65.                 break;
  66.             case 3:
  67.                 light.setMode(Light.SPOT);
  68.                 break;
  69.         }
  70.     }
  71.     public void draw3D(Graphics g){
  72.         g.setColor(0x0000FF);
  73.         g.fillRect(0, 0, getWidth(), getHeight());
  74.         try{
  75.             g3d.bindTarget(g); // Binds the given Graphics or mutable Image2D as the rendering target of this Graphics3D
  76.             g3d.render(world); // Render the world
  77.         }finally{
  78.             g3d.releaseTarget();
  79.         }
  80.     }
  81.     private void draw2D(Graphics g){
  82.         g.setColor(0xFFFFFF);
  83.         switch(lightIndex){
  84.             case 0:
  85.                 g.drawString("环境光(Ambient)", 0, 0, 0);
  86.                 break;
  87.             case 1:
  88.                 g.drawString("镜面光(Directional)", 0, 0, 0);
  89.                 break;
  90.             case 2:
  91.                 g.drawString("漫射光(Omni)", 0, 0, 0);
  92.                 break;
  93.             case 3:
  94.                 g.drawString("散射光(Spot)", 0, 0, 0);
  95.                 break;
  96.         }
  97.     }
  98.     public void run() {
  99.         Graphics g = getGraphics();
  100.         while(true){
  101.         icosahedronMesh.postRotate(1.0f, 0.0f, 1.0f, 0.0f);
  102.         light.postRotate(1.0f, 1.0f, 0.0f, 0.0f); //enable this to make the light rotate around it's x-axis
  103.         draw3D(g);
  104.         draw2D(g);
  105.         flushGraphics();
  106.         }
  107.     }
  108.    public void commandAction(Command cmd, Displayable disp) {
  109.         if(cmd == EXIT_Cmd){
  110.          midlet.notifyDestroyed();
  111.         }else if(cmd == AMBIENT_Cmd){
  112.          lightIndex = 0;
  113.          nextLight();
  114.         }else if(cmd == DIRECTIONAL_Cmd){
  115.          lightIndex = 1;
  116.          nextLight();
  117.         }else if(cmd == OMNI_Cmd){
  118.          lightIndex = 2;
  119.          nextLight();
  120.         }else if(cmd == SPOT_Cmd){
  121.          lightIndex = 3;
  122.          nextLight();
  123.         }     
  124.    }    
  125.     private Mesh createIcosahedron(){
  126.         final short X = 525;
  127.         final short Z = 850;
  128.         short[]ORG_POINTS = new short[] {-X, 0, Z,      X, 0, Z,    -X, 0, -Z,      X, 0, -Z,
  129.                                          0, Z, X,      0, Z, -X,    0, -Z, X,      0, -Z, -X,
  130.                                          Z, X, 0,     -Z, X, 0,     Z, -X, 0,     -Z, -X, 0};
  131.         int []ORG_INDICES = new int[] {0,4, 1,        0,9,4,       9,5,4,       4,5,8,      4,8,1,
  132.                                        8,10,1,       8,3,10,     5,3,8,       5,2,3,       2,7,3,
  133.                                        7,10,3,       7,6,10,     7,11,6,     11,0,6,     0,1,6,
  134.                                        6,1,10,       9,0,11,     9,11,2,     9,2,5,       7,2,11};
  135.         short[]POINTS = new short[72*3];
  136.         int []INDICES = new int[80*3+80];
  137.         for(int i=0; i<36; i++){
  138.             POINTS[i] = ORG_POINTS[i];
  139.         }
  140.         for(int i=0; i<60; i++){
  141.             INDICES[i] = ORG_INDICES[i];
  142.         }
  143.         // Start sub deviding
  144.         // every triangle should become 4 triangles.
  145.         VEK v12, v23, v31;
  146.         int pointIndex = 36;
  147.         int numPoints  = 12;
  148.         int indiceIndex = 60;
  149.         for(int i=0; i<60; i+=3){
  150.             VEK v1 = new VEK(POINTS[INDICES[i]*3], POINTS[INDICES[i]*3+1], POINTS[INDICES[i]*3+2]);
  151.             VEK v2 = new VEK(POINTS[INDICES[i+1]*3], POINTS[INDICES[i+1]*3+1], POINTS[INDICES[i+1]*3+2]);
  152.             VEK v3 = new VEK(POINTS[INDICES[i+2]*3], POINTS[INDICES[i+2]*3+1], POINTS[INDICES[i+2]*3+2]);
  153.             v12 = new VEK(v1.X + v2.X, v1.Y + v2.Y, v1.Z+v2.Z);
  154.             v23 = new VEK(v2.X + v3.X, v2.Y + v3.Y, v2.Z+v3.Z);
  155.             v31 = new VEK(v3.X + v1.X, v3.Y + v1.Y, v3.Z+v1.Z);
  156.             v12 = MATH.vekNormalizePoint(v12);
  157.             v23 = MATH.vekNormalizePoint(v23);
  158.             v31 = MATH.vekNormalizePoint(v31);
  159.             // 3 new points
  160.             POINTS[pointIndex] = v12.X;     // numPoints
  161.             POINTS[pointIndex+1] = v12.Y;
  162.             POINTS[pointIndex+2] = v12.Z;
  163.             POINTS[pointIndex+3] = v23.X; // numPoints + 1
  164.             POINTS[pointIndex+4] = v23.Y;
  165.             POINTS[pointIndex+5] = v23.Z;
  166.             POINTS[pointIndex+6] = v31.X; // numPoints + 2
  167.             POINTS[pointIndex+7] = v31.Y;
  168.             POINTS[pointIndex+8] = v31.Z;
  169.             pointIndex+=9;
  170.      
  171.             // 4 new triangles
  172.             INDICES[indiceIndex] = INDICES[i];
  173.             INDICES[indiceIndex+1] = numPoints;
  174.             INDICES[indiceIndex+2] = numPoints+2;
  175.             INDICES[indiceIndex+3] = INDICES[i+1];
  176.             INDICES[indiceIndex+4] = numPoints+1;
  177.             INDICES[indiceIndex+5] = numPoints;
  178.             INDICES[indiceIndex+6] = INDICES[i+2];
  179.             INDICES[indiceIndex+7] = numPoints+2;
  180.             INDICES[indiceIndex+8] = numPoints+1;
  181.             INDICES[indiceIndex+9] = numPoints;
  182.             INDICES[indiceIndex+10] = numPoints+1;
  183.             INDICES[indiceIndex+11] = numPoints+2;
  184.             indiceIndex += 12;
  185.             numPoints +=3;
  186.         }
  187.         // a normal is created for every point.
  188.         short[] NORMALS = new short[POINTS.length];
  189.         VEK a, b, c;
  190.          for(int i=0; i<NORMALS.length; i+=3){
  191.              a = new VEK(POINTS[i], POINTS[i+1], POINTS[i+2]);
  192.              VEK v = MATH.vekNormalizeNormal(a);
  193.              NORMALS[i] = v.X;
  194.              NORMALS[i+1] = v.Y;
  195.              NORMALS[i+2] = v.Z;
  196.          }
  197.         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};
  198.         for(int i=0; i<100; i++){
  199.             LENGTH[i] = 3;
  200.         }
  201.         VertexArray POSITION_ARRAY, NORMAL_ARRAY;
  202.         IndexBuffer INDEX_BUFFER;
  203.         // Create a VertexArray to be used by the VertexBuffer
  204.         POSITION_ARRAY = new VertexArray(POINTS.length / 3, 3, 2);
  205.         POSITION_ARRAY.set(0, POINTS.length / 3, POINTS);
  206.         NORMAL_ARRAY = new VertexArray(NORMALS.length / 3, 3, 2);
  207.         NORMAL_ARRAY.set(0, NORMALS.length / 3, NORMALS);
  208.         INDEX_BUFFER = new TriangleStripArray(INDICES, LENGTH);
  209.         // VertexBuffer holds references to VertexArrays that contain the positions, colors, normals, 
  210.         // and texture coordinates for a set of vertices
  211.         VertexBuffer vertexBuffer = new VertexBuffer();
  212.         vertexBuffer.setPositions(POSITION_ARRAY,(1.0f/1000.0f), null);
  213.         vertexBuffer.setNormals(NORMAL_ARRAY);
  214.         
  215.         // Create the 3D object defined as a polygonal surface
  216.         Mesh mesh = new Mesh(vertexBuffer, INDEX_BUFFER, null);
  217.         
  218.         Appearance appearance = new Appearance(); // A set of component objects that define the rendering attributes of a Mesh
  219.         PolygonMode polygonMode = new PolygonMode(); // An Appearance component encapsulating polygon-level attributes
  220.         polygonMode.setPerspectiveCorrectionEnable(true);
  221.         polygonMode.setCulling(PolygonMode.CULL_FRONT); // Use CULL_FRONT for performance
  222.         appearance.setPolygonMode(polygonMode);
  223.         Material material = new Material();
  224.         material.setColor(Material.AMBIENT, 0xFF0000);
  225.         material.setVertexColorTrackingEnable(true);
  226.         appearance.setMaterial(material);
  227.  
  228.         mesh.setAppearance(0, appearance); // Set the appearance to the 3D object        
  229.         return mesh;
  230.     }
  231. }
  232. class VEK{
  233.     public short X;
  234.     public short Y;
  235.     public short Z;
  236.     public VEK(){
  237.         X=Y=Z=0;
  238.     }
  239.     public VEK(int x, int y, int z){
  240.         X = (short)x;
  241.         Y = (short)y;
  242.         Z = (short)z;
  243.     }
  244.     public String toString(){
  245.         return "X=" + X + " Y=" + Y + " Z=" + Z;
  246.     }
  247.     
  248. }
  249. /*
  250.  *  A few extra math methods used to create the Icosahedron
  251.  */
  252. class MATH{
  253.     public static VEK vekCalculateNormal(VEK v1, VEK v2, VEK v3)  // calculate the normal for a triangle
  254.     {
  255.             VEK q = new VEK(v2.X - v1.X, v2.Y- v1.Y, v2.Z -v1.Z);
  256.             VEK p = new VEK(v3.X - v1.X, v3.Y- v1.Y, v3.Z -v1.Z);
  257.             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);
  258.             return c;
  259.     }
  260.     public static double vekLength(VEK u) // return the length of the vektor
  261.     {
  262.             return Math.sqrt((u.X*u.X) + (u.Y*u.Y) + (u.Z*u.Z));
  263.     }
  264.     
  265.     public static VEK vekNormalizeNormal(VEK u)  // Normalize a NORMAL
  266.     {
  267.             double length = vekLength(u);
  268.             if(length==0){
  269.                     u.X=u.Y=u.Z=0;
  270.                      return u;
  271.             }
  272.             double a, b, c;
  273.             a = u.X / length;
  274.             b = u.Y / length;
  275.             c = u.Z / length;
  276.             a *= 127;
  277.             b *= 127;
  278.             c *= 127;
  279.             u.X = (short)(a);
  280.             u.Y = (short)(b);
  281.             u.Z = (short)(c);
  282.             return u;
  283.     }
  284.     public static VEK vekNormalizePoint(VEK u)  // Normalize a POINT
  285.     {
  286.             double length = vekLength(u);
  287.             if(length==0){
  288.                     u.X=u.Y=u.Z=0;
  289.                      return u;
  290.             }
  291.             double a, b, c;
  292.             a = u.X / length;
  293.             b = u.Y / length;
  294.             c = u.Z / length;
  295.             a *= 1000;
  296.             b *= 1000;
  297.             c *= 1000;
  298.             u.X = (short)(a);
  299.             u.Y = (short)(b);
  300.             u.Z = (short)(c);
  301.             return u;
  302.     }
  303. }