Add triangulation method setting to OBJ export dialog
This commit is contained in:
parent
dfd497b9d1
commit
cca0ec4a24
@ -1556,6 +1556,8 @@ OBJOptionChooser.checkbox.removeOffset.ttip = <html>If true, remove the offset o
|
|||||||
OBJOptionChooser.btn.showAdvanced = Show Advanced options
|
OBJOptionChooser.btn.showAdvanced = Show Advanced options
|
||||||
OBJOptionChooser.checkbox.triangulate = Triangulate mesh
|
OBJOptionChooser.checkbox.triangulate = Triangulate mesh
|
||||||
OBJOptionChooser.checkbox.triangulate.ttip = If true, triangulate the mesh before exporting (convert all quads or high-order polygons to a triangle).
|
OBJOptionChooser.checkbox.triangulate.ttip = If true, triangulate the mesh before exporting (convert all quads or high-order polygons to a triangle).
|
||||||
|
OBJOptionChooser.lbl.triangulationMethod = Triangulation method:
|
||||||
|
OBJOptionChooser.lbl.triangulationMethod.ttip = Select the desired algorithm to use for the triangulation.
|
||||||
OBJOptionChooser.checkbox.sRGB = Export colors in sRGB
|
OBJOptionChooser.checkbox.sRGB = Export colors in sRGB
|
||||||
OBJOptionChooser.checkbox.sRGB.ttip = <html>If true, export colors in sRGB instead of a linear color scheme.<br>Is useful for instance when exporting for use in Blender.</html>
|
OBJOptionChooser.checkbox.sRGB.ttip = <html>If true, export colors in sRGB instead of a linear color scheme.<br>Is useful for instance when exporting for use in Blender.</html>
|
||||||
OBJOptionChooser.lbl.Scaling = Scaling:
|
OBJOptionChooser.lbl.Scaling = Scaling:
|
||||||
@ -1574,6 +1576,12 @@ LevelOfDetail.LOW_QUALITY = Low quality
|
|||||||
LevelOfDetail.NORMAL_QUALITY = Normal quality
|
LevelOfDetail.NORMAL_QUALITY = Normal quality
|
||||||
LevelOfDetail.HIGH_QUALITY = High quality
|
LevelOfDetail.HIGH_QUALITY = High quality
|
||||||
|
|
||||||
|
! TriangulationMethod
|
||||||
|
TriangulationMethod.SIMPLE = Simple (fast)
|
||||||
|
TriangulationMethod.SIMPLE.ttip = Simple triangulation method (fast, but may produce poor results)
|
||||||
|
TriangulationMethod.DELAUNAY = Delaunay (recommended)
|
||||||
|
TriangulationMethod.DELAUNAY.ttip = Constrained Delaunay triangulation method (recommended, but may be slow for large models)
|
||||||
|
|
||||||
! ThrustCurveMotorSelectionPanel
|
! ThrustCurveMotorSelectionPanel
|
||||||
TCMotorSelPan.lbl.Selrocketmotor = Select rocket motor:
|
TCMotorSelPan.lbl.Selrocketmotor = Select rocket motor:
|
||||||
TCMotorSelPan.checkbox.hideSimilar = Hide very similar thrust curves
|
TCMotorSelPan.checkbox.hideSimilar = Hide very similar thrust curves
|
||||||
|
@ -76,6 +76,43 @@ public class ObjUtils {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public enum TriangulationMethod {
|
||||||
|
SIMPLE(trans.get("TriangulationMethod.SIMPLE"), trans.get("TriangulationMethod.SIMPLE.ttip"), "SIMPLE"),
|
||||||
|
DELAUNAY(trans.get("TriangulationMethod.DELAUNAY"), trans.get("TriangulationMethod.DELAUNAY.ttip"), "DELAUNAY");
|
||||||
|
|
||||||
|
private final String label;
|
||||||
|
private final String tooltip;
|
||||||
|
private final String exportLabel;
|
||||||
|
|
||||||
|
TriangulationMethod(String label, String tooltip, String exportLabel) {
|
||||||
|
this.label = label;
|
||||||
|
this.tooltip = tooltip;
|
||||||
|
this.exportLabel = exportLabel;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return label;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getTooltip() {
|
||||||
|
return tooltip;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getExportLabel() {
|
||||||
|
return exportLabel;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static TriangulationMethod fromExportLabel(String exportLabel) {
|
||||||
|
for (TriangulationMethod tm : TriangulationMethod.values()) {
|
||||||
|
if (tm.getExportLabel().equals(exportLabel)) {
|
||||||
|
return tm;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return TriangulationMethod.DELAUNAY;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Offset the indices by the given offset
|
* Offset the indices by the given offset
|
||||||
|
@ -33,6 +33,10 @@ public class OBJExportOptions {
|
|||||||
* If true, triangulate all faces (convert quads and higher-order polygons to triangles)
|
* If true, triangulate all faces (convert quads and higher-order polygons to triangles)
|
||||||
*/
|
*/
|
||||||
private boolean triangulate;
|
private boolean triangulate;
|
||||||
|
/**
|
||||||
|
* The method to use for triangulation.
|
||||||
|
*/
|
||||||
|
private ObjUtils.TriangulationMethod triangulationMethod;
|
||||||
/**
|
/**
|
||||||
* If true, use sRGB colors instead of linear color space.
|
* If true, use sRGB colors instead of linear color space.
|
||||||
*/
|
*/
|
||||||
@ -94,6 +98,14 @@ public class OBJExportOptions {
|
|||||||
this.triangulate = triangulate;
|
this.triangulate = triangulate;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ObjUtils.TriangulationMethod getTriangulationMethod() {
|
||||||
|
return triangulationMethod;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTriangulationMethod(ObjUtils.TriangulationMethod triangulationMethod) {
|
||||||
|
this.triangulationMethod = triangulationMethod;
|
||||||
|
}
|
||||||
|
|
||||||
public boolean isExportAppearance() {
|
public boolean isExportAppearance() {
|
||||||
return exportAppearance;
|
return exportAppearance;
|
||||||
}
|
}
|
||||||
|
@ -175,7 +175,14 @@ public class OBJExporterFactory {
|
|||||||
|
|
||||||
// Triangulate mesh
|
// Triangulate mesh
|
||||||
if (this.options.isTriangulate()) {
|
if (this.options.isTriangulate()) {
|
||||||
obj = TriangulationHelper.constrainedDelaunayTriangulate(obj);
|
ObjUtils.TriangulationMethod triangulationMethod = this.options.getTriangulationMethod();
|
||||||
|
if (triangulationMethod == ObjUtils.TriangulationMethod.DELAUNAY) {
|
||||||
|
obj = TriangulationHelper.constrainedDelaunayTriangulate(obj);
|
||||||
|
} else if (triangulationMethod == ObjUtils.TriangulationMethod.SIMPLE) {
|
||||||
|
obj = TriangulationHelper.simpleTriangulate(obj);
|
||||||
|
} else {
|
||||||
|
throw new IllegalArgumentException("Unsupported triangulation method: " + triangulationMethod);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove position offset
|
// Remove position offset
|
||||||
|
@ -128,6 +128,7 @@ public abstract class Preferences implements ChangeSource {
|
|||||||
private static final String OBJ_EXPORT_AS_SEPARATE_FILES = "ExportAsSeparateFiles";
|
private static final String OBJ_EXPORT_AS_SEPARATE_FILES = "ExportAsSeparateFiles";
|
||||||
private static final String OBJ_REMOVE_OFFSET = "RemoveOffset";
|
private static final String OBJ_REMOVE_OFFSET = "RemoveOffset";
|
||||||
private static final String OBJ_TRIANGULATE = "Triangulate";
|
private static final String OBJ_TRIANGULATE = "Triangulate";
|
||||||
|
private static final String OBJ_TRIANGULATION_METHOD = "TriangulationMethod";
|
||||||
private static final String OBJ_SRGB = "sRGB";
|
private static final String OBJ_SRGB = "sRGB";
|
||||||
private static final String OBJ_LOD = "LOD";
|
private static final String OBJ_LOD = "LOD";
|
||||||
private static final String OBJ_SCALING = "Scaling";
|
private static final String OBJ_SCALING = "Scaling";
|
||||||
@ -1051,6 +1052,7 @@ public abstract class Preferences implements ChangeSource {
|
|||||||
objExportOptionsNode.putBoolean(OBJ_EXPORT_AS_SEPARATE_FILES, options.isExportAsSeparateFiles());
|
objExportOptionsNode.putBoolean(OBJ_EXPORT_AS_SEPARATE_FILES, options.isExportAsSeparateFiles());
|
||||||
objExportOptionsNode.putBoolean(OBJ_REMOVE_OFFSET, options.isRemoveOffset());
|
objExportOptionsNode.putBoolean(OBJ_REMOVE_OFFSET, options.isRemoveOffset());
|
||||||
objExportOptionsNode.putBoolean(OBJ_TRIANGULATE, options.isTriangulate());
|
objExportOptionsNode.putBoolean(OBJ_TRIANGULATE, options.isTriangulate());
|
||||||
|
objExportOptionsNode.put(OBJ_TRIANGULATION_METHOD, options.getTriangulationMethod().getExportLabel());
|
||||||
objExportOptionsNode.putBoolean(OBJ_SRGB, options.isUseSRGB());
|
objExportOptionsNode.putBoolean(OBJ_SRGB, options.isUseSRGB());
|
||||||
|
|
||||||
objExportOptionsNode.putFloat(OBJ_SCALING, options.getScaling());
|
objExportOptionsNode.putFloat(OBJ_SCALING, options.getScaling());
|
||||||
@ -1081,6 +1083,9 @@ public abstract class Preferences implements ChangeSource {
|
|||||||
options.setExportAsSeparateFiles(objExportOptionsNode.getBoolean(OBJ_EXPORT_AS_SEPARATE_FILES, false));
|
options.setExportAsSeparateFiles(objExportOptionsNode.getBoolean(OBJ_EXPORT_AS_SEPARATE_FILES, false));
|
||||||
options.setRemoveOffset(objExportOptionsNode.getBoolean(OBJ_REMOVE_OFFSET, true));
|
options.setRemoveOffset(objExportOptionsNode.getBoolean(OBJ_REMOVE_OFFSET, true));
|
||||||
options.setTriangulate(objExportOptionsNode.getBoolean(OBJ_TRIANGULATE, true));
|
options.setTriangulate(objExportOptionsNode.getBoolean(OBJ_TRIANGULATE, true));
|
||||||
|
options.setTriangulationMethod(ObjUtils.TriangulationMethod.fromExportLabel(
|
||||||
|
objExportOptionsNode.get(OBJ_TRIANGULATION_METHOD, ObjUtils.TriangulationMethod.DELAUNAY.getExportLabel())
|
||||||
|
));
|
||||||
options.setUseSRGB(objExportOptionsNode.getBoolean(OBJ_SRGB, false));
|
options.setUseSRGB(objExportOptionsNode.getBoolean(OBJ_SRGB, false));
|
||||||
|
|
||||||
options.setScaling(objExportOptionsNode.getFloat(OBJ_SCALING, 1000));
|
options.setScaling(objExportOptionsNode.getFloat(OBJ_SCALING, 1000));
|
||||||
|
@ -175,6 +175,7 @@ public class OBJExporterFactoryTest {
|
|||||||
bodyTube.setFilled(true);
|
bodyTube.setFilled(true);
|
||||||
|
|
||||||
options.setTriangulate(true);
|
options.setTriangulate(true);
|
||||||
|
options.setTriangulationMethod(ObjUtils.TriangulationMethod.DELAUNAY);
|
||||||
options.setRemoveOffset(false);
|
options.setRemoveOffset(false);
|
||||||
options.setExportAppearance(true);
|
options.setExportAppearance(true);
|
||||||
options.setScaling(1000);
|
options.setScaling(1000);
|
||||||
@ -193,6 +194,14 @@ public class OBJExporterFactoryTest {
|
|||||||
//// Just hope for no exceptions :)
|
//// Just hope for no exceptions :)
|
||||||
assertEquals(warnings.size(), 1);
|
assertEquals(warnings.size(), 1);
|
||||||
|
|
||||||
|
// Test simple triangulation
|
||||||
|
options.setTriangulationMethod(ObjUtils.TriangulationMethod.SIMPLE);
|
||||||
|
|
||||||
|
exporterFactory = new OBJExporterFactory(components, rocket.getSelectedConfiguration(), tempFile.toFile(), options, warnings);
|
||||||
|
exporterFactory.doExport();
|
||||||
|
//// Just hope for no exceptions :)
|
||||||
|
assertEquals(warnings.size(), 1);
|
||||||
|
|
||||||
// Clean up
|
// Clean up
|
||||||
Files.delete(tempFile);
|
Files.delete(tempFile);
|
||||||
}
|
}
|
||||||
|
@ -15,11 +15,13 @@ import net.sf.openrocket.unit.UnitGroup;
|
|||||||
|
|
||||||
import javax.swing.AbstractButton;
|
import javax.swing.AbstractButton;
|
||||||
import javax.swing.BorderFactory;
|
import javax.swing.BorderFactory;
|
||||||
|
import javax.swing.DefaultListCellRenderer;
|
||||||
import javax.swing.JButton;
|
import javax.swing.JButton;
|
||||||
import javax.swing.JCheckBox;
|
import javax.swing.JCheckBox;
|
||||||
import javax.swing.JComboBox;
|
import javax.swing.JComboBox;
|
||||||
import javax.swing.JComponent;
|
import javax.swing.JComponent;
|
||||||
import javax.swing.JLabel;
|
import javax.swing.JLabel;
|
||||||
|
import javax.swing.JList;
|
||||||
import javax.swing.JOptionPane;
|
import javax.swing.JOptionPane;
|
||||||
import javax.swing.JPanel;
|
import javax.swing.JPanel;
|
||||||
import javax.swing.JSeparator;
|
import javax.swing.JSeparator;
|
||||||
@ -29,6 +31,7 @@ import javax.swing.UIManager;
|
|||||||
import javax.swing.event.ChangeEvent;
|
import javax.swing.event.ChangeEvent;
|
||||||
import javax.swing.event.ChangeListener;
|
import javax.swing.event.ChangeListener;
|
||||||
import java.awt.Color;
|
import java.awt.Color;
|
||||||
|
import java.awt.Component;
|
||||||
import java.awt.Window;
|
import java.awt.Window;
|
||||||
import java.awt.event.ActionEvent;
|
import java.awt.event.ActionEvent;
|
||||||
import java.awt.event.ActionListener;
|
import java.awt.event.ActionListener;
|
||||||
@ -53,6 +56,7 @@ public class OBJOptionChooser extends JPanel {
|
|||||||
private final JCheckBox exportAsSeparateFiles;
|
private final JCheckBox exportAsSeparateFiles;
|
||||||
private final JCheckBox removeOffset;
|
private final JCheckBox removeOffset;
|
||||||
private final JCheckBox triangulate;
|
private final JCheckBox triangulate;
|
||||||
|
private final JComboBox<ObjUtils.TriangulationMethod> triangulationMethod;
|
||||||
private final JCheckBox sRGB;
|
private final JCheckBox sRGB;
|
||||||
private final JComboBox<ObjUtils.LevelOfDetail> LOD;
|
private final JComboBox<ObjUtils.LevelOfDetail> LOD;
|
||||||
private final DoubleModel scalingModel;
|
private final DoubleModel scalingModel;
|
||||||
@ -236,6 +240,17 @@ public class OBJOptionChooser extends JPanel {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
//// Triangulation method
|
||||||
|
JLabel tmLabel = new JLabel(trans.get("OBJOptionChooser.lbl.triangulationMethod"));
|
||||||
|
tmLabel.setToolTipText(trans.get("OBJOptionChooser.lbl.triangulationMethod.ttip"));
|
||||||
|
advancedOptionsPanel.add(tmLabel, "spanx, split 2");
|
||||||
|
this.triangulationMethod = new JComboBox<>(ObjUtils.TriangulationMethod.values());
|
||||||
|
this.triangulationMethod.setToolTipText(trans.get("OBJOptionChooser.lbl.triangulationMethod.ttip"));
|
||||||
|
this.triangulationMethod.setRenderer(new TriangulationMethodRenderer());
|
||||||
|
destroyTheMagic(triangulationMethod);
|
||||||
|
addOptimizationListener(triangulationMethod);
|
||||||
|
advancedOptionsPanel.add(triangulationMethod, "growx, wrap unrel");
|
||||||
|
|
||||||
//// Level of detail
|
//// Level of detail
|
||||||
JLabel LODLabel = new JLabel(trans.get("OBJOptionChooser.lbl.LevelOfDetail"));
|
JLabel LODLabel = new JLabel(trans.get("OBJOptionChooser.lbl.LevelOfDetail"));
|
||||||
LODLabel.setToolTipText(trans.get("OBJOptionChooser.lbl.LevelOfDetail.ttip"));
|
LODLabel.setToolTipText(trans.get("OBJOptionChooser.lbl.LevelOfDetail.ttip"));
|
||||||
@ -394,6 +409,7 @@ public class OBJOptionChooser extends JPanel {
|
|||||||
if (!opts.isTriangulate()) {
|
if (!opts.isTriangulate()) {
|
||||||
this.exportAppearance.setSelected(opts.isExportAppearance());
|
this.exportAppearance.setSelected(opts.isExportAppearance());
|
||||||
}
|
}
|
||||||
|
this.triangulationMethod.setSelectedItem(opts.getTriangulationMethod());
|
||||||
this.sRGB.setSelected(opts.isUseSRGB());
|
this.sRGB.setSelected(opts.isUseSRGB());
|
||||||
|
|
||||||
this.scalingModel.setValue(opts.getScaling());
|
this.scalingModel.setValue(opts.getScaling());
|
||||||
@ -422,6 +438,7 @@ public class OBJOptionChooser extends JPanel {
|
|||||||
opts.setExportAsSeparateFiles(exportAsSeparateFiles.isSelected());
|
opts.setExportAsSeparateFiles(exportAsSeparateFiles.isSelected());
|
||||||
opts.setRemoveOffset(removeOffset.isSelected());
|
opts.setRemoveOffset(removeOffset.isSelected());
|
||||||
opts.setTriangulate(triangulate.isSelected());
|
opts.setTriangulate(triangulate.isSelected());
|
||||||
|
opts.setTriangulationMethod((ObjUtils.TriangulationMethod) triangulationMethod.getSelectedItem());
|
||||||
opts.setUseSRGB(sRGB.isSelected());
|
opts.setUseSRGB(sRGB.isSelected());
|
||||||
opts.setScaling((float) scalingModel.getValue());
|
opts.setScaling((float) scalingModel.getValue());
|
||||||
opts.setLOD((ObjUtils.LevelOfDetail) LOD.getSelectedItem());
|
opts.setLOD((ObjUtils.LevelOfDetail) LOD.getSelectedItem());
|
||||||
@ -441,6 +458,7 @@ public class OBJOptionChooser extends JPanel {
|
|||||||
options.setRemoveOffset(true);
|
options.setRemoveOffset(true);
|
||||||
options.setScaling(1000);
|
options.setScaling(1000);
|
||||||
options.setTriangulate(true);
|
options.setTriangulate(true);
|
||||||
|
options.setTriangulationMethod(ObjUtils.TriangulationMethod.DELAUNAY);
|
||||||
options.setLOD(ObjUtils.LevelOfDetail.HIGH_QUALITY);
|
options.setLOD(ObjUtils.LevelOfDetail.HIGH_QUALITY);
|
||||||
|
|
||||||
loadOptions(options);
|
loadOptions(options);
|
||||||
@ -453,6 +471,7 @@ public class OBJOptionChooser extends JPanel {
|
|||||||
*/
|
*/
|
||||||
private boolean isOptimizedFor3DPrinting(OBJExportOptions options) {
|
private boolean isOptimizedFor3DPrinting(OBJExportOptions options) {
|
||||||
return !options.isExportMotors() && !options.isExportAppearance() && options.isTriangulate() &&
|
return !options.isExportMotors() && !options.isExportAppearance() && options.isTriangulate() &&
|
||||||
|
options.getTriangulationMethod() == ObjUtils.TriangulationMethod.DELAUNAY &&
|
||||||
options.getLOD() == ObjUtils.LevelOfDetail.HIGH_QUALITY && options.isRemoveOffset() && options.getScaling() == 1000;
|
options.getLOD() == ObjUtils.LevelOfDetail.HIGH_QUALITY && options.isRemoveOffset() && options.getScaling() == 1000;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -581,6 +600,22 @@ public class OBJOptionChooser extends JPanel {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static class TriangulationMethodRenderer extends DefaultListCellRenderer {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Component getListCellRendererComponent(JList list, Object value,
|
||||||
|
int index, boolean isSelected, boolean cellHasFocus) {
|
||||||
|
|
||||||
|
JComponent comp = (JComponent) super.getListCellRendererComponent(list,
|
||||||
|
value, index, isSelected, cellHasFocus);
|
||||||
|
|
||||||
|
if (index > -1 && value instanceof ObjUtils.TriangulationMethod) {
|
||||||
|
list.setToolTipText(((ObjUtils.TriangulationMethod) value).getTooltip());
|
||||||
|
}
|
||||||
|
return comp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*private void coordTransComboAction(ItemEvent e, JComboBox<Axis> otherCombo) {
|
/*private void coordTransComboAction(ItemEvent e, JComboBox<Axis> otherCombo) {
|
||||||
if (e.getStateChange() != ItemEvent.SELECTED) {
|
if (e.getStateChange() != ItemEvent.SELECTED) {
|
||||||
return;
|
return;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user