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)) {