Render motors nicely

This commit is contained in:
bkuker 2013-01-09 14:11:23 -05:00
parent 05ff94836f
commit ceb7d16651
10 changed files with 190 additions and 46 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 60 KiB

View File

@ -10,19 +10,19 @@ import net.sf.openrocket.util.MathUtil;
* @author Bill Kuker <bkuker@billkuker.com> * @author Bill Kuker <bkuker@billkuker.com>
*/ */
public class Appearance { public class Appearance {
public static final Appearance MISSING = new Appearance(new Color(0, 0, 0), 100, null); public static final Appearance MISSING = new Appearance(new Color(0, 0, 0), 1, null);
private final Color paint; private final Color paint;
private final double shine; private final double shine;
private final Decal texture; private final Decal texture;
Appearance(final Color paint, final double shine, final Decal texture) { public Appearance(final Color paint, final double shine, final Decal texture) {
this.paint = paint; this.paint = paint;
this.shine = MathUtil.clamp(shine, 0, 1); this.shine = MathUtil.clamp(shine, 0, 1);
this.texture = texture; this.texture = texture;
} }
Appearance(final Color paint, final double shine) { public Appearance(final Color paint, final double shine) {
this.paint = paint; this.paint = paint;
this.shine = MathUtil.clamp(shine, 0, 1); this.shine = MathUtil.clamp(shine, 0, 1);
this.texture = null; this.texture = null;

View File

@ -9,25 +9,27 @@ import net.sf.openrocket.util.Coordinate;
* @author Bill Kuker <bkuker@billkuker.com> * @author Bill Kuker <bkuker@billkuker.com>
*/ */
public class Decal { public class Decal {
public static enum EdgeMode { public static enum EdgeMode {
REPEAT("TextureWrap.Repeat"), MIRROR("TextureWrap.Mirror"), CLAMP("TextureWrap.Clamp"), STICKER("TextureWrap.Sticker"); REPEAT("TextureWrap.Repeat"), MIRROR("TextureWrap.Mirror"), CLAMP("TextureWrap.Clamp"), STICKER("TextureWrap.Sticker");
private final String transName; private final String transName;
EdgeMode(final String name){
EdgeMode(final String name) {
this.transName = name; this.transName = name;
} }
@Override @Override
public String toString(){ public String toString() {
return Application.getTranslator().get(transName); return Application.getTranslator().get(transName);
} }
} }
private final Coordinate offset, center, scale; private final Coordinate offset, center, scale;
private final double rotation; private final double rotation;
private final DecalImage image; private final DecalImage image;
private final EdgeMode mode; private final EdgeMode mode;
Decal(final Coordinate offset, final Coordinate center, final Coordinate scale, final double rotation, public Decal(final Coordinate offset, final Coordinate center, final Coordinate scale, final double rotation,
final DecalImage image, final EdgeMode mode) { final DecalImage image, final EdgeMode mode) {
this.offset = offset; this.offset = offset;
this.center = center; this.center = center;
@ -36,35 +38,35 @@ public class Decal {
this.image = image; this.image = image;
this.mode = mode; this.mode = mode;
} }
public Coordinate getOffset() { public Coordinate getOffset() {
return offset; return offset;
} }
public Coordinate getCenter() { public Coordinate getCenter() {
return center; return center;
} }
public Coordinate getScale() { public Coordinate getScale() {
return scale; return scale;
} }
public double getRotation() { public double getRotation() {
return rotation; return rotation;
} }
public EdgeMode getEdgeMode() { public EdgeMode getEdgeMode() {
return mode; return mode;
} }
public DecalImage getImage() { public DecalImage getImage() {
return image; return image;
} }
@Override @Override
public String toString() { public String toString() {
return "Texture [offset=" + offset + ", center=" + center + ", scale=" + scale + ", rotation=" + rotation return "Texture [offset=" + offset + ", center=" + center + ", scale=" + scale + ", rotation=" + rotation
+ ", image=" + image + "]"; + ", image=" + image + "]";
} }
} }

View File

@ -0,0 +1,42 @@
package net.sf.openrocket.appearance.defaults;
import net.sf.openrocket.appearance.Appearance;
import net.sf.openrocket.appearance.Decal;
import net.sf.openrocket.appearance.Decal.EdgeMode;
import net.sf.openrocket.motor.Motor;
import net.sf.openrocket.motor.ThrustCurveMotor;
import net.sf.openrocket.util.Color;
import net.sf.openrocket.util.Coordinate;
public class MotorAppearance extends Appearance {
private static MotorAppearance ESTES = new MotorAppearance("/datafiles/textures/motors/estes.png");
private static MotorAppearance AEROTECH = new MotorAppearance("/datafiles/textures/motors/aerotech.png");
public static Appearance getAppearance(Motor m) {
if (m instanceof ThrustCurveMotor) {
ThrustCurveMotor tcm = (ThrustCurveMotor) m;
if ("Estes".equals(tcm.getManufacturer().getSimpleName())) {
return ESTES;
}
if ("AeroTech".equals(tcm.getManufacturer().getSimpleName())) {
return AEROTECH;
}
}
return Appearance.MISSING;
}
protected MotorAppearance(final String resource) {
super(
new Color(0, 0, 0),
.1,
new Decal(
new Coordinate(0, 0),
new Coordinate(0, 0),
new Coordinate(1, 1),
0,
new ResourceDecalImage(resource), EdgeMode.REPEAT));
}
}

View File

@ -0,0 +1,32 @@
package net.sf.openrocket.appearance.defaults;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import net.sf.openrocket.appearance.DecalImage;
public class ResourceDecalImage implements DecalImage {
final String resource;
ResourceDecalImage(final String resource) {
this.resource = resource;
}
@Override
public String getName() {
return resource;
}
@Override
public InputStream getBytes() throws FileNotFoundException, IOException {
return this.getClass().getResourceAsStream(resource);
}
@Override
public void exportImage(File file, boolean watchForChanges) throws IOException {
}
}

View File

@ -15,6 +15,7 @@ import javax.media.opengl.glu.GLUtessellatorCallback;
import javax.media.opengl.glu.GLUtessellatorCallbackAdapter; import javax.media.opengl.glu.GLUtessellatorCallbackAdapter;
import net.sf.openrocket.logging.LogHelper; import net.sf.openrocket.logging.LogHelper;
import net.sf.openrocket.motor.Motor;
import net.sf.openrocket.rocketcomponent.BodyTube; import net.sf.openrocket.rocketcomponent.BodyTube;
import net.sf.openrocket.rocketcomponent.EllipticalFinSet; import net.sf.openrocket.rocketcomponent.EllipticalFinSet;
import net.sf.openrocket.rocketcomponent.FinSet; import net.sf.openrocket.rocketcomponent.FinSet;
@ -314,10 +315,9 @@ public class ComponentRenderer {
} }
public void renderMotor(final GL2 gl, final Coordinate c, double l, double r) { public void renderMotor(final GL2 gl, final Coordinate c, Motor motor) {
final float outside[] = { 0.2f, 0.2f, 0.2f, 1.0f }; double l = motor.getLength();
gl.glMaterialfv(GL.GL_FRONT, GLLightingFunc.GL_DIFFUSE, outside, 0); double r = motor.getDiameter() / 2;
gl.glMaterialfv(GL.GL_FRONT, GLLightingFunc.GL_AMBIENT, outside, 0);
gl.glPushMatrix(); gl.glPushMatrix();
@ -325,15 +325,48 @@ public class ComponentRenderer {
gl.glRotated(90, 0, 1.0, 0); gl.glRotated(90, 0, 1.0, 0);
gl.glMatrixMode(GL.GL_TEXTURE);
gl.glPushMatrix();
gl.glTranslated(0, .125, 0);
gl.glScaled(1, .75, 0);
glu.gluCylinder(q, r, r, l, LOD, 1); glu.gluCylinder(q, r, r, l, LOD, 1);
glu.gluDisk(q, r, 0, LOD, 2); gl.glPopMatrix();
gl.glMatrixMode(GLMatrixFunc.GL_MODELVIEW);
{
final double da = (2.0f * Math.PI) / LOD;
final double dt = 1.0 / LOD;
gl.glBegin(GL.GL_TRIANGLE_STRIP);
gl.glNormal3d(0, 0, 1);
for (int i = 0; i < LOD + 1; i++) {
gl.glTexCoord2d(i * dt, .125);
gl.glVertex3d(r * Math.cos(da * i), r * Math.sin(da * i), 0);
gl.glTexCoord2d(i * dt, 0);
gl.glVertex3d(0, 0, 0);
}
gl.glEnd();
}
gl.glTranslated(0, 0, l); gl.glTranslated(0, 0, l);
gl.glRotated(180, 0, 1.0, 0); gl.glRotated(180, 0, 1.0, 0);
glu.gluDisk(q, r, 0, LOD, 2); {
final double da = (2.0f * Math.PI) / LOD;
final double dt = 1.0 / LOD;
gl.glBegin(GL.GL_TRIANGLE_STRIP);
gl.glNormal3d(0, 0, 1);
for (int i = 0; i < LOD + 1; i++) {
gl.glTexCoord2d(i * dt, .875);
gl.glVertex3d(r * Math.cos(da * i), r * Math.sin(da * i), 0);
gl.glTexCoord2d(i * dt, 1);
gl.glVertex3d(0, 0, 0);
}
gl.glEnd();
}
gl.glPopMatrix(); gl.glPopMatrix();
} }
} }

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.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;
import net.sf.openrocket.rocketcomponent.NoseCone; import net.sf.openrocket.rocketcomponent.NoseCone;
@ -16,6 +17,7 @@ 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];
@ -29,9 +31,9 @@ public class FigureRenderer extends RocketRenderer {
GL2 gl = drawable.getGL().getGL2(); GL2 gl = drawable.getGL().getGL2();
gl.glLightModelfv(GL2ES1.GL_LIGHT_MODEL_AMBIENT, gl.glLightModelfv(GL2ES1.GL_LIGHT_MODEL_AMBIENT,
new float[] { 0,0,0 }, 0); new float[] { 0, 0, 0 }, 0);
float amb = 0.3f; float amb = 0.3f;
float dif = 1.0f - amb; float dif = 1.0f - amb;
float spc = 1.0f; float spc = 1.0f;
@ -41,21 +43,21 @@ public class FigureRenderer extends RocketRenderer {
new float[] { dif, dif, dif, 1 }, 0); new float[] { dif, dif, dif, 1 }, 0);
gl.glLightfv(GLLightingFunc.GL_LIGHT1, GLLightingFunc.GL_SPECULAR, gl.glLightfv(GLLightingFunc.GL_LIGHT1, GLLightingFunc.GL_SPECULAR,
new float[] { spc, spc, spc, 1 }, 0); new float[] { spc, spc, spc, 1 }, 0);
gl.glEnable(GLLightingFunc.GL_LIGHT1); gl.glEnable(GLLightingFunc.GL_LIGHT1);
gl.glEnable(GLLightingFunc.GL_LIGHTING); gl.glEnable(GLLightingFunc.GL_LIGHTING);
gl.glShadeModel(GLLightingFunc.GL_SMOOTH); gl.glShadeModel(GLLightingFunc.GL_SMOOTH);
gl.glEnable(GLLightingFunc.GL_NORMALIZE); gl.glEnable(GLLightingFunc.GL_NORMALIZE);
} }
@Override @Override
public boolean isDrawn(RocketComponent c) { public boolean isDrawn(RocketComponent c) {
return true; return true;
} }
@Override @Override
public boolean isDrawnTransparent(RocketComponent c) { public boolean isDrawnTransparent(RocketComponent c) {
if (c instanceof BodyTube) if (c instanceof BodyTube)
@ -74,7 +76,7 @@ public class FigureRenderer extends RocketRenderer {
} }
private static final HashMap<Class<?>, Color> defaultColorCache = new HashMap<Class<?>, Color>(); private static final HashMap<Class<?>, Color> defaultColorCache = new HashMap<Class<?>, Color>();
@Override @Override
public void renderComponent(GL2 gl, RocketComponent c, float alpha) { public void renderComponent(GL2 gl, RocketComponent c, float alpha) {
@ -88,13 +90,13 @@ public class FigureRenderer extends RocketRenderer {
defaultColorCache.put(c.getClass(), figureColor); defaultColorCache.put(c.getClass(), figureColor);
} }
} }
// Set up the front A&D color // Set up the front A&D color
convertColor(figureColor, color); convertColor(figureColor, color);
color[3] = alpha; color[3] = alpha;
gl.glMaterialfv(GL.GL_FRONT, GLLightingFunc.GL_DIFFUSE, color, 0); gl.glMaterialfv(GL.GL_FRONT, GLLightingFunc.GL_DIFFUSE, color, 0);
gl.glMaterialfv(GL.GL_FRONT, GLLightingFunc.GL_AMBIENT, color, 0); gl.glMaterialfv(GL.GL_FRONT, GLLightingFunc.GL_AMBIENT, color, 0);
// Set up the Specular color & Shine // Set up the Specular color & Shine
convertColor(figureColor, color); convertColor(figureColor, color);
float d = 0.9f; float d = 0.9f;
@ -102,13 +104,13 @@ public class FigureRenderer extends RocketRenderer {
color[0] = Math.max(color[0], d) * m; color[0] = Math.max(color[0], d) * m;
color[1] = Math.max(color[1], d) * m; color[1] = Math.max(color[1], d) * m;
color[2] = Math.max(color[2], d) * m; color[2] = Math.max(color[2], d) * m;
gl.glMaterialfv(GL.GL_FRONT, GLLightingFunc.GL_SPECULAR, color, 0); gl.glMaterialfv(GL.GL_FRONT, GLLightingFunc.GL_SPECULAR, color, 0);
gl.glMateriali(GL.GL_FRONT, GLLightingFunc.GL_SHININESS, getShine(c)); gl.glMateriali(GL.GL_FRONT, GLLightingFunc.GL_SHININESS, getShine(c));
color[0] = color[1] = color[2] = 0; color[0] = color[1] = color[2] = 0;
gl.glMaterialfv(GL.GL_BACK, GLLightingFunc.GL_SPECULAR, color, 0); gl.glMaterialfv(GL.GL_BACK, GLLightingFunc.GL_SPECULAR, color, 0);
//Back A&D //Back A&D
convertColor(figureColor, color); convertColor(figureColor, color);
color[0] = color[0] * 0.4f; color[0] = color[0] * 0.4f;
@ -117,7 +119,7 @@ public class FigureRenderer extends RocketRenderer {
color[3] = alpha; color[3] = alpha;
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.renderGeometry(gl, c);
} }
@ -140,9 +142,9 @@ public class FigureRenderer extends RocketRenderer {
} }
return 20; return 20;
} }
protected static void convertColor(Color color, float[] out) { protected static void convertColor(Color color, float[] out) {
if ( color == null ){ if (color == null) {
out[0] = 1; out[0] = 1;
out[1] = 1; out[1] = 1;
out[2] = 0; out[2] = 0;
@ -152,4 +154,13 @@ public class FigureRenderer extends RocketRenderer {
out[2] = Math.max(0.2f, (float) color.getBlue() / 255f) * 2; out[2] = Math.max(0.2f, (float) color.getBlue() / 255f) * 2;
} }
} }
@Override
protected void renderMotor(GL2 gl, Coordinate c, 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);
}
} }

