是否可以仅使用 aspectRatio、y_scale、x_scale 和 frustum_length 来计算视锥体?
Is is possible to calculate the view frustum with only the: aspectRatio, y_scale, x_scale and frustum_length?
我正在创建一个游戏,我在其中使用 aspectRatio、y_scale、x_scale 和 frustum_length 计算视图矩阵,所以我想知道是否有一种方法可以计算视图只有那些变量的截锥体。
变量:
float aspectRatio = (float)Display.getWidth() / (float)Display.getHeight();
float y_scale = (float) ((1f / Math.tan(Math.toRadians(FOV / 2f))) * aspectRatio);
float x_scale = y_scale / aspectRatio;
float frustum_length = FAR_PLANE - NEAR_PLANE;
当透视投影对称时,(y轴)视场角FOV
、长宽比aspectRatio
和到近平面的距离(NEAR_PLANE
)和远平面(FAR_PLANE
),则可以计算space视野内视锥的8个角点:
float aspectRatio = (float)Display.getWidth() / (float)Display.getHeight();
float y_scale = 1.0f / (float)Math.tan( Math.toRadians(FOV / 2.0) );
float x_scale = y_scale * aspectRatio;
float near_x = NEAR_PLANE * x_scale;
float near_y = NEAR_PLANE * y_scale;
float far_x = FAR_PLANE * x_scale;
float far_y = FAR_PLANE * y_scale;
Vector3f left_bottom_near = new Vector3f(-near_x, -near_y, FAR_PLANE);
Vector3f right_bottom_near = new Vector3f( near_x, -near_y, FAR_PLANE);
Vector3f left_top_near = new Vector3f(-near_x, near_y, FAR_PLANE);
Vector3f right_top_near = new Vector3f( near_x, near_y, FAR_PLANE);
Vector3f left_bottom_far = new Vector3f(-far_x, -far_y, FAR_PLANE);
Vector3f right_bottom_far = new Vector3f( far_x, -far_y, FAR_PLANE);
Vector3f left_top_far = new Vector3f(-far_x, far_y, FAR_PLANE);
Vector3f right_top_far = new Vector3f( far_x, far_y, FAR_PLANE);
如果你想知道世界space中视锥的8个角点,那么这些点必须从视图space转换到世界space。
从世界 space 转换到视图 space 的矩阵是 "view" 矩阵。可以从视图 space 转换到世界 space 的矩阵是逆视图矩阵 (invert()
).
逆视图矩阵是由视图的视图位置、视图方向和视图的上向量定义的矩阵。 Matrix4f
可以设置如下:
Vector3f eyePos; // position of the view (eye position)
Vector3f targetPos; // the point which is looked at
Vector3f upVec; // up vector of the view
Vector3f zAxis = Vector3f.sub(eyePos, targetPos, null);
zAxis.normalise();
Vector3f xAxis = Vector3f.cross(upVec, zAxis, null);
xAxis.normalise();
Vector3f yAxis = Vector3f.cross(zAxis, upVec, null);
Matrix4f inverseView = new Matrix4f();
inverseView.m00 = xAxis.x; inverseView.m01 = xAxis.y; inverseView.m02 = xAxis.z; inverseView.m03 = 0.0f;
inverseView.m10 = yAxis.x; inverseView.m11 = yAxis.y; inverseView.m12 = yAxis.z; inverseView.m13 = 0.0f;
inverseView.m20 = zAxis.x; inverseView.m21 = zAxis.y; inverseView.m22 = zAxis.z; inverseView.m23 = 0.0f;
inverseView.m30 = eyePos.x; inverseView.m31 = eyePos.y; inverseView.m32 = eyePos.z; inverseView.m33 = 1.0f;
注意,view的坐标系space是一个Right-handed系统,X轴指向左边,Y轴指向上方,然后Z轴指向在视图之外(请注意,在右手系统中,Z 轴是 X 轴和 Y 轴的叉积)。
最后角点可以通过矩阵进行变换:
例如
Vector4f left_bottom_near_v4 = new Vector4f(
left_bottom_near.x, left_bottom_near.y, left_bottom_near.z, 1.0f
);
Vector4f left_bottom_near_world_v4 = new Vector4f();
Matrix4f.transform(Matrix4f left, left_bottom_near_v4, left_bottom_near_world_v4);
Vector3f left_bottom_near_world = new Vector3f(
left_bottom_near_world_v4 .x, left_bottom_near_world_v4 .y, left_bottom_near_world_v4 .z
);
我正在创建一个游戏,我在其中使用 aspectRatio、y_scale、x_scale 和 frustum_length 计算视图矩阵,所以我想知道是否有一种方法可以计算视图只有那些变量的截锥体。
变量:
float aspectRatio = (float)Display.getWidth() / (float)Display.getHeight();
float y_scale = (float) ((1f / Math.tan(Math.toRadians(FOV / 2f))) * aspectRatio);
float x_scale = y_scale / aspectRatio;
float frustum_length = FAR_PLANE - NEAR_PLANE;
当透视投影对称时,(y轴)视场角FOV
、长宽比aspectRatio
和到近平面的距离(NEAR_PLANE
)和远平面(FAR_PLANE
),则可以计算space视野内视锥的8个角点:
float aspectRatio = (float)Display.getWidth() / (float)Display.getHeight();
float y_scale = 1.0f / (float)Math.tan( Math.toRadians(FOV / 2.0) );
float x_scale = y_scale * aspectRatio;
float near_x = NEAR_PLANE * x_scale;
float near_y = NEAR_PLANE * y_scale;
float far_x = FAR_PLANE * x_scale;
float far_y = FAR_PLANE * y_scale;
Vector3f left_bottom_near = new Vector3f(-near_x, -near_y, FAR_PLANE);
Vector3f right_bottom_near = new Vector3f( near_x, -near_y, FAR_PLANE);
Vector3f left_top_near = new Vector3f(-near_x, near_y, FAR_PLANE);
Vector3f right_top_near = new Vector3f( near_x, near_y, FAR_PLANE);
Vector3f left_bottom_far = new Vector3f(-far_x, -far_y, FAR_PLANE);
Vector3f right_bottom_far = new Vector3f( far_x, -far_y, FAR_PLANE);
Vector3f left_top_far = new Vector3f(-far_x, far_y, FAR_PLANE);
Vector3f right_top_far = new Vector3f( far_x, far_y, FAR_PLANE);
如果你想知道世界space中视锥的8个角点,那么这些点必须从视图space转换到世界space。
从世界 space 转换到视图 space 的矩阵是 "view" 矩阵。可以从视图 space 转换到世界 space 的矩阵是逆视图矩阵 (invert()
).
逆视图矩阵是由视图的视图位置、视图方向和视图的上向量定义的矩阵。 Matrix4f
可以设置如下:
Vector3f eyePos; // position of the view (eye position)
Vector3f targetPos; // the point which is looked at
Vector3f upVec; // up vector of the view
Vector3f zAxis = Vector3f.sub(eyePos, targetPos, null);
zAxis.normalise();
Vector3f xAxis = Vector3f.cross(upVec, zAxis, null);
xAxis.normalise();
Vector3f yAxis = Vector3f.cross(zAxis, upVec, null);
Matrix4f inverseView = new Matrix4f();
inverseView.m00 = xAxis.x; inverseView.m01 = xAxis.y; inverseView.m02 = xAxis.z; inverseView.m03 = 0.0f;
inverseView.m10 = yAxis.x; inverseView.m11 = yAxis.y; inverseView.m12 = yAxis.z; inverseView.m13 = 0.0f;
inverseView.m20 = zAxis.x; inverseView.m21 = zAxis.y; inverseView.m22 = zAxis.z; inverseView.m23 = 0.0f;
inverseView.m30 = eyePos.x; inverseView.m31 = eyePos.y; inverseView.m32 = eyePos.z; inverseView.m33 = 1.0f;
注意,view的坐标系space是一个Right-handed系统,X轴指向左边,Y轴指向上方,然后Z轴指向在视图之外(请注意,在右手系统中,Z 轴是 X 轴和 Y 轴的叉积)。
最后角点可以通过矩阵进行变换:
例如
Vector4f left_bottom_near_v4 = new Vector4f(
left_bottom_near.x, left_bottom_near.y, left_bottom_near.z, 1.0f
);
Vector4f left_bottom_near_world_v4 = new Vector4f();
Matrix4f.transform(Matrix4f left, left_bottom_near_v4, left_bottom_near_world_v4);
Vector3f left_bottom_near_world = new Vector3f(
left_bottom_near_world_v4 .x, left_bottom_near_world_v4 .y, left_bottom_near_world_v4 .z
);