/*******************************************************************************
* Copyright (c) 2013 Philip Collin.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the GNU Public License v3.0
* which accompanies this distribution, and is available at
* http://www.gnu.org/licenses/gpl.html
*
* Contributors:
* Philip Collin - initial API and implementation
******************************************************************************/
package com.lyeeedar.Roguelike3D.Graphics.Renderers;
import java.util.Comparator;
import com.badlogic.gdx.graphics.Camera;
import com.badlogic.gdx.graphics.Mesh;
import com.badlogic.gdx.math.Matrix4;
import com.badlogic.gdx.math.Vector3;
import com.badlogic.gdx.utils.Array;
import com.badlogic.gdx.utils.Pool;
import com.lyeeedar.Roguelike3D.Graphics.Lights.LightManager;
import com.lyeeedar.Roguelike3D.Graphics.Materials.Material;
import com.lyeeedar.Roguelike3D.Graphics.Models.StillModel;
import com.lyeeedar.Roguelike3D.Graphics.Models.StillModelAttributes;
import com.lyeeedar.Roguelike3D.Graphics.Models.StillModelInstance;
import com.lyeeedar.Roguelike3D.Graphics.Models.RiggedModels.RiggedSubMesh;
import com.lyeeedar.Roguelike3D.Graphics.Renderers.Renderer.DrawableManager.Drawable;
public abstract class Renderer {
public Camera cam;
public boolean drawing;
protected DrawableManager drawableManager = new DrawableManager();
public Renderer()
{
updateResolution();
}
public void begin () {
drawing = true;
}
public void draw (StillModel model, StillModelAttributes attributes) {
if (cam != null) if (!cam.frustum.sphereInFrustum(attributes.getSortCenter(), attributes.getBoundingSphereRadius()*2)) return;
drawableManager.add(model, attributes);
}
public void draw (RiggedSubMesh mesh, Matrix4 model_matrix, Material mat, float radius) {
if (cam != null) if (!cam.frustum.sphereInFrustum(Vector3.tmp3.set(0, 0, 0).mul(model_matrix), radius*2)) return;
drawableManager.add(mesh, model_matrix, mat);
}
public void end (LightManager lightManager) {
flush(lightManager);
drawing = false;
drawableManager.clear();
}
protected abstract void flush(LightManager lightManager);
public void dispose()
{
disposeSuper();
}
protected abstract void disposeSuper();
public abstract void createShader(LightManager lights);
public abstract void updateResolution();
class DrawableManager {
Pool<Drawable> drawablePool = new Pool<Drawable>() {
@Override
protected Drawable newObject () {
return new Drawable();
}
};
Array<Drawable> drawables = new Array<Drawable>();
public void add (StillModel model, StillModelAttributes attributes) {
Drawable drawable = drawablePool.obtain();
drawable.set(model, attributes);
drawables.add(drawable);
}
public void add(RiggedSubMesh mesh, Matrix4 model_matrix, Material mat) {
Drawable drawable = drawablePool.obtain();
drawable.set(mesh, model_matrix, mat);
drawables.add(drawable);
}
public void clear () {
clear(drawables);
}
private void clear (Array<Drawable> drawables) {
while (drawables.size > 0) {
final Drawable drawable = drawables.pop();
drawablePool.free(drawable);
}
}
class Drawable implements Comparable<Drawable> {
private static final int PRIORITY_DISCRETE_STEPS = 256;
Mesh mesh;
final Matrix4 model_matrix = new Matrix4();
final Vector3 sortCenter = new Vector3();
Material material;
int distance;
int materialHash;
int primitiveType;
public void set (RiggedSubMesh mesh, Matrix4 model_matrix, Material mat)
{
setCommon(mesh.getMesh(), mesh.primitiveType, model_matrix, mat);
}
public void set (StillModel model, StillModelAttributes attributes) {
model_matrix.set(attributes.getTransform()).scale(attributes.scale, attributes.scale, attributes.scale).mul(attributes.rotation);
setCommon(model.subMeshes[0].mesh, model.subMeshes[0].primitiveType, model_matrix, attributes.material);
}
private void setCommon (Mesh mesh, int primitiveType, Matrix4 model_matrix, Material mat) {
this.mesh = mesh;
this.model_matrix.set(model_matrix);
this.material = mat;
this.primitiveType = primitiveType;
sortCenter.set(0, 0, 0).mul(model_matrix);
distance = (int)(PRIORITY_DISCRETE_STEPS * sortCenter.dst(cam.position));
if (material != null) {
} else {
System.err.println("Error! Attributes has no Material!");
}
materialHash = material.hashCode();
}
@Override
public int compareTo (Drawable other) {
return other.distance - this.distance;
}
}
}
public static final Comparator<Drawable> sorter = new Comparator<Drawable>() {
public int compare (Drawable a, Drawable b) {
if (a.materialHash != b.materialHash) return b.materialHash - a.materialHash;
return b.distance - a.distance;
}
};
}