【libGDX】立方体手动旋转

1 前言

        本文主要介绍使用 libGDX 绘制立方体,并实现手动触摸事件控制立方体旋转。 

        为方便控制触摸旋转,并提高渲染性能,我们通过改变相机的位置和姿态实现立方体旋转效果。

        读者如果对 libGDX 不太熟悉,请回顾以下内容。

  • 使用Mesh绘制三角形
  • 使用Mesh绘制矩形
  • 使用Mesh绘制圆形
  • 使用Mesh绘制立方体
  • Mesh立方体贴图(6张图)

2 立方体手动旋转

        本节将使用 Mesh、ShaderProgram、Shader、InputAdapter 实现立方体手动旋转,OpenGL ES 的实现见博客 → 立方体手动旋转,本节完整代码资源见 → libGDX立方体手动旋转。

        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("RotateCube");
		new Lwjgl3Application(new RotateCube(), config);
	}
}

        RotateCube.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.VertexAttribute;
import com.badlogic.gdx.graphics.VertexAttributes.Usage;
import com.badlogic.gdx.graphics.glutils.ShaderProgram;

public class RotateCube extends ApplicationAdapter {
	private ShaderProgram mShaderProgram;
	private Mesh mMesh;
	private CameraController mCameraController;

	@Override
	public void create() {
		initShader();
		initMesh();
		mCameraController = new CameraController();
	}

	@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();
		mShaderProgram.setUniformMatrix("u_mvpTrans", mCameraController.combined());
		renderCube();
	}

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

	private void renderCube() { // 渲染立方体
		for (int i = 0; i < 6; i++) {
			mMesh.render(mShaderProgram, GL30.GL_TRIANGLE_FAN, i * 4, 4);
		}
	}

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

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

        CameraController.java

package com.zhyan8.game;

import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.InputAdapter;
import com.badlogic.gdx.graphics.PerspectiveCamera;
import com.badlogic.gdx.math.Matrix4;
import com.badlogic.gdx.math.Vector3;

public class CameraController {
    private PerspectiveCamera mCamera;

    public CameraController() {
        mCamera = new PerspectiveCamera(67, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
        mCamera.near = 0.3f;
        mCamera.far = 1000f;
        mCamera.position.set(0f, 0f, 4f);
        mCamera.lookAt(0, 0, 0);
        mCamera.update();
        Gdx.input.setInputProcessor(mInputAdapter);
    }

    public Matrix4 combined() {
        return mCamera.combined;
    }

    private void updateCamera(float deltaX, float deltaY) {
        Vector3 right = mCamera.up.cpy();
        right.crs(mCamera.direction);
        Vector3 vec1 = new Vector3(right.x * deltaX, right.y * deltaX, right.z * deltaX);
        Vector3 vec2 = new Vector3(mCamera.up.x * deltaY, mCamera.up.y * deltaY, mCamera.up.z * deltaY);
        vec1.add(vec2).crs(mCamera.direction);
        float angle = (float) Math.sqrt(deltaX * deltaX + deltaY * deltaY);
        mCamera.rotateAround(Vector3.Zero, vec1, angle);
        //mCamera.lookAt(Vector3.Zero);
        mCamera.update();
    }

    private InputAdapter mInputAdapter = new InputAdapter() {
        private float mPreX = 0;
        private float mPreY = 0;

        @Override
        public boolean touchDown(int screenX, int screenY, int pointer, int button) {
            mPreX = screenX;
            mPreY = screenY;
            return true;
        }

        @Override
        public boolean touchDragged(int screenX, int screenY, int pointer) {
            float offsetX = screenX - mPreX;
            float offsetY = screenY - mPreY;
            updateCamera(offsetX * 0.3f, offsetY * 0.3f);
            mPreX = screenX;
            mPreY = screenY;
            return true;
        }
    };
}

        Model.java

package com.zhyan8.game;

public class Model {
    private static float r = 1.0f;

