OpenglES2.0 for Android:各种变换来一波

Android OpenGLES2.0开发(十):FBO离屏渲染 FBO(Frame Buffer Object)即帧缓冲区对象,实际上是一个可添加缓冲区的容器,可以为其添加纹理或渲染缓冲区对象(RBO)。FBO可以让我们的渲染不渲染到屏幕上,而是渲染到离屏Buffer中。可以理解为将OpenGL ES绘制的图像内容输出到一块内存中,而我们可以对这块内存进行多次绘制。当然这块内存中的数据也可保存到本地SD卡中,也可重新绘制到屏幕上用于显示。FBO是一个容器,自身不能用于渲染,需要与一些可渲染的缓冲区绑定在一起,像纹理或者渲染缓冲区。 阅读详情

OpenglES2.0 for Android:各种变换来一波

监听屏幕事件

在进行各种变换之前,我们先来了解一下如何监听屏幕的事件。我们下面的变换都需要用立方体来演示,所以我们继续使用上一节的绘制立方体的内容
首先新建一个项目 OpengESChange ,将上一节中关于绘制立方体的代码复制过来 。在前面我们一直在使用
android.opengl.GLSurfaceView
在第一篇中我们已经知道了这个类的作用,为了监听屏幕事件,我们创建一个类继承自该类,重写其onTouchEvent方法。
此时该类 代码如下 : (MySurfaceView.java  ):
package com.cumt.opengeschange;

import com.cumt.render.MyRender;
import android.content.Context;
import android.opengl.GLSurfaceView;
import android.view.MotionEvent;

public class MySurfaceView extends GLSurfaceView {
	
	private MyRender myRender;

	public MySurfaceView(Context context) {
		super(context);
		// TODO Auto-generated constructor stub
		myRender = new MyRender(context);
		this.setEGLContextClientVersion(2);
		this.setRenderer(myRender);
		// 设置渲染模式为主动渲染
		this.setRenderMode(GLSurfaceView.RENDERMODE_CONTINUOUSLY);
	}
	
	@Override
	public boolean onTouchEvent(MotionEvent event) {
		// TODO Auto-generated method stub
		return super.onTouchEvent(event);
	}
}

在onTouchEvent方法中我们就可以检测到各种事件了   我们也可以使用GLSurfaceView的setOnTouchListener来监听视图的触控事件 ,代码如下(MySurfaceView.java  ):

package com.cumt.opengeschange;

import com.cumt.render.MyRender;
import android.content.Context;
import android.opengl.GLSurfaceView;
import android.view.MotionEvent;
import android.view.View;

public class MySurfaceView extends GLSurfaceView {
	
	private MyRender myRender;

	public MySurfaceView(Context context) {
		super(context);
		// TODO Auto-generated constructor stub
		myRender = new MyRender(context);
		this.setEGLContextClientVersion(2);
		this.setRenderer(myRender);
		// 设置渲染模式为主动渲染
		this.setRenderMode(GLSurfaceView.RENDERMODE_CONTINUOUSLY);
		this.setOnTouchListener(new OnTouchListener() {
			
			public boolean onTouch(View v, MotionEvent event) {
				// TODO Auto-generated method stub
				return false;
			}
		});
	}
}


此时MainActivity也有稍微的改动 (MainActivity.java ):

package com.cumt.opengeschange;

import android.app.Activity;
import android.content.pm.ActivityInfo;
import android.os.Bundle;
import android.view.Window;
import android.view.WindowManager;

public class MainActivity extends Activity {

	private MySurfaceView glSurfaceView;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		// 设置为全屏
		requestWindowFeature(Window.FEATURE_NO_TITLE);
		getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
				WindowManager.LayoutParams.FLAG_FULLSCREEN);
		// 设置为横屏模式
		setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
		glSurfaceView = new MySurfaceView(this);
		setContentView(glSurfaceView);
	}

	@Override
	protected void onPause() {
		// TODO Auto-generated method stub
		super.onPause();
		glSurfaceView.onPause();
	}

	@Override
	protected void onResume() {
		// TODO Auto-generated method stub
		super.onResume();
		glSurfaceView.onResume();
	}
}


