Refactor rendering a little, separating inside, outside and edge surfaces

push geometry into a sub-package

Remove display lists

Force all calls to render geometry through a callback object

Switch to a design where I get individual Geometry callbacks. Easier to
deal with
This commit is contained in:
bkuker 2013-03-02 17:39:07 -05:00
parent 4ff2eb11ec
commit 8b633bcd95
7 changed files with 158 additions and 127 deletions

View File

@ -8,6 +8,7 @@ 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;
@ -17,7 +18,6 @@ import net.sf.openrocket.rocketcomponent.SymmetricComponent;
import net.sf.openrocket.rocketcomponent.Transition;
import net.sf.openrocket.startup.Application;
import net.sf.openrocket.util.Color;
import net.sf.openrocket.util.Coordinate;
public class FigureRenderer extends RocketRenderer {
private final float[] color = new float[4];
@ -120,7 +120,7 @@ public class FigureRenderer extends RocketRenderer {
gl.glMaterialfv(GL.GL_BACK, GLLightingFunc.GL_DIFFUSE, color, 0);
gl.glMaterialfv(GL.GL_BACK, GLLightingFunc.GL_AMBIENT, color, 0);
cr.renderGeometry(gl, c);
cr.getGeometry(c, Surface.OUTSIDE).render(gl);
}
@Override
@ -161,10 +161,10 @@ public class FigureRenderer extends RocketRenderer {
@Override
protected void renderMotor(GL2 gl, Coordinate c, Motor motor) {
protected void renderMotor(GL2 gl, Motor motor) {
final float outside[] = { 0.2f, 0.2f, 0.2f, 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, c, motor);
super.renderMotor(gl, motor);
}
}

View File

@ -16,10 +16,11 @@ import net.sf.openrocket.appearance.Appearance;
import net.sf.openrocket.appearance.Decal;
import net.sf.openrocket.appearance.defaults.DefaultAppearance;
import net.sf.openrocket.document.OpenRocketDocument;
import net.sf.openrocket.gui.figure3d.geometry.Geometry;
import net.sf.openrocket.gui.figure3d.geometry.Geometry.Surface;
import net.sf.openrocket.motor.Motor;
import net.sf.openrocket.rocketcomponent.RocketComponent;
import net.sf.openrocket.util.Color;
import net.sf.openrocket.util.Coordinate;
import com.jogamp.opengl.util.texture.Texture;
import com.jogamp.opengl.util.texture.TextureData;
@ -95,26 +96,18 @@ public class RealisticRenderer extends RocketRenderer {
}
@Override
protected void renderMotor(final GL2 gl, final Coordinate c, final Motor motor) {
render(gl, new Runnable() {
@Override
public void run() {
cr.renderMotor(gl, c, motor);
}
}, DefaultAppearance.getDefaultAppearance(motor), 1);
protected void renderMotor(final GL2 gl, final Motor motor) {
render(gl, cr.getGeometry(motor, Surface.OUTSIDE), DefaultAppearance.getDefaultAppearance(motor), true, 1);
}
@Override
public void renderComponent(final GL2 gl, final RocketComponent c, final float alpha) {
render(gl, new Runnable() {
@Override
public void run() {
cr.renderGeometry(gl, c);
}
}, getAppearance(c), alpha);
render(gl, cr.getGeometry(c, Surface.OUTSIDE), getAppearance(c), true, alpha);
render(gl, cr.getGeometry(c, Surface.EDGES), getAppearance(c), false, alpha);
render(gl, cr.getGeometry(c, Surface.INSIDE), DefaultAppearance.getDefaultAppearance(c), true, alpha);
}
private void render(GL2 gl, Runnable g, Appearance a, float alpha) {
private void render(GL2 gl, Geometry g, Appearance a, boolean decals, float alpha) {
final Decal t = a.getTexture();
final Texture tex = getTexture(t);
@ -137,9 +130,9 @@ public class RealisticRenderer extends RocketRenderer {
gl.glMaterialfv(GL.GL_BACK, GLLightingFunc.GL_SPECULAR, colorBlack, 0);
gl.glMateriali(GL.GL_BACK, GLLightingFunc.GL_SHININESS, 0);
g.run();
g.render(gl);
if (t != null && tex != null) {
if (decals && t != null && tex != null) {
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_MAG_FILTER, GL.GL_LINEAR);
@ -176,7 +169,7 @@ public class RealisticRenderer extends RocketRenderer {
gl.glTexParameterf(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MAX_ANISOTROPY_EXT, anisotrophy);
}
g.run();
g.render(gl);
if (t.getEdgeMode() == Decal.EdgeMode.STICKER) {
gl.glDepthFunc(GL.GL_LESS);

View File

@ -12,6 +12,8 @@ import javax.media.opengl.GL2GL3;
import javax.media.opengl.GLAutoDrawable;
import javax.media.opengl.fixedfunc.GLLightingFunc;
import net.sf.openrocket.gui.figure3d.geometry.ComponentRenderer;
import net.sf.openrocket.gui.figure3d.geometry.Geometry.Surface;
import net.sf.openrocket.logging.LogHelper;
import net.sf.openrocket.motor.Motor;
import net.sf.openrocket.rocketcomponent.Configuration;
@ -73,10 +75,10 @@ public abstract class RocketRenderer {
if (isDrawnTransparent(c)) {
gl.glEnable(GL.GL_CULL_FACE);
gl.glCullFace(GL.GL_FRONT);
cr.renderGeometry(gl, c);
cr.getGeometry(c, Surface.OUTSIDE).render(gl);
gl.glDisable(GL.GL_CULL_FACE);
} else {
cr.renderGeometry(gl, c);
cr.getGeometry(c, Surface.OUTSIDE).render(gl);
}
}
@ -115,14 +117,14 @@ public abstract class RocketRenderer {
// Draw as lines, set Z to nearest
gl.glPolygonMode(GL.GL_FRONT_AND_BACK, GL2GL3.GL_LINE);
gl.glDepthRange(0, 0);
cr.renderGeometry(gl, c);
cr.getGeometry(c, Surface.OUTSIDE).render(gl);
// Draw polygons, always passing depth test,
// setting Z to farthest
gl.glPolygonMode(GL.GL_FRONT_AND_BACK, GL2GL3.GL_FILL);
gl.glDepthRange(1, 1);
gl.glDepthFunc(GL.GL_ALWAYS);
cr.renderGeometry(gl, c);
cr.getGeometry(c, Surface.OUTSIDE).render(gl);
gl.glDepthFunc(GL.GL_LESS);
gl.glDepthRange(0, 1);
}
@ -183,14 +185,17 @@ public abstract class RocketRenderer {
.getLength() + mount.getMotorOverhang() - length));
for (int i = 0; i < position.length; i++) {
renderMotor(gl, position[i], motor);
gl.glPushMatrix();
gl.glTranslated(position[i].x, position[i].y, position[i].z);
renderMotor(gl, motor);
gl.glPopMatrix();
}
}
}
protected void renderMotor(GL2 gl, Coordinate c, Motor motor) {
cr.renderMotor(gl, c, motor);
protected void renderMotor(GL2 gl, Motor motor) {
cr.getGeometry(motor, Surface.OUTSIDE).render(gl);
}
}

View File

@ -1,7 +1,4 @@
package net.sf.openrocket.gui.figure3d;
import java.util.HashMap;
import java.util.Map;
package net.sf.openrocket.gui.figure3d.geometry;
import javax.media.opengl.GL;
import javax.media.opengl.GL2;
@ -14,6 +11,7 @@ import javax.media.opengl.glu.GLUtessellator;
import javax.media.opengl.glu.GLUtessellatorCallback;
import javax.media.opengl.glu.GLUtessellatorCallbackAdapter;
import net.sf.openrocket.gui.figure3d.geometry.Geometry.Surface;
import net.sf.openrocket.logging.LogHelper;
import net.sf.openrocket.motor.Motor;
import net.sf.openrocket.rocketcomponent.BodyTube;
@ -31,6 +29,7 @@ import net.sf.openrocket.util.Coordinate;
* @author Bill Kuker <bkuker@billkuker.com>
*/
public class ComponentRenderer {
@SuppressWarnings("unused")
private static final LogHelper log = Application.getLogger();
private int LOD = 80;
@ -50,59 +49,62 @@ public class ComponentRenderer {
glu.gluQuadricTexture(q, true);
}
private Map<RocketComponent, Integer> lists = new HashMap<RocketComponent, Integer>();
public void updateFigure(GLAutoDrawable drawable) {
log.debug("Clearing Display Lists");
GL2 gl = drawable.getGL().getGL2();
for (int i : lists.values()) {
gl.glDeleteLists(i, 1);
}
lists.clear();
}
public void renderGeometry(GL2 gl, RocketComponent c) {
public Geometry getGeometry(final RocketComponent c, final Surface which) {
return new Geometry() {
@Override
public void render(GL2 gl) {
renderGeometry(gl, c, which);
}
};
}
public Geometry getGeometry(final Motor motor, Surface which) {
return new Geometry() {
@Override
public void render(GL2 gl) {
renderMotor(gl, motor);
}
};
}
private void renderGeometry(GL2 gl, RocketComponent c, Surface which) {
if (glu == null)
throw new IllegalStateException(this + " Not Initialized");
glu.gluQuadricNormals(q, GLU.GLU_SMOOTH);
Coordinate[] oo = c.toAbsolute(new Coordinate(0, 0, 0));
if (lists.containsKey(c)) {
gl.glCallList(lists.get(c));
} else {
int list = gl.glGenLists(1);
gl.glNewList(list, GL2.GL_COMPILE_AND_EXECUTE);
for (Coordinate o : oo) {
gl.glPushMatrix();
Coordinate[] oo = c.toAbsolute(new Coordinate(0, 0, 0));
gl.glTranslated(o.x, o.y, o.z);
for (Coordinate o : oo) {
gl.glPushMatrix();
gl.glTranslated(o.x, o.y, o.z);
if (c instanceof BodyTube) {
renderTube(gl, (BodyTube) c);
} else if (c instanceof LaunchLug) {
renderLug(gl, (LaunchLug) c);
} else if (c instanceof RingComponent) {
renderRing(gl, (RingComponent) c);
} else if (c instanceof Transition) {
renderTransition(gl, (Transition) c);
} else if (c instanceof MassObject) {
renderMassObject(gl, (MassObject) c);
} else if (c instanceof FinSet) {
renderFinSet(gl, (FinSet) c);
} else {
renderOther(gl, c);
}
gl.glPopMatrix();
if (c instanceof BodyTube) {
renderTube(gl, (BodyTube) c, which);
} else if (c instanceof LaunchLug) {
renderLug(gl, (LaunchLug) c);
} else if (c instanceof RingComponent) {
renderRing(gl, (RingComponent) c);
} else if (c instanceof Transition) {
renderTransition(gl, (Transition) c);
} else if (c instanceof MassObject) {
renderMassObject(gl, (MassObject) c);
} else if (c instanceof FinSet) {
renderFinSet(gl, (FinSet) c);
} else {
renderOther(gl, c);
}
gl.glEndList();
lists.put(c, list);
gl.glPopMatrix();
}
}
private void renderOther(GL2 gl, RocketComponent c) {
@ -164,10 +166,32 @@ public class ComponentRenderer {
}
private void renderTube(GL2 gl, BodyTube t) {
private void renderTube(GL2 gl, BodyTube t, Surface which) {
//TODO REfactor without the extra transforms
//outside
gl.glRotated(90, 0, 1.0, 0);
glu.gluCylinder(q, t.getOuterRadius(), t.getOuterRadius(),
t.getLength(), LOD, 1);
if (which == Surface.OUTSIDE)
glu.gluCylinder(q, t.getOuterRadius(), t.getOuterRadius(),
t.getLength(), LOD, 1);
//edges
gl.glRotated(180, 0, 1.0, 0);
if (which == Surface.EDGES)
glu.gluDisk(q, t.getInnerRadius(), t.getOuterRadius(), LOD, 2);
gl.glRotated(180, 0, 1.0, 0);
gl.glTranslated(0, 0, t.getLength());
if (which == Surface.EDGES)
glu.gluDisk(q, t.getInnerRadius(), t.getOuterRadius(), LOD, 2);
//inside
gl.glTranslated(0, 0, -t.getLength());
if (which == Surface.INSIDE)
glu.gluCylinder(q, t.getInnerRadius(), t.getInnerRadius(),
t.getLength(), LOD, 1);
}
private void renderRing(GL2 gl, RingComponent r) {
@ -315,14 +339,12 @@ public class ComponentRenderer {
}
public void renderMotor(final GL2 gl, final Coordinate c, Motor motor) {
private void renderMotor(final GL2 gl, Motor motor) {
double l = motor.getLength();
double r = motor.getDiameter() / 2;
gl.glPushMatrix();
gl.glTranslated(c.x, c.y, c.z);
gl.glRotated(90, 0, 1.0, 0);
gl.glMatrixMode(GL.GL_TEXTURE);

View File

@ -0,0 +1,11 @@
package net.sf.openrocket.gui.figure3d.geometry;
import javax.media.opengl.GL2;
public interface Geometry {
public static enum Surface {
OUTSIDE, INSIDE, EDGES;
}
public void render(GL2 gl);
}

View File

@ -112,31 +112,31 @@
* in the design, construction, operation or maintenance of any nuclear
* facility.
*/
package net.sf.openrocket.gui.figure3d;
package net.sf.openrocket.gui.figure3d.geometry;
import javax.media.opengl.GL;
import javax.media.opengl.GL2;
import net.sf.openrocket.rocketcomponent.MassObject;
public final class MassObjectRenderer {
final class MassObjectRenderer {
private static final boolean textureFlag = true;
private MassObjectRenderer() {
}
public static final void drawMassObject(final GL2 gl, final MassObject o,
static final void drawMassObject(final GL2 gl, final MassObject o,
final int slices, final int stacks) {
double da, r, dz;
double x, y, z, nz, nsign;
int i, j;
nsign = 1.0f;
da = 2.0f * PI / slices;
dz = o.getLength() / stacks;
double ds = 1.0f / slices;
double dt = 1.0f / stacks;
double t = 0.0f;
@ -146,13 +146,13 @@ public final class MassObjectRenderer {
double rNext = getRadius(o, z + dz);
if (j == stacks - 1)
rNext = 0;
if (j == stacks - 1)
rNext = 0;
// Z component of normal vectors
nz = -(rNext - r) / dz;
double s = 0.0f;
glBegin(gl, GL2.GL_QUAD_STRIP);
for (i = 0; i <= slices; i++) {
@ -186,7 +186,7 @@ public final class MassObjectRenderer {
z += dz;
} // for stacks
}
private static final double getRadius(MassObject o, double z) {
double arc = Math.min(o.getLength(), 2 * o.getRadius()) * 0.35f;
double r = o.getRadius();
@ -202,33 +202,33 @@ public final class MassObjectRenderer {
}
return o.getRadius();
}
// ----------------------------------------------------------------------
// Internals only below this point
//
private static final double PI = Math.PI;
private static final void glBegin(GL gl, int mode) {
gl.getGL2().glBegin(mode);
}
private static final void glEnd(GL gl) {
gl.getGL2().glEnd();
}
private static final void glVertex3d(GL gl, double x, double y, double z) {
gl.getGL2().glVertex3d(x, y, z);
}
private static final void glNormal3d(GL gl, double x, double y, double z) {
gl.getGL2().glNormal3d(x, y, z);
}
private static final void glTexCoord2d(GL gl, double x, double y) {
gl.getGL2().glTexCoord2d(x, y);
}
/**
* Call glNormal3f after scaling normal to unit length.
*
@ -238,7 +238,7 @@ public final class MassObjectRenderer {
*/
private static final void normal3d(GL gl, double x, double y, double z) {
double mag;
mag = Math.sqrt(x * x + y * y + z * z);
if (mag > 0.00001F) {
x /= mag;
@ -247,16 +247,16 @@ public final class MassObjectRenderer {
}
glNormal3d(gl, x, y, z);
}
private static final void TXTR_COORD(GL gl, double x, double y) {
if (textureFlag)
glTexCoord2d(gl, x, y);
}
private static final double sin(double r) {
return Math.sin(r);
}
private static final double cos(double r) {
return Math.cos(r);
}

View File

@ -112,31 +112,31 @@
* in the design, construction, operation or maintenance of any nuclear
* facility.
*/
package net.sf.openrocket.gui.figure3d;
package net.sf.openrocket.gui.figure3d.geometry;
import javax.media.opengl.GL;
import javax.media.opengl.GL2;
import net.sf.openrocket.rocketcomponent.Transition;
public final class TransitionRenderer {
final class TransitionRenderer {
private static final boolean textureFlag = true;
private TransitionRenderer() {
}
public static final void drawTransition(final GL2 gl, final Transition tr,
static final void drawTransition(final GL2 gl, final Transition tr,
final int slices, final int stacks) {
double da, r, dz;
double x, y, z, nz, nsign;
int i, j;
nsign = 1.0f;
da = 2.0f * PI / slices;
dz = (double) tr.getLength() / stacks;
double ds = 1.0f / slices;
double dt = 1.0f / stacks;
double t = 0.0f;
@ -145,13 +145,13 @@ public final class TransitionRenderer {
for (j = 0; j < stacks; j++) {
r = (double) tr.getRadius(z);
double rNext = (double) tr.getRadius(z + dz);
if (j == stacks - 1)
rNext = (double) tr.getRadius(tr.getLength());
// Z component of normal vectors
nz = -(rNext - r) / dz;
double s = 0.0f;
glBegin(gl, GL2.GL_QUAD_STRIP);
for (i = 0; i <= slices; i++) {
@ -184,35 +184,35 @@ public final class TransitionRenderer {
t += dt;
z += dz;
} // for stacks
}
// ----------------------------------------------------------------------
// Internals only below this point
//
private static final double PI = (double) Math.PI;
private static final void glBegin(GL gl, int mode) {
gl.getGL2().glBegin(mode);
}
private static final void glEnd(GL gl) {
gl.getGL2().glEnd();
}
private static final void glVertex3d(GL gl, double x, double y, double z) {
gl.getGL2().glVertex3d(x, y, z);
}
private static final void glNormal3d(GL gl, double x, double y, double z) {
gl.getGL2().glNormal3d(x, y, z);
}
private static final void glTexCoord2d(GL gl, double x, double y) {
gl.getGL2().glTexCoord2d(x, y);
}
/**
* Call glNormal3f after scaling normal to unit length.
*
@ -222,7 +222,7 @@ public final class TransitionRenderer {
*/
private static final void normal3d(GL gl, double x, double y, double z) {
double mag;
mag = (double) Math.sqrt(x * x + y * y + z * z);
if (mag > 0.00001F) {
x /= mag;
@ -231,16 +231,16 @@ public final class TransitionRenderer {
}
glNormal3d(gl, x, y, z);
}
private static final void TXTR_COORD(GL gl, double x, double y) {
if (textureFlag)
glTexCoord2d(gl, x, y);
}
private static final double sin(double r) {
return (double) Math.sin(r);
}
private static final double cos(double r) {
return (double) Math.cos(r);
}