2014-09-06 87 views
2

我正在使用Java和OpenGL(LWJGL)來設置一些矩陣,我不想使用內置方法,因爲我也希望這可以在Android上工作,所以使用LWJGL的Matrix類不會適當。目前,我正在使用fov 70,znear 0.1,zfar 1000設置透視圖。使用當前設置進行旋轉只會導致奇怪的結果,不能以正確的方式旋轉,並且對象縮放奇怪並且經常消失。OpenGL 2.0矩陣不能正常工作

這裏是Matrix4D類:

public class Matrix4D { 

/* The values within this matrix */ 
public float[] values; 

/* The default constructor */ 
public Matrix4D() { 
    //Create the values 
    this.values = new float[16]; 
} 

/* The constructor with the values given */ 
public Matrix4D(float[] values) { 
    //Create the values 
    this.values = values; 
} 

/* The constructor with the values given */ 
public Matrix4D(float[][] values) { 
    //Load the values 
    load(values); 
} 

/* The method used to set the values given a 2 dimensional array */ 
public void load(float[][] values) { 
    this.values = new float[] { 
      values[0][0], values[0][1], values[0][2], values[0][3], 
      values[1][0], values[1][1], values[1][2], values[1][3], 
      values[2][0], values[2][1], values[2][2], values[2][3], 
      values[3][0], values[3][1], values[3][2], values[3][3] 
    }; 
} 

/* The method used to get a value using the coordinate within this matrix */ 
public float get(int x, int y) { 
    //Get the position 
    int position = x + (y * 4); 
    //Return the value 
    return this.values[position]; 
} 

/* The method used to return a string representation of this matrix */ 
public String toString() { 
    //Return the string 
    return "[ " + this.values[0] + " " + this.values[1] + " " + + this.values[2] + " " + + this.values[3] + " ]" + "\n" + 
      "[ " + this.values[4] + " " + this.values[5] + " " + + this.values[6] + " " + + this.values[7] + " ]" + "\n" + 
      "[ " + this.values[8] + " " + this.values[9] + " " + + this.values[10] + " " + + this.values[11] + " ]" + "\n" + 
      "[ " + this.values[12] + " " + this.values[13] + " " + + this.values[14] + " " + + this.values[15] + " ]"; 
} 

/* The method used to get the values */ 
public float[] getValues() { return this.values; } 

/* The method used to get the values in a 2D array */ 
public float[][] getValues2DArray() { 
    //The array 
    float[][] array = new float[4][4]; 
    //Go through each value 
    int column = 0; 
    int row = 0; 
    while (column * row < array.length) { 
     row ++; 
     if (row >= 4) { 
      column++; 
      row = 0; 
     } 
     array[column][row] = this.values[column * row]; 
    } 
    //Return the array 
    return array; 
} 

} 

這裏是矩陣類(用於設置和執行上的矩陣計算):

