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.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.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.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:
|
||||
@ -1574,6 +1576,12 @@ LevelOfDetail.LOW_QUALITY = Low quality
|
||||
LevelOfDetail.NORMAL_QUALITY = Normal 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
|
||||
TCMotorSelPan.lbl.Selrocketmotor = Select rocket motor:
|
||||
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
|
||||
|
@ -33,6 +33,10 @@ public class OBJExportOptions {
|
||||
* If true, triangulate all faces (convert quads and higher-order polygons to triangles)
|
||||
*/
|
||||
private boolean triangulate;
|
||||
/**
|
||||
* The method to use for triangulation.
|
||||
*/
|
||||
private ObjUtils.TriangulationMethod triangulationMethod;
|
||||
/**
|
||||
* If true, use sRGB colors instead of linear color space.
|
||||
*/
|
||||
@ -94,6 +98,14 @@ public class OBJExportOptions {
|
||||
this.triangulate = triangulate;
|
||||
}
|
||||
|
||||
public ObjUtils.TriangulationMethod getTriangulationMethod() {
|
||||
return triangulationMethod;
|
||||
}
|
||||
|
||||
public void setTriangulationMethod(ObjUtils.TriangulationMethod triangulationMethod) {
|
||||
this.triangulationMethod = triangulationMethod;
|
||||
}
|
||||
|
||||
public boolean isExportAppearance() {
|
||||
return exportAppearance;
|
||||
}
|
||||
|
@ -175,7 +175,14 @@ public class OBJExporterFactory {
|
||||
|
||||
// Triangulate mesh
|
||||
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
|
||||
|
@ -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_REMOVE_OFFSET = "RemoveOffset";
|
||||
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_LOD = "LOD";
|
||||
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_REMOVE_OFFSET, options.isRemoveOffset());
|
||||
objExportOptionsNode.putBoolean(OBJ_TRIANGULATE, options.isTriangulate());
|
||||
objExportOptionsNode.put(OBJ_TRIANGULATION_METHOD, options.getTriangulationMethod().getExportLabel());
|
||||
objExportOptionsNode.putBoolean(OBJ_SRGB, options.isUseSRGB());
|
||||
|
||||
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.setRemoveOffset(objExportOptionsNode.getBoolean(OBJ_REMOVE_OFFSET, 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.setScaling(objExportOptionsNode.getFloat(OBJ_SCALING, 1000));
|
||||
|
@ -175,6 +175,7 @@ public class OBJExporterFactoryTest {
|
||||
bodyTube.setFilled(true);
|
||||
|
||||
options.setTriangulate(true);
|
||||
options.setTriangulationMethod(ObjUtils.TriangulationMethod.DELAUNAY);
|
||||
options.setRemoveOffset(false);
|
||||
options.setExportAppearance(true);
|
||||
options.setScaling(1000);
|
||||
@ -193,6 +194,14 @@ public class OBJExporterFactoryTest {
|
||||
//// Just hope for no exceptions :)
|
||||
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
|
||||
Files.delete(tempFile);
|
||||
}
|
||||
|
@ -15,11 +15,13 @@ import net.sf.openrocket.unit.UnitGroup;
|
||||
|
||||
import javax.swing.AbstractButton;
|
||||
import javax.swing.BorderFactory;
|
||||
import javax.swing.DefaultListCellRenderer;
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.JCheckBox;
|
||||
import javax.swing.JComboBox;
|
||||
import javax.swing.JComponent;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JList;
|
||||
import javax.swing.JOptionPane;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.JSeparator;
|
||||
@ -29,6 +31,7 @@ import javax.swing.UIManager;
|
||||
import javax.swing.event.ChangeEvent;
|
||||
import javax.swing.event.ChangeListener;
|
||||
import java.awt.Color;
|
||||
import java.awt.Component;
|
||||
import java.awt.Window;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
@ -53,6 +56,7 @@ public class OBJOptionChooser extends JPanel {
|
||||
private final JCheckBox exportAsSeparateFiles;
|
||||
private final JCheckBox removeOffset;
|
||||
private final JCheckBox triangulate;
|
||||
private final JComboBox<ObjUtils.TriangulationMethod> triangulationMethod;
|
||||
private final JCheckBox sRGB;
|
||||
private final JComboBox<ObjUtils.LevelOfDetail> LOD;
|
||||
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
|
||||
JLabel LODLabel = new JLabel(trans.get("OBJOptionChooser.lbl.LevelOfDetail"));
|
||||
LODLabel.setToolTipText(trans.get("OBJOptionChooser.lbl.LevelOfDetail.ttip"));
|
||||
@ -394,6 +409,7 @@ public class OBJOptionChooser extends JPanel {
|
||||
if (!opts.isTriangulate()) {
|
||||
this.exportAppearance.setSelected(opts.isExportAppearance());
|
||||
}
|
||||
this.triangulationMethod.setSelectedItem(opts.getTriangulationMethod());
|
||||
this.sRGB.setSelected(opts.isUseSRGB());
|
||||
|
||||
this.scalingModel.setValue(opts.getScaling());
|
||||
@ -422,6 +438,7 @@ public class OBJOptionChooser extends JPanel {
|
||||
opts.setExportAsSeparateFiles(exportAsSeparateFiles.isSelected());
|
||||
opts.setRemoveOffset(removeOffset.isSelected());
|
||||
opts.setTriangulate(triangulate.isSelected());
|
||||
opts.setTriangulationMethod((ObjUtils.TriangulationMethod) triangulationMethod.getSelectedItem());
|
||||
opts.setUseSRGB(sRGB.isSelected());
|
||||
opts.setScaling((float) scalingModel.getValue());
|
||||
opts.setLOD((ObjUtils.LevelOfDetail) LOD.getSelectedItem());
|
||||
@ -441,6 +458,7 @@ public class OBJOptionChooser extends JPanel {
|
||||
options.setRemoveOffset(true);
|
||||
options.setScaling(1000);
|
||||
options.setTriangulate(true);
|
||||
options.setTriangulationMethod(ObjUtils.TriangulationMethod.DELAUNAY);
|
||||
options.setLOD(ObjUtils.LevelOfDetail.HIGH_QUALITY);
|
||||
|
||||
loadOptions(options);
|
||||
@ -453,6 +471,7 @@ public class OBJOptionChooser extends JPanel {
|
||||
*/
|
||||
private boolean isOptimizedFor3DPrinting(OBJExportOptions options) {
|
||||
return !options.isExportMotors() && !options.isExportAppearance() && options.isTriangulate() &&
|
||||
options.getTriangulationMethod() == ObjUtils.TriangulationMethod.DELAUNAY &&
|
||||
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) {
|
||||
if (e.getStateChange() != ItemEvent.SELECTED) {
|
||||
return;
|
||||
|
Loading…
x
Reference in New Issue
Block a user