I have an ArrayList<Vector3f>
where I store all the vertices of a 3D object. They are needed for collision detection (AABB) and for rendering them in 3D space. However, I have found that my method for transforming these vertices does not work as I would like. When the object is rendered, it appears with a position and rotation very different from the specified position and rotation. The shape and its scale do not appear to be distorted.
expectation:
reality:
Component.java:
package Engine;
import java.util.ArrayList;
import org.joml.Matrix4f;
import org.joml.Vector3f;
public abstract class Component {
private Vector3f pos = new Vector3f(0, 0, 0);
private Vector3f rotate = new Vector3f(0, 0, 0);
private Vector3f scale = new Vector3f(1, 1, 1);
public boolean checkColision(Component component) {
ArrayList<Vector3f> transformedVertices = transformVertices();
ArrayList<Vector3f> componentTransformedVertices = component.transformVertices();
Vector3f max = new Vector3f(Float.MIN_VALUE, Float.MIN_VALUE, Float.MIN_VALUE);
Vector3f min = new Vector3f(Float.MAX_VALUE, Float.MAX_VALUE, Float.MAX_VALUE);
for(Vector3f vertex : transformedVertices) {
if(vertex.x > max.x) max.x = vertex.x;
if(vertex.y > max.y) max.y = vertex.y;
if(vertex.z > max.z) max.z = vertex.z;
if(vertex.x < min.x) min.x = vertex.x;
if(vertex.y < min.y) min.y = vertex.y;
if(vertex.z < min.z) min.z = vertex.z;
}
Vector3f componentMax = new Vector3f(Float.MIN_VALUE, Float.MIN_VALUE, Float.MIN_VALUE);
Vector3f componentMin = new Vector3f(Float.MAX_VALUE, Float.MAX_VALUE, Float.MAX_VALUE);
for(Vector3f vertex : componentTransformedVertices) {
if(vertex.x > componentMax.x) componentMax.x = vertex.x;
if(vertex.y > componentMax.y) componentMax.y = vertex.y;
if(vertex.z > componentMax.z) componentMax.z = vertex.z;
if(vertex.x < componentMin.x) componentMin.x = vertex.x;
if(vertex.y < componentMin.y) componentMin.y = vertex.y;
if(vertex.z < componentMin.z) componentMin.z = vertex.z;
}
if (
componentMin.x <= max.x && min.x <= componentMax.x &&
componentMin.y <= max.x && min.y <= componentMax.y &&
componentMin.z <= max.x && min.z <= componentMax.z)
return true;
return false;
}
public Vector3f getPos() {
return pos;
}
public Vector3f getRotate() {
return rotate;
}
public Vector3f getScale() {
return scale;
}
public void setPos(Vector3f pos) {
this.pos = pos;
}
public void setRotation(Vector3f rotate) {
this.rotate = rotate;
}
public void setScale(Vector3f scale) {
this.scale = scale;
}
public abstract void render();
public abstract ArrayList<Vector3f> getVertices();
public synchronized ArrayList<Vector3f> transformVertices() {
ArrayList<Vector3f> transformedVertices = new ArrayList<>();
Matrix4f transformationMatrix = new Matrix4f()
.translate(pos)
.rotateX(rotate.x)
.rotateY(rotate.y)
.rotateZ(rotate.z)
.scale(scale);
for (Vector3f vertex : getVertices()) {
Vector3f transformedVertex = new Vector3f(vertex);
transformedVertex.mulPosition(transformationMatrix);
transformedVertices.add(transformedVertex);
}
return transformedVertices;
}
}
Cube.java:
package Models;
import Engine.Component;
import java.util.ArrayList;
import org.joml.Vector3f;
import org.lwjgl.opengl.GL11;
public class Cube extends Component {
public float size = 1.0f;
@Override
public void render() {
GL11.glBegin(GL11.GL_QUADS);
GL11.glColor3f(0.7f, 0.7f, 0.7f);
for(Vector3f vertex : transformVertices()) {
GL11.glVertex3f(vertex.x, vertex.y, vertex.z);
}
GL11.glEnd();
}
@Override
public ArrayList<Vector3f> getVertices() {
return new ArrayList<Vector3f>() {{
add(new Vector3f(-size, size, -size));
add(new Vector3f(size, size, -size));
add(new Vector3f(size, size, size));
add(new Vector3f(-size, size, size));
add(new Vector3f(-size, -size, -size));
add(new Vector3f(-size, -size, size));
add(new Vector3f(size, -size, size));
add(new Vector3f(size, -size, -size));
add(new Vector3f(-size, -size, size));
add(new Vector3f(-size, size, size));
add(new Vector3f(size, size, size));
add(new Vector3f(size, -size, size));
add(new Vector3f(-size, -size, -size));
add(new Vector3f(size, -size, -size));
add(new Vector3f(size, size, -size));
add(new Vector3f(-size, size, -size));
add(new Vector3f(-size, -size, -size));
add(new Vector3f(-size, -size, size));
add(new Vector3f(-size, size, size));
add(new Vector3f(-size, size, -size));
add(new Vector3f(size, -size, -size));
add(new Vector3f(size, size, -size));
add(new Vector3f(size, size, size));
add(new Vector3f(size, -size, size));
}};
}
}
Sphere.java:
package Models;
import Engine.Component;
import org.lwjgl.opengl.GL11;
import static org.lwjgl.opengl.GL11.*;
import java.util.ArrayList;
import org.joml.Vector3f;
public class Sphere extends Component {
public float radius = 1.0f;
public int gradation = 100;
public final float PI = (float) Math.PI;
@Override
public void render() {
GL11.glBegin(GL_TRIANGLE_STRIP);
for(Vector3f vertex : transformVertices()) {
GL11.glVertex3f(vertex.x, vertex.y, vertex.z);
}
GL11.glEnd();
}
@Override
public ArrayList<Vector3f> getVertices() {
ArrayList<Vector3f> vertices = new ArrayList<>();
float x, y, z, alpha, beta;
for (alpha = 0.0f; alpha < Math.PI; alpha += PI / gradation) {
for (beta = 0.0f; beta < 2.01f * Math.PI; beta += PI / gradation) {
x = (float) (radius * Math.cos(beta) * Math.sin(alpha));
y = (float) (radius * Math.sin(beta) * Math.sin(alpha));
z = (float) (radius * Math.cos(alpha));
vertices.add(new Vector3f(x, y, z));
x = (float) (radius * Math.cos(beta) * Math.sin(alpha + PI / gradation));
y = (float) (radius * Math.sin(beta) * Math.sin(alpha + PI / gradation));
z = (float) (radius * Math.cos(alpha + PI / gradation));
vertices.add(new Vector3f(x, y, z));
}
}
return vertices;
}
}