Cod*_*ler 11 3d geometry trigonometry lwjgl frustum
我在如何计算三维空间中视锥体的边界点的图表之后绘制了图表.首先,我有两组数据,每组包含三个值:摄像机的xyz坐标和围绕x,y和z轴的旋转.给定一定的视距,应该可以计算出6个平面中每个平面的边界点.我一直用这些方程来计算远平面的宽度和高度:
hfar = 2 * tan(45/2) * view_distance
wfar = hfar * ratio
Run Code Online (Sandbox Code Playgroud)
hfar是远平面的高度,wfar是宽度,比率是视口宽度除以高度的比率.我一直在使用下图来试图找出它:

我需要找到由(?,?,?)注释的点.我一直试图计算这些值几天,但无济于事.任何帮助,将不胜感激.
此外,可以在此处和此处找到一些提供有关该主题的信息的好消息来源.
编辑:我掀起的另一个图像显示通过y轴的单个切片向下看x轴.它显示的信息与上图相同,但它也显示了我的问题:我无法计算远平面的每个边界点的正确z轴值.
请记住,可以通过x轴进行相同的切割以显示相同的过程但是具有玩家向上或向下看的角度.
我认为您要解决的一般问题是如何在 3d 中旋转对象。据我了解,您知道如何获得相机矢量的大小,但不知道它们的方向。您定义了关于 x、y 和 z 轴的角度旋转,这些旋转要应用于相机的 [up]、[side] 和 [view/lookAt] 向量。

上图说明了我所说的 up、side 和 lookAt 向量的含义。它们与您的截锥体相关,如下图所示。

这是 C++ 中的一些粗略代码,它们将旋转给定轴和角度的点:
Vec3 RotatedBy(Vec3 const &axisVec, double angleDegCCW)
{
if(!angleDegCCW)
{ return Vec3(this->x,this->y,this->z); }
Vec3 rotatedVec;
double angleRad = angleDegCCW*3.141592653589/180.0;
rotatedVec = this->ScaledBy(cos(angleRad)) +
(axisVec.Cross(*this)).ScaledBy(sin(angleRad)) +
axisVec.ScaledBy(axisVec.Dot(*this)).ScaledBy(1-cos(angleRad));
return rotatedVec;
}
Run Code Online (Sandbox Code Playgroud)
一旦你有了旋转的向上、视图和侧向矢量,你就可以找到远平面的角落。
计算近处和远处飞机的中心点:
vec3 nearCenter = camPos - camForward * nearDistance;
vec3 farCenter = camPos - camForward * farDistance;
Run Code Online (Sandbox Code Playgroud)
计算近处和远处平面的宽度和高度:
real nearHeight = 2 * tan(fovRadians/ 2) * nearDistance;
real farHeight = 2 * tan(fovRadians / 2) * farDistance;
real nearWidth = nearHeight * viewRatio;
real farWidth = farHeight * viewRatio;
Run Code Online (Sandbox Code Playgroud)
计算近处和远处飞机的角点:
vec3 farTopLeft = farCenter + camUp * (farHeight*0.5) - camRight * (farWidth*0.5);
vec3 farTopRight = farCenter + camUp * (farHeight*0.5) + camRight * (farWidth*0.5);
vec3 farBottomLeft = farCenter - camUp * (farHeight*0.5) - camRight * (farWidth*0.5);
vec3 farBottomRight = farCenter - camUp * (farHeight*0.5) + camRight * (farWidth*0.5);
vec3 nearTopLeft = nearCenter + camY * (nearHeight*0.5) - camX * (nearWidth*0.5);
vec3 nearTopRight = nearCenter + camY * (nearHeight*0.5) + camX * (nearWidth*0.5);
vec3 nearBottomLeft = nearCenter - camY * (nearHeight*0.5) - camX * (nearWidth*0.5);
vec3 nearBottomRight = nearCenter - camY * (nearHeight*0.5) + camX * (nearWidth*0.5);
Run Code Online (Sandbox Code Playgroud)
从平面的任意三个角计算每个平面,缠绕CW或CCW指向内部(取决于坐标系).
vec3 p0, p1, p2;
p0 = nearBottomLeft; p1 = farBottomLeft; p2 = farTopLeft;
vec3 leftPlaneNormal = Normalize(Cross(p1-p0, p2-p1));
vec3 leftPlaneOffset = Dot(leftPlaneNormal, p0);
p0 = nearTopLeft; p1 = farTopLeft; p2 = farTopRight;
vec3 topPlaneNormal = Normalize(Cross(p1-p0, p2-p1));
vec3 topPlaneNormal = Dot(topPlaneNormal , p0);
p0 = nearTopRight; p1 = farTopRight; p2 = farBottomRight;
vec3 rightPlaneNormal = Normalize(Cross(p1-p0, p2-p1));
vec3 rightPlaneNormal = Dot(rightPlaneNormal , p0);
p0 = nearBottomRight; p1 = farBottomRight; p2 = farBottomLeft;
vec3 bottomPlaneNormal = Normalize(Cross(p1-p0, p2-p1));
vec3 bottomPlaneNormal = Dot(bottomPlaneNormal , p0);
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
14824 次 |
| 最近记录: |