Add vertex scaling
This commit is contained in:
parent
15d3bce807
commit
bff72d3532
@ -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");
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user