/******************************************************************************
* Copyright (c) 2008 Marco Della Vedova, Matteo Foppiano
* and Pimods contributors
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.pixelinstrument.net/license/cpl-v10.html
******************************************************************************/
package net.sf.robocode.bv3d;
import javax.media.opengl.GL;
import javax.media.opengl.glu.GLU;
import javax.media.opengl.GLAutoDrawable;
import javax.media.opengl.GLEventListener;
import java.awt.image.BufferedImage;
import java.nio.ByteBuffer;
import java.nio.IntBuffer;
import net.sf.robocode.bv3d.model.LoadModel;
import net.sf.robocode.bv3d.model.Model;
import net.sf.robocode.bv3d.model.ModelFace;
import net.sf.robocode.bv3d.model.ModelObject;
import net.sf.robocode.bv3d.model.ModelMaterial;
import net.sf.robocode.bv3d.math.Vertex3f;
import net.sf.robocode.bv3d.Scene;
/**
*
* @author Marco Della Vedova - pixelinstrument.net
* @author Matteo Foppiano - pixelinstrument.net
*/
public class GraphicListener implements GLEventListener {
private Scene scene;
private float width, height;
public void display(GLAutoDrawable drawable) {
GL gl = drawable.getGL();
GLU glu = new GLU();
gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);
gl.glEnable(GL.GL_NORMALIZE);
// gl.glEnable( GL.GL_RESCALE_NORMAL );
gl.glMatrixMode(GL.GL_PROJECTION);
gl.glLoadIdentity();
glu.gluPerspective(50f, 1, 0.1f, 25.0);
gl.glMatrixMode(GL.GL_MODELVIEW);
gl.glLoadIdentity();
gl.glScalef(600f / this.width, 600f / this.height, 1);
if (this.scene != null) {
this.scene.draw(gl);
}
}
public void displayChanged(GLAutoDrawable drawable, boolean modeChanged, boolean deviceChanged) {}
public void init(GLAutoDrawable drawable) {
GL gl = drawable.getGL();
gl.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
gl.glClearDepth(1.0);
gl.glEnable(GL.GL_DEPTH_TEST);
gl.glDepthFunc(GL.GL_LEQUAL);
gl.glFrontFace(GL.GL_CW);
gl.glShadeModel(GL.GL_SMOOTH);
gl.glEnable(GL.GL_CULL_FACE);
gl.glCullFace(GL.GL_BACK);
gl.glEnable(GL.GL_TEXTURE_2D);
gl.glEnable(GL.GL_BLEND);
gl.glBlendFunc(GL.GL_SRC_ALPHA, GL.GL_ONE_MINUS_SRC_ALPHA);
gl.glEnable(GL.GL_LIGHTING);
float ambient[] = { 0.6f, 0.6f, 0.6f, 1 };
gl.glLightModelfv(GL.GL_LIGHT_MODEL_AMBIENT, ambient, 0);
gl.glEnable(GL.GL_COLOR_MATERIAL);
gl.glColorMaterial(GL.GL_FRONT, GL.GL_AMBIENT_AND_DIFFUSE);
float specColor[] = { 0.2f, 0.2f, 0.2f, 1};
gl.glMaterialfv(GL.GL_FRONT, GL.GL_SPECULAR, specColor, 0);
gl.glMaterialf(GL.GL_FRONT, GL.GL_SHININESS, 64);
}
public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) {
this.width = width;
this.height = height;
}
public void setScene(Scene scene) {
this.scene = scene;
}
public Scene getScene() {
return(this.scene);
}
public float getWidth() {
return(this.width);
}
public float getHeight() {
return(this.height);
}
// TODO the time required for texture loading cause a NullPointerException on first execution
public static int[][] loadTextureFromModel(GL gl, Model model) {
int[][] texture = new int[model.getNumberOfMaterials()][];
for (int m = 0; m < texture.length; m++) {
ModelMaterial mat = model.getMaterial(m);
texture[m] = new int[mat.getNumberOfTextures()];
gl.glGenTextures(texture[m].length, texture[m], 0);
for (int t = 0; t < texture[m].length; t++) {
BufferedImage image = LoadModel.getTextureFromFile(mat.getTexture(t).getImage());
if (image != null) {
ByteBuffer buffer = ByteBuffer.allocateDirect(image.getHeight() * image.getWidth() * 4);
IntBuffer bufferInt = buffer.asIntBuffer();
for (int r = 0; r < image.getHeight(); r++) {
for (int c = 0; c < image.getWidth(); c++) {
bufferInt.put(image.getRGB(c, r));
}
}
gl.glBindTexture(GL.GL_TEXTURE_2D, texture[m][t]);
(new GLU()).gluBuild2DMipmaps(GL.GL_TEXTURE_2D, GL.GL_RGBA, image.getWidth(), image.getHeight(),
GL.GL_RGBA, GL.GL_UNSIGNED_BYTE, buffer);
// gl.glTexImage2D( GL.GL_TEXTURE_2D, 0, GL.GL_RGBA, image.getWidth(), image.getHeight(), 0, GL.GL_RGBA, GL.GL_UNSIGNED_BYTE, buffer );
// gl.glTexParameteri( GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MAG_FILTER, GL.GL_LINEAR_MIPMAP_LINEAR );
gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MAG_FILTER, GL.GL_LINEAR);
gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MIN_FILTER, GL.GL_LINEAR_MIPMAP_LINEAR);
gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_WRAP_S, GL.GL_CLAMP_TO_EDGE);
gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_WRAP_T, GL.GL_CLAMP_TO_EDGE);
gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_GENERATE_MIPMAP, GL.GL_TRUE);
}
}
}
return(texture);
}
public static int[] loadDisplayListFromModel(GL gl, Model model) {
int grpIndex[] = new int[model.getNumberOfGroups()];
for (int i = 0, c = 0; i < model.getNumberOfGroups(); i++) {
grpIndex[i] = gl.glGenLists(model.getGroup(i).getNumberOfObjects());
for (int j = 0; j < model.getGroup(i).getNumberOfObjects(); j++) {
gl.glNewList(grpIndex[i] + j, GL.GL_COMPILE);
drawObject(gl, model, model.getGroup(i).getObject(j));
gl.glEndList();
}
}
return(grpIndex);
}
private static void drawObject(GL gl, Model model, ModelObject o) {
Vertex3f vertex[] = model.getVertex();
Vertex3f normal[] = model.getNormals();
Vertex3f uv[] = model.getUV();
boolean useNormals = false;
boolean useUV = false;
if (normal.length > 0) {
useNormals = true;
}
if (uv.length > 0) {
useUV = true;
}
gl.glBegin(GL.GL_TRIANGLES);
for (int i = 0; i < o.getNumberOfFaces(); i++) {
ModelFace face = o.getFace(i);
int nv1 = face.getVertexIndex(0) - 1;
int nn1 = -1;
int nt1 = -1;
if (useNormals) {
nn1 = face.getNormalIndex(0) - 1;
}
if (useUV) {
nt1 = face.getUVIndex(0) - 1;
}
for (int j = 1; j < face.getNumberOfVertexIndex() - 1; j++) {
if (useNormals) {
gl.glNormal3f(normal[nn1].x, normal[nn1].y, normal[nn1].z);
}
if (useUV) {
gl.glTexCoord2f(uv[nt1].x, uv[nt1].y);
}
gl.glVertex3f(vertex[nv1].x, vertex[nv1].y, vertex[nv1].z);
if (useNormals) {
int nn2 = face.getNormalIndex(j) - 1;
gl.glNormal3f(normal[nn2].x, normal[nn2].y, normal[nn2].z);
}
if (useUV) {
int nt2 = face.getUVIndex(j) - 1;
gl.glTexCoord2f(uv[nt2].x, uv[nt2].y);
}
int nv2 = face.getVertexIndex(j) - 1;
gl.glVertex3f(vertex[nv2].x, vertex[nv2].y, vertex[nv2].z);
if (useNormals) {
int nn3 = face.getNormalIndex(j + 1) - 1;
gl.glNormal3f(normal[nn3].x, normal[nn3].y, normal[nn3].z);
}
if (useUV) {
int nt3 = face.getUVIndex(j + 1) - 1;
gl.glTexCoord2f(uv[nt3].x, uv[nt3].y);
}
int nv3 = face.getVertexIndex(j + 1) - 1;
gl.glVertex3f(vertex[nv3].x, vertex[nv3].y, vertex[nv3].z);
}
}
gl.glEnd();
}
}