View File

@ -14,9 +14,12 @@ import javax.media.opengl.fixedfunc.GLMatrixFunc;
import net.sf.openrocket.appearance.Appearance; import net.sf.openrocket.appearance.Appearance;
import net.sf.openrocket.appearance.Decal; import net.sf.openrocket.appearance.Decal;
import net.sf.openrocket.appearance.defaults.MotorAppearance;
import net.sf.openrocket.document.OpenRocketDocument; import net.sf.openrocket.document.OpenRocketDocument;
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;
@ -92,8 +95,26 @@ public class RealisticRenderer extends RocketRenderer {
} }
@Override @Override
public void renderComponent(GL2 gl, RocketComponent c, float alpha) { protected void renderMotor(final GL2 gl, final Coordinate c, final Motor motor) {
final Appearance a = getAppearance(c); render(gl, new Runnable() {
@Override
public void run() {
cr.renderMotor(gl, c, motor);
}
}, MotorAppearance.getAppearance(motor), 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);
}
private void render(GL2 gl, Runnable g, Appearance a, float alpha) {
final Decal t = a.getTexture(); final Decal t = a.getTexture();
final Texture tex = getTexture(t); final Texture tex = getTexture(t);
@ -116,7 +137,7 @@ 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);
cr.renderGeometry(gl, c); g.run();
if (t != null && tex != null) { if (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);
@ -155,7 +176,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);
} }
cr.renderGeometry(gl, c); g.run();
if (t.getEdgeMode() == Decal.EdgeMode.STICKER) { if (t.getEdgeMode() == Decal.EdgeMode.STICKER) {
gl.glDepthFunc(GL.GL_LESS); gl.glDepthFunc(GL.GL_LESS);

View File

@ -176,16 +176,19 @@ public abstract class RocketRenderer {
MotorMount mount = iterator.next(); MotorMount mount = iterator.next();
Motor motor = mount.getMotor(motorID); Motor motor = mount.getMotor(motorID);
double length = motor.getLength(); double length = motor.getLength();
double radius = motor.getDiameter() / 2;
Coordinate[] position = ((RocketComponent) mount).toAbsolute(new Coordinate(((RocketComponent) mount) Coordinate[] position = ((RocketComponent) mount).toAbsolute(new Coordinate(((RocketComponent) mount)
.getLength() + mount.getMotorOverhang() - length)); .getLength() + mount.getMotorOverhang() - length));
for (int i = 0; i < position.length; i++) { for (int i = 0; i < position.length; i++) {
cr.renderMotor(gl, position[i], length, radius); renderMotor(gl, position[i], motor);
} }
} }
} }
protected void renderMotor(GL2 gl, Coordinate c, Motor motor) {
cr.renderMotor(gl, c, motor);
}
} }