一、什么是相机坐标系
相机坐标系(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进行渲染