public class Matrix { 

/* The different matrices */ 
public static Matrix4D modelMatrix = new Matrix4D(); 
public static Matrix4D viewMatrix = new Matrix4D(); 
public static Matrix4D projectionMatrix = new Matrix4D(); 
public static Matrix4D modelViewProjectionMatrix = new Matrix4D(); 

/* The static method used to load an identity matrix */ 
public static void loadIdentity(Matrix4D matrix) { 
    //Load the identity matrix 
    matrix.load(new float[][] { 
      new float[] { 1, 0, 0, 0 }, 
      new float[] { 0, 1, 0, 0 }, 
      new float[] { 0, 0, 1, 0 }, 
      new float[] { 0, 0, 0, 1 }, 
    }); 
} 

/* The static method used to add two matrices together */ 
public static Matrix4D add(Matrix4D matrixA, Matrix4D matrixB) { 
    //Create a new matrix 
    Matrix4D matrix = new Matrix4D(); 
    //Go through each value 
    for (int a = 0; a < matrix.values.length; a++) 
     //Assign the current value 
     matrix.values[a] = matrixA.values[a] + matrixB.values[a]; 
    //Return the matrix 
    return matrix; 
} 

/* The static method used to subtract a matrix (B) from another (A) */ 
public static Matrix4D subtract(Matrix4D matrixA, Matrix4D matrixB) { 
    //Create a new matrix 
    Matrix4D matrix = new Matrix4D(); 
    //Go through each value 
    for (int a = 0; a < matrix.values.length; a++) 
     //Assign the current value 
     matrix.values[a] = matrixB.values[a] - matrixA.values[a]; 
    //Return the matrix 
    return matrix; 
} 

/* The static method used to multiply two matrices together */ 
public static Matrix4D multiply(Matrix4D matrixA, Matrix4D matrixB) { 
    //Create a new matrix 
    Matrix4D matrix = new Matrix4D(new float[][] { 
      new float[] { 
        (matrixA.values[0] * matrixB.values[0]) + (matrixA.values[1] * matrixB.values[4]) + (matrixA.values[2] * matrixB.values[8]) + (matrixA.values[3] * matrixB.values[12]), 
        (matrixA.values[0] * matrixB.values[1]) + (matrixA.values[1] * matrixB.values[5]) + (matrixA.values[2] * matrixB.values[9]) + (matrixA.values[3] * matrixB.values[13]), 
        (matrixA.values[0] * matrixB.values[2]) + (matrixA.values[1] * matrixB.values[6]) + (matrixA.values[2] * matrixB.values[10]) + (matrixA.values[3] * matrixB.values[14]), 
        (matrixA.values[0] * matrixB.values[3]) + (matrixA.values[1] * matrixB.values[7]) + (matrixA.values[2] * matrixB.values[11]) + (matrixA.values[3] * matrixB.values[15]) 
      }, 
      new float[] { 
        (matrixA.values[4] * matrixB.values[0]) + (matrixA.values[5] * matrixB.values[4]) + (matrixA.values[6] * matrixB.values[8]) + (matrixA.values[7] * matrixB.values[12]), 
        (matrixA.values[4] * matrixB.values[1]) + (matrixA.values[5] * matrixB.values[5]) + (matrixA.values[6] * matrixB.values[9]) + (matrixA.values[7] * matrixB.values[13]), 
        (matrixA.values[4] * matrixB.values[2]) + (matrixA.values[5] * matrixB.values[6]) + (matrixA.values[6] * matrixB.values[10]) + (matrixA.values[7] * matrixB.values[14]), 
        (matrixA.values[4] * matrixB.values[3]) + (matrixA.values[5] * matrixB.values[7]) + (matrixA.values[6] * matrixB.values[11]) + (matrixA.values[7] * matrixB.values[15]) 
      }, 
      new float[] { 
        (matrixA.values[8] * matrixB.values[0]) + (matrixA.values[9] * matrixB.values[4]) + (matrixA.values[10] * matrixB.values[8]) + (matrixA.values[11] * matrixB.values[12]), 
        (matrixA.values[8] * matrixB.values[1]) + (matrixA.values[9] * matrixB.values[5]) + (matrixA.values[10] * matrixB.values[9]) + (matrixA.values[11] * matrixB.values[13]), 
        (matrixA.values[8] * matrixB.values[2]) + (matrixA.values[9] * matrixB.values[6]) + (matrixA.values[10] * matrixB.values[10]) + (matrixA.values[11] * matrixB.values[14]), 
        (matrixA.values[8] * matrixB.values[3]) + (matrixA.values[9] * matrixB.values[7]) + (matrixA.values[10] * matrixB.values[11]) + (matrixA.values[11] * matrixB.values[15]) 
      }, 
      new float[] { 
        (matrixA.values[12] * matrixB.values[0]) + (matrixA.values[13] * matrixB.values[4]) + (matrixA.values[14] * matrixB.values[8]) + (matrixA.values[15] * matrixB.values[12]), 
        (matrixA.values[12] * matrixB.values[1]) + (matrixA.values[13] * matrixB.values[5]) + (matrixA.values[14] * matrixB.values[9]) + (matrixA.values[15] * matrixB.values[13]), 
        (matrixA.values[12] * matrixB.values[2]) + (matrixA.values[13] * matrixB.values[6]) + (matrixA.values[14] * matrixB.values[10]) + (matrixA.values[15] * matrixB.values[14]), 
        (matrixA.values[12] * matrixB.values[3]) + (matrixA.values[13] * matrixB.values[7]) + (matrixA.values[14] * matrixB.values[11]) + (matrixA.values[15] * matrixB.values[15]) 
      } 
    }); 
    //Return the matrix 
    return matrix; 
} 

/* The static method used to transpose a matrix */ 
public static Matrix4D transpose(Matrix4D matrix) { 
    //Get the values from the matrix 
    float[][] values = matrix.getValues2DArray(); 
    //The new values 
    float[][] newValues = new float[4][4]; 
    //Go through the array 
    for (int y = 0; y < values.length; y++) { 
     for (int x = 0; x < values[y].length; x++) { 
      //Assign the new value 
      newValues[x][y] = values[y][x]; 
     } 
    } 
    //Return the matrix 
    return new Matrix4D(newValues); 
} 

/* The static method used to translate a matrix */ 
public static Matrix4D translate(Matrix4D matrix, Vector3D vector) { 
    //The transform matrix 
    Matrix4D transform = new Matrix4D(new float[][] { 
      new float[] { 0, 0, 0, vector.x }, 
      new float[] { 0, 0, 0, vector.y }, 
      new float[] { 0, 0, 0, vector.z }, 
      new float[] { 0, 0, 0, 0 }, 
    }); 
    //Add onto the matrix and return the result 
    return add(matrix, transform); 
} 

/* The static method used to rotate a matrix */ 
public static Matrix4D rotate(Matrix4D matrix, float angle, int x, int y, int z) { 
    //The transform matrix 
    Matrix4D transform = new Matrix4D(); 
    //Calculate the values needed 
    float cos = (float) Math.cos(angle); 
    float sin = (float) Math.sin(angle); 
    //Check the x y and z values 
    if (x == 1) { 
     transform.load(new float[][] { 
       new float[] { 0, 0, 0, 0 }, 
       new float[] { 0, cos, -sin, 0 }, 
       new float[] { 0, sin, cos, 0 }, 
       new float[] { 0, 0, 0, 0 }, 
     }); 
    } else if (y == 1) { 
     transform.load(new float[][] { 
       new float[] { cos, 0, sin, 0 }, 
       new float[] { 0, 0, 0, 0 }, 
       new float[] { -sin, 0, cos, 0 }, 
       new float[] { 0, 0, 0, 0 }, 
     }); 
    } else if (z == 1) { 
     transform.load(new float[][] { 
       new float[] { cos, -sin, 0, 0 }, 
       new float[] { sin, cos, 0, 0 }, 
       new float[] { 0, 0, 0, 0 }, 
       new float[] { 0, 0, 0, 0 }, 
     }); 
    } 
    //Add onto the matrix and return the result 
    return add(matrix, transform); 
} 

/* The static method used to scale a matrix */ 
public static Matrix4D scale(Matrix4D matrix, Vector3D vector) { 
    //The transform matrix 
    Matrix4D transform = new Matrix4D(new float[][] { 
      new float[] { vector.x, 0, 0, 0 }, 
      new float[] { 0, vector.y, 0, 0 }, 
      new float[] { 0, 0, vector.z, 0 }, 
      new float[] { 0, 0, 0, 0 }, 
    }); 
    //Add onto the matrix and return the result 
    return add(matrix, transform); 
} 

/* The static method used to return an orthographic projection matrix */ 
public static Matrix4D ortho(float left, float right, float top, float bottom, float zfar, float znear) { 
    return new Matrix4D(new float[][] { 
      new float[] { 2/(right - left), 0, 0, -((right + left)/(right - left)) }, 
      new float[] { 0, 2/(top - bottom), 0, -((top + bottom)/(top - bottom)) }, 
      new float[] { 0, 0, -2/(zfar - znear), -((zfar + znear)/(zfar - znear)) }, 
      new float[] { 0, 0, 0, 1 }, 
    }); 
} 

/* The static method used to return a perspective projection matrix */ 
public static Matrix4D perspective(float fov, float aspect, float zNear, float zFar) { 
    float f = (float) (1f/Math.tan(fov/2f)); 
    return new Matrix4D(new float[][] { 
      new float[] { f/aspect, 0, 0, 0 }, 
      new float[] { 0, f, 0, 0 }, 
      new float[] { 0, 0, (zFar + zNear)/(zFar - zNear), (2 * zFar * zNear)/(zNear - zFar) }, 
      new float[] { 0, 0, -1, 0 }, 
    }); 
} 

} 

