Merge pull request #39 from bkuker/kruland-integration-defaults
Add Default appearances
BIN
core/resources/datafiles/textures/balsa.png
Normal file
After Width: | Height: | Size: 553 KiB |
BIN
core/resources/datafiles/textures/cardboard.png
Normal file
After Width: | Height: | Size: 84 KiB |
BIN
core/resources/datafiles/textures/chute.png
Normal file
After Width: | Height: | Size: 144 KiB |
BIN
core/resources/datafiles/textures/hardboard.png
Normal file
After Width: | Height: | Size: 134 KiB |
BIN
core/resources/datafiles/textures/motors/aerotech.png
Normal file
After Width: | Height: | Size: 12 KiB |
BIN
core/resources/datafiles/textures/motors/estes.png
Normal file
After Width: | Height: | Size: 60 KiB |
BIN
core/resources/datafiles/textures/motors/reusable.png
Normal file
After Width: | Height: | Size: 10 KiB |
BIN
core/resources/datafiles/textures/spiral-wound-alpha.png
Normal file
After Width: | Height: | Size: 2.0 KiB |
BIN
core/resources/datafiles/textures/wadding.png
Normal file
After Width: | Height: | Size: 66 KiB |
BIN
core/resources/datafiles/textures/wood.png
Normal file
After Width: | Height: | Size: 1.4 MiB |
@ -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:
|
||||
|
@ -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;
|
||||
|
@ -13,11 +13,13 @@ 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);
|
||||
}
|
||||
}
|
||||
@ -27,7 +29,7 @@ public class Decal {
|
||||
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;
|
||||
|
@ -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<Color, Appearance> plastics = new HashMap<Color, Appearance>();
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
@ -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
|
||||
}
|
||||
|
||||
}
|
@ -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<EdgeMode>(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");
|
||||
}
|
||||
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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<Coordinate> bounds = configuration.getBounds();
|
||||
final Bounds b = new Bounds();
|
||||
final Collection<Coordinate> 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<RocketComponent> selection = new HashSet<RocketComponent>();
|
||||
|
||||
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;
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
@ -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*/
|
||||
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;
|
||||
};
|
||||
|
||||
private static enum VIEW_TYPE {
|
||||
Sideview,
|
||||
Backview,
|
||||
Figure3D,
|
||||
Realistic3D;
|
||||
@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();
|
||||
}
|
||||
}
|
||||
};
|
||||
|