2011-04-03 81 views
2

我的矩陣數學有點生疏,所以我在計算適當的轉換過程時遇到了一些問題,我需要在這裏應用。正確的轉換設置,用於縮放然後旋轉

我有一個全屏幕四邊形,座標範圍從[-1, 1]兩個方向。我使用非方形紋理紋理這個四邊形,然後縮放我的模型視圖矩陣以調整大小並保留寬高比。我也想旋轉調整大小的四邊形,但我得到拉伸/扭曲的結果。

下面是我經歷的過程:

_gl.viewport(0, 0, _gl.viewportWidth, _gl.viewportHeight); // full-screen viewport 
mat4.rotate(_modelview_matrix, degToRad(-1.0 * _desired_rotation), [0, 0, 1]); // rotate around z 
mat4.scale(_modelview_matrix, [_shape.width/_gl.viewportWidth, _shape.height/_gl.viewportHeight, 1]); // scale down 

注意,這是在WebGL的實現,但是這個過程應該是普遍的。

爲了簡單起見,這一切都是在原點完成的。我很確定我錯過了縮放和旋轉之間的一些關係,但我不確定它是什麼。

Rotation distortion

如果我想四的大小爲_shape.width, _shape.height和任意角度有一個旋轉,我缺少什麼?

謝謝!

回答

2

您可以使用投影和模型視圖的任意組合。因此,請簡化您的生活:使用一些保留窗口縱橫比的投影,以便模型視圖座標不會受到各向異性扭曲。然後將紋理繪製到具有相同邊緣比例的四邊形上。

這是C語言,但概念應該足夠簡單。

typedef struct Projection { 
    enum{perspective, ortho} type; 
    union { 
     GLfloat fov; 
     GLfloat size; 
    }; 
    GLfloat near; 
    GLfloat far; 
} Projection; 

Projection projection; 

GLuint tex_width; 
GLuint tex_height; 

GLuint viewport_width; 
GLuint viewport_height; 

/*...*/ 

void display() 
{ 
    GLfloat viewport_aspect; 

    if(!viewport_width || !viewport_height) 
     return; 

    viewport_aspect = (float)viewport_width/(float)viewport_height; 

    glViewport(0, 0, viewport_width, viewport_height); 

    glMatrixMode(GL_PROJECTION); 
    glLoadIdentity(); 

    switch(projection.type) { 
    case ortho: { 
      glOrtho(-0.5 * viewport_aspect * projection.size, 
        0.5 * viewport_aspect * projection.size, 
        -0.5 * projection.size, 
        0.5 * projection.size, 
        -projection.near, 
        projection.far); 
     } 
    case perspective: { 
      glFrustum(-0.5 * viewport_aspect * projection.near * projection.fov, 
         0.5 * viewport_aspect * projection.near * projection.fov, 
         -0.5 * projection.near * projection.fov, 
         0.5 * projection.near * projection.fov, 
         -projection.near, 
         projection.far); 
     } 
    default: 
     return; 
    } 

    glMatrixMode(GL_MODELVIEW); 
    glLoadIdentity(); 

    { 
     GLfloat const T = 0.5*(float)texture_width/(float)texture_height; 

     GLfloat quad[4][4] = { 
      /* X  Y, U,  V */ 
      {-T, -0.5, 0.0, 0.0}, 
      { T, -0.5, 1.0, 0.0}, 
      { T, 0.5, 1.0, 1.0}, 
      {-T, 0.5, 0.0, 1.0}, 
     } 

     glEnableClientState(GL_VERTEX_ARRAY); 
     glEnableClientState(GL_TEXTURE_COORD_ARRAY); 
     glVertexPointer(2, GL_FLOAT, (char*)&quad[6]-(char*)&quad[2], &quad[2]); 
     glTexCoordPointer(2, GL_FLOAT, (char*)&quad[6]-(char*)&quad[2], &quad[2]); 

     glEnable(GL_TEXTURE_2D); 
     glBindTexture(GL_TEXTURE_2D, texture_ID); 

     glDrawArrays(GL_QUADS, 0, 4); 
    } 
} 
+0

謝謝!這正是我所需要的。我回去調整我的頂點的位置,以您的示例爲指導。這是我在縮放比例和長寬比保存之間所需的分離。 – Xenethyl 2011-04-03 22:20:23

2

我從來沒有使用過webgl,所以在這裏沒有我的例子,但是你不應該在你的modelview矩陣中進行寬高比校正。這是投影矩陣要做的事情。

如何做到這一點的一個例子可以找到here

+0

糟糕!感謝您指出我嘗試將模型視圖和投影矩陣合併在一起的錯誤。我*認爲*在這種孤立的情況下,它沒有什麼不同,因爲我只進行了兩次轉換,但這仍然是非常糟糕的做法。我已經在我的代碼中解決了這個問題。 – Xenethyl 2011-04-03 22:18:16