我使用右手坐标(x =右,y =向上)将我的物体放在世界空间中.
当我必须使用SFML渲染它们时,我遇到了问题,因为我无法在sf :: View中使用(y = up)矩阵设置View矩阵,然后全部渲染y-flipped.
我正在考虑的一个解决方案是在渲染之前在每个对象上翻转y轴:
ObjectTransformMatrix * MatrixScale(1.0f,-1.0f)
但我想我必须将sf :: View中心移动到:
y = y - (view_size.y / 2.0)
为什么sf :: View是y-inverted?我的解决方案是否正确
为什么sf :: View是y-inverted?
大多数图形包/库的屏幕空间坐标系都是左上角的原点,其中X向右,Y向下.这只是一个惯例,SFML恰好选择了这个.请注意,这不是左手或右手; 这将取决于第三轴,如果有的话.我会认为你所指的另一个坐标系是传统的数学坐标系.
在渲染之前在每个对象上翻转y轴
不要这样做!你的世界是为了方便而定义的.为什么在可以更改sf::View
将在内部隐式应用于所有渲染对象的camera()变换时更改它.从文档:
sf :: View定义2D场景中的摄像机.
这是一个非常强大的概念:您可以滚动,旋转或缩放整个场景,而无需改变绘制可绘制对象的方式.[...]要应用视图,您必须将其分配给渲染目标.然后,在此渲染目标中绘制的每个对象都将受到视图的影响,直到您使用另一个视图.
基本上你会将下面派生的矩阵设置为相机的变换,但是通过暴露的函数sf::View
.
我的解决方案是否正确
部分正确,你已经猜到了其余部分.翻转轴只是解决方案的一部分,您还应将原点转换到正确的位置.你需要的是M m→s,其中m是数学空间,s是屏幕空间.要找到您需要转换屏幕空间坐标系以与数学坐标系对齐.由于两个坐标系中的比例相同,我们可以使用宽度W和高度H(最初来自屏幕空间)的值.
我们这样:
S--->---- W ---------+ | | v | | | | | | | | | H | | | | | ^ | | | M--->----------------+
当我们做S 1,-1时,即将X轴刻度为1,将Y轴刻度为-1(翻转Y),我们得到了
^ | S--->---- W ---------+ | | | | | | | | | | | | H | | | | | ^ | | | M--->----------------+
这个新系统不再是S,因为它的Y被翻转; 我们称之为S'.现在我们要将它的原点转换(移动)到达M.因为我们要转换坐标系而不是点,我们要对S'进行转换,转换的中间坐标系而不是S.
我们做T 0,-H即沿负Y移动H单位.我们最终会得到
+-------- W ---------+ | | | | | | | | | | | | H | | | | | ^ | | | O--->----------------+ where both M and S are at O.
我们要连接S和T以获得最终的M m→s.由于我们正在变换坐标系,而不是点,我们要进行后乘(假设您使用的是列向量约定).
M m→s = S 1,-1 T 0,-H
| 1 0 0 | | 1 0 0 | | 1 0 0 | | 0 ?1 0 | | 0 1 ?H | = | 0 ?1 H | | 0 0 1 | | 0 0 1 | | 0 0 1 |
假设我们的屏幕是5×5(为简单起见).将世界空间中的点(1,1)转换为屏幕空间:
| 1 0 0 | |1| |1| | 0 ?1 5 | |1| = |4| | 0 0 1 | |1| |1|
(1,4)是屏幕空间中的点坐标.
如果你正在关注行向量约定,您对置式,M = AB即,M 牛逼 = B 牛逼一个牛逼.这会给我们
| 1 0 0 | | 1 0 0 | | 1 0 0 | | 0 1 0 | | 0 ?1 0 | = | 0 ?1 0 | | 0 ?H 1 | | 0 0 1 | | 0 H 1 |