【libGDX】使用Mesh绘制立方体

1 前言

        本文主要介绍使用 Mesh 绘制立方体,读者如果对 Mesh 不太熟悉,请回顾以下内容:

  • 使用Mesh绘制三角形
  • 使用Mesh绘制矩形
  • 使用Mesh绘制圆形

        在绘制立方体的过程中,主要用到了 MVP (Model View Projection)矩阵变换。

  • Model:模型变换,施加在模型上的空间变换,包含平移变换(translateM)、旋转变换(rotateM)、对称变换(transposeM)、缩放变换(scaleM);
  • View:观察变换,施加在观察点上的变换,用于调整观察点位置、观察朝向、观察正方向;
  • Projection:透视变换,施加在视觉上的变换,用于调整模型的透视效果(如:矩形的透视效果是梯形)。

        上述变换依次叠加,得到一个总的变换矩阵,即 MVP 变换矩阵,mvpMatrix = projectionMatrix * viewMatrix * modelMatrix,MVP 变换作用到模型的原始坐标矩阵上,得到的最终坐标矩阵即为用户观测到的模型状态。 

        对于立体图形的绘制,绘制前需要清除深度缓存,并开启深度测试,如下。

Gdx.gl.glClear(GL30.GL_COLOR_BUFFER_BIT | GL30.GL_DEPTH_BUFFER_BIT);
Gdx.gl.glEnable(GL30.GL_DEPTH_TEST);

2 绘制立方体

        本节将使用 Mesh、ShaderProgram、Shader 绘制立方体,OpenGL ES 的实现见博客 → 绘制立方体。

        DesktopLauncher.java

package com.zhyan8.game;

import com.badlogic.gdx.backends.lwjgl3.Lwjgl3Application;
import com.badlogic.gdx.backends.lwjgl3.Lwjgl3ApplicationConfiguration;

public class DesktopLauncher {
	public static void main (String[] arg) {
		Lwjgl3ApplicationConfiguration config = new Lwjgl3ApplicationConfiguration();
		config.setForegroundFPS(60);
		config.setTitle("Cube");
		new Lwjgl3Application(new Cube(), config);
	}
}

        Cube.java

package com.zhyan8.game;

import com.badlogic.gdx.ApplicationAdapter;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.GL30;
import com.badlogic.gdx.graphics.Mesh;
import com.badlogic.gdx.graphics.PerspectiveCamera;
import com.badlogic.gdx.graphics.VertexAttribute;
import com.badlogic.gdx.graphics.VertexAttributes.Usage;
import com.badlogic.gdx.graphics.glutils.ShaderProgram;
import com.badlogic.gdx.math.Matrix4;
import com.badlogic.gdx.math.Vector3;

public class Cube extends ApplicationAdapter {
	private PerspectiveCamera mCamera;
	private ShaderProgram mShaderProgram;
	private Mesh mMesh;
	private Vector3 mRotateAxis; // 旋转轴
	private int mRotateAgree = 0; // 旋转角度
	Matrix4 mModelMatrix; // 模型变换矩阵

	@Override
	public void create() {
		initCamera();
		initShader();
		initMesh();
		mRotateAxis = new Vector3(0.3f, 0.5f, 0.7f);
		mModelMatrix = new Matrix4();
	}

	@Override
	public void render() {
		Gdx.gl.glClearColor(0.455f, 0.725f, 1.0f, 1.0f);
		Gdx.gl.glClear(GL30.GL_COLOR_BUFFER_BIT | GL30.GL_DEPTH_BUFFER_BIT);
		Gdx.gl.glEnable(GL30.GL_DEPTH_TEST);
		mShaderProgram.bind();
		transform();
		mMesh.render(mShaderProgram, GL30.GL_TRIANGLES);
	}

	@Override
	public void dispose() {
		mShaderProgram.dispose();
		mMesh.dispose();
	}