此时我们的前期工作已经OK 了 

平移变换

先来看下平移变换矩阵 :

矩阵中的三个参数分别表示沿X ,Y,Z轴方向的位移


平移矩阵M 乘 当前P点的向量,即可得到平移后的P ‘  点的向量 。

现在我们想要在原来绘制立方体的基础上实现这样的功能 :手指在屏幕上向左或向右移动时,我们的立方体向左或向右移动一段距离 。
首先我们需要修改MatrixState中的代码 ,新建一个平移变换矩阵 并初始化为单位矩阵,然后创建一个方法共外部调用以设置平移,最后修改我们原先的
getFinalMatrix方法,在该方法中乘上该平移矩阵。过程如下代码所示 (MatrixState.java ):

package com.cumt.utils;

import android.opengl.Matrix;
//存储系统矩阵状态的类
public class MatrixState {
	
	private static float[] mProjMatrix = new float[16];// 4x4矩阵 存储投影矩阵
	private static float[] mVMatrix = new float[16];// 摄像机位置朝向9参数矩阵
	
	/*
	 * 第一步 :新建平移变换矩阵
	 */
	private static float[] mtMatrix = new float[16];// 平移变换矩阵
	
	/*
	 * 第二步: 初始化为单位矩阵
	 */
	static{
		//初始化为单位矩阵
		Matrix.setIdentityM(mtMatrix, 0);
	}
	
	/*
	 * 第三步 : 平移变换方法共外部使用
	 */
	public static void translate(float x,float y,float z)//设置沿xyz轴移动
    {
    	Matrix.translateM(mtMatrix, 0, x, y, z);
    }
	// 设置摄像机
	public static void setCamera(float cx, // 摄像机位置x
			float cy, // 摄像机位置y
			float cz, // 摄像机位置z
			float tx, // 摄像机目标点x
			float ty, // 摄像机目标点y
			float tz, // 摄像机目标点z
			float upx, // 摄像机UP向量X分量
			float upy, // 摄像机UP向量Y分量
			float upz // 摄像机UP向量Z分量
	) {
		Matrix.setLookAtM(mVMatrix, 0, cx, cy, cz, tx, ty, tz, upx, upy, upz);
	}

	// 设置透视投影参数
	public static void setProjectFrustum(float left, // near面的left
			float right, // near面的right
			float bottom, // near面的bottom
			float top, // near面的top
			float near, // near面距离
			float far // far面距离
	) {
		Matrix.frustumM(mProjMatrix, 0, left, right, bottom, top, near, far);
	}

	// 获取具体物体的总变换矩阵
	static float[] mMVPMatrix = new float[16];

	public static float[] getFinalMatrix() {
		
		/*
		 * 第四步  : 乘以平移变换矩阵
		 */
		Matrix.multiplyMM(mMVPMatrix, 0, mVMatrix, 0, mtMatrix, 0);
		Matrix.multiplyMM(mMVPMatrix, 0, mProjMatrix, 0, mMVPMatrix, 0);
		return mMVPMatrix;
	}
}

这里我们使用静态代码段初始化平移矩阵为单位矩阵,如果用户没有设置平移变换矩阵,也不会影响原图形。

然后我们在MySurfaceView中监听用户的屏幕移动事件 ,代码如下 (MySurfaceView.java):

package com.cumt.opengeschange;

import com.cumt.render.MyRender;
import com.cumt.utils.MatrixState;
import android.content.Context;
import android.opengl.GLSurfaceView;
import android.view.MotionEvent;
import android.view.View;

public class MySurfaceView extends GLSurfaceView {
	
	private MyRender myRender;
	private float mPreviousX;//上次的触控位置X坐标

