/*
* Copyright 2013 MovingBlocks
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.terasology.rendering;
import org.lwjgl.opengl.GL11;
import org.terasology.logic.players.LocalPlayer;
import org.terasology.math.AABB;
import org.terasology.math.geom.Vector3f;
import org.terasology.math.geom.Vector4f;
import org.terasology.registry.CoreRegistry;
import static org.lwjgl.opengl.GL11.GL_BLEND;
import static org.lwjgl.opengl.GL11.GL_LINE_LOOP;
import static org.lwjgl.opengl.GL11.GL_QUADS;
import static org.lwjgl.opengl.GL11.glBegin;
import static org.lwjgl.opengl.GL11.glCallList;
import static org.lwjgl.opengl.GL11.glColor4f;
import static org.lwjgl.opengl.GL11.glDeleteLists;
import static org.lwjgl.opengl.GL11.glDisable;
import static org.lwjgl.opengl.GL11.glEnable;
import static org.lwjgl.opengl.GL11.glEnd;
import static org.lwjgl.opengl.GL11.glEndList;
import static org.lwjgl.opengl.GL11.glGenLists;
import static org.lwjgl.opengl.GL11.glLineWidth;
import static org.lwjgl.opengl.GL11.glNewList;
import static org.lwjgl.opengl.GL11.glPopMatrix;
import static org.lwjgl.opengl.GL11.glPushMatrix;
import static org.lwjgl.opengl.GL11.glScalef;
import static org.lwjgl.opengl.GL11.glTranslated;
import static org.lwjgl.opengl.GL11.glVertex3f;
/**
* Renderer for an AABB.
*
*/
public class AABBRenderer implements BlockOverlayRenderer {
private int displayListWire = -1;
private int displayListSolid = -1;
private Vector4f solidColor = new Vector4f(1f, 1f, 1f, 1f);
private AABB aabb;
public AABBRenderer(AABB aabb) {
this.aabb = aabb;
}
@Override
public void setAABB(AABB from) {
if (from != null && !from.equals(this.aabb)) {
this.aabb = from;
dispose();
}
}
public void dispose() {
if (displayListWire != -1) {
glDeleteLists(displayListWire, 1);
displayListWire = -1;
}
if (displayListSolid != -1) {
glDeleteLists(displayListSolid, 1);
displayListSolid = -1;
}
}
public void setSolidColor(Vector4f color) {
solidColor = color;
}
/**
* Renders this AABB.
* <br><br>
*
* @param lineThickness The thickness of the line
*/
@Override
public void render(float lineThickness) {
CoreRegistry.get(ShaderManager.class).enableDefault();
glPushMatrix();
Vector3f cameraPosition = CoreRegistry.get(LocalPlayer.class).getViewPosition();
glTranslated(aabb.getCenter().x - cameraPosition.x, -cameraPosition.y, aabb.getCenter().z - cameraPosition.z);
renderLocally(lineThickness);
glPopMatrix();
}
public void renderSolid() {
CoreRegistry.get(ShaderManager.class).enableDefault();
glPushMatrix();
Vector3f cameraPosition = CoreRegistry.get(LocalPlayer.class).getViewPosition();
glTranslated(aabb.getCenter().x - cameraPosition.x, -cameraPosition.y, aabb.getCenter().z - cameraPosition.z);
renderSolidLocally();
glPopMatrix();
}
public void renderLocally(float lineThickness) {
CoreRegistry.get(ShaderManager.class).enableDefault();
if (displayListWire == -1) {
generateDisplayListWire();
}
glPushMatrix();
glTranslated(0f, aabb.getCenter().y, 0f);
glLineWidth(lineThickness);
glCallList(displayListWire);
glPopMatrix();
}
public void renderSolidLocally() {
CoreRegistry.get(ShaderManager.class).enableDefault();
if (displayListSolid == -1) {
generateDisplayListSolid();
}
glEnable(GL_BLEND);
glPushMatrix();
glTranslated(0f, aabb.getCenter().y, 0f);
glScalef(1.5f, 1.5f, 1.5f);
glCallList(displayListSolid);
glPopMatrix();
glDisable(GL_BLEND);
}
private void generateDisplayListSolid() {
displayListSolid = glGenLists(1);
glNewList(displayListSolid, GL11.GL_COMPILE);
glBegin(GL_QUADS);
glColor4f(solidColor.x, solidColor.y, solidColor.z, solidColor.w);
Vector3f dimensions = aabb.getExtents();
GL11.glVertex3f(-dimensions.x, dimensions.y, dimensions.z);
GL11.glVertex3f(dimensions.x, dimensions.y, dimensions.z);
GL11.glVertex3f(dimensions.x, dimensions.y, -dimensions.z);
GL11.glVertex3f(-dimensions.x, dimensions.y, -dimensions.z);
GL11.glVertex3f(-dimensions.x, -dimensions.y, -dimensions.z);
GL11.glVertex3f(-dimensions.x, -dimensions.y, dimensions.z);
GL11.glVertex3f(-dimensions.x, dimensions.y, dimensions.z);
GL11.glVertex3f(-dimensions.x, dimensions.y, -dimensions.z);
GL11.glVertex3f(-dimensions.x, -dimensions.y, dimensions.z);
GL11.glVertex3f(dimensions.x, -dimensions.y, dimensions.z);
GL11.glVertex3f(dimensions.x, dimensions.y, dimensions.z);
GL11.glVertex3f(-dimensions.x, dimensions.y, dimensions.z);
GL11.glVertex3f(dimensions.x, dimensions.y, -dimensions.z);
GL11.glVertex3f(dimensions.x, dimensions.y, dimensions.z);
GL11.glVertex3f(dimensions.x, -dimensions.y, dimensions.z);
GL11.glVertex3f(dimensions.x, -dimensions.y, -dimensions.z);
GL11.glVertex3f(-dimensions.x, dimensions.y, -dimensions.z);
GL11.glVertex3f(dimensions.x, dimensions.y, -dimensions.z);
GL11.glVertex3f(dimensions.x, -dimensions.y, -dimensions.z);
GL11.glVertex3f(-dimensions.x, -dimensions.y, -dimensions.z);
GL11.glVertex3f(-dimensions.x, -dimensions.y, -dimensions.z);
GL11.glVertex3f(dimensions.x, -dimensions.y, -dimensions.z);
GL11.glVertex3f(dimensions.x, -dimensions.y, dimensions.z);
GL11.glVertex3f(-dimensions.x, -dimensions.y, dimensions.z);
glEnd();
glEndList();
}
private void generateDisplayListWire() {
float offset = 0.001f;
displayListWire = glGenLists(1);
glNewList(displayListWire, GL11.GL_COMPILE);
glColor4f(0.0f, 0.0f, 0.0f, 1.0f);
Vector3f dimensions = aabb.getExtents();
// FRONT
glBegin(GL_LINE_LOOP);
glVertex3f(-dimensions.x - offset, -dimensions.y - offset, -dimensions.z - offset);
glVertex3f(+dimensions.x + offset, -dimensions.y - offset, -dimensions.z - offset);
glVertex3f(+dimensions.x + offset, +dimensions.y + offset, -dimensions.z - offset);
glVertex3f(-dimensions.x - offset, +dimensions.y + offset, -dimensions.z - offset);
glEnd();
// BACK
glBegin(GL_LINE_LOOP);
glVertex3f(-dimensions.x - offset, -dimensions.y - offset, +dimensions.z + offset);
glVertex3f(+dimensions.x + offset, -dimensions.y - offset, +dimensions.z + offset);
glVertex3f(+dimensions.x + offset, +dimensions.y + offset, +dimensions.z + offset);
glVertex3f(-dimensions.x - offset, +dimensions.y + offset, +dimensions.z + offset);
glEnd();
// TOP
glBegin(GL_LINE_LOOP);
glVertex3f(-dimensions.x - offset, -dimensions.y - offset, -dimensions.z - offset);
glVertex3f(+dimensions.x + offset, -dimensions.y - offset, -dimensions.z - offset);
glVertex3f(+dimensions.x + offset, -dimensions.y - offset, +dimensions.z + offset);
glVertex3f(-dimensions.x - offset, -dimensions.y - offset, +dimensions.z + offset);
glEnd();
// BOTTOM
glBegin(GL_LINE_LOOP);
glVertex3f(-dimensions.x - offset, +dimensions.y + offset, -dimensions.z - offset);
glVertex3f(+dimensions.x + offset, +dimensions.y + offset, -dimensions.z - offset);
glVertex3f(+dimensions.x + offset, +dimensions.y + offset, +dimensions.z + offset);
glVertex3f(-dimensions.x - offset, +dimensions.y + offset, +dimensions.z + offset);
glEnd();
// LEFT
glBegin(GL_LINE_LOOP);
glVertex3f(-dimensions.x - offset, -dimensions.y - offset, -dimensions.z - offset);
glVertex3f(-dimensions.x - offset, -dimensions.y - offset, +dimensions.z + offset);
glVertex3f(-dimensions.x - offset, +dimensions.y + offset, +dimensions.z + offset);
glVertex3f(-dimensions.x - offset, +dimensions.y + offset, -dimensions.z - offset);
glEnd();
// RIGHT
glBegin(GL_LINE_LOOP);
glVertex3f(+dimensions.x + offset, -dimensions.y - offset, -dimensions.z - offset);
glVertex3f(+dimensions.x + offset, -dimensions.y - offset, +dimensions.z + offset);
glVertex3f(+dimensions.x + offset, +dimensions.y + offset, +dimensions.z + offset);
glVertex3f(+dimensions.x + offset, +dimensions.y + offset, -dimensions.z - offset);
glEnd();
glEndList();
}
public AABB getAABB() {
return aabb;
}
}