package net.sf.openrocket.gui.figure3d.geometry;
import javax.media.opengl.GL;
import javax.media.opengl.GL2;
import javax.media.opengl.fixedfunc.GLLightingFunc;
import javax.media.opengl.fixedfunc.GLMatrixFunc;
import javax.media.opengl.glu.GLU;
import javax.media.opengl.glu.GLUtessellator;
import javax.media.opengl.glu.GLUtessellatorCallback;
import javax.media.opengl.glu.GLUtessellatorCallbackAdapter;
import net.sf.openrocket.rocketcomponent.EllipticalFinSet;
import net.sf.openrocket.rocketcomponent.FinSet;
import net.sf.openrocket.util.Coordinate;
public class FinRenderer {
private GLUtessellator tobj = GLU.gluNewTess();
public void renderFinSet(final GL2 gl, FinSet fs) {
Coordinate finPoints[] = fs.getFinPointsWithTab();
double minX = Double.MAX_VALUE;
double minY = Double.MAX_VALUE;
double maxX = Double.MIN_VALUE;
double maxY = Double.MIN_VALUE;
for (int i = 0; i < finPoints.length; i++) {
Coordinate c = finPoints[i];
minX = Math.min(c.x, minX);
minY = Math.min(c.y, minY);
maxX = Math.max(c.x, maxX);
maxY = Math.max(c.y, maxY);
}
gl.glMatrixMode(GL.GL_TEXTURE);
gl.glPushMatrix();
gl.glScaled(1 / (maxX - minX), 1 / (maxY - minY), 0);
gl.glTranslated(-minX, -minY - fs.getBodyRadius(), 0);
gl.glMatrixMode(GLMatrixFunc.GL_MODELVIEW);
gl.glRotated(fs.getBaseRotation() * (180.0 / Math.PI), 1, 0, 0);
for (int fin = 0; fin < fs.getFinCount(); fin++) {
gl.glPushMatrix();
gl.glTranslated(fs.getLength() / 2, 0, 0);
gl.glRotated(fs.getCantAngle() * (180.0 / Math.PI), 0, 1, 0);
gl.glTranslated(-fs.getLength() / 2, 0, 0);
GLUtessellatorCallback cb = new GLUtessellatorCallbackAdapter() {
@Override
public void vertex(Object vertexData) {
double d[] = (double[]) vertexData;
gl.glTexCoord2d(d[0], d[1]);
gl.glVertex3dv(d, 0);
}
@Override
public void begin(int type) {
gl.glBegin(type);
}
@Override
public void end() {
gl.glEnd();
}
};
GLU.gluTessCallback(tobj, GLU.GLU_TESS_VERTEX, cb);
GLU.gluTessCallback(tobj, GLU.GLU_TESS_BEGIN, cb);
GLU.gluTessCallback(tobj, GLU.GLU_TESS_END, cb);
GLU.gluTessBeginPolygon(tobj, null);
GLU.gluTessBeginContour(tobj);
gl.glNormal3f(0, 0, 1);
for (int i = finPoints.length - 1; i >= 0; i--) {
Coordinate c = finPoints[i];
double[] p = new double[] { c.x, c.y + fs.getBodyRadius(),
c.z + fs.getThickness() / 2.0 };
GLU.gluTessVertex(tobj, p, 0, p);
}
GLU.gluTessEndContour(tobj);
GLU.gluTessEndPolygon(tobj);
GLU.gluTessBeginPolygon(tobj, null);
GLU.gluTessBeginContour(tobj);
gl.glNormal3f(0, 0, -1);
for (int i = 0; i < finPoints.length; i++) {
Coordinate c = finPoints[i];
double[] p = new double[] { c.x, c.y + fs.getBodyRadius(),
c.z - fs.getThickness() / 2.0 };
GLU.gluTessVertex(tobj, p, 0, p);
}
GLU.gluTessEndContour(tobj);
GLU.gluTessEndPolygon(tobj);
// Strip around the edge
if (!(fs instanceof EllipticalFinSet))
gl.glShadeModel(GLLightingFunc.GL_FLAT);
gl.glBegin(GL.GL_TRIANGLE_STRIP);
for (int i = 0; i <= finPoints.length; i++) {
Coordinate c = finPoints[i % finPoints.length];
// if ( i > 1 ){
Coordinate c2 = finPoints[(i - 1 + finPoints.length)
% finPoints.length];
gl.glNormal3d(c2.y - c.y, c.x - c2.x, 0);
// }
gl.glTexCoord2d(c.x, c.y + fs.getBodyRadius());
gl.glVertex3d(c.x, c.y + fs.getBodyRadius(),
c.z - fs.getThickness() / 2.0);
gl.glVertex3d(c.x, c.y + fs.getBodyRadius(),
c.z + fs.getThickness() / 2.0);
}
gl.glEnd();
if (!(fs instanceof EllipticalFinSet))
gl.glShadeModel(GLLightingFunc.GL_SMOOTH);
gl.glPopMatrix();
gl.glRotated(360.0 / fs.getFinCount(), 1, 0, 0);
}
gl.glMatrixMode(GL.GL_TEXTURE);
gl.glPopMatrix();
gl.glMatrixMode(GLMatrixFunc.GL_MODELVIEW);
}
}