Ich versuche eine 4 * 4 Float-Matrix-Klasse zu schreiben, um einen 3D-Raum mit Modell-, Ansichts- und Projektionsmatrizen zu erstellen. In meinem aktuellen Zustand, wenn ich versuche, die Ansichtsmatrix zu drehen, scheint es auch eine Übersetzung anzuwenden, und der Raum wird verzerrt (als ob er gequetscht wäre). Die Multiplikation der Projektion, der Ansicht und der Modellmatrix erfolgt im Vertex-Shader.OpenGL Java Matrix4f Implementierung
Edit5: Die nicht funktionierenden Zustand der Transformationsfunktionen gefunden unten ist:
public class Mat4f {
public float m00, m10, m20, m30,
m01, m11, m21, m31,
m02, m12, m22, m32,
m03, m13, m23, m33;
public Mat4f() {
loadIdentity();
}
public Mat4f loadIdentity() {
m00 = 1.0f; m10 = 0.0f; m20 = 0.0f; m30 = 0.0f;
m01 = 0.0f; m11 = 1.0f; m21 = 0.0f; m31 = 0.0f;
m02 = 0.0f; m12 = 0.0f; m22 = 1.0f; m32 = 0.0f;
m03 = 0.0f; m13 = 0.0f; m23 = 0.0f; m33 = 1.0f;
return this;
}
public Mat4f store(FloatBuffer buffer) {
buffer.put(m00);
buffer.put(m01);
buffer.put(m02);
buffer.put(m03);
buffer.put(m10);
buffer.put(m11);
buffer.put(m12);
buffer.put(m13);
buffer.put(m20);
buffer.put(m21);
buffer.put(m22);
buffer.put(m23);
buffer.put(m30);
buffer.put(m31);
buffer.put(m32);
buffer.put(m33);
buffer.flip();
return this;
}
public Mat4f loadPerspective(float fov, float ratio, float near, float far) {
m11 = (float) (1.0f/(Math.tan(fov/2.0f)));
m00 = m11/ratio;
m22 = -(far + near)/(far - near);
m23 = -1.0f;
m32 = -2.0f * far * near/(far - near);
m33 = 0.0f;
return this;
}
public Mat4f translate(float x, float y, float z) {
m30 = x;
m31 = y;
m32 = z;
return this;
}
public Mat4f scale(float x, float y, float z) {
m00 = x;
m11 = y;
m22 = z;
return this;
}
public Mat4f rotateX(float x) {
m11 = (float) Math.cos(x);
m12 = (float) Math.sin(x);
m21 = (float) -(Math.sin(x));
m22 = (float) Math.cos(x);
return this;
}
public Mat4f rotateY(float y) {
m00 = (float) Math.cos(y);
m02 = (float) -(Math.sin(y));
m20 = (float) Math.sin(y);
m22 = (float) Math.cos(y);
return this;
}
public Mat4f rotateZ(float z) {
m00 = (float) Math.cos(z);
m01 = (float) Math.sin(z);
m10 = (float) -(Math.sin(z));
m11 = (float) Math.cos(z);
return this;
}
}
Und der richtige Weg, diejenigen zu tun, ist wie folgt:
public Mat4f translate(float x, float y, float z, Mat4f dest) {
dest.m00 = m00;
dest.m01 = m01;
dest.m02 = m02;
dest.m03 = m03;
dest.m10 = m10;
dest.m11 = m11;
dest.m12 = m12;
dest.m13 = m13;
dest.m20 = m20;
dest.m21 = m21;
dest.m22 = m22;
dest.m23 = m23;
dest.m30 = m00 * x + m10 * y + m20 * z + m30;
dest.m31 = m01 * x + m11 * y + m21 * z + m31;
dest.m32 = m02 * x + m12 * y + m22 * z + m32;
dest.m33 = m03 * x + m13 * y + m23 * z + m33;
return this;
}
public Mat4f translate(float x, float y, float z) {
return translate(x, y, z, this);
}
public Mat4f scale(float x, float y, float z, Mat4f dest) {
dest.m00 = m00 * x;
dest.m01 = m01 * x;
dest.m02 = m02 * x;
dest.m03 = m03 * x;
dest.m10 = m10 * y;
dest.m11 = m11 * y;
dest.m12 = m12 * y;
dest.m13 = m13 * y;
dest.m20 = m20 * z;
dest.m21 = m21 * z;
dest.m22 = m22 * z;
dest.m23 = m23 * z;
dest.m30 = m30;
dest.m31 = m31;
dest.m32 = m32;
dest.m33 = m33;
return this;
}
public Mat4f scale(float x, float y, float z) {
return scale(x, y, z, this);
}
public Mat4f rotateX(float x, Mat4f dest) {
float cos = (float) Math.cos(x);
float sin = (float) Math.sin(x);
float rm11 = cos;
float rm12 = sin;
float rm21 = -sin;
float rm22 = cos;
float nm10 = m10 * rm11 + m20 * rm12;
float nm11 = m11 * rm11 + m21 * rm12;
float nm12 = m12 * rm11 + m22 * rm12;
float nm13 = m13 * rm11 + m23 * rm12;
dest. m20 = m10 * rm21 + m20 * rm22;
dest.m21 = m11 * rm21 + m21 * rm22;
dest.m22 = m12 * rm21 + m22 * rm22;
dest. m23 = m13 * rm21 + m23 * rm22;
dest.m10 = nm10;
dest.m11 = nm11;
dest.m12 = nm12;
dest.m13 = nm13;
return this;
}
public Mat4f rotateX(float x) {
return rotateX(x, this);
}
public Mat4f rotateY(float y, Mat4f dest) {
float cos = (float) Math.cos(y);
float sin = (float) Math.sin(y);
float rm00 = cos;
float rm02 = -sin;
float rm20 = sin;
float rm22 = cos;
float nm00 = m00 * rm00 + m20 * rm02;
float nm01 = m01 * rm00 + m21 * rm02;
float nm02 = m02 * rm00 + m22 * rm02;
float nm03 = m03 * rm00 + m23 * rm02;
dest.m20 = m00 * rm20 + m20 * rm22;
dest.m21 = m01 * rm20 + m21 * rm22;
dest.m22 = m02 * rm20 + m22 * rm22;
dest.m23 = m03 * rm20 + m23 * rm22;
dest.m00 = nm00;
dest.m01 = nm01;
dest.m02 = nm02;
dest.m03 = nm03;
return this;
}
public Mat4f rotateY(float y) {
return rotateY(y, this);
}
public Mat4f rotateZ(float z, Mat4f dest) {
float cos = (float) Math.cos(z);
float sin = (float) Math.sin(z);
float rm00 = cos;
float rm01 = sin;
float rm10 = -sin;
float rm11 = cos;
float nm00 = m00 * rm00 + m10 * rm01;
float nm01 = m01 * rm00 + m11 * rm01;
float nm02 = m02 * rm00 + m12 * rm01;
float nm03 = m03 * rm00 + m13 * rm01;
dest.m10 = m00 * rm10 + m10 * rm11;
dest.m11 = m01 * rm10 + m11 * rm11;
dest.m12 = m02 * rm10 + m12 * rm11;
dest.m13 = m03 * rm10 + m13 * rm11;
dest.m00 = nm00;
dest.m01 = nm01;
dest.m02 = nm02;
dest.m03 = nm03;
return this;
}
public Mat4f rotateZ(float z) {
return rotateZ(z, this);
}
Um die Matrizen zu ändern I verwendet die folgende Reihenfolge der Transformationen:
public void transform() {
mMat.loadIdentity();
mMat.translate(position.x, position.y, position.z);
mMat.rotateX((float) Math.toRadians(orientation.x));
mMat.rotateY((float) Math.toRadians(orientation.y));
mMat.rotateZ((float) Math.toRadians(orientation.z));
mMat.scale(scale.x, scale.y, scale.z);
}
public void updateCamera() {
Vec3f position = World.camera.getPosition();
vMat.loadIdentity();
vMat.rotateX((float) Math.toRadians(World.camera.getPitch()));
vMat.rotateY((float) Math.toRadians(World.camera.getYaw()));
vMat.translate(-position.x, -position.y, position.z);
}
Edit: die perspektivische Projektion ist in Ordnung, und so ist die Übersetzung, aber wenn ich die Modellmatrix in einer Mat4f speichere, folgt die Drehung der Modelle der Kamera.
Edit2: Die Ausrichtung des Modells folgt nicht mehr der Kameradrehung, wenn ich Mat4f als Modellmatrix verwende. Die Projektionsmatrix, die Übersetzung und die Skalierung funktionieren gut.
Edit3: Bearbeitet den Code, die angewandte Rotation ist keine Vollkreisrotation, das Modell schwingt nach links und rechts.
Edit4: Ich habe dabei die Rotation mit Matrixmultiplikation versuchten
Vielen Dank, dass Sie sich die Zeit genommen haben, meine Frage zu beantworten! Die loadPerspective-Methode, die Übersetzung und die Skalierung funktionieren einwandfrei, daher kann es sich nicht um das Problem beim Sortieren handeln. Wenn ich die Speicherfunktion so ändere, daß sie die Zeile major ist (was meiner Meinung nach dasselbe ist wie die Änderung meiner Indizes in m03, m13 und m23 im Falle einer Übersetzung), dann ist alles stockdunkel, auch wenn ich die Reihenfolge der Multiplikationen in der Vertexshader –
Ich aktualisierte meine Antwort. – derhass
Die Positions-, Orientierungs- und Skalierungsfelder der Objekte behalten ihre absoluten Werte, nicht das Delta. Ich rufe die Identitätsmatrix jedes Mal auf, bevor ich eine Matrix übersetze. Das einzige, was ich nicht funktioniere, ist die Rotation. Ich habe versucht, die Indizes nur in der Rotation zu transponieren, und das hat auch nicht funktioniert. Ich habe auch versucht, der Funktion abhängige Werte hinzuzufügen (siehe die Änderung), aber es erzeugt immer die gleiche Art von Fehlverhalten. –