Add basic material exporting :)
This commit is contained in:
parent
ee51a7ec49
commit
6e981a39a0
@ -0,0 +1,68 @@
|
||||
package net.sf.openrocket.file.wavefrontobj.export;
|
||||
|
||||
import net.sf.openrocket.appearance.Appearance;
|
||||
import net.sf.openrocket.appearance.defaults.DefaultAppearance;
|
||||
import net.sf.openrocket.file.wavefrontobj.DefaultMtl;
|
||||
import net.sf.openrocket.file.wavefrontobj.DefaultObj;
|
||||
import net.sf.openrocket.rocketcomponent.RocketComponent;
|
||||
import net.sf.openrocket.util.Color;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Helper class for exporting a rocket component's appearance to an MTL file.
|
||||
*
|
||||
* @author Sibo Van Gool <sibo.vangool@hotmail.com>
|
||||
*/
|
||||
public class MtlExpoter {
|
||||
private final DefaultObj obj;
|
||||
private final RocketComponent component;
|
||||
private final String materialName;
|
||||
private List<DefaultMtl> materials;
|
||||
|
||||
/**
|
||||
* Export the appearance of a rocket component
|
||||
* <b>NOTE: </b> you still have to call {@link #doExport()} to actually export the appearance.
|
||||
* @param obj The obj file that will use the material
|
||||
* @param component The component to export the appearance of
|
||||
* @param materialName The name of the material to generate
|
||||
* @param materials The list of materials to add the new material(s) to
|
||||
*/
|
||||
public MtlExpoter(DefaultObj obj, RocketComponent component, String materialName, List<DefaultMtl> materials) {
|
||||
this.obj = obj;
|
||||
this.component = component;
|
||||
this.materialName = materialName;
|
||||
this.materials = materials;
|
||||
}
|
||||
|
||||
/**
|
||||
* Export the appearance of the component to the MTL file. Also sets the active material group in the OBJ file.
|
||||
*/
|
||||
public void doExport() {
|
||||
// Set the active material group
|
||||
obj.setActiveMaterialGroupName(materialName);
|
||||
DefaultMtl material = new DefaultMtl(materialName);
|
||||
|
||||
// Get the component appearance
|
||||
Appearance appearance = component.getAppearance();
|
||||
if (appearance == null) {
|
||||
appearance = DefaultAppearance.getDefaultAppearance(component);
|
||||
}
|
||||
|
||||
// Apply coloring
|
||||
Color color = appearance.getPaint();
|
||||
final float r = color.getRed()/255f;
|
||||
final float g = color.getGreen()/255f;
|
||||
final float b = color.getBlue()/255f;
|
||||
material.setKd(r, g, b); // Diffuse color
|
||||
material.setKa(0f, 0f, 0f); // No emission
|
||||
material.setKs(1f, 1f, 1f); // Use white specular highlights
|
||||
material.setD(color.getAlpha()/255f); // Opacity
|
||||
material.setNs((float) appearance.getShine() * 750); // Shine (max is 1000, but this too strong compared to OpenRocket's max)
|
||||
material.setIllum(2); // Use Phong reflection (specular highlights etc.)
|
||||
|
||||
// TODO: Apply texture
|
||||
|
||||
materials.add(material);
|
||||
}
|
||||
}
|
@ -2,6 +2,8 @@ package net.sf.openrocket.file.wavefrontobj.export;
|
||||
|
||||
import de.javagl.obj.ObjWriter;
|
||||
import net.sf.openrocket.file.wavefrontobj.CoordTransform;
|
||||
import net.sf.openrocket.file.wavefrontobj.DefaultMtl;
|
||||
import net.sf.openrocket.file.wavefrontobj.DefaultMtlWriter;
|
||||
import net.sf.openrocket.file.wavefrontobj.DefaultObj;
|
||||
import net.sf.openrocket.file.wavefrontobj.ObjUtils;
|
||||
import net.sf.openrocket.file.wavefrontobj.export.components.BodyTubeExporter;
|
||||
@ -94,6 +96,8 @@ public class OBJExporterFactory {
|
||||
public void doExport() {
|
||||
DefaultObj obj = new DefaultObj();
|
||||
Map<String, DefaultObj> objFileMap;
|
||||
Map<DefaultObj, List<DefaultMtl>> materials = new HashMap<>();
|
||||
materials.put(obj, new ArrayList<>());
|
||||
boolean exportAsSeparateFiles = this.options.isExportAsSeparateFiles();
|
||||
|
||||
if (exportAsSeparateFiles) {
|
||||
@ -129,11 +133,13 @@ public class OBJExporterFactory {
|
||||
// If separate export, create a new OBJ for each component
|
||||
if (exportAsSeparateFiles) {
|
||||
obj = new DefaultObj();
|
||||
materials.put(obj, new ArrayList<>());
|
||||
}
|
||||
|
||||
// Component exporting
|
||||
String groupName = idx + "_" + component.getName();
|
||||
handleComponent(obj, this.configuration, this.options.getTransformer(), component, groupName, this.options.getLOD());
|
||||
handleComponent(obj, this.configuration, this.options.getTransformer(), component, groupName,
|
||||
materials.get(obj), this.options.getLOD(), options);
|
||||
|
||||
// If separate export, add this object to the map of objects to export
|
||||
if (exportAsSeparateFiles) {
|
||||
@ -169,6 +175,18 @@ public class OBJExporterFactory {
|
||||
ObjUtils.scaleVertices(obj, options.getScaling());
|
||||
}
|
||||
|
||||
// Export materials
|
||||
if (options.isExportAppearance()) {
|
||||
String mtlFilePath = FileUtils.removeExtension(filePath) + ".mtl";
|
||||
List<DefaultMtl> mtls = materials.get(obj);
|
||||
try (OutputStream mtlOutputStream = new FileOutputStream(mtlFilePath)) {
|
||||
DefaultMtlWriter.write(mtls, mtlOutputStream);
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
obj.setMtlFileNames(List.of(mtlFilePath));
|
||||
}
|
||||
|
||||
// Write the OBJ file
|
||||
writeObj(obj, filePath);
|
||||
}
|
||||
@ -184,7 +202,8 @@ public class OBJExporterFactory {
|
||||
|
||||
@SuppressWarnings("unchecked") // This is safe because of the structure we set up.
|
||||
private <T extends RocketComponent> void handleComponent(DefaultObj obj, FlightConfiguration config, CoordTransform transformer,
|
||||
T component, String groupName, ObjUtils.LevelOfDetail LOD) {
|
||||
T component, String groupName, List<DefaultMtl> materials,
|
||||
ObjUtils.LevelOfDetail LOD, OBJExportOptions options) {
|
||||
ExporterFactory<T> factory = null;
|
||||
Class<?> currentClass = component.getClass();
|
||||
|
||||
@ -198,6 +217,12 @@ public class OBJExporterFactory {
|
||||
throw new IllegalArgumentException("Unsupported component type: " + component.getClass().getName());
|
||||
}
|
||||
|
||||
// Export material
|
||||
if (options.isExportAppearance()) {
|
||||
MtlExpoter mtlExpoter = new MtlExpoter(obj, component, "mat_" + groupName, materials);
|
||||
mtlExpoter.doExport();
|
||||
}
|
||||
|
||||
// Export component
|
||||
final RocketComponentExporter<T> exporter = factory.create(obj, config, transformer, component, groupName, LOD);
|
||||
exporter.addToObj();
|
||||
|
@ -19,6 +19,8 @@ public class RingComponentExporter extends RocketComponentExporter<RingComponent
|
||||
|
||||
@Override
|
||||
public void addToObj() {
|
||||
obj.setActiveGroupNames(groupName);
|
||||
|
||||
final float outerRadius = (float) component.getOuterRadius();
|
||||
final float innerRadius = (float) component.getInnerRadius();
|
||||
final float length = (float) component.getLength();
|
||||
@ -32,7 +34,7 @@ public class RingComponentExporter extends RocketComponentExporter<RingComponent
|
||||
private void generateMesh(float outerRadius, float innerRadius, float length, InstanceContext context) {
|
||||
// Generate the mesh
|
||||
int startIdx = obj.getNumVertices();
|
||||
TubeExporter.addTubeMesh(obj, transformer, groupName, outerRadius, innerRadius, length, LOD);
|
||||
TubeExporter.addTubeMesh(obj, transformer, null, outerRadius, innerRadius, length, LOD);
|
||||
int endIdx = Math.max(obj.getNumVertices() - 1, startIdx); // Clamp in case no vertices were added
|
||||
|
||||
// Translate the mesh to the position in the rocket
|
||||
|
Loading…
x
Reference in New Issue
Block a user