Newer
Older
EPQ-3D-renderer / src / main / java / uk / org / floop / epq3d / Object3d.java
@cory cory on 15 Apr 2023 4 KB Final changes (idk)
package uk.org.floop.epq3d;

import uk.ac.manchester.tornado.api.annotations.Parallel;

import java.util.ArrayList;
import java.util.Random;

public class Object3d {
    public PointComp[] points;
    public int[][] faceList;
    public double[][][] uvPoints;

    public Face[] faces;
    public Point3D boundingSphereC;
    public double boundingSphereR;
    public boolean hasEdges;
    public Texture[] textures;

    public Object3d(Random random, PointComp[] _points, int[][] _faceList, double[][][] _uvPoints, boolean _hasEdges, Texture[] _textures, boolean initialise) {
        points = _points;
        faceList = _faceList;
        uvPoints = _uvPoints;
        hasEdges = _hasEdges;
        textures = _textures;

        if (initialise) {
            initialise(random);
        }
    }


    public void invalidate(drawData drawData) {
        for (Face face :
                faces) {
            face.invalidate();
        }
        for (Texture texture:
        textures){
            texture.invalidate(drawData);
        }
    }

    public void draw(drawData drawData, ArrayList<Integer> frustumInfo) {
        for (@Parallel Face face :
                faces) {
            // check whether faces are pointing towards or away from the camera
            Vector3D camVec = new Vector3D(0, 0, 0);
            camVec.createFrom2Points(drawData.playerPos, face.points[0].point);
            if (drawData.backfaceCullingDisabled || face.normal.angleTo(camVec) >= Math.PI / 2 - 0.01) {
                // check for frustum culling of faces
                // works the same as for collections.
                // see explanation within ObjectCollection
                ArrayList<Integer> newFrustumInfo = new ArrayList<Integer>();
                boolean draw = true;
                for (int planeId:
                        frustumInfo) {
                    double dist = drawData.frustumPlanes[planeId].getDistance(face.boundingSphereC);
                    if (dist < -face.boundingSphereR + face.boundingSphereR * drawData.frustumCullingOverridePercent){
                        draw = false;
                        break;
                    } else if(dist < face.boundingSphereR) {
                        newFrustumInfo.add(planeId);
                    }
                }
                if(draw){face.draw(drawData, newFrustumInfo);}
            }
        }
    }

    public void initialise(Random random) {
        // init faces
        faces = new Face[faceList.length];
        for (int face = 0; face < faceList.length; face += 1) {
            faces[face] = new Face();
            faces[face].points = new PointComp[faceList[face].length];
            for (int point = 0; point < faceList[face].length; point += 1) {
                faces[face].points[point] = points[faceList[face][point]];
            }
            faces[face].hasEdges = hasEdges;
            faces[face].texture = textures[face];
            faces[face].UVPoints = uvPoints[face];
            faces[face].initialise(random);
        }
        // init bounding sphere
        double distance = 0;
        double newDis;
        Point3D pointA = points[0].point;
        Point3D pointB = points[0].point;
        Vector3D distanceVec = new Vector3D();
        for (int i = 1; i < points.length; i += 1) {
            distanceVec.createFrom2Points(points[0].point, points[i].point);
            newDis = distanceVec.getLength();
            if (newDis >= distance) {
                pointA = points[i].point;
                distance = newDis;
            }
        }
        for (PointComp point : points) {
            distanceVec.createFrom2Points(points[0].point, points[0].point);
            newDis = distanceVec.getLength();
            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;
        for (PointComp point :
                points) {
            distanceVec.createFrom2Points(boundingSphereC, point.point);
            distance = distanceVec.getLength();
            boundingSphereR = Math.max(boundingSphereR, distance);
        }
    }
}