gpt4 book ai didi

c++ - 设置不对称截锥体

转载 作者:塔克拉玛干 更新时间:2023-11-03 01:29:48 25 4
gpt4 key购买 nike

我有一个程序,我在其中跟踪用户的位置并设置视锥体(将相机设置在用户的位置)以根据用户的位置更改场景的视角。直到现在,我的显示屏的所有四个角都处于同一 z 轴,并且我能够设置不对称平截头体并根据用户的视角改变场景。

当前代码如下所示:

UserCam::begin(){
saveGlobalMatrices();
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glFrustum(_topLeftNear.x, _bottomRightNear.x, _bottomRightNear.y, _topLeftNear.y, _camZNear, _camZFar);

glMatrixMode(GL_MODELVIEW);
glLoadIdentity();

gluLookAt(_wcUserHead.x, _wcUserHead.y, _topLeftScreen.z, _wcUserHead.x, _wcUserHead.y, _topLeftScreen.z-1, 0, 1, 0);
}

UserCam::end(){
loadGlobalMatrices();
}

UserCam::setupCam(){
this->_topLeftScreen = _wcTopLeftScreen - _wcUserHead; //wcTopLeftScreen, wcBottomRightScreen and wcUserHead are in the same frame of reference
this->_bottomRightScreen = _wcBottomRightScreen - _wcUserHead;

this->_topLeftNear = (_topLeftScreen/ _topLeftScreen.z) * _camZNear;
this->_bottomRightNear = (_bottomRightScreen/_bottomRightScreen.z )) * _camZNear;
}

但是,我希望能够对向用户保持倾斜和/或所有顶点不在同一 Z 的显示器执行相同的操作。

enter image description here以上可以想象成一种倾斜的窗口,其顶点将具有从用户位置定义的平截头体。在显示器没有所有顶点都在同一 Z 的情况下,这样的截锥体怎么可能?

编辑
我正在考虑的设置中有三架飞机。中间的一个给出了正确的不对称平截头体,因为所有顶点都在同一个 Z 轴上,而左右平面有两个顶点,每个顶点在不同的 Z 轴上。相同的顶点如下:

Plane1: TL : (-426.66, 0, 200), TR: (0, 0, 0), BL : (-426.66, 320.79, 200), BR : (0, 320.79, 0)
Plane2: TL : (0, 0, 0), TR: (426.66, 0, 0), BL : (0, 320.79, 0), BR: (426.66, 320.79, 0)
Plane3: TL: (426.66, 0, 0), TR: (853.32, 0, 200), BL : (426.66, 320.79, 0), BR : (853.32, 320.79, 200)

最佳答案

此设置的想法是将其转换为所有角都具有相同 z 坐标的情况。通常这是通过 View 矩阵完成的,你会得到:

overall_transform = (projection) * (view * world)

或者用OpenGL的写法

overall_transform = projection * modelview

如果不想篡改原来的modelview矩阵,应该在中间再引入一个矩阵:

overall_transform = (projection * adaption) * (view * world)

其中 adaptation 是一个旋转矩阵,它将屏幕的角映射到具有恒定 z 坐标的平面。

为了找到projection 的正确参数,您必须使用adaptation 转换屏幕。

编辑

我们从一个已知相机位置、方向和屏幕的任意场景开始。我们认为模型矩阵已经存在于每个对象中:

Initial situation

然后我们需要将相机与原点对齐的 View 转换 V。可以使用 gluLookAt 轻松计算该矩阵。整个矩阵是 T = V * M:

After view transformation

到这一步为止,所有三个屏幕的矩阵都是相同的。所以这部分应该在模型 View 矩阵中。我们现在添加的内容进入投影矩阵,因为它因屏幕而异。

我们需要应用旋转 R 使屏幕垂直于 z 轴。相机的位置在这一步不能改变,因为它代表投影中心。整体转换现在是 T = R * V * M

为了计算角度,我们可以使用例如atan2:

dx = right.x - left.x
dz = right.z - left.z
angle = atan2(dz, dx)

可能需要根据您的实际需要稍微调整此计算。

After rotation adaption

现在是应用实际透视变换的时候了,这可以通过 glFrustum 完成。

我们需要找到屏幕的局部边缘。您可以使用当前变换 (R * V) 来变换屏幕坐标。

TL' = R * V * TL
BL' = R * V * BL
BR' = R * V * BR

现在所有三个坐标应具有相同的 z 坐标。我们可以按如下方式使用它们:

common_z = TL'.z = BL'.z = BR'.z
glFrustum(TL'.x / common_z * z_near,
BR'.x / common_z * z_near,
BL'.y / common_z * z_near,
TL'.y / common_z * z_near,
z_near, z_far)

总的来说T = glFrustum * R * V * M:

glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(...);
//any further model transforms

glMatrixMode(GL_PROJECTION);
glFrustum(...);
glRotate(...);

关于c++ - 设置不对称截锥体,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17587752/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com