-2

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;
    }
}
genpfault
  • 51,148
  • 11
  • 85
  • 139
notwhale
  • 19
  • 4
  • 2
    Just a forward-thinking note: It's a lot easier, and more performant, to detect the collision of basic shapes using algebra rather than direct vertex comparison. For instance, two spheres intersect if the difference between their centers is smaller than the sum of both their radii. Boxes can be compared based on comparing pairs of opposing verticies (i.e. two opposing corners). Checking just vertices would fail in cases like a small sphere going through the center of a box, so consideration of faces or edges may be pertinent. – Rogue Aug 31 '23 at 14:22

0 Answers0