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。
下面是它目前的樣子。
我剛剛嘗試過,仍然不太正確。我添加了一些發生的事情的照片。它會與轉換順序有關嗎?我認爲我目前正在縮放,旋轉然後翻譯。 – 2851999 2014-09-07 10:51:44
你實際上沒有正確計算你的翻譯,旋轉和比例矩陣。要正確地將轉換應用到傳遞給函數的矩陣,應該乘以新的而不是添加。你還需要在主對角線上有1個這樣的功能。 – 2014-09-07 20:20:51