《智能设备艺术、科技、文化作品实例开发与设计》android开发系列介绍---2.3棋类作品:3d魔方

2.3棋类作品:3d魔方
2.3.1 Android为OpenGL介绍

Android为OpenGL  ES支持提供了GLSurfaceView组件,这个组件用于显示3D图形。GLSurfaceView本身并不提供绘制3D图形的功能,而是由GLSurfaceView.Renderer来完成了SurfaceView中3D图形的绘制。

归纳起来,在Android中使用OpenGL  ES需要三个步骤:

1、创建GLSurfaceView组件,使用Activity来显示GLSurfaceView组件。

2、为GLSurfaceView组件创建GLSurfaceView.Renderer实例,实现GLSurfaceView.Renderer类时需要实现该接口里的三个方法:

  abstract void  onDrawFrame(GL10  gl):Renderer对象调用该方法绘制GLSurfaceView的当前帧。

  abstract void  onSurfaceChanged(GL10  gl , int  width  ,int height):当GLSurfaceView的大小改变时回调该方法。

  abstract void  onSurfaceCreated(GL10  gl  ,  EGLConfig config):当GLSurfaceView被创建时回调该方法。

3、调用GLSurfaceView组件的setRenderer()方法指定Renderer对象,该Renderer对象将会完成GLSurfaceView里3D图像的绘制。

从上面的介绍不难看出,实际上绘制3D图形的难点不是如何使用GLSurfaceView组件,而是如何实现Renderer类。实现Renderer类时需要实现三个方法,这三个方法都有一个GL10形参,它就代表了GLOpen  ES的“绘制画笔”,我们可以把它想象成Swing  2D绘图中的Graphics,也可以想象成Android  2D绘图中的Canvas组件-----当我们希望Renderer绘制3D图形时,实际上是调用GL10的方法来进行绘制的。

 

publicvoid onSurfaceChanged(GL10 gl, int width, int height) {  
        // TODOAuto-generated method stub  
          
        //设置OpenGL的场景大小  
        gl.glViewport(0, 0,width, height);  
       gl.glMatrixMode(GL10.GL_PROJECTION); // 设置投影矩阵    
        gl.glLoadIdentity(); //设置矩阵为单位矩阵,相当于重置矩阵           
       GLU.gluPerspective(gl, 45.0f, ((float) width) / height, 0.1f, 10f);//设置透视范围      
    }  
    //当窗口被创建是调用  
    public void onSurfaceCreated(GL10gl, EGLConfig config) {  
        // TODOAuto-generated method stub  
          
           gl.glClearColor(0.0f, 0.0f, 0.0f, 1.0f);//设置清屏时背景的颜色,R,G,B,A    
           
           gl.glEnable(GL10.GL_DEPTH_TEST); //启用深度缓存    
           gl.glEnable(GL10.GL_CULL_FACE);  //启用背面剪裁    
           gl.glClearDepthf(1.0f);    // 设置深度缓存值    
           gl.glDepthFunc(GL10.GL_LEQUAL);  // 设置深度缓存比较函数,GL_LEQUAL表示新的像素的深度缓存值小于等于当前像素的深度缓存值(通过gl.glClearDepthf(1.0f)设置)时通过深度测试      
           gl.glShadeModel(GL10.GL_SMOOTH);// 设置阴影模式GL_SMOOTH    
    }  
      
