在模型矩阵上链接旋转
Chaining rotation on model matrix
我有一个小的 opengl 世界,我尝试用模型矩阵制作一个小立方体并围绕原点轴旋转它。我几乎把所有事情都做对了,但我的问题是,每当我尝试链接旋转时,即(一次在 x 轴上旋转,然后在不重置矩阵的情况下在 y 轴上旋转)我没有得到我想要的。我希望立方体在固定轴上旋转,但立方体在其自己的轴上旋转。我的意思是说我想使用原点的轴旋转但模型使用它自己的轴旋转,轴保持在原点但它有点随模型旋转。我以为我的相机在移动而不是模型,但是当我尝试使用多个盒子时它证明我的相机在它自己的位置上。我不知道如何进行正确的旋转。这是我所做的代码(一些代码来自 learnopengl.com):
x_Camera camera;
class XYZ_line
{
public:
glm::vec3 xCol, yCol, zCol;
std::vector<glm::vec3>m_Vertices;
unsigned int VBO, VAO;
GAME::Shader shader;
glm::mat4 model;
inline void Init()
{
model = glm::mat4(1.0f);
shader.Init(GAME::CubeVsShader, GAME::CubeFsShader);
shader.Bind();
xCol = glm::vec3(1.0f, 0.0f, 0.0f);
yCol = glm::vec3(0.0f, 1.0f, 0.0f);
zCol = glm::vec3(0.0f, 0.0f, 1.0f);
float x1 = 0.0f, x2 = 800.0f;
m_Vertices.push_back(glm::vec3(x1, 0.0f, 0.0f)); m_Vertices.push_back(xCol);
m_Vertices.push_back(glm::vec3(x2, 0.0f, 0.0f)); m_Vertices.push_back(xCol);
m_Vertices.push_back(glm::vec3(0.0f, x1, 0.0f)); m_Vertices.push_back(yCol);
m_Vertices.push_back(glm::vec3(0.0f, x2, 0.0f)); m_Vertices.push_back(yCol);
m_Vertices.push_back(glm::vec3(0.0f, 0.0f, x1)); m_Vertices.push_back(zCol);
m_Vertices.push_back(glm::vec3(0.0f, 0.0f, x2)); m_Vertices.push_back(zCol);
glGenVertexArrays(1, &VAO);
glGenBuffers(1, &VBO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBindVertexArray(VAO);
glBufferData(GL_ARRAY_BUFFER, sizeof(glm::vec3) * m_Vertices.size(), &m_Vertices[0], GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(float) * 6, 0);
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(float) * 6, (void*)(sizeof(float) * 3));
}
void SetMatrices(glm::mat4& v, glm::mat4& p)
{
shader.Bind();
glBindVertexArray(VAO);
shader.SetUniformMat4fv("projection", 1, GL_FALSE, p);
shader.SetUniformMat4fv("view", 1, GL_FALSE, v);
shader.SetUniformMat4fv("model", 1, GL_FALSE, model);
}
void Draw()
{
shader.Bind();
glBindVertexArray(VAO);
glDrawArrays(GL_LINES, 0, m_Vertices.size() / 2);
}
};
void KeyCallback(GLFWwindow* window, int key, int scancode, int action, int mods);
void processInput(GLFWwindow* window);
float deltaTime = 0.0f;
float lastFrame = 0.0f;
glm::mat4 projection;
glm::mat4 view;
Cube cube;
const glm::vec3 fCol = glm::vec3(1.0f, 1.0f, 1.0f);//white
const glm::vec3 bCol = glm::vec3(1.0f, 0.6f, 0.0f);//orange
const glm::vec3 rCol = glm::vec3(1.0f, 0.0f, 0.0f);//red
const glm::vec3 lCol = glm::vec3(1.0f, 1.0f, 0.0f);//yellow
const glm::vec3 uCol = glm::vec3(0.0f, 0.0f, 1.0f);//blue
const glm::vec3 dCol = glm::vec3(0.0f, 1.0f, 0.0f);//green
int main()
{
GLFWwindow* window;
if (!glfwInit())
{
return -1;
}
window = glfwCreateWindow(800, 800, "TEST", NULL, NULL);
if (!window)
{
glfwTerminate();
return -1;
}
glfwMakeContextCurrent(window);
if (glewInit() != GLEW_OK)
{
glfwTerminate();
return -1;
}
glfwSetKeyCallback(window, KeyCallback);
camera.Init(glm::vec3(0.0f, 0.0f, 10.0f));
XYZ_line xyzLine1;
xyzLine1.Init();
float bSize = 1.0f;
float x1 = -1.6f, x2 = -0.5f, x3 = 0.6f;
float z1 = 1.6f, z2 = 0.5f, z3 = -0.6f;
cube.Init(glm::vec3(x1, x3, z1), bSize);
cube.m_Color_L = lCol; cube.m_Color_R = rCol; cube.m_Color_F = fCol;
cube.m_Color_B = bCol; cube.m_Color_U = uCol; cube.m_Color_D = dCol;
cube.SetVertexData();
glEnable(GL_DEPTH_TEST);
while (!glfwWindowShouldClose(window))
{
float currentFrame = glfwGetTime();
deltaTime = currentFrame - lastFrame;
lastFrame = currentFrame;
processInput(window);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glClearColor(0.8f, 0.8f, 0.8f, 1.0f);
view = camera.GetViewMatrix();
projection = glm::perspective(glm::radians(camera.Zoom), 1.0f, 0.1f, 10000.0f);
xyzLine1.model = cube.model;
xyzLine1.SetMatrices(view, projection);
xyzLine1.Draw();
cube.SetMatrices(view, projection);
cube.Draw();
glfwSwapBuffers(window);
glfwPollEvents();
}
glfwTerminate();
return 0;
}
void processInput(GLFWwindow* window)
{
if (glfwGetKey(window, GLFW_KEY_W) == GLFW_PRESS)
{
camera.ProcessKeyboard(Camera_Movement::FORWARD, deltaTime);
}
if (glfwGetKey(window, GLFW_KEY_S) == GLFW_PRESS)
{
camera.ProcessKeyboard(Camera_Movement::BACKWARD, deltaTime);
}
if (glfwGetKey(window, GLFW_KEY_A) == GLFW_PRESS)
{
camera.ProcessKeyboard(Camera_Movement::LEFT, deltaTime);
}
if (glfwGetKey(window, GLFW_KEY_D) == GLFW_PRESS)
{
camera.ProcessKeyboard(Camera_Movement::RIGHT, deltaTime);
}
if (glfwGetKey(window, GLFW_KEY_Q) == GLFW_PRESS)
{
camera.ProcessKeyboard(Camera_Movement::UP, deltaTime);
}
if (glfwGetKey(window, GLFW_KEY_E) == GLFW_PRESS)
{
camera.ProcessKeyboard(Camera_Movement::DOWN, deltaTime);
}
}
void KeyCallback(GLFWwindow* window, int key, int scancode, int action, int mods)
{
if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
{
glfwSetWindowShouldClose(window, true);
}
if (glfwGetKey(window, GLFW_KEY_X) == GLFW_PRESS)
{
cube.RotateX();
}
if (glfwGetKey(window, GLFW_KEY_Y) == GLFW_PRESS)
{
cube.RotateY();
}
if (glfwGetKey(window, GLFW_KEY_Z) == GLFW_PRESS)
{
cube.RotateZ();
}
}
和我的 Cube
class:
class Cube
{
public:
glm::vec3 t1, t2, t3, t4;
glm::vec3 b1, b2, b3, b4;
glm::vec3 m_Color_L, m_Color_R, m_Color_U, m_Color_D, m_Color_F, m_Color_B;
glm::mat4 model;
float m_CubeSize;
float rot_angle_X = 0.0f;
float rot_angle_Y = 0.0f;
float rot_angle_Z = 0.0f;
Cube();
void Init(glm::vec3 _from, float CubeSize);
Cube(const Cube& e);
Cube& operator=(const Cube& e);
Cube(Cube&& e)noexcept;
Cube& operator=(Cube&& e)noexcept;
Cube* operator-> () { return this; }
operator Cube* () { return this; }
Cube* Clone() { return new Cube(*this); }
void SetVertexData();
unsigned int GetVertexDataSize() { return vertices.size(); }
void Reset();
glm::vec3 GetCenter();
private:
glm::vec3 m_Min, m_Max, m_Cpt;
std::vector<glm::vec3>vertices;
void SetEdgeVertices(glm::vec3 _from, float size);
public:
Shader cShader;
unsigned int cubeVBO, cubeVAO;
void RotateX();
void RotateY();
void RotateZ();
void Draw();
glm::vec3 GetPosition() { return model[3]; }
void SetMatrices(glm::mat4& v, glm::mat4& p);
private:
};
const std::string CubeVsShader =
{
"#version 330 core\n"
"layout(location=0) in vec4 pos;\n"
"layout(location=1) in vec4 col;\n"
"\n"
"uniform mat4 model;\n"
"uniform mat4 view;\n"
"uniform mat4 projection;\n"
"\n"
"out vec4 color;\n"
"void main(){\n"
"gl_Position=projection*view*model*pos;\n"
"color=col;\n"
"}\n"
"\n"
};
const std::string CubeFsShader =
{
"#version 330 core\n"
"out vec4 FragColor;\n"
"\n"
"in vec4 color;\n"
"void main(){\n"
"FragColor=color;\n"
"}\n"
"\n"
};
Cube::Cube()
:t1(glm::vec3()), t2(glm::vec3()), t3(glm::vec3()), t4(glm::vec3()),
b1(glm::vec3()), b2(glm::vec3()), b3(glm::vec3()), b4(glm::vec3()), m_CubeSize(0.0f)
{
}
void Cube::Init(glm::vec3 _from, float CubeSize)
{
SetEdgeVertices(_from, CubeSize);
model = glm::mat4(1.0f);
cShader.Init(CubeVsShader, CubeFsShader);
cShader.Bind();
glGenVertexArrays(1, &cubeVAO);
glGenBuffers(1, &cubeVBO);
glBindBuffer(GL_ARRAY_BUFFER, cubeVBO);
glBindVertexArray(cubeVAO);
glBufferData(GL_ARRAY_BUFFER, sizeof(glm::vec3) * 48, 0, GL_DYNAMIC_DRAW);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(float) * 6, 0);
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(float) * 6, (void*)(sizeof(float) * 3));
}
Cube::Cube(const Cube& e)
{
t1 = e.t1; t2 = e.t2; t3 = e.t3; t4 = e.t4;
b1 = e.b1; b2 = e.b2; b3 = e.b3; b4 = e.b4;
m_CubeSize = e.m_CubeSize;
m_Color_L = e.m_Color_L;
m_Color_R = e.m_Color_R;
m_Color_U = e.m_Color_U;
m_Color_D = e.m_Color_D;
m_Color_F = e.m_Color_F;
m_Color_B = e.m_Color_B;
cShader = e.cShader;
cubeVBO = e.cubeVBO;
cubeVAO = e.cubeVAO;
rot_angle_X = e.rot_angle_X;
rot_angle_Y = e.rot_angle_Y;
rot_angle_Z = e.rot_angle_Z;
model = e.model;
AddToVector(vertices, e.vertices);
m_Min = e.m_Min;
m_Max = e.m_Max;
m_Cpt = e.m_Cpt;
}
Cube& Cube::operator=(const Cube& e)
{
t1 = e.t1; t2 = e.t2; t3 = e.t3; t4 = e.t4;
b1 = e.b1; b2 = e.b2; b3 = e.b3; b4 = e.b4;
m_CubeSize = e.m_CubeSize;
m_Color_B = e.m_Color_B;
m_Color_F = e.m_Color_F;
m_Color_L = e.m_Color_L;
m_Color_R = e.m_Color_R;
m_Color_U = e.m_Color_U;
m_Color_D = e.m_Color_D;
cShader = e.cShader;
cubeVBO = e.cubeVBO;
cubeVAO = e.cubeVAO;
model = e.model;
rot_angle_X = e.rot_angle_X;
rot_angle_Y = e.rot_angle_Y;
rot_angle_Z = e.rot_angle_Z;
AddToVector(vertices, e.vertices);
m_Min = e.m_Min;
m_Max = e.m_Max;
m_Cpt = e.m_Cpt;
return *this;
}
Cube::Cube(Cube&& e) noexcept
{
t1 = std::move(e.t1); t2 = std::move(e.t2); t3 = std::move(e.t3); t4 = std::move(e.t4);
b1 = std::move(e.b1); b2 = std::move(e.b2); b3 = std::move(e.b3); b4 = std::move(e.b4);
m_CubeSize = std::move(e.m_CubeSize);
m_Color_B = std::move(e.m_Color_B);
m_Color_F = std::move(e.m_Color_F);
m_Color_L = std::move(e.m_Color_L);
m_Color_R = std::move(e.m_Color_R);
m_Color_U = std::move(e.m_Color_U);
m_Color_D = std::move(e.m_Color_D);
cShader = std::move(e.cShader);
cubeVBO = std::move(e.cubeVBO);
cubeVAO = std::move(e.cubeVAO);
model = std::move(e.model);
rot_angle_X = std::move(e.rot_angle_X);
rot_angle_Y = std::move(e.rot_angle_Y);
rot_angle_Z = std::move(e.rot_angle_Z);
AddToVector(vertices, std::move(e.vertices));
m_Min = std::move(e.m_Min);
m_Max = std::move(e.m_Max);
m_Cpt = std::move(e.m_Cpt);
}
Cube& Cube::operator=(Cube&& e) noexcept
{
t1 = std::move(e.t1); t2 = std::move(e.t2); t3 = std::move(e.t3); t4 = std::move(e.t4);
b1 = std::move(e.b1); b2 = std::move(e.b2); b3 = std::move(e.b3); b4 = std::move(e.b4);
m_CubeSize = std::move(e.m_CubeSize);
m_Color_B = std::move(e.m_Color_B);
m_Color_F = std::move(e.m_Color_F);
m_Color_L = std::move(e.m_Color_L);
m_Color_R = std::move(e.m_Color_R);
m_Color_U = std::move(e.m_Color_U);
m_Color_D = std::move(e.m_Color_D);
cShader = std::move(e.cShader);
cubeVBO = std::move(e.cubeVBO);
cubeVAO = std::move(e.cubeVAO);
model = std::move(e.model);
rot_angle_X = std::move(e.rot_angle_X);
rot_angle_Y = std::move(e.rot_angle_Y);
rot_angle_Z = std::move(e.rot_angle_Z);
m_Min = std::move(e.m_Min);
m_Max = std::move(e.m_Max);
m_Cpt = std::move(e.m_Cpt);
AddToVector(vertices, std::move(e.vertices));
return *this;
}
void Cube::SetVertexData()
{
ResetVectors(&vertices);
vertices.push_back(b1); vertices.push_back(m_Color_D); vertices.push_back(b2); vertices.push_back(m_Color_D);
vertices.push_back(b3); vertices.push_back(m_Color_D); vertices.push_back(b4); vertices.push_back(m_Color_D);
vertices.push_back(t1); vertices.push_back(m_Color_U); vertices.push_back(t2); vertices.push_back(m_Color_U);
vertices.push_back(t3); vertices.push_back(m_Color_U); vertices.push_back(t4); vertices.push_back(m_Color_U);
vertices.push_back(b1); vertices.push_back(m_Color_L); vertices.push_back(b2); vertices.push_back(m_Color_L);
vertices.push_back(t2); vertices.push_back(m_Color_L); vertices.push_back(t1); vertices.push_back(m_Color_L);
vertices.push_back(b4); vertices.push_back(m_Color_R); vertices.push_back(b3); vertices.push_back(m_Color_R);
vertices.push_back(t3); vertices.push_back(m_Color_R); vertices.push_back(t4); vertices.push_back(m_Color_R);
vertices.push_back(b2); vertices.push_back(m_Color_B); vertices.push_back(b3); vertices.push_back(m_Color_B);
vertices.push_back(t3); vertices.push_back(m_Color_B); vertices.push_back(t2); vertices.push_back(m_Color_B);
vertices.push_back(b1); vertices.push_back(m_Color_F); vertices.push_back(b4); vertices.push_back(m_Color_F);
vertices.push_back(t4); vertices.push_back(m_Color_F); vertices.push_back(t1); vertices.push_back(m_Color_F);
cShader.Bind();
glBindVertexArray(cubeVAO);
glBindBuffer(GL_ARRAY_BUFFER, cubeVBO);
glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(glm::vec3) * vertices.size(), &vertices[0]);
}
void Cube::Reset()
{
b1 = b2 = b3 = b4 = t1 = t2 = t3 = t4 = glm::vec3(0.0f);
m_Color_B = m_Color_F = m_Color_U = glm::vec3(0.0f);
m_Color_D = m_Color_L = m_Color_R = glm::vec3(0.0f);
m_CubeSize = 0.0f;
this->cubeVBO = 0;
ResetVectors(&this->vertices);
this->cShader.Reset();
}
glm::vec3 Cube::GetCenter()
{
return m_Cpt;
}
void Cube::SetEdgeVertices(glm::vec3 _from, float size)
{
glm::vec3 _min(_from), _max;
_max.x = _min.x + size; _max.y = _min.y + size; _max.z = _min.z - size;
this->m_Min = _min; this->m_Max = _max;
this->m_Cpt = (_max + _min) / glm::vec3(2.0f);
this->b1 = glm::vec3(_min.x, _min.y, _min.z); this->b2 = glm::vec3(_min.x, _min.y, _max.z);
this->b3 = glm::vec3(_max.x, _min.y, _max.z); this->b4 = glm::vec3(_max.x, _min.y, _min.z);
this->t1 = glm::vec3(_min.x, _max.y, _min.z); this->t2 = glm::vec3(_min.x, _max.y, _max.z);
this->t3 = glm::vec3(_max.x, _max.y, _max.z); this->t4 = glm::vec3(_max.x, _max.y, _min.z);
this->m_CubeSize = size;
}
void Rotate(glm::mat4& mat, float ang_x, float ang_y, float ang_z)
{
glm::mat4 transformX = glm::mat4(1.0f);
glm::mat4 transformY = glm::mat4(1.0f);
glm::mat4 transformZ = glm::mat4(1.0f);
transformX = glm::rotate(transformX, glm::radians(ang_x), glm::vec3(1.0f, 0.0f, 0.0f));
transformY = glm::rotate(transformY, glm::radians(ang_y), glm::vec3(0.0f, 1.0f, 0.0f));
transformZ = glm::rotate(transformZ, glm::radians(ang_z), glm::vec3(0.0f, 0.0f, 1.0f));
mat = transformX * transformY * transformZ;
}
void Cube::RotateX()
{
model = glm::mat4(1.0f);
rot_angle_X += 90.0f;
if (rot_angle_X >= 360.0f)
{
rot_angle_X = 0.0f;
}
Rotate(model, rot_angle_X, rot_angle_Y, rot_angle_Z);
}
void Cube::RotateY()
{
model = glm::mat4(1.0f);
rot_angle_Y += 90.0f;
if (rot_angle_Y >= 360.0f)
{
rot_angle_Y = 0.0f;
}
Rotate(model, rot_angle_X, rot_angle_Y, rot_angle_Z);
}
void Cube::RotateZ()
{
model = glm::mat4(1.0f);
rot_angle_Z += 90.0f;
if (rot_angle_Z >= 360.0f)
{
rot_angle_Z = 0.0f;
}
Rotate(model, rot_angle_X, rot_angle_Y, rot_angle_Z);
}
void Cube::Draw()
{
cShader.Bind();
glBindVertexArray(cubeVAO);
glDrawArrays(GL_QUADS, 0, vertices.size() / 2);
}
void Cube::SetMatrices(glm::mat4& v, glm::mat4& p)
{
cShader.Bind();
glBindVertexArray(cubeVAO);
cShader.SetUniformMat4fv("model", 1, GL_FALSE, model);
cShader.SetUniformMat4fv("view", 1, GL_FALSE, v);
cShader.SetUniformMat4fv("projection", 1, GL_FALSE, p);
}
我想不通我哪里做错了。任何想法或帮助将不胜感激!!!
矩阵乘法不是commutative。变薄意味着
rotateX(a) * rotateY(b) * rotateX(c)
与 rotateX(a+c) * rotateY(b)
不同。
不加角度,而是将新的旋转矩阵乘以当前模型矩阵:
class Cube
{
public:
glm::mat4 model = glm::mat4(1.0f);
// [...]
}
void Rotate(glm::mat4& mat, float ang_x, float ang_y, float ang_z)
{
glm::mat4 transformX = glm::rotate(glm::mat4(1.0f), glm::radians(ang_x), glm::vec3(1.0f, 0.0f, 0.0f));
glm::mat4 transformY = glm::rotate(glm::mat4(1.0f), glm::radians(ang_y), glm::vec3(0.0f, 1.0f, 0.0f));
glm::mat4 transformZ = glm::rotate(glm::mat4(1.0f), glm::radians(ang_z), glm::vec3(0.0f, 0.0f, 1.0f));
mat = transformX * transformY * transformZ * mat;
}
void Cube::RotateX()
{
Rotate(model, 90.0f, 0.0f, 0.0f);
}
void Cube::RotateY()
{
Rotate(model, 0.0f, 90.0f, 0.0f);
}
void Cube::RotateZ()
{
Rotate(model, 0.0f, 0.0f, 90.0f);
}
我有一个小的 opengl 世界,我尝试用模型矩阵制作一个小立方体并围绕原点轴旋转它。我几乎把所有事情都做对了,但我的问题是,每当我尝试链接旋转时,即(一次在 x 轴上旋转,然后在不重置矩阵的情况下在 y 轴上旋转)我没有得到我想要的。我希望立方体在固定轴上旋转,但立方体在其自己的轴上旋转。我的意思是说我想使用原点的轴旋转但模型使用它自己的轴旋转,轴保持在原点但它有点随模型旋转。我以为我的相机在移动而不是模型,但是当我尝试使用多个盒子时它证明我的相机在它自己的位置上。我不知道如何进行正确的旋转。这是我所做的代码(一些代码来自 learnopengl.com):
x_Camera camera;
class XYZ_line
{
public:
glm::vec3 xCol, yCol, zCol;
std::vector<glm::vec3>m_Vertices;
unsigned int VBO, VAO;
GAME::Shader shader;
glm::mat4 model;
inline void Init()
{
model = glm::mat4(1.0f);
shader.Init(GAME::CubeVsShader, GAME::CubeFsShader);
shader.Bind();
xCol = glm::vec3(1.0f, 0.0f, 0.0f);
yCol = glm::vec3(0.0f, 1.0f, 0.0f);
zCol = glm::vec3(0.0f, 0.0f, 1.0f);
float x1 = 0.0f, x2 = 800.0f;
m_Vertices.push_back(glm::vec3(x1, 0.0f, 0.0f)); m_Vertices.push_back(xCol);
m_Vertices.push_back(glm::vec3(x2, 0.0f, 0.0f)); m_Vertices.push_back(xCol);
m_Vertices.push_back(glm::vec3(0.0f, x1, 0.0f)); m_Vertices.push_back(yCol);
m_Vertices.push_back(glm::vec3(0.0f, x2, 0.0f)); m_Vertices.push_back(yCol);
m_Vertices.push_back(glm::vec3(0.0f, 0.0f, x1)); m_Vertices.push_back(zCol);
m_Vertices.push_back(glm::vec3(0.0f, 0.0f, x2)); m_Vertices.push_back(zCol);
glGenVertexArrays(1, &VAO);
glGenBuffers(1, &VBO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBindVertexArray(VAO);
glBufferData(GL_ARRAY_BUFFER, sizeof(glm::vec3) * m_Vertices.size(), &m_Vertices[0], GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(float) * 6, 0);
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(float) * 6, (void*)(sizeof(float) * 3));
}
void SetMatrices(glm::mat4& v, glm::mat4& p)
{
shader.Bind();
glBindVertexArray(VAO);
shader.SetUniformMat4fv("projection", 1, GL_FALSE, p);
shader.SetUniformMat4fv("view", 1, GL_FALSE, v);
shader.SetUniformMat4fv("model", 1, GL_FALSE, model);
}
void Draw()
{
shader.Bind();
glBindVertexArray(VAO);
glDrawArrays(GL_LINES, 0, m_Vertices.size() / 2);
}
};
void KeyCallback(GLFWwindow* window, int key, int scancode, int action, int mods);
void processInput(GLFWwindow* window);
float deltaTime = 0.0f;
float lastFrame = 0.0f;
glm::mat4 projection;
glm::mat4 view;
Cube cube;
const glm::vec3 fCol = glm::vec3(1.0f, 1.0f, 1.0f);//white
const glm::vec3 bCol = glm::vec3(1.0f, 0.6f, 0.0f);//orange
const glm::vec3 rCol = glm::vec3(1.0f, 0.0f, 0.0f);//red
const glm::vec3 lCol = glm::vec3(1.0f, 1.0f, 0.0f);//yellow
const glm::vec3 uCol = glm::vec3(0.0f, 0.0f, 1.0f);//blue
const glm::vec3 dCol = glm::vec3(0.0f, 1.0f, 0.0f);//green
int main()
{
GLFWwindow* window;
if (!glfwInit())
{
return -1;
}
window = glfwCreateWindow(800, 800, "TEST", NULL, NULL);
if (!window)
{
glfwTerminate();
return -1;
}
glfwMakeContextCurrent(window);
if (glewInit() != GLEW_OK)
{
glfwTerminate();
return -1;
}
glfwSetKeyCallback(window, KeyCallback);
camera.Init(glm::vec3(0.0f, 0.0f, 10.0f));
XYZ_line xyzLine1;
xyzLine1.Init();
float bSize = 1.0f;
float x1 = -1.6f, x2 = -0.5f, x3 = 0.6f;
float z1 = 1.6f, z2 = 0.5f, z3 = -0.6f;
cube.Init(glm::vec3(x1, x3, z1), bSize);
cube.m_Color_L = lCol; cube.m_Color_R = rCol; cube.m_Color_F = fCol;
cube.m_Color_B = bCol; cube.m_Color_U = uCol; cube.m_Color_D = dCol;
cube.SetVertexData();
glEnable(GL_DEPTH_TEST);
while (!glfwWindowShouldClose(window))
{
float currentFrame = glfwGetTime();
deltaTime = currentFrame - lastFrame;
lastFrame = currentFrame;
processInput(window);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glClearColor(0.8f, 0.8f, 0.8f, 1.0f);
view = camera.GetViewMatrix();
projection = glm::perspective(glm::radians(camera.Zoom), 1.0f, 0.1f, 10000.0f);
xyzLine1.model = cube.model;
xyzLine1.SetMatrices(view, projection);
xyzLine1.Draw();
cube.SetMatrices(view, projection);
cube.Draw();
glfwSwapBuffers(window);
glfwPollEvents();
}
glfwTerminate();
return 0;
}
void processInput(GLFWwindow* window)
{
if (glfwGetKey(window, GLFW_KEY_W) == GLFW_PRESS)
{
camera.ProcessKeyboard(Camera_Movement::FORWARD, deltaTime);
}
if (glfwGetKey(window, GLFW_KEY_S) == GLFW_PRESS)
{
camera.ProcessKeyboard(Camera_Movement::BACKWARD, deltaTime);
}
if (glfwGetKey(window, GLFW_KEY_A) == GLFW_PRESS)
{
camera.ProcessKeyboard(Camera_Movement::LEFT, deltaTime);
}
if (glfwGetKey(window, GLFW_KEY_D) == GLFW_PRESS)
{
camera.ProcessKeyboard(Camera_Movement::RIGHT, deltaTime);
}
if (glfwGetKey(window, GLFW_KEY_Q) == GLFW_PRESS)
{
camera.ProcessKeyboard(Camera_Movement::UP, deltaTime);
}
if (glfwGetKey(window, GLFW_KEY_E) == GLFW_PRESS)
{
camera.ProcessKeyboard(Camera_Movement::DOWN, deltaTime);
}
}
void KeyCallback(GLFWwindow* window, int key, int scancode, int action, int mods)
{
if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
{
glfwSetWindowShouldClose(window, true);
}
if (glfwGetKey(window, GLFW_KEY_X) == GLFW_PRESS)
{
cube.RotateX();
}
if (glfwGetKey(window, GLFW_KEY_Y) == GLFW_PRESS)
{
cube.RotateY();
}
if (glfwGetKey(window, GLFW_KEY_Z) == GLFW_PRESS)
{
cube.RotateZ();
}
}
和我的 Cube
class:
class Cube
{
public:
glm::vec3 t1, t2, t3, t4;
glm::vec3 b1, b2, b3, b4;
glm::vec3 m_Color_L, m_Color_R, m_Color_U, m_Color_D, m_Color_F, m_Color_B;
glm::mat4 model;
float m_CubeSize;
float rot_angle_X = 0.0f;
float rot_angle_Y = 0.0f;
float rot_angle_Z = 0.0f;
Cube();
void Init(glm::vec3 _from, float CubeSize);
Cube(const Cube& e);
Cube& operator=(const Cube& e);
Cube(Cube&& e)noexcept;
Cube& operator=(Cube&& e)noexcept;
Cube* operator-> () { return this; }
operator Cube* () { return this; }
Cube* Clone() { return new Cube(*this); }
void SetVertexData();
unsigned int GetVertexDataSize() { return vertices.size(); }
void Reset();
glm::vec3 GetCenter();
private:
glm::vec3 m_Min, m_Max, m_Cpt;
std::vector<glm::vec3>vertices;
void SetEdgeVertices(glm::vec3 _from, float size);
public:
Shader cShader;
unsigned int cubeVBO, cubeVAO;
void RotateX();
void RotateY();
void RotateZ();
void Draw();
glm::vec3 GetPosition() { return model[3]; }
void SetMatrices(glm::mat4& v, glm::mat4& p);
private:
};
const std::string CubeVsShader =
{
"#version 330 core\n"
"layout(location=0) in vec4 pos;\n"
"layout(location=1) in vec4 col;\n"
"\n"
"uniform mat4 model;\n"
"uniform mat4 view;\n"
"uniform mat4 projection;\n"
"\n"
"out vec4 color;\n"
"void main(){\n"
"gl_Position=projection*view*model*pos;\n"
"color=col;\n"
"}\n"
"\n"
};
const std::string CubeFsShader =
{
"#version 330 core\n"
"out vec4 FragColor;\n"
"\n"
"in vec4 color;\n"
"void main(){\n"
"FragColor=color;\n"
"}\n"
"\n"
};
Cube::Cube()
:t1(glm::vec3()), t2(glm::vec3()), t3(glm::vec3()), t4(glm::vec3()),
b1(glm::vec3()), b2(glm::vec3()), b3(glm::vec3()), b4(glm::vec3()), m_CubeSize(0.0f)
{
}
void Cube::Init(glm::vec3 _from, float CubeSize)
{
SetEdgeVertices(_from, CubeSize);
model = glm::mat4(1.0f);
cShader.Init(CubeVsShader, CubeFsShader);
cShader.Bind();
glGenVertexArrays(1, &cubeVAO);
glGenBuffers(1, &cubeVBO);
glBindBuffer(GL_ARRAY_BUFFER, cubeVBO);
glBindVertexArray(cubeVAO);
glBufferData(GL_ARRAY_BUFFER, sizeof(glm::vec3) * 48, 0, GL_DYNAMIC_DRAW);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(float) * 6, 0);
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(float) * 6, (void*)(sizeof(float) * 3));
}
Cube::Cube(const Cube& e)
{
t1 = e.t1; t2 = e.t2; t3 = e.t3; t4 = e.t4;
b1 = e.b1; b2 = e.b2; b3 = e.b3; b4 = e.b4;
m_CubeSize = e.m_CubeSize;
m_Color_L = e.m_Color_L;
m_Color_R = e.m_Color_R;
m_Color_U = e.m_Color_U;
m_Color_D = e.m_Color_D;
m_Color_F = e.m_Color_F;
m_Color_B = e.m_Color_B;
cShader = e.cShader;
cubeVBO = e.cubeVBO;
cubeVAO = e.cubeVAO;
rot_angle_X = e.rot_angle_X;
rot_angle_Y = e.rot_angle_Y;
rot_angle_Z = e.rot_angle_Z;
model = e.model;
AddToVector(vertices, e.vertices);
m_Min = e.m_Min;
m_Max = e.m_Max;
m_Cpt = e.m_Cpt;
}
Cube& Cube::operator=(const Cube& e)
{
t1 = e.t1; t2 = e.t2; t3 = e.t3; t4 = e.t4;
b1 = e.b1; b2 = e.b2; b3 = e.b3; b4 = e.b4;
m_CubeSize = e.m_CubeSize;
m_Color_B = e.m_Color_B;
m_Color_F = e.m_Color_F;
m_Color_L = e.m_Color_L;
m_Color_R = e.m_Color_R;
m_Color_U = e.m_Color_U;
m_Color_D = e.m_Color_D;
cShader = e.cShader;
cubeVBO = e.cubeVBO;
cubeVAO = e.cubeVAO;
model = e.model;
rot_angle_X = e.rot_angle_X;
rot_angle_Y = e.rot_angle_Y;
rot_angle_Z = e.rot_angle_Z;
AddToVector(vertices, e.vertices);
m_Min = e.m_Min;
m_Max = e.m_Max;
m_Cpt = e.m_Cpt;
return *this;
}
Cube::Cube(Cube&& e) noexcept
{
t1 = std::move(e.t1); t2 = std::move(e.t2); t3 = std::move(e.t3); t4 = std::move(e.t4);
b1 = std::move(e.b1); b2 = std::move(e.b2); b3 = std::move(e.b3); b4 = std::move(e.b4);
m_CubeSize = std::move(e.m_CubeSize);
m_Color_B = std::move(e.m_Color_B);
m_Color_F = std::move(e.m_Color_F);
m_Color_L = std::move(e.m_Color_L);
m_Color_R = std::move(e.m_Color_R);
m_Color_U = std::move(e.m_Color_U);
m_Color_D = std::move(e.m_Color_D);
cShader = std::move(e.cShader);
cubeVBO = std::move(e.cubeVBO);
cubeVAO = std::move(e.cubeVAO);
model = std::move(e.model);
rot_angle_X = std::move(e.rot_angle_X);
rot_angle_Y = std::move(e.rot_angle_Y);
rot_angle_Z = std::move(e.rot_angle_Z);
AddToVector(vertices, std::move(e.vertices));
m_Min = std::move(e.m_Min);
m_Max = std::move(e.m_Max);
m_Cpt = std::move(e.m_Cpt);
}
Cube& Cube::operator=(Cube&& e) noexcept
{
t1 = std::move(e.t1); t2 = std::move(e.t2); t3 = std::move(e.t3); t4 = std::move(e.t4);
b1 = std::move(e.b1); b2 = std::move(e.b2); b3 = std::move(e.b3); b4 = std::move(e.b4);
m_CubeSize = std::move(e.m_CubeSize);
m_Color_B = std::move(e.m_Color_B);
m_Color_F = std::move(e.m_Color_F);
m_Color_L = std::move(e.m_Color_L);
m_Color_R = std::move(e.m_Color_R);
m_Color_U = std::move(e.m_Color_U);
m_Color_D = std::move(e.m_Color_D);
cShader = std::move(e.cShader);
cubeVBO = std::move(e.cubeVBO);
cubeVAO = std::move(e.cubeVAO);
model = std::move(e.model);
rot_angle_X = std::move(e.rot_angle_X);
rot_angle_Y = std::move(e.rot_angle_Y);
rot_angle_Z = std::move(e.rot_angle_Z);
m_Min = std::move(e.m_Min);
m_Max = std::move(e.m_Max);
m_Cpt = std::move(e.m_Cpt);
AddToVector(vertices, std::move(e.vertices));
return *this;
}
void Cube::SetVertexData()
{
ResetVectors(&vertices);
vertices.push_back(b1); vertices.push_back(m_Color_D); vertices.push_back(b2); vertices.push_back(m_Color_D);
vertices.push_back(b3); vertices.push_back(m_Color_D); vertices.push_back(b4); vertices.push_back(m_Color_D);
vertices.push_back(t1); vertices.push_back(m_Color_U); vertices.push_back(t2); vertices.push_back(m_Color_U);
vertices.push_back(t3); vertices.push_back(m_Color_U); vertices.push_back(t4); vertices.push_back(m_Color_U);
vertices.push_back(b1); vertices.push_back(m_Color_L); vertices.push_back(b2); vertices.push_back(m_Color_L);
vertices.push_back(t2); vertices.push_back(m_Color_L); vertices.push_back(t1); vertices.push_back(m_Color_L);
vertices.push_back(b4); vertices.push_back(m_Color_R); vertices.push_back(b3); vertices.push_back(m_Color_R);
vertices.push_back(t3); vertices.push_back(m_Color_R); vertices.push_back(t4); vertices.push_back(m_Color_R);
vertices.push_back(b2); vertices.push_back(m_Color_B); vertices.push_back(b3); vertices.push_back(m_Color_B);
vertices.push_back(t3); vertices.push_back(m_Color_B); vertices.push_back(t2); vertices.push_back(m_Color_B);
vertices.push_back(b1); vertices.push_back(m_Color_F); vertices.push_back(b4); vertices.push_back(m_Color_F);
vertices.push_back(t4); vertices.push_back(m_Color_F); vertices.push_back(t1); vertices.push_back(m_Color_F);
cShader.Bind();
glBindVertexArray(cubeVAO);
glBindBuffer(GL_ARRAY_BUFFER, cubeVBO);
glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(glm::vec3) * vertices.size(), &vertices[0]);
}
void Cube::Reset()
{
b1 = b2 = b3 = b4 = t1 = t2 = t3 = t4 = glm::vec3(0.0f);
m_Color_B = m_Color_F = m_Color_U = glm::vec3(0.0f);
m_Color_D = m_Color_L = m_Color_R = glm::vec3(0.0f);
m_CubeSize = 0.0f;
this->cubeVBO = 0;
ResetVectors(&this->vertices);
this->cShader.Reset();
}
glm::vec3 Cube::GetCenter()
{
return m_Cpt;
}
void Cube::SetEdgeVertices(glm::vec3 _from, float size)
{
glm::vec3 _min(_from), _max;
_max.x = _min.x + size; _max.y = _min.y + size; _max.z = _min.z - size;
this->m_Min = _min; this->m_Max = _max;
this->m_Cpt = (_max + _min) / glm::vec3(2.0f);
this->b1 = glm::vec3(_min.x, _min.y, _min.z); this->b2 = glm::vec3(_min.x, _min.y, _max.z);
this->b3 = glm::vec3(_max.x, _min.y, _max.z); this->b4 = glm::vec3(_max.x, _min.y, _min.z);
this->t1 = glm::vec3(_min.x, _max.y, _min.z); this->t2 = glm::vec3(_min.x, _max.y, _max.z);
this->t3 = glm::vec3(_max.x, _max.y, _max.z); this->t4 = glm::vec3(_max.x, _max.y, _min.z);
this->m_CubeSize = size;
}
void Rotate(glm::mat4& mat, float ang_x, float ang_y, float ang_z)
{
glm::mat4 transformX = glm::mat4(1.0f);
glm::mat4 transformY = glm::mat4(1.0f);
glm::mat4 transformZ = glm::mat4(1.0f);
transformX = glm::rotate(transformX, glm::radians(ang_x), glm::vec3(1.0f, 0.0f, 0.0f));
transformY = glm::rotate(transformY, glm::radians(ang_y), glm::vec3(0.0f, 1.0f, 0.0f));
transformZ = glm::rotate(transformZ, glm::radians(ang_z), glm::vec3(0.0f, 0.0f, 1.0f));
mat = transformX * transformY * transformZ;
}
void Cube::RotateX()
{
model = glm::mat4(1.0f);
rot_angle_X += 90.0f;
if (rot_angle_X >= 360.0f)
{
rot_angle_X = 0.0f;
}
Rotate(model, rot_angle_X, rot_angle_Y, rot_angle_Z);
}
void Cube::RotateY()
{
model = glm::mat4(1.0f);
rot_angle_Y += 90.0f;
if (rot_angle_Y >= 360.0f)
{
rot_angle_Y = 0.0f;
}
Rotate(model, rot_angle_X, rot_angle_Y, rot_angle_Z);
}
void Cube::RotateZ()
{
model = glm::mat4(1.0f);
rot_angle_Z += 90.0f;
if (rot_angle_Z >= 360.0f)
{
rot_angle_Z = 0.0f;
}
Rotate(model, rot_angle_X, rot_angle_Y, rot_angle_Z);
}
void Cube::Draw()
{
cShader.Bind();
glBindVertexArray(cubeVAO);
glDrawArrays(GL_QUADS, 0, vertices.size() / 2);
}
void Cube::SetMatrices(glm::mat4& v, glm::mat4& p)
{
cShader.Bind();
glBindVertexArray(cubeVAO);
cShader.SetUniformMat4fv("model", 1, GL_FALSE, model);
cShader.SetUniformMat4fv("view", 1, GL_FALSE, v);
cShader.SetUniformMat4fv("projection", 1, GL_FALSE, p);
}
我想不通我哪里做错了。任何想法或帮助将不胜感激!!!
矩阵乘法不是commutative。变薄意味着
rotateX(a) * rotateY(b) * rotateX(c)
与 rotateX(a+c) * rotateY(b)
不同。
不加角度,而是将新的旋转矩阵乘以当前模型矩阵:
class Cube
{
public:
glm::mat4 model = glm::mat4(1.0f);
// [...]
}
void Rotate(glm::mat4& mat, float ang_x, float ang_y, float ang_z)
{
glm::mat4 transformX = glm::rotate(glm::mat4(1.0f), glm::radians(ang_x), glm::vec3(1.0f, 0.0f, 0.0f));
glm::mat4 transformY = glm::rotate(glm::mat4(1.0f), glm::radians(ang_y), glm::vec3(0.0f, 1.0f, 0.0f));
glm::mat4 transformZ = glm::rotate(glm::mat4(1.0f), glm::radians(ang_z), glm::vec3(0.0f, 0.0f, 1.0f));
mat = transformX * transformY * transformZ * mat;
}
void Cube::RotateX()
{
Rotate(model, 90.0f, 0.0f, 0.0f);
}
void Cube::RotateY()
{
Rotate(model, 0.0f, 90.0f, 0.0f);
}
void Cube::RotateZ()
{
Rotate(model, 0.0f, 0.0f, 90.0f);
}