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

一、轮廓勾勒

勾勒三维物体轮廓线条的步骤如下:

(1)调用glEnableClientState方法启用顶点开关

(2)调用glVertexPointer方法指定三维物体的顶点坐标集合

(3)调用glDrawArrays方法在顶点坐标集合之间绘制点、线、面

(4)调用glDisableClientState方法禁用顶点开关

在三维坐标系中,每个点都有x,y,z三个方向上的坐标值,也即是需要三个浮点数来表示一个点,一个面又至少由三个不在一条直线上的点唯一确定,而四个点可以构成一个四边形。OpenGL使用浮点数组表达一块平面区域的时候,数组大小等于该面的顶点个数×3,也就是说,每三个浮点数用来指定一个顶点的x,y,z坐标值,所以总共需要三倍于顶点数量的浮点数才能表示这些顶点构成的平面

glDrawArrays的取值如下

glDrawArrays方法的绘制模式

说明

GL10.GL_POINTS

只描绘各个独立的点

GL10.GL_LINE_STRIP

前后两个顶点用线段连接,但不闭合(最后一个点与第一个点不连接)

GL10.GL_LINE_LOOP

前后两个顶点用线段连接,并且闭合(最后一个点与第一个点有连接)

GL10.GL_TRIANGLES

每隔三个顶点绘制一个三角形的平面

实战效果如下

旋转的立方体和球体演示动画已上传至个人主页 有需要可自行前往观看

代码如下

Java类

