这是一些关于矩阵变换的opengl代码。相机的缩放和移动都很好,但是旋转部分不好。我们要做的是围绕物体旋转相机(在x和z方向),这应该是在camera函数中完成的,但是当我们调用它时,camera只是上下移动。当我们在main中使用完全相同的rotate代码而不调用函数时,轮换工作正常,我们遗漏了什么?
// Include standard headers
#include <stdio.h>
#include <stdlib.h>
#include <string>
#include <vector>
#include <iostream>
#include <fstream>
#include <algorithm>
#include <sstream>
// Include GLEW
#include <GL/glew.h>
// Include GLFW
#include <GLFW/glfw3.h>
GLFWwindow* window;
// Include GLM
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
using namespace glm;
using namespace std;
glm::mat4 ViewMatrix;
glm::mat4 ProjectionMatrix;
glm::mat4 ModelMatrix = glm::mat4(1.0); // added model matrix
glm::mat4 getViewMatrix() {
return ViewMatrix;
}
glm::mat4 getProjectionMatrix() {
return ProjectionMatrix;
}
// Initial position : on +Z
glm::vec3 position = glm::vec3(0, 10, 0);
// Initial horizontal angle : toward -Z
float horizontalAngle = 3.14f;
// Initial vertical angle : none
float verticalAngle = 2.0f;
// Initial Field of View
float initialFoV = 90.0f;
float speed = 3.0f; // 3 units / second
float mouseSpeed = 0.005f;
float h = rand() % (9) + 2.0f;
float height = h / 2;
void camera_function() //shamelessly copied by controls (camera example)
{
// glfwGetTime is called only once, the first time this function is called
static double lastTime = glfwGetTime();
// Compute time difference between current and last frame
double currentTime = glfwGetTime();
float deltaTime = float(currentTime - lastTime);
// Get mouse position
double xpos, ypos;
glfwGetCursorPos(window, &xpos, &ypos);
// Reset mouse position for next frame
glfwSetCursorPos(window, 1024 / 2, 768 / 2);
// Compute new orientation
horizontalAngle += mouseSpeed * float(1024 / 2 - xpos);
verticalAngle += mouseSpeed * float(768 / 2 - ypos);
// Direction : Spherical coordinates to Cartesian coordinates conversion
glm::vec3 direction(
cos(verticalAngle) * sin(horizontalAngle),
sin(verticalAngle),
cos(verticalAngle) * cos(horizontalAngle)
);
// Right vector
glm::vec3 right = glm::vec3(
sin(horizontalAngle - 3.14f / 2.0f),
0,
cos(horizontalAngle - 3.14f / 2.0f)
);
// Up vector
glm::vec3 up = glm::cross(right, direction);
float r = 45.0f;
// Move forward
if (glfwGetKey(window, GLFW_KEY_KP_ADD) == GLFW_PRESS) { //zoom in
position += direction * deltaTime * speed;
}
// Move backward
if (glfwGetKey(window, GLFW_KEY_KP_SUBTRACT) == GLFW_PRESS) { //zoom out
position -= direction * deltaTime * speed;
}
// rotate right - problem here
if (glfwGetKey(window, GLFW_KEY_W) == GLFW_PRESS) {
r+=5;
glm::mat4 SMatrix = glm::rotate(SMatrix, glm::radians(r), glm::vec3(1,0,0));
ModelMatrix = SMatrix;
//change to rotation for axis x
}
// rotate left - problem here
if (glfwGetKey(window, GLFW_KEY_X) == GLFW_PRESS) {
r-=5;
glm::mat4 SMatrix = glm::rotate(SMatrix, glm::radians(r), glm::vec3(1,0,0));
ModelMatrix = SMatrix;
//change to rotation for axis x
}
// Move up
if (glfwGetKey(window, GLFW_KEY_Q) == GLFW_PRESS) {
position += up * deltaTime * speed;
//change to rotation for axis z
}
// Move down
if (glfwGetKey(window, GLFW_KEY_Z) == GLFW_PRESS) {
position -= up * deltaTime * speed;
//change to rotation for axis z
}
float FoV = initialFoV;
// Projection matrix : 45° Field of View, 4:3 ratio, display range : 0.1 unit <-> 100 units
ProjectionMatrix = glm::perspective(glm::radians(FoV), 4.0f / 4.0f, 0.1f, 100.0f);
// Camera matrix
ViewMatrix = glm::lookAt(
position, // Camera is here
position + direction, // and looks here : at the same position, plus "direction"
up // Head is up (set to 0,-1,0 to look upside-down)
// For the next frame, the "last time" will be "now"
);
lastTime = currentTime;
}
// loadshaders was given, i have not written it so the post isnt too long
int main(void)
{
// Initialise GLFW
if (!glfwInit())
{
fprintf(stderr, "Failed to initialize GLFW\n");
getchar();
return -1;
}
glfwWindowHint(GLFW_SAMPLES, 4);
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
const char* title = u8"\u0395\u03c1\u03b3\u03b1\u03c3\u03af\u03b1\u0020\u0031\u0392\u0020\u002d\u0020\u03a4\u03c1\u03b1\u03c0\u03b5\u03b6\u03bf\u03b5\u03b9\u03b4\u03ad\u03c2\u0020\u03a0\u03c1\u03af\u03c3\u03bc\u03b1";
// Open a window and create its OpenGL context
window = glfwCreateWindow(1000, 1000, title, NULL, NULL);
if (window == NULL) {
fprintf(stderr, "Failed to open GLFW window. If you have an Intel GPU, they are not 3.3 compatible. Try the 2.1 version of the tutorials.\n");
getchar();
glfwTerminate();
return -1;
}
glfwMakeContextCurrent(window);
// Initialize GLEW
glewExperimental = true; // Needed for core profile
if (glewInit() != GLEW_OK) {
fprintf(stderr, "Failed to initialize GLEW\n");
getchar();
glfwTerminate();
return -1;
}
// Ensure we can capture the escape key being pressed below
glfwSetInputMode(window, GLFW_STICKY_KEYS, GL_TRUE);
// Dark green background
glClearColor(0.0f, 0.0f, 0.4f, 0.0f);
glEnable(GL_DEPTH_TEST);
GLuint VertexArrayID;
glGenVertexArrays(1, &VertexArrayID);
glBindVertexArray(VertexArrayID);
// Create and compile our GLSL program from the shaders
GLuint programID = LoadShaders("ProjBVertexShader.vertexshader", "ProjBFragmentShader.fragmentshader");
GLuint MatrixID = glGetUniformLocation(programID, "MVP");
glm::mat4 Projection = glm::perspective(glm::radians(45.0f), 4.0f / 4.0f, 0.1f, 100.0f);
// Camera matrix
glm::mat4 View = glm::lookAt(
glm::vec3(10.0f, 50.0f, 0.0f),
glm::vec3(0.0f, 0.0f, 0.0f),
glm::vec3(0.0f, 0.0f, 1.0f)
);
// Model matrix : an identity matrix (model will be at the origin)
glm::mat4 Model = glm::mat4(1.0f);
// Our ModelViewProjection : multiplication of our 3 matrices
glm::mat4 MVP = Projection * View * Model; // Remember, matrix multiplication is the other way around
// also removed vertex buffer data - was given
GLuint vertexbuffer;
glGenBuffers(1, &vertexbuffer);
glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(g_vertex_buffer_data), g_vertex_buffer_data, GL_STATIC_DRAW);
GLuint colorbuffer;
glGenBuffers(1, &colorbuffer);
glBindBuffer(GL_ARRAY_BUFFER, colorbuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(g_color_buffer_data), g_color_buffer_data, GL_STATIC_DRAW);
glm::mat4 ModelMatrix = glm::mat4(1.0);
do {
// Clear the screen
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// Use our shader
glUseProgram(programID);
glm::mat4 ProjectionMatrix = getProjectionMatrix();
glm::mat4 ViewMatrix = getViewMatrix();
glm::mat4 MVP = ProjectionMatrix * ViewMatrix * ModelMatrix;
float sz = 1.0f;
/* problem here, this method only works when in main - not when called as camerafunction
float r = 0.0f;
if (glfwGetKey(window, GLFW_KEY_W) == GLFW_PRESS) {
r += 5;
ModelMatrix = glm::rotate(ModelMatrix, glm::radians(r), glm::vec3(1, 0, 0));
//change to rotation for axis x
}
*/
if (glfwGetKey(window, GLFW_KEY_U) == GLFW_PRESS) {
sz = sz + 0.01f;
ModelMatrix = glm::scale(ModelMatrix, glm::vec3(1.0f, 1.0f, sz));
}
if (glfwGetKey(window, GLFW_KEY_P) == GLFW_PRESS) {
sz = sz - 0.01f;
ModelMatrix = glm::scale(ModelMatrix, glm::vec3(1.0f, 1.0f, sz));
}
glUniformMatrix4fv(MatrixID, 1, GL_FALSE, &MVP[0][0]);
camera_function();
// 1rst attribute buffer : vertices
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
glVertexAttribPointer(
0, // attribute 0. No particular reason for 0, but must match the layout in the shader.
3, // size
GL_FLOAT, // type
GL_FALSE, // normalized?
0, // stride
(void*)0 // array buffer offset
);
// 2nd attribute buffer : colors
glEnableVertexAttribArray(1);
glBindBuffer(GL_ARRAY_BUFFER, colorbuffer);
glVertexAttribPointer(
1, // attribute. No particular reason for 1, but must match the layout in the shader.
3, // size
GL_FLOAT, // type
GL_FALSE, // normalized?
0, // stride
(void*)0 // array buffer offset
);
// Draw the triangle !
glDrawArrays(GL_TRIANGLES, 0, 12 * 3); // 3 indices starting at 0 -> 1 triangle
glDisableVertexAttribArray(0);
glDisableVertexAttribArray(1);
// Swap buffers
glfwSwapBuffers(window);
glfwPollEvents();
} // Check if the ESC key was pressed or the window was closed
while (glfwGetKey(window, GLFW_KEY_SPACE) != GLFW_PRESS &&
glfwWindowShouldClose(window) == 0);
// Cleanup VBO
glDeleteBuffers(1, &vertexbuffer);
glDeleteVertexArrays(1, &VertexArrayID);
glDeleteProgram(programID);
// Close OpenGL window and terminate GLFW
glfwTerminate();
return 0;
}
我们尝试在每个函数都能看到的地方初始化模型矩阵,但失败了,然后尝试在相机函数中初始化它,但按下键什么也没做。我们认为我们缺少一些变量,或者相机函数中没有的主要变量,但似乎都匹配。
1条答案
按热度按时间wfsdck301#
你的浮点数r = 45.0f;在rotate函数中局部定义,因此它始终在每帧创建,并且值从不递增。
float r = 45.0f使其成为全局变量或静态变量。