В настоящее время я пытаюсь реализовать отбраковку Frustum в моем движке, и на небольших объектах он работает отлично, но более крупные объекты отбраковываются гораздо раньше, чем должны.
Вы можете видеть, что он отлично работает с меньшими объектами, но более крупные объекты отбираются намного раньше, чем должны.
Вот мой класс Frustum Culler и Plane:
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;
}
}