2.3.2绘制一个3d正方体和一个参照体



 class MyRendererimplements Renderer{  
         
         
     float box[] = new float[] {   
               // FRONT    
               -0.2f, -0.2f,  0.2f,    
                0.2f, -0.2f,  0.2f,    
               -0.2f,  0.2f,  0.2f,    
                0.2f,  0.2f,  0.2f,    
               // BACK    
               -0.2f, -0.2f, -0.2f,    
               -0.2f,  0.2f, -0.2f,    
                0.2f, -0.2f, -0.2f,    
                0.2f,  0.2f, -0.2f,    
               // LEFT    
               -0.2f, -0.2f,  0.2f,    
               -0.2f,  0.2f,  0.2f,    
               -0.2f, -0.2f, -0.2f,    
               -0.2f,  0.2f, -0.2f,    
               // RIGHT    
                0.2f, -0.2f, -0.2f,    
                0.2f,  0.2f, -0.2f,    
                0.2f, -0.2f,  0.2f,    
                0.2f,  0.2f,  0.2f,    
               // TOP    
               -0.2f,  0.2f,  0.2f,    
                0.2f,  0.2f,  0.2f,    
                -0.2f,  0.2f, -0.2f,    
                0.2f,  0.2f, -0.2f,    
               // BOTTOM    
               -0.2f, -0.2f,  0.2f,    
               -0.2f, -0.2f, -0.2f,    
                0.2f, -0.2f,  0.2f,    
                0.2f, -0.2f, -0.2f,    
            };   
        
        FloatBuffercubeBuff,  cubeBuff1;    
            
        float xrot = 0.0f;   
        float yrot = 0.0f;   
        /**   
         * 将float数组转换存储在字节缓冲数组   
         * @param arr  
         * @return  
         */   
        public FloatBuffermakeFloatBuffer(float[] arr) {    
           ByteBuffer bb = ByteBuffer.allocateDirect(arr.length * 4);//分配缓冲空间,一个float占4个字节    
            bb.order(ByteOrder.nativeOrder());//设置字节顺序, 其中ByteOrder.nativeOrder()是获取本机字节顺序    
           FloatBuffer fb = bb.asFloatBuffer(); //转换为float型    
           fb.put(arr);        //添加数据    
           fb.position(0);      //设置数组的起始位置    
            returnfb;    
        }    
            
    public MyRenderer(){  
         cubeBuff =makeFloatBuffer(box);//转换float数组    
         cubeBuff1 =makeFloatBuffer(box);
    }  
      
     //所有的绘图操作都在此方法中执行  
  
    public void onDrawFrame(GL10 gl) { 
        // TODOAuto-generated method stub  
          
        gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);// 清除屏幕和深度缓存    
           
           gl.glMatrixMode(GL10.GL_MODELVIEW);   //切换至模型观察矩阵    
           gl.glLoadIdentity();// 重置当前的模型观察矩阵    
           GLU.gluLookAt(gl, 0, 0, 3, 0, 0, 0, 0, 1, 0);//设置视点和模型中心位置    
            
           gl.glVertexPointer(3, GL10.GL_FLOAT, 0, cubeBuff);//设置顶点数据    
       // gl.glLoadIdentity();// 重置当前的模型观察矩阵    
     // GLU.gluLookAt(gl, 0, 0,3, 0, 0, 0, 0, 1, 0);//设置视点和模型中心位置    
            
           gl.glRotatef(rotate, 1, 0, 0);  //绕着(0,0,0)与(1,0,0)即x轴旋转    
           gl.glRotatef(rotate, 0, 1, 0);    
               
   
  gl.glTranslatef(-0.6f, -0.2f, 0f); 
     gl.glVertexPointer(3,GL10.GL_FLOAT, 0, cubeBuff1);//设置顶点数据 
           gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);    
            
            //六个面一个面绘制一种颜色  
           gl.glColor4f(1.0f, 0, 0, 1.0f);   //设置颜色,红色    
           gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, 4);  //绘制正方型FRONT面    
           gl.glColor4f(1.0f, 1.0f, 0, 1.0f);   
           gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 4, 4);    
            
           gl.glColor4f(0, 1.0f, 0, 1.0f);    
           gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 8, 4);    
           gl.glColor4f(0, 1.0f, 1.0f, 1.0f);  
           gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 12, 4);    
               
           gl.glColor4f(0, 0, 1.0f, 1.0f);    
           gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 16, 4);   
           gl.glColor4f(1.0f, 1.0f, 1.0f, 1.0f);    
           gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 20, 4);    
          // gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 20,40); 
            
            xrot+= 1.0f;    
            yrot+= 0.5f;    
           gl.glMatrixMode(GL10.GL_MODELVIEW);   //切换至模型观察矩阵    
           gl.glLoadIdentity();// 重置当前的模型观察矩阵    
           GLU.gluLookAt(gl, 0, 0, 3, 0, 0, 0, 0, 1, 0);//设置视点和模型中心位置    
            
           gl.glVertexPointer(3, GL10.GL_FLOAT, 0, cubeBuff);//设置顶点数据    
       // gl.glLoadIdentity();// 重置当前的模型观察矩阵    
     // GLU.gluLookAt(gl, 0, 0,3, 0, 0, 0, 0, 1, 0);//设置视点和模型中心位置    
            
   
 // gl.glTranslatef(-0.6f, -0.2f,0f); 
     gl.glVertexPointer(3,GL10.GL_FLOAT, 0, cubeBuff1);//设置顶点数据 
           gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);    
            
           //gl.glRotatef(rotate, 1, 0, 0);  //绕着(0,0,0)与(1,0,0)即x轴旋转    
          // gl.glRotatef(rotate, 0, 1, 0);    
               
            //六个面一个面绘制一种颜色  
           gl.glColor4f(1.0f, 0, 0, 1.0f);   //设置颜色,红色    
           gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, 4);  //绘制正方型FRONT面    
           gl.glColor4f(1.0f, 1.0f, 0, 1.0f);   
           gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 4, 4);    
            
           gl.glColor4f(0, 1.0f, 0, 1.0f);    
           gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 8, 4);    
           gl.glColor4f(0, 1.0f, 1.0f, 1.0f);  
           gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 12, 4);    
               
            gl.glColor4f(0,0, 1.0f, 1.0f);    
           gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 16, 4);   
           gl.glColor4f(1.0f, 1.0f, 1.0f, 1.0f);    
           gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 20, 4);    
             
    }  

 

 

