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>
*/
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 double shine;
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.shine = MathUtil.clamp(shine, 0, 1);
this.texture = texture;
}
Appearance(final Color paint, final double shine) {
public Appearance(final Color paint, final double shine) {
this.paint = paint;
this.shine = MathUtil.clamp(shine, 0, 1);
this.texture = null;

View File

@ -9,25 +9,27 @@ import net.sf.openrocket.util.Coordinate;
* @author Bill Kuker <bkuker@billkuker.com>
*/
public class Decal {
public static enum EdgeMode {
REPEAT("TextureWrap.Repeat"), MIRROR("TextureWrap.Mirror"), CLAMP("TextureWrap.Clamp"), STICKER("TextureWrap.Sticker");
private final String transName;
EdgeMode(final String name){
EdgeMode(final String name) {
this.transName = name;
}
@Override
public String toString(){
public String toString() {
return Application.getTranslator().get(transName);
}
}
private final Coordinate offset, center, scale;
private final double rotation;
private final DecalImage image;
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) {
this.offset = offset;
this.center = center;
@ -36,35 +38,35 @@ public class Decal {
this.image = image;
this.mode = mode;
}
public Coordinate getOffset() {
return offset;
}
public Coordinate getCenter() {
return center;
}
public Coordinate getScale() {
return scale;
}
public double getRotation() {
return rotation;
}
public EdgeMode getEdgeMode() {
return mode;
}
public DecalImage getImage() {
return image;
}
@Override
public String toString() {
return "Texture [offset=" + offset + ", center=" + center + ", scale=" + scale + ", rotation=" + rotation
+ ", 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 net.sf.openrocket.logging.LogHelper;
import net.sf.openrocket.motor.Motor;
import net.sf.openrocket.rocketcomponent.BodyTube;
import net.sf.openrocket.rocketcomponent.EllipticalFinSet;
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) {
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);
public void renderMotor(final GL2 gl, final Coordinate c, Motor motor) {
double l = motor.getLength();
double r = motor.getDiameter() / 2;
gl.glPushMatrix();
@ -325,15 +325,48 @@ public class ComponentRenderer {
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.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.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();
}
}

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.motor.Motor;
import net.sf.openrocket.rocketcomponent.BodyTube;
import net.sf.openrocket.rocketcomponent.ExternalComponent;
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.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];
@ -29,9 +31,9 @@ public class FigureRenderer extends RocketRenderer {
GL2 gl = drawable.getGL().getGL2();
gl.glLightModelfv(GL2ES1.GL_LIGHT_MODEL_AMBIENT,
new float[] { 0,0,0 }, 0);
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;
@ -41,21 +43,21 @@ public class FigureRenderer extends RocketRenderer {
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)
@ -74,7 +76,7 @@ public class FigureRenderer extends RocketRenderer {
}
private static final HashMap<Class<?>, Color> defaultColorCache = new HashMap<Class<?>, Color>();
@Override
public void renderComponent(GL2 gl, RocketComponent c, float alpha) {
@ -88,13 +90,13 @@ public class FigureRenderer extends RocketRenderer {
defaultColorCache.put(c.getClass(), figureColor);
}
}
// 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;
@ -102,13 +104,13 @@ public class FigureRenderer extends RocketRenderer {
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));
color[0] = color[1] = color[2] = 0;
gl.glMaterialfv(GL.GL_BACK, GLLightingFunc.GL_SPECULAR, color, 0);
//Back A&D
convertColor(figureColor, color);
color[0] = color[0] * 0.4f;
@ -117,7 +119,7 @@ public class FigureRenderer extends RocketRenderer {
color[3] = alpha;
gl.glMaterialfv(GL.GL_BACK, GLLightingFunc.GL_DIFFUSE, color, 0);
gl.glMaterialfv(GL.GL_BACK, GLLightingFunc.GL_AMBIENT, color, 0);
cr.renderGeometry(gl, c);
}
@ -140,9 +142,9 @@ public class FigureRenderer extends RocketRenderer {
}
return 20;
}
protected static void convertColor(Color color, float[] out) {
if ( color == null ){
if (color == null) {
out[0] = 1;
out[1] = 1;
out[2] = 0;
@ -152,4 +154,13 @@ public class FigureRenderer extends RocketRenderer {
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.Decal;
import net.sf.openrocket.appearance.defaults.MotorAppearance;
import net.sf.openrocket.document.OpenRocketDocument;
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;
@ -92,8 +95,26 @@ public class RealisticRenderer extends RocketRenderer {
}
@Override
public void renderComponent(GL2 gl, RocketComponent c, float alpha) {
final Appearance a = getAppearance(c);
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);
}
}, 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 Texture tex = getTexture(t);
@ -116,7 +137,7 @@ public class RealisticRenderer extends RocketRenderer {
gl.glMaterialfv(GL.GL_BACK, GLLightingFunc.GL_SPECULAR, colorBlack, 0);
gl.glMateriali(GL.GL_BACK, GLLightingFunc.GL_SHININESS, 0);
cr.renderGeometry(gl, c);
g.run();
if (t != null && tex != null) {
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);
}
cr.renderGeometry(gl, c);
g.run();
if (t.getEdgeMode() == Decal.EdgeMode.STICKER) {
gl.glDepthFunc(GL.GL_LESS);

View File

@ -176,16 +176,19 @@ public abstract class RocketRenderer {
MotorMount mount = iterator.next();
Motor motor = mount.getMotor(motorID);
double length = motor.getLength();
double radius = motor.getDiameter() / 2;
Coordinate[] position = ((RocketComponent) mount).toAbsolute(new Coordinate(((RocketComponent) mount)
.getLength() + mount.getMotorOverhang() - length));
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);
}
}