最後用於設置方法的透視/正射投影是:

/* The static method to setup an orthographic view given the width, height 
* znear and zfar values */ 
public static void setupOrtho(float width, float height, float znear , float zfar) { 
    Matrix.loadIdentity(Matrix.modelMatrix); 
    Matrix.loadIdentity(Matrix.viewMatrix); 
    Matrix.projectionMatrix = Matrix.ortho(0, width, 0, height, znear, zfar); 
} 

/* The static method used to setup a perspective view given the 
* fov, z near and z far value */ 
public static void setupPerspective(float fov, float zNear, float zFar) { 
    setupPerspective(fov, (float) (Settings.Window.Width/Settings.Window.Height), zNear, zFar); 
} 

/* The static method used to setup a perspective view given the 
* fov, aspect ratio, z near and z far values */ 
public static void setupPerspective(float fov, float aspect, float zNear, float zFar) { 
    Matrix.loadIdentity(Matrix.modelMatrix); 
    Matrix.loadIdentity(Matrix.viewMatrix); 
    Matrix.projectionMatrix = Matrix.perspective(fov, aspect, zNear, zFar); 
} 

要渲染所有這些並將矩陣傳遞給我正在使用的着色器

//Multiply the matrices together 
    Matrix4D modelViewMatrix = Matrix.multiply(Matrix.modelMatrix, Matrix.viewMatrix); 
    Matrix.modelViewProjectionMatrix = (Matrix.multiply(modelViewMatrix, Matrix.projectionMatrix)); 
    System.out.println(Matrix.modelViewProjectionMatrix.toString() + "\n"); 

而在着色器中,我將當前頂點位置乘以模型視圖投影marix。

下面是它目前的樣子。

What the output currently looks like

回答

1

你似乎在錯誤的順序來乘以你的矩陣。當組合矩陣變換時,方程右邊的變換將是第一次變換。

你計算矩陣爲模型×查看×投影。將其與矢量相乘時,將首先執行投影,然後執行視圖變換,最後執行模型變換。顯然這不是你想要的。

您的最終矩陣應該像投影×視圖×模型一樣按照正確的順序進行轉換。

+0

我剛剛嘗試過,仍然不太正確。我添加了一些發生的事情的照片。它會與轉換順序有關嗎?我認爲我目前正在縮放,旋轉然後翻譯。 – 2851999 2014-09-07 10:51:44

+0

你實際上沒有正確計算你的翻譯,旋轉和比例矩陣。要正確地將轉換應用到傳遞給函數的矩陣,應該乘以新的而不是添加。你還需要在主對角線上有1個這樣的功能。 – 2014-09-07 20:20:51