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;
}
}