diff --git a/core/resources/l10n/messages.properties b/core/resources/l10n/messages.properties
index 0ccde6a8f..0668aabcc 100644
--- a/core/resources/l10n/messages.properties
+++ b/core/resources/l10n/messages.properties
@@ -1489,6 +1489,11 @@ StorageOptChooser.lbl.Saveopt = Save options
! OBJOptionChooser
OBJOptionChooser.lbl.component = Component: %s
OBJOptionChooser.lbl.multipleComponents = Multiple components
+OBJOptionChooser.lbl.optimizeFor = Optimize for:
+OBJOptionChooser.btn.opt3DPrint = 3D printing
+OBJOptionChooser.btn.opt3DPrint.ttip = Optimize the OBJ export settings for 3D printing.
+OBJOptionChooser.btn.opt3DRend = 3D rendering
+OBJOptionChooser.btn.opt3DRend.ttip = Optimize the OBJ export settings for use in 3D rendering software.
OBJOptionChooser.checkbox.exportChildren = Export children
OBJOptionChooser.checkbox.exportChildren.ttip = If true, export children of the selected components as well.
OBJOptionChooser.checkbox.exportChildren.assemblies.ttip = Component assemblies always export their children.
@@ -1518,7 +1523,7 @@ OBJOptionChooser.lbl.CoordinateTransform.Forward.ttip = Select the OBJ axis that
! LevelOfDetail
LevelOfDetail.LOW_QUALITY = Low quality
-LevelOfDetail.NORMAL = Normal quality
+LevelOfDetail.NORMAL_QUALITY = Normal quality
LevelOfDetail.HIGH_QUALITY = High quality
! ThrustCurveMotorSelectionPanel
diff --git a/core/src/net/sf/openrocket/file/wavefrontobj/ObjUtils.java b/core/src/net/sf/openrocket/file/wavefrontobj/ObjUtils.java
index 3a31365cb..0931fc57d 100644
--- a/core/src/net/sf/openrocket/file/wavefrontobj/ObjUtils.java
+++ b/core/src/net/sf/openrocket/file/wavefrontobj/ObjUtils.java
@@ -24,7 +24,7 @@ public class ObjUtils {
*/
public enum LevelOfDetail {
LOW_QUALITY(25, trans.get("LevelOfDetail.LOW_QUALITY"), "LOW"),
- NORMAL(60, trans.get("LevelOfDetail.NORMAL"), "NORMAL"),
+ NORMAL_QUALITY(60, trans.get("LevelOfDetail.NORMAL_QUALITY"), "NORMAL"),
HIGH_QUALITY(100, trans.get("LevelOfDetail.HIGH_QUALITY"), "HIGH");
private final int value;
@@ -51,7 +51,7 @@ public class ObjUtils {
return lod;
}
}
- return LevelOfDetail.NORMAL;
+ return LevelOfDetail.NORMAL_QUALITY;
}
/**
diff --git a/core/src/net/sf/openrocket/file/wavefrontobj/export/OBJExportOptions.java b/core/src/net/sf/openrocket/file/wavefrontobj/export/OBJExportOptions.java
index 82766288b..ab283f718 100644
--- a/core/src/net/sf/openrocket/file/wavefrontobj/export/OBJExportOptions.java
+++ b/core/src/net/sf/openrocket/file/wavefrontobj/export/OBJExportOptions.java
@@ -51,7 +51,7 @@ public class OBJExportOptions {
this.exportAsSeparateFiles = false;
this.removeOffset = true;
this.triangulate = false;
- this.LOD = ObjUtils.LevelOfDetail.NORMAL;
+ this.LOD = ObjUtils.LevelOfDetail.NORMAL_QUALITY;
this.transformer = new DefaultCoordTransform(rocket.getLength());
this.scaling = 1.0f;
}
diff --git a/core/src/net/sf/openrocket/startup/Preferences.java b/core/src/net/sf/openrocket/startup/Preferences.java
index 7667cdd90..2bcb8d885 100644
--- a/core/src/net/sf/openrocket/startup/Preferences.java
+++ b/core/src/net/sf/openrocket/startup/Preferences.java
@@ -1066,18 +1066,19 @@ public abstract class Preferences implements ChangeSource {
java.util.prefs.Preferences preferences = getPreferences();
java.util.prefs.Preferences objExportOptionsNode = preferences.node(OBJ_EXPORT_OPTIONS_NODE);
+ // By default, we will use options optimized for 3D printing (most-used case)
OBJExportOptions options = new OBJExportOptions(rocket);
options.setExportChildren(objExportOptionsNode.getBoolean(OBJ_EXPORT_CHILDREN, false));
options.setExportAppearance(objExportOptionsNode.getBoolean(OBJ_EXPORT_APPEARANCE, false));
options.setExportAsSeparateFiles(objExportOptionsNode.getBoolean(OBJ_EXPORT_AS_SEPARATE_FILES, false));
options.setRemoveOffset(objExportOptionsNode.getBoolean(OBJ_REMOVE_OFFSET, true));
- options.setTriangulate(objExportOptionsNode.getBoolean(OBJ_TRIANGULATE, false));
+ options.setTriangulate(objExportOptionsNode.getBoolean(OBJ_TRIANGULATE, true));
options.setUseSRGB(objExportOptionsNode.getBoolean(OBJ_SRGB, false));
- options.setScaling(objExportOptionsNode.getFloat(OBJ_SCALING, 1));
+ options.setScaling(objExportOptionsNode.getFloat(OBJ_SCALING, 1000));
options.setLOD(ObjUtils.LevelOfDetail.fromExportLabel(
- objExportOptionsNode.get(OBJ_LOD, ObjUtils.LevelOfDetail.NORMAL.getExportLabel())));
+ objExportOptionsNode.get(OBJ_LOD, ObjUtils.LevelOfDetail.HIGH_QUALITY.getExportLabel())));
// Load CoordTransform
java.util.prefs.Preferences coordTransformNode = objExportOptionsNode.node(OBJ_TRANSFORMER_NODE);
diff --git a/swing/src/net/sf/openrocket/file/wavefrontobj/OBJOptionChooser.java b/swing/src/net/sf/openrocket/file/wavefrontobj/OBJOptionChooser.java
index 3d4de68a2..5837f751d 100644
--- a/swing/src/net/sf/openrocket/file/wavefrontobj/OBJOptionChooser.java
+++ b/swing/src/net/sf/openrocket/file/wavefrontobj/OBJOptionChooser.java
@@ -12,6 +12,7 @@ import net.sf.openrocket.rocketcomponent.RocketComponent;
import net.sf.openrocket.startup.Application;
import net.sf.openrocket.unit.UnitGroup;
+import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JLabel;
@@ -20,6 +21,8 @@ import javax.swing.JSeparator;
import javax.swing.JSpinner;
import javax.swing.JToggleButton;
import java.awt.Window;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.util.ArrayList;
@@ -54,10 +57,37 @@ public class OBJOptionChooser extends JPanel {
this.selectedComponents = selectedComponents;
this.rocket = rocket;
- // ------------ Component selection ------------
+ // ------------ Component/optimization selection ------------
+ // Component
componentsLabel = new JLabel();
updateComponentsLabel(selectedComponents);
- this.add(componentsLabel, "spanx, wrap");
+ this.add(componentsLabel, "spanx, wrap unrel");
+
+ // Optimize for:
+ JLabel label = new JLabel(trans.get("OBJOptionChooser.lbl.optimizeFor"));
+ this.add(label);
+
+ // 3D printing
+ JButton opt3DPrint = new JButton(trans.get("OBJOptionChooser.btn.opt3DPrint"));
+ opt3DPrint.setToolTipText(trans.get("OBJOptionChooser.btn.opt3DPrint.ttip"));
+ opt3DPrint.addActionListener(new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ optimizeSettingsFor3DPrinting(opts);
+ }
+ });
+ this.add(opt3DPrint, "wrap");
+
+ // 3D rendering
+ JButton opt3DRend = new JButton(trans.get("OBJOptionChooser.btn.opt3DRend"));
+ opt3DRend.setToolTipText(trans.get("OBJOptionChooser.btn.opt3DRend.ttip"));
+ opt3DRend.addActionListener(new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ optimizeSettingsFor3DRendering(opts);
+ }
+ });
+ this.add(opt3DRend, "skip 1, wrap");
this.add(new JSeparator(JSeparator.HORIZONTAL), "spanx, growx, wrap para");
@@ -101,16 +131,6 @@ public class OBJOptionChooser extends JPanel {
this.exportAsSeparateFiles.setToolTipText(trans.get("OBJOptionChooser.checkbox.exportAsSeparateFiles.ttip"));
this.add(exportAsSeparateFiles, "spanx, wrap unrel");
- //// Scaling
- JLabel scalingLabel = new JLabel(trans.get("OBJOptionChooser.lbl.Scaling"));
- scalingLabel.setToolTipText(trans.get("OBJOptionChooser.lbl.Scaling.ttip"));
- this.add(scalingLabel, "spanx, split 2");
- this.scalingModel = new DoubleModel(opts, "ScalingDouble", UnitGroup.UNITS_SCALING, 0, 10000);
- JSpinner spin = new JSpinner(scalingModel.getSpinnerModel());
- spin.setToolTipText(trans.get("OBJOptionChooser.lbl.Scaling.ttip"));
- spin.setEditor(new SpinnerEditor(spin, 5));
- this.add(spin, "wrap");
-
this.add(new JSeparator(JSeparator.HORIZONTAL), "spanx, growx, wrap para");
// ------------ Advanced options ------------
@@ -123,6 +143,16 @@ public class OBJOptionChooser extends JPanel {
advancedOptionsPanel.setLayout(new MigLayout("ins 0"));
advancedOptionsPanel.setVisible(false);
+ //// Scaling
+ JLabel scalingLabel = new JLabel(trans.get("OBJOptionChooser.lbl.Scaling"));
+ scalingLabel.setToolTipText(trans.get("OBJOptionChooser.lbl.Scaling.ttip"));
+ advancedOptionsPanel.add(scalingLabel, "spanx, split 2");
+ this.scalingModel = new DoubleModel(opts, "ScalingDouble", UnitGroup.UNITS_SCALING, 0, 10000);
+ JSpinner spin = new JSpinner(scalingModel.getSpinnerModel());
+ spin.setToolTipText(trans.get("OBJOptionChooser.lbl.Scaling.ttip"));
+ spin.setEditor(new SpinnerEditor(spin, 5));
+ advancedOptionsPanel.add(spin, "wrap");
+
//// Export colors in sRGB
this.sRGB = new JCheckBox(trans.get("OBJOptionChooser.checkbox.sRGB"));
this.sRGB.setToolTipText(trans.get("OBJOptionChooser.checkbox.sRGB.ttip"));
@@ -320,6 +350,20 @@ public class OBJOptionChooser extends JPanel {
opts.setTransformer(new DefaultCoordTransform(rocket.getLength()));
}
+ private static void optimizeSettingsFor3DPrinting(OBJExportOptions options) {
+ options.setExportAppearance(false);
+ options.setScaling(1000);
+ options.setTriangulate(true);
+ options.setLOD(ObjUtils.LevelOfDetail.HIGH_QUALITY);
+ }
+
+ private static void optimizeSettingsFor3DRendering(OBJExportOptions options) {
+ options.setExportAppearance(true);
+ options.setScaling(1);
+ options.setTriangulate(false);
+ options.setLOD(ObjUtils.LevelOfDetail.NORMAL_QUALITY);
+ }
+
private static boolean isOnlyComponentAssembliesSelected(List selectedComponents) {
for (RocketComponent component : selectedComponents) {
if (!(component instanceof ComponentAssembly)) {