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 1da464f47..34fd085a7 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 @@ -31,7 +31,7 @@ public class FinSetExporter extends RocketComponentExporter { final float thickness = (float) component.getThickness(); boolean hasTabs = component.getTabLength() > 0 && component.getTabHeight() > 0; final Coordinate[] locations = component.getComponentLocations(); - final double[] angles = component.getComponentAngles(); + final Coordinate[] angles = component.getComponentAngles(); if (locations.length != angles.length) { throw new IllegalArgumentException("Number of locations and angles must match"); @@ -44,7 +44,7 @@ public class FinSetExporter extends RocketComponentExporter { } private void generateMesh(FloatPoints floatPoints, FloatPoints floatTabPoints, float thickness, - boolean hasTabs, Coordinate location, double angle) { + boolean hasTabs, Coordinate location, Coordinate angle) { // Generate the mesh final int startIdx = obj.getNumVertices(); final int normalsStartIdx = obj.getNumNormals(); @@ -68,7 +68,7 @@ public class FinSetExporter extends RocketComponentExporter { cantAngle, 0, 0, 0, (float) -component.getLength(), 0); // Then do the axial rotation - final float axialRot = (float) angle; + final float axialRot = (float) angle.x; ObjUtils.rotateVertices(obj, startIdx, endIdx, normalsStartIdx, normalsEndIdx, 0, axialRot, 0, 0, 0, 0); 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 d24314f2b..a58594d4d 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 @@ -37,7 +37,7 @@ public class RailButtonExporter extends RocketComponentExporter { final float flangeHeight = (float) component.getFlangeHeight(); final float screwHeight = (float) component.getScrewHeight(); final Coordinate[] locations = component.getComponentLocations(); - final double[] angles = component.getComponentAngles(); + final Coordinate[] angles = component.getComponentAngles(); // Generate the mesh for (int i = 0; i < locations.length; i++) { @@ -47,7 +47,7 @@ public class RailButtonExporter extends RocketComponentExporter { } private void generateMesh(float outerRadius, float innerRadius, float baseHeight, float innerHeight, float flangeHeight, - float screwHeight, Coordinate location, double angle) { + float screwHeight, Coordinate location, Coordinate angle) { final int startIdx = obj.getNumVertices(); final int normalStartIdx = obj.getNumNormals(); @@ -97,7 +97,7 @@ public class RailButtonExporter extends RocketComponentExporter { // Rotate the mesh (also PI/2!) final float rX = 0; - final float rY = (float) angle; + final float rY = (float) angle.x; final float rZ = (float) - Math.PI / 2; ObjUtils.rotateVertices(obj, startIdx, endIdx, normalStartIdx, normalEndIdx, rX, rY, rZ, 0, 0, 0); diff --git a/core/src/net/sf/openrocket/rocketcomponent/RocketComponent.java b/core/src/net/sf/openrocket/rocketcomponent/RocketComponent.java index 18ae98f3c..b14eeddcb 100644 --- a/core/src/net/sf/openrocket/rocketcomponent/RocketComponent.java +++ b/core/src/net/sf/openrocket/rocketcomponent/RocketComponent.java @@ -1598,34 +1598,51 @@ public abstract class RocketComponent implements ChangeSource, Cloneable, Iterab * 3-instance pod set will return 6 locations, not 2 * * @return Coordinates of all instance angles in the rocket, relative to the rocket's origin + * x-component = rotation around x-axis, y = around y-axis, and z around z-axis + * !!! OpenRocket rotations follow left-hand rule of rotation !!! */ - public double[] getComponentAngles() { + public Coordinate[] getComponentAngles() { if (this.parent == null) { // == improperly initialized components OR the root Rocket instance - return getInstanceAngles(); + return axialRotToCoord(getInstanceAngles()); } else { - double[] parentAngles = this.parent.getComponentAngles(); + Coordinate[] parentAngles = this.parent.getComponentAngles(); int parentCount = parentAngles.length; // override .getInstanceAngles() in each subclass - double[] instanceAngles = this.getInstanceAngles(); + Coordinate[] instanceAngles = axialRotToCoord(this.getInstanceAngles()); int instanceCount = instanceAngles.length; // usual case optimization if ((parentCount == 1) && (instanceCount == 1)) { - return new double[]{parentAngles[0] + instanceAngles[0]}; + return new Coordinate[] {parentAngles[0].add(instanceAngles[0])}; } int thisCount = instanceCount * parentCount; - double[] theseAngles = new double[thisCount]; + Coordinate[] theseAngles = new Coordinate[thisCount]; for (int pi = 0; pi < parentCount; pi++) { for (int ii = 0; ii < instanceCount; ii++) { - theseAngles[pi + parentCount*ii] = parentAngles[pi] + instanceAngles[ii]; + theseAngles[pi + parentCount*ii] = parentAngles[pi].add(instanceAngles[ii]); } } return theseAngles; } } + + /** + * Converts an array of axial angles to an array of coordinates. + * x-component = rotation around x-axis, y = around y-axis, and z around z-axis + * !!! OpenRocket rotations follow left-hand rule of rotation !!! + * @param angles array of axial angles + * @return array of coordinates + */ + private Coordinate[] axialRotToCoord(double[] angles) { + Coordinate[] coords = new Coordinate[angles.length]; + for (int i = 0; i < angles.length; i++) { + coords[i] = new Coordinate(angles[i], 0, 0); + } + return coords; + } /////////// Coordinate changes ///////////