	public MySurfaceView(Context context) {
		super(context);
		// TODO Auto-generated constructor stub
		myRender = new MyRender(context);
		this.setEGLContextClientVersion(2);
		this.setRenderer(myRender);
		// 设置渲染模式为主动渲染
		this.setRenderMode(GLSurfaceView.RENDERMODE_CONTINUOUSLY);
		
		this.setOnTouchListener(new OnTouchListener() {
			
			public boolean onTouch(View v, MotionEvent event) {
				// TODO Auto-generated method stub
				float x = event.getX();//当前的触控位置X坐标
				switch (event.getAction()) {
				case MotionEvent.ACTION_MOVE://检测到移动事件时
					float dx = x - mPreviousX;
					if(dx > 0){
						MatrixState.translate(0.1f, 0, 0);
					}else{
						MatrixState.translate(-0.1f, 0, 0);
					}
				}
				mPreviousX=x;
				return true;
			}
			
		});
	}
}

来看下运行效果 :


旋转变换

看下旋转矩阵 :



表示将点 P 绕向量 U 旋转  θ 度 。在OpenGL中我们使用
void android.opengl. Matrix.rotateM( float[] m, int mOffset, float a, float x, float y, float z)
方法来设置旋转 ,第一个参数表示返回的旋转矩阵,mOffset表示偏移量,一般设置为0 ,a 表示角度 ,x y z表示旋转轴对应向量的X,Y,Z分量

下面我们来实现这样一个功能 : 每点击屏幕一次,让我们的立方体沿着其 Y 轴旋转30度 

首先在我们原来的 MatrixState类中新增一个方法来设置旋转 ,新增代码如下 :

//旋转变换
	public static void rotate(float angle, float x, float y, float z) {// 设置绕xyz轴移动
		Matrix.rotateM(mtMatrix, 0, angle, x, y, z);
	}

然后就在MySurfaceView类中设置监听事件和旋转 ,此时MySurfaceView.java代码如下 :

package com.cumt.opengeschange;

import com.cumt.render.MyRender;
import com.cumt.utils.MatrixState;
import android.content.Context;
import android.opengl.GLSurfaceView;
import android.view.MotionEvent;
import android.view.View;

public class MySurfaceView extends GLSurfaceView {
	
	private MyRender myRender;

	public MySurfaceView(Context context) {
		super(context);
		// TODO Auto-generated constructor stub
		myRender = new MyRender(context);
		this.setEGLContextClientVersion(2);
		this.setRenderer(myRender);
		// 设置渲染模式为主动渲染
		this.setRenderMode(GLSurfaceView.RENDERMODE_CONTINUOUSLY);
		
		this.setOnTouchListener(new OnTouchListener() {
			
			public boolean onTouch(View v, MotionEvent event) {
				// TODO Auto-generated method stub
				switch (event.getAction()) {
				case MotionEvent.ACTION_DOWN://检测到点击事件时
					MatrixState.rotate(30, 0, 1, 0);
				}
				return true;
			}
		});
	}
}

我们运行看下效果:


缩放变换

缩放矩阵 :


上面矩阵中三个参数分别表示缩放变换中的沿X,Y,Z轴方向的缩放率。

我们来实现下面的效果:点击屏幕后进行一定比例的缩放操作 
首先在MatrixState.java中加入如下代码 :
//缩放变换
	public static void scale(float x,float y,float z)
    {
    	Matrix.scaleM(mtMatrix,0, x, y, z);
    }

然后就在MySurfaceView类中设置监听事件和缩放 ,此时MySurfaceView.java代码如下 :

package com.cumt.opengeschange;

import com.cumt.render.MyRender;
import com.cumt.utils.MatrixState;
import android.content.Context;
import android.opengl.GLSurfaceView;
import android.view.MotionEvent;
import android.view.View;

public class MySurfaceView extends GLSurfaceView {
	
	private MyRender myRender;

	public MySurfaceView(Context context) {
		super(context);
		// TODO Auto-generated constructor stub
		myRender = new MyRender(context);
		this.setEGLContextClientVersion(2);
		this.setRenderer(myRender);
		// 设置渲染模式为主动渲染
		this.setRenderMode(GLSurfaceView.RENDERMODE_CONTINUOUSLY);
		
		this.setOnTouchListener(new OnTouchListener() {
			
			public boolean onTouch(View v, MotionEvent event) {
				// TODO Auto-generated method stub
				switch (event.getAction()) {
				case MotionEvent.ACTION_DOWN://检测到点击事件时
					MatrixState.scale(0.4f, 1.5f, 0.6f);//xyz三个方向按各自的缩放因子进行缩放
				}
				return true;
			}
		});
	}
}


