diff --git a/core/src/net/sf/openrocket/file/wavefrontobj/export/OBJExporterFactory.java b/core/src/net/sf/openrocket/file/wavefrontobj/export/OBJExporterFactory.java index 6aa8dbaf7..19dc426b3 100644 --- a/core/src/net/sf/openrocket/file/wavefrontobj/export/OBJExporterFactory.java +++ b/core/src/net/sf/openrocket/file/wavefrontobj/export/OBJExporterFactory.java @@ -17,6 +17,8 @@ import net.sf.openrocket.rocketcomponent.BodyTube; import net.sf.openrocket.rocketcomponent.ComponentAssembly; import net.sf.openrocket.rocketcomponent.FinSet; import net.sf.openrocket.rocketcomponent.FlightConfiguration; +import net.sf.openrocket.rocketcomponent.InstanceContext; +import net.sf.openrocket.rocketcomponent.InstanceMap; import net.sf.openrocket.rocketcomponent.LaunchLug; import net.sf.openrocket.rocketcomponent.MassObject; import net.sf.openrocket.rocketcomponent.RailButton; @@ -28,6 +30,7 @@ import net.sf.openrocket.rocketcomponent.TubeFinSet; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; +import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Map; @@ -132,8 +135,13 @@ public class OBJExporterFactory { continue; } + InstanceMap map = configuration.getActiveInstances(); + ArrayList contexts = map.get(component); + contexts.get(0).transform.getXrotation(); + + String groupName = component.getName() + "_" + idx; - handleComponent(obj, this.transformer, component, groupName, this.LOD); + handleComponent(obj, this.configuration, this.transformer, component, groupName, this.LOD); // TODO: motor rendering @@ -161,8 +169,8 @@ public class OBJExporterFactory { } @SuppressWarnings("unchecked") // This is safe because of the structure we set up. - private void handleComponent(DefaultObj obj, CoordTransform transformer, T component, - String groupName, ObjUtils.LevelOfDetail LOD) { + private void handleComponent(DefaultObj obj, FlightConfiguration config, CoordTransform transformer, + T component, String groupName, ObjUtils.LevelOfDetail LOD) { ExporterFactory factory = null; Class currentClass = component.getClass(); @@ -176,12 +184,12 @@ public class OBJExporterFactory { throw new IllegalArgumentException("Unsupported component type: " + component.getClass().getName()); } - final RocketComponentExporter exporter = factory.create(obj, transformer, component, groupName, LOD); + final RocketComponentExporter exporter = factory.create(obj, config, transformer, component, groupName, LOD); exporter.addToObj(); } interface ExporterFactory { - RocketComponentExporter create(DefaultObj obj, CoordTransform transformer, T component, String groupName, - ObjUtils.LevelOfDetail LOD); + RocketComponentExporter create(DefaultObj obj, FlightConfiguration config, CoordTransform transformer, + T component, String groupName, ObjUtils.LevelOfDetail LOD); } } diff --git a/core/src/net/sf/openrocket/file/wavefrontobj/export/components/BodyTubeExporter.java b/core/src/net/sf/openrocket/file/wavefrontobj/export/components/BodyTubeExporter.java index f6a7f3bf8..c159ce025 100644 --- a/core/src/net/sf/openrocket/file/wavefrontobj/export/components/BodyTubeExporter.java +++ b/core/src/net/sf/openrocket/file/wavefrontobj/export/components/BodyTubeExporter.java @@ -6,12 +6,14 @@ import net.sf.openrocket.file.wavefrontobj.ObjUtils; import net.sf.openrocket.file.wavefrontobj.export.shapes.CylinderExporter; import net.sf.openrocket.file.wavefrontobj.export.shapes.TubeExporter; import net.sf.openrocket.rocketcomponent.BodyTube; +import net.sf.openrocket.rocketcomponent.FlightConfiguration; +import net.sf.openrocket.rocketcomponent.InstanceContext; import net.sf.openrocket.util.Coordinate; public class BodyTubeExporter extends RocketComponentExporter { - public BodyTubeExporter(DefaultObj obj, CoordTransform transformer, BodyTube component, String groupName, - ObjUtils.LevelOfDetail LOD) { - super(obj, transformer, component, groupName, LOD); + public BodyTubeExporter(DefaultObj obj, FlightConfiguration config, CoordTransform transformer, BodyTube component, + String groupName, ObjUtils.LevelOfDetail LOD) { + super(obj, config, transformer, component, groupName, LOD); } @Override @@ -20,16 +22,15 @@ public class BodyTubeExporter extends RocketComponentExporter { final float innerRadius = (float) component.getInnerRadius(); final float length = (float) component.getLength(); final boolean isFilled = component.isFilled(); - final Coordinate[] locations = component.getComponentLocations(); // Generate the mesh - for (Coordinate location : locations) { - generateMesh(outerRadius, innerRadius, length, isFilled, location); + for (InstanceContext context : config.getActiveInstances().getInstanceContexts(component)) { + generateMesh(outerRadius, innerRadius, length, isFilled, context); } } private void generateMesh(float outerRadius, float innerRadius, float length, boolean isFilled, - Coordinate location) { + InstanceContext context) { int startIdx = obj.getNumVertices(); if (isFilled || Float.compare(innerRadius, 0) == 0) { @@ -45,6 +46,7 @@ public class BodyTubeExporter extends RocketComponentExporter { int endIdx = Math.max(obj.getNumVertices() - 1, startIdx); // Clamp in case no vertices were added // Translate the mesh to the position in the rocket + Coordinate location = context.getLocation(); ObjUtils.translateVerticesFromComponentLocation(obj, transformer, startIdx, endIdx, location); } } diff --git a/core/src/net/sf/openrocket/file/wavefrontobj/export/components/FinSetExporter.java b/core/src/net/sf/openrocket/file/wavefrontobj/export/components/FinSetExporter.java index 9cae383c8..abfb6ca8f 100644 --- a/core/src/net/sf/openrocket/file/wavefrontobj/export/components/FinSetExporter.java +++ b/core/src/net/sf/openrocket/file/wavefrontobj/export/components/FinSetExporter.java @@ -7,15 +7,17 @@ import net.sf.openrocket.file.wavefrontobj.DefaultObj; import net.sf.openrocket.file.wavefrontobj.ObjUtils; import net.sf.openrocket.file.wavefrontobj.export.shapes.PolygonExporter; import net.sf.openrocket.rocketcomponent.FinSet; +import net.sf.openrocket.rocketcomponent.FlightConfiguration; +import net.sf.openrocket.rocketcomponent.InstanceContext; import net.sf.openrocket.util.Coordinate; import java.util.ArrayList; import java.util.List; public class FinSetExporter extends RocketComponentExporter { - public FinSetExporter(@NotNull DefaultObj obj, @NotNull CoordTransform transformer, FinSet component, - String groupName, ObjUtils.LevelOfDetail LOD) { - super(obj, transformer, component, groupName, LOD); + public FinSetExporter(@NotNull DefaultObj obj, FlightConfiguration config, @NotNull CoordTransform transformer, + FinSet component, String groupName, ObjUtils.LevelOfDetail LOD) { + super(obj, config, transformer, component, groupName, LOD); } @Override @@ -32,21 +34,15 @@ public class FinSetExporter extends RocketComponentExporter { final FloatPoints floatTabPoints = getPointsAsFloat(tabPointsReversed); final float thickness = (float) component.getThickness(); boolean hasTabs = component.getTabLength() > 0 && component.getTabHeight() > 0; - final Coordinate[] locations = component.getComponentLocations(); - final Coordinate[] angles = component.getComponentAngles(); - - if (locations.length != angles.length) { - throw new IllegalArgumentException("Number of locations and angles must match"); - } // Generate the fin meshes - for (int i = 0; i < locations.length; i++) { - generateMesh(floatPoints, floatTabPoints, thickness, hasTabs, locations[i], angles[i]); + for (InstanceContext context : config.getActiveInstances().getInstanceContexts(component)) { + generateMesh(floatPoints, floatTabPoints, thickness, hasTabs, context); } } private void generateMesh(FloatPoints floatPoints, FloatPoints floatTabPoints, float thickness, - boolean hasTabs, Coordinate location, Coordinate angle) { + boolean hasTabs, InstanceContext context) { // Generate the mesh final int startIdx = obj.getNumVertices(); final int normalsStartIdx = obj.getNumNormals(); @@ -77,12 +73,16 @@ public class FinSetExporter extends RocketComponentExporter { orig.getX(), orig.getY(), orig.getZ()); // Then do the component rotation (axial rotation) - rot = transformer.convertRot(angle.x, angle.y, angle.z); + final double rotX = context.transform.getXrotation(); + final double rotY = context.transform.getYrotation(); + final double rotZ = context.transform.getZrotation(); + rot = transformer.convertRot(rotX, rotY, rotZ); ObjUtils.rotateVertices(obj, startIdx, endIdx, normalsStartIdx, normalsEndIdx, rot.getX(), rot.getY(), rot.getZ(), orig.getX(), orig.getY(), orig.getZ()); // Translate the mesh to the position in the rocket + final Coordinate location = context.getLocation(); ObjUtils.translateVerticesFromComponentLocation(obj, transformer, startIdx, endIdx, location); } diff --git a/core/src/net/sf/openrocket/file/wavefrontobj/export/components/LaunchLugExporter.java b/core/src/net/sf/openrocket/file/wavefrontobj/export/components/LaunchLugExporter.java index e9880fdac..15b4a69c4 100644 --- a/core/src/net/sf/openrocket/file/wavefrontobj/export/components/LaunchLugExporter.java +++ b/core/src/net/sf/openrocket/file/wavefrontobj/export/components/LaunchLugExporter.java @@ -6,29 +6,30 @@ import net.sf.openrocket.file.wavefrontobj.DefaultObj; import net.sf.openrocket.file.wavefrontobj.ObjUtils; import net.sf.openrocket.file.wavefrontobj.export.shapes.CylinderExporter; import net.sf.openrocket.file.wavefrontobj.export.shapes.TubeExporter; +import net.sf.openrocket.rocketcomponent.FlightConfiguration; +import net.sf.openrocket.rocketcomponent.InstanceContext; import net.sf.openrocket.rocketcomponent.LaunchLug; import net.sf.openrocket.util.Coordinate; public class LaunchLugExporter extends RocketComponentExporter { - public LaunchLugExporter(@NotNull DefaultObj obj, @NotNull CoordTransform transformer, LaunchLug component, - String groupName, ObjUtils.LevelOfDetail LOD) { - super(obj, transformer, component, groupName, LOD); + public LaunchLugExporter(@NotNull DefaultObj obj, FlightConfiguration config, @NotNull CoordTransform transformer, + LaunchLug component, String groupName, ObjUtils.LevelOfDetail LOD) { + super(obj, config, transformer, component, groupName, LOD); } @Override public void addToObj() { - final Coordinate[] locations = component.getComponentLocations(); final float outerRadius = (float) component.getOuterRadius(); final float innerRadius = (float) component.getInnerRadius(); final float length = (float) component.getLength(); // Generate the mesh - for (Coordinate location : locations) { - generateMesh(outerRadius, innerRadius, length, location); + for (InstanceContext context : config.getActiveInstances().getInstanceContexts(component)) { + generateMesh(outerRadius, innerRadius, length, context); } } - private void generateMesh(float outerRadius, float innerRadius, float length, Coordinate location) { + private void generateMesh(float outerRadius, float innerRadius, float length, InstanceContext context) { int startIdx = obj.getNumVertices(); // Generate the instance mesh @@ -45,6 +46,7 @@ public class LaunchLugExporter extends RocketComponentExporter { int endIdx = Math.max(obj.getNumVertices() - 1, startIdx); // Clamp in case no vertices were added // Translate the mesh to the position in the rocket + final Coordinate location = context.getLocation(); ObjUtils.translateVerticesFromComponentLocation(obj, transformer, startIdx, endIdx, location); } } diff --git a/core/src/net/sf/openrocket/file/wavefrontobj/export/components/MassObjectExporter.java b/core/src/net/sf/openrocket/file/wavefrontobj/export/components/MassObjectExporter.java index 7ae605048..c1eb0acb9 100644 --- a/core/src/net/sf/openrocket/file/wavefrontobj/export/components/MassObjectExporter.java +++ b/core/src/net/sf/openrocket/file/wavefrontobj/export/components/MassObjectExporter.java @@ -5,31 +5,32 @@ import net.sf.openrocket.file.wavefrontobj.CoordTransform; import net.sf.openrocket.file.wavefrontobj.DefaultObj; import net.sf.openrocket.file.wavefrontobj.DefaultObjFace; import net.sf.openrocket.file.wavefrontobj.ObjUtils; +import net.sf.openrocket.rocketcomponent.FlightConfiguration; +import net.sf.openrocket.rocketcomponent.InstanceContext; import net.sf.openrocket.rocketcomponent.MassObject; import net.sf.openrocket.util.Coordinate; import net.sf.openrocket.util.RocketComponentUtils; public class MassObjectExporter extends RocketComponentExporter { - public MassObjectExporter(@NotNull DefaultObj obj, @NotNull CoordTransform transformer, MassObject component, - String groupName, ObjUtils.LevelOfDetail LOD) { - super(obj, transformer, component, groupName, LOD); + public MassObjectExporter(@NotNull DefaultObj obj, FlightConfiguration config, @NotNull CoordTransform transformer, + MassObject component, String groupName, ObjUtils.LevelOfDetail LOD) { + super(obj, config, transformer, component, groupName, LOD); } @Override public void addToObj() { obj.setActiveGroupNames(groupName); - final Coordinate[] locations = component.getComponentLocations(); final int numSides = LOD.getValue() / 2; final int numStacks = LOD.getValue() / 2; // Generate the mesh - for (Coordinate location : locations) { - generateMesh(numSides, numStacks, location); + for (InstanceContext context : config.getActiveInstances().getInstanceContexts(component)) { + generateMesh(numSides, numStacks, context); } } - private void generateMesh(int numSides, int numStacks, Coordinate location) { + private void generateMesh(int numSides, int numStacks, InstanceContext context) { // Other meshes may have been added to the obj, so we need to keep track of the starting indices int startIdx = obj.getNumVertices(); int normalsStartIdx = obj.getNumNormals(); @@ -134,6 +135,7 @@ public class MassObjectExporter extends RocketComponentExporter { // Translate the mesh to the position in the rocket // We will create an offset location that has the same effect as the axial rotation of the mass object + final Coordinate location = context.getLocation(); Coordinate offsetLocation = getOffsetLocation(location); ObjUtils.translateVerticesFromComponentLocation(obj, transformer, startIdx, endIdx, offsetLocation); } diff --git a/core/src/net/sf/openrocket/file/wavefrontobj/export/components/RailButtonExporter.java b/core/src/net/sf/openrocket/file/wavefrontobj/export/components/RailButtonExporter.java index 0d0178b78..ba58410da 100644 --- a/core/src/net/sf/openrocket/file/wavefrontobj/export/components/RailButtonExporter.java +++ b/core/src/net/sf/openrocket/file/wavefrontobj/export/components/RailButtonExporter.java @@ -8,6 +8,8 @@ import net.sf.openrocket.file.wavefrontobj.DefaultObjFace; import net.sf.openrocket.file.wavefrontobj.ObjUtils; import net.sf.openrocket.file.wavefrontobj.export.shapes.CylinderExporter; import net.sf.openrocket.file.wavefrontobj.export.shapes.DiskExporter; +import net.sf.openrocket.rocketcomponent.FlightConfiguration; +import net.sf.openrocket.rocketcomponent.InstanceContext; import net.sf.openrocket.rocketcomponent.RailButton; import net.sf.openrocket.util.Coordinate; @@ -23,9 +25,9 @@ public class RailButtonExporter extends RocketComponentExporter { * @param groupName The name of the group to export to * @param LOD Level of detail to use for the export (e.g. '80') */ - public RailButtonExporter(@NotNull DefaultObj obj, @NotNull CoordTransform transformer, RailButton component, - String groupName, ObjUtils.LevelOfDetail LOD) { - super(obj, transformer, component, groupName, LOD); + public RailButtonExporter(@NotNull DefaultObj obj, FlightConfiguration config, @NotNull CoordTransform transformer, + RailButton component, String groupName, ObjUtils.LevelOfDetail LOD) { + super(obj, config, transformer, component, groupName, LOD); } @Override @@ -38,18 +40,15 @@ public class RailButtonExporter extends RocketComponentExporter { final float innerHeight = (float) component.getInnerHeight(); final float flangeHeight = (float) component.getFlangeHeight(); final float screwHeight = (float) component.getScrewHeight(); - final Coordinate[] locations = component.getComponentLocations(); - final Coordinate[] angles = component.getComponentAngles(); // Generate the mesh - for (int i = 0; i < locations.length; i++) { - generateMesh(outerRadius, innerRadius, baseHeight, innerHeight, flangeHeight, screwHeight, - locations[i], angles[i]); + for (InstanceContext context : config.getActiveInstances().getInstanceContexts(component)) { + generateMesh(outerRadius, innerRadius, baseHeight, innerHeight, flangeHeight, screwHeight, context); } } private void generateMesh(float outerRadius, float innerRadius, float baseHeight, float innerHeight, float flangeHeight, - float screwHeight, Coordinate location, Coordinate angle) { + float screwHeight, InstanceContext context) { final int startIdx = obj.getNumVertices(); final int normalStartIdx = obj.getNumNormals(); @@ -109,16 +108,17 @@ public class RailButtonExporter extends RocketComponentExporter { rot.getX(), rot.getY(), rot.getZ(), orig.getX(), orig.getY(), orig.getZ()); - // Then do the axial rotation - rX = angle.x + component.getAngleOffset(); - rY = 0; - rZ = 0; - rot = transformer.convertRot(rX, rY, rZ); + // Then do the component rotation (axial rotation) + final double rotX = context.transform.getXrotation() + component.getAngleOffset(); + final double rotY = context.transform.getYrotation(); + final double rotZ = context.transform.getZrotation(); + rot = transformer.convertRot(rotX, rotY, rotZ); ObjUtils.rotateVertices(obj, startIdx, endIdx, normalStartIdx, normalEndIdx, rot.getX(), rot.getY(), rot.getZ(), orig.getX(), orig.getY(), orig.getZ()); // Translate the mesh to the position in the rocket + final Coordinate location = context.getLocation(); ObjUtils.translateVerticesFromComponentLocation(obj, transformer, startIdx, endIdx, location); } diff --git a/core/src/net/sf/openrocket/file/wavefrontobj/export/components/RingComponentExporter.java b/core/src/net/sf/openrocket/file/wavefrontobj/export/components/RingComponentExporter.java index d13e7202b..ff54c9c01 100644 --- a/core/src/net/sf/openrocket/file/wavefrontobj/export/components/RingComponentExporter.java +++ b/core/src/net/sf/openrocket/file/wavefrontobj/export/components/RingComponentExporter.java @@ -6,13 +6,15 @@ import net.sf.openrocket.file.wavefrontobj.DefaultObj; import net.sf.openrocket.file.wavefrontobj.ObjUtils; import net.sf.openrocket.file.wavefrontobj.export.shapes.CylinderExporter; import net.sf.openrocket.file.wavefrontobj.export.shapes.TubeExporter; +import net.sf.openrocket.rocketcomponent.FlightConfiguration; +import net.sf.openrocket.rocketcomponent.InstanceContext; import net.sf.openrocket.rocketcomponent.RingComponent; import net.sf.openrocket.util.Coordinate; public class RingComponentExporter extends RocketComponentExporter { - public RingComponentExporter(@NotNull DefaultObj obj, @NotNull CoordTransform transformer, RingComponent component, - String groupName, ObjUtils.LevelOfDetail LOD) { - super(obj, transformer, component, groupName, LOD); + public RingComponentExporter(@NotNull DefaultObj obj, FlightConfiguration config, @NotNull CoordTransform transformer, + RingComponent component, String groupName, ObjUtils.LevelOfDetail LOD) { + super(obj, config, transformer, component, groupName, LOD); } @Override @@ -20,15 +22,14 @@ public class RingComponentExporter extends RocketComponentExporter { protected final DefaultObj obj; + protected final FlightConfiguration config; protected final T component; protected final String groupName; protected final ObjUtils.LevelOfDetail LOD; @@ -23,14 +25,16 @@ public abstract class RocketComponentExporter { /** * Wavefront OBJ exporter for a rocket component. * @param obj The OBJ to export to + * @param config The flight configuration to use for the export * @param transformer Coordinate system transformer to use to switch from the OpenRocket coordinate system to a custom OBJ coordinate system * @param component The component to export * @param groupName The name of the group to export to * @param LOD Level of detail to use for the export (e.g. '80') */ - public RocketComponentExporter(@NotNull DefaultObj obj, @NotNull CoordTransform transformer, T component, - String groupName, ObjUtils.LevelOfDetail LOD) { + public RocketComponentExporter(@NotNull DefaultObj obj, @NotNull FlightConfiguration config, @NotNull CoordTransform transformer, + T component, String groupName, ObjUtils.LevelOfDetail LOD) { this.obj = obj; + this.config = config; this.component = component; this.groupName = groupName; this.LOD = LOD; diff --git a/core/src/net/sf/openrocket/file/wavefrontobj/export/components/TransitionExporter.java b/core/src/net/sf/openrocket/file/wavefrontobj/export/components/TransitionExporter.java index 8c41955ba..28c5365ad 100644 --- a/core/src/net/sf/openrocket/file/wavefrontobj/export/components/TransitionExporter.java +++ b/core/src/net/sf/openrocket/file/wavefrontobj/export/components/TransitionExporter.java @@ -9,6 +9,8 @@ import net.sf.openrocket.file.wavefrontobj.ObjUtils; import net.sf.openrocket.file.wavefrontobj.export.shapes.CylinderExporter; import net.sf.openrocket.file.wavefrontobj.export.shapes.DiskExporter; import net.sf.openrocket.file.wavefrontobj.export.shapes.TubeExporter; +import net.sf.openrocket.rocketcomponent.FlightConfiguration; +import net.sf.openrocket.rocketcomponent.InstanceContext; import net.sf.openrocket.rocketcomponent.Transition; import net.sf.openrocket.util.Coordinate; @@ -19,9 +21,9 @@ public class TransitionExporter extends RocketComponentExporter { private static final double RADIUS_EPSILON = 1e-4; private final int nrOfSides; - public TransitionExporter(@NotNull DefaultObj obj, @NotNull CoordTransform transformer, Transition component, - String groupName, ObjUtils.LevelOfDetail LOD) { - super(obj, transformer, component, groupName, LOD); + public TransitionExporter(@NotNull DefaultObj obj, FlightConfiguration config, @NotNull CoordTransform transformer, + Transition component, String groupName, ObjUtils.LevelOfDetail LOD) { + super(obj, config, transformer, component, groupName, LOD); this.nrOfSides = LOD.getNrOfSides(Math.max(component.getForeRadius(), component.getAftRadius())); } @@ -29,15 +31,13 @@ public class TransitionExporter extends RocketComponentExporter { public void addToObj() { obj.setActiveGroupNames(groupName); - final Coordinate[] locations = component.getComponentLocations(); - // Generate the mesh - for (Coordinate location : locations) { - generateMesh(location); + for (InstanceContext context : config.getActiveInstances().getInstanceContexts(component)) { + generateMesh(context); } } - private void generateMesh(Coordinate location) { + private void generateMesh(InstanceContext context) { int startIdx = obj.getNumVertices(); final boolean hasForeShoulder = Double.compare(component.getForeShoulderRadius(), 0) > 0 @@ -99,6 +99,7 @@ public class TransitionExporter extends RocketComponentExporter { int endIdx = Math.max(obj.getNumVertices() - 1, startIdx); // Clamp in case no vertices were added // Translate the mesh to the position in the rocket + final Coordinate location = context.getLocation(); ObjUtils.translateVerticesFromComponentLocation(obj, transformer, startIdx, endIdx, location); } diff --git a/core/src/net/sf/openrocket/file/wavefrontobj/export/components/TubeFinSetExporter.java b/core/src/net/sf/openrocket/file/wavefrontobj/export/components/TubeFinSetExporter.java index 30c831f0f..30175d809 100644 --- a/core/src/net/sf/openrocket/file/wavefrontobj/export/components/TubeFinSetExporter.java +++ b/core/src/net/sf/openrocket/file/wavefrontobj/export/components/TubeFinSetExporter.java @@ -5,13 +5,15 @@ import net.sf.openrocket.file.wavefrontobj.CoordTransform; import net.sf.openrocket.file.wavefrontobj.DefaultObj; import net.sf.openrocket.file.wavefrontobj.ObjUtils; import net.sf.openrocket.file.wavefrontobj.export.shapes.TubeExporter; +import net.sf.openrocket.rocketcomponent.FlightConfiguration; +import net.sf.openrocket.rocketcomponent.InstanceContext; import net.sf.openrocket.rocketcomponent.TubeFinSet; import net.sf.openrocket.util.Coordinate; public class TubeFinSetExporter extends RocketComponentExporter { - public TubeFinSetExporter(@NotNull DefaultObj obj, @NotNull CoordTransform transformer, TubeFinSet component, String groupName, - ObjUtils.LevelOfDetail LOD) { - super(obj, transformer, component, groupName, LOD); + public TubeFinSetExporter(@NotNull DefaultObj obj, FlightConfiguration config, @NotNull CoordTransform transformer, + TubeFinSet component, String groupName, ObjUtils.LevelOfDetail LOD) { + super(obj, config, transformer, component, groupName, LOD); } @Override @@ -21,20 +23,14 @@ public class TubeFinSetExporter extends RocketComponentExporter { final float outerRadius = (float) component.getOuterRadius(); final float innerRadius = (float) component.getInnerRadius(); final float length = (float) component.getLength(); - final Coordinate[] locations = component.getComponentLocations(); - final double[] angles = component.getInstanceAngles(); - - if (locations.length != angles.length) { - throw new IllegalArgumentException("Number of locations and angles must match"); - } // Generate the fin meshes - for (int i = 0; i < locations.length; i++) { - generateMesh(outerRadius, innerRadius, length, locations[i], angles[i]); + for (InstanceContext context : config.getActiveInstances().getInstanceContexts(component)) { + generateMesh(outerRadius, innerRadius, length, context); } } - private void generateMesh(float outerRadius, float innerRadius, float length, Coordinate location, double angle) { + private void generateMesh(float outerRadius, float innerRadius, float length, InstanceContext context) { // Create the fin meshes final int startIdx = obj.getNumVertices(); @@ -45,14 +41,16 @@ public class TubeFinSetExporter extends RocketComponentExporter { // Translate the mesh to the position in the rocket // We will create an offset location that has the same effect as the axial rotation of the launch lug - Coordinate offsetLocation = getOffsetLocation(outerRadius, location, angle); + final double rotX = context.transform.getXrotation(); + final Coordinate location = context.getLocation(); + Coordinate offsetLocation = getOffsetLocation(outerRadius, location, rotX); ObjUtils.translateVerticesFromComponentLocation(obj, transformer, startIdx, endIdx, offsetLocation); } - private static Coordinate getOffsetLocation(float outerRadius, Coordinate location, double angle) { + private static Coordinate getOffsetLocation(float outerRadius, Coordinate location, double rotX) { // ! This is all still referenced to the OpenRocket coordinate system, not the OBJ one - final float dy = outerRadius * (float) Math.cos(angle); - final float dz = outerRadius * (float) Math.sin(angle); + final float dy = outerRadius * (float) Math.cos(rotX); + final float dz = outerRadius * (float) Math.sin(rotX); final double x = location.x; final double y = location.y + dy; final double z = location.z + dz;