Add vertex scaling

This commit is contained in:
SiboVG 2023-08-15 03:18:08 +02:00
parent 15d3bce807
commit bff72d3532
3 changed files with 104 additions and 14 deletions

View File

@ -203,6 +203,63 @@ public class ObjUtils {
}
}
/**
* Scale the vertices of an object around a certain origin.
* <b>NOTE: this uses the Wavefront OBJ coordinate system</b>
* @param obj The object to scale the vertices of
* @param startIdx The starting vertex index to scale
* @param endIdx The ending vertex index to scale (inclusive)
* @param scaleX The scaling factor in the x direction
* @param scaleY The scaling factor in the y direction
* @param scaleZ The scaling factor in the z direction
* @param origX The x coordinate of the origin of the scaling
* @param origY The y coordinate of the origin of the scaling
* @param origZ The z coordinate of the origin of the scaling
*/
public static void scaleVertices(DefaultObj obj, int startIdx, int endIdx,
float scaleX, float scaleY, float scaleZ,
float origX, float origY, float origZ) {
verifyIndexRange(obj, startIdx, endIdx);
if (Float.compare(scaleX, 1) == 0 && Float.compare(scaleY, 1) == 0 && Float.compare(scaleZ, 1) == 0) {
return;
}
for (int i = startIdx; i <= endIdx; i++) {
FloatTuple vertex = obj.getVertex(i);
// Translate vertex to origin
final float x = vertex.getX() - origX;
final float y = vertex.getY() - origY;
final float z = vertex.getZ() - origZ;
// Apply scaling
float scaledX = x * scaleX;
float scaledY = y * scaleY;
float scaledZ = z * scaleZ;
// Translate vertex back to its original position
scaledX += origX;
scaledY += origY;
scaledZ += origZ;
FloatTuple scaledVertex = new DefaultFloatTuple(scaledX, scaledY, scaledZ);
obj.setVertex(i, scaledVertex);
}
}
/**
* Scale the vertices of an object around the origin
* <b>NOTE: this uses the Wavefront OBJ coordinate system</b>
* @param obj The object to scale the vertices of
* @param scaling The uniform scaling factor
*/
public static void scaleVertices(DefaultObj obj, float scaling) {
scaleVertices(obj, 0, obj.getNumVertices() - 1,
scaling, scaling, scaling,
0, 0, 0);
}
private static void verifyIndexRange(DefaultObj obj, int startIdx, int endIdx) {
if (startIdx < 0 || startIdx >= obj.getNumVertices()) {
throw new IllegalArgumentException("startIdx must be between 0 and the number of vertices");

View File

@ -36,6 +36,10 @@ public class OBJExportOptions {
* This is used to convert the coordinates from the rocket's coordinate system to the OBJ coordinate system (which is arbitrary).
*/
private CoordTransform transformer;
/**
* The scaling factor to use for the export (1 = no scaling).
*/
private float scaling;
// TODO: scaling (to mm = x1000, or SI units)
@ -47,6 +51,7 @@ public class OBJExportOptions {
this.triangulate = false;
this.LOD = ObjUtils.LevelOfDetail.NORMAL;
this.transformer = new DefaultCoordTransform(rocket.getLength());
this.scaling = 1.0f;
}
public boolean isExportChildren() {
@ -104,4 +109,12 @@ public class OBJExportOptions {
public void setExportAsSeparateFiles(boolean exportAsSeparateFiles) {
this.exportAsSeparateFiles = exportAsSeparateFiles;
}
public float getScaling() {
return scaling;
}
public void setScaling(float scaling) {
this.scaling = scaling;
}
}

View File

@ -34,6 +34,7 @@ import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
@ -92,8 +93,15 @@ public class OBJExporterFactory {
*/
public void doExport() {
DefaultObj obj = new DefaultObj();
Map<String, DefaultObj> objFileMap;
boolean exportAsSeparateFiles = this.options.isExportAsSeparateFiles();
if (exportAsSeparateFiles) {
objFileMap = new HashMap<>();
} else {
objFileMap = Map.of(this.filePath, obj);
}
// Get all the components to export
Set<RocketComponent> componentsToExport = new HashSet<>(this.components);
if (this.options.isExportChildren()) {
@ -127,30 +135,42 @@ public class OBJExporterFactory {
String groupName = idx + "_" + component.getName();
handleComponent(obj, this.configuration, this.options.getTransformer(), component, groupName, this.options.getLOD());
// If separate export, already need to write the OBJ here
// If separate export, add this object to the map of objects to export
if (exportAsSeparateFiles) {
String path = FileUtils.removeExtension(this.filePath) + "_" + groupName + ".obj";
writeObj(obj, path);
objFileMap.put(path, obj);
}
idx++;
}
if (this.options.isTriangulate()) {
obj = de.javagl.obj.ObjUtils.triangulate(obj, new DefaultObj());
}
// Apply export options and write the OBJ files
for (Map.Entry<String, DefaultObj> entry : objFileMap.entrySet()) {
String filePath = entry.getKey();
obj = entry.getValue();
if (this.options.isRemoveOffset()) {
// Because of some rotation and translation operations when creating the meshes, the bounds can be inaccurate.
// Therefore, we will recalculate them to be sure.
// Is a bit computationally expensive, but it's the only way to be sure...
obj.recalculateAllVertexBounds();
// Triangulate mesh
if (this.options.isTriangulate()) {
obj = de.javagl.obj.ObjUtils.triangulate(obj, new DefaultObj());
}
ObjUtils.removeVertexOffset(obj, this.options.getTransformer());
}
// Remove position offset
if (this.options.isRemoveOffset()) {
// Because of some rotation and translation operations when creating the meshes, the bounds can be inaccurate.
// Therefore, we will recalculate them to be sure.
// Is a bit computationally expensive, but it's the only way to be sure...
obj.recalculateAllVertexBounds();
if (!exportAsSeparateFiles) {
writeObj(obj, this.filePath);
ObjUtils.removeVertexOffset(obj, this.options.getTransformer());
}
// Perform scaling
if (Float.compare(options.getScaling(), 1) != 0) {
ObjUtils.scaleVertices(obj, options.getScaling());
}
// Write the OBJ file
writeObj(obj, filePath);
}
}