运行效果:



最后祝大家端午节快乐~~


Android OpenGLES2.0开发(六):着色器语言GLSL 该篇文章讲解了GLSL的基本语法,需要结合实例去不断练习才能熟练的使用 阅读详情

相关推荐

微信小程序 | 小程序开发

事实上,目前小程序在我们生活中已经随处可见(特别是这次疫情的推动,不管是什么岗位、什么年龄阶段的人,到哪都需要打开健康码)WePY是由腾讯开源的,一款让小程序支持组件化开发的框架,通过预编译的手段让开发者可以选择自己喜欢的开发风格去开发小程序。Mpvue是一个使用Vue开发小程序的前端框架,也是 支持 微信小程序、百度智能小程序,头条小程序 和 支付宝小程序;微信小程序、支付宝小程序、淘宝小程序、抖音小程序、头条小程序、QQ小程序、美团小程序等。,其他平台的小程序往往是平台本身的一些公司或者顺手开发的。

CoderHing的博客~ 1万+

Android API开发之OpenGL开发之Android OpenGL之使用GLSurfaceView创建一个3D旋转的图形

本文讲述使用GLSurfaceView创建一个3D旋转的图形   代码1:OpenGLESActivity.java   public class OpenGLESActivity extends AppCompatActivity {       private GLSurfaceView glSurfaceView;     @Override     protected void...

听海的博客 3141

【安徽理工大学】一文带你高分拿下计算机考研复试(85+的秘密)

一文带你高分拿下安徽理工大学计算机考研复试(85+的秘密)

猫天意的博客 1523

Android OpenGLES2.0(十一)——利用OpenGLES做Camera预览

学习FFMpeg,推荐雷神的博客。天妒英才,为雷神叹息。第一步 下载FFmpeg(F F m peg)。 第二步 解压FFmpeg。 第三步 windows安装MinGW和Msys。也许还要yasm,名字改为yasm.exe放到C:\WINDOWS\system32中。Linux下就不用这么麻烦了。 第四步 建立如下目录结构,ffmpeg为解压出来的FFmpeg。configure为ff

偶尔记录的一些学习笔记 2万+

零基础教程:用Python给试卷照片自动切题(有道OCR+PIL完整流程)

本文为零基础用户提供了一套完整的Python自动化切题方案。通过调用有道OCR API识别试卷照片中的题目坐标,并利用PIL库进行精准裁剪,将杂乱的试卷图片自动分割为独立的题目图像。教程详细涵盖了环境搭建、图像预处理、API调用、坐标解析与批量处理全流程,帮助教育工作者和技术爱好者高效处理大量试卷,实现工作流程自动化。

grpc6streamer的博客 1173

解决 python2.7中 ImportError: No module named Crypto.Signature

我的解决办法,先查看有没有安装 pip,直接执行pip 回车 没有出现null什么的就安装了,如果没有安装去其他博客哪里看一下,正常情况是默认就有的,然后使用。发现我自己也不会啊,就百度看看,想着网上的解决方法一大片,但是都是废话,能用的没有几个,而且能安装的没有几个。这个里面的python2、3就是系统里面的python版本,直接跟我这样就可以了除非版本不一样,也就是没有这个版本。就可以使用了,第一个应该是卸载之前的,然后重新安装,我的就是这样解决的。就比如我的,我现在使用的 python2.7。

记录一下 1610

android gles2物体旋转,在Android的Opengles 2.0中绘制精灵的最快方法

我认为您正在追求粒子系统.类似的问题在这里:Drawing many textured particles quickly in OpenGL ES 1.1.使用点精灵非常便宜,但是您必须在片段着色器中做额外的工作,如果您需要不同大小的粒子,我不确定GLES2是否支持gl_PointSize. gl_PointSize Corresponding to World Space Size我的首选粒子...

weixin_35003319的博客 308

大整数因数分解工具——yafu

可以将大整数放在一个新建文件中——data.txt,最后面一定要换行,不然会出现eof;done processing batchfile,运行命令。2.点击设置——系统——系统信息——高级系统设置——环境变量——点击PATH(上下都可以)——新建 添加yafu-x64.exe 所在路径——点击确定。,如果整数数过长,会出现错误mismatched parens;1.找到yafu-x64.exe 所在的文件路径。如果出现以下图像,说明配置成功。3.打开cmd,输入。

l2ohvef的博客 6156

Android OpenGLES2.0(九)——利用OpenGL进行图片处理

在之前的博客中我们就有提过OpenGLES的常见应用范围,其中有一个就是图片的处理。为了保证效率,Android手机中许多美颜相机、图片处理应用,都用到了OpenGLES来处理图片。上一篇博客中,我们利用OpenGLES 显示出了一张图片,并保证图片正常显示,不会被拉伸和压缩。在本篇博客中,我们来了解下利用OpenGLES来处理图片的一些简单方法。相关原理本篇博客以简单的图片色彩处理、模糊和放大镜效

偶尔记录的一些学习笔记 1万+

Word公式一键转MathType保姆级教程(附omml2mml.xsl报错终极解决方案)

本文提供Word公式一键转MathType的保姆级教程,重点解决常见的omml2mml.xsl报错问题。通过详细分析报错原因、官方解决方案实操步骤及转换后格式优化技巧,帮助用户高效完成公式转换,适用于科研论文和商业文档编辑。

weixin_30082367的博客 554

光谱预处理最简单实现方法--基于OpenSA光谱分析库

系列文章目录 “光晰本质,谱见不同”,光谱作为物质的指纹,被广泛应用于成分分析中。伴随微型光谱仪/光谱成像仪的发展与普及,基于光谱的分析技术将不只停留于工业和实验室,即将走入生活,实现万物感知,见微知著。本系列文章致力于光谱分析技术的科普和应用。 文章目录系列文章目录前言一、数据来源二、代码解读2.1 读取数据2 .2 划分数据集2 .3 返回训练集和测试集并绘制光谱图片2.4 建立1-D CNN模型2.5 训练1-D CNN模型2.6 测试1-D CNN模型2.7 运行CNN模型,并用查看结果总结

Echo_Code的博客 7067

Andriod OpenGL 教程 04 - 旋转

关键字: android OpenGL 移动开发 教程 在这一课,我们将演示如何旋转三角形和四边形。左图中的三角形沿Y轴旋转,四边形沿着X轴旋转。 为了实现上述目的,我们需要在MyGLRenderer.java中添加一些代码,是三角形和四边形按我们的要求动态地旋转起来。 添加四个控制变量: privatefloatangleTriangle = 0.0f;     privatefl

seniorwizard的专栏 1015

使用 MATLAB/Simulink 对基于同步发电机的双机系统进行建模

双机系统(Two-Machine System)是电力系统中用于研究动态稳定性和控制策略的一个典型模型。它由两台同步发电机通过输电网络相互连接,模拟实际电网中的互联操作。当发生短路故障时,系统的暂态稳定性会受到挑战,可能导致发电机失步或电压崩溃。本教程将带你使用 MATLAB/Simulink 对基于同步发电机的双机系统进行建模,并对其在短路故障条件下的暂态稳定性进行仿真和分析。

amy_mhd的博客 216

Android OpenGLES2.0开发(四):矩阵变换和相机投影

本章主要讲解了OpenGL ES环境下绘图变形的几种处理方式,让我们对坐标系、矩阵、相机、投影有一个全面的认识

xiaozhiwz的专栏 1538

pscad IEEE标准系统搭建说明

pscad IEEE标准系统搭建说明,包含典型的IEEE 9节点、14节点、30节点、39节点和118节点系统。内含标准测试系统的原始数据和潮流结果。

win10 跳过U8环境检测的IE WebControls.rar

win10 安装u8的时候 提示IE WebControls 不通过,这个工具可以欺骗u8的检查。 跳过U8环境检测的IE WebControls。提示导入失败后,重新检测通过。

Android OpenGLES2.0(一)OpenGLES2.0基础介绍

Andoid OpenGlES基础认识,OpenGL在不同的平台上有不同的实现,但是它定义好了专业的程序接口,不同的平台都是遵照该接口来进行实现的,思想完全相同,方法名也是一致的,所以使用时也基本一致,只需要根据不同的语言环境稍有不同而已。OpenGL这套3D图形API从1992年发布的1.0版本到目前最新2014年发布的4.5版本,在众多平台上多有着广泛的使用。...

主要记录一些问题处理记录,部分是作为知识库使用 2400

SAP B1中文培訓教材_SDK

公司内部培训资料,对开发工具 ,DIAPI, UIAPI,Add-ON有详细解说

Android OpenGLES2.0开发(一):艰难的开始

本章节我们简单讲解了OpenGL ES是什么,刨除了很多晦涩难懂的概念。

xiaozhiwz的专栏 1669

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

Android OpenGLES2.0(一)——了解OpenGLES2.0

OpenGL在不同的平台上有不同的实现,但是它定义好了专业的程序接口,不同的平台都是遵照该接口来进行实现的,思想完全相同,方法名也是一致的,所以使用时也基本一致,只需要根据不同的语言环境稍有不同而已。OpenGL这套3D图形API从1992年发布的1.0版本到目前最新2014年发布的4.5版本,在众多平台上多有着广泛的使用。OpenGL ES相对于OpenGL来说,减少了许多不是必须的方法和数据类型,去掉了不必须的功能,对代价大的功能做了限制,比OpenGL更为轻量。在OpenGL ES的世界里,没有四边形

liuliuhelingdao的博客 2016

OpenglES2.0 for Android:来做个地球吧

OpenglES2.0 for Android:来做个地球吧 上两节中我们说了纹理映射,也利用纹理给我们的平面图形以及立方体穿上了漂亮的衣服,在继续学习其他知识之前,让我们先来用纹理映射以及我们前面做的球 来实现一个地球的贴图。整体效果如下 图所示: 贴图所需要的图片素材如下 : 素材  " 窃取 ” 了csdn另一位网友的

cassiePython的专栏 3732

Android OpenGLES2.0开发(八):Camera预览

该篇章主要讲解了OpenGL ES对外部纹理Camera预览数据的渲染

xiaozhiwz的专栏 1681

Android OpenGLES2.0(十)——OpenGL中的平移、旋转、缩放

在前面的博客中,所有的例子都是一个对象,类似绘制圆锥绘制圆柱,我们都是传入一个参数,然后去控制那个圆面的位置,如果我们要绘制几个个正方形,它的位置、大小、方向都是不相同的,按照那种方式该多麻烦啊。所以我们需要更好的办法——矩阵变换。 什么是矩阵 其实在之前的博客中,我们也基本都用到了矩阵,投影的设置,就是根据参数生成一个4*4的矩阵,我们用长度为16的浮点型数组来存储,相机的设置也是如此。那么矩...

android开发笔记 3036

Android OpenGLES2.0开发(七):纹理贴图之显示图片

本文讲解了纹理贴图的基本用法,纹理坐标和OpenGL ES坐标系的不同

xiaozhiwz的专栏 1923

OpenGLES Android篇零基础系列(一):OpenGLES2.x可渲染管道基本流程

转载请注明出处前言OpenGL ES是OpenGL的一个子集,是针对手机、PDA和游戏主机等嵌入式设备而设计的。该API由Khronos集团定义推广,Khronos是一个图形软硬件行业协会,该协会主要关注图形和多媒体方面的开放标准。 因此OpenGL ES作为第三方库被应用在android中。 到目前为止,OpenGL ES已经发展有了3个版本,OpenGL ES 1.0 , OpenGL ES

死磕到底 7745
上一篇: OpenglES2.0 for Android:来画个立方体吧
下一篇: OpenglES2.0 for Android:来画个球吧
cassiePython
博客等级 码龄12年 303粉丝 135原创
评论 7
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值