Mesh Culling Model Instance

mail@pastecode.io avatar
unknown
java
a year ago
5.5 kB
15
Indexable
Never
package com.mygdx.game;

import com.badlogic.gdx.graphics.Camera;
import com.badlogic.gdx.graphics.g3d.Model;
import com.badlogic.gdx.graphics.g3d.ModelInstance;
import com.badlogic.gdx.graphics.g3d.Renderable;
import com.badlogic.gdx.graphics.g3d.model.MeshPart;
import com.badlogic.gdx.graphics.g3d.model.Node;
import com.badlogic.gdx.graphics.g3d.model.NodePart;
import com.badlogic.gdx.math.Matrix4;
import com.badlogic.gdx.math.Vector3;
import com.badlogic.gdx.math.collision.BoundingBox;
import com.badlogic.gdx.utils.Array;
import com.badlogic.gdx.utils.GdxRuntimeException;
import com.badlogic.gdx.utils.Pool;

import java.util.HashMap;
import java.util.Map;

/**
 * @author JamesTKhan
 * @version August 31, 2023
 */
public class MeshCullingModelInstance extends ModelInstance {
    private static final BoundingBox bounds = new BoundingBox();
    private final Map<MeshPart, BoundingBox> boundingBoxes = new HashMap<>();
    private Camera camera;

    public MeshCullingModelInstance(Model model) {
        super(model);
    }

    public MeshCullingModelInstance(Model model, String nodeId, boolean mergeTransform) {
        super(model, nodeId, mergeTransform);
    }

    public MeshCullingModelInstance(Model model, Matrix4 transform, String nodeId, boolean mergeTransform) {
        super(model, transform, nodeId, mergeTransform);
    }

    public MeshCullingModelInstance(Model model, String nodeId, boolean parentTransform, boolean mergeTransform) {
        super(model, nodeId, parentTransform, mergeTransform);
    }

    public MeshCullingModelInstance(Model model, Matrix4 transform, String nodeId, boolean parentTransform, boolean mergeTransform) {
        super(model, transform, nodeId, parentTransform, mergeTransform);
    }

    public MeshCullingModelInstance(Model model, String nodeId, boolean recursive, boolean parentTransform, boolean mergeTransform) {
        super(model, nodeId, recursive, parentTransform, mergeTransform);
    }

    public MeshCullingModelInstance(Model model, Matrix4 transform, String nodeId, boolean recursive, boolean parentTransform, boolean mergeTransform) {
        super(model, transform, nodeId, recursive, parentTransform, mergeTransform);
    }

    public MeshCullingModelInstance(Model model, Matrix4 transform, String nodeId, boolean recursive, boolean parentTransform, boolean mergeTransform, boolean shareKeyframes) {
        super(model, transform, nodeId, recursive, parentTransform, mergeTransform, shareKeyframes);
    }

    public MeshCullingModelInstance(Model model, String... rootNodeIds) {
        super(model, rootNodeIds);
    }

    public MeshCullingModelInstance(Model model, Matrix4 transform, String... rootNodeIds) {
        super(model, transform, rootNodeIds);
    }

    public MeshCullingModelInstance(Model model, Array<String> rootNodeIds) {
        super(model, rootNodeIds);
    }

    public MeshCullingModelInstance(Model model, Matrix4 transform, Array<String> rootNodeIds) {
        super(model, transform, rootNodeIds);
    }

    public MeshCullingModelInstance(Model model, Matrix4 transform, Array<String> rootNodeIds, boolean shareKeyframes) {
        super(model, transform, rootNodeIds, shareKeyframes);
    }

    public MeshCullingModelInstance(Model model, Vector3 position) {
        super(model, position);
    }

    public MeshCullingModelInstance(Model model, float x, float y, float z) {
        super(model, x, y, z);
    }

    public MeshCullingModelInstance(Model model, Matrix4 transform) {
        super(model, transform);
    }

    public MeshCullingModelInstance(ModelInstance copyFrom) {
        super(copyFrom);
    }

    public MeshCullingModelInstance(ModelInstance copyFrom, Matrix4 transform) {
        super(copyFrom, transform);
    }

    public MeshCullingModelInstance(ModelInstance copyFrom, Matrix4 transform, boolean shareKeyframes) {
        super(copyFrom, transform, shareKeyframes);
    }

    @Override
    protected void getRenderables (Node node, Array<Renderable> renderables, Pool<Renderable> pool) {
        if (camera == null) {
            throw new GdxRuntimeException("Camera cannot be null on MeshCullingModelInstance.");
        }

        if (node.parts.size > 0) {
            for (NodePart nodePart : node.parts) {
                if (nodePart.enabled) {
                    MeshPart meshPart = nodePart.meshPart;

                    BoundingBox boundingBox;

                    // Get bounding box for mesh part
                    if (!boundingBoxes.containsKey(meshPart)) {
                        boundingBox = new BoundingBox();
                        meshPart.mesh.calculateBoundingBox(boundingBox, meshPart.offset, meshPart.size);
                        boundingBoxes.put(meshPart, boundingBox);
                    } else {
                        boundingBox = boundingBoxes.get(meshPart);
                    }

                    // Mesh culling
                    bounds.set(boundingBox).mul(transform).mul(node.globalTransform);  // Transform to world space
                    if (!camera.frustum.boundsInFrustum(bounds)) {
                        continue;
                    }

                    renderables.add(getRenderable(pool.obtain(), node, nodePart));
                }
            }
        }

        for (Node child : node.getChildren()) {
            getRenderables(child, renderables, pool);
        }

    }

    public void setCamera(Camera camera) {
        this.camera = camera;
    }
}