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.GLAutoDrawable;
import javax.media.opengl.fixedfunc.GLLightingFunc; 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.motor.Motor;
import net.sf.openrocket.rocketcomponent.BodyTube; import net.sf.openrocket.rocketcomponent.BodyTube;
import net.sf.openrocket.rocketcomponent.ExternalComponent; 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.rocketcomponent.Transition;
import net.sf.openrocket.startup.Application; import net.sf.openrocket.startup.Application;
import net.sf.openrocket.util.Color; import net.sf.openrocket.util.Color;
import net.sf.openrocket.util.Coordinate;
public class FigureRenderer extends RocketRenderer { public class FigureRenderer extends RocketRenderer {
private final float[] color = new float[4]; 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_DIFFUSE, color, 0);
gl.glMaterialfv(GL.GL_BACK, GLLightingFunc.GL_AMBIENT, color, 0); gl.glMaterialfv(GL.GL_BACK, GLLightingFunc.GL_AMBIENT, color, 0);
cr.renderGeometry(gl, c); cr.getGeometry(c, Surface.OUTSIDE).render(gl);
} }
@Override @Override
@ -161,10 +161,10 @@ public class FigureRenderer extends RocketRenderer {
@Override @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 }; 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_DIFFUSE, outside, 0);
gl.glMaterialfv(GL.GL_FRONT, GLLightingFunc.GL_AMBIENT, 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.Decal;
import net.sf.openrocket.appearance.defaults.DefaultAppearance; import net.sf.openrocket.appearance.defaults.DefaultAppearance;
import net.sf.openrocket.document.OpenRocketDocument; 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.motor.Motor;
import net.sf.openrocket.rocketcomponent.RocketComponent; import net.sf.openrocket.rocketcomponent.RocketComponent;
import net.sf.openrocket.util.Color; 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.Texture;
import com.jogamp.opengl.util.texture.TextureData; import com.jogamp.opengl.util.texture.TextureData;
@ -95,26 +96,18 @@ public class RealisticRenderer extends RocketRenderer {
} }
@Override @Override
protected void renderMotor(final GL2 gl, final Coordinate c, final Motor motor) { protected void renderMotor(final GL2 gl, final Motor motor) {
render(gl, new Runnable() { render(gl, cr.getGeometry(motor, Surface.OUTSIDE), DefaultAppearance.getDefaultAppearance(motor), true, 1);
@Override
public void run() {
cr.renderMotor(gl, c, motor);
}
}, DefaultAppearance.getDefaultAppearance(motor), 1);
} }
@Override @Override
public void renderComponent(final GL2 gl, final RocketComponent c, final float alpha) { public void renderComponent(final GL2 gl, final RocketComponent c, final float alpha) {
render(gl, new Runnable() { render(gl, cr.getGeometry(c, Surface.OUTSIDE), getAppearance(c), true, alpha);
@Override render(gl, cr.getGeometry(c, Surface.EDGES), getAppearance(c), false, alpha);
public void run() { render(gl, cr.getGeometry(c, Surface.INSIDE), DefaultAppearance.getDefaultAppearance(c), true, alpha);
cr.renderGeometry(gl, c);
}
}, getAppearance(c), 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 Decal t = a.getTexture();
final Texture tex = getTexture(t); 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.glMaterialfv(GL.GL_BACK, GLLightingFunc.GL_SPECULAR, colorBlack, 0);
gl.glMateriali(GL.GL_BACK, GLLightingFunc.GL_SHININESS, 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_MIN_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_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); gl.glTexParameterf(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MAX_ANISOTROPY_EXT, anisotrophy);
} }
g.run(); g.render(gl);
if (t.getEdgeMode() == Decal.EdgeMode.STICKER) { if (t.getEdgeMode() == Decal.EdgeMode.STICKER) {
gl.glDepthFunc(GL.GL_LESS); 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.GLAutoDrawable;
import javax.media.opengl.fixedfunc.GLLightingFunc; 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.logging.LogHelper;
import net.sf.openrocket.motor.Motor; import net.sf.openrocket.motor.Motor;
import net.sf.openrocket.rocketcomponent.Configuration; import net.sf.openrocket.rocketcomponent.Configuration;
@ -73,10 +75,10 @@ public abstract class RocketRenderer {
if (isDrawnTransparent(c)) { if (isDrawnTransparent(c)) {
gl.glEnable(GL.GL_CULL_FACE); gl.glEnable(GL.GL_CULL_FACE);
gl.glCullFace(GL.GL_FRONT); gl.glCullFace(GL.GL_FRONT);
cr.renderGeometry(gl, c); cr.getGeometry(c, Surface.OUTSIDE).render(gl);
gl.glDisable(GL.GL_CULL_FACE); gl.glDisable(GL.GL_CULL_FACE);
} else { } 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 // Draw as lines, set Z to nearest
gl.glPolygonMode(GL.GL_FRONT_AND_BACK, GL2GL3.GL_LINE); gl.glPolygonMode(GL.GL_FRONT_AND_BACK, GL2GL3.GL_LINE);
gl.glDepthRange(0, 0); gl.glDepthRange(0, 0);
cr.renderGeometry(gl, c); cr.getGeometry(c, Surface.OUTSIDE).render(gl);
// Draw polygons, always passing depth test, // Draw polygons, always passing depth test,
// setting Z to farthest // setting Z to farthest
gl.glPolygonMode(GL.GL_FRONT_AND_BACK, GL2GL3.GL_FILL); gl.glPolygonMode(GL.GL_FRONT_AND_BACK, GL2GL3.GL_FILL);
gl.glDepthRange(1, 1); gl.glDepthRange(1, 1);
gl.glDepthFunc(GL.GL_ALWAYS); gl.glDepthFunc(GL.GL_ALWAYS);
cr.renderGeometry(gl, c); cr.getGeometry(c, Surface.OUTSIDE).render(gl);
gl.glDepthFunc(GL.GL_LESS); gl.glDepthFunc(GL.GL_LESS);
gl.glDepthRange(0, 1); gl.glDepthRange(0, 1);
} }
@ -183,14 +185,17 @@ public abstract class RocketRenderer {
.getLength() + mount.getMotorOverhang() - length)); .getLength() + mount.getMotorOverhang() - length));
for (int i = 0; i < position.length; i++) { 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) { protected void renderMotor(GL2 gl, Motor motor) {
cr.renderMotor(gl, c, motor); cr.getGeometry(motor, Surface.OUTSIDE).render(gl);
} }
} }

