SFML :: View倒y轴标准?如何解决它?

时间:2015-12-16 11:24:57

标签: opengl graphics 2d viewport sfml

我使用右手坐标(x =右,y =上)将我的物体放在世界空间中。

当我必须使用SFML渲染它们时我遇到了问题,因为我无法在sf :: View中使用(y = up)矩阵设置View矩阵,然后全部渲染为y-翻转。

我想到的一个解决方案是在渲染之前在每个对象上翻转y轴:

ObjectTransformMatrix * MatrixScale(1.0f,-1.0f)

但我认为我必须将sf :: View中心移至:

y = y - (view_size.y / 2.0)

为什么sf :: View是y-inverted?我的解决方案是否正确

3 个答案:

答案 0 :(得分:5)

  

为什么sf :: View是y-inverted?

大多数图形包/库的屏幕空间坐标系都是左上角的原点,其中X向右,Y向下。这只是一个惯例,SFML恰好选择了这个。请注意,这不是左手或右手;这将取决于第三轴,如果有的话。我会认为你所指的另一个坐标系是传统的数学坐标系。

  

在渲染之前在每个对象上翻转y轴

不要这样做!你的世界是为了方便而定义的。当您可以更改相机(sf::View)变换时,为什么要更改它,该变换将在内部隐式应用于所有渲染对象。来自the documentation

  

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 T = B T A T < / SUP>。这会给我们

| 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 |

答案 1 :(得分:2)

我只是颠倒了窗户高度。我想就是这样。

sf::View view = window.getDefaultView();
view.setSize(WINDOW_WIDTH, -WINDOW_HEIGHT); 
window.setView(view);

答案 2 :(得分:0)

我发现最好的方法就是简单地在向窗口渲染精灵之前和之后翻转y位置坐标:

void draw(window)
{
    pos = sprite.getPos();
    sprite.setPos(pos.x, pos.y * -1);
    window.draw(sprite);
    sprite.setPos(pos.x, pos.y * -1);
}