三维漫游的实现

一、本文主要是展示一个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工具类前面展示过这里就省略了。

 

转载于:https://www.cnblogs.com/bokeofzp/p/5967481.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/356648.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

MySQL JDBC驱动程序如何处理准备好的语句

准备的语句类型 在研究《 高性能Java持久性》一书中的“ 语句缓存”一章时&#xff0c;我有机会比较了Oracle&#xff0c;SQL Server&#xff0c;PostgreSQL和MySQL处理预准备语句的方式。 感谢Jess Balint &#xff08;MySQL JDBC驱动程序贡献者&#xff09;&#xff0c;他在…

Nodejs学习(三)-安装nodejs supervisor,提高点效率吧。

安装好了express准备写项目&#xff0c;可是发现随便改一下js都要使用npm start重新启动才能生效&#xff0c;这个很不好&#xff0c;搜索一下发现有这么一个模块supervisor。那就安装一下吧。 1.安装&#xff0c;这个必须是全局安装那就开始吧。 npm -g install supervisor 设…

网络语言不c,哪些网络用语不文明?

满意答案林昨末sk2013.02.26采纳率&#xff1a;47% 等级&#xff1a;11已帮助&#xff1a;8049人Q1. 你认为在网络上出现的不文明用语情况_B___&#xff1f;A.是人们宣泄情绪的一种重要方式 B.是当今社会的一个缩影&#xff0c;没有办法C.不应当提倡&#xff0c;应加大管理力…

android 无限旋转动画,android ——不停旋转动画