	private void initCamera() { // 初始化相机
		mCamera = new PerspectiveCamera(67, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
		mCamera.near = 0.3f;
		mCamera.far = 1000f;
		mCamera.position.set(0f, 0f, 2.5f);
		mCamera.lookAt(0, 0, 0);
		mCamera.update();
	}

	private void initShader() { // 初始化着色器程序
		String vertex = Gdx.files.internal("shaders/cube_vertex.glsl").readString();
		String fragment = Gdx.files.internal("shaders/cube_fragment.glsl").readString();
		mShaderProgram = new ShaderProgram(vertex, fragment);
	}

	private void initMesh() { // 初始化网格
		float[] vertices = getVertices(0.5f, 1.0f);
		short[] indices = getIndices();
		VertexAttribute vertexPosition = new VertexAttribute(Usage.Position, 3, "a_position");
		VertexAttribute colorPosition = new VertexAttribute(Usage.ColorUnpacked, 4, "a_color");
		mMesh = new Mesh(true, vertices.length / 7, indices.length, vertexPosition, colorPosition);
		mMesh.setVertices(vertices);
		mMesh.setIndices(indices);
	}

	private void transform() { // MVP矩阵变换
		mRotateAgree = (mRotateAgree + 2) % 360;
		mModelMatrix.idt(); // 模型变换矩阵单位化
		mModelMatrix.rotate(mRotateAxis, mRotateAgree);
		Matrix4 mvpMatrix = mModelMatrix.mulLeft(mCamera.combined);
		mShaderProgram.setUniformMatrix("u_mvpTrans", mvpMatrix);
	}

	private float[] getVertices(float r, float c) { // 获取顶点数据
		float[] vertex = new float[] {
				r, r, r, c, c, c, 1, //0
				-r, r, r, 0, c, c, 1, //1
				-r, -r, r, 0, 0, c, 1, //2
				r, -r, r, c, 0, c, 1, //3
				r, r, -r, c, c, 0, 1, //4
				-r, r, -r, 0, c, 0, 1, //5
				-r, -r, -r, 0, 0, 0, 1, //6
				r, -r, -r, c, 0, 0, 1 //7
		};
		return vertex;
	}

	private short[] getIndices() { // 获取三角形顶点索引序列
		short[] indices = new short[] {
				0, 1, 2, 0, 2, 3, //前面
				0, 5, 1, 0, 4, 5, //上面
				0, 3, 7, 0, 7, 4, //右面
				6, 5, 4, 6, 4, 7, //后面
				6, 3, 2, 6, 7, 3, //下面
				6, 2, 1, 6, 1, 5 //左面
		};
		return indices;
	}
}

        cube_vertex.glsl

#version 300 es

in vec3 a_position;
in vec4 a_color;

uniform mat4 u_mvpTrans; // MVP矩阵变换

out vec4 v_color;

void main() {
    gl_Position = u_mvpTrans * vec4(a_position, 1.0);
    v_color = a_color;
}

        cube_fragment.glsl

#version 300 es
precision mediump float; // 声明float型变量的精度为mediump

in vec4 v_color;

out vec4 fragColor;

void main() {
    fragColor = v_color;
}