package com.example.threed;import android.opengl.GLSurfaceView;
import android.opengl.GLU;
import android.os.Bundle;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Spinner;import androidx.appcompat.app.AppCompatActivity;import com.example.threed.util.GlVertexUtil;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 GlLineActivity extends AppCompatActivity {private GLSurfaceView glsv_content; // 声明一个图形库表面视图对象private List<FloatBuffer> mVertexList = new ArrayList<>(); // 顶点列表private int mType; // 形状的类型private int mDivide = 20; // 将经纬度等分的面数private float mRadius = 4; // 球半径private int mAngle = 0; // 旋转角度@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_gl_line);initShapeSpinner(); // 初始化形状下拉框mVertexList = GlVertexUtil.getCubeVertexs();glsv_content = findViewById(R.id.glsv_content);// 给OpenGL的表面视图注册三维图形的渲染器glsv_content.setRenderer(new LineRender());// 设置渲染模式。默认的RENDERMODE_CONTINUOUSLY表示持续刷新,RENDERMODE_WHEN_DIRTY表示只有首次创建和调用requestRender方法时才会刷新glsv_content.setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY);//glsv_content.requestRender(); // 主动请求渲染操作}// 初始化形状下拉框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) {mVertexList = GlVertexUtil.getCubeVertexs(); // 获得立方体的顶点列表} else if (mType == 1 || mType == 3) {// 获得球体的顶点列表mVertexList = GlVertexUtil.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) {}}// 定义一个三维图形的渲染器private class LineRender implements GLSurfaceView.Renderer {// 在表面创建时触发@Overridepublic void onSurfaceCreated(GL10 gl, EGLConfig config) {// 设置白色背景。0.0f相当于00,1.0f相当于FFgl.glClearColor(1.0f, 1.0f, 1.0f, 1.0f);gl.glShadeModel(GL10.GL_SMOOTH); // 启用阴影平滑}// 在表面变更时触发@Overridepublic void onSurfaceChanged(GL10 gl, int width, int height) {gl.glViewport(0, 0, width, height); // 设置输出屏幕大小// 设置投影矩阵,对应gluPerspective(调整相机)、glFrustumf(透视投影)、glOrthof(正交投影)gl.glMatrixMode(GL10.GL_PROJECTION);gl.glLoadIdentity(); // 重置投影矩阵,即去掉所有的平移、缩放、旋转操作// 设置透视图视窗大小GLU.gluPerspective(gl, 40, (float) width / height, 0.1f, 20.0f);// 选择模型观察矩阵,对应gluLookAt(人动)、glTranslatef/glScalef/glRotatef(物动)gl.glMatrixMode(GL10.GL_MODELVIEW);gl.glLoadIdentity(); // 重置模型矩阵}// 执行框架绘制动作@Overridepublic void onDrawFrame(GL10 gl) {// 清除屏幕和深度缓存gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);gl.glLoadIdentity(); // 重置当前的模型观察矩阵gl.glColor4f(0.0f, 0.0f, 1.0f, 1.0f); // 设置画笔颜色// 设置观测点。eyeXYZ表示眼睛坐标,centerXYZ表示原点坐标,upX=1表示X轴朝上,upY=1表示Y轴朝上,upZ=1表示Z轴朝上GLU.gluLookAt(gl, 10.0f, 8.0f, 6.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f);// 旋转图形。围绕着Z轴与Y轴之间的平分线旋转gl.glRotatef(mAngle, 0, 0, -1);gl.glRotatef(mAngle, 0, -1, 0);mAngle++;// gl.glTranslatef(1, 0, 0); // 沿x轴方向移动1个单位// gl.glScalef(0.1f, 0.1f, 0.1f); // 沿x、y、z方向缩放0.1倍gl.glLineWidth(3); // 指定线宽if (mType == 0 || mType == 2) {drawCube(gl); // 绘制立方体} else if (mType == 1 || mType == 3) {drawBall(gl); // 绘制球体}}}// 绘制立方体private void drawCube(GL10 gl) {// 启用顶点开关。GL_VERTEX_ARRAY表示顶点数组,GL_COLOR_ARRAY表示颜色数组gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);for (FloatBuffer buffer : mVertexList) {// 将顶点坐标传给 OpenGL 管道gl.glVertexPointer(3, GL10.GL_FLOAT, 0, buffer);// 用画线的方式将点连接并画出来gl.glDrawArrays(GL10.GL_LINE_LOOP, 0, GlVertexUtil.getCubePointCount());}gl.glDisableClientState(GL10.GL_VERTEX_ARRAY); // 禁用顶点开关}// 绘制球体private void drawBall(GL10 gl) {gl.glEnableClientState(GL10.GL_VERTEX_ARRAY); // 启用顶点开关// 每次画两条相邻的纬度线for (int i = 0; i <= mDivide && i < mVertexList.size(); i++) {// 将顶点坐标传给 OpenGL 管道gl.glVertexPointer(3, GL10.GL_FLOAT, 0, mVertexList.get(i));// 用画线的方式将点连接并画出来gl.glDrawArrays(GL10.GL_LINE_STRIP, 0, mDivide * 2 + 2);}gl.glDisableClientState(GL10.GL_VERTEX_ARRAY); // 禁用顶点开关}@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】勾勒出三维立方体和球体以及它们的转动图形讲解及实战(附源码和演示视频 超详细)相关推荐

  1. 【Android App】给三维魔方贴图以及旋转动画讲解和实战(附源码和演示视频 超详细必看)

    需要源码请点赞关注收藏后评论区留言私信~~~ 一.给三维物体贴图 除了位置坐标.颜色向量和矩阵向量,着色器还支持声明材质坐标和纹理采样器. 其中材质坐标表示物体表面摊平后的二维空间,纹理采样器表示采用 ...

  2. 【Android App】利用腾讯地图获取地点信息和规划导航线路讲解及实战(附源码和演示视频 超详细必看)

    需要源码请点赞关注收藏后评论区留言~~~ 一.获取地点信息 至于如何集成腾讯地图和调用腾讯地图接口此处不再赘述,有需要请参见我之前的博客 腾讯地图用来搜索POI地点的工具是TencentSearch, ...

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

    需要全部代码请点赞关注收藏后评论区留言私信~~~ 手机最开始用于通话,后来增加了短信功能,初步满足了人与人之间的沟通需求.然而短信只能发文字,于是出现了能够发图片的彩信,但不管短信还是彩信,资费都太贵 ...

  4. 【Android App】实战项目之仿抖音的短视频分享App(附源码和演示视频 超详细必看)

    需要全部代码请点赞关注收藏后评论区留言私信~~~ 与传统的影视行业相比,诞生于移动互联网时代的短视频是个全新行业,它制作方便又容易传播,一出现就成为大街小巷的时髦潮流. 各行各业的人们均可通过短视频展 ...

  5. 【Android App】Vulkan实现宇宙中旋转雷达动画效果(附源码和原始视频 超详细必看)

    需要源码请点赞关注收藏后评论区留言私信~~~ 一.Vulkan简介 Vulkan是一个跨平台的图形绘制接口,被称为下一代OpenGL,因为尽管OpenGL提供了丰富的图形API,但他在底层实现的C代码 ...

  6. 【Android App】实战项目之虚拟现实(VR)的全景相册(附源码和演示视频 可用于学习和大作业)

    需要源码请点赞关注收藏后评论区留言私信~~~ 不管是绘画还是摄影,都是把三维的物体投影到平面上,其实仍旧呈现二维的模拟画面. 随着科技的发展,传统的成像手段越来越凸显出局限性,缘由在于人们需要一种更逼 ...

  7. 【Android App】实战项目之实现你问我答的智能语音机器人(超详细 附源码和演示视频)

    需要全部代码请点赞关注收藏后评论区留言私信~~~ 一.需求描述 想必大家都见过商场里的智能语音机器人,你对它提问时它可以自动回答你的问题,接下来我们也实现这样一个机器人,它依靠语音技术完成问询服务 基 ...

  8. Android App开发实战项目之模仿美图秀秀的抠图工具(附源码和演示视频 简单易懂 可直接使用)

    需要图片集和源码请点赞关注收藏后评论区留言~~~ 所谓抠图神器,就是从一副图片中扣出用户想要的某块区域 一.需求描述 美图的修图功能如此强大,离不开专业的图片加工技术,抠图便是其中重要的一项功能.在A ...

  9. Android App开发实战项目之仿喜马拉雅的听说书App实现(超详细 附源码和演示视频)

    需要全部源码请点赞关注收藏后评论区留下QQ~~~ 一.需求分析 用户不仅能在平台上收听音频,还能成为内容创作者,总之长音频分享平台需要满足两种角色的使用:一种是作为内容创作者发布自己的音频,另一种是作 ...

最新文章

  1. 手把手教你使用Flex 3——《Flex 3程序设计》
  2. 【数理知识】《随机过程》方兆本老师-第6章-鞅过程及其性质
  3. javascript(js)获取访客通过搜索引擎进入页面的搜索关键词的简洁有效代码
  4. linux 4412跑程序,荣品4412的板子上跑纯linux
  5. 利用Mybatis写第一个数据库操作的程序
  6. 数列分段II(信息学奥赛一本通-T1436)
  7. 螺旋进刀非法平面选择_进刀方法、刀片类型、术语...螺纹加工重点知识你都知道吗?...
  8. 哪些手机支持双wifi?
  9. 玩转Spring Boot 集成Dubbo
  10. python与办公自动化-python办公自动化:自动进行word文档处理和排版
  11. Firefly III 搭建个人财务记账平台
  12. Qt通过ODBC连接opengauss数据库
  13. 一张图看懂“火星坐标系”
  14. 中国车牌号的分类说明识别及含义
  15. 金蝶检测服务器响应异常,连接金蝶云服务器异常 请检查
  16. Win10+Ubuntu18.04双系统安装配置教程(二)——磁盘分区
  17. 免费远程控制软件新功能
  18. git push origin HEAD
  19. 作为一位资深Java程序员应该注意的几点
  20. Redis 查看端口使用情况

热门文章

  1. java 1.8 x64_JRE1.8 64位下载_JRE 8u202 windows x64下载 1.8.0-202 x64_当载软件站
  2. Xodo PDF一些选项的意思
  3. 【米斯特吴】2021年全年系列课程包(Vue/React/Node/大厂面试)
  4. PIC单片机中断服务程序
  5. [宋史学习] 赵光义对西夏的一系列错误
  6. dos.bat 批处理文件的应用——批量压缩
  7. 全志哪吒D1-H Tina Linux Ubuntu 22.04入门踩坑日记
  8. 圣诞节暖心邮件 贺卡 礼物都给你准备好了 外贸人请查收
  9. 高考测试分数软件,高考分数查询软件
  10. Andriod开发 GridView