Currently I'm trying to implement Frustum culling into my engine, and on smaller objects it works perfectly fine, but larger objects get culled out much sooner than they should be.
You can see that it works perfectly fine with smaller objects
But larger objects get culled out much sooner than they should be.
Here is my Frustum Culler and Plane class:
package toolbox;
import org.lwjgl.opengl.Display;
import org.lwjgl.util.vector.Matrix4f;
import org.lwjgl.util.vector.Vector3f;
import org.lwjgl.util.vector.Vector4f;
import entities.Entity;
import main.Camera;
import utils.Maths;
public class FrustumCuller {
private static final float HALF_DIAGONAL = 0.8536F;
private Camera camera;
private Plane2[] frustum;
private float farDistance;
private float heightFar;
private float widthFar;
public FrustumCuller(Camera camera) {
this.frustum = new Plane2[2];
this.farDistance = camera.getFarPlane();
this.heightFar = ((float) (2.0D * Math.tan(Maths.degreesToRadians(camera.getFov())) * this.farDistance));
this.widthFar = ((this.heightFar) * (Display.getWidth() / Display.getHeight()) * 2);
this.camera = camera;
}
public void updatePlanes() {
Vector3f point = new Vector3f(this.camera.getPosition().x, this.camera.getPosition().y,
this.camera.getPosition().z);
Vector3f direction = new Vector3f();
Vector3f up = new Vector3f();
Vector3f down = new Vector3f();
Vector3f left = new Vector3f();
Vector3f right = new Vector3f();
calculateVectorDirections(direction, up, down, right, left);
Vector3f farPlaneCenter = Vector3f.add(point, new Vector3f(direction.x * this.farDistance,
direction.y * this.farDistance, direction.z * this.farDistance), null);
this.frustum[0] = new Plane2(calculatePlaneNormal(point, farPlaneCenter, right, up, this.widthFar / 2.0F),
point);
this.frustum[1] = new Plane2(calculatePlaneNormal(point, farPlaneCenter, right, down, -this.widthFar / 2.0F),
point);
}
public void testEntityInView(Entity entity) {
boolean render = true;
Vector3f point = new Vector3f(entity.getPosition().x, entity.getPosition().y, entity.getPosition().z);
for (Plane2 plane : this.frustum) {
float distance = plane.getSignedDistance(point);
if (distance < (-entity.getFurthestPoint())) {
render = false;
}
}
entity.setCanRender(render);
}
private Vector3f calculatePlaneNormal(Vector3f point, Vector3f farPlaneCenter, Vector3f right, Vector3f onPlane,
float side) {
Vector3f sidePoint = Vector3f.add(farPlaneCenter, new Vector3f(right.x * side, right.y * side, right.z * side),
null);
Vector3f alongPlane = Vector3f.sub(sidePoint, point, null);
alongPlane.normalise();
return Vector3f.cross(onPlane, alongPlane, null);
}
private void calculateVectorDirections(Vector3f direction, Vector3f up, Vector3f down, Vector3f right,
Vector3f left) {
Vector4f originalDirection = new Vector4f(0.0F, 0.0F, -1.0F, 1.0F);
Vector4f originalUp = new Vector4f(0.0F, 1.0F, 0.0F, 1.0F);
Matrix4f rotation = new Matrix4f();
rotation.rotate(Maths.degreesToRadians(-this.camera.getYaw()), new Vector3f(0.0F, 1.0F, 0.0F));
rotation.rotate(Maths.degreesToRadians(-this.camera.getPitch()), new Vector3f(1.0F, 0.0F, 0.0F));
Matrix4f.transform(rotation, originalUp, originalUp);
Matrix4f.transform(rotation, originalDirection, originalDirection);
up.set(originalUp);
direction.set(originalDirection);
right.set(Vector3f.cross(direction, up, null));
right.normalise();
right.negate(left);
up.negate(down);
}
}
package toolbox;
import org.lwjgl.util.vector.Vector3f;
import rendering.Triangle;
import rendering.Triangle;
import rendering.Triangle;
public class Plane2 {
private Triangle triangle;
private Vector3f origin;
private Vector3f normal;
private float constant;
private float t0;
private float t1;
public Plane2(Triangle triangle) {
this.triangle = triangle;
Vector3f point0 = triangle.getPointN(0);
Vector3f point1 = triangle.getPointN(1);
Vector3f point2 = triangle.getPointN(2);
this.normal = Vector3f.cross(Vector3f.sub(point2, point0, null), Vector3f.sub(point1, point0, null), null);
this.normal.normalise();
this.origin = new Vector3f(point0.x, point0.y, point0.z);
this.constant = (-(this.normal.x * this.origin.x + this.normal.y * this.origin.y
+ this.normal.z * this.origin.z));
}
public Plane2(Vector3f normal, Vector3f origin) {
this.normal = normal;
this.origin = origin;
this.constant = (-(normal.x * origin.x + normal.y * origin.y + normal.z * origin.z));
}
public float getSignedDistance(Vector3f point) {
return Vector3f.dot(this.normal, point) + this.constant;
}
public boolean isFrontFacingTo(Vector3f direction) {
float dot = Vector3f.dot(this.normal, direction);
return dot <= 0.0F;
}
public Triangle getTriangle() {
return this.triangle;
}
public Vector3f getOrigin() {
return this.origin;
}
public Vector3f getNormal() {
return this.normal;
}
public float getConstant() {
return this.constant;
}
public float getT0() {
return this.t0;
}
public void setT0(float t0) {
this.t0 = t0;
}
public float getT1() {
return this.t1;
}
public void setT1(float t1) {
this.t1 = t1;
}
}