zoukankan      html  css  js  c++  java
  • 三维漫游的实现

    一、本文主要是展示一个demo,实现的是画一个三维的立方体,通过滑动屏幕来旋转方向,上下左右来移动。直接上代码:

    MainActivity:
    package com.example.zp.a3dword;
     
    import android.graphics.Bitmap;
    import android.graphics.BitmapFactory;
    import android.graphics.Point;
    import android.opengl.GLSurfaceView;
    import android.support.v7.app.AppCompatActivity;
    import android.os.Bundle;
    import android.view.KeyEvent;
    import android.view.MotionEvent;
    import android.view.View;
    import android.view.Window;
    import android.view.WindowManager;
     
    public class MainActivity extends AppCompatActivity {
     
    private GLSurfaceView glSurfaceView;
    GLRenderer renderer;
    //屏幕的宽高
    int width;
    int height;
    float speed = 0.5f;
     
    @Override
    protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    glSurfaceView= (GLSurfaceView) findViewById(R.id.gl_surfaceView);
    // glSurfaceView =new GLSurfaceView(this);
    Bitmap bitmap = BitmapFactory.decodeResource(this.getResources(), R.drawable.ayx);
    Bitmap bitmap2 = BitmapFactory.decodeResource(this.getResources(), R.drawable.ayx2);
    Bitmap mBitmap[] = {bitmap,bitmap2};
    renderer=new GLRenderer(mBitmap);
    glSurfaceView.setRenderer(renderer);
    // setContentView(glSurfaceView);
    WindowManager wm = this.getWindowManager();
    Point p = new Point(0,0);
    wm.getDefaultDisplay().getSize(p);
    width = p.x;
    height =p.y;
     
    }
     
    int downX; //向一个方向的起始点坐标
    int previewX; // 记住前一个点的x坐标
    int currentX; //当前点的ex坐标
     
    int downY; //向一个方向的起始点坐标
    int previewY; // 记住前一个点的x坐标
    int currentY; //当前点的ex坐标
     
    @Override
    public boolean onTouchEvent(MotionEvent event) {
    switch (event.getAction()) {
    case MotionEvent.ACTION_DOWN:
    downX = (int) event.getX();
    previewX = downX;
    downY = (int) event.getY();
    previewY= downY;
    break;
    case MotionEvent.ACTION_MOVE:
    currentX = (int) event.getX();
    currentY = (int) event.getY();
    //****************************X方向旋转******************************************//
    //判断运动的方向是否改变,大于0不改变
    if((currentX - downX)*(currentX - previewX)>0)
    {
    int dis = currentX - downX;
    float angle = (float) dis / (float) width * (float) Math.PI;
    renderer.letfrightDirectionChange(angle);
    previewX = currentX;
    }
    else
    {
    downX = previewX;
    }
    //****************************Y方向旋转******************************************//
    currentY = (int) event.getY();
    //判断运动的方向是否改变,大于0不改变
    if((currentY - downY)*(currentY - previewY)>0)
    {
    int dis = currentY - downY;
    float angle = (float) dis / (float) width * (float) Math.PI;
    renderer.updownDirectionChange(angle);
    previewY = currentY;
    }
    else
    {
    downY = previewY;
    }
     
    break;
    case MotionEvent.ACTION_UP:
    break;
    }
    return true;
    }
     
    public void goBack(View view)
    {
    renderer.goAhead(-speed);
    }
    public void goAhead(View view)
    {
    renderer.goAhead(speed);
    }
    public void goLeft(View view)
    {
    renderer.goleft(speed);
    }
    public void goRight(View view)
    {
    renderer.goleft(-speed);
    }
    }
    Render的实现:
    package com.example.zp.a3dword;
     
    import android.graphics.Bitmap;
    import android.opengl.GLSurfaceView;
    import android.opengl.GLUtils;
    import java.nio.FloatBuffer;
    import java.nio.IntBuffer;
     
    import javax.microedition.khronos.egl.EGLConfig;
    import javax.microedition.khronos.opengles.GL10;
     
    /**
    * Created by lenovo on 2016/9/7.
    */
    public class GLRenderer implements GLSurfaceView.Renderer{
     
    float xrot = 0;
    float yrot = 0;
     
    private float visonPointX=0f;
    private float visonPointY=0f;
    private float visonPointZ=-3f;
     
    int size=3;
    int one = 0x10000*size;
     
    int textureSize = 2;
    int texture[] = new int [textureSize];
    private Bitmap mBitmap[];
     
     
    //当正方体很小,为1个点位的时候发现在角落的时候两边出现黑条,这是因为屏幕显示的,即我们看到的视觉是一个以(0,0,0)为中心的平面,旋转函数是旋转整个三维世界,而
    //视觉平面的大小位置永远不变,我自己定义为视觉坐标,视觉坐标是不变的,三维世界的坐标起初与视觉坐标是一致的,且视觉显示的是-1层即z为-1的那层只有小与-1的物体可以看到
    // 当随着三维世界的旋转就会与视觉坐标产生差异,视觉坐标不变,当随着三维世界的旋转,三维世界的坐标对应的点对应与视觉坐标-1层及大于-1层的物体就不会显示
    //正方体的6个面,4个点确定一个面
    IntBuffer vertices = BufferUtil.intToBuffer(new int[]{
    -one,-one,one,
    one,-one,one,
     
    -one,one,one, one,one,one,
     
    -one,-one,-one,
    -one,one,-one,
     
    one,-one,-one,one,one,-one,
     
    -one,one,-one,
    -one,one,one,
     
    one,one,-one, one,one,one,
     
    -one,-one,-one,
    one,-one,-one,
     
    -one,-one,one,one,-one,one,
     
    one,-one,-one,
    one,one,-one,
     
    one,-one,one, one,one,one,
     
    -one,-one,-one,
    -one,-one,one,
     
    -one,one,-one,-one,one,one
     
    });
     
    //这里one 为几就贴几张,是指一个边贴几张,一个面就是one*one张了,one为1*5所以这里除以5,就会只贴一张
    int one2 = one/size;
    IntBuffer texCoords2 = BufferUtil.intToBuffer(new int[]{
    0, one2, one2, one2, 0, 0, one2, 0,
    0, 0, 0, one2, one2, 0, one2, one2,
    one2, one2, one2, 0, 0, one2, 0, 0,
    0, one2, one2, one2, 0, 0, one2, 0,
    0, 0, 0, one2, one2, 0, one2, one2,
    one2, 0, 0, 0, one2, one2, 0, one2,
    });
     
    public GLRenderer(Bitmap mBitmap[])
    {
    this.mBitmap = mBitmap;
    }
     
    @Override
    public void onDrawFrame(GL10 gl)
    {
    // 清除屏幕和深度缓存
    gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
    // 重置当前的模型观察矩阵
    // gl.glEnable(GL10.GL_LIGHTING);
    gl.glLoadIdentity();
    gl.glTranslatef(visonPointX,visonPointY,visonPointZ);
     
    //设置3个方向的旋转
    gl.glRotatef(xrot, 1.0f, 0.0f, 0.0f);
    gl.glRotatef(yrot, 0.0f,1.0f, 0.0f);
    // gl.glRotatef(zrot, 0.0f, 0.0f, 1.0f);
     
     
    gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
    gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);//启用纹理映射
     
    gl.glVertexPointer(3, GL10.GL_FIXED, 0, vertices);
    gl.glTexCoordPointer(2, GL10.GL_FIXED, 0, texCoords2);
    gl.glBindTexture(GL10.GL_TEXTURE_2D, texture[1]);
     
    for(int i = 0 ; i < 6 ; i ++)
    {
    gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP , i*4 , 4);
    gl.glFinish();
    }
    gl.glDisableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
    gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
     
    }
     
    @Override
    public void onSurfaceChanged(GL10 gl, int width, int height)
    {
    float ratio = (float) width / height;
    //设置OpenGL场景的大小
    gl.glViewport(0, 0, width, height);
    //设置投影矩阵
    gl.glMatrixMode(GL10.GL_PROJECTION);
    //重置投影矩阵
    gl.glLoadIdentity();
    // 设置视口的大小
    gl.glFrustumf(-ratio, ratio, -1, 1, 1, 10);
    // 选择模型观察矩阵
    gl.glMatrixMode(GL10.GL_MODELVIEW);
    // 重置模型观察矩阵
    gl.glLoadIdentity();
     
    }
     
    @Override
    public void onSurfaceCreated(GL10 gl, EGLConfig config)
    {
    // 黑色背景
    gl.glClearColor(0, 0, 0, 0);
    // gl.glEnable(GL10.GL_CULL_FACE);
    // 启用阴影平滑
    gl.glShadeModel(GL10.GL_SMOOTH);
    // 启用深度测试
    gl.glEnable(GL10.GL_DEPTH_TEST);
     
    // 启用混合模式
    gl.glEnable(GL10.GL_BLEND);
    gl.glDisable(GL10.GL_DEPTH_TEST); // 关闭深度测试
    //设置光线,,1.0f为全光线,a=50%
    gl.glColor4f(1.0f,1.0f,1.0f,0.5f);
    // 基于源象素alpha通道值的半透明混合函数
    gl.glBlendFunc(GL10.GL_SRC_ALPHA,GL10.GL_ONE);
     
    //启用纹理映射
    gl.glClearDepthf(1.0f);
    //深度测试的类型
    gl.glDepthFunc(GL10.GL_LEQUAL);
    //精细的透视修正
    gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, GL10.GL_NICEST);
    //允许2D贴图,纹理
    gl.glEnable(GL10.GL_TEXTURE_2D);
    getTextures(gl);
     
     
     
    // //设置光颜色
    // FloatBuffer lightAmbient = BufferUtil.floatToBuffer(new float[]{
    // 1f, 1f, 1f, 1f
    // } );
    // FloatBuffer lightDiffuse = BufferUtil.floatToBuffer(new float[]{
    // 1f,1f,1f,1f
    // } );
    // //定义光源位置
    // FloatBuffer lightPosition = BufferUtil.floatToBuffer(new float[]{
    // -2f,0f,-4f,1f
    // } );
    //
    //// //设置环境光
    // gl.glLightfv(GL10.GL_LIGHT1, GL10.GL_AMBIENT, lightAmbient);
    //
    // //设置漫射光
    // gl.glLightfv(GL10.GL_LIGHT1, GL10.GL_DIFFUSE, lightDiffuse);
    //
    // //设置光源位置
    // gl.glLightfv(GL10.GL_LIGHT1, GL10.GL_POSITION, lightPosition);
    //
    // //开启一号光源
    // gl.glEnable(GL10.GL_LIGHT1);
     
    }
     
     
    private void getTextures(GL10 gl)
    {
    IntBuffer intBuffer = IntBuffer.allocate(2);//申请2个纹理存储空间
    // 创建纹理
    gl.glGenTextures(2 , intBuffer); //创建2个纹理,绑定intuffer
    texture[0] = intBuffer.get(); // 获取第一个纹理的存储指针,即纹理存储位置,位置+1
    texture[1] = intBuffer.get(); //获取下一个纹理存储的位置
     
    // 设置要使用的纹理
    gl.glBindTexture(GL10.GL_TEXTURE_2D, texture[0]);
    //生成纹理
    GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0 , mBitmap[0] , 0);//利用图mBitmap[0]生成纹理,存储在texture[0]
    // 线形滤波
    gl.glTexParameterx(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_LINEAR);
    gl.glTexParameterx(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_LINEAR);
     
    //生成第二个纹理
    gl.glBindTexture(GL10.GL_TEXTURE_2D, texture[1]);
    GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0 , mBitmap[1] , 0);//利用图mBitmap[0]生成纹理,存储在texture[1]
    gl.glTexParameterx(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_LINEAR);
    gl.glTexParameterx(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_LINEAR);
     
    }
     
    //三维世界向右旋转,我们的视觉就向左旋转了
    public void letfrightDirectionChange( float angle)
    {
    yrot = yrot + angle;
    }
     
    public void updownDirectionChange(float angle)
    {
    xrot = xrot + angle;
    }
     
    public void goAhead (float dis)
    {
    visonPointZ = visonPointZ + dis;
    }
    public void goleft (float dis)
    {
    visonPointX = visonPointX + dis;
    }
     
    }
    BufferUtil工具类前面展示过这里就省略了。
  • 相关阅读:
    poj 1321
    Cocos2D-html5 公布游戏js编译为jsc
    Android定位开发之百度定位、高德定位、腾讯定位,三足鼎立一起为我所用!
    python 设计模式之 单例模式
    css画电脑键盘
    【C/C++学院】(23)Mysql数据库编程--C语言编程实现mysqlclient
    用DOM4J包实现对xml文件按属性分离。
    MVC4中AJAX Html页面打开调用后台方法实现动态载入数据库中的数据
    贝勒爷教你怎样在Mac上安装Microsoft Office
    6.Swift教程翻译系列——Swift集合类型
  • 原文地址:https://www.cnblogs.com/bokeofzp/p/5967481.html
Copyright © 2011-2022 走看看