package com.fdangelo.circleworld.universeview.tilemap;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.GL10;
import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.graphics.Mesh;
import com.badlogic.gdx.graphics.VertexAttributes.Usage;
import com.badlogic.gdx.graphics.g3d.utils.MeshBuilder;
import com.badlogic.gdx.graphics.glutils.ShaderProgram;
import com.badlogic.gdx.math.Matrix4;
import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.math.Vector3;
import com.badlogic.gdx.utils.Disposable;
import com.fdangelo.circleworld.universeengine.tilemap.Planet;
import com.fdangelo.circleworld.universeengine.tilemap.PlanetType;
import com.fdangelo.circleworld.universeengine.tilemap.TilemapCircle;
public class TilemapCircleViewBackgroundRenderer implements Disposable {
private TilemapCircle tilemapCircle;
private Vector2[] circleNormals;
private float[] circleHeights;
private Mesh mesh;
static private ShaderProgram shader;
static private int shaderWorldViewLocation;
public TilemapCircleViewBackgroundRenderer() {
if (shader == null) {
final String vertexShader = "attribute vec4 a_position;\n" + "attribute vec4 a_color;\n" + "uniform mat4 u_projTrans;\n" + "varying vec4 v_color;"
+ "void main() \n" + "{ \n" + " v_color = a_color; \n"
+ " gl_Position = u_projTrans * a_position; \n" + "}";
final String fragmentShader = "#ifdef GL_ES\n" + "precision mediump float;\n" + "#endif\n" + "varying vec4 v_color;\n"
+ "void main() \n" + "{ \n" + " gl_FragColor = v_color;\n"
+ "}";
shader = new ShaderProgram(vertexShader, fragmentShader);
if (!shader.isCompiled()) {
throw new IllegalArgumentException("Error compiling shader: " + shader.getLog());
}
shaderWorldViewLocation = shader.getUniformLocation("u_projTrans");
}
}
public final void init(final TilemapCircleView tilemapCircleView) {
// this.tilemapCircleView = tilemapCircleView;
tilemapCircle = tilemapCircleView.getTilemapCircle();
circleNormals = tilemapCircle.getCircleNormals();
circleHeights = tilemapCircle.getCircleHeights();
initMesh();
}
static private Color fromColor = new Color();
static private Color toColor = new Color();
static private MeshBuilder meshBuilder;
static private Vector3 vertexPos = new Vector3();
static private Color vertexColor = new Color();
private final void initMesh() {
fromColor.set(Color.BLUE);
toColor.set(Color.CYAN);
toColor.a = 0;
if (tilemapCircle instanceof Planet) {
final PlanetType planetType = ((Planet) tilemapCircle).getPlanetType();
fromColor.set(planetType.backColorFrom);
toColor.set(planetType.backColorTo);
}
if (mesh != null) {
mesh.dispose();
mesh = null;
}
final int totalTriangles = circleNormals.length;
final int totalIndices = totalTriangles * 3;
final int totalVertices = circleNormals.length + 1;
if (meshBuilder == null) {
meshBuilder = new MeshBuilder();
meshBuilder.begin(Usage.Position | Usage.Color);
meshBuilder.ensureCapacity(totalVertices + 1, totalIndices + 1);
} else {
meshBuilder.begin(Usage.Position | Usage.Color);
}
final float heavenHeight = circleHeights[circleHeights.length - 1]
+ (circleHeights[circleHeights.length - 1] - circleHeights[circleHeights.length - 2]) * 5.0f; // Repeat
// the
// last
// tile
// height
// 5
// times
vertexPos.set(0, 0, -10);
vertexColor.set(fromColor);
meshBuilder.vertex(vertexPos, null, vertexColor, null);
vertexColor.set(toColor);
for (int i = 0; i < circleNormals.length; i++) {
vertexPos.set(circleNormals[i].x * heavenHeight, circleNormals[i].y * heavenHeight, -10);
meshBuilder.vertex(vertexPos, null, vertexColor, null);
}
short vertexOffset = 1;
for (int i = 1; i < circleNormals.length; i++) {
meshBuilder.triangle((short) 0, (short) (vertexOffset - 1), vertexOffset);
vertexOffset++;
}
meshBuilder.triangle((short) 0, (short) (vertexOffset - 1), (short) 1);
mesh = meshBuilder.end();
}
@Override
public void dispose() {
if (mesh != null) {
mesh.dispose();
mesh = null;
}
}
public final void draw(final Matrix4 matrix) {
Gdx.gl.glDepthMask(false);
Gdx.gl.glEnable(GL20.GL_BLEND);
Gdx.gl.glBlendFunc(GL10.GL_SRC_ALPHA, GL10.GL_ONE_MINUS_SRC_ALPHA);
shader.begin();
shader.setUniformMatrix(shaderWorldViewLocation, matrix);
mesh.render(shader, GL10.GL_TRIANGLES);
shader.end();
}
}