运行有问题或需要源码请点赞关注收藏后评论区留言~~~

一、三维投影

OpenGL,定义了跨语言跨平台的图形程序接口,对于Android开发者来说,OpenGL就是用来绘制三维图形的技术手段。当然OpenGL并不仅限于展示静止的三维图形,也能用来播放运动着的三维动画。

只要具备了绘图场所,绘画载体,绘图工具就可以进行绘画创作,对于OpenGL的三维绘图来说,同样具备三种要素,分别是GLSurfaceView,GLSurfaceView.Rnender,和GL10,这样就能实现绘画功能

同样要对于Android自定义控件 分为以下四个步骤

1:声明自定义控件的构造方法 可以在此获取并初始化控件属性

2:重写onMeasure方法 可在此测量控件的宽度和高度

3:重写onLayout方法  可在此挪动控件的位置

4:重写onDraw方法  可在此绘制空间的形状 颜色 文字以及图案等等

GL10编码的三类常见方法如下

1:颜色的取值范围 从0-1

2:三维坐标系 有x y z三个坐标

3:坐标矩阵变换 分为以下三步

设置绘图区域

调整镜头参数

挪动观测方位

实现三维图形效果如下

可以在下拉框中自行选择缩放比率以及旋转角度

代码如下

Java类

package com.example.threed;import androidx.appcompat.app.AppCompatActivity;import android.opengl.GLES30;
import android.opengl.GLSurfaceView;
import android.opengl.Matrix;
import android.os.Bundle;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Spinner;import com.example.threed.util.EsVertexUtil;
import com.example.threed.util.GlUtil;import java.nio.FloatBuffer;
import java.util.ArrayList;
import java.util.List;import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;public class EsMatrixActivity extends AppCompatActivity {private final static String TAG = "EsMatrixActivity";private GLSurfaceView glsv_content; // 声明一个图形库表面视图对象private int mType; // 形状的类型private int mDivide = 20; // 将经纬度等分的面数private float mRadius = 4; // 球半径private int mAngle = 60; // 旋转角度private int mProgramId; // 声明glsl小程序的编号private float[] mProjectionMatrix = new float[16]; // 声明投影矩阵private float[] mModelMatrix = new float[16]; // 声明模型矩阵private float[] mMVPMatrix = new float[16]; // 声明结果矩阵@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_es_matrix);initVertexList(); // 初始化立方体的顶点列表initShapeSpinner(); // 初始化形状下拉框glsv_content = findViewById(R.id.glsv_content);// 声明使用OpenGL ES的版本号为3.0。使用ES30方法之前务必指定版本号glsv_content.setEGLContextClientVersion(3);// 给OpenGL的表面视图注册三维图形的渲染器glsv_content.setRenderer(new MatrixRenderer());// 设置渲染模式。默认的RENDERMODE_CONTINUOUSLY表示持续刷新,RENDERMODE_WHEN_DIRTY表示只有首次创建和调用requestRender方法时才会刷新glsv_content.setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY);//glsv_content.requestRender(); // 主动请求渲染操作}private List<FloatBuffer> mVertexList = new ArrayList<>(); // 顶点列表// 以下定义了立方体六个面的顶点坐标数组(每个坐标点都由三个浮点数组成)private static float[] vertexsFront = {0.5f, 0.5f, 0.5f, 0.5f, 0.5f, -0.5f, -0.5f, 0.5f, -0.5f, -0.5f, 0.5f, 0.5f};private static float[] vertexsBack = {0.5f, -0.5f, 0.5f, 0.5f, -0.5f, -0.5f, -0.5f, -0.5f, -0.5f, -0.5f, -0.5f, 0.5f};private static float[] vertexsTop = {0.5f, 0.5f, 0.5f, 0.5f, -0.5f, 0.5f, -0.5f, -0.5f, 0.5f, -0.5f, 0.5f, 0.5f};private static float[] vertexsBottom = {0.5f, 0.5f, -0.5f, 0.5f, -0.5f, -0.5f, -0.5f, -0.5f, -0.5f, -0.5f, 0.5f, -0.5f};private static float[] vertexsLeft = {-0.5f, 0.5f, 0.5f, -0.5f, 0.5f, -0.5f, -0.5f, -0.5f, -0.5f, -0.5f, -0.5f, 0.5f};private static float[] vertexsRight = {0.5f, 0.5f, 0.5f, 0.5f, 0.5f, -0.5f, 0.5f, -0.5f, -0.5f, 0.5f, -0.5f, 0.5f};// 初始化立方体的顶点列表private void initVertexList() {mVertexList.add(GlUtil.getFloatBuffer(vertexsFront));mVertexList.add(GlUtil.getFloatBuffer(vertexsBack));mVertexList.add(GlUtil.getFloatBuffer(vertexsTop));mVertexList.add(GlUtil.getFloatBuffer(vertexsBottom));mVertexList.add(GlUtil.getFloatBuffer(vertexsLeft));mVertexList.add(GlUtil.getFloatBuffer(vertexsRight));}// 初始化形状下拉框private void initShapeSpinner() {ArrayAdapter<String> shapeAdapter = new ArrayAdapter<>(this,R.layout.item_select, shapeArray);Spinner sp_shape = findViewById(R.id.sp_shape);sp_shape.setPrompt("请选择三维物体形状");sp_shape.setAdapter(shapeAdapter);sp_shape.setOnItemSelectedListener(new ShapeSelectedListener());sp_shape.setSelection(0);}private String[] shapeArray = { "静止立方体", "静止球体", "旋转立方体", "旋转球体" };class ShapeSelectedListener implements AdapterView.OnItemSelectedListener {public void onItemSelected(AdapterView<?> arg0, View arg1, int arg2, long arg3) {mType = arg2;mVertexList.clear();if (mType == 0 || mType == 2) {initVertexList(); // 初始化立方体的顶点列表} else if (mType == 1 || mType == 3) {// 获取球体的顶点列表mVertexList = EsVertexUtil.getBallVertexs(mDivide, mRadius);}if (mType == 2 || mType == 3) {glsv_content.setRenderMode(GLSurfaceView.RENDERMODE_CONTINUOUSLY); // 设置渲染模式} else {glsv_content.setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY); // 设置渲染模式glsv_content.requestRender(); // 主动请求渲染操作}}public void onNothingSelected(AdapterView<?> arg0) {}}public class MatrixRenderer implements GLSurfaceView.Renderer {@Overridepublic void onSurfaceCreated(GL10 gl, EGLConfig config) {GLES30.glClearColor(1f, 1f, 1f, 1f); //设置背景颜色// 初始化着色器mProgramId = GlUtil.initShaderProgram(EsMatrixActivity.this, "matrix_vertex.glsl", "matrix_fragment.glsl");}@Overridepublic void onSurfaceChanged(GL10 gl, int width, int height) {GLES30.glViewport(0, 0, width, height); // 设置输出屏幕大小float aspectRatio = width>height ? 1.0f*width/height : 1.0f*height/width;Matrix.setIdentityM(mProjectionMatrix, 0); // 初始化投影矩阵// 计算矩阵的正交投影Matrix.orthoM(mProjectionMatrix, 0, -1f, 1f, -aspectRatio, aspectRatio, -1f, 1f);}@Overridepublic void onDrawFrame(GL10 gl) {// 清除屏幕和深度缓存GLES30.glClear(GLES30.GL_COLOR_BUFFER_BIT | GLES30.GL_DEPTH_BUFFER_BIT);Matrix.setIdentityM(mModelMatrix, 0); // 初始化模型矩阵Matrix.rotateM(mModelMatrix, 0, mAngle,1f, 1f, 0.5f); // 旋转模型矩阵// 把投影矩阵和模型矩阵相乘,得到最终的变换矩阵Matrix.multiplyMM(mMVPMatrix, 0, mProjectionMatrix, 0, mModelMatrix, 0);// 获取顶点着色器的unMatrix位置int matrixLoc = GLES30.glGetUniformLocation(mProgramId, "unMatrix");// 输入变换矩阵信息GLES30.glUniformMatrix4fv(matrixLoc, 1, false, mMVPMatrix, 0);mAngle++;GLES30.glLineWidth(3); // 指定线宽if (mType == 0 || mType == 2) {drawCube(); // 绘制立方体} else if (mType == 1 || mType == 3) {drawBall(); // 绘制球体}}}// 绘制立方体private void drawCube() {// 获取顶点着色器的vPosition位置int positionLoc = GLES30.glGetAttribLocation(mProgramId, "vPosition");GLES30.glEnableVertexAttribArray(positionLoc); // 启用顶点属性数组for (FloatBuffer buffer : mVertexList) {// 指定顶点属性数组的信息GLES30.glVertexAttribPointer(positionLoc, 3, GLES30.GL_FLOAT, false, 0, buffer);// 绘制物体的轮廓线条GLES30.glDrawArrays(GLES30.GL_LINE_LOOP, 0, EsVertexUtil.getCubePointCount());}GLES30.glDisableVertexAttribArray(positionLoc); // 禁用顶点属性数组}// 绘制球体private void drawBall() {// 获取顶点着色器的vPosition位置int positionLoc = GLES30.glGetAttribLocation(mProgramId, "vPosition");GLES30.glEnableVertexAttribArray(positionLoc); // 启用顶点属性数组// 每次画两条相邻的纬度线for (int i = 0; i <= mDivide && i < mVertexList.size(); i++) {// 指定顶点属性数组的信息GLES30.glVertexAttribPointer(positionLoc, 3, GLES30.GL_FLOAT, false, 0, mVertexList.get(i));// 绘制物体的轮廓线条GLES30.glDrawArrays(GLES30.GL_LINE_STRIP, 0, mDivide * 2 + 2);}GLES30.glDisableVertexAttribArray(positionLoc); // 禁用顶点属性数组}@Overrideprotected void onPause() {super.onPause();glsv_content.onPause(); // 暂停绘制三维图形}@Overrideprotected void onResume() {super.onResume();glsv_content.onResume(); // 恢复绘制三维图形}}

XML文件

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical" ><LinearLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"android:orientation="horizontal" ><TextViewandroid:layout_width="0dp"android:layout_height="wrap_content"android:layout_weight="1"android:gravity="right"android:text="三维物体形状:"android:textColor="@color/black"android:textSize="17sp" /><Spinnerandroid:id="@+id/sp_shape"android:layout_width="0dp"android:layout_height="wrap_content"android:layout_weight="1"android:spinnerMode="dialog" /></LinearLayout><!-- 注意这里要使用控件的全路径android.opengl.GLSurfaceView --><android.opengl.GLSurfaceViewandroid:id="@+id/glsv_content"android:layout_width="match_parent"android:layout_height="400dp" /></LinearLayout>

创作不易 觉得有帮助请点赞关注收藏

Android App开发中OpenGL三维投影的讲解及实现(附源码和演示 简单易懂)相关推荐

  1. 【Android App】实战项目之仿微信的视频通话(附源码和演示 超详细必看)

    需要源码请点赞关注收藏后评论区留言私信~~~ 虽然手机出现许多年了,它具备的功能也越来越丰富,但是最基本的通话功能几乎没有变化.从前使用固定电话的时候,通话就是听声音:如今使用最新的智能手机,通话仍旧 ...

  2. Android App开发动画特效之利用滚动器实现平滑翻页(附源码和演示 简单易懂)

    需要图片集请点赞关注收藏后评论区留言~~~ 一.利用滚动器实现平滑翻页 在日常生活中,平移动画比较常见,有时也被称为位移动画,左右翻页和上下滚动其实都用到了平移动画,譬如平滑翻书的动画效果,就是位移动 ...

  3. Web 开发中很实用的10个效果【附源码下载】

    在工作中,我们可能会用到各种交互效果.而这些效果在平常翻看文章的时候碰到很多,但是一时半会又想不起来在哪,所以养成知识整理的习惯是很有必要的.这篇文章给大家推荐10个在 Web 开发中很有用的效果,记 ...

  4. Android Studio App开发入门之在活动之间传递消息(附源码 超详细必看)(包括显示和隐式Intent,向上一个和下一个Activity发送数据)

     运行有问题或需要源码请点赞关注收藏后评论区留言~~ 显示Intent和隐式Intent Intent是各个组件之间的信息沟通的桥梁,既能在Activity之间沟通,又能在Activity与Servi ...

  5. Android App开发实战项目之大头贴App功能实现(附源码和演示 简单易上手)

    需要图片集和源码请点赞关注收藏后评论区留言~~~ 一.需求描述 大头贴App有两个特征,第一个是头要大,拿来一张照片后把人像区域裁剪出来,这样新图片里的人头才会比较大,第二个是在周围贴上装饰物,而且装 ...

  6. Android AR开发实践之七:OpenGLES相机预览背景绘制源码详解

    Android AR开发实践之七:OpenGLES相机预览背景绘制源码详解 目录 Android AR开发实践之七:OpenGLES相机预览背景绘制源码详解 一.OpenGL ES渲染管线 1.基本处 ...

  7. 微信公众平台开发教程(四) 实例入门:机器人(附源码)

    微信公众平台开发教程(四) 实例入门:机器人(附源码) 上一篇文章,写了基本框架,可能很多人会觉得晕头转向,这里提供一个简单的例子来予以说明,希望能帮你解开谜团. 一.功能介绍 通过微信公众平台实现在 ...

  8. Android一行代码实现网络加载GIF闪图(附源码)

    最近项目有个需求是要从网络加载GIF闪图, 但是Android原生的ImageView并不支持Gif... 于是从网上看了些Dome, 发现总是有些这样那样的问题, 譬如: ☹ 没有缓存,还要自己写一 ...

  9. C#使用Xamarin开发可移植移动应用(3.Xamarin.Views控件)附源码

    .NET core2.0 发布了,刺激,大致看了一下,很不错,打算后期学习.(不出意外,应该也会写个小系列). 虽然官方推荐用共享类库创建新的类库..然而我这个Demo还是使用的可移植.. 嗯..解释 ...

最新文章

  1. CTO梁军离职,市值蒸发59亿,核心技术人才仅剩3人!寒武纪“动荡”的6周年
  2. Sharepoint之升级篇
  3. 挑战程序设计竞赛_实力爆棚!2019年,华中科技大学拿下亚洲区竞赛金牌4枚!...
  4. 表单提交数据大小的限制
  5. dns 主从 windows
  6. .net项目进不去后台解决
  7. idea 配置springmvc+mybatis(图文教程)
  8. linux启动项目报连不上mysql_Linux运维常见故障及处理的 32 个妙计
  9. Visual Studio的Node.js插件:NTVS 1.0正式发布
  10. 二进制数据(Image类型)从一个表存入另一个表
  11. Spring boot 解决 hibernate no session异常
  12. 【Spring笔记】Spring创建hello程序
  13. 使用ffmpeg 命令分割视频方法
  14. 拍拍抢拍精灵v2.1秒杀器所有源代码【开源】
  15. 会计信息质量可靠性的案例_会计信息可靠性的分析
  16. AD18运行PCB DRC显示一处警告, Design contains shelved or modified (but not repoured) polygons.
  17. 全开源即时通讯(IM)系统 高仿微信,android移动应用开发
  18. 【软件测试】小陈她的测试追梦之路,实习开端到测试第一人......
  19. 这位“华为天才少年”,竟然要我用“充电宝”打《只狼》
  20. Netty 大文件传输

热门文章

  1. 线性电源与开关电源的比较
  2. ps 置换滤镜制作文字人像
  3. 合同相似可逆等价矩阵的关系及性质_矩阵等价、合同、相似的联系与区别
  4. 收获节任务:缅怀英雄
  5. 大学四年自学走来,关于怎么学「操作系统」和「计算机网络」我贡献出来了!......
  6. mysql数据库合并游戏合服_[转载]浅谈滚服游戏如果实现一键合服
  7. 分析电车共享充电桩APP方案开发小程序系统的6种操作步骤
  8. HTML5期末大作业:烧烤美食网站设计——火锅烧烤美食山庄(7页) HTML+CSS+JavaScript 网页设计期末作业个人主页
  9. 微信小程序-同时获取麦克风、相机权限、获取多个权限
  10. java游戏boss是冰龙_那些令人难忘的龙形Boss!这款游戏里的龙居然有点小萌?