View File

@ -1,7 +1,4 @@
package net.sf.openrocket.gui.figure3d; package net.sf.openrocket.gui.figure3d.geometry;
import java.util.HashMap;
import java.util.Map;
import javax.media.opengl.GL; import javax.media.opengl.GL;
import javax.media.opengl.GL2; 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.GLUtessellatorCallback;
import javax.media.opengl.glu.GLUtessellatorCallbackAdapter; 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.logging.LogHelper;
import net.sf.openrocket.motor.Motor; import net.sf.openrocket.motor.Motor;
import net.sf.openrocket.rocketcomponent.BodyTube; import net.sf.openrocket.rocketcomponent.BodyTube;
@ -31,6 +29,7 @@ import net.sf.openrocket.util.Coordinate;
* @author Bill Kuker <bkuker@billkuker.com> * @author Bill Kuker <bkuker@billkuker.com>
*/ */
public class ComponentRenderer { public class ComponentRenderer {
@SuppressWarnings("unused")
private static final LogHelper log = Application.getLogger(); private static final LogHelper log = Application.getLogger();
private int LOD = 80; private int LOD = 80;
@ -50,31 +49,37 @@ public class ComponentRenderer {
glu.gluQuadricTexture(q, true); glu.gluQuadricTexture(q, true);
} }
private Map<RocketComponent, Integer> lists = new HashMap<RocketComponent, Integer>();
public void updateFigure(GLAutoDrawable drawable) { 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) if (glu == null)
throw new IllegalStateException(this + " Not Initialized"); throw new IllegalStateException(this + " Not Initialized");
glu.gluQuadricNormals(q, GLU.GLU_SMOOTH); glu.gluQuadricNormals(q, GLU.GLU_SMOOTH);
if (lists.containsKey(c)) {
gl.glCallList(lists.get(c));
} else {
int list = gl.glGenLists(1);
gl.glNewList(list, GL2.GL_COMPILE_AND_EXECUTE);
Coordinate[] oo = c.toAbsolute(new Coordinate(0, 0, 0)); Coordinate[] oo = c.toAbsolute(new Coordinate(0, 0, 0));
for (Coordinate o : oo) { for (Coordinate o : oo) {
@ -83,7 +88,7 @@ public class ComponentRenderer {
gl.glTranslated(o.x, o.y, o.z); gl.glTranslated(o.x, o.y, o.z);
if (c instanceof BodyTube) { if (c instanceof BodyTube) {
renderTube(gl, (BodyTube) c); renderTube(gl, (BodyTube) c, which);
} else if (c instanceof LaunchLug) { } else if (c instanceof LaunchLug) {
renderLug(gl, (LaunchLug) c); renderLug(gl, (LaunchLug) c);
} else if (c instanceof RingComponent) { } else if (c instanceof RingComponent) {
@ -100,9 +105,6 @@ public class ComponentRenderer {
gl.glPopMatrix(); gl.glPopMatrix();
} }
gl.glEndList();
lists.put(c, list);
}
} }
private void renderOther(GL2 gl, RocketComponent c) { 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); gl.glRotated(90, 0, 1.0, 0);
if (which == Surface.OUTSIDE)
glu.gluCylinder(q, t.getOuterRadius(), t.getOuterRadius(), glu.gluCylinder(q, t.getOuterRadius(), t.getOuterRadius(),
t.getLength(), LOD, 1); 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) { 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 l = motor.getLength();
double r = motor.getDiameter() / 2; double r = motor.getDiameter() / 2;
gl.glPushMatrix(); gl.glPushMatrix();
gl.glTranslated(c.x, c.y, c.z);
gl.glRotated(90, 0, 1.0, 0); gl.glRotated(90, 0, 1.0, 0);
gl.glMatrixMode(GL.GL_TEXTURE); 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,20 +112,20 @@
* in the design, construction, operation or maintenance of any nuclear * in the design, construction, operation or maintenance of any nuclear
* facility. * facility.
*/ */
package net.sf.openrocket.gui.figure3d; package net.sf.openrocket.gui.figure3d.geometry;
import javax.media.opengl.GL; import javax.media.opengl.GL;
import javax.media.opengl.GL2; import javax.media.opengl.GL2;
import net.sf.openrocket.rocketcomponent.MassObject; import net.sf.openrocket.rocketcomponent.MassObject;
public final class MassObjectRenderer { final class MassObjectRenderer {
private static final boolean textureFlag = true; private static final boolean textureFlag = true;
private MassObjectRenderer() { 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) { final int slices, final int stacks) {
double da, r, dz; double da, r, dz;

View File

@ -112,20 +112,20 @@
* in the design, construction, operation or maintenance of any nuclear * in the design, construction, operation or maintenance of any nuclear
* facility. * facility.
*/ */
package net.sf.openrocket.gui.figure3d; package net.sf.openrocket.gui.figure3d.geometry;
import javax.media.opengl.GL; import javax.media.opengl.GL;
import javax.media.opengl.GL2; import javax.media.opengl.GL2;
import net.sf.openrocket.rocketcomponent.Transition; import net.sf.openrocket.rocketcomponent.Transition;
public final class TransitionRenderer { final class TransitionRenderer {
private static final boolean textureFlag = true; private static final boolean textureFlag = true;
private TransitionRenderer() { 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) { final int slices, final int stacks) {
double da, r, dz; double da, r, dz;