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