From 7ebed840b68c31bd2b3e2ed3acc6779890af779c Mon Sep 17 00:00:00 2001 From: SiboVG Date: Mon, 14 Aug 2023 02:20:16 +0200 Subject: [PATCH] Refactor tube exporter to use cylinder exporter --- .../export/components/BodyTubeExporter.java | 16 +- .../export/components/LaunchLugExporter.java | 14 +- .../export/components/RailButtonExporter.java | 28 ++-- .../components/RingComponentExporter.java | 13 +- .../export/components/TransitionExporter.java | 28 ++-- .../export/shapes/CylinderExporter.java | 37 +++-- .../export/shapes/TubeExporter.java | 141 +++++------------- .../export/OBJExporterFactoryTest.java | 47 ++---- 8 files changed, 113 insertions(+), 211 deletions(-) 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 c159ce025..1ffcdde6b 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 @@ -29,20 +29,10 @@ public class BodyTubeExporter extends RocketComponentExporter { } } - private void generateMesh(float outerRadius, float innerRadius, float length, boolean isFilled, - InstanceContext context) { + private void generateMesh(float outerRadius, float innerRadius, float length, boolean isFilled, InstanceContext context) { + // Generate the mesh int startIdx = obj.getNumVertices(); - - if (isFilled || Float.compare(innerRadius, 0) == 0) { - CylinderExporter.addCylinderMesh(obj, transformer, groupName, outerRadius, length, true, LOD); - } else { - if (Float.compare(innerRadius, outerRadius) == 0) { - CylinderExporter.addCylinderMesh(obj, transformer, groupName, outerRadius, length, false, LOD); - } else { - TubeExporter.addTubeMesh(obj, transformer, groupName, outerRadius, innerRadius, length, LOD); - } - } - + TubeExporter.addTubeMesh(obj, transformer, groupName, outerRadius, isFilled ? 0 : 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 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 15b4a69c4..0ca3d14eb 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 @@ -30,19 +30,9 @@ public class LaunchLugExporter extends RocketComponentExporter { } private void generateMesh(float outerRadius, float innerRadius, float length, InstanceContext context) { + // Generate the mesh int startIdx = obj.getNumVertices(); - - // Generate the instance mesh - if (Float.compare(innerRadius, 0) == 0) { - CylinderExporter.addCylinderMesh(obj, transformer, groupName, outerRadius, length, true, LOD); - } else { - if (Float.compare(innerRadius, outerRadius) == 0) { - CylinderExporter.addCylinderMesh(obj, transformer, groupName, outerRadius, length, false, LOD); - } else { - TubeExporter.addTubeMesh(obj, transformer, groupName, outerRadius, innerRadius, length, LOD); - } - } - + TubeExporter.addTubeMesh(obj, transformer, groupName, 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 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 ba58410da..a74a567a4 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 @@ -53,45 +53,45 @@ public class RailButtonExporter extends RocketComponentExporter { final int normalStartIdx = obj.getNumNormals(); // Generate base cylinder - List baseCylinderBottomVertices = new ArrayList<>(); - List baseCylinderTopVertices = new ArrayList<>(); + List baseCylinderForeVertices = new ArrayList<>(); + List baseCylinderAftVertices = new ArrayList<>(); CylinderExporter.addCylinderMesh(obj, transformer, null, outerRadius, baseHeight, false, LOD, - baseCylinderBottomVertices, baseCylinderTopVertices); + baseCylinderForeVertices, baseCylinderAftVertices); // Generate inner cylinder int tmpStartIdx = obj.getNumVertices(); - List innerCylinderBottomVertices = new ArrayList<>(); - List innerCylinderTopVertices = new ArrayList<>(); + List innerCylinderForeVertices = new ArrayList<>(); + List innerCylinderAftVertices = new ArrayList<>(); CylinderExporter.addCylinderMesh(obj, transformer, null, innerRadius, innerHeight, false, LOD, - innerCylinderBottomVertices, innerCylinderTopVertices); + innerCylinderForeVertices, innerCylinderAftVertices); int tmpEndIdx = Math.max(obj.getNumVertices() - 1, tmpStartIdx); FloatTuple locOffs = transformer.convertLocWithoutOriginOffs(baseHeight, 0, 0); ObjUtils.translateVertices(obj, tmpStartIdx, tmpEndIdx, locOffs.getX(), locOffs.getY(), locOffs.getZ()); // Generate flange cylinder tmpStartIdx = obj.getNumVertices(); - List flangeCylinderBottomVertices = new ArrayList<>(); - List flangeCylinderTopVertices = new ArrayList<>(); + List flangeCylinderForeVertices = new ArrayList<>(); + List flangeCylinderAftVertices = new ArrayList<>(); CylinderExporter.addCylinderMesh(obj, transformer, null, outerRadius, flangeHeight, false, LOD, - flangeCylinderBottomVertices, flangeCylinderTopVertices); + flangeCylinderForeVertices, flangeCylinderAftVertices); tmpEndIdx = Math.max(obj.getNumVertices() - 1, tmpStartIdx); locOffs = transformer.convertLocWithoutOriginOffs(baseHeight + innerHeight, 0, 0); ObjUtils.translateVertices(obj, tmpStartIdx, tmpEndIdx, locOffs.getX(), locOffs.getY(), locOffs.getZ()); // Generate base disk - DiskExporter.closeDiskMesh(obj, transformer, null, baseCylinderTopVertices, false, true); + DiskExporter.closeDiskMesh(obj, transformer, null, baseCylinderForeVertices, false, true); // Generate base inner disk - DiskExporter.closeDiskMesh(obj, transformer, null, baseCylinderBottomVertices, innerCylinderTopVertices, false, false); + DiskExporter.closeDiskMesh(obj, transformer, null, baseCylinderAftVertices, innerCylinderForeVertices, false, false); // Generate flange inner disk - DiskExporter.closeDiskMesh(obj, transformer, null, innerCylinderBottomVertices, flangeCylinderTopVertices, true, true); + DiskExporter.closeDiskMesh(obj, transformer, null, innerCylinderAftVertices, flangeCylinderForeVertices, true, true); // Generate flange disk/screw if (Float.compare(screwHeight, 0) == 0) { - DiskExporter.closeDiskMesh(obj, transformer, null, flangeCylinderBottomVertices, false, false); + DiskExporter.closeDiskMesh(obj, transformer, null, flangeCylinderAftVertices, false, false); } else { - addScrew(obj, baseHeight, innerHeight, flangeHeight, outerRadius, screwHeight, LOD, flangeCylinderBottomVertices); + addScrew(obj, baseHeight, innerHeight, flangeHeight, outerRadius, screwHeight, LOD, flangeCylinderAftVertices); } 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 ff54c9c01..347cc5f94 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 @@ -30,18 +30,9 @@ public class RingComponentExporter extends RocketComponentExporter { float outerFore = (float) component.getForeRadius(); float innerFore = (float) (component.getForeRadius() - component.getThickness()); - TubeExporter.addTubeMesh(obj, transformer, null, outerAft, outerFore, innerAft, innerFore, + TubeExporter.addTubeMesh(obj, transformer, null, outerFore, outerAft, innerFore, innerAft, (float) component.getLength(), this.nrOfSides, - outsideAftRingVertices, outsideForeRingVertices, insideAftRingVertices, insideForeRingVertices); + outsideForeRingVertices, outsideAftRingVertices, insideForeRingVertices, insideAftRingVertices); } // Otherwise, use complex geometry else { @@ -370,10 +370,10 @@ public class TransitionExporter extends RocketComponentExporter { private void addShoulder(float shoulderRadius, float shoulderLength, float shoulderThickness, boolean isCapped, boolean isForeSide, int nrOfSides, List outerRingVertices, List innerRingVertices) { final float innerCylinderRadius = isCapped ? 0 : shoulderRadius - shoulderThickness; - final List outerCylinderBottomVertices = new ArrayList<>(); - final List outerCylinderTopVertices = new ArrayList<>(); - final List innerCylinderBottomVertices = isCapped ? null : new ArrayList<>(); - final List innerCylinderTopVertices = isCapped ? null : new ArrayList<>(); + final List outerCylinderForeVertices = new ArrayList<>(); + final List outerCylinderAftVertices = new ArrayList<>(); + final List innerCylinderForeVertices = isCapped ? null : new ArrayList<>(); + final List innerCylinderAftVertices = isCapped ? null : new ArrayList<>(); int startIdx; int endIdx; @@ -403,7 +403,7 @@ public class TransitionExporter extends RocketComponentExporter { // Generate outer cylinder (no. 3) startIdx = obj.getNumVertices(); CylinderExporter.addCylinderMesh(obj, transformer, null, shoulderRadius, shoulderLength, - false, nrOfSides, outerCylinderBottomVertices, outerCylinderTopVertices); + false, nrOfSides, outerCylinderForeVertices, outerCylinderAftVertices); endIdx = Math.max(obj.getNumVertices() - 1, startIdx); // Translate the outer cylinder to the correct position @@ -415,7 +415,7 @@ public class TransitionExporter extends RocketComponentExporter { if (!isCapped) { startIdx = obj.getNumVertices(); CylinderExporter.addCylinderMesh(obj, transformer, null, innerCylinderRadius, shoulderLength + shoulderThickness, - false, false, nrOfSides, innerCylinderBottomVertices, innerCylinderTopVertices); + false, false, nrOfSides, innerCylinderForeVertices, innerCylinderAftVertices); endIdx = Math.max(obj.getNumVertices() - 1, startIdx); // Translate the outer cylinder to the correct position @@ -426,23 +426,23 @@ public class TransitionExporter extends RocketComponentExporter { // Generate shoulder top disk (no. 4) if (isForeSide) { - DiskExporter.closeDiskMesh(obj, transformer, null, outerCylinderTopVertices, innerCylinderTopVertices, false, true); + DiskExporter.closeDiskMesh(obj, transformer, null, outerCylinderForeVertices, innerCylinderForeVertices, false, true); } else { - DiskExporter.closeDiskMesh(obj, transformer, null, outerCylinderBottomVertices, innerCylinderBottomVertices, false, false); + DiskExporter.closeDiskMesh(obj, transformer, null, outerCylinderAftVertices, innerCylinderAftVertices, false, false); } // Generate transition outer disk (no. 5) if (isForeSide) { - DiskExporter.closeDiskMesh(obj, transformer, null, outerRingVertices, outerCylinderBottomVertices, false, true); + DiskExporter.closeDiskMesh(obj, transformer, null, outerRingVertices, outerCylinderAftVertices, false, true); } else { - DiskExporter.closeDiskMesh(obj, transformer, null, outerRingVertices, outerCylinderTopVertices, false, false); + DiskExporter.closeDiskMesh(obj, transformer, null, outerRingVertices, outerCylinderForeVertices, false, false); } // Generate transition inner disk (no. 6) if (isForeSide) { - DiskExporter.closeDiskMesh(obj, transformer, null, innerRingVertices, innerCylinderBottomVertices, false, false); + DiskExporter.closeDiskMesh(obj, transformer, null, innerRingVertices, innerCylinderAftVertices, false, false); } else { - DiskExporter.closeDiskMesh(obj, transformer, null, innerRingVertices, innerCylinderTopVertices, false, true); + DiskExporter.closeDiskMesh(obj, transformer, null, innerRingVertices, innerCylinderForeVertices, false, true); } } diff --git a/core/src/net/sf/openrocket/file/wavefrontobj/export/shapes/CylinderExporter.java b/core/src/net/sf/openrocket/file/wavefrontobj/export/shapes/CylinderExporter.java index 957ed1db4..179b5fca5 100644 --- a/core/src/net/sf/openrocket/file/wavefrontobj/export/shapes/CylinderExporter.java +++ b/core/src/net/sf/openrocket/file/wavefrontobj/export/shapes/CylinderExporter.java @@ -14,19 +14,20 @@ public class CylinderExporter { * @param obj The obj to add the mesh to * @param transformer The coordinate system transformer to use to switch from the OpenRocket coordinate system to a custom OBJ coordinate system * @param groupName The name of the group to add the mesh to, or null if no group should be added (use the active group) - * @param radius The radius of the cylinder + * @param foreRadius The fore (top) radius of the cylinder + * @param aftRadius The aft (bottom) radius of the cylinder * @param length The length of the cylinder * @param numSides The number of sides of the cylinder * @param solid Whether the cylinder should be solid (true) or hollow (false) * NOTE: Culling is not really thought of for the hollow cylinder; this mode is really meant to be * combined with other objects * @param isOutside Whether the cylinder is an outside face (true) or inside face (false) - * @param bottomRingVertices A list to add the bottom ring vertex indices to - * @param topRingVertices A list to add the top ring vertex indices to + * @param foreRingVertices A list to add the fore (top) ring vertex indices to + * @param aftRingVertices A list to add the aft (bottom) ring vertex indices to */ public static void addCylinderMesh(@NotNull DefaultObj obj, @NotNull CoordTransform transformer, String groupName, - float radius, float length, int numSides, boolean solid, boolean isOutside, - List bottomRingVertices, List topRingVertices) { + float foreRadius, float aftRadius, float length, int numSides, boolean solid, boolean isOutside, + List foreRingVertices, List aftRingVertices) { // Set the new group if (groupName != null) { obj.setActiveGroupNames(groupName); @@ -47,10 +48,10 @@ public class CylinderExporter { } // Generate side top vertices - generateRingVertices(obj, transformer, startIdx, numSides, 0, radius, isOutside, topRingVertices); + generateRingVertices(obj, transformer, startIdx, numSides, 0, foreRadius, isOutside, foreRingVertices); // Generate side bottom vertices - generateRingVertices(obj, transformer, startIdx + numSides, numSides, length, radius, isOutside, bottomRingVertices); + generateRingVertices(obj, transformer, startIdx + numSides, numSides, length, aftRadius, isOutside, aftRingVertices); // Create faces for the bottom and top if (solid) { @@ -111,28 +112,34 @@ public class CylinderExporter { } } + public static void addCylinderMesh(@NotNull DefaultObj obj, @NotNull CoordTransform transformer, String groupName, + float radius, float length, int numSides, boolean solid, boolean isOutside, + List foreRingVertices, List aftRingVertices) { + addCylinderMesh(obj, transformer, groupName, radius, radius, length, numSides, solid, isOutside, foreRingVertices, aftRingVertices); + } + public static void addCylinderMesh(@NotNull DefaultObj obj, @NotNull CoordTransform transformer, String groupName, float radius, float height, int numSides, boolean solid, - List bottomRingVertices, List topRingVertices) { - addCylinderMesh(obj, transformer, groupName, radius, height, numSides, solid, true, bottomRingVertices, topRingVertices); + List foreRingVertices, List aftRingVertices) { + addCylinderMesh(obj, transformer, groupName, radius, height, numSides, solid, true, foreRingVertices, aftRingVertices); } public static void addCylinderMesh(@NotNull DefaultObj obj, @NotNull CoordTransform transformer, String groupName, float radius, float height, boolean solid, ObjUtils.LevelOfDetail LOD, - List bottomRingVertices, List topRingVertices) { - addCylinderMesh(obj, transformer, groupName, radius, height, LOD.getNrOfSides(radius), solid, bottomRingVertices, topRingVertices); + List foreRingVertices, List aftRingVertices) { + addCylinderMesh(obj, transformer, groupName, radius, height, LOD.getNrOfSides(radius), solid, foreRingVertices, aftRingVertices); } public static void addCylinderMesh(@NotNull DefaultObj obj, @NotNull CoordTransform transformer, String groupName, float radius, float height, boolean solid, boolean isOutside, int nrOfSlices, - List bottomRingVertices, List topRingVertices) { - addCylinderMesh(obj, transformer, groupName, radius, height, nrOfSlices, solid, isOutside, bottomRingVertices, topRingVertices); + List foreRingVertices, List aftRingVertices) { + addCylinderMesh(obj, transformer, groupName, radius, height, nrOfSlices, solid, isOutside, foreRingVertices, aftRingVertices); } public static void addCylinderMesh(@NotNull DefaultObj obj, @NotNull CoordTransform transformer, String groupName, float radius, float height, boolean solid, int nrOfSlices, - List bottomRingVertices, List topRingVertices) { - addCylinderMesh(obj, transformer, groupName, radius, height, nrOfSlices, solid, bottomRingVertices, topRingVertices); + List foreRingVertices, List aftRingVertices) { + addCylinderMesh(obj, transformer, groupName, radius, height, nrOfSlices, solid, foreRingVertices, aftRingVertices); } public static void addCylinderMesh(@NotNull DefaultObj obj, @NotNull CoordTransform transformer, String groupName, diff --git a/core/src/net/sf/openrocket/file/wavefrontobj/export/shapes/TubeExporter.java b/core/src/net/sf/openrocket/file/wavefrontobj/export/shapes/TubeExporter.java index 6b413509b..c726967ac 100644 --- a/core/src/net/sf/openrocket/file/wavefrontobj/export/shapes/TubeExporter.java +++ b/core/src/net/sf/openrocket/file/wavefrontobj/export/shapes/TubeExporter.java @@ -6,6 +6,7 @@ import net.sf.openrocket.file.wavefrontobj.DefaultObj; import net.sf.openrocket.file.wavefrontobj.DefaultObjFace; import net.sf.openrocket.file.wavefrontobj.ObjUtils; +import java.util.ArrayList; import java.util.List; import static net.sf.openrocket.file.wavefrontobj.export.shapes.CylinderExporter.generateRingVertices; @@ -16,23 +17,25 @@ public class TubeExporter { * It is drawn in the origin of the OBJ coordinate system. The longitudinal axis is positive, converted OpenRocket x-axis. * @param obj The obj to add the mesh to * @param groupName The name of the group to add the mesh to, or null if no group should be added (use the active group) - * @param aftOuterRadius The outer radius of the aft (bottom) of the tube * @param foreOuterRadius The outer radius of the fore (top) of the tube - * @param aftInnerRadius The inner radius of the aft (bottom) of the tube + * @param aftOuterRadius The outer radius of the aft (bottom) of the tube * @param foreInnerRadius The inner radius of the fore (top) of the tube + * Set to 0, together with aftInnerRadius, to create a solid tube + * @param aftInnerRadius The inner radius of the aft (bottom) of the tube + * Set to 0, together with foreInnerRadius, to create a solid tube * @param length The length of the tube * @param numSides The number of sides of the tube - * @param bottomOuterVertices A list to add the indices of the bottom outer vertices to, or null if the indices are not needed - * @param topOuterVertices A list to add the indices of the top outer vertices to, or null if the indices are not needed - * @param bottomInnerVertices A list to add the indices of the bottom inner vertices to, or null if the indices are not needed - * @param topInnerVertices A list to add the indices of the top inner vertices to, or null if the indices are not needed + * @param foreOuterVertices A list to add the indices of the fore (top) outer vertices to, or null if the indices are not needed + * @param aftOuterVertices A list to add the indices of the aft (bottom) outer vertices to, or null if the indices are not needed + * @param foreInnerVertices A list to add the indices of the fore (top) inner vertices to, or null if the indices are not needed + * @param aftInnerVertices A list to add the indices of the aft (bottom) inner vertices to, or null if the indices are not needed */ public static void addTubeMesh(@NotNull DefaultObj obj, @NotNull CoordTransform transformer, String groupName, - float aftOuterRadius, float foreOuterRadius, - float aftInnerRadius, float foreInnerRadius, float length, int numSides, - List bottomOuterVertices, List topOuterVertices, - List bottomInnerVertices, List topInnerVertices) { - if (aftInnerRadius > aftOuterRadius || foreInnerRadius > foreOuterRadius) { + float foreOuterRadius, float aftOuterRadius, + float foreInnerRadius, float aftInnerRadius, float length, int numSides, + List foreOuterVertices, List aftOuterVertices, + List foreInnerVertices, List aftInnerVertices) { + if (Float.compare(aftInnerRadius, aftOuterRadius) > 0 || Float.compare(foreInnerRadius, foreOuterRadius) > 0) { throw new IllegalArgumentException("Inner radius must be less than outer radius"); } @@ -41,102 +44,38 @@ public class TubeExporter { obj.setActiveGroupNames(groupName); } - // 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(); - - obj.addNormal(transformer.convertLocWithoutOriginOffs(-1, 0, 0)); // Top faces normal - obj.addNormal(transformer.convertLocWithoutOriginOffs(1, 0, 0)); // Bottom faces normal - - // Generate top outside vertices - generateRingVertices(obj, transformer, startIdx, numSides, 0, foreOuterRadius, true, topOuterVertices); - - // Generate top inside vertices - generateRingVertices(obj, transformer, startIdx + numSides, numSides, 0, foreInnerRadius, false, topInnerVertices); - - // Generate bottom outside vertices - generateRingVertices(obj, transformer, startIdx + 2*numSides, numSides, length, aftOuterRadius, true, bottomOuterVertices); - - // Generate bottom inside vertices - generateRingVertices(obj, transformer, startIdx + 3*numSides, numSides, length, aftInnerRadius, false, bottomInnerVertices); - - // Create top faces - for (int i = 0; i < numSides; i++) { - int[] vertexIndices = new int[] { - i, // Bottom-left of quad outside vertex - ((i + 1) % numSides), // Bottom-right of quad outside vertex - numSides + ((i + 1) % numSides), // Top-right of quad inside vertex - numSides + i, // Top-left of quad inside vertex - }; - ObjUtils.offsetIndex(vertexIndices, startIdx); - int[] normalIndices = new int[] {0, 0, 0, 0}; - ObjUtils.offsetIndex(normalIndices, normalsStartIdx); - - DefaultObjFace face = new DefaultObjFace(vertexIndices, null, normalIndices); - obj.addFace(face); + // We need to store the vertices to create the closing disks, so we'll create lists if they do not exist + if (foreOuterVertices == null) { + foreOuterVertices = new ArrayList<>(); + } + if (aftOuterVertices == null) { + aftOuterVertices = new ArrayList<>(); + } + if (foreInnerVertices == null) { + foreInnerVertices = new ArrayList<>(); + } + if (aftInnerVertices == null) { + aftInnerVertices = new ArrayList<>(); } - // Create bottom faces - for (int i = 0; i < numSides; i++) { - int[] vertexIndices = new int[] { - 2*numSides + i, // Bottom-left of quad outside vertex - 3*numSides + i, // Top-left of quad inside vertex - 3*numSides + ((i + 1) % numSides), // Top-right of quad inside vertex - 2*numSides + ((i + 1) % numSides), // Bottom-right of quad outside vertex - }; - ObjUtils.offsetIndex(vertexIndices, startIdx); - - int[] normalIndices = new int[] {1, 1, 1, 1}; - ObjUtils.offsetIndex(normalIndices, normalsStartIdx); - - DefaultObjFace face = new DefaultObjFace(vertexIndices, null, normalIndices); - obj.addFace(face); + // Generate inside mesh + boolean hasForeThickness = Float.compare(foreOuterRadius, foreInnerRadius) > 0 && Float.compare(foreInnerRadius, 0) > 0; + boolean hasAftThickness = Float.compare(aftOuterRadius, aftInnerRadius) > 0 && Float.compare(aftInnerRadius, 0) > 0; + if (hasForeThickness || hasAftThickness) { + CylinderExporter.addCylinderMesh(obj, transformer, null, foreInnerRadius, aftInnerRadius, length, numSides, + false, false, foreInnerVertices, aftInnerVertices); } - // Create outside side faces - for (int i = 0; i < numSides; i++) { - final int nextIdx = (i + 1) % numSides; - int[] vertexIndices = new int[]{ - i, // Bottom-left of quad outside vertex - 2*numSides + i, // Top-left of quad outside vertex - 2*numSides + nextIdx, // Top-right of quad outside vertex - nextIdx, // Bottom-right of quad outside vertex - }; - ObjUtils.offsetIndex(vertexIndices, startIdx); + // Generate outside mesh + CylinderExporter.addCylinderMesh(obj, transformer, null, foreOuterRadius, aftOuterRadius, length, numSides, + !hasForeThickness && !hasAftThickness, true, foreOuterVertices, aftOuterVertices); - int[] normalIndices = new int[]{ - i, // Bottom-left of quad outside vertex - 2*numSides + i, // Top-left of quad outside vertex - 2*numSides + nextIdx, // Top-right of quad outside vertex - nextIdx, // Bottom-right of quad outside vertex - }; - ObjUtils.offsetIndex(normalIndices, normalsStartIdx + 2); // Extra 2 offset for bottom and top normals - - DefaultObjFace face = new DefaultObjFace(vertexIndices, null, normalIndices); - obj.addFace(face); + // Close the mesh + if (hasForeThickness) { + DiskExporter.closeDiskMesh(obj, transformer, null, foreOuterVertices, foreInnerVertices, false, true); } - - // Create inside side faces - for (int i = 0; i < numSides; i++) { - final int nextIdx = (i + 1) % numSides; - int[] vertexIndices = new int[]{ - numSides + i, // Bottom-left of quad inside vertex - numSides + nextIdx, // Bottom-right of quad inside vertex - 3*numSides + nextIdx, // Top-right of quad inside vertex - 3*numSides + i, // Top-left of quad inside vertex - }; - ObjUtils.offsetIndex(vertexIndices, startIdx); - - int[] normalIndices = new int[]{ - numSides + i, // Bottom-left of quad inside vertex - numSides + nextIdx, // Bottom-right of quad inside vertex - 3*numSides + nextIdx, // Top-right of quad inside vertex - 3*numSides + i, // Top-left of quad inside vertex - }; - ObjUtils.offsetIndex(normalIndices, normalsStartIdx + 2); // Extra 2 offset for bottom and top normals - - DefaultObjFace face = new DefaultObjFace(vertexIndices, null, normalIndices); - obj.addFace(face); + if (hasAftThickness) { + DiskExporter.closeDiskMesh(obj, transformer, null, aftOuterVertices, aftInnerVertices, false, false); } } diff --git a/core/test/net/sf/openrocket/file/wavefrontobj/export/OBJExporterFactoryTest.java b/core/test/net/sf/openrocket/file/wavefrontobj/export/OBJExporterFactoryTest.java index 67d0e398e..f0699ec8b 100644 --- a/core/test/net/sf/openrocket/file/wavefrontobj/export/OBJExporterFactoryTest.java +++ b/core/test/net/sf/openrocket/file/wavefrontobj/export/OBJExporterFactoryTest.java @@ -12,7 +12,6 @@ import net.sf.openrocket.document.OpenRocketDocument; import net.sf.openrocket.document.OpenRocketDocumentFactory; import net.sf.openrocket.file.GeneralRocketLoader; import net.sf.openrocket.file.RocketLoadException; -import net.sf.openrocket.file.openrocket.OpenRocketSaver; import net.sf.openrocket.file.openrocket.OpenRocketSaverTest; import net.sf.openrocket.file.wavefrontobj.CoordTransform; import net.sf.openrocket.file.wavefrontobj.DefaultCoordTransform; @@ -33,8 +32,6 @@ import net.sf.openrocket.rocketcomponent.Transition; import net.sf.openrocket.rocketcomponent.TrapezoidFinSet; import net.sf.openrocket.rocketcomponent.TubeFinSet; import net.sf.openrocket.startup.Application; -import net.sf.openrocket.util.BaseTestCase.BaseTestCase; -import net.sf.openrocket.util.TestRockets; import org.junit.BeforeClass; import org.junit.Test; @@ -47,13 +44,8 @@ import java.util.List; import static org.junit.Assert.fail; public class OBJExporterFactoryTest { - private final OpenRocketSaver saver = new OpenRocketSaver(); private static final File TMP_DIR = new File("./tmp/"); - public static final String SIMULATION_EXTENSION_SCRIPT = "// Test < &\n// >\n// components = List.of(rocket); + // Create a temp file for storing the exported OBJ Path tempFile = Files.createTempFile("testExport", ".obj"); String filePath = tempFile.toAbsolutePath().toString(); - filePath = "/Users/SiboVanGool/Downloads/testExport.obj"; // TODO: delete me - TestRockets.dumpRocket(rocket, "/Users/SiboVanGool/Downloads/test.ork"); // TODO: delete me + // Do the exporting CoordTransform transformer = new DefaultCoordTransform(rocket.getLength()); OBJExporterFactory exporterFactory = new OBJExporterFactory(components, rocket.getSelectedConfiguration(), true, false, true, transformer, filePath); exporterFactory.doExport(); - // Test with other parameters - /*noseCone.setShoulderCapped(false); - railButton.setScrewHeight(0); + // Test with other parameters + noseCone.setShoulderCapped(false); + railButton.setScrewHeight(0); + bodyTube.setFilled(true); transformer = new DefaultCoordTransform(rocket.getLength()); - exporterFactory = new OBJExporterFactory(components, false, false, true, + exporterFactory = new OBJExporterFactory(components, rocket.getSelectedConfiguration(), false, false, true, transformer, filePath); - exporterFactory.doExport();*/ - + exporterFactory.doExport(); + // Clean up Files.delete(tempFile); } - - private OpenRocketDocument loadRocket(String fileName) { - GeneralRocketLoader loader = new GeneralRocketLoader(new File(fileName)); - OpenRocketDocument rocketDoc = null; - try { - rocketDoc = loader.load(); - } catch (RocketLoadException e) { - e.printStackTrace(); - fail("RocketLoadException while loading file " + fileName + " : " + e.getMessage()); - } - return rocketDoc; - } }