Newer
Older
EPQ-3D-renderer / src / main / java / uk / org / floop / epq3d / ObjectCollection.java
@cory cory on 30 Jan 2023 5 KB Fix #5
package uk.org.floop.epq3d;

import java.awt.image.BufferedImage;
import java.util.ArrayList;

// stores both objects and other object collections
public class ObjectCollection {
    public String name;
    public ArrayList<PointComp> points = new ArrayList<PointComp>();

    //private Object3d collectionObject;
    public double boundingSphereR;
    public Point3D boundingSphereC;

    public ArrayList<ObjectCollection> subCollections = new ArrayList<ObjectCollection>();
    public ArrayList<Object3d> objects = new ArrayList<Object3d>();

    public ArrayList<PointComp> initialiseAll(){
        for (ObjectCollection subCollection:
             subCollections) {
            ArrayList<PointComp> subPoints = subCollection.initialiseAll();
            points.addAll(subPoints);
        }
        initialise();

        return points;
    }
    public void invalidate(boolean invalidatePoints){
        // the first level of object collections should contain all the points for the sublevels.
        // this means that we only need to invalidate them at the top level
        if(invalidatePoints){for (PointComp point:
             points) {
            point.invalidate();
        }}
        for(ObjectCollection subCollection:
        subCollections){
            subCollection.invalidate(false);
        }
        for(Object3d object:
        objects){
            object.invalidate();
        }
    }

    public void draw(int[][] img, int[][] zBuf, BufferedImage debugImg, Matrix camMatrix, Point3D playerPos, Plane[] frustumPlanes, double FPDis, int scrX, int scrY){
        for (Object3d object:
             objects) {
            boolean draw = true;
            int i = 0;
            for (Plane plane:
                 frustumPlanes) {
                    debugImg.getGraphics().drawString(
                            "Dis: " + String.format("%.1f", plane.getDistance(object.boundingSphereC)), 500, 10 + 20*i);
                if(plane.getDistance(object.boundingSphereC) < -object.boundingSphereR){
                    draw = false;
                    break;}
                i += 1;
            }
            if(draw){object.draw(img, zBuf, debugImg, camMatrix, FPDis, scrX, scrY, playerPos);}
        }
        // todo check for frustum culling
        for(ObjectCollection collection:
        subCollections){
            boolean draw = true;
            int i = 0;
            for (Plane plane:
                    frustumPlanes) {
                debugImg.getGraphics().drawString(
                        "Dis: " + String.format("%.1f", plane.getDistance(collection.boundingSphereC)), 500, 10 + 20*i);
                if(plane.getDistance(collection.boundingSphereC) < -collection.boundingSphereR){
                    draw = false;
                    break;}
                i += 1;
            }
            collection.draw(img, zBuf, debugImg, camMatrix, playerPos, frustumPlanes, FPDis, scrX, scrY);
        }
    }
    public void addCollection(){
        subCollections.add(new ObjectCollection());
    }
    public void addCollection(ObjectCollection newCollection){
        subCollections.add(newCollection);
    }
    // making sure that all the point indices make sense might be a nightmare but ehh
    public void addObject(Object3d object){
        PointComp[] newpoints = object.points;
        objects.add(object);
        // add the new object

        // merge lists
        for (PointComp newpoint : newpoints) {
            boolean found = false;
            // find out if any of the new points already exist in the list
            for (PointComp point : points) {
                if (newpoint == point) {
                    found = true;
                    break;
                }
            }
            if (!found) {
                points.add(newpoint);
            }
        }
    }
    public void initialise(){
        // init bounding sphere
        double distance = 0;
        double newDis;
        Point3D pointA = points.get(0).point;
        Point3D pointB = points.get(0).point;
        // todo - maybe use some vector classes?
        for (int i = 1; i < points.size(); i+=1) {
            newDis = Math.pow(points.get(0).point.x - points.get(i).point.x, 2) +
                    Math.pow(points.get(0).point.y - points.get(i).point.y, 2) +
                    Math.pow(points.get(0).point.z - points.get(i).point.z, 2);
            if (newDis >= distance){
                pointA = points.get(i).point;
                distance = newDis;}}
        for (PointComp point : points) {
            newDis = Math.pow(pointA.x - point.point.x, 2) +
                    Math.pow(pointA.y - point.point.y, 2) +
                    Math.pow(pointA.z - point.point.z, 2);
            if (newDis >= distance){
                pointB = point.point;
                distance = newDis;}}
        boundingSphereC = new Point3D(
                (pointA.x + pointB.x) / 2,
                (pointA.y + pointB.y)/2,
                (pointA.z + pointB.z)/2);
        boundingSphereR = Math.sqrt(distance)/2;
        boolean valid = false;
        for (PointComp point:
                points) {
            distance = Math.sqrt(
                    Math.pow(boundingSphereC.x - point.point.x, 2)+
                            Math.pow(boundingSphereC.y - point.point.y, 2)+
                            Math.pow(boundingSphereC.z - point.point.z, 2));
            if(distance > boundingSphereR){
                boundingSphereR = distance;
            }
        }
    }
}