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 31615abad..6a156fa2f 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 @@ -226,7 +226,7 @@ public class TransitionExporter extends RocketComponentExporter { boolean isAftRing = Double.compare(x, (float) component.getLength()) == 0; // Case 5: Add normal vertices - addQuadVertices(numSlices, foreRingVertices, aftRingVertices, r, rNext, x, isForeRing, isAftRing, isOutside); + addQuadVertices(numSlices, foreRingVertices, aftRingVertices, r, rNext, x, xNext, isForeRing, isAftRing, isOutside); actualNumStacks++; } } @@ -296,7 +296,7 @@ public class TransitionExporter extends RocketComponentExporter { } private void addQuadVertices(int numSlices, List foreRingVertices, List aftRingVertices, - double r, double rNext, float x, boolean isForeRing, boolean isAftRing, boolean isOutside) { + double r, double rNext, float x, float xNext, boolean isForeRing, boolean isAftRing, boolean isOutside) { for (int i = 0; i < numSlices; i++) { double angle = 2 * Math.PI * i / numSlices; float y = (float) (r * Math.cos(angle)); @@ -313,9 +313,20 @@ public class TransitionExporter extends RocketComponentExporter { } // Calculate the normal - final float nx = isOutside ? (float) (r - rNext) : (float) (rNext -r); - final float ny = isOutside ? y : -y; - final float nz = isOutside ? z : -z; + // We need special nx normal when the radius changes + float nx; + if (Double.compare(r, rNext) != 0) { + final double slopeAngle = Math.atan(Math.abs(xNext - x) / (rNext - r)); + nx = (float) Math.cos(Math.PI - slopeAngle); + } else { + nx = 0; + } + float ny = (float) Math.cos(angle); + float nz = (float) Math.sin(angle); + + nx = isOutside ? nx : -nx; + ny = isOutside ? ny : -ny; + nz = isOutside ? nz : -nz; obj.addNormal(transformer.convertLocWithoutOriginOffs(nx, ny, nz)); } } 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 cf7402d82..2e6926cfe 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 @@ -51,10 +51,10 @@ public class CylinderExporter { } // Generate side top vertices - generateRingVertices(obj, transformer, numSides, 0, foreRadius, isOutside, foreRingVertices, foreRingNormals); + generateRingVertices(obj, transformer, numSides, 0, length, foreRadius, aftRadius, isOutside, foreRingVertices, foreRingNormals); // Generate side bottom vertices - generateRingVertices(obj, transformer, numSides, length, aftRadius, isOutside, aftRingVertices, aftRingNormals); + generateRingVertices(obj, transformer, numSides, length, 0, aftRadius, foreRadius, isOutside, aftRingVertices, aftRingNormals); // Create faces for the bottom and top if (solid) { @@ -134,12 +134,6 @@ public class CylinderExporter { addCylinderMesh(obj, transformer, groupName, radius, length, numSides, solid, true, foreRingVertices, aftRingVertices); } - public static void addCylinderMesh(@NotNull DefaultObj obj, @NotNull CoordTransform transformer, String groupName, - float radius, float length, boolean solid, ObjUtils.LevelOfDetail LOD, - List foreRingVertices, List aftRingVertices) { - addCylinderMesh(obj, transformer, groupName, radius, length, LOD.getNrOfSides(radius), solid, foreRingVertices, aftRingVertices); - } - public static void addCylinderMesh(@NotNull DefaultObj obj, @NotNull CoordTransform transformer, String groupName, float radius, float length, boolean solid, boolean isOutside, int nrOfSlices, List foreRingVertices, List aftRingVertices) { @@ -153,8 +147,8 @@ public class CylinderExporter { } public static void generateRingVertices(DefaultObj obj, CoordTransform transformer, - int numSides, float x, float radius, boolean isOutside, - List vertexList, List normalList) { + int numSides, float x, float nextX, float radius, float nextRadius, + boolean isOutside, List vertexList, List normalList) { int startIdx = obj.getNumVertices(); int normalsStartIdx = obj.getNumNormals(); @@ -165,7 +159,23 @@ public class CylinderExporter { // Side top vertices obj.addVertex(transformer.convertLoc(x, y, z)); - obj.addNormal(transformer.convertLocWithoutOriginOffs(0, isOutside ? y : -y, isOutside ? z : -z)); // This kind of normal ensures the object is smoothly rendered (like the 'Shade Smooth' option in Blender) + + // We need special nx normal when the radius changes + float nx; + if (Float.compare(radius, nextRadius) != 0) { + final double slopeAngle = Math.atan(Math.abs(nextX - x) / (nextRadius - radius)); + nx = (float) Math.cos(Math.PI - slopeAngle); + } else { + nx = 0; + } + float ny = (float) Math.cos(angle); + float nz = (float) Math.sin(angle); + + nx = isOutside ? nx : -nx; + ny = isOutside ? ny : -ny; + nz = isOutside ? nz : -nz; + + obj.addNormal(transformer.convertLocWithoutOriginOffs(nx, ny, nz)); // This kind of normal ensures the object is smoothly rendered (like the 'Shade Smooth' option in Blender) if (vertexList != null) { vertexList.add(startIdx + i); 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 c726967ac..a09f22df2 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 @@ -3,14 +3,11 @@ package net.sf.openrocket.file.wavefrontobj.export.shapes; import com.sun.istack.NotNull; 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 java.util.ArrayList; import java.util.List; -import static net.sf.openrocket.file.wavefrontobj.export.shapes.CylinderExporter.generateRingVertices; - public class TubeExporter { /** * Add a tube mesh to the obj.