Java OpenGL矩阵奇异变换
我一直在尝试制作一个游戏引擎,只是为了学习一些新的东西,一切都正常,但我后来决定,对于照明,我将制作自己的矩阵类,并将最终的矩阵传递给着色器。不幸的是,这最终破坏了整个渲染系统,因为现在所有的东西都在拉伸,这肯定是不对的。目前我已经搞乱了乘法的顺序,但它仍然不起作用,我已经有一个多月的问题了,我只想修复它,继续制造引擎 首先,这里是在PC上使用的默认着色器:Java OpenGL矩阵奇异变换,java,opengl,matrix,lwjgl,Java,Opengl,Matrix,Lwjgl,我一直在尝试制作一个游戏引擎,只是为了学习一些新的东西,一切都正常,但我后来决定,对于照明,我将制作自己的矩阵类,并将最终的矩阵传递给着色器。不幸的是,这最终破坏了整个渲染系统,因为现在所有的东西都在拉伸,这肯定是不对的。目前我已经搞乱了乘法的顺序,但它仍然不起作用,我已经有一个多月的问题了,我只想修复它,继续制造引擎 首先,这里是在PC上使用的默认着色器: public static final String[] pcVertexShaderCode = new String[] {
public static final String[] pcVertexShaderCode = new String[] {
"attribute vec4 andor_vertexPosition;",
"attribute vec3 andor_normal;",
"attribute vec2 andor_vtextureCoord;",
"attribute vec4 andor_vcolour;",
"uniform mat4 andor_modelmatrix;",
"uniform mat4 andor_viewmatrix;",
"uniform mat4 andor_projectionmatrix;",
"uniform mat4 andor_modelviewprojectionmatrix;",
"varying vec4 andor_colour;",
"varying vec2 andor_textureCoord;",
"void andor_main();",
"void main() {",
" andor_colour = andor_vcolour;",
" andor_textureCoord = andor_vtextureCoord;",
// " andor_modelviewprojectionmatrix = andor_modelmatrix * andor_viewmatrix * andor_projectionmatrix;",
" gl_Position = andor_modelviewprojectionmatrix * andor_vertexPosition;",
" andor_main();",
"}" };
public static final String[] pcFragmentShaderCode = new String[] {
"uniform sampler2D andor_texture;",
"uniform float andor_hasTexture;",
"varying vec4 andor_colour;",
"varying vec2 andor_textureCoord;",
"void andor_main();",
"void main() {",
" if (andor_hasTexture > 0.5) {",
" gl_FragColor = andor_colour * texture2D(andor_texture, andor_textureCoord);",
" } else {",
" gl_FragColor = andor_colour;",
" }",
" andor_main();",
"}" };
这是场景中每个对象调用的渲染方法:
/* The method used to draw the object */
public void render() {
//Multiply the matrices together
Matrix4D projectionViewMatrix = Matrix.multiply(Matrix.projectionMatrix, Matrix.viewMatrix);
Matrix.modelViewProjectionMatrix = (Matrix.multiply(projectionViewMatrix, Matrix.modelMatrix));
//Sky box in relatively the right place
// Matrix4D modelViewMatrix = Matrix.multiply(Matrix.modelMatrix, Matrix.viewMatrix);
// Matrix.modelViewProjectionMatrix = (Matrix.multiply(modelViewMatrix, Matrix.projectionMatrix));
// Matrix4D modelProjectionMatrix = Matrix.multiply(Matrix.modelMatrix, Matrix.projectionMatrix);
// Matrix.modelViewProjectionMatrix = (Matrix.multiply(Matrix.viewMatrix, modelProjectionMatrix));
// Matrix4D modelViewMatrix = Matrix.multiply(Matrix.modelMatrix, Matrix.viewMatrix);
// Matrix.modelViewProjectionMatrix = (modelViewMatrix);
// //TEST
// for (int a = 0; a < 16; a++) {
// //2D WORKS!!!!! Kind of...
// Matrix.modelViewProjectionMatrix.values[a] = Matrix.modelMatrix.values[a] * Matrix.projectionMatrix.values[a] * Matrix.viewMatrix.values[a];
// }
System.out.println(Matrix.modelViewProjectionMatrix.toString() + "\n");
//Set the correct android shader
Shader shader = defaultShader;
if (currentShader != null)
shader = currentShader;
//Use the shader program
GL20.glUseProgram(shader.program);
//Enable the arrays as needed
int vertexPositionAttribute = shader.getAttributeLocation("andor_vertexPosition");
int normalAttribute = 0;
int colourAttribute = 0;
int texturesAttribute = 0;
int modelMatrixAttribute = shader.getUniformLocation("andor_modelmatrix");
int viewMatrixAttribute = shader.getUniformLocation("andor_viewmatrix");
int projectionMatrixAttribute = shader.getUniformLocation("andor_projectionmatrix");
int matrixAttribute = shader.getUniformLocation("andor_modelviewprojectionmatrix");
GL20.glUniformMatrix4(modelMatrixAttribute, false, BufferUtils.createFlippedBuffer(Matrix.modelMatrix.getValues()));
GL20.glUniformMatrix4(viewMatrixAttribute, false, BufferUtils.createFlippedBuffer(Matrix.viewMatrix.getValues()));
GL20.glUniformMatrix4(projectionMatrixAttribute, false, BufferUtils.createFlippedBuffer(Matrix.projectionMatrix.getValues()));
GL20.glUniformMatrix4(matrixAttribute, false, BufferUtils.createFlippedBuffer(Matrix.modelViewProjectionMatrix.getValues()));
GL20.glEnableVertexAttribArray(vertexPositionAttribute);
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, this.verticesHandle);
GL20.glVertexAttribPointer(vertexPositionAttribute, this.vertexValuesCount, GL11.GL_FLOAT, false, 0, 0);
if (this.normalsData != null) {
normalAttribute = shader.getAttributeLocation("andor_normal");
GL20.glEnableVertexAttribArray(normalAttribute);
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, this.normalsHandle);
GL20.glVertexAttribPointer(normalAttribute, this.vertexValuesCount, GL11.GL_FLOAT, false, 0, 0);
}
if (this.colourData != null) {
colourAttribute = shader.getAttributeLocation("andor_vcolour");
GL20.glEnableVertexAttribArray(colourAttribute);
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, this.coloursHandle);
GL20.glVertexAttribPointer(colourAttribute, this.colourValuesCount, GL11.GL_FLOAT, false, 0, 0);
}
if (this.textureData != null) {
texturesAttribute = shader.getAttributeLocation("andor_vtextureCoord");
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, this.texturesHandle);
GL20.glEnableVertexAttribArray(texturesAttribute);
GL20.glVertexAttribPointer(texturesAttribute, this.textureValuesCount, GL11.GL_FLOAT, false, 0, 0);
GL20.glUniform1i(shader.getUniformLocation("andor_texture"), 0);
if (texture != null)
GL20.glUniform1f(shader.getUniformLocation("andor_hasTexture"), 1f);
}
if (this.drawOrder != null) {
GL15.glBindBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER, this.drawOrderHandle);
GL11.glDrawElements(this.renderMode, this.drawOrder.length, GL11.GL_UNSIGNED_SHORT, 0);
GL15.glBindBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER, 0);
} else {
//Draw the arrays
GL11.glDrawArrays(this.renderMode, 0, this.verticesData.length / this.vertexValuesCount);
}
//Disable the arrays as needed
if (this.normalsData != null)
GL20.glDisableVertexAttribArray(normalAttribute);
if (this.textureData != null)
GL20.glDisableVertexAttribArray(texturesAttribute);
if (this.colourData != null)
GL20.glDisableVertexAttribArray(colourAttribute);
GL20.glDisableVertexAttribArray(vertexPositionAttribute);
//Stop using the shader program
GL20.glUseProgram(0);
}
在camera类中,这用于移动玩家视图:
//Get the rotation
Vector3D r = this.getRotation();
//Get the position
Vector3D p = this.getPosition();
//Get the scale
Vector3D s = this.getScale();
//Rotate by the specified amount
Matrix.viewMatrix = Matrix.rotate(Matrix.viewMatrix, r.x, 1, 0, 0);
Matrix.viewMatrix = Matrix.rotate(Matrix.viewMatrix, r.y, 0, 1, 0);
Matrix.viewMatrix = Matrix.rotate(Matrix.viewMatrix, r.z, 0, 0, 1);
//Move to the correct position
Matrix.viewMatrix = Matrix.translate(Matrix.viewMatrix, p);
//Scale by the correct amount
Matrix.viewMatrix = Matrix.scale(Matrix.viewMatrix, s);
以下是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;
}
}
公共类矩阵x4d{
/*此矩阵中的值*/
公众价值观;
/*默认构造函数*/
公共矩阵x4d(){
//创建值
this.values=新浮动[16];
}
/*具有给定值的构造函数*/
公共矩阵x4d(浮点[]值){
//创建值
这个值=值;
}
/*具有给定值的构造函数*/
公共矩阵x4d(浮点[][]值){
//加载值
荷载(值);
}
/*用于设置给定二维数组的值的方法*/
公共无效荷载(浮动[][]值){
this.values=new float[]{
值[0][0]、值[0][1]、值[0][2]、值[0][3],
数值[1][0]、数值[1][1]、数值[1][2]、数值[1][3],
数值[2][0]、数值[2][1]、数值[2][2]、数值[2][3],
数值[3][0]、数值[3][1]、数值[3][2]、数值[3][3]
};
}
/*使用此矩阵中的坐标获取值的方法*/
公共浮点get(整数x,整数y){
//获得职位
内部位置=x+(y*4);
//返回值
返回此。值[位置];
}
/*用于返回此矩阵的字符串表示形式的方法*/
公共字符串toString(){
//返回字符串
返回“[”+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]+”;
}
/*用于获取值的方法*/
public float[]getValues(){返回this.values;}
/*用于获取二维数组中的值的方法*/
公开浮动[][]getValues2DArray(){
//阵列
float[][]数组=新的float[4][4];
//检查每个值
int列=0;
int行=0;
while(列*行=4){
列++;
行=0;
}
数组[列][行]=此.值[列*行];
}
//返回数组
返回数组;
}
}
下面是矩阵类:
package org.andor.core;
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[] { 1, 0, 0, vector.x },
new float[] { 0, 1, 0, vector.y },
new float[] { 0, 0, 1, vector.z },
new float[] { 0, 0, 0, 1 },
});
//Add onto the matrix and return the result
return multiply(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[] { 1, 0, 0, 0 },
new float[] { 0, cos, -sin, 0 },
new float[] { 0, sin, cos, 0 },
new float[] { 0, 0, 0, 1 },
});
} else if (y == 1) {
transform.load(new float[][] {
new float[] { cos, 0, sin, 0 },
new float[] { 0, 1, 0, 0 },
new float[] { -sin, 0, cos, 0 },
new float[] { 0, 0, 0, 1 },
});
} else if (z == 1) {
transform.load(new float[][] {
new float[] { cos, -sin, 0, 0 },
new float[] { sin, cos, 0, 0 },
new float[] { 0, 0, 1, 0 },
new float[] { 0, 0, 0, 1 },
});
}
//Add onto the matrix and return the result
return multiply(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, 1 },
});
//Add onto the matrix and return the result
return multiply(matrix, transform);
}
/* The static method used to return an orthographic projection matrix */
public static Matrix4D ortho(float left, float right, float bottom, float top, float zfar, float znear) {
// Matrix4D mat = new Matrix4D();
// mat.values[0] = 2 / (right - left);
// mat.values[5] = 2 / (top - bottom);
// mat.values[10] = - 2 / (zfar - znear);
// mat.values[12] = - (right + left) / (right - left);
// mat.values[13] = -(top + bottom) / (top - bottom);
// mat.values[14] = -(zfar + znear) / (zfar - znear);
// return mat;
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) {
//Calculate the values that need to be calculated the most frequently
float f = 1.0f / (float) Math.tan(fov / 2 * (Math.PI / 360.0));
float rangeReciprocal = 1.0f / (zNear - zFar);
Matrix4D matrix = new Matrix4D();
//Set the matrix values
matrix.values[0] = f / aspect;
matrix.values[1] = 0.0f;
matrix.values[2] = 0.0f;
matrix.values[3] = 0.0f;
matrix.values[4] = 0.0f;
matrix.values[5] = f;
matrix.values[6] = 0.0f;
matrix.values[7] = 0.0f;
matrix.values[8] = 0.0f;
matrix.values[9] = 0.0f;
matrix.values[10] = (zFar + zNear) * rangeReciprocal;
matrix.values[11] = -1.0f;
matrix.values[12] = 0.0f;
matrix.values[13] = 0.0f;
matrix.values[14] = 2.0f * zFar * zNear * rangeReciprocal;
matrix.values[15] = 0.0f;
return matrix;
}
}
package org.andor.core;
公共类矩阵{
/*不同的矩阵*/
公共静态矩阵x4d modelMatrix=新矩阵x4d();
public static Matrix4D viewMatrix=new Matrix4D();
公共静态Matrix4D projectionMatrix=新Matrix4D();
公共静态Matrix4D modelViewProjectionMatrix=新Matrix4D();
/*用于加载单位矩阵的静态方法*/
公共静态void loadIdentity(矩阵x4d矩阵){
//加载单位矩阵
矩阵加载(新浮点[][]{
新浮点[]{1,0,0,0},
新浮点[]{0,1,0,0},
新浮点[]{0,0,1,0},
新浮点[]{0,0,0,1},
});
}
/*用于将两个矩阵相加的静态方法*/
公共静态Matrix4D添加(Matrix4D matrixA,Matrix4D matrixB){
//创建一个新的矩阵
Matrix4D矩阵=新的Matrix4D();
//检查每个值
对于(int a=0;apackage org.andor.core;
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[] { 1, 0, 0, vector.x },
new float[] { 0, 1, 0, vector.y },
new float[] { 0, 0, 1, vector.z },
new float[] { 0, 0, 0, 1 },
});
//Add onto the matrix and return the result
return multiply(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[] { 1, 0, 0, 0 },
new float[] { 0, cos, -sin, 0 },
new float[] { 0, sin, cos, 0 },
new float[] { 0, 0, 0, 1 },
});
} else if (y == 1) {
transform.load(new float[][] {
new float[] { cos, 0, sin, 0 },
new float[] { 0, 1, 0, 0 },
new float[] { -sin, 0, cos, 0 },
new float[] { 0, 0, 0, 1 },
});
} else if (z == 1) {
transform.load(new float[][] {
new float[] { cos, -sin, 0, 0 },
new float[] { sin, cos, 0, 0 },
new float[] { 0, 0, 1, 0 },
new float[] { 0, 0, 0, 1 },
});
}
//Add onto the matrix and return the result
return multiply(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, 1 },
});
//Add onto the matrix and return the result
return multiply(matrix, transform);
}
/* The static method used to return an orthographic projection matrix */
public static Matrix4D ortho(float left, float right, float bottom, float top, float zfar, float znear) {
// Matrix4D mat = new Matrix4D();
// mat.values[0] = 2 / (right - left);
// mat.values[5] = 2 / (top - bottom);
// mat.values[10] = - 2 / (zfar - znear);
// mat.values[12] = - (right + left) / (right - left);
// mat.values[13] = -(top + bottom) / (top - bottom);
// mat.values[14] = -(zfar + znear) / (zfar - znear);
// return mat;
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) {
//Calculate the values that need to be calculated the most frequently
float f = 1.0f / (float) Math.tan(fov / 2 * (Math.PI / 360.0));
float rangeReciprocal = 1.0f / (zNear - zFar);
Matrix4D matrix = new Matrix4D();
//Set the matrix values
matrix.values[0] = f / aspect;
matrix.values[1] = 0.0f;
matrix.values[2] = 0.0f;
matrix.values[3] = 0.0f;
matrix.values[4] = 0.0f;
matrix.values[5] = f;
matrix.values[6] = 0.0f;
matrix.values[7] = 0.0f;
matrix.values[8] = 0.0f;
matrix.values[9] = 0.0f;
matrix.values[10] = (zFar + zNear) * rangeReciprocal;
matrix.values[11] = -1.0f;
matrix.values[12] = 0.0f;
matrix.values[13] = 0.0f;
matrix.values[14] = 2.0f * zFar * zNear * rangeReciprocal;
matrix.values[15] = 0.0f;
return matrix;
}
}