package org.terasology.componentSystem.rendering;
import org.terasology.componentSystem.RenderSystem;
import org.terasology.components.AABBCollisionComponent;
import org.terasology.components.rendering.MeshComponent;
import org.terasology.components.world.LocationComponent;
import org.terasology.entitySystem.EntityManager;
import org.terasology.entitySystem.EntityRef;
import org.terasology.entitySystem.RegisterComponentSystem;
import org.terasology.game.CoreRegistry;
import org.terasology.logic.LocalPlayer;
import org.terasology.logic.manager.ShaderManager;
import org.terasology.math.TeraMath;
import org.terasology.model.structures.AABB;
import org.terasology.rendering.primitives.Mesh;
import org.terasology.rendering.primitives.Tessellator;
import org.terasology.rendering.primitives.TessellatorHelper;
import org.terasology.rendering.shader.ShaderProgram;
import org.terasology.rendering.world.WorldRenderer;
import javax.vecmath.AxisAngle4f;
import javax.vecmath.Vector3d;
import javax.vecmath.Vector3f;
import javax.vecmath.Vector4f;
import static org.lwjgl.opengl.GL11.*;
/**
* TODO: This should be made generic (no explicit shader or mesh) and ported directly into WorldRenderer?
*
* @author Immortius <immortius@gmail.com>
*/
@RegisterComponentSystem(headedOnly = true)
public class MeshRenderer implements RenderSystem {
private EntityManager manager;
private Mesh mesh;
private WorldRenderer worldRenderer;
@Override
public void initialise() {
manager = CoreRegistry.get(EntityManager.class);
worldRenderer = CoreRegistry.get(WorldRenderer.class);
Tessellator tessellator = new Tessellator();
TessellatorHelper.addBlockMesh(tessellator, new Vector4f(1.0f, 1.0f, 1.0f, 1.0f), 0.8f, 0.8f, 0.6f, 0f, 0f, 0f);
TessellatorHelper.addBlockMesh(tessellator, new Vector4f(1.0f, 1.0f, 1.0f, 0.6f), 1.0f, 1.0f, 0.8f, 0f, 0f, 0f);
mesh = tessellator.generateMesh();
}
@Override
public void shutdown() {
}
@Override
public void renderTransparent() {
Vector3d cameraPosition = worldRenderer.getActiveCamera().getPosition();
for (EntityRef entity : manager.iteratorEntities(MeshComponent.class, AABBCollisionComponent.class, LocationComponent.class)) {
// TODO: Probably don't need this collision component, there should be some sort of AABB built into the mesh
MeshComponent meshComp = entity.getComponent(MeshComponent.class);
if (meshComp.renderType == MeshComponent.RenderType.Normal) continue;
AABBCollisionComponent collision = entity.getComponent(AABBCollisionComponent.class);
LocationComponent location = entity.getComponent(LocationComponent.class);
Vector3f worldPos = location.getWorldPosition();
Vector3d extents = new Vector3d(collision.getExtents());
float worldScale = location.getWorldScale();
extents.scale(worldScale);
AABB aabb = new AABB(new Vector3d(worldPos), new Vector3d(collision.getExtents()));
if (worldRenderer.isAABBVisible(aabb)) {
glPushMatrix();
glTranslated(worldPos.x - cameraPosition.x, worldPos.y - cameraPosition.y, worldPos.z - cameraPosition.z);
AxisAngle4f rot = new AxisAngle4f();
rot.set(location.getWorldRotation());
glRotatef(TeraMath.RAD_TO_DEG * rot.angle, rot.x, rot.y, rot.z);
glScalef(worldScale, worldScale, worldScale);
ShaderProgram shader = ShaderManager.getInstance().getShaderProgram("gelatinousCube");
shader.enable();
shader.setFloat4("colorOffset", meshComp.color.x, meshComp.color.y, meshComp.color.z, meshComp.color.w);
shader.setFloat("light", worldRenderer.getRenderingLightValueAt(worldPos));
mesh.render();
glPopMatrix();
}
}
}
@Override
public void renderOpaque() {
boolean carryingTorch = CoreRegistry.get(LocalPlayer.class).isCarryingTorch();
Vector3d cameraPosition = worldRenderer.getActiveCamera().getPosition();
for (EntityRef entity : manager.iteratorEntities(MeshComponent.class, AABBCollisionComponent.class, LocationComponent.class)) {
// TODO: Probably don't need this collision component, there should be some sort of AABB built into the mesh
MeshComponent meshComp = entity.getComponent(MeshComponent.class);
if (meshComp.renderType != MeshComponent.RenderType.Normal || meshComp.mesh == null) continue;
AABBCollisionComponent collision = entity.getComponent(AABBCollisionComponent.class);
LocationComponent location = entity.getComponent(LocationComponent.class);
Vector3f worldPos = location.getWorldPosition();
Vector3d extents = new Vector3d(collision.getExtents());
float worldScale = location.getWorldScale();
extents.scale(worldScale);
AABB aabb = new AABB(new Vector3d(worldPos), new Vector3d(collision.getExtents()));
if (worldRenderer.isAABBVisible(aabb)) {
glPushMatrix();
glTranslated(worldPos.x - cameraPosition.x, worldPos.y - cameraPosition.y, worldPos.z - cameraPosition.z);
AxisAngle4f rot = new AxisAngle4f();
rot.set(location.getWorldRotation());
glRotatef(TeraMath.RAD_TO_DEG * rot.angle, rot.x, rot.y, rot.z);
glScalef(worldScale, worldScale, worldScale);
meshComp.material.enable();
meshComp.material.setFloat("light", worldRenderer.getRenderingLightValueAt(worldPos));
meshComp.material.setInt("carryingTorch", carryingTorch ? 1 : 0);
meshComp.material.bindTextures();
meshComp.mesh.render();
glPopMatrix();
}
}
}
@Override
public void renderOverlay() {
}
@Override
public void renderFirstPerson() {
}
}