2.3.3 触屏改变旋转参数
public boolean onTouchEvent(final MotionEvent event) {

      // rotate+=1;

      setTitle("成功啦!!");

  

      if (event.getAction() == MotionEvent.ACTION_MOVE) {

         final float xdiff = (xAngle - event.getX());

         final float ydiff = (yAngle - event.getY());

        

          {

             xAngle = xAngle+ ydiff;

                yAngle = yAngle + xdiff;

            }

          rotate+=1; 

         xAngle = event.getX();

         yAngle = event.getY();

      }

      return true;

   }


2.3.4绘制27个3d正方体组成一个三阶魔方

  调用Draw1(gl, i - 1, j - 1, k - 1,

 

                         rx[3 * k + 9 * j + i + 1], ry[3 * k + 9 * j + i

 

                               + 1], rz[3 * k + 9 * j + i + 1]);

27次,每次在onDrawFrame(GL10 gl)中刷新位置与旋转角度。

 

   public void Draw1(GL10 gl, int x, int y, int z, int rx, int ry, int rz) {

 

         gl.glLoadIdentity();// 重置当前的模型观察矩阵

 

         GLU.gluLookAt(gl, 0, 0, 3, 0, 0,0, 0, 1, 0);// 设置视点和模型中心位置

 

 

 

         gl.glVertexPointer(3, GL10.GL_FLOAT, 0, cubeBuff);// 设置顶点数据

 

         gl.glRotatef(30, 1, 0, 0); // 绕着(0,0,0)(1,0,0)x轴旋转

 

         gl.glRotatef(-30, 0, 1, 0); // 绕着(0,0,0)(1,0,0)x轴旋转

 

         for (int k = e; k >= 1; k--) {

 

            if (c[3 * z + 13 + 9 * y + x + 1][k] == 1) {

 

                gl.glRotatef(90, 1, 0, 0);

 

            }

 

            if (c[3 * z + 13 + 9 * y + x + 1][k] == 2) {

 

                gl.glRotatef(90, 0, 1, 0);

 

            }

 

            if (c[3 * z + 13 + 9 * y + x + 1][k] == 3) {

 

                gl.glRotatef(90, 0, 0, 1);

 

            }

 

         }

 

         // gl.glRotatef(rotate, 1 , 0, 0);

 

 

 

         // gl.glRotatef(rotate,0 , 1, 0);

 

         // gl.glRotatef(rotate, ox[-1][1][1][0],ox[-1][1][1][1],

 

         // ox[-1][1][1][2]);

 

         float zoom = .6f;

 

         gl.glTranslatef(zoom * .41f * x, zoom *.41f * y, zoom * .41f * z);

 

         gl.glScalef(zoom, zoom, zoom);

 

 

 

         gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);

 

 

 

         // 六个面一个面绘制一种颜色

 

         gl.glColor4f(1.0f, 0, 0, 1.0f); // 设置颜色,红色

 

         gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, 4); // 绘制正方型FRONT

 

         gl.glColor4f(1.0f, 1.0f, 0, 1.0f);

 

         gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 4, 4);

 

 

 

         gl.glColor4f(0, 1.0f, 0, 1.0f);

 

         gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 8, 4);

 

         gl.glColor4f(0, 1.0f, 1.0f, 1.0f);

 

         gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 12, 4);

 

 

 

         gl.glColor4f(0, 0, 1.0f, 1.0f);

 

         gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 16, 4);

 

         gl.glColor4f(1.0f, 1.0f, 1.0f, 1.0f);

 

         gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 20, 4);

 

 

 

      }

 

 

 

      public void onDrawFrame(GL10 gl) {

 

         // TODO Auto-generated method stub

 

 

 

         gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);// 清除屏幕和深度缓存

 

         gl.glScalef(.8f, .8f, .8f);

 

         gl.glMatrixMode(GL10.GL_MODELVIEW); // 切换至模型观察矩阵

 

         for (int k = 0; k < 3; k++) {

 

            for (int j = 0; j < 3; j++) {

 

                for (int i = 0; i < 3; i++) {

 

                   Draw1(gl, i - 1, j - 1, k -1,

 

                         rx[3 * k + 9 * j + i + 1], ry[3 * k + 9 * j + i

 

                               + 1], rz[3 * k + 9 * j + i + 1]);

 

                   // Draw1(gl,zb[k-1][j-1][i-1][0],zb[k][j][i][1],zb[k][j][i][2]);

 

                }

 

            }

 

         }

 

         // Draw1(gl, -1, -2, 1, 0, 0, 0);

 

      }

 

 

 