xml文件android:fromDegrees"359"android:toDegrees"0"android:duration"1000"android:repeatCount"-1"android:pivotX"50%"android:pivotY"50%"/>代码/开始旋转/public voidstartRotateAnimation(View view, …

九章算法强化班 - 课程大纲

第1章 FLAG算法面试难度提高&#xff1f;如何准备&#xff1f; 各类IT企业的面试算法难度及风格 如何解决中等难度以上的算法题 如果解决follow up问题 Two sum   1. Two sum follow up I   2. Two sum follow up II - Triangle count Kth largest element   1. 第…

JavaOne演讲者选择了您不应该错过的10个会话

确保您的会议安排中包含这些JavaOne会话 JavaOne 2015从这个星期日开始&#xff0c;数百个会话同时进行&#xff0c;因此很难筛选所有会话并选择要参加的会话。 这就是为什么我们邀请5位我们最喜欢的JavaOne发言人让我们了解他们的会议&#xff0c;并选择他们最期待的会议。 好…

谷歌发布最新版安卓Android,谷歌正式除名华为,安卓12华为首发无望,但鸿蒙将迎难顶上!...

原标题&#xff1a;谷歌正式"除名"华为&#xff0c;安卓12华为首发无望&#xff0c;但鸿蒙将迎难顶上&#xff01;前几天谷歌正式发布了新一代的安卓12系统。这也是安卓的第十二个大更新版本&#xff0c;从安卓1.0发布的2008年算起&#xff0c;安卓系统已经走过13个年…

android sd卡 格式化 rom,Android开发之获取SD卡及手机ROM容量的方法

本文实例讲述了Android获取SD卡及手机ROM容量的方法。分享给大家供大家参考&#xff0c;具体如下&#xff1a;这里通过一个简单的小例子&#xff0c;来获取SD卡的容量和手机ROM的容量&#xff0c;代码如下&#xff1a;package com.urovo.sdcardspace;import java.io.File;impor…

未知的生成错误 因为没有预加载,所以无法解析程序集 GalaSoft.MvvmLight

使用wpf开发时&#xff0c;在ViewModel中引用了DevExpress注册的GalaSoft.MvvmLight命名空间&#xff0c;使用其ViewModelBase&#xff0c;在View界面中绑定事件时出现错误&#xff1a; 错误 13 未知的生成错误“因为没有预加载&#xff0c;所以无法解析程序集“GalaSoft.MvvmL…

maven原型_Maven原型创建技巧

maven原型我最近需要为姜黄SOA项目创建一些Maven原型。 对于不了解的人来说&#xff0c; Maven原型是一种基于一些预先罐装的项目模板生成项目的方法。 对于当前的姜黄SOA原型&#xff0c;它将创建一个多模块Maven项目&#xff0c;其中包含Interface和Service项目以及基本的WSD…

android 副mic测试,【收藏】Android Audio Framework CTS Verifier 测试方法

This new suite of tests requires human intervention and some external hardware including a Loopback Plug, a USB reference microphone and external speakers. For devices without 3.5 mm (⅛”) headset port, the user will be able to skip the test and mark it a…

python的数与字符串

数的类型&#xff1a; >>符号整数型(int)&#xff1a;0、1、-1 >>长整型(long)&#xff1a;88888888、999999999 >>浮点型(float)&#xff1a;2.77777、3.4445544 >>布尔型(bool)&#xff1a;True、False >>复数型(complex)&#xff1a;42j、-92…

Java在几乎所有方面都可以胜任本机响应

我与一位同事讨论了Java与JavaScript的话题&#xff0c;这是一个有问题的话题。 然后&#xff0c;他提到React Native多么出色&#xff0c;我决定我必须研究一下&#xff0c;也许要为Codename One掌握一些想法…… 那里有一些不错的主意&#xff0c;但是它们都不是革命性的或例…

魅蓝android底层是什么,魅蓝E2的手机系统是什么

魅蓝E2的手机系统是什么魅蓝E2的手机系统是Flyme 6系统。魅蓝E2搭载了基于YunOS底层深度定制的Flyme 6系统&#xff0c;相交于Flyme 5系列&#xff0c;Flyme 6拥有更轻巧明快的设计元素&#xff0c;辅以让人称颂的人工智能技术One Mind&#xff0c;可以有效保障魅蓝E2日常使用流…

android夜间模式揭露动画,Android Material Design系列之夜间模式

今天我们讲讲夜间模式的实现&#xff0c;这篇文章的名字应该叫&#xff1a;《Android Material Design系列之夜间模式》。在Android 5.0 之后&#xff0c;实现夜间模式并非很难了&#xff0c;支持的5.0库提供了非常简单的实现方式。不信&#xff0c;你就往下看。首先说&#xf…

reader dc

https://get.adobe.com/cn/reader/otherversions/转载于:https://www.cnblogs.com/zengkefu/p/5981109.html

jboss drools_JBoss Drools –入门

jboss drools这篇文章是关于我如何掌握JBoss Drools的 。 其背后的原因是&#xff1a;SAP收购了我公司当前的规则引擎&#xff0c;而Drools是我们将寻找的另一种选择&#xff0c;只要有人有能力提高概念验证的能力。 尽管似乎有大量的文档&#xff0c;但是我总是会通过示例来发…

Android开发环境(IDE)

一&#xff1a;Eclipse 1、装JDK&#xff1b; 2、装Eclipse&#xff1b;//应与JDK同为32/64位。 3、装ADT&#xff1b; 4、装android sdk&#xff1b; 推荐下载ADT bundle包&#xff08;包含Eclipse&#xff0c;Android SDK Manager&#xff0c;sdk&#xff09;。此Eclipse已经…

华为荣耀30pro鸿蒙内测版,荣耀手机用户放心了 消息称荣耀30 Pro正在内测华为鸿蒙OS...

2021-5-11 13:12【天极网手机频道】鸿蒙OS2.0手机版目前正在大规模开发者公测阶段&#xff0c;有消息称6月份将开始大规模向华为手机用户推送。而对于不少荣耀手机用户来讲&#xff0c;他们也十分期待体验鸿蒙OS&#xff0c;但荣耀品牌已经与华为品牌分离&#xff0c;这让不少荣…

Docker容器中的WildFly Swarm JAX-RS微服务

这些天&#xff0c;每个人都在谈论微服务。 关于如何在企业级应用这些原则&#xff0c;有很多意见和想法&#xff0c;而很少有示例。 可以肯定的是&#xff0c;即使在几天前的会议上&#xff0c;我也很少发现有人在生产环境中运行Docker容器。 当我问起初次体验以及是否有人玩过…