diff --git a/core/resources/datafiles/examples/Sticker Decals.ork b/core/resources/datafiles/examples/Sticker Decals.ork index 18e1a26d1..3f0c85d05 100644 Binary files a/core/resources/datafiles/examples/Sticker Decals.ork and b/core/resources/datafiles/examples/Sticker Decals.ork differ diff --git a/core/resources/datafiles/textures/balsa.png b/core/resources/datafiles/textures/balsa.png new file mode 100644 index 000000000..f48f581fb Binary files /dev/null and b/core/resources/datafiles/textures/balsa.png differ diff --git a/core/resources/datafiles/textures/cardboard.png b/core/resources/datafiles/textures/cardboard.png new file mode 100644 index 000000000..0101594de Binary files /dev/null and b/core/resources/datafiles/textures/cardboard.png differ diff --git a/core/resources/datafiles/textures/chute.png b/core/resources/datafiles/textures/chute.png new file mode 100644 index 000000000..c58f4f465 Binary files /dev/null and b/core/resources/datafiles/textures/chute.png differ diff --git a/core/resources/datafiles/textures/hardboard.png b/core/resources/datafiles/textures/hardboard.png new file mode 100644 index 000000000..a769700d8 Binary files /dev/null and b/core/resources/datafiles/textures/hardboard.png differ diff --git a/core/resources/datafiles/textures/motors/aerotech.png b/core/resources/datafiles/textures/motors/aerotech.png new file mode 100644 index 000000000..5efeac52f Binary files /dev/null and b/core/resources/datafiles/textures/motors/aerotech.png differ diff --git a/core/resources/datafiles/textures/motors/estes.png b/core/resources/datafiles/textures/motors/estes.png new file mode 100644 index 000000000..9d8efbf24 Binary files /dev/null and b/core/resources/datafiles/textures/motors/estes.png differ diff --git a/core/resources/datafiles/textures/motors/reusable.png b/core/resources/datafiles/textures/motors/reusable.png new file mode 100644 index 000000000..17ce44745 Binary files /dev/null and b/core/resources/datafiles/textures/motors/reusable.png differ diff --git a/core/resources/datafiles/textures/spiral-wound-alpha.png b/core/resources/datafiles/textures/spiral-wound-alpha.png new file mode 100644 index 000000000..628dd92bb Binary files /dev/null and b/core/resources/datafiles/textures/spiral-wound-alpha.png differ diff --git a/core/resources/datafiles/textures/wadding.png b/core/resources/datafiles/textures/wadding.png new file mode 100644 index 000000000..a80104b0a Binary files /dev/null and b/core/resources/datafiles/textures/wadding.png differ diff --git a/core/resources/datafiles/textures/wood.png b/core/resources/datafiles/textures/wood.png new file mode 100644 index 000000000..8e46ce4a4 Binary files /dev/null and b/core/resources/datafiles/textures/wood.png differ diff --git a/core/resources/l10n/messages.properties b/core/resources/l10n/messages.properties index a43d03cd2..4d49265b3 100644 --- a/core/resources/l10n/messages.properties +++ b/core/resources/l10n/messages.properties @@ -47,7 +47,8 @@ RocketActions.MoveDownAct.ttip.Movedown = Move this component downwards. RocketPanel.FigTypeAct.Sideview = Side view RocketPanel.FigTypeAct.Backview = Back view RocketPanel.FigTypeAct.Figure3D = 3D Figure -RocketPanel.FigTypeAct.Realistic3D = 3D Realistic +RocketPanel.FigTypeAct.Finished = 3D Finished +RocketPanel.FigTypeAct.Unfinished = 3D Unfinished RocketPanel.lbl.Flightcfg = Flight configuration: diff --git a/core/src/net/sf/openrocket/appearance/Appearance.java b/core/src/net/sf/openrocket/appearance/Appearance.java index a421c15e8..385256bb6 100644 --- a/core/src/net/sf/openrocket/appearance/Appearance.java +++ b/core/src/net/sf/openrocket/appearance/Appearance.java @@ -10,19 +10,19 @@ import net.sf.openrocket.util.MathUtil; * @author Bill Kuker */ 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; diff --git a/core/src/net/sf/openrocket/appearance/Decal.java b/core/src/net/sf/openrocket/appearance/Decal.java index ff56014bc..5e5461188 100644 --- a/core/src/net/sf/openrocket/appearance/Decal.java +++ b/core/src/net/sf/openrocket/appearance/Decal.java @@ -9,25 +9,27 @@ import net.sf.openrocket.util.Coordinate; * @author Bill Kuker */ 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 + "]"; } - + } diff --git a/core/src/net/sf/openrocket/appearance/defaults/DefaultAppearance.java b/core/src/net/sf/openrocket/appearance/defaults/DefaultAppearance.java new file mode 100644 index 000000000..acb74b5d9 --- /dev/null +++ b/core/src/net/sf/openrocket/appearance/defaults/DefaultAppearance.java @@ -0,0 +1,111 @@ +package net.sf.openrocket.appearance.defaults; + +import java.util.HashMap; + +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.rocketcomponent.BodyTube; +import net.sf.openrocket.rocketcomponent.EngineBlock; +import net.sf.openrocket.rocketcomponent.FinSet; +import net.sf.openrocket.rocketcomponent.InnerTube; +import net.sf.openrocket.rocketcomponent.LaunchLug; +import net.sf.openrocket.rocketcomponent.MassObject; +import net.sf.openrocket.rocketcomponent.Parachute; +import net.sf.openrocket.rocketcomponent.RadiusRingComponent; +import net.sf.openrocket.rocketcomponent.RocketComponent; +import net.sf.openrocket.rocketcomponent.Transition; +import net.sf.openrocket.rocketcomponent.TubeCoupler; +import net.sf.openrocket.util.Color; +import net.sf.openrocket.util.Coordinate; + +public class DefaultAppearance { + + private static Appearance simple(String resource) { + return new Appearance( + new Color(1, 1, 1), + 0, + new Decal( + new Coordinate(0, 0), + new Coordinate(0, 0), + new Coordinate(1, 1), + 0, + new ResourceDecalImage(resource), EdgeMode.REPEAT)); + }; + + private static Appearance simpleAlpha(Color base, float shine, String resource) { + return new Appearance( + base, + shine, + new Decal( + new Coordinate(0, 0), + new Coordinate(0, 0), + new Coordinate(1, 1), + 0, + new ResourceDecalImage(resource), EdgeMode.REPEAT)); + }; + + private static Appearance BALSA = simple("/datafiles/textures/balsa.png"); + private static Appearance WOOD = simple("/datafiles/textures/wood.png"); + @SuppressWarnings("unused") + private static Appearance CARDBOARD = simple("/datafiles/textures/cardboard.png"); + private static Appearance HARDBOARD = simple("/datafiles/textures/hardboard.png"); + private static Appearance WADDING = simple("/datafiles/textures/wadding.png"); + private static Appearance CHUTE = simple("/datafiles/textures/chute.png"); + + + private static final Appearance ESTES_BT = simpleAlpha(new Color(212, 185, 145), .3f, "/datafiles/textures/spiral-wound-alpha.png"); + private static final Appearance ESTES_IT = simpleAlpha(new Color(168, 146, 116), .1f, "/datafiles/textures/spiral-wound-alpha.png"); + private static final Appearance WHITE_BT = simpleAlpha(new Color(240, 240, 240), .3f, "/datafiles/textures/spiral-wound-alpha.png"); + + private static Appearance ESTES_MOTOR = simple("/datafiles/textures/motors/estes.png"); + private static Appearance AEROTECH_MOTOR = simple("/datafiles/textures/motors/aerotech.png"); + private static Appearance REUSABLE_MOTOR = simpleAlpha(new Color(195, 60, 50), .6f, "/datafiles/textures/motors/reusable.png"); + + private static HashMap plastics = new HashMap(); + + private static Appearance getPlastic(Color c) { + if (!plastics.containsKey(c)) { + plastics.put(c, new Appearance(c, .3)); + } + return plastics.get(c); + } + + public static Appearance getDefaultAppearance(RocketComponent c) { + if (c instanceof BodyTube) + return ESTES_BT; + if (c instanceof InnerTube || c instanceof TubeCoupler) + return ESTES_IT; + if (c instanceof FinSet) + return BALSA; + if (c instanceof LaunchLug) + return WHITE_BT; + if (c instanceof Transition) + return getPlastic(new Color(255, 255, 255)); + if (c instanceof RadiusRingComponent) + return WOOD; + if (c instanceof Parachute) + return CHUTE; + if (c instanceof EngineBlock) + return HARDBOARD; + if (c instanceof MassObject) + return WADDING; + + return Appearance.MISSING; + } + + public static Appearance getDefaultAppearance(Motor m) { + if (m instanceof ThrustCurveMotor) { + ThrustCurveMotor tcm = (ThrustCurveMotor) m; + if ("Estes".equals(tcm.getManufacturer().getSimpleName())) { + return ESTES_MOTOR; + } + if ("AeroTech".equals(tcm.getManufacturer().getSimpleName())) { + return AEROTECH_MOTOR; + } + } + return REUSABLE_MOTOR; + } +} diff --git a/core/src/net/sf/openrocket/appearance/defaults/ResourceDecalImage.java b/core/src/net/sf/openrocket/appearance/defaults/ResourceDecalImage.java new file mode 100644 index 000000000..6b41636d0 --- /dev/null +++ b/core/src/net/sf/openrocket/appearance/defaults/ResourceDecalImage.java @@ -0,0 +1,56 @@ +package net.sf.openrocket.appearance.defaults; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStream; +import java.util.EventListener; + +import net.sf.openrocket.appearance.DecalImage; +import net.sf.openrocket.document.Attachment; + + +class ResourceDecalImage implements DecalImage { + + final String resource; + + ResourceDecalImage(final String resource) { + this.resource = resource; + } + + @Override + public String toString() { + return getName(); + } + + @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 { + + } + + @Override + public int compareTo(Attachment a) { + return this.hashCode() - a.hashCode(); + } + + @Override + public void addChangeListener(EventListener listener) { + //Unimplemented, this can not change + } + + @Override + public void removeChangeListener(EventListener listener) { + //Unimplemented, this can not change + } + +} diff --git a/core/src/net/sf/openrocket/gui/configdialog/AppearancePanel.java b/core/src/net/sf/openrocket/gui/configdialog/AppearancePanel.java index 493b9710d..b88b3b661 100644 --- a/core/src/net/sf/openrocket/gui/configdialog/AppearancePanel.java +++ b/core/src/net/sf/openrocket/gui/configdialog/AppearancePanel.java @@ -23,6 +23,7 @@ import javax.swing.SwingUtilities; import net.miginfocom.swing.MigLayout; import net.sf.openrocket.appearance.AppearanceBuilder; import net.sf.openrocket.appearance.Decal.EdgeMode; +import net.sf.openrocket.appearance.defaults.DefaultAppearance; import net.sf.openrocket.document.OpenRocketDocument; import net.sf.openrocket.gui.SpinnerEditor; import net.sf.openrocket.gui.adaptors.BooleanModel; @@ -116,7 +117,7 @@ public class AppearancePanel extends JPanel { public AppearancePanel(final OpenRocketDocument document, final RocketComponent c) { super(new MigLayout("fill", "[150][grow][150][grow]")); - ab = new AppearanceBuilder(c.getAppearance()); + ab = new AppearanceBuilder(c.getAppearance() != null ? c.getAppearance() : DefaultAppearance.getDefaultAppearance(c)); net.sf.openrocket.util.Color figureColor = c.getColor(); if (figureColor == null) { @@ -151,6 +152,7 @@ public class AppearancePanel extends JPanel { figureColorButton.addActionListener(new ColorActionListener(c, "Color")); colorButton.addActionListener(new ColorActionListener(ab, "Paint")); + BooleanModel mDefault = new BooleanModel(c.getAppearance() == null); BooleanModel fDefault = new BooleanModel(c.getColor() == null); @@ -215,12 +217,26 @@ public class AppearancePanel extends JPanel { add(new JSeparator(SwingConstants.HORIZONTAL), "span, wrap, growx"); {// Texture Header Row - add(new StyledLabel(trans.get("AppearanceCfg.lbl.Appearance"), Style.BOLD), "wrap"); + add(new StyledLabel(trans.get("AppearanceCfg.lbl.Appearance"), Style.BOLD)); + final JCheckBox materialDefault = new JCheckBox(mDefault); + materialDefault.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + if (materialDefault.isSelected()) { + c.setAppearance(null); + } else { + c.setAppearance(ab.getAppearance()); + } + } + }); + materialDefault.setText(trans.get("AppearanceCfg.lbl.Usedefault")); + add(materialDefault, "wrap"); } {// Texture File add(new JLabel(trans.get("AppearanceCfg.lbl.Texture"))); JPanel p = new JPanel(new MigLayout("fill, ins 0", "[grow][]")); + mDefault.addEnableComponent(textureDropDown, false); p.add(textureDropDown, "grow"); add(p, "span 3, growx, wrap"); final JButton editBtn = new JButton(trans.get("AppearanceCfg.but.edit")); @@ -243,12 +259,13 @@ public class AppearancePanel extends JPanel { } }); + mDefault.addEnableComponent(editBtn, false); p.add(editBtn); } { // Color add(new JLabel(trans.get("AppearanceCfg.lbl.color.Color"))); - //mDefault.addEnableComponent(colorButton, false); + mDefault.addEnableComponent(colorButton, false); add(colorButton); } @@ -258,11 +275,13 @@ public class AppearancePanel extends JPanel { add(new JLabel("x:"), "split 4"); JSpinner scaleU = new JSpinner(new DoubleModel(ab, "ScaleX", TEXTURE_UNIT).getSpinnerModel()); scaleU.setEditor(new SpinnerEditor(scaleU)); + mDefault.addEnableComponent(scaleU, false); add(scaleU, "w 40"); add(new JLabel("y:")); JSpinner scaleV = new JSpinner(new DoubleModel(ab, "ScaleY", TEXTURE_UNIT).getSpinnerModel()); scaleV.setEditor(new SpinnerEditor(scaleV)); + mDefault.addEnableComponent(scaleV, false); add(scaleV, "wrap, w 40"); } @@ -274,6 +293,10 @@ public class AppearancePanel extends JPanel { JSlider slide = new JSlider(shineModel.getSliderModel(0, 1)); UnitSelector unit = new UnitSelector(shineModel); + mDefault.addEnableComponent(slide, false); + mDefault.addEnableComponent(spin, false); + mDefault.addEnableComponent(unit, false); + add(spin, "split 3, w 50"); add(unit); add(slide, "w 50"); @@ -286,11 +309,13 @@ public class AppearancePanel extends JPanel { add(new JLabel("x:"), "split 4"); JSpinner offsetU = new JSpinner(new DoubleModel(ab, "OffsetU", TEXTURE_UNIT).getSpinnerModel()); offsetU.setEditor(new SpinnerEditor(offsetU)); + mDefault.addEnableComponent(offsetU, false); add(offsetU, "w 40"); add(new JLabel("y:")); JSpinner offsetV = new JSpinner(new DoubleModel(ab, "OffsetV", TEXTURE_UNIT).getSpinnerModel()); offsetV.setEditor(new SpinnerEditor(offsetV)); + mDefault.addEnableComponent(offsetV, false); add(offsetV, "wrap, w 40"); } @@ -299,6 +324,7 @@ public class AppearancePanel extends JPanel { EdgeMode[] list = new EdgeMode[EdgeMode.values().length + 1]; System.arraycopy(EdgeMode.values(), 0, list, 1, EdgeMode.values().length); JComboBox combo = new JComboBox(new EnumModel(ab, "EdgeMode", list)); + mDefault.addEnableComponent(combo, false); add(combo); } @@ -308,9 +334,11 @@ public class AppearancePanel extends JPanel { DoubleModel rotationModel = new DoubleModel(ab, "Rotation", UnitGroup.UNITS_ANGLE); JSpinner rotation = new JSpinner(rotationModel.getSpinnerModel()); rotation.setEditor(new SpinnerEditor(rotation)); + mDefault.addEnableComponent(rotation, false); add(rotation, "split 3, w 50"); add(new UnitSelector(rotationModel)); BasicSlider bs = new BasicSlider(rotationModel.getSliderModel(-Math.PI, Math.PI)); + mDefault.addEnableComponent(bs, false); add(bs, "w 50, wrap"); } diff --git a/core/src/net/sf/openrocket/gui/figure3d/ComponentRenderer.java b/core/src/net/sf/openrocket/gui/figure3d/ComponentRenderer.java index 57a592ce5..1a2434049 100644 --- a/core/src/net/sf/openrocket/gui/figure3d/ComponentRenderer.java +++ b/core/src/net/sf/openrocket/gui/figure3d/ComponentRenderer.java @@ -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(); } } diff --git a/core/src/net/sf/openrocket/gui/figure3d/FigureRenderer.java b/core/src/net/sf/openrocket/gui/figure3d/FigureRenderer.java index 6c9c47605..dbacece61 100644 --- a/core/src/net/sf/openrocket/gui/figure3d/FigureRenderer.java +++ b/core/src/net/sf/openrocket/gui/figure3d/FigureRenderer.java @@ -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]; @@ -156,4 +158,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); + } } diff --git a/core/src/net/sf/openrocket/gui/figure3d/RealisticRenderer.java b/core/src/net/sf/openrocket/gui/figure3d/RealisticRenderer.java index 0e3bbb102..257778fff 100644 --- a/core/src/net/sf/openrocket/gui/figure3d/RealisticRenderer.java +++ b/core/src/net/sf/openrocket/gui/figure3d/RealisticRenderer.java @@ -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.DefaultAppearance; 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); + } + }, DefaultAppearance.getDefaultAppearance(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); @@ -220,10 +241,10 @@ public class RealisticRenderer extends RocketRenderer { } - private Appearance getAppearance(RocketComponent c) { + protected Appearance getAppearance(RocketComponent c) { Appearance ret = c.getAppearance(); if (ret == null) { - ret = Appearance.MISSING; + ret = DefaultAppearance.getDefaultAppearance(c); } return ret; } diff --git a/core/src/net/sf/openrocket/gui/figure3d/RocketFigure3d.java b/core/src/net/sf/openrocket/gui/figure3d/RocketFigure3d.java index 6c0d6ffbf..7082f3391 100644 --- a/core/src/net/sf/openrocket/gui/figure3d/RocketFigure3d.java +++ b/core/src/net/sf/openrocket/gui/figure3d/RocketFigure3d.java @@ -51,8 +51,9 @@ import com.jogamp.opengl.util.awt.Overlay; */ public class RocketFigure3d extends JPanel implements GLEventListener { - public static final int TYPE_REALISTIC = 0; - public static final int TYPE_FIGURE = 1; + public static final int TYPE_FIGURE = 0; + public static final int TYPE_UNFINISHED = 1; + public static final int TYPE_FINISHED = 2; private static final long serialVersionUID = 1L; private static final LogHelper log = Application.getLogger(); @@ -67,8 +68,8 @@ public class RocketFigure3d extends JPanel implements GLEventListener { private static double fovX = Double.NaN; private static final int CARET_SIZE = 20; - private OpenRocketDocument document; - private Configuration configuration; + private final OpenRocketDocument document; + private final Configuration configuration; private GLCanvas canvas; @@ -90,7 +91,7 @@ public class RocketFigure3d extends JPanel implements GLEventListener { RocketRenderer rr = new FigureRenderer(); - public RocketFigure3d(OpenRocketDocument document, Configuration config) { + public RocketFigure3d(final OpenRocketDocument document, final Configuration config) { this.document = document; this.configuration = config; this.setLayout(new BorderLayout()); @@ -131,10 +132,10 @@ public class RocketFigure3d extends JPanel implements GLEventListener { log.debug("Setting up GL capabilities..."); log.verbose("GL - Getting Default Profile"); - GLProfile glp = GLProfile.get(GLProfile.GL2); + final GLProfile glp = GLProfile.get(GLProfile.GL2); log.verbose("GL - creating GLCapabilities"); - GLCapabilities caps = new GLCapabilities(glp); + final GLCapabilities caps = new GLCapabilities(glp); log.verbose("GL - setSampleBuffers"); caps.setSampleBuffers(true); @@ -217,21 +218,21 @@ public class RocketFigure3d extends JPanel implements GLEventListener { MouseEvent pressEvent; @Override - public void mousePressed(MouseEvent e) { + public void mousePressed(final MouseEvent e) { lastX = e.getX(); lastY = e.getY(); pressEvent = e; } @Override - public void mouseClicked(MouseEvent e) { + public void mouseClicked(final MouseEvent e) { pickPoint = new Point(lastX, canvas.getHeight() - lastY); pickEvent = e; internalRepaint(); } @Override - public void mouseDragged(MouseEvent e) { + public void mouseDragged(final MouseEvent e) { int dx = lastX - e.getX(); int dy = lastY - e.getY(); lastX = e.getX(); @@ -257,13 +258,9 @@ public class RocketFigure3d extends JPanel implements GLEventListener { canvas.addMouseListener(a); } - public void setConfiguration(Configuration configuration) { - this.configuration = configuration; - updateFigure(); - } @Override - public void display(GLAutoDrawable drawable) { + public void display(final GLAutoDrawable drawable) { GL2 gl = drawable.getGL().getGL2(); GLU glu = new GLU(); @@ -307,7 +304,7 @@ public class RocketFigure3d extends JPanel implements GLEventListener { } - private void drawCarets(GL2 gl, GLU glu) { + private void drawCarets(final GL2 gl, final GLU glu) { final Graphics2D og2d = caretOverlay.createGraphics(); setRenderingHints(og2d); @@ -355,7 +352,7 @@ public class RocketFigure3d extends JPanel implements GLEventListener { * Re-blits the overlay every frame. Only re-renders the overlay * when needed. */ - private void drawExtras(GL2 gl, GLU glu) { + private void drawExtras(final GL2 gl, final GLU glu) { //Only re-render if needed // redrawExtras: Some external change (new simulation data) means // the data is out of date. @@ -391,17 +388,17 @@ public class RocketFigure3d extends JPanel implements GLEventListener { } @Override - public void dispose(GLAutoDrawable drawable) { + public void dispose(final GLAutoDrawable drawable) { log.verbose("GL - dispose() called"); rr.dispose(drawable); } @Override - public void init(GLAutoDrawable drawable) { + public void init(final GLAutoDrawable drawable) { log.verbose("GL - init()"); rr.init(drawable); - GL2 gl = drawable.getGL().getGL2(); + final GL2 gl = drawable.getGL().getGL2(); gl.glClearDepth(1.0f); // clear z-buffer to the farthest gl.glDepthFunc(GL.GL_LESS); // the type of depth test to do @@ -426,12 +423,12 @@ public class RocketFigure3d extends JPanel implements GLEventListener { } @Override - public void reshape(GLAutoDrawable drawable, int x, int y, int w, int h) { + public void reshape(final GLAutoDrawable drawable, final int x, final int y, final int w, final int h) { log.verbose("GL - reshape()"); - GL2 gl = drawable.getGL().getGL2(); - GLU glu = new GLU(); + final GL2 gl = drawable.getGL().getGL2(); + final GLU glu = new GLU(); - double ratio = (double) w / (double) h; + final double ratio = (double) w / (double) h; fovX = fovY * ratio; gl.glMatrixMode(GLMatrixFunc.GL_PROJECTION); @@ -461,8 +458,8 @@ public class RocketFigure3d extends JPanel implements GLEventListener { if (cachedBounds != null) { return cachedBounds; } else { - Bounds b = new Bounds(); - Collection bounds = configuration.getBounds(); + final Bounds b = new Bounds(); + final Collection bounds = configuration.getBounds(); for (Coordinate c : bounds) { b.xMax = Math.max(b.xMax, c.x); b.xMin = Math.min(b.xMin, c.x); @@ -484,21 +481,21 @@ public class RocketFigure3d extends JPanel implements GLEventListener { } } - private void setupView(GL2 gl, GLU glu) { + private void setupView(final GL2 gl, final GLU glu) { gl.glLoadIdentity(); gl.glLightfv(GLLightingFunc.GL_LIGHT1, GLLightingFunc.GL_POSITION, lightPosition, 0); // Get the bounds - Bounds b = calculateBounds(); + final Bounds b = calculateBounds(); // Calculate the distance needed to fit the bounds in both the X and Y // direction // Add 10% for space around it. - double dX = (b.xSize * 1.2 / 2.0) + final double dX = (b.xSize * 1.2 / 2.0) / Math.tan(Math.toRadians(fovX / 2.0)); - double dY = (b.rMax * 2.0 * 1.2 / 2.0) + final double dY = (b.rMax * 2.0 * 1.2 / 2.0) / Math.tan(Math.toRadians(fovY / 2.0)); // Move back the greater of the 2 distances @@ -551,7 +548,7 @@ public class RocketFigure3d extends JPanel implements GLEventListener { private Set selection = new HashSet(); - public void setSelection(RocketComponent[] selection) { + public void setSelection(final RocketComponent[] selection) { this.selection.clear(); if (selection != null) { for (RocketComponent c : selection) @@ -560,14 +557,14 @@ public class RocketFigure3d extends JPanel implements GLEventListener { internalRepaint(); } - private void setRoll(double rot) { + private void setRoll(final double rot) { if (MathUtil.equals(roll, rot)) return; this.roll = MathUtil.reduce360(rot); internalRepaint(); } - private void setYaw(double rot) { + private void setYaw(final double rot) { if (MathUtil.equals(yaw, rot)) return; this.yaw = MathUtil.reduce360(rot); @@ -576,16 +573,16 @@ public class RocketFigure3d extends JPanel implements GLEventListener { // ///////////// Extra methods - private Coordinate project(Coordinate c, GL2 gl, GLU glu) { - double[] mvmatrix = new double[16]; - double[] projmatrix = new double[16]; - int[] viewport = new int[4]; + private Coordinate project(final Coordinate c, final GL2 gl, final GLU glu) { + final double[] mvmatrix = new double[16]; + final double[] projmatrix = new double[16]; + final int[] viewport = new int[4]; gl.glGetIntegerv(GL.GL_VIEWPORT, viewport, 0); gl.glGetDoublev(GLMatrixFunc.GL_MODELVIEW_MATRIX, mvmatrix, 0); gl.glGetDoublev(GLMatrixFunc.GL_PROJECTION_MATRIX, projmatrix, 0); - double out[] = new double[4]; + final double out[] = new double[4]; glu.gluProject(c.x, c.y, c.z, mvmatrix, 0, projmatrix, 0, viewport, 0, out, 0); @@ -596,22 +593,22 @@ public class RocketFigure3d extends JPanel implements GLEventListener { private Coordinate cp = new Coordinate(0, 0, 0); private Coordinate cg = new Coordinate(0, 0, 0); - public void setCG(Coordinate cg) { + public void setCG(final Coordinate cg) { this.cg = cg; redrawExtras = true; } - public void setCP(Coordinate cp) { + public void setCP(final Coordinate cp) { this.cp = cp; redrawExtras = true; } - public void addRelativeExtra(FigureElement p) { + public void addRelativeExtra(final FigureElement p) { relativeExtra.add(p); redrawExtras = true; } - public void removeRelativeExtra(FigureElement p) { + public void removeRelativeExtra(final FigureElement p) { relativeExtra.remove(p); redrawExtras = true; } @@ -621,12 +618,12 @@ public class RocketFigure3d extends JPanel implements GLEventListener { redrawExtras = true; } - public void addAbsoluteExtra(FigureElement p) { + public void addAbsoluteExtra(final FigureElement p) { absoluteExtra.add(p); redrawExtras = true; } - public void removeAbsoluteExtra(FigureElement p) { + public void removeAbsoluteExtra(final FigureElement p) { absoluteExtra.remove(p); redrawExtras = true; } @@ -654,8 +651,10 @@ public class RocketFigure3d extends JPanel implements GLEventListener { rr.dispose(drawable); if (t == TYPE_FIGURE) { rr = new FigureRenderer(); - } else { + } else if (t == TYPE_FINISHED) { rr = new RealisticRenderer(document); + } else if (t == TYPE_UNFINISHED) { + rr = new UnfinishedRenderer(document); } rr.init(drawable); return false; diff --git a/core/src/net/sf/openrocket/gui/figure3d/RocketRenderer.java b/core/src/net/sf/openrocket/gui/figure3d/RocketRenderer.java index c5707ed70..dc2b5c449 100644 --- a/core/src/net/sf/openrocket/gui/figure3d/RocketRenderer.java +++ b/core/src/net/sf/openrocket/gui/figure3d/RocketRenderer.java @@ -178,16 +178,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); + } + } diff --git a/core/src/net/sf/openrocket/gui/figure3d/UnfinishedRenderer.java b/core/src/net/sf/openrocket/gui/figure3d/UnfinishedRenderer.java new file mode 100644 index 000000000..e7773dc68 --- /dev/null +++ b/core/src/net/sf/openrocket/gui/figure3d/UnfinishedRenderer.java @@ -0,0 +1,25 @@ +package net.sf.openrocket.gui.figure3d; + +import net.sf.openrocket.appearance.Appearance; +import net.sf.openrocket.appearance.defaults.DefaultAppearance; +import net.sf.openrocket.document.OpenRocketDocument; +import net.sf.openrocket.rocketcomponent.BodyTube; +import net.sf.openrocket.rocketcomponent.InnerTube; +import net.sf.openrocket.rocketcomponent.RocketComponent; + +public class UnfinishedRenderer extends RealisticRenderer { + + public UnfinishedRenderer(OpenRocketDocument document) { + super(document); + } + + @Override + public boolean isDrawnTransparent(RocketComponent c) { + return c instanceof BodyTube || c instanceof InnerTube; + } + + @Override + protected Appearance getAppearance(RocketComponent c) { + return DefaultAppearance.getDefaultAppearance(c); + } +} diff --git a/core/src/net/sf/openrocket/gui/scalefigure/RocketPanel.java b/core/src/net/sf/openrocket/gui/scalefigure/RocketPanel.java index 3a590c5f3..f5c76648e 100644 --- a/core/src/net/sf/openrocket/gui/scalefigure/RocketPanel.java +++ b/core/src/net/sf/openrocket/gui/scalefigure/RocketPanel.java @@ -91,16 +91,21 @@ public class RocketPanel extends JPanel implements TreeSelectionListener, Change private static final Translator trans = Application.getTranslator(); - /*RocketPanel.FigTypeAct.Sideview = Side view - RocketPanel.FigTypeAct.Backview = Back view - RocketPanel.FigViewAct.3DFigure = 3D Figure - RocketPanel.FigViewAct.3DRealistic = 3D Realistic*/ - - private static enum VIEW_TYPE { - Sideview, - Backview, - Figure3D, - Realistic3D; + public static enum VIEW_TYPE { + Sideview(false, RocketFigure.TYPE_SIDE), + Backview(false, RocketFigure.TYPE_BACK), + Figure3D(true, RocketFigure3d.TYPE_FIGURE), + Unfinished(true, RocketFigure3d.TYPE_UNFINISHED), + Finished(true, RocketFigure3d.TYPE_FINISHED); + + public final boolean is3d; + private final int type; + + private VIEW_TYPE(final boolean is3d, final int type) { + this.is3d = is3d; + this.type = type; + }; + @Override public String toString() { return trans.get("RocketPanel.FigTypeAct." + super.toString()); @@ -280,23 +285,12 @@ public class RocketPanel extends JPanel implements TreeSelectionListener, Change public void setSelectedItem(Object o) { super.setSelectedItem(o); VIEW_TYPE v = (VIEW_TYPE) o; - switch (v) { - case Sideview: - figure.setType(RocketFigure.TYPE_SIDE); - go2D(); - break; - case Backview: - figure.setType(RocketFigure.TYPE_BACK); - go2D(); - break; - case Realistic3D: - figure3d.setType(RocketFigure3d.TYPE_REALISTIC); + if (v.is3d) { + figure3d.setType(v.type); go3D(); - break; - case Figure3D: - figure3d.setType(RocketFigure3d.TYPE_FIGURE); - go3D(); - break; + } else { + figure.setType(v.type); + go2D(); } } };