    public static float[] vertices = new float[] {
            // 前面
            r, r, r, 0.92f, 0.30f, 0.29f, 1.0f, // 0
            -r, r, r, 0.92f, 0.30f, 0.29f, 1.0f, // 1
            -r, -r, r, 0.92f, 0.30f, 0.29f, 1.0f, // 2
            r, -r, r, 0.92f, 0.30f, 0.29f, 1.0f, // 3
            // 后面
            r, r, -r, 0.93f, 0.57f, 0.17f, 1.0f, // 4
            -r, r, -r, 0.93f, 0.57f, 0.17f, 1.0f, // 5
            -r, -r, -r, 0.93f, 0.57f, 0.17f, 1.0f, // 6
            r, -r, -r, 0.93f, 0.57f, 0.17f, 1.0f, // 7
            // 上面
            r, r, r, 1.0f, 1.0f, 1.0f, 1.0f, // 8
            r, r, -r, 1.0f, 1.0f, 1.0f, 1.0f, // 9
            -r, r, -r, 1.0f, 1.0f, 1.0f, 1.0f, // 10
            -r, r, r, 1.0f, 1.0f, 1.0f, 1.0f, // 11
            // 下面
            r, -r, r, 0.99f, 0.95f, 0.0f, 1.0f, // 12
            r, -r, -r, 0.99f, 0.95f, 0.0f, 1.0f, // 13
            -r, -r, -r, 0.99f, 0.95f, 0.0f, 1.0f, // 14
            -r, -r, r, 0.99f, 0.95f, 0.0f, 1.0f, // 15
            // 右面
            r, r, r, 0.11f, 0.61f, 0.98f, 1.0f, // 16
            r, r, -r, 0.11f, 0.61f, 0.98f, 1.0f, // 17
            r, -r, -r, 0.11f, 0.61f, 0.98f, 1.0f, // 18
            r, -r, r, 0.11f, 0.61f, 0.98f, 1.0f, // 19
            // 左面
            -r, r, r, 0.15f, 0.87f, 0.50f, 1.0f, // 20
            -r, r, -r, 0.15f, 0.87f, 0.50f, 1.0f, // 21
            -r, -r, -r, 0.15f, 0.87f, 0.50f, 1.0f, // 22
            -r, -r, r, 0.15f, 0.87f, 0.50f, 1.0f // 23
    };

    public static short[] indices = new short[] {
            0, 1, 2, 3, // 前面
            4, 5, 6, 7, // 上面
            8, 9, 10, 11, // 右面
            12, 13, 14, 15, // 后面
            16, 17, 18, 19, // 下面
            20, 21, 22, 23 // 左面
    };
}

        square_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;
}

        square_fragment.glsl

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

in vec4 v_color;

out vec4 fragColor;

void main() {
    fragColor = v_color;
}

        运行效果如下。

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

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

相关文章

11.31链表,之前的数据结构(未完,饼)

根据输入序列建立二叉树 链表 回顾一下二分面积最小 一些性质题回顾 哈夫曼树构建 第十一周——哈夫曼树 5 1 2 2 5 9 37 桶排序 #include <iostream> #include <vector> #include <algorithm> #include<stack> #include<queue> #includ…

docker部署kerberos,群晖nas中nfs开启kerberos校验

背景 nas开启nfs存储共享&#xff0c;默认情况下只能给IP/24做限制, 达不到安全效果 需要增加kerberos策略校验&#xff0c;并且持久化kerberos数据&#xff0c;避免容器重启丢失数据 环境描述 宿主机系统&#xff1a;CentOS Linux release 7.9.2009 (Core) Docker版本&#xf…

ESP32-Web-Server编程- 实现 Web 登录网页

ESP32-Web-Server编程- 实现 Web 登录网页 概述 是时候实现更加安全的网页了。登录机制是最简单的控制网页访问权限的方法。 需求及功能解析 本节演示如何在 ESP32 上部署一个 Web 服务器&#xff0c;并建立登录页面的机制&#xff0c;用户可以实现登录、登出的功能&#x…

【Python表白限定】李峋同款可写字版跳动的爱心(完整代码)

文章目录 跳动的爱心环境需求完整代码详细分析系列文章 跳动的爱心 环境需求 python3.11.4PyCharm Community Edition 2023.2.5pyinstaller6.2.0&#xff08;可选&#xff0c;这个库用于打包&#xff0c;使程序没有python环境也可以运行&#xff0c;如果想发给好朋友的话需要这…

nginx配置反向代理及负载均衡

目录 1.前端发送的请求&#xff0c;是如何请求到后端服务的1.nginx 反向代理的好处&#xff1a;2.nginx 反向代理的配置方式&#xff1a;3. nginx 负载均衡的配置方式 1.前端发送的请求&#xff0c;是如何请求到后端服务的 1.nginx 反向代理的好处&#xff1a; 提高访问速度 因…

一文解决msxml3.dll文件缺失问题,快速修复msxml3.dll

在了解问题之前&#xff0c;我们必须首先清楚msxml3.dll到底是什么。DLL&#xff08;Dynamic Link Libraries&#xff09;文件是Windows操作系统使用的一个重要组成部分&#xff0c;用于存储执行特定操作或任务的代码和数据。msxml3.dll为Windows系统提供处理XML文档的功能。如…

小米摄像头拆机教程

今天拆解一下好久不用的小米摄像头&#xff0c;记录下拆机过程&#xff0c;有需要的小伙伴可以自行查看 一、拆底座 首先拿出底座的四个橡皮塞、把对应的螺丝拧下来就可以了&#xff0c;这一步还是比较简单的 二、拆下底部排线 三、拆下底部电机和底座 按下方的红圈拆掉电机上的…

全网最新最全的Jmeter接口测试:jmeter组件元件介绍

