只完成了4个面,剩下2面
代码
OpenGL 魔方
#pragma once
#include <glad/glad.h>
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
#include <vector>
#include <Class/Shader/Shader.h>
namespace CubeN {
// 定义一个枚举类型,表示方向。其中FRONT表示前,BACK表示后,UP表示上,DOWN表示下,LEFT表示左,RIGHT表示右
enum Direction {
FRONT, // 前
BACK, // 后
UP, // 上
DOWN, // 下
LEFT, // 左
RIGHT // 右
};
// 定义一个结构体,表示魔方的颜色。其中front表示前面的颜色,back表示后面的颜色,up表示上面的颜色,down表示下面的颜色,left表示左边的颜色,right表示右边的颜色
static struct MagicCubeColor
{
glm::vec3 front = glm::vec3(1.0f, 1.0f, 1.0f); // 前面的颜色为白色
glm::vec3 back = glm::vec3(1.0f, 0.0f, 0.0f); // 后面的颜色为红色
glm::vec3 up = glm::vec3(1.0f, 1.0f, 0.0f); // 上面的颜色为黄色
glm::vec3 down = glm::vec3(0.0f, 1.0f, 0.0f); // 下面的颜色为绿色
glm::vec3 left = glm::vec3(0.0f, 0.0f, 1.0f); // 左边的颜色为蓝色
glm::vec3 right = glm::vec3(0.83f, 0.0f, 1.0f); // 右边的颜色为紫色
};
// 定义一个结构体,表示魔方的位置和顶点属性。其中VAO表示顶点属性对象,VBO表示顶点缓冲对象,position表示魔方的位置
struct MagicCubeStruct
{
unsigned int VAO, VBO;
int count;
Direction direction[3];
bool isRotating = false;
glm::vec3 color[3];
glm::vec3 position;
};
struct MagicCubeStructInd {
float front[9];
float back[9];
float up[9];
float down[9];
float left[9];
float right[9];
};
class MagicCube
{
private:
float* PCube;
int CubeSize;
float Cube[216] = {
// 前面
1.0f, -1.0f, 1.0f, 0.5f, 0.5f, 0.5f,
-1.0f, -1.0f, 1.0f, 0.5f, 0.5f, 0.5f,
1.0f, 1.0f, 1.0f, 0.5f, 0.5f, 0.5f,
-1.0f, -1.0f, 1.0f, 0.5f, 0.5f, 0.5f,
-1.0f, 1.0f, 1.0f, 0.5f, 0.5f, 0.5f,
1.0f, 1.0f, 1.0f, 0.5f, 0.5f, 0.5f,
// 后面
-1.0f, 1.0f, -1.0f, 0.5f, 0.5f, 0.5f,
-1.0f, -1.0f, -1.0f, 0.5f, 0.5f, 0.5f,
1.0f, -1.0f, -1.0f, 0.5f, 0.5f, 0.5f,
1.0f, -1.0f, -1.0f, 0.5f, 0.5f, 0.5f,
1.0f, 1.0f, -1.0f, 0.5f, 0.5f, 0.5f,
-1.0f, 1.0f, -1.0f, 0.5f, 0.5f, 0.5f,
// 上面
-1.0f, 1.0f, -1.0f, 0.5f, 0.5f, 0.5f,
1.0f, 1.0f, -1.0f, 0.5f, 0.5f, 0.5f,
1.0f, 1.0f, 1.0f, 0.5f, 0.5f, 0.5f,
1.0f, 1.0f, 1.0f, 0.5f, 0.5f, 0.5f,
-1.0f, 1.0f, 1.0f, 0.5f, 0.5f, 0.5f,
-1.0f, 1.0f, -1.0f, 0.5f, 0.5f, 0.5f,
// 下面
-1.0f, -1.0f, 1.0f, 0.5f, 0.5f, 0.5f,
1.0f, -1.0f, 1.0f, 0.5f, 0.5f, 0.5f,
1.0f, -1.0f, -1.0f, 0.5f, 0.5f, 0.5f,
1.0f, -1.0f, -1.0f, 0.5f, 0.5f, 0.5f,
-1.0f, -1.0f, -1.0f, 0.5f, 0.5f, 0.5f,
-1.0f, -1.0f, 1.0f, 0.5f, 0.5f, 0.5f,
// 左面
-1.0f, -1.0f, 1.0f, 0.5f, 0.5f, 0.5f,
-1.0f, -1.0f, -1.0f, 0.5f, 0.5f, 0.5f,
-1.0f, 1.0f, 1.0f, 0.5f, 0.5f, 0.5f,
-1.0f, -1.0f, -1.0f, 0.5f, 0.5f, 0.5f,
-1.0f, 1.0f, -1.0f, 0.5f, 0.5f, 0.5f,
-1.0f, 1.0f, 1.0f, 0.5f, 0.5f, 0.5f,
// 右面
1.0f, -1.0f, -1.0f, 0.5f, 0.5f, 0.5f,
1.0f, -1.0f, 1.0f, 0.5f, 0.5f, 0.5f,
1.0f, 1.0f, -1.0f, 0.5f, 0.5f, 0.5f,
1.0f, -1.0f, 1.0f, 0.5f, 0.5f, 0.5f,
1.0f, 1.0f, 1.0f, 0.5f, 0.5f, 0.5f,
1.0f, 1.0f, -1.0f, 0.5f, 0.5f, 0.5f
};
float deltaTime;
// 上一帧的时间
float lastFrame;
// 移动速度
float speed;
// 要旋转的面
float* TheToRotate;
// 旋转方向
float rotDir = 1.0;
// 旋转角度
float angle;
// 旋转向量
glm::vec3 angleVec;
// 创建魔方的骨架
void Skeleton();
// 创建魔方的上面部分
void CreateUpper();
// 创建魔方的中心部分
void CreateCentre();
// 创建魔方的下面部分
void CreateBelow();
// 修改魔方的面的颜色
void ModifyCubeColor(Direction* direction, MagicCubeStruct& mcf, int count);
// 设置魔方的网格数据
void setupMesh(MagicCubeStruct& mcf);
// 根据给定的方向,返回相应的颜色。
glm::vec3 ReturnColor(Direction direction);
// 根据给定的方向,返回相应的面
float* ReturnFace(Direction direction);
// 重新渲染
void ReRendering();
// 销毁 vao vbo
void DeleteVertexData();
// 是否旋转
void IsRotating(bool rotating);
public:
// 魔方的颜色属性
MagicCubeColor color;
// 存放魔方各个位置的结构体数组
std::vector<MagicCubeStruct> CubePos;
MagicCubeStructInd CubeInd;
// 初始化魔方的方法
void MagicCubeInit();
// 旋转
void rotate(Direction direction);
void Draw(Shader& shader, double currentTime);
// 销毁
void DeleteCube();
};
}
#include "MagicCube.h"
namespace CubeN {
void MagicCube::Skeleton()
{
MagicCubeStruct mcf;
mcf.count = 1;
// 后面
mcf.direction[0] = BACK;
mcf.color[0] = ReturnColor(BACK);
ModifyCubeColor(mcf.direction, mcf, mcf.count);
mcf.position = glm::vec3(0.0f, 0.0f, -2.0f);
CubePos.push_back(mcf); // 0
// 前面
mcf.direction[0] = FRONT;
mcf.color[0] = ReturnColor(FRONT);
ModifyCubeColor(mcf.direction, mcf, mcf.count);
mcf.position = glm::vec3(0.0f, 0.0f, 2.0f);
CubePos.push_back(mcf); // 1
// 上面
mcf.direction[0] = UP;
mcf.color[0] = ReturnColor(UP);
ModifyCubeColor(mcf.direction, mcf, mcf.count);
mcf.position = glm::vec3(0.0f, 2.0f, 0.0f);
CubePos.push_back(mcf);// 2
// 下面
mcf.direction[0] = DOWN;
mcf.color[0] = ReturnColor(DOWN);
ModifyCubeColor(mcf.direction, mcf, mcf.count);
mcf.position = glm::vec3(0.0f, -2.0f, 0.0f);
CubePos.push_back(mcf);// 3
// 左面
mcf.direction[0] = LEFT;
mcf.color[0] = ReturnColor(LEFT);
ModifyCubeColor(mcf.direction, mcf, mcf.count);
mcf.position = glm::vec3(-2.0f, 0.0f, 0.0f);
CubePos.push_back(mcf);// 4
// 右面
mcf.direction[0] = RIGHT;
mcf.color[0] = ReturnColor(RIGHT);
ModifyCubeColor(mcf.direction, mcf, mcf.count);
mcf.position = glm::vec3(2.0f, 0.0f, 0.0f);
CubePos.push_back(mcf);// 5
}
void MagicCube::CreateUpper()
{
MagicCubeStruct mcf;
mcf.count = 3;
// 左前
mcf.position = glm::vec3(-2.0f, 2.0f, 2.0f);
mcf.direction[0] = FRONT; // 前
mcf.direction[1] = LEFT; // 左
mcf.direction[2] = UP; // 上
mcf.color[0] = ReturnColor(FRONT);
mcf.color[1] = ReturnColor(LEFT);
mcf.color[2] = ReturnColor(UP);
ModifyCubeColor(mcf.direction, mcf, mcf.count);
CubePos.push_back(mcf); // 6
// 左后
mcf.position = glm::vec3(-2.0f, 2.0f, -2.0f);
mcf.direction[0] = BACK; // 后
mcf.direction[1] = LEFT; // 左
mcf.direction[2] = UP; // 上
mcf.color[0] = ReturnColor(BACK);
mcf.color[1] = ReturnColor(LEFT);
mcf.color[2] = ReturnColor(UP);
ModifyCubeColor(mcf.direction, mcf, mcf.count);
CubePos.push_back(mcf); // 7
// 右前
mcf.position = glm::vec3(2.0f, 2.0f, 2.0f);
mcf.direction[0] = FRONT; // 前
mcf.direction[1] = RIGHT; // 右
mcf.direction[2] = UP; // 上
mcf.color[0] = ReturnColor(FRONT);
mcf.color[1] = ReturnColor(RIGHT);
mcf.color[2] = ReturnColor(UP);
ModifyCubeColor(mcf.direction, mcf, mcf.count);
CubePos.push_back(mcf); // 8
// 右后
mcf.position = glm::vec3(2.0f, 2.0f, -2.0f);
mcf.direction[0] = BACK; // 后
mcf.direction[1] = RIGHT; // 右
mcf.direction[2] = UP; // 上
mcf.color[0] = ReturnColor(BACK);
mcf.color[1] = ReturnColor(RIGHT);
mcf.color[2] = ReturnColor(UP);
ModifyCubeColor(mcf.direction, mcf, mcf.count);
CubePos.push_back(mcf); // 9
mcf.count = 2;
// 前中
mcf.position = glm::vec3(0.0f, 2.0f, 2.0f);
mcf.direction[0] = FRONT; // 前
mcf.direction[1] = UP; // 上
mcf.color[0] = ReturnColor(FRONT);
mcf.color[1] = ReturnColor(UP);
ModifyCubeColor(mcf.direction, mcf, mcf.count);
CubePos.push_back(mcf); // 10
// 右中
mcf.position = glm::vec3(2.0f, 2.0f, 0.0f);
mcf.direction[0] = RIGHT; // 右
mcf.direction[1] = UP; // 上
mcf.color[0] = ReturnColor(RIGHT);
mcf.color[1] = ReturnColor(UP);
ModifyCubeColor(mcf.direction, mcf, mcf.count);
CubePos.push_back(mcf); // 11
// 后中
mcf.position = glm::vec3(0.0f, 2.0f, -2.0f);
mcf.direction[0] = BACK; // 后
mcf.direction[1] = UP; // 上
mcf.color[0] = ReturnColor(BACK);
mcf.color[1] = ReturnColor(UP);
ModifyCubeColor(mcf.direction, mcf, mcf.count);
CubePos.push_back(mcf); // 12
// 左中
mcf.position = glm::vec3(-2.0f, 2.0f, 0.0f);
mcf.direction[0] = LEFT; // 左
mcf.direction[1] = UP; // 上
mcf.color[0] = ReturnColor(LEFT);
mcf.color[1] = ReturnColor(UP);
ModifyCubeColor(mcf.direction, mcf, mcf.count);
CubePos.push_back(mcf); // 13
}
void MagicCube::CreateCentre()
{
MagicCubeStruct mcf;
mcf.count = 2;
// 左前
mcf.position = glm::vec3(-2.0f, 0.0f, 2.0f);
mcf.direction[0] = FRONT; // 前
mcf.direction[1] = LEFT; // 左
mcf.color[0] = ReturnColor(FRONT);
mcf.color[1] = ReturnColor(LEFT);
ModifyCubeColor(mcf.direction, mcf, mcf.count);
CubePos.push_back(mcf); // 14
// 右前
mcf.position = glm::vec3(2.0f, 0.0f, 2.0f);
mcf.direction[0] = FRONT; // 前
mcf.direction[1] = RIGHT; // 右
mcf.color[0] = ReturnColor(FRONT);
mcf.color[1] = ReturnColor(RIGHT);
ModifyCubeColor(mcf.direction, mcf, mcf.count);
CubePos.push_back(mcf); // 15
// 右后
mcf.position = glm::vec3(2.0f, 0.0f, -2.0f);
mcf.direction[0] = BACK; // 后
mcf.direction[1] = RIGHT; // 右
mcf.color[0] = ReturnColor(BACK);
mcf.color[1] = ReturnColor(RIGHT);
ModifyCubeColor(mcf.direction, mcf, mcf.count);
CubePos.push_back(mcf); // 16
// 左后
mcf.position = glm::vec3(-2.0f, 0.0f, -2.0f);
mcf.direction[0] = BACK; // 后
mcf.direction[1] = LEFT; // 左
mcf.color[0] = ReturnColor(BACK);
mcf.color[1] = ReturnColor(LEFT);
ModifyCubeColor(mcf.direction, mcf, mcf.count);
CubePos.push_back(mcf); // 17
}
void MagicCube::CreateBelow()
{
MagicCubeStruct mcf;
mcf.count = 3;
// 左前
mcf.position = glm::vec3(-2.0f, -2.0f, 2.0f);
mcf.direction[0] = FRONT; // 前
mcf.direction[1] = LEFT; // 左
mcf.direction[2] = DOWN; // 下
mcf.color[0] = ReturnColor(FRONT);
mcf.color[1] = ReturnColor(LEFT);
mcf.color[2] = ReturnColor(DOWN);
ModifyCubeColor(mcf.direction, mcf, mcf.count);
CubePos.push_back(mcf); // 18
// 左后
mcf.position = glm::vec3(-2.0f, -2.0f, -2.0f);
mcf.direction[0] = BACK; // 后
mcf.direction[1] = LEFT; // 左
mcf.direction[2] = DOWN; // 下
mcf.color[0] = ReturnColor(BACK);
mcf.color[1] = ReturnColor(LEFT);
mcf.color[2] = ReturnColor(DOWN);
ModifyCubeColor(mcf.direction, mcf, mcf.count);
CubePos.push_back(mcf); // 19
// 右前
mcf.position = glm::vec3(2.0f, -2.0f, 2.0f);
mcf.direction[0] = FRONT; // 前
mcf.direction[1] = RIGHT; // 右
mcf.direction[2] = DOWN; // 下
mcf.color[0] = ReturnColor(FRONT);
mcf.color[1] = ReturnColor(RIGHT);
mcf.color[2] = ReturnColor(DOWN);
ModifyCubeColor(mcf.direction, mcf, mcf.count);
CubePos.push_back(mcf); // 20
// 右后
mcf.position = glm::vec3(2.0f, -2.0f, -2.0f);
mcf.direction[0] = BACK; // 后
mcf.direction[1] = RIGHT; // 右
mcf.direction[2] = DOWN; // 下
mcf.color[0] = ReturnColor(BACK);
mcf.color[1] = ReturnColor(RIGHT);
mcf.color[2] = ReturnColor(DOWN);
ModifyCubeColor(mcf.direction, mcf, mcf.count);
CubePos.push_back(mcf); // 21
mcf.count = 2;
// 前中
mcf.position = glm::vec3(0.0f, -2.0f, 2.0f);
mcf.direction[0] = FRONT; // 前
mcf.direction[1] = DOWN; // 下
mcf.color[0] = ReturnColor(FRONT);
mcf.color[1] = ReturnColor(DOWN);
ModifyCubeColor(mcf.direction, mcf, mcf.count);
CubePos.push_back(mcf); // 22
// 右中
mcf.position = glm::vec3(2.0f, -2.0f, 0.0f);
mcf.direction[0] = RIGHT; // 右
mcf.direction[1] = DOWN; // 下
mcf.color[0] = ReturnColor(RIGHT);
mcf.color[1] = ReturnColor(DOWN);
ModifyCubeColor(mcf.direction, mcf, mcf.count);
CubePos.push_back(mcf); // 23
// 后中
mcf.position = glm::vec3(0.0f, -2.0f, -2.0f);
mcf.direction[0] = BACK; // 后
mcf.direction[1] = DOWN; // 下
mcf.color[0] = ReturnColor(BACK);
mcf.color[1] = ReturnColor(DOWN);
ModifyCubeColor(mcf.direction, mcf, mcf.count);
CubePos.push_back(mcf); // 24
// 左中
mcf.position = glm::vec3(-2.0f, -2.0f, 0.0f);
mcf.direction[0] = LEFT; // 左
mcf.direction[1] = DOWN; // 下
mcf.color[0] = ReturnColor(LEFT);
mcf.color[1] = ReturnColor(DOWN);
ModifyCubeColor(mcf.direction, mcf, mcf.count);
CubePos.push_back(mcf); // 25
}
void MagicCube::ModifyCubeColor(Direction* direction, MagicCubeStruct& mcf, int count)
{
// 获取立方体
memmove(PCube, Cube, CubeSize);
for (int i = 0; i < count; i++) {
// 获取颜色
glm::vec3 CubeColor = mcf.color[i];
// 修改颜色
int start = direction[i] * 6;
int end = start + 6;
for (int i = start; i < end; i++)
{
PCube[i * 6 + 3] = CubeColor.x;
PCube[i * 6 + 4] = CubeColor.y;
PCube[i * 6 + 5] = CubeColor.z;
}
}
setupMesh(mcf);
}
void MagicCube::setupMesh(MagicCubeStruct& mcf)
{
// 创建 vao
glGenVertexArrays(1, &mcf.VAO);
// 创建 vbo
glGenBuffers(1, &mcf.VBO);
// 绑定 vao
glBindVertexArray(mcf.VAO);
// 把顶点数据绑定到 vbo
glBindBuffer(GL_ARRAY_BUFFER, mcf.VBO);
glBufferData(GL_ARRAY_BUFFER, CubeSize, PCube, GL_STATIC_DRAW);
// 设置属性指针
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)0);
glEnableVertexAttribArray(0);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)(sizeof(float) * 3));
glEnableVertexAttribArray(1);
// 解绑
glBindVertexArray(0);
}
glm::vec3 MagicCube::ReturnColor(Direction direction)
{
switch (direction) {
case FRONT:
return color.front;
case BACK:
return color.back;
case UP:
return color.up;
case DOWN:
return color.down;
case LEFT:
return color.left;
case RIGHT:
return color.right;
default:
return glm::vec3(0.0f);
}
}
float* MagicCube::ReturnFace(Direction direction)
{
switch (direction) {
case FRONT:
return CubeInd.front;
case BACK:
return CubeInd.back;
case UP:
return CubeInd.up;
case DOWN:
return CubeInd.down;
case LEFT:
return CubeInd.left;
case RIGHT:
return CubeInd.right;
default:
exit(EXIT_FAILURE);
}
}
void MagicCube::ReRendering()
{
DeleteVertexData();
for (auto& mcf : CubePos)
{
ModifyCubeColor(mcf.direction, mcf, mcf.count);
}
}
void MagicCube::DeleteVertexData()
{
for (const auto& mcf : CubePos)
{
glDeleteVertexArrays(1, &mcf.VAO);
glDeleteBuffers(1, &mcf.VBO);
}
}
void MagicCube::IsRotating(bool rotating)
{
for (int i = 0; i < 9; i++)
{
CubePos[TheToRotate[i]].isRotating = rotating;
}
if (!rotating) TheToRotate = nullptr;
}
void MagicCube::MagicCubeInit()
{
PCube = new float[256];
angle = 0;
TheToRotate = nullptr;
CubeSize = 216 * sizeof(float);
speed = 0.005;
Skeleton();
CreateUpper();
CreateCentre();
CreateBelow();
// ----------------------- 前 -----------------------
// 左 中 右(第一排)
CubeInd.front[0] = 6;
CubeInd.front[1] = 10;
CubeInd.front[2] = 8;
// 左 右(第二排)
CubeInd.front[3] = 14;
CubeInd.front[4] = 15;
// 左 中 右(第三排)
CubeInd.front[5] = 18;
CubeInd.front[6] = 22;
CubeInd.front[7] = 20;
// ----------------------- 后 -----------------------
// 左 中 右(第一排)
CubeInd.back[0] = 7;
CubeInd.back[1] = 12;
CubeInd.back[2] = 9;
// 左 右(第二排)
CubeInd.back[3] = 16;
CubeInd.back[4] = 17;
// 左 中 右(第三排)
CubeInd.back[5] = 19;
CubeInd.back[6] = 24;
CubeInd.back[7] = 21;
// ----------------------- 上 -----------------------
// 左 中 右(第一排)
CubeInd.up[0] = 7;
CubeInd.up[1] = 12;
CubeInd.up[2] = 9;
// 左 右(第二排)
CubeInd.up[3] = 13;
CubeInd.up[4] = 11;
// 左 中 右(第三排)
CubeInd.up[5] = 6;
CubeInd.up[6] = 10;
CubeInd.up[7] = 8;
// ----------------------- 下 -----------------------
// 左 中 右(第一排)
CubeInd.down[0] = 18;
CubeInd.down[1] = 22;
CubeInd.down[2] = 20;
// 左 右(第二排)
CubeInd.down[3] = 25;
CubeInd.down[4] = 23;
// 左 中 右(第三排)
CubeInd.down[5] = 19;
CubeInd.down[6] = 24;
CubeInd.down[7] = 21;
// ----------------------- 左 -----------------------
// 左 中 右(第一排)
CubeInd.left[0] = 7;
CubeInd.left[1] = 13;
CubeInd.left[2] = 6;
// 左 右(第二排)
CubeInd.left[3] = 17;
CubeInd.left[4] = 14;
// 左 中 右(第三排)
CubeInd.left[5] = 19;
CubeInd.left[6] = 25;
CubeInd.left[7] = 18;
// ----------------------- 右 -----------------------
// 左 中 右(第一排)
CubeInd.right[0] = 8;
CubeInd.right[1] = 11;
CubeInd.right[2] = 9;
// 左 右(第二排)
CubeInd.right[3] = 15;
CubeInd.right[4] = 16;
// 左 中 右(第三排)
CubeInd.right[5] = 20;
CubeInd.right[6] = 23;
CubeInd.right[7] = 21;
// ----------------------- 中 -----------------------
CubeInd.front[8] = 1;
CubeInd.back[8] = 0;
CubeInd.left[8] = 4;
CubeInd.right[8] = 5;
CubeInd.up[8] = 2;
CubeInd.down[8] = 3;
}
void MagicCube::rotate(Direction direction)
{
if (TheToRotate != nullptr) return;
// 受影响的面有 上 左 下 右
TheToRotate = ReturnFace(direction);
IsRotating(true);
// 前
if (direction == FRONT) {
// 旋转轴
angleVec = glm::vec3(0.0f, 0.0f, 1.0f);
glm::vec3 vec1 = CubePos[CubeInd.up[5]].color[2];
glm::vec3 vec2 = CubePos[CubeInd.up[6]].color[1];
glm::vec3 vec3 = CubePos[CubeInd.up[7]].color[2];
// 上
CubePos[CubeInd.up[5]].color[2] = CubePos[CubeInd.right[0]].color[1];
CubePos[CubeInd.up[6]].color[1] = CubePos[CubeInd.right[3]].color[1];
CubePos[CubeInd.up[7]].color[2] = CubePos[CubeInd.right[5]].color[1];
// 右
CubePos[CubeInd.right[0]].color[1] = CubePos[CubeInd.down[2]].color[2];
CubePos[CubeInd.right[3]].color[1] = CubePos[CubeInd.down[1]].color[1];
CubePos[CubeInd.right[5]].color[1] = CubePos[CubeInd.down[0]].color[2];
// 下
CubePos[CubeInd.down[0]].color[2] = CubePos[CubeInd.left[2]].color[1];
CubePos[CubeInd.down[1]].color[1] = CubePos[CubeInd.left[4]].color[1];
CubePos[CubeInd.down[2]].color[2] = CubePos[CubeInd.left[7]].color[1];
// 左
CubePos[CubeInd.left[2]].color[1] = vec3;
CubePos[CubeInd.left[4]].color[1] = vec2;
CubePos[CubeInd.left[7]].color[1] = vec1;
// 前
vec1 = CubePos[CubeInd.front[0]].color[0];
vec2 = CubePos[CubeInd.front[1]].color[0];
vec3 = CubePos[CubeInd.front[2]].color[0];
CubePos[CubeInd.front[0]].color[0] = CubePos[CubeInd.front[2]].color[0];
CubePos[CubeInd.front[1]].color[0] = CubePos[CubeInd.front[4]].color[0];
CubePos[CubeInd.front[2]].color[0] = CubePos[CubeInd.front[7]].color[0];
CubePos[CubeInd.front[2]].color[0] = CubePos[CubeInd.front[7]].color[0];
CubePos[CubeInd.front[4]].color[0] = CubePos[CubeInd.front[6]].color[0];
CubePos[CubeInd.front[7]].color[0] = CubePos[CubeInd.front[5]].color[0];
CubePos[CubeInd.front[7]].color[0] = CubePos[CubeInd.front[5]].color[0];
CubePos[CubeInd.front[5]].color[0] = CubePos[CubeInd.front[0]].color[0];
CubePos[CubeInd.front[6]].color[0] = CubePos[CubeInd.front[3]].color[0];
CubePos[CubeInd.front[0]].color[0] = vec3;
CubePos[CubeInd.front[3]].color[0] = vec2;
CubePos[CubeInd.front[5]].color[0] = vec1;
}
// 右
else if (direction == RIGHT) {
// 旋转轴
angleVec = glm::vec3(1.0f, 0.0f, 0.0f);
glm::vec3 vec1 = CubePos[CubeInd.right[0]].color[2];
glm::vec3 vec2 = CubePos[CubeInd.right[1]].color[1];
glm::vec3 vec3 = CubePos[CubeInd.right[2]].color[2];
// 上
CubePos[CubeInd.right[0]].color[2] = CubePos[CubeInd.back[2]].color[0];
CubePos[CubeInd.right[1]].color[1] = CubePos[CubeInd.back[3]].color[0];
CubePos[CubeInd.right[2]].color[2] = CubePos[CubeInd.back[7]].color[0];
// 右
CubePos[CubeInd.back[2]].color[0] = CubePos[CubeInd.down[7]].color[2];
CubePos[CubeInd.back[3]].color[0] = CubePos[CubeInd.down[4]].color[1];
CubePos[CubeInd.back[7]].color[0] = CubePos[CubeInd.down[2]].color[2];
// 下
CubePos[CubeInd.down[2]].color[2] = CubePos[CubeInd.front[2]].color[0];
CubePos[CubeInd.down[4]].color[1] = CubePos[CubeInd.front[4]].color[0];
CubePos[CubeInd.down[7]].color[2] = CubePos[CubeInd.front[7]].color[0];
// 左
CubePos[CubeInd.front[2]].color[0] = vec3;
CubePos[CubeInd.front[4]].color[0] = vec2;
CubePos[CubeInd.front[7]].color[0] = vec1;
// 右
vec1 = CubePos[CubeInd.right[0]].color[1];
vec2 = CubePos[CubeInd.right[1]].color[0];
vec3 = CubePos[CubeInd.right[2]].color[1];
CubePos[CubeInd.right[0]].color[1] = CubePos[CubeInd.right[2]].color[1];
CubePos[CubeInd.right[1]].color[0] = CubePos[CubeInd.right[4]].color[1];
CubePos[CubeInd.right[2]].color[1] = CubePos[CubeInd.right[7]].color[1];
CubePos[CubeInd.right[2]].color[1] = CubePos[CubeInd.right[7]].color[1];
CubePos[CubeInd.right[4]].color[1] = CubePos[CubeInd.right[6]].color[0];
CubePos[CubeInd.right[7]].color[1] = CubePos[CubeInd.right[5]].color[1];
CubePos[CubeInd.right[7]].color[1] = CubePos[CubeInd.right[5]].color[1];
CubePos[CubeInd.right[5]].color[1] = CubePos[CubeInd.right[0]].color[1];
CubePos[CubeInd.right[6]].color[0] = CubePos[CubeInd.right[3]].color[1];
CubePos[CubeInd.right[0]].color[1] = vec3;
CubePos[CubeInd.right[3]].color[1] = vec2;
CubePos[CubeInd.right[5]].color[1] = vec1;
}
// 后
else if (direction == BACK) {
// 旋转轴
angleVec = glm::vec3(0.0f, 0.0f, 1.0f);
glm::vec3 vec1 = CubePos[CubeInd.back[0]].color[2];
glm::vec3 vec2 = CubePos[CubeInd.back[1]].color[1];
glm::vec3 vec3 = CubePos[CubeInd.back[2]].color[2];
CubePos[CubeInd.back[0]].color[2] = CubePos[CubeInd.right[2]].color[1];
CubePos[CubeInd.back[1]].color[1] = CubePos[CubeInd.right[4]].color[1];
CubePos[CubeInd.back[2]].color[2] = CubePos[CubeInd.right[7]].color[1];
CubePos[CubeInd.right[2]].color[1] = CubePos[CubeInd.down[7]].color[2];
CubePos[CubeInd.right[4]].color[1] = CubePos[CubeInd.down[6]].color[1];
CubePos[CubeInd.right[7]].color[1] = CubePos[CubeInd.down[5]].color[2];
CubePos[CubeInd.down[5]].color[2] = CubePos[CubeInd.left[0]].color[1];
CubePos[CubeInd.down[6]].color[1] = CubePos[CubeInd.left[3]].color[1];
CubePos[CubeInd.down[7]].color[2] = CubePos[CubeInd.left[5]].color[1];
CubePos[CubeInd.left[0]].color[1] = vec3;
CubePos[CubeInd.left[3]].color[1] = vec2;
CubePos[CubeInd.left[5]].color[1] = vec1;
vec1 = CubePos[CubeInd.back[0]].color[0];
vec2 = CubePos[CubeInd.back[1]].color[0];
vec3 = CubePos[CubeInd.back[2]].color[0];
CubePos[CubeInd.back[0]].color[0] = CubePos[CubeInd.back[2]].color[0];
CubePos[CubeInd.back[1]].color[0] = CubePos[CubeInd.back[3]].color[0];
CubePos[CubeInd.back[2]].color[0] = CubePos[CubeInd.back[7]].color[0];
CubePos[CubeInd.back[2]].color[0] = CubePos[CubeInd.back[7]].color[0];
CubePos[CubeInd.back[3]].color[0] = CubePos[CubeInd.back[6]].color[0];
CubePos[CubeInd.back[7]].color[0] = CubePos[CubeInd.back[5]].color[0];
CubePos[CubeInd.back[7]].color[0] = CubePos[CubeInd.back[5]].color[0];
CubePos[CubeInd.back[5]].color[0] = CubePos[CubeInd.back[0]].color[0];
CubePos[CubeInd.back[6]].color[0] = CubePos[CubeInd.back[4]].color[0];
CubePos[CubeInd.back[0]].color[0] = vec3;
CubePos[CubeInd.back[4]].color[0] = vec2;
CubePos[CubeInd.back[5]].color[0] = vec1;
}
// 左
else if (direction == LEFT) {
// 旋转轴
angleVec = glm::vec3(1.0f, 0.0f, 0.0f);
glm::vec3 vec1 = CubePos[CubeInd.left[0]].color[2];
glm::vec3 vec2 = CubePos[CubeInd.left[1]].color[1];
glm::vec3 vec3 = CubePos[CubeInd.left[2]].color[2];
CubePos[CubeInd.left[0]].color[2] = CubePos[CubeInd.back[5]].color[0];
CubePos[CubeInd.left[1]].color[1] = CubePos[CubeInd.back[4]].color[0];
CubePos[CubeInd.left[2]].color[2] = CubePos[CubeInd.back[0]].color[0];
CubePos[CubeInd.back[0]].color[0] = CubePos[CubeInd.down[5]].color[2];
CubePos[CubeInd.back[4]].color[0] = CubePos[CubeInd.down[3]].color[1];
CubePos[CubeInd.back[5]].color[0] = CubePos[CubeInd.down[0]].color[2];
CubePos[CubeInd.down[0]].color[2] = CubePos[CubeInd.front[0]].color[0];
CubePos[CubeInd.down[3]].color[1] = CubePos[CubeInd.front[3]].color[0];
CubePos[CubeInd.down[5]].color[2] = CubePos[CubeInd.front[5]].color[0];
CubePos[CubeInd.front[0]].color[0] = vec1;
CubePos[CubeInd.front[3]].color[0] = vec2;
CubePos[CubeInd.front[5]].color[0] = vec3;
vec1 = CubePos[CubeInd.left[0]].color[1];
vec2 = CubePos[CubeInd.left[1]].color[0];
vec3 = CubePos[CubeInd.left[2]].color[1];
CubePos[CubeInd.left[0]].color[1] = CubePos[CubeInd.left[5]].color[1];
CubePos[CubeInd.left[1]].color[0] = CubePos[CubeInd.left[3]].color[1];
CubePos[CubeInd.left[2]].color[1] = CubePos[CubeInd.left[0]].color[1];
CubePos[CubeInd.left[0]].color[1] = CubePos[CubeInd.left[5]].color[1];
CubePos[CubeInd.left[3]].color[1] = CubePos[CubeInd.left[6]].color[0];
CubePos[CubeInd.left[5]].color[1] = CubePos[CubeInd.left[7]].color[1];
CubePos[CubeInd.left[7]].color[1] = CubePos[CubeInd.left[5]].color[1];
CubePos[CubeInd.left[5]].color[1] = CubePos[CubeInd.left[7]].color[1];
CubePos[CubeInd.left[6]].color[0] = CubePos[CubeInd.left[4]].color[1];
CubePos[CubeInd.left[2]].color[1] = vec1;
CubePos[CubeInd.left[4]].color[1] = vec2;
CubePos[CubeInd.left[7]].color[1] = vec3;
}
}
void MagicCube::Draw(Shader& shader, double currentTime)
{
if (TheToRotate) {
deltaTime = currentTime - lastFrame;
if (deltaTime > speed) {
angle += rotDir;
lastFrame = currentTime;
}
}
if (angle > 90|| angle < -90) {
IsRotating(false);
angle = 0;
// 重新渲染
ReRendering();
}
for (int i = 0; i < 26; i++)
{
glBindVertexArray(CubePos[i].VAO);
glm::mat4 mMat = glm::scale(glm::mat4(1.0f), glm::vec3(0.1f));
if (CubePos[i].isRotating) {
mMat = glm::rotate(mMat, glm::radians(angle), angleVec);
}
// 模型矩阵
mMat = glm::translate(mMat, CubePos[i].position);
// 模型矩阵
shader.setPUFMat4("m_matrix", glm::value_ptr(mMat));
// 绘制模型
glDrawArrays(GL_TRIANGLES, 0, 36);
}
}
void MagicCube::DeleteCube()
{
delete[]PCube;
DeleteVertexData();
}
}
main.cpp
#include <glad/glad.h>
#include <GLFW/glfw3.h>
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
#include <ImgUI/imgui.h>
#include <ImgUI/imgui_impl_glfw.h>
#include <ImgUI/imgui_impl_opengl3.h>
#include <iostream>
#include <assert.h>
#include <cmath>
#include <map>
#include <ctime>
#include <stack>
#include <vector>
#include <Class/Shader/Shader.h>
#include <Class/Camera/Camera.h>
#include "MagicCube.h"
// 创建着色器类
Shader shader;
// 创建魔法类
CubeN::MagicCube myMagicCube;
// 位置、目标、上向量
Camera myCamera(glm::vec3(0.0f, 0.0f, 3.0f),glm::vec3(0.0f, 0.0f, -1.0f),glm::vec3(0.0f, 1.0f, 0.0f));
float aspect;// 屏幕宽度比
bool isCtrlPressed = true;
GLuint
vLoad,// 视图矩阵
mLoad,// 模型矩阵
pLoad;// 透视矩阵
glm::mat4
mMat, // 模型矩阵
pMat, // 透视矩阵
vMat; // 视图矩阵
// 初始自定义代码
void init(GLFWwindow* window);
// 渲染自定义代码
void display(GLFWwindow* window, double currentTime);
// 销毁
void destroy(GLFWwindow* window);
// 窗口改变事件
void window_reshape_callback(GLFWwindow* window, int width, int height);
// 注册了鼠标移动事件
void mouse_callback(GLFWwindow* window, double xpos, double ypos);
// 注册了鼠标移动事件
void scroll_callback(GLFWwindow* window, double xoffset, double yoffset);
// 监听按键,鼠标事件
void ProcessInput(GLFWwindow* window);
// 键盘按下和抬起事件的回调函数
void onKey(GLFWwindow* window, int key, int scancode, int action, int mods);
int main() {
// 初始化 glfw
if (!glfwInit()) { exit(EXIT_FAILURE); }
// 设置 opengl 版本 (4.6 核心)
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 6);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
// 创建 window 窗口
GLFWwindow* window = glfwCreateWindow(600, 600, "LearOpenGL 3.5", NULL, NULL);
// 链接 opengl 上下文
glfwMakeContextCurrent(window);
// 初始化 glad 获取 opengl api 函数 地址
if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)) { exit(EXIT_FAILURE); }
// 开启垂直
glfwSwapInterval(1);
// 注册窗口改变事件
glfwSetWindowSizeCallback(window, window_reshape_callback);
// 隐藏光标
// glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
// 注册了鼠标移动事件
glfwSetCursorPosCallback(window, mouse_callback);
// 注册了鼠标滚动事件
glfwSetScrollCallback(window, scroll_callback);
// 设置键盘事件的回调函数
glfwSetKeyCallback(window, onKey);
// 创建imgui上下文
ImGui::CreateContext();
ImGuiIO& io = ImGui::GetIO();
// 设置样式
ImGui::StyleColorsDark();
// 设置平台和渲染器
ImGui_ImplGlfw_InitForOpenGL(window, true);
ImGui_ImplOpenGL3_Init("#version 460");
// 初始化着色器类
shader.init("vertShader.glsl", "fragShader.glsl");
// 初始化魔方
myMagicCube.MagicCubeInit();
// 初始自定义代码
init(window);
myCamera.fov = 45.0f;
// 循环渲染
while (!glfwWindowShouldClose(window))
{
// 监听键盘
ProcessInput(window);
ImGui_ImplOpenGL3_NewFrame();
ImGui_ImplGlfw_NewFrame();
ImGui::NewFrame();
ImGui::Begin("imgui");
ImGui::Text("%.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate);
ImGui::End();
// 渲染自定义代码
display(window, glfwGetTime());
// 渲染 gui
ImGui::Render();
ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());
// 交换缓存和轮询IO事件
glfwSwapBuffers(window);
glfwPollEvents();
}
// 释放内存
destroy(window);
// 成功退出程序
exit(EXIT_SUCCESS);
}
void init(GLFWwindow* window) {
// 开启着色器程序
shader.useProgram();
mLoad = shader.getULocation("m_matrix");
vLoad = shader.getULocation("v_matrix");
pLoad = shader.getULocation("p_matrix");
// 获取窗口的宽高
int width, height;
glfwGetFramebufferSize(window, &width, &height);// 获取屏幕宽,高
// 计算宽高比
aspect = (float)width / (float)height;//获取屏幕比例
}
void display(GLFWwindow* window, double currentTime) {
// 填充颜色缓冲区
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
// 清除深度缓冲区
glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
// 创建透视矩阵 / 设置投影矩阵
pMat = glm::perspective(glm::radians(myCamera.fov), aspect, 0.1f, 1000.0f);
// 将视图矩阵压入栈
vMat = myCamera.getLookAt();
// 开启着色器程序
shader.useProgram();
// 视图矩阵
shader.setPUFMat4(vLoad, glm::value_ptr(vMat));
// 透视矩阵
shader.setPUFMat4(pLoad, glm::value_ptr(pMat));
// 开启深度测试
glEnable(GL_DEPTH_TEST);
// 设置深度测试的比较方式
glDepthFunc(GL_LESS);
// 开启背面剔除
glEnable(GL_CULL_FACE);
// 设置立方体顶点的缠绕顺序为逆时针方向
glFrontFace(GL_CW);
myMagicCube.Draw(shader, currentTime);
}
void destroy(GLFWwindow* window) {
// 销毁 vao vbo
myMagicCube.DeleteCube();
// 销毁着色器
shader.deleteProgram();
// 销毁窗口
glfwDestroyWindow(window);
glfwTerminate();
}
void window_reshape_callback(GLFWwindow* window, int width, int height)
{
// 设置和帧缓冲区相关的屏幕区域
glViewport(0, 0, width, height);
aspect = (float)width / (float)height;//获取屏幕比例
}
// 监听按键,鼠标事件
void ProcessInput(GLFWwindow* window)
{
// 检查用户是否按下了返回键(Esc)
if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
{
// 下一次while循环的条件检测将会失败,程序将会关闭
glfwSetWindowShouldClose(window, true);
}
static float deltaTime = 0.0f;
static float lastFrame = 0.0f;
float currentFrame = glfwGetTime();
deltaTime = currentFrame - lastFrame; // 当前帧与上一帧的时间差
lastFrame = currentFrame; // 上一帧的时间
if (glfwGetKey(window, GLFW_KEY_W) == GLFW_PRESS)
myCamera.ProcessKeyboard(FORWARD, deltaTime);
if (glfwGetKey(window, GLFW_KEY_S) == GLFW_PRESS)
myCamera.ProcessKeyboard(BACKWARD, deltaTime);
if (glfwGetKey(window, GLFW_KEY_A) == GLFW_PRESS)
myCamera.ProcessKeyboard(LEFT, deltaTime);
if (glfwGetKey(window, GLFW_KEY_D) == GLFW_PRESS)
myCamera.ProcessKeyboard(RIGHT, deltaTime);
}
// 回调函数,鼠标进入程序窗口,获取焦点
void mouse_callback(GLFWwindow* window, double xpos, double ypos)
{
static bool firstMouse = true;
static float lastX = 0.0f;
static float lastY = 0.0f;
static float xoffset = 0.0f;
static float yoffset = 0.0f;
if (firstMouse)
{
lastX = xpos;
lastY = ypos;
firstMouse = false;
}
// 获取 x 坐标
xoffset = xpos - lastX;
// 注意这里是相反的,因为y坐标是从底部往顶部依次增大的
yoffset = lastY - ypos;
// 更新鼠标坐标
lastX = xpos;
lastY = ypos;
if (!isCtrlPressed)
myCamera.mouse_callback(xoffset, yoffset);
}
// 监听鼠标滚动
void scroll_callback(GLFWwindow* window, double xoffset, double yoffset)
{
myCamera.scroll_callback(xoffset, yoffset);
}
// 键盘按下和抬起事件的回调函数
void onKey(GLFWwindow* window, int key, int scancode, int action, int mods) {
if (action == GLFW_PRESS) {
// 键盘按下的处理逻辑
if (key == GLFW_KEY_LEFT_CONTROL && !isCtrlPressed) {
isCtrlPressed = true;
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_NORMAL);
}
else if (key == GLFW_KEY_LEFT_CONTROL && isCtrlPressed) {
isCtrlPressed = false;
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
}
if (key == GLFW_KEY_I) {
myMagicCube.rotate(CubeN::FRONT);
}
else if (key == GLFW_KEY_L) {
myMagicCube.rotate(CubeN::RIGHT);
}
else if (key == GLFW_KEY_M) {
myMagicCube.rotate(CubeN::BACK);
}
else if (key == GLFW_KEY_J) {
myMagicCube.rotate(CubeN::LEFT);
}
}
else if (action == GLFW_RELEASE) {
// 键盘抬起的处理逻辑
}
}