package net.sf.openrocket.gui.figure3d;
import java.util.HashMap;
import javax.media.opengl.GL;
import javax.media.opengl.GL2;
import javax.media.opengl.GL2ES1;
import javax.media.opengl.GLAutoDrawable;
import javax.media.opengl.fixedfunc.GLLightingFunc;
import net.sf.openrocket.gui.figure3d.geometry.Geometry.Surface;
import net.sf.openrocket.motor.Motor;
import net.sf.openrocket.rocketcomponent.BodyTube;
import net.sf.openrocket.rocketcomponent.ExternalComponent;
import net.sf.openrocket.rocketcomponent.NoseCone;
import net.sf.openrocket.rocketcomponent.RocketComponent;
import net.sf.openrocket.rocketcomponent.SymmetricComponent;
import net.sf.openrocket.rocketcomponent.Transition;
import net.sf.openrocket.startup.Application;
import net.sf.openrocket.util.Color;
public class FigureRenderer extends RocketRenderer {
private final float[] color = new float[4];
public FigureRenderer() {
}
@Override
public void init(GLAutoDrawable drawable) {
super.init(drawable);
GL2 gl = drawable.getGL().getGL2();
gl.glLightModelfv(GL2ES1.GL_LIGHT_MODEL_AMBIENT,
new float[] { 0, 0, 0 }, 0);
float amb = 0.3f;
float dif = 1.0f - amb;
float spc = 1.0f;
gl.glLightfv(GLLightingFunc.GL_LIGHT1, GLLightingFunc.GL_AMBIENT,
new float[] { amb, amb, amb, 1 }, 0);
gl.glLightfv(GLLightingFunc.GL_LIGHT1, GLLightingFunc.GL_DIFFUSE,
new float[] { dif, dif, dif, 1 }, 0);
gl.glLightfv(GLLightingFunc.GL_LIGHT1, GLLightingFunc.GL_SPECULAR,
new float[] { spc, spc, spc, 1 }, 0);
gl.glEnable(GLLightingFunc.GL_LIGHT1);
gl.glEnable(GLLightingFunc.GL_LIGHTING);
gl.glShadeModel(GLLightingFunc.GL_SMOOTH);
gl.glEnable(GLLightingFunc.GL_NORMALIZE);
}
@Override
public boolean isDrawn(RocketComponent c) {
return true;
}
@Override
public boolean isDrawnTransparent(RocketComponent c) {
if (c instanceof BodyTube)
return true;
if (c instanceof NoseCone)
return false;
if (c instanceof SymmetricComponent) {
if (((SymmetricComponent) c).isFilled())
return false;
}
if (c instanceof Transition) {
Transition t = (Transition) c;
return !t.isAftShoulderCapped() && !t.isForeShoulderCapped();
}
return false;
}
private static final HashMap<Class<?>, Color> defaultColorCache = new HashMap<Class<?>, Color>();
@Override
public void renderComponent(GL2 gl, RocketComponent c, float alpha) {
gl.glLightModeli(GL2ES1.GL_LIGHT_MODEL_TWO_SIDE, 1);
Color figureColor = c.getColor();
if (figureColor == null) {
if (defaultColorCache.containsKey(c.getClass())) {
figureColor = defaultColorCache.get(c.getClass());
} else {
figureColor = Application.getPreferences().getDefaultColor(c.getClass());
defaultColorCache.put(c.getClass(), figureColor);
}
}
//Inside
convertColor(figureColor, color);
color[0] = color[0] * 0.7f;
color[1] = color[1] * 0.7f;
color[2] = color[2] * 0.7f;
color[3] = 1.0f;
gl.glMaterialfv(GL.GL_FRONT, GLLightingFunc.GL_DIFFUSE, color, 0);
gl.glMaterialfv(GL.GL_FRONT, GLLightingFunc.GL_AMBIENT, color, 0);
cr.getGeometry(c, Surface.INSIDE).render(gl);
//OUtside
// Set up the front A&D color
convertColor(figureColor, color);
color[3] = alpha;
gl.glMaterialfv(GL.GL_FRONT, GLLightingFunc.GL_DIFFUSE, color, 0);
gl.glMaterialfv(GL.GL_FRONT, GLLightingFunc.GL_AMBIENT, color, 0);
// Set up the Specular color & Shine
convertColor(figureColor, color);
float d = 0.9f;
float m = (float) getShine(c) / 128.0f;
color[0] = Math.max(color[0], d) * m;
color[1] = Math.max(color[1], d) * m;
color[2] = Math.max(color[2], d) * m;
gl.glMaterialfv(GL.GL_FRONT, GLLightingFunc.GL_SPECULAR, color, 0);
gl.glMateriali(GL.GL_FRONT, GLLightingFunc.GL_SHININESS, getShine(c));
cr.getGeometry(c, Surface.OUTSIDE).render(gl);
cr.getGeometry(c, Surface.EDGES).render(gl);
color[0] = color[1] = color[2] = 0;
gl.glMaterialfv(GL.GL_FRONT, GLLightingFunc.GL_SPECULAR, color, 0);
}
@Override
public void flushTextureCache(GLAutoDrawable drawable) {
}
private static int getShine(RocketComponent c) {
if (c instanceof ExternalComponent) {
switch (((ExternalComponent) c).getFinish()) {
case ROUGH:
return 10;
case UNFINISHED:
return 30;
case NORMAL:
return 40;
case SMOOTH:
return 80;
case POLISHED:
return 128;
default:
return 100;
}
}
return 20;
}
protected static void convertColor(Color color, float[] out) {
if (color == null) {
out[0] = 1;
out[1] = 1;
out[2] = 0;
} else {
out[0] = Math.max(0.2f, (float) color.getRed() / 255f) * 2;
out[1] = Math.max(0.2f, (float) color.getGreen() / 255f) * 2;
out[2] = Math.max(0.2f, (float) color.getBlue() / 255f) * 2;
}
}
@Override
protected void renderMotor(GL2 gl, Motor motor) {
final float outside[] = { 0.3f, 0.3f, 0.3f, 1.0f };
gl.glMaterialfv(GL.GL_FRONT, GLLightingFunc.GL_DIFFUSE, outside, 0);
gl.glMaterialfv(GL.GL_FRONT, GLLightingFunc.GL_AMBIENT, outside, 0);
super.renderMotor(gl, motor);
}
}