一、什麼是相機坐標系?
相機坐標系,又稱為相機空間坐標系,是指相機內部的坐標系,通常原點位於相機的光心位置。在相機坐標系中,其它的參數都是針對相機而言的,例如相機的焦距、光圈、透視投影矩陣等。
在OpenGL等圖形學API中,我們常用3個向量表示相機坐標系的狀態,即相機位置向量(eye)、相機視線向量(center)和相機上方向量(up)。根據這三個向量,可以構建出一個正交或投影的相機坐標系,以此來描述相機內部場景的設置和視角。
視圖變換部分代碼示例: mat4 view = lookAt(eye, center, up);
二、什麼是世界坐標系?
世界坐標系是指整個場景的坐標系,所有的物體都是相對於這個坐標系而言的。在OpenGL等圖形學API中,我們常用世界坐標系來描述場景的配置和物體的定位。在這個坐標系中,相機的位置和姿態通常是已知的,所以我們在建立物體的模型坐標系時,可以很方便地將其附加在世界坐標繫上。
模型矩陣變換部分代碼示例: mat4 model = translate(mat4(1.0f), vec3(0.0f, 0.0f, 0.0f)); model = scale(model, vec3(1.0f, 1.0f, 1.0f)); model = rotate(model, radians(angle), axis);
三、相機坐標系與世界坐標系的關係
相機坐標系與世界坐標系之間的轉換是圖形學應用中非常重要的一個問題。相機坐標系通常需要通過透視矩陣(Perspective Matrix)或正交矩陣(Orthogonal Matrix)來進行轉換,而世界坐標系則通常需要用到模型矩陣(Model Matrix)。
在OpenGL中,我們通過將不同的矩陣相乘,來實現對相機坐標系和世界坐標系的轉換。具體的計算方式可以參考下面的代碼示例:
視圖變換部分代碼示例: mat4 view = lookAt(eye, center, up); 透視投影矩陣部分代碼示例: mat4 proj = perspective(radians(45.0f), (float)width / (float)height, 0.1f, 100.0f); 模型矩陣變換部分代碼示例: mat4 model = translate(mat4(1.0f), vec3(0.0f, 0.0f, 0.0f)); model = scale(model, vec3(1.0f, 1.0f, 1.0f)); model = rotate(model, radians(angle), axis); 最終變換矩陣部分代碼示例: mat4 mvp = proj * view * model;
四、相機坐標系與世界坐標系的應用
相機坐標系與世界坐標系的概念在計算機圖形學中有著非常廣泛的應用。例如,我們可以利用相機坐標系的變換來動態地改變場景的視角,並在屏幕上渲染出預期的效果;而在計算機視覺處理中,我們也可以將相機坐標系和世界坐標系用於圖像的校正、姿態的計算等。
下面是一個例子,演示了如何利用OpenGL中的相機坐標系和世界坐標系,來繪製出一個基本的紋理立方體:
// 創建立方體的頂點和紋理坐標 float vertices[] = { // 頂點坐標 // 紋理坐標 -1.0f, -1.0f, -1.0f, 0.0f, 0.0f, 1.0f, -1.0f, -1.0f, 1.0f, 0.0f, 1.0f, 1.0f, -1.0f, 1.0f, 1.0f, 1.0f, 1.0f, -1.0f, 1.0f, 1.0f, -1.0f, 1.0f, -1.0f, 0.0f, 1.0f, -1.0f, -1.0f, -1.0f, 0.0f, 0.0f, // 更多的頂點和紋理坐標,省略... }; // 創建立方體的VAO和VBO unsigned int VAO, VBO; glGenVertexArrays(1, &VAO); glGenBuffers(1, &VBO); glBindVertexArray(VAO); glBindBuffer(GL_ARRAY_BUFFER, VBO); glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)0); glEnableVertexAttribArray(0); glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)(3 * sizeof(float))); glEnableVertexAttribArray(1); // 載入立方體的紋理 unsigned int texture; glGenTextures(1, &texture); glBindTexture(GL_TEXTURE_2D, texture); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); int width, height, nrChannels; unsigned char *data = stbi_load("container.jpg", &width, &height, &nrChannels, 0); if (data) { glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, data); glGenerateMipmap(GL_TEXTURE_2D); } else { std::cout << "Failed to load texture" << std::endl; } stbi_image_free(data); // 圖形渲染循環 while (!glfwWindowShouldClose(window)) { // 處理輸入事件 processInput(window); // 渲染背景色和立方體 glClearColor(0.2f, 0.3f, 0.3f, 1.0f); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // 應用相機坐標系和世界坐標系的變換 mat4 view = lookAt(eye, center, up); mat4 proj = perspective(radians(45.0f), (float)SCR_WIDTH / (float)SCR_HEIGHT, 0.1f, 100.0f); mat4 model = mat4(1.0f); mat4 mvp = proj * view * model; ourShader.setMat4("mvp", mvp); // 繪製立方體 glBindTexture(GL_TEXTURE_2D, texture); glBindVertexArray(VAO); glDrawArrays(GL_TRIANGLES, 0, 36); // 交換緩衝區並檢查事件 glfwSwapBuffers(window); glfwPollEvents(); }
五、總結
相機坐標系與世界坐標系的概念在計算機圖形學和計算機視覺領域有著廣泛的應用,尤其對於那些需要對物體姿態、視角、紋理等進行處理的應用來說,更是不可或缺的基礎概念。因此,深入理解這兩個坐標系的原理和應用,對於圖形學和視覺處理領域的學習和應用有著重要的啟發意義。
原創文章,作者:LBTKP,如若轉載,請註明出處:https://www.506064.com/zh-tw/n/333524.html