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