Improve normals

This commit is contained in:
SiboVG 2023-08-17 02:47:30 +02:00
parent 353105d1bd
commit ea59b9d012
3 changed files with 37 additions and 19 deletions

View File

@ -226,7 +226,7 @@ public class TransitionExporter extends RocketComponentExporter<Transition> {
boolean isAftRing = Double.compare(x, (float) component.getLength()) == 0; boolean isAftRing = Double.compare(x, (float) component.getLength()) == 0;
// Case 5: Add normal vertices // 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++; actualNumStacks++;
} }
} }
@ -296,7 +296,7 @@ public class TransitionExporter extends RocketComponentExporter<Transition> {
} }
private void addQuadVertices(int numSlices, List<Integer> foreRingVertices, List<Integer> aftRingVertices, private void addQuadVertices(int numSlices, List<Integer> foreRingVertices, List<Integer> 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++) { for (int i = 0; i < numSlices; i++) {
double angle = 2 * Math.PI * i / numSlices; double angle = 2 * Math.PI * i / numSlices;
float y = (float) (r * Math.cos(angle)); float y = (float) (r * Math.cos(angle));
@ -313,9 +313,20 @@ public class TransitionExporter extends RocketComponentExporter<Transition> {
} }
// Calculate the normal // Calculate the normal
final float nx = isOutside ? (float) (r - rNext) : (float) (rNext -r); // We need special nx normal when the radius changes
final float ny = isOutside ? y : -y; float nx;
final float nz = isOutside ? z : -z; 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)); obj.addNormal(transformer.convertLocWithoutOriginOffs(nx, ny, nz));
} }
} }

View File

@ -51,10 +51,10 @@ public class CylinderExporter {
} }
// Generate side top vertices // 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 // 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 // Create faces for the bottom and top
if (solid) { if (solid) {
@ -134,12 +134,6 @@ public class CylinderExporter {
addCylinderMesh(obj, transformer, groupName, radius, length, numSides, solid, true, foreRingVertices, aftRingVertices); 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<Integer> foreRingVertices, List<Integer> 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, public static void addCylinderMesh(@NotNull DefaultObj obj, @NotNull CoordTransform transformer, String groupName,
float radius, float length, boolean solid, boolean isOutside, int nrOfSlices, float radius, float length, boolean solid, boolean isOutside, int nrOfSlices,
List<Integer> foreRingVertices, List<Integer> aftRingVertices) { List<Integer> foreRingVertices, List<Integer> aftRingVertices) {
@ -153,8 +147,8 @@ public class CylinderExporter {
} }
public static void generateRingVertices(DefaultObj obj, CoordTransform transformer, public static void generateRingVertices(DefaultObj obj, CoordTransform transformer,
int numSides, float x, float radius, boolean isOutside, int numSides, float x, float nextX, float radius, float nextRadius,
List<Integer> vertexList, List<Integer> normalList) { boolean isOutside, List<Integer> vertexList, List<Integer> normalList) {
int startIdx = obj.getNumVertices(); int startIdx = obj.getNumVertices();
int normalsStartIdx = obj.getNumNormals(); int normalsStartIdx = obj.getNumNormals();
@ -165,7 +159,23 @@ public class CylinderExporter {
// Side top vertices // Side top vertices
obj.addVertex(transformer.convertLoc(x, y, z)); 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) { if (vertexList != null) {
vertexList.add(startIdx + i); vertexList.add(startIdx + i);

View File

@ -3,14 +3,11 @@ package net.sf.openrocket.file.wavefrontobj.export.shapes;
import com.sun.istack.NotNull; import com.sun.istack.NotNull;
import net.sf.openrocket.file.wavefrontobj.CoordTransform; import net.sf.openrocket.file.wavefrontobj.CoordTransform;
import net.sf.openrocket.file.wavefrontobj.DefaultObj; 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.file.wavefrontobj.ObjUtils;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import static net.sf.openrocket.file.wavefrontobj.export.shapes.CylinderExporter.generateRingVertices;
public class TubeExporter { public class TubeExporter {
/** /**
* Add a tube mesh to the obj. * Add a tube mesh to the obj.