JMeter 的主要测试组件总结如下&#xff1a; 1. 测试计划是使用 JMeter 进行测试的起点&#xff0c;它是其它 JMeter 测试元件的容器 2. 线程组代表一定数量的并发用户&#xff0c;它可以用来模拟并发用户发送请求。实际的 请求内容在Sampler中定义&#xff0c;它被线程组包含…

Redis主从复制实现RCE

文章目录 前置知识概念redis module 利用条件利用工具思路例题 [网鼎杯 2020 玄武组]SSRFMe 前置知识 概念 背景是多台服务器要保存同一份数据&#xff0c;如何实现其一致性呢&#xff1f;数据的读写操作是否每台服务器都可以处理&#xff1f;这里Redis就提供了主从复制的模式…

c++ pcl出现LNK2019 宏定义 PCL_NO_PRECOMPILE

问题&#xff1a;c pcl使用拟合圆柱时出现LNK2019问题&#xff1b; 说明&#xff1a;lib等配置没有问题&#xff1b; 解决方案 在上述代码中添加如下代码即可 #define PCL_NO_PRECOMPILE 是 C 中的预处理器指令&#xff0c;用于在代码中定义一个宏。而 #undef PCL_NO_PRECOM…

汽车行驶不同工况数据

1、内容简介 略 28-可以交流、咨询、答疑 2、内容说明 汽车行驶不同工况数据 汽车行驶不同工况数据 ECE、EUDC、FTP75、NEDC、自定义 3、仿真分析 4、参考论文 略 链接&#xff1a;https://pan.baidu.com/s/1AAJ_SlHseYpa5HAwMJlk1w 提取码&#xff1a;rvol

Unittest自动化测试之unittestunittest_生成测试报告

unittest_生成测试报告 测试报告为测试结果的统计即展示&#xff0c;是自动化测试不可或缺的一部分&#xff0c;利用unittest 可以生成测试报告 方式一、使用第三方 HTMLTestRunner 执行测试用例集&#xff0c;生成网页版测试报告&#xff08;推荐&#xff09; HTMLTestRunn…

进程与线程的区别

作者简介&#xff1a; zoro-1&#xff0c;目前大二&#xff0c;正在学习Java&#xff0c;数据结构,mysql,javaee等 作者主页&#xff1a; zoro-1的主页 欢迎大家点赞 &#x1f44d; 收藏 ⭐ 加关注哦&#xff01;&#x1f496;&#x1f496; 进程与线程的区别 进程线程进程与线…

Java流处理之序列化和打印流

文章目录 序列化概述ObjectOutputStream类构造方法序列化操作 ObjectInputStream类构造方法反序列化操作1**反序列化操作2** 案例&#xff1a;序列化集合案例分析案例实现 打印流概述PrintStream类构造方法改变打印流向 序列化 概述 Java 提供了一种对象序列化的机制。用一个…

回顾Django的第二天

1.http 1.1http请求协议与响应协议 1.1.1简介 http协议包含由浏览器发送数据到服务器需要遵循的请求协议与服务器发送数据到浏览器需要遵循的请求协议。用于HTTP协议交互的信被为HTTP报文。请求端(客户端)的HTTP报文 做请求报文,响应端(服务器端)的 做响应报文。HTTP报文本身…

Linux5-计划任务、进程

计划任务 一、cron 计划任务 周期性计划任务 cron 任务概述 • 用途:按照设置的时间间隔为用户反复执行某一项固定的系统任务 • 软件包&#xff1a;cronie、crontabs • 系统服务&#xff1a;crond • 日志文件&#xff1a;/var/log/crond 管理计划任务策略 • 使用 cro…

threejs教程

应群友要求出了个小白教程&#xff0c;此外也有进阶教程。 替代之前老版本的教程。 教程案例&#xff1a; 新教程地址&#xff1a;https://www.wellyyss.cn/ys-course/#/ 教程使用的是react搭建的 高级教程主要是案例 年底比较忙估计要晚一点才整合。 后续的计划是&#xff1…

三、Linux高级命令

目录 1、重定向命令 1.1 重定向 > 1.2 重定向 >> 该章节的所有操作都在/export/data/shell目录进行&#xff0c;请提前创建该目录。 mkdir -p /export/data/ 1、重定向命令 1.1 重定向 > Linux 允许将命令执行结果重定向到一个文件&#xff0c;本应显示在…

Ubuntu18.04 Udacity project_9_PID_control 如何运行

工程源码和仿真器下载&#xff1a; 源码 仿真器 --- Ubuntu就下载 term2_sim_linux.zip 这个压缩文件即可 紧接着给方框中的文件赋可执行权限 打开project_9_PID_control文件夹 执行如下脚本&#xff0c;安装必要的库&#xff0c;比如websocket&#xff08;程序生成的可执行…

nagios 监控dell设备(网上相关内容较少,特意留档)

#创作灵感#记录工作实践、项目复盘 错误信息&#xff1a; a.Unable to get status information due to technical issues. b.Dell EMC device discovery is in progress... Error: Empty or Invalid Passphrase is configured c.Error: Path not configured for the macro …