Add texturing for motors
This commit is contained in:
parent
4fc3901f00
commit
d63e2e9084
@ -74,10 +74,10 @@ public class MotorExporter {
|
||||
List<Integer> foreRingVertices = new ArrayList<>();
|
||||
List<Integer> aftRingVertices = new ArrayList<>();
|
||||
CylinderExporter.addCylinderMesh(obj, transformer, null, (float) radius, (float) length, numSides, false, true,
|
||||
foreRingVertices, aftRingVertices);
|
||||
0, 1, 0.125f, 0.875f, foreRingVertices, aftRingVertices);
|
||||
|
||||
// Close the fore end
|
||||
DiskExporter.closeDiskMesh(obj, transformer, null, foreRingVertices, false, true);
|
||||
DiskExporter.closeDiskMesh(obj, transformer, null, foreRingVertices, false, true, 0, 1, 0.875f, 1);
|
||||
|
||||
// Generate the aft end inner ring vertices
|
||||
List<Integer> aftInnerRingVertices = new ArrayList<>();
|
||||
@ -100,12 +100,26 @@ public class MotorExporter {
|
||||
}
|
||||
|
||||
// Close outer and inner aft ring
|
||||
DiskExporter.closeDiskMesh(obj, transformer, null, aftRingVertices, aftInnerRingVertices, false, false);
|
||||
DiskExporter.closeDiskMesh(obj, transformer, null, aftRingVertices, aftInnerRingVertices, false, false, 0, 1, 0.125f, 0.1f);
|
||||
|
||||
// Add cone tip vertex
|
||||
obj.addVertex(transformer.convertLoc(length - coneLength, 0, 0));
|
||||
obj.addNormal(transformer.convertLocWithoutOriginOffs(1, 0, 0));
|
||||
|
||||
// Add texture coordinates
|
||||
final int texCoordsStartIdx = obj.getNumTexCoords();
|
||||
//// Inner aft ring
|
||||
for (int i = 0; i <= numSides; i++) {
|
||||
final float u = ((float) i) / numSides;
|
||||
obj.addTexCoord(u, 0.1f);
|
||||
}
|
||||
|
||||
//// Cone tip
|
||||
for (int i = 0; i <= numSides; i++) {
|
||||
final float u = ((float) i) / numSides;
|
||||
obj.addTexCoord(u, 0f);
|
||||
}
|
||||
|
||||
int endIdx = Math.max(obj.getNumVertices() - 1, startIdx); // Clamp in case no vertices were added
|
||||
int normalsEndIdx = Math.max(obj.getNumNormals() - 1, normalsStartIdx);
|
||||
|
||||
@ -122,8 +136,14 @@ public class MotorExporter {
|
||||
normalsStartIdx + nextIdx,
|
||||
normalsStartIdx + i,
|
||||
};
|
||||
final int[] texCoordIndices = new int[] {
|
||||
numSides+1 + i,
|
||||
i+1,
|
||||
i,
|
||||
};
|
||||
ObjUtils.offsetIndex(texCoordIndices, texCoordsStartIdx);
|
||||
|
||||
DefaultObjFace face = new DefaultObjFace(vertexIndices, null, normalIndices);
|
||||
DefaultObjFace face = new DefaultObjFace(vertexIndices, texCoordIndices, normalIndices);
|
||||
obj.addFace(face);
|
||||
}
|
||||
|
||||
|
@ -5,6 +5,7 @@ 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.util.MathUtil;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@ -22,6 +23,10 @@ public class CylinderExporter {
|
||||
* 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 uMin The minimum u texture coordinate
|
||||
* @param uMax The maximum u texture coordinate
|
||||
* @param vMin The minimum v texture coordinate
|
||||
* @param vMax The maximum v texture coordinate
|
||||
* @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
|
||||
* @param foreRingNormals A list to add the fore (top) ring normal indices to
|
||||
@ -29,6 +34,7 @@ public class CylinderExporter {
|
||||
*/
|
||||
public static void addCylinderMesh(@NotNull DefaultObj obj, @NotNull CoordTransform transformer, String groupName,
|
||||
float foreRadius, float aftRadius, float length, int numSides, boolean solid, boolean isOutside,
|
||||
float uMin, float uMax, float vMin, float vMax,
|
||||
List<Integer> foreRingVertices, List<Integer> aftRingVertices,
|
||||
List<Integer> foreRingNormals, List<Integer> aftRingNormals) {
|
||||
// Set the new group
|
||||
@ -52,10 +58,12 @@ public class CylinderExporter {
|
||||
}
|
||||
|
||||
// Generate side top vertices
|
||||
generateRingVertices(obj, transformer, numSides, 0, length, length, foreRadius, aftRadius, isOutside, foreRingVertices, foreRingNormals);
|
||||
generateRingVertices(obj, transformer, numSides, 0, length, length, foreRadius, aftRadius, isOutside,
|
||||
uMin, uMax, vMin, vMax, foreRingVertices, foreRingNormals);
|
||||
|
||||
// Generate side bottom vertices
|
||||
generateRingVertices(obj, transformer, numSides, length, 0, length, aftRadius, foreRadius, isOutside, aftRingVertices, aftRingNormals);
|
||||
generateRingVertices(obj, transformer, numSides, length, 0, length, aftRadius, foreRadius, isOutside,
|
||||
uMin, uMax, vMin, vMax, aftRingVertices, aftRingNormals);
|
||||
|
||||
// Create faces for the bottom and top
|
||||
if (solid) {
|
||||
@ -138,6 +146,21 @@ public class CylinderExporter {
|
||||
obj.addFace(face);
|
||||
}
|
||||
}
|
||||
public static void addCylinderMesh(@NotNull DefaultObj obj, @NotNull CoordTransform transformer, String groupName,
|
||||
float foreRadius, float aftRadius, float length, int numSides, boolean solid, boolean isOutside,
|
||||
List<Integer> foreRingVertices, List<Integer> aftRingVertices,
|
||||
List<Integer> foreRingNormals, List<Integer> aftRingNormals) {
|
||||
addCylinderMesh(obj, transformer, groupName, foreRadius, aftRadius, length, numSides, solid, isOutside,
|
||||
0, 1, 0, 1, foreRingVertices, aftRingVertices, foreRingNormals, aftRingNormals);
|
||||
}
|
||||
|
||||
public static void addCylinderMesh(@NotNull DefaultObj obj, @NotNull CoordTransform transformer, String groupName,
|
||||
float foreRadius, float aftRadius, float length, int numSides, boolean solid, boolean isOutside,
|
||||
float uMin, float uMax, float vMin, float vMax,
|
||||
List<Integer> foreRingVertices, List<Integer> aftRingVertices) {
|
||||
addCylinderMesh(obj, transformer, groupName, foreRadius, aftRadius, length, numSides, solid, isOutside,
|
||||
uMin, uMax, vMin, vMax, foreRingVertices, aftRingVertices, null, null);
|
||||
}
|
||||
|
||||
public static void addCylinderMesh(@NotNull DefaultObj obj, @NotNull CoordTransform transformer, String groupName,
|
||||
float foreRadius, float aftRadius, float length, int numSides, boolean solid, boolean isOutside,
|
||||
@ -146,6 +169,14 @@ public class CylinderExporter {
|
||||
foreRingVertices, aftRingVertices, null, null);
|
||||
}
|
||||
|
||||
public static void addCylinderMesh(@NotNull DefaultObj obj, @NotNull CoordTransform transformer, String groupName,
|
||||
float radius, float length, int numSides, boolean solid, boolean isOutside,
|
||||
float uMin, float uMax, float vMin, float vMax,
|
||||
List<Integer> foreRingVertices, List<Integer> aftRingVertices) {
|
||||
addCylinderMesh(obj, transformer, groupName, radius, radius, length, numSides, solid, isOutside,
|
||||
uMin, uMax, vMin, vMax, foreRingVertices, aftRingVertices);
|
||||
}
|
||||
|
||||
public static void addCylinderMesh(@NotNull DefaultObj obj, @NotNull CoordTransform transformer, String groupName,
|
||||
float radius, float length, int numSides, boolean solid, boolean isOutside,
|
||||
List<Integer> foreRingVertices, List<Integer> aftRingVertices) {
|
||||
@ -172,7 +203,8 @@ public class CylinderExporter {
|
||||
|
||||
public static void generateRingVertices(DefaultObj obj, CoordTransform transformer,
|
||||
int numSides, float x, float nextX, float xMax, float radius, float nextRadius,
|
||||
boolean isOutside, List<Integer> vertexList, List<Integer> normalList) {
|
||||
boolean isOutside, float uMin, float uMax, float vMin, float vMax,
|
||||
List<Integer> vertexList, List<Integer> normalList) {
|
||||
int startIdx = obj.getNumVertices();
|
||||
int normalsStartIdx = obj.getNumNormals();
|
||||
|
||||
@ -181,10 +213,11 @@ public class CylinderExporter {
|
||||
final float y = radius * (float) Math.cos(angle);
|
||||
final float z = radius * (float) Math.sin(angle);
|
||||
|
||||
// Side top vertices
|
||||
// Vertex
|
||||
obj.addVertex(transformer.convertLoc(x, y, z));
|
||||
|
||||
// We need special nx normal when the radius changes
|
||||
// Normal
|
||||
//// 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));
|
||||
@ -209,13 +242,17 @@ public class CylinderExporter {
|
||||
}
|
||||
|
||||
// Texture coordinates
|
||||
final float u = (float) i / numSides;
|
||||
final float v = isOutside ? (xMax - x) / xMax : x / xMax; // For some reason, the texture is vertically flipped in OR for inside cylinders. Don't really like it, but it is what it is
|
||||
|
||||
float u = ((float) i) / numSides;
|
||||
u = (float) MathUtil.map(u, 0, 1, uMin, uMax);
|
||||
float v = isOutside ? (xMax - x) / xMax : x / xMax; // For some reason, the texture is vertically flipped in OR for inside cylinders. Don't really like it, but it is what it is
|
||||
v = (float) MathUtil.map(v, 0, 1, vMin, vMax);
|
||||
obj.addTexCoord(u, v);
|
||||
}
|
||||
|
||||
// Need to add a last texture coordinate for the end of the texture
|
||||
final float v = isOutside ? (xMax - x) / xMax : x / xMax;
|
||||
obj.addTexCoord(1f, v);
|
||||
float v = isOutside ? (xMax - x) / xMax : x / xMax;
|
||||
v = (float) MathUtil.map(v, 0, 1, vMin, vMax);
|
||||
obj.addTexCoord(uMax, v);
|
||||
}
|
||||
}
|
||||
|
@ -19,10 +19,15 @@ public class DiskExporter {
|
||||
* @param innerVertices The indices of the inner vertices, or null if the disk is solid
|
||||
* @param isClockwise Whether the vertices are in clockwise order (true) or counter-clockwise order (false)
|
||||
* @param isTopFace Whether the disk is a top face (true) or bottom face (false)
|
||||
* @param uMin The minimum u texture coordinate
|
||||
* @param uMax The maximum u texture coordinate
|
||||
* @param vMin The minimum v texture coordinate
|
||||
* @param vMax The maximum v texture coordinate
|
||||
*/
|
||||
public static void closeDiskMesh(@NotNull DefaultObj obj, @NotNull CoordTransform transformer, String groupName,
|
||||
@NotNull List<Integer> outerVertices, List<Integer> innerVertices,
|
||||
boolean isClockwise, boolean isTopFace) {
|
||||
boolean isClockwise, boolean isTopFace,
|
||||
float uMin, float uMax, float vMin, float vMax) {
|
||||
if (outerVertices.isEmpty()) {
|
||||
throw new IllegalArgumentException("Outer vertices cannot be empty");
|
||||
}
|
||||
@ -45,6 +50,21 @@ public class DiskExporter {
|
||||
obj.addNormal(transformer.convertLocWithoutOriginOffs(isTopFace ? -1 : 1, 0, 0)); // TODO: hm, what if the object is rotated? If the disk is not drawn in the y direction?
|
||||
final int normalIndex = obj.getNumNormals() - 1;
|
||||
|
||||
final int texCoordsStartIdx = obj.getNumTexCoords();
|
||||
final int numSides = outerVertices.size();
|
||||
|
||||
// Create the texture coordinates
|
||||
//// Outer vertices
|
||||
for (int i = 0; i <= numSides; i++) {
|
||||
final float u = uMin + ((float) i) / numSides * (uMax - uMin);
|
||||
obj.addTexCoord(u, vMin);
|
||||
}
|
||||
//// Inner vertices
|
||||
for (int i = 0; i <= numSides; i++) {
|
||||
final float u = uMin + ((float) i) / numSides * (uMax - uMin);
|
||||
obj.addTexCoord(u, vMax);
|
||||
}
|
||||
|
||||
if (isSolid) {
|
||||
// Add the center vertex
|
||||
final int centerVertexIdx;
|
||||
@ -59,6 +79,8 @@ public class DiskExporter {
|
||||
// Add the triangle faces
|
||||
for (int i = 0; i < outerVertices.size(); i++) {
|
||||
int nextIdx = (i + 1) % outerVertices.size();
|
||||
|
||||
// Vertices
|
||||
int[] vertexIndices = new int[] {
|
||||
centerVertexIdx,
|
||||
outerVertices.get(nextIdx),
|
||||
@ -66,14 +88,27 @@ public class DiskExporter {
|
||||
};
|
||||
vertexIndices = ObjUtils.reverseIndexWinding(vertexIndices, isTopFace != isClockwise);
|
||||
|
||||
// Normals
|
||||
int[] normalIndices = new int[] { normalIndex, normalIndex, normalIndex };
|
||||
DefaultObjFace face = new DefaultObjFace(vertexIndices, null, normalIndices);
|
||||
|
||||
// Texture coordinates
|
||||
int[] texCoordsIndices = new int[] {
|
||||
numSides+1 + i,
|
||||
i+1,
|
||||
i,
|
||||
};
|
||||
texCoordsIndices = ObjUtils.reverseIndexWinding(texCoordsIndices, isTopFace != isClockwise);
|
||||
ObjUtils.offsetIndex(texCoordsIndices, texCoordsStartIdx);
|
||||
|
||||
DefaultObjFace face = new DefaultObjFace(vertexIndices, texCoordsIndices, normalIndices);
|
||||
obj.addFace(face);
|
||||
}
|
||||
} else {
|
||||
// Add the quad faces
|
||||
for (int i = 0; i < outerVertices.size(); i++) {
|
||||
int nextIdx = (i + 1) % outerVertices.size();
|
||||
|
||||
// Vertices
|
||||
int[] vertexIndices = new int[] {
|
||||
outerVertices.get(i), // Bottom-left of quad
|
||||
innerVertices.get(i), // Top-left of quad
|
||||
@ -82,13 +117,40 @@ public class DiskExporter {
|
||||
};
|
||||
vertexIndices = ObjUtils.reverseIndexWinding(vertexIndices, isTopFace != isClockwise);
|
||||
|
||||
// Normals
|
||||
int[] normalIndices = new int[] { normalIndex, normalIndex, normalIndex, normalIndex };
|
||||
DefaultObjFace face = new DefaultObjFace(vertexIndices, null, normalIndices);
|
||||
|
||||
// Texture coordinates
|
||||
int[] texCoordsIndices = new int[] {
|
||||
i,
|
||||
numSides+1 + i,
|
||||
numSides+1 + i+1,
|
||||
i+1,
|
||||
};
|
||||
texCoordsIndices = ObjUtils.reverseIndexWinding(texCoordsIndices, isTopFace != isClockwise);
|
||||
ObjUtils.offsetIndex(texCoordsIndices, texCoordsStartIdx);
|
||||
|
||||
|
||||
DefaultObjFace face = new DefaultObjFace(vertexIndices, texCoordsIndices, normalIndices);
|
||||
obj.addFace(face);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void closeDiskMesh(@NotNull DefaultObj obj, @NotNull CoordTransform transformer, String groupName,
|
||||
@NotNull List<Integer> outerVertices, List<Integer> innerVertices,
|
||||
boolean isClockwise, boolean isTopFace) {
|
||||
// By default, OpenRocket doesn't really render textures on disks (often edges of tubes), so we don't either
|
||||
closeDiskMesh(obj, transformer, groupName, outerVertices, innerVertices, isClockwise, isTopFace, 0, 0, 0, 0);
|
||||
}
|
||||
|
||||
public static void closeDiskMesh(@NotNull DefaultObj obj, @NotNull CoordTransform transformer, String groupName,
|
||||
@NotNull List<Integer> outerVertices, boolean isClockwise, boolean isTopFace,
|
||||
float uMin, float uMax, float vMin, float vMax) {
|
||||
closeDiskMesh(obj, transformer, groupName, outerVertices, null, isClockwise, isTopFace, uMin, uMax, vMin, vMax);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Adds a (closed) disk mesh to the obj by using existing outer and inner vertices
|
||||
* @param obj The obj to add the mesh to
|
||||
@ -100,7 +162,8 @@ public class DiskExporter {
|
||||
*/
|
||||
public static void closeDiskMesh(@NotNull DefaultObj obj, @NotNull CoordTransform transformer, String groupName,
|
||||
@NotNull List<Integer> outerVertices, boolean isClockwise, boolean isTopFace) {
|
||||
closeDiskMesh(obj, transformer, groupName, outerVertices, null, isClockwise, isTopFace);
|
||||
// By default, OpenRocket doesn't really render textures on disks (often edges of tubes), so we don't either
|
||||
closeDiskMesh(obj, transformer, groupName, outerVertices, isClockwise, isTopFace, 0, 0, 0, 0);
|
||||
}
|
||||
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user