Camera_练习二

试着创建你自己的LookAt函数,其中你需要手动创建一个我们在一开始讨论的观察矩阵。用你的函数实现来替换GLM的LookAt函数,看看它是否还能一样地工作

1 glm::mat4 LookAt(glm::vec3 pos, glm::vec3 r, glm::vec3 u, glm::vec3 d){
2     glm::mat4 a = glm::mat4(1.0f);
3     a[0][0] = r.x; a[1][0] = r.y; a[2][0] = r.z;
4     a[0][1] = u.x; a[1][1] = u.y; a[2][1] = u.z;
5     a[0][2] = -d.x; a[1][2] = -d.y; a[2][2] = -d.z;
6     glm::mat4 b = glm::mat4(1.0f);
7     b = glm::translate(b, glm::vec3(-pos.x, -pos.y, -pos.z));
8     return a*b;
9 }
View Code

根据定义,由方向向量、右轴和上轴构成的矩阵与由摄像机坐标构成的矩阵相乘就得到LookAt矩阵了

注意:

  1. 方向向量和我们定义的Front(摄像机的朝向)是相反的
  2. glm中矩阵的存储和现实中的矩阵是不同的,glm中矩阵的列对应着现实中矩阵的行

 

最后还需调用glm::mat4 view = LookAt(camera.Position, camera.Right, camera.Up, camera.Front);即可

  1 #include <glad/glad.h>
  2 #include <GLFW/glfw3.h>
  3 #define STB_IMAGE_IMPLEMENTATION
  4 #include <stb/stb_image.h>
  5 
  6 #include <glm/glm.hpp>
  7 #include <glm/gtc/matrix_transform.hpp>
  8 #include <glm/gtc/type_ptr.hpp>
  9 
 10 #include <Shader/shader.h>
 11 #include <Camera/camera.h>
 12 
 13 #include <iostream>
 14 
 15 void framebuffer_size_callback(GLFWwindow* window, int width, int height);
 16 void mouse_callback(GLFWwindow* window, double xpos, double ypos);
 17 void scroll_callback(GLFWwindow* window, double xoffset, double yoffset);
 18 void processInput(GLFWwindow *window);
 19 
 20 // settings
 21 const unsigned int SCR_WIDTH = 800;
 22 const unsigned int SCR_HEIGHT = 600;
 23 
 24 // camera
 25 Camera camera(glm::vec3(0.0f, 0.0f, 3.0f));
 26 float lastX = SCR_WIDTH / 2.0f;
 27 float lastY = SCR_HEIGHT / 2.0f;
 28 bool firstMouse = true;
 29 
 30 //timeing
 31 float deltaTime = 0.0f; // 当前帧与上一帧的时间差
 32 float lastFrame = 0.0f; // 上一帧的时间
 33 
 34 glm::mat4 LookAt(glm::vec3 pos, glm::vec3 r, glm::vec3 u, glm::vec3 d){
 35     glm::mat4 a = glm::mat4(1.0f);
 36     a[0][0] = r.x; a[1][0] = r.y; a[2][0] = r.z;
 37     a[0][1] = u.x; a[1][1] = u.y; a[2][1] = u.z;
 38     a[0][2] = -d.x; a[1][2] = -d.y; a[2][2] = -d.z;
 39     glm::mat4 b = glm::mat4(1.0f);
 40     b = glm::translate(b, glm::vec3(-pos.x, -pos.y, -pos.z));
 41     return a*b;
 42 }
 43 
 44 int main()
 45 {
 46     // glfw: initialize and configure
 47     // ------------------------------
 48     glfwInit();
 49     glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
 50     glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
 51     glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
 52 
 53 #ifdef __APPLE__
 54     glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); // uncomment this statement to fix compilation on OS X
 55 #endif
 56 
 57     // glfw window creation
 58     // --------------------
 59     GLFWwindow* window = glfwCreateWindow(SCR_WIDTH, SCR_HEIGHT, "LearnOpenGL", NULL, NULL);
 60     if (window == NULL)
 61     {
 62         std::cout << "Failed to create GLFW window" << std::endl;
 63         glfwTerminate();
 64         return -1;
 65     }
 66     glfwMakeContextCurrent(window);
 67     glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);
 68     glfwSetCursorPosCallback(window, mouse_callback);
 69     glfwSetScrollCallback(window, scroll_callback);
 70 
 71     // tell GLFW to capture our mouse
 72     glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
 73 
 74     // glad: load all OpenGL function pointers
 75     // ---------------------------------------
 76     if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
 77     {
 78         std::cout << "Failed to initialize GLAD" << std::endl;
 79         return -1;
 80     }
 81 
 82     // configure global opengl state
 83     // -----------------------------
 84     glEnable(GL_DEPTH_TEST);
 85 
 86     // build and compile our shader zprogram
 87     // ------------------------------------
 88     Shader ourShader("vs.in", "fs.in");
 89 
 90     // set up vertex data (and buffer(s)) and configure vertex attributes
 91     // ------------------------------------------------------------------
 92     float vertices[] = {
 93         -0.5f, -0.5f, -0.5f, 0.0f, 0.0f,
 94         0.5f, -0.5f, -0.5f, 1.0f, 0.0f,
 95         0.5f, 0.5f, -0.5f, 1.0f, 1.0f,
 96         0.5f, 0.5f, -0.5f, 1.0f, 1.0f,
 97         -0.5f, 0.5f, -0.5f, 0.0f, 1.0f,
 98         -0.5f, -0.5f, -0.5f, 0.0f, 0.0f,
 99 
100         -0.5f, -0.5f, 0.5f, 0.0f, 0.0f,
101         0.5f, -0.5f, 0.5f, 1.0f, 0.0f,
102         0.5f, 0.5f, 0.5f, 1.0f, 1.0f,
103         0.5f, 0.5f, 0.5f, 1.0f, 1.0f,
104         -0.5f, 0.5f, 0.5f, 0.0f, 1.0f,
105         -0.5f, -0.5f, 0.5f, 0.0f, 0.0f,
106 
107         -0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
108         -0.5f, 0.5f, -0.5f, 1.0f, 1.0f,
109         -0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
110         -0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
111         -0.5f, -0.5f, 0.5f, 0.0f, 0.0f,
112         -0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
113 
114         0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
115         0.5f, 0.5f, -0.5f, 1.0f, 1.0f,
116         0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
117         0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
118         0.5f, -0.5f, 0.5f, 0.0f, 0.0f,
119         0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
120 
121         -0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
122         0.5f, -0.5f, -0.5f, 1.0f, 1.0f,
123         0.5f, -0.5f, 0.5f, 1.0f, 0.0f,
124         0.5f, -0.5f, 0.5f, 1.0f, 0.0f,
125         -0.5f, -0.5f, 0.5f, 0.0f, 0.0f,
126         -0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
127 
128         -0.5f, 0.5f, -0.5f, 0.0f, 1.0f,
129         0.5f, 0.5f, -0.5f, 1.0f, 1.0f,
130         0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
131         0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
132         -0.5f, 0.5f, 0.5f, 0.0f, 0.0f,
133         -0.5f, 0.5f, -0.5f, 0.0f, 1.0f
134     };
135     // world space positions of our cubes
136     glm::vec3 cubePositions[] = {
137         glm::vec3(0.0f, 0.0f, 0.0f),
138         glm::vec3(2.0f, 5.0f, -15.0f),
139         glm::vec3(-1.5f, -2.2f, -2.5f),
140         glm::vec3(-3.8f, -2.0f, -12.3f),
141         glm::vec3(2.4f, -0.4f, -3.5f),
142         glm::vec3(-1.7f, 3.0f, -7.5f),
143         glm::vec3(1.3f, -2.0f, -2.5f),
144         glm::vec3(1.5f, 2.0f, -2.5f),
145         glm::vec3(1.5f, 0.2f, -1.5f),
146         glm::vec3(-1.3f, 1.0f, -1.5f)
147     };
148     unsigned int VBO, VAO;
149     glGenVertexArrays(1, &VAO);
150     glGenBuffers(1, &VBO);
151 
152     glBindVertexArray(VAO);
153 
154     glBindBuffer(GL_ARRAY_BUFFER, VBO);
155     glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
156 
157     // position attribute
158     glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)0);
159     glEnableVertexAttribArray(0);
160     // texture coord attribute
161     glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)(3 * sizeof(float)));
162     glEnableVertexAttribArray(1);
163 
164 
165     // load and create a texture 
166     // -------------------------
167     unsigned int texture1, texture2;
168     // texture 1
169     // ---------
170     glGenTextures(1, &texture1);
171     glBindTexture(GL_TEXTURE_2D, texture1);
172     // set the texture wrapping parameters
173     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
174     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
175     // set texture filtering parameters
176     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
177     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
178     // load image, create texture and generate mipmaps
179     int width, height, nrChannels;
180     stbi_set_flip_vertically_on_load(true); // tell stb_image.h to flip loaded texture's on the y-axis.
181     unsigned char *data = stbi_load("container.jpg", &width, &height, &nrChannels, 0);
182     if (data)
183     {
184         glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, data);
185         glGenerateMipmap(GL_TEXTURE_2D);
186     }
187     else
188     {
189         std::cout << "Failed to load texture" << std::endl;
190     }
191     stbi_image_free(data);
192     // texture 2
193     // ---------
194     glGenTextures(1, &texture2);
195     glBindTexture(GL_TEXTURE_2D, texture2);
196     // set the texture wrapping parameters
197     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
198     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
199     // set texture filtering parameters
200     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
201     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
202     // load image, create texture and generate mipmaps
203     data = stbi_load("awesomeface.png", &width, &height, &nrChannels, 0);
204     if (data)
205     {
206         // note that the awesomeface.png has transparency and thus an alpha channel, so make sure to tell OpenGL the data type is of GL_RGBA
207         glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
208         glGenerateMipmap(GL_TEXTURE_2D);
209     }
210     else
211     {
212         std::cout << "Failed to load texture" << std::endl;
213     }
214     stbi_image_free(data);
215 
216     // tell opengl for each sampler to which texture unit it belongs to (only has to be done once)
217     // -------------------------------------------------------------------------------------------
218     ourShader.use();
219     ourShader.setInt("texture1", 0);
220     ourShader.setInt("texture2", 1);
221 
222     // pass projection matrix to shader (as projection matrix rarely changes there's no need to do this per frame)
223     // -----------------------------------------------------------------------------------------------------------
224     //glm::mat4 projection = glm::perspective(glm::radians(45.0f), (float)SCR_WIDTH / (float)SCR_HEIGHT, 0.1f, 100.0f);
225     //ourShader.setMat4("projection", projection);
226 
227 
228     // render loop
229     // -----------
230     while (!glfwWindowShouldClose(window))
231     {
232         float currentFrame = glfwGetTime();
233         deltaTime = currentFrame - lastFrame;
234         lastFrame = currentFrame;
235 
236         // input
237         // -----
238         processInput(window);
239 
240         // render
241         // ------
242         glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
243         glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
244 
245         // bind textures on corresponding texture units
246         glActiveTexture(GL_TEXTURE0);
247         glBindTexture(GL_TEXTURE_2D, texture1);
248         glActiveTexture(GL_TEXTURE1);
249         glBindTexture(GL_TEXTURE_2D, texture2);
250 
251         // activate shader
252         ourShader.use();
253 
254         // pass projection matrix to shader (note that in this case it could change every frame)
255         glm::mat4 projection = glm::perspective(glm::radians(camera.Zoom), (float)SCR_WIDTH / (float)SCR_HEIGHT, 0.1f, 100.0f);
256         ourShader.setMat4("projection", projection);
257 
258         // camera/view transformation
259 
260         //glm::mat4 view = glm::mat4(1.0f); // make sure to initialize matrix to identity matrix first
261         //float radius = 10.0f;
262         //float camX = sin(glfwGetTime()) * radius;
263         //float camZ = cos(glfwGetTime()) * radius;
264         //view = glm::lookAt(glm::vec3(camX, 0.0f, camZ), glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(0.0f, 1.0f, 0.0f));
265 
266         //glm::mat4 view = camera.GetViewMatrix();
267         glm::mat4 view = LookAt(camera.Position, camera.Right, camera.Up, camera.Front);
268         ourShader.setMat4("view", view);
269 
270         // render boxes
271         glBindVertexArray(VAO);
272         for (unsigned int i = 0; i < 10; i++)
273         {
274             // calculate the model matrix for each object and pass it to shader before drawing
275             glm::mat4 model = glm::mat4(1.0f);
276             model = glm::translate(model, cubePositions[i]);
277             float angle = 20.0f * i;
278             model = glm::rotate(model, glm::radians(angle), glm::vec3(1.0f, 0.3f, 0.5f));
279             ourShader.setMat4("model", model);
280 
281             glDrawArrays(GL_TRIANGLES, 0, 36);
282         }
283 
284         // glfw: swap buffers and poll IO events (keys pressed/released, mouse moved etc.)
285         // -------------------------------------------------------------------------------
286         glfwSwapBuffers(window);
287         glfwPollEvents();
288     }
289 
290     // optional: de-allocate all resources once they've outlived their purpose:
291     // ------------------------------------------------------------------------
292     glDeleteVertexArrays(1, &VAO);
293     glDeleteBuffers(1, &VBO);
294 
295     // glfw: terminate, clearing all previously allocated GLFW resources.
296     // ------------------------------------------------------------------
297     glfwTerminate();
298     return 0;
299 }
300 
301 // process all input: query GLFW whether relevant keys are pressed/released this frame and react accordingly
302 // ---------------------------------------------------------------------------------------------------------
303 void processInput(GLFWwindow *window)
304 {
305     if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
306         glfwSetWindowShouldClose(window, true);
307 
308     if (glfwGetKey(window, GLFW_KEY_W) == GLFW_PRESS)
309         camera.ProcessKeyboard(FORWARD, deltaTime);
310     if (glfwGetKey(window, GLFW_KEY_S) == GLFW_PRESS)
311         camera.ProcessKeyboard(BACKWARD, deltaTime);
312     if (glfwGetKey(window, GLFW_KEY_A) == GLFW_PRESS)
313         camera.ProcessKeyboard(LEFT, deltaTime);
314     if (glfwGetKey(window, GLFW_KEY_D) == GLFW_PRESS)
315         camera.ProcessKeyboard(RIGHT, deltaTime);
316 }
317 
318 // glfw: whenever the window size changed (by OS or user resize) this callback function executes
319 // ---------------------------------------------------------------------------------------------
320 void framebuffer_size_callback(GLFWwindow* window, int width, int height)
321 {
322     // make sure the viewport matches the new window dimensions; note that width and 
323     // height will be significantly larger than specified on retina displays.
324     glViewport(0, 0, width, height);
325 }
326 
327 void mouse_callback(GLFWwindow* window, double xpos, double ypos){
328     if (firstMouse)
329     {
330         lastX = xpos;
331         lastY = ypos;
332         firstMouse = false;
333     }
334 
335     float xoffset = xpos - lastX;
336     float yoffset = lastY - ypos;
337     //std::cout << ypos << std::endl;
338     lastX = xpos;
339     lastY = ypos;
340 
341     camera.ProcessMouseMovement(xoffset, yoffset);
342 }
343 
344 // glfw: whenever the mouse scroll wheel scrolls, this callback is called
345 // ----------------------------------------------------------------------
346 void scroll_callback(GLFWwindow* window, double xoffset, double yoffset)
347 {
348     camera.ProcessMouseScroll(yoffset);
349 }
View Code

 

posted @ 2019-11-29 19:09  ljy3268  阅读(154)  评论(0编辑  收藏  举报