您的位置:

相机坐标系详解

一、什么是相机坐标系

相机坐标系(Camera Coordinate System)是指相机自身的坐标系,也就是相机感知世界的坐标系。相机坐标系可以通过三个基向量来表示,分别是相机的右向量、上向量和前(视)向量。

由于相机可以随意移动或旋转,因此相机坐标系的原点和坐标轴是相对世界坐标系而言的。相机坐标系原点一般位于相机的光心,也就是所有视线的交点。从这个点出发向右、上、前三个方向延伸的向量就是相机坐标系的基向量。

二、相机坐标系的转换

相机坐标系与世界坐标系不同,因此在使用相机进行渲染时需要进行坐标系的转换。通常包括以下两个步骤:

1.视变换

视变换(View Transformation)就是将世界坐标系中的物体转换到相机坐标系中。视变换的核心就是将相机矩阵(Camera Matrix)与物体矩阵(Object Matrix)进行乘法运算,从而得到物体在相机坐标系中的坐标。

2.投影变换

投影变换(Projection Transformation)是将相机坐标系中的物体投影到屏幕上的最终步骤。它通常包括正射投影和透视投影两种方式。

正射投影(Orthographic Projection)是指将相机坐标系中的物体投影到一个平行于相机的投影平面上,适用于需要保持物体大小不变的场景。

透视投影(Perspective Projection)是指将相机坐标系中的物体投影到一个斜向相机的投影平面上,适用于需要表现景深效果的场景。

三、相机坐标系的应用

相机坐标系在计算机图形学中有着广泛的应用。一些经典的图像处理、机器视觉和三维游戏都会用到相机坐标系。

1.计算机视觉

在计算机视觉中,相机坐标系是一个非常重要的概念。例如,在目标跟踪、姿态估计和立体视觉领域中,需要将物体从世界坐标系转换到相机坐标系,并根据相应的投影矩阵计算出物体的位置和旋转角度。

2.三维游戏

在三维游戏中,相机坐标系虽然不是游戏场景的坐标系,但是它扮演着至关重要的角色。游戏中的相机可以随意移动和旋转,因此需要根据相机矩阵和投影矩阵渲染出正确的图像。

3.图像处理

在图像处理中,相机坐标系也会经常用到。例如在对图像进行仿射变换时,需要将相机坐标系中的点通过矩阵变换映射到新的坐标系中。

四、代码示例

1.视变换

glm::mat4 getViewMatrix(glm::vec3 cameraPosition, glm::vec3 cameraTarget, glm::vec3 worldUp){
    //计算相机坐标系中的前向量
    glm::vec3 cameraDirection = glm::normalize(cameraPosition - cameraTarget);
    //计算相机坐标系中的右向量
    glm::vec3 cameraRight = glm::normalize(glm::cross(worldUp, cameraDirection));
    //计算相机坐标系中的上向量
    glm::vec3 cameraUp = glm::cross(cameraDirection, cameraRight);
    //构造相机矩阵
    glm::mat4 viewMatrix = glm::mat4(1.0f);
    viewMatrix[0][0] = cameraRight.x;
    viewMatrix[1][0] = cameraRight.y;
    viewMatrix[2][0] = cameraRight.z;
    viewMatrix[0][1] = cameraUp.x;
    viewMatrix[1][1] = cameraUp.y;
    viewMatrix[2][1] = cameraUp.z;
    viewMatrix[0][2] = cameraDirection.x;
    viewMatrix[1][2] = cameraDirection.y;
    viewMatrix[2][2] = cameraDirection.z;
    viewMatrix = glm::translate(viewMatrix, -cameraPosition);
    return viewMatrix;
}

2.投影变换

glm::mat4 getPerspectiveProjectionMatrix(float fov, float aspectRatio, float nearClip, float farClip){
    float tanHalfFov = tan(glm::radians(fov) / 2.0f);
    float yScale = 1.0f / tanHalfFov;
    float xScale = yScale / aspectRatio;
    glm::mat4 projMatrix;
    projMatrix[0][0] = xScale;
    projMatrix[1][1] = yScale;
    projMatrix[2][2] = -(farClip + nearClip) / (farClip - nearClip);
    projMatrix[3][2] = -2.0f * farClip * nearClip / (farClip - nearClip);
    projMatrix[2][3] = -1.0f;
    projMatrix[3][3] = 0.0f;
    return projMatrix;
}

3.应用示例代码

//计算相机矩阵和投影矩阵
glm::mat4 viewMatrix = getViewMatrix(cameraPosition, cameraTarget, worldUp);
glm::mat4 projectionMatrix = getPerspectiveProjectionMatrix(fov, screenWidth / screenHeight, nearClip, farClip);
//将物体从世界坐标系转换到相机坐标系
glm::mat4 modelMatrix = glm::mat4(1.0f);
glm::mat4 mvpMatrix = projectionMatrix * viewMatrix * modelMatrix;
//根据mvpMatrix进行渲染