2.3.5绘制3d三阶魔方XYZ轴转动算法

 

   void rxo(int k) {

 

 

 

      for (int i = 0; i < 8; i++) {

 

         if (k <4) {

 

            x0[i] = x00[i]+k-1;

 

         }

 

         else if (k <7) {

 

            x0[i] = y0[i]+(k-4)*9;

 

         }

 

         else if (k <10) {

 

            x0[i] = z0[i] + (k-7)*3;

 

         }

 

      }

 

      int b[] = { 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,1, 1, 1, 1, 1, 1, 1, 1,

 

            1, 1, 1, 1, 1, 1, 1, 1 };

 

      for (int i = 0; i < 8; i++) {

 

         for (int p = 1; p < 28; p++) {

 

            if ((a0[p] == x0[i]) && (b[p] == 1)) {

 

                a0[p] = x0[(i + 6) % 8];

 

                b[p] = 0;

 

            }

 

 

 

         }

 

      }

 

 

 

   }

 

 

public boolean onTouchEvent(final MotionEvent event) {

 

      // rotate+=1; rotate1+=1;final

 

      float xdiff = (xAngle - fx[0]);

 

      final float ydiff = (yAngle - fy[0]);

 

      if (event.getX() > 1) {

 

         fx[0] = (int)(event.getX());

 

         fy[0] = (int)(event.getY());

 

      }

 

      if (event.getAction() == MotionEvent.ACTION_DOWN) { // 按下

 

         fx[1] = (int)(event.getX());

 

         fy[1] = (int)(event.getY());

 

      }

 

      if (event.getAction() == MotionEvent.ACTION_UP) {

 

 

 

         // rotate+=45; rotate1+=45;

 

 

 

         if (fy[1] > 610) {

 

            if (Math.abs(xdiff) * 1.2 < Math.abs(ydiff)){

 

                if (fx[1] < 180) {

 

                   fx[2] = 1;

 

                } else if (fx[1] < 290) {

 

                   fx[2] = 2;

 

                } else if (fx[1] < 500) {

 

                   fx[2] = 3;

 

                }

 

            } else if (Math.abs(xdiff) * 1.2 >Math.abs(ydiff)){

 

                if (fy[1] - (fx[1] - 190) / 2.5 < 670) {

 

                   fx[2] = 6;

 

                } else if (fy[1] - (fx[1] - 190) / 2.5 < 770) {

 

                   fx[2] = 5;

 

                } else if (fy[1] - (fx[1] - 190) / 2.5 < 880) {

 

                   fx[2] = 4;

 

                }

 

            }

 

         }else {

        

            if (fy[1] - (fx[1] - 190) / 2.5 < 460) {

 

                fx[2] = 7;

 

            } else if (fy[1] - (fx[1] - 190) / 2.5 < 500) {

 

                fx[2] = 8;

 

            } else  {

 

                fx[2] = 9;

            }

         }

 

 

         if (fx[2] < 4) {

 

            e++;

 

 

 

            for (int k = 1; k < 28; k++) {

 

                if (x[a0[k]] != fx[2]-2) {

 

                   c[k][e] = 0;

 

                }

 

 

 

                if (x[a0[k]] == fx[2]-2) {

 

                   aa = aa + k + "@";

 

 

 

                   c[k][e] = 1;

 

                   rx[k] += 30;

 

                   for (int k2 = 1; k2 < 280; k2++) {

 

                      for (int k1 = 1; k1 < 280; k1++)

 

                         ;

 

                   }

 

 

 

                   rx[k] += 30;

 

 

 

                   for (int k2 = 1; k2 < 280; k2++) {

 

                      for (int k1 = 1; k1 < 280; k1++)

 

                         ;

 

                   }

 

                   rx[k] += 30;

 

 

 

                }

 

            }

 

            rxo(fx[2]);

 

            setTitle(aa);

 

         } else if (fx[2] > 6) {

 

 

 

            e++;

 

            for (int k = 1; k < 28; k++) {

 

                if (z[a0[k]] == fx[2]-8) {

 

                   c[k][e] = 3;

 

                   for (int k2 = 1; k2 < 280; k2++) {

 

                      for (int k1 = 1; k1 < 280; k1++)

 

                         ;

 

                   }

 

 

 

                   rz[k] += 30;

 

                   for (int k2 = 1; k2 < 280; k2++) {

 

                      for (int k1 = 1; k1 < 280; k1++)

 

                         ;

 

                   }

 

 

 

                   rz[k] += 30;

 

                   rxo(fx[2]);

 

                }

 

            }

 

         } else if (fx[2] < 7) {

 

            e++;

 

            aa = "";

 

            for (int k = 1; k < 28; k++) {

 

                if (y[a0[k]] == fx[2]-5) {

 

                   aa = aa + k + "@";

 

 

 

                   c[k][e] = 2;

 

                   for (int k2 = 1; k2 < 280; k2++) {

 

                      for (int k1 = 1; k1 < 280; k1++)

 

                         ;

 

                   }

 

 

 

                   ry[k] += 30;

 

                   for (int k2 = 1; k2 < 280; k2++) {

 

                      for (int k1 = 1; k1 < 280; k1++)

 

                         ;

 

                   }

 

 

 

                   ry[k] += 30;

 

                }

 

            }

 

            rxo(fx[2]);

 

            setTitle(aa);

 

         }

 

 

 

         // fx[0]=(int) (event.getX());

 

         // rotate+=1;

 

         xAngle = event.getX();

 

         yAngle = event.getY();

 

 

 

      }

 

      setTitle(fx[1] + "@" + fy[1] + "@" + xdiff + "@" + ydiff + "@" + fx[0]

 

            + "@" + fx[2]);

 

      return true;

 

   }


  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值