        运行效果如下。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Javaweb之前后台分离开发介绍的详细解析

2.1 前后台分离开发介绍 在之前的课程中,我们介绍过,前端开发有2种方式:前后台混合开发和前后台分离开发。 前后台混合开发,顾名思义就是前台后台代码混在一起开发,如下图所示: 这种开发模式有如下缺点&a…

C++11『lambda表达式 ‖ 线程库 ‖ 包装器』

✨个人主页: 北 海 🎉所属专栏: C修行之路 🎃操作环境: Visual Studio 2022 版本 17.6.5 文章目录 🌇前言🏙️正文1.lambda表达式1.1.仿函数的使用1.2.lambda表达式的语法1.3.lambda表达式的使用…

C/C++ 开发SCM服务管理组件

SCM(Service Control Manager)服务管理器是 Windows 操作系统中的一个关键组件,负责管理系统服务的启动、停止和配置。服务是一种在后台运行的应用程序,可以在系统启动时自动启动,也可以由用户或其他应用程序手动启动。…

win10戴尔电脑安装操作系统遇到的问题MBR分区表只能安装GPT磁盘

首先按F2启动boot管理界面 调整启动盘的启动顺序,这里启动U盘为第一顺序。 第一步 选择安装程序的磁盘 第二步 转换磁盘为GPT磁盘 一般出现 磁盘0和1,说明存在两个盘 ,这里两个盘不是说的是C盘和D盘的问题,而是在物理上实际存在…

2024年度投资策略:AI大模型和半导体国产化加速

今天分享的是AI系列深度研究报告:《2024年度投资策略:AI大模型和半导体国产化加速》。 (报告出品方:东方证券) 报告共计:48页 前言: 行情回顾与未来展望 电子板块涨幅转正,信心逐渐回归。截至…

Ps:参考线

参考线 Guides用于帮助精确地定位图像或元素,显示为浮动在图像上的非打印线,可以移动或移除,还可以临时锁定。 Ps 中的参考线可分为三大类:画布参考线、画板参考线和智能参考线。 可在“首选项/参考线、网格和切片”中设置参考线的…

【Java线程通信】一窥究竟

今天我们要聊一聊Java线程通信。如果你是一个Java开发者,那么你肯定知道线程是Java中的一个重要概念。线程是程序执行的最小单位,它可以独立运行,也可以与其他线程共享资源。那么,线程之间如何进行通信呢?这就是我们今…

【uniapp】部分图标点击事件无反应

比如:点击这个图标在h5都正常,在小程序上无反应 css:也设置z-index,padding 页面上也试过click.native.stop.prevent"changePassword()" 时而可以时而不行, 最后发现是手机里输入键盘的原因,输…

文心一言 VS 讯飞星火 VS chatgpt (141)-- 算法导论12.1 1题

一、用go语言,对于关键字集合(1,4,5,10,16,17,21),分别画出高度为 2、3、4、5和6的二又搜索树。 文心一言: 以下是用Go语言为给定的关键字集合(1, 4, 5, 10, 16, 17, 2…

马养殖场建设VR模拟实训教学平台具有灵活性和复用性

为保障养殖场生物安全,避免疫病传播,学生出入养殖场受时间和地域的限制, 生产实习多以参观为主,通过畜牧企业技术人员的讲解,学生被动了解生产过程。为了解决畜牧养殖实训难的问题,借助VR技术开展畜牧养殖虚…

CUDA与GPU编程

文章目录 CUDA与GPU编程1. 并行处理与GPU体系架构1.1 并行处理简介1.1.1 串行处理与并行处理的区别1.1.2 并行处理的概念1.1.3 常见的并行处理 1.2 GPU并行处理1.2.1 GPU与CPU并行处理的异同1.2.2 CPU的优化方式1.2.3 GPU的特点 1.3 环境搭建 CUDA与GPU编程 1. 并行处理与GPU体…

关于easy-es的聚合问题

es实体类&#xff1a; public class ChemicalES {IndexId(type IdType.CUSTOMIZE)private Long id;HighLightIndexField(fieldType FieldType.TEXT, analyzer "ik_max_word")private String name;IndexField(fieldType FieldType.KEYWORD)private List<Stri…

某60区块链安全之未初始化的存储指针实战一学习记录

区块链安全 文章目录 区块链安全未初始化的存储指针实战一实验目的实验环境实验工具实验原理实验过程 未初始化的存储指针实战一 实验目的 学会使用python3的web3模块 学会分析以太坊智能合约未初始化的存储指针漏洞 找到合约漏洞进行分析并形成利用 实验环境 Ubuntu18.04操…

Vue3 封装组件库并发布到npm仓库

一、创建 Vue3 TS Vite 项目 输入项目名称&#xff0c;并依次选择需要安装的依赖项 npm create vuelatest 项目目录结构截图如下&#xff1a; 二、编写组件代码、配置项和本地打包测试组件 在项目根目录新建 package 文件夹用于存放组件 &#xff08;以customVideo为例&a…

HTTPS攻击怎么防御?

HTTPS 简介 超文本传输安全协议&#xff08; HTTPS &#xff09;是一种通过计算机网络进行安全通信的传输协议。HTTPS 经由 HTTP 进行通信&#xff0c;但利用 SSL/TLS 来加密数据包。 HTTPS 开发的主要目的&#xff0c;是提供对网站服务器的身份认证&#xff0c;保护交换数据的…

【开源】基于Vue.js的数据可视化的智慧河南大屏

项目编号&#xff1a; S 059 &#xff0c;文末获取源码。 \color{red}{项目编号&#xff1a;S059&#xff0c;文末获取源码。} 项目编号&#xff1a;S059&#xff0c;文末获取源码。 目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块三、系统展示四、核心代码4.1 数据模块 …

基于遗传优化的多属性判决5G-Wifi网络切换算法matlab仿真

目录 1.算法运行效果图预览 2.算法运行软件版本 3.部分核心程序 4.算法理论概述 5.算法完整程序工程 1.算法运行效果图预览 2.算法运行软件版本 MATLAB2022a 3.部分核心程序 .......................................................................... %接收功率、网…

浅谈 Guava 中的 ImmutableMap.of 方法的坑

作者&#xff1a;明明如月学长&#xff0c; CSDN 博客专家&#xff0c;大厂高级 Java 工程师&#xff0c;《性能优化方法论》作者、《解锁大厂思维&#xff1a;剖析《阿里巴巴Java开发手册》》、《再学经典&#xff1a;《EffectiveJava》独家解析》专栏作者。 热门文章推荐&…

练习七-在Verilog中使用任务task

在Verilog中使用任务task 1&#xff0c;任务目的2&#xff0c;RTL代码&#xff0c;交换3&#xff0c;测试代码4&#xff0c;波形显示 1&#xff0c;任务目的 &#xff08;1&#xff09;掌握任务在verilog模块设计中的应用&#xff1b; &#xff08;2&#xff09;学会在电平敏感…

新一代网络监控技术——Telemetry

一、Telemetry的背景 传统的网络设备监控方式有SNMP、CLI、Syslog、NetStream、sFlow&#xff0c;其中SNMP为主流的监控数据方式。而随着网络系统规模的扩大&#xff0c;网络设备数量的增多&#xff0c;网络结构的复杂&#xff0c;相应监控要求也不断提升&#xff0c;如今这些…