【Android App】勾勒出三维立方体和球体以及它们的转动图形讲解及实战(附源码和演示视频 超详细)
创始人
2024-02-25 15:48:15
0

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

一、轮廓勾勒

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

(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 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 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文件

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

相关内容

热门资讯

监控摄像头接入GB28181平... 流程简介将监控摄像头的视频在网站和APP中直播,要解决的几个问题是:1&...
Windows10添加群晖磁盘... 在使用群晖NAS时,我们需要通过本地映射的方式把NAS映射成本地的一块磁盘使用。 通过...
protocol buffer... 目录 目录 什么是protocol buffer 1.protobuf 1.1安装  1.2使用...
Fluent中创建监测点 1 概述某些仿真问题,需要创建监测点,用于获取空间定点的数据࿰...
educoder数据结构与算法...                                                   ...
MySQL下载和安装(Wind... 前言:刚换了一台电脑,里面所有东西都需要重新配置,习惯了所...
MFC文件操作  MFC提供了一个文件操作的基类CFile,这个类提供了一个没有缓存的二进制格式的磁盘...
在Word、WPS中插入AxM... 引言 我最近需要写一些文章,在排版时发现AxMath插入的公式竟然会导致行间距异常&#...
有效的括号 一、题目 给定一个只包括 '(',')','{','}'...
【Ctfer训练计划】——(三... 作者名:Demo不是emo  主页面链接:主页传送门 创作初心ÿ...