簡體   English   中英

如何解決相機沿 X 軸的旋轉問題?

[英]How to solve camera rotation along the X-axis?

我有一個 Opengl 光線追蹤器,它能夠加載 obj 文件並以光線追蹤的方式將其可視化。 我的應用程序使用 assimp 加載 obj 文件,然后使用着色器存儲緩沖區將所有三角形面(包括頂點及其索引)發送到片段着色器。 之后,片段着色器通過跟蹤光線的路徑來計算像素的顏色。 光線來自相機 ( posCamera ) 的 position 並穿過虛擬 canvas 的像素。 基本結構即將將結果渲染到這個四邊形 canvas。

目前,我正在研究相機。 相機始終注視着0,0,0點 ( viewPoint ),並且可以通過下面的 function 圍繞 y 軸旋轉:

void setCamera(float param) {
    connect = posCamera - viewPoint;

    posCamera = glm::vec3(connect.x * cos(param) + connect.z * sin(param), connect.y,
                          -connect.x * sin(param) + connect.z * cos(param)) + viewPoint;

    canvasX = cross(upVector, connect) * getLength(connect) * tanf(fieldOfview / 2);
    canvasY = cross(connect, canvasX) * getLength(connect) * tanf(fieldOfview / 2);

    setCam(posCamera,viewPoint, canvasY, fieldOfview);

我也只想圍繞 x 軸旋轉場景。 為了解決這個問題,我創建了一個新的 function:

void rotateAroundX(float param) {
    connect = posCamera - viewPoint;
    posCamera = glm::vec3(posCamera.x,
                          connect.y * cos(param) + connect.z * sin(param),
                          -connect.y * sin(param) + connect.z * cos(param))+viewPoint;
    canvasX = cross(upVector, connect) * getLength(connect) * tanf(fieldOfview / 2);
    canvasY = cross(connect, canvasX) * getLength(connect) * tanf(fieldOfview / 2);

    setCam(posCamera,viewPoint, canvasY, fieldOfview);
}

它正在工作,但不幸的是,該比率存在一些失真。 更重要的是,有時相機只是圍繞一個點循環。 這是一個與問題相關的視頻:鏈接 你可以看到水平旋轉做得很好。

這是我的頂點着色器:

#version 460 core
layout(location = 0) in vec2 normQuadCoord;

uniform vec3 viewPoint;
uniform vec3 canvasX, canvasY;
out vec3 pixel;

void main()
{
    pixel = canvasX * normQuadCoord.x + canvasY * normQuadCoord.y + viewPoint;
    gl_Position = vec4(normQuadCoord, 0, 1);
}

這是完整源代碼的鏈接: source

除了相機旋轉之外,我不知道這種“渲染到四邊形”概念是否可以實現自由飛行的相機。 任何幫助表示贊賞!


更新 1

我嘗試了 Rabbid76 的建議並修改了源代碼。 我也做了一些重構。 更新矩形 canvas 尺寸的方法如下所示:

void Init::updateCanvasSizes() {
    connect = camera.getPosCamera() - camera.getViewPoint();

    float aspect = (float)SCR_W_H.first/(float)SCR_W_H.second;
    float length = tanf(camera.getFieldOfview() / 2);

    canvasX = glm::normalize(glm::cross(camera.upVector, connect)) / length / aspect;
    canvasY = glm::normalize(glm::cross(connect, canvasX)) / length;

}

處理相機繞 X 軸旋轉的方法修改為:

void Init::rotateCamAroundX(float param) {
    camera.posCamera = glm::vec3(camera.posCamera.x,
               (camera.posCamera.y - camera.viewPoint.y) * cos(param) + (camera.posCamera.z - camera.viewPoint.z) * sin(param) + camera.viewPoint.y,
               -(camera.posCamera.y - camera.viewPoint.y) * sin(param) + (camera.posCamera.z - camera.viewPoint.z) * cos(param) + camera.viewPoint.z);

    updateCanvasSizes();
}

視野已從45度修改為45 * (float)M_PI / 180 ,因此 model 的比率變得更好一些。 不幸的是,在相機繞 X 軸旋轉的過程中,仍然可以發現場景拉伸和失真。 當相機達到一定程度時,它也會回過頭來查看camera.viewPoint 我不知道如何“關閉它”。

結果可以在這個視頻中看到: 鏈接 首先可以看到繞 Y 軸的旋轉,然后可以看到繞 X 軸的旋轉。

您必須尊重視口的縱橫比。

在計算射線方向的點時, canvasXcanvasY會考慮縱橫比。

p = pixel = canvasX * normQuadCoord.x + canvasY * normQuadCoord.y + viewPoint;

如果視口是矩形的,則向量的大小必須不同。 canvasX是從中心到右側的向量, canvasY是從中心到視口頂部的向量。 為了補償視圖的矩形性並獲得正確的投影,矢量長度的比率必須等於縱橫比的倒數:

 width     | canvasY |
-------- = -----------
 height    | canvasX |

因此, canvasX的長度必須按倒數縱橫比進行縮放。 縱橫比是視圖的寬度和高度的商( (float)SCR_WIDTH/(float)SCR_HEIGHT ):

float aspect = (float)SCR_WIDTH/(float)SCR_HEIGHT;
float length = tanf(fieldOfview / 2);

canvasX = glm::normalize(glm::cross(upVector, connect)) / length / aspect;
canvasY = glm::normalize(glm::cross(connect, canvasX)) / length;

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM