Use instance context for orientation/position
Fixes issues with components in pods not being oriented correctly! :)
This commit is contained in:
parent
fc7f71e11f
commit
87c4cbec97
@ -17,6 +17,8 @@ import net.sf.openrocket.rocketcomponent.BodyTube;
|
|||||||
import net.sf.openrocket.rocketcomponent.ComponentAssembly;
|
import net.sf.openrocket.rocketcomponent.ComponentAssembly;
|
||||||
import net.sf.openrocket.rocketcomponent.FinSet;
|
import net.sf.openrocket.rocketcomponent.FinSet;
|
||||||
import net.sf.openrocket.rocketcomponent.FlightConfiguration;
|
import net.sf.openrocket.rocketcomponent.FlightConfiguration;
|
||||||
|
import net.sf.openrocket.rocketcomponent.InstanceContext;
|
||||||
|
import net.sf.openrocket.rocketcomponent.InstanceMap;
|
||||||
import net.sf.openrocket.rocketcomponent.LaunchLug;
|
import net.sf.openrocket.rocketcomponent.LaunchLug;
|
||||||
import net.sf.openrocket.rocketcomponent.MassObject;
|
import net.sf.openrocket.rocketcomponent.MassObject;
|
||||||
import net.sf.openrocket.rocketcomponent.RailButton;
|
import net.sf.openrocket.rocketcomponent.RailButton;
|
||||||
@ -28,6 +30,7 @@ import net.sf.openrocket.rocketcomponent.TubeFinSet;
|
|||||||
import java.io.FileOutputStream;
|
import java.io.FileOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
@ -132,8 +135,13 @@ public class OBJExporterFactory {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
InstanceMap map = configuration.getActiveInstances();
|
||||||
|
ArrayList<InstanceContext> contexts = map.get(component);
|
||||||
|
contexts.get(0).transform.getXrotation();
|
||||||
|
|
||||||
|
|
||||||
String groupName = component.getName() + "_" + idx;
|
String groupName = component.getName() + "_" + idx;
|
||||||
handleComponent(obj, this.transformer, component, groupName, this.LOD);
|
handleComponent(obj, this.configuration, this.transformer, component, groupName, this.LOD);
|
||||||
|
|
||||||
// TODO: motor rendering
|
// TODO: motor rendering
|
||||||
|
|
||||||
@ -161,8 +169,8 @@ public class OBJExporterFactory {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked") // This is safe because of the structure we set up.
|
@SuppressWarnings("unchecked") // This is safe because of the structure we set up.
|
||||||
private <T extends RocketComponent> void handleComponent(DefaultObj obj, CoordTransform transformer, T component,
|
private <T extends RocketComponent> void handleComponent(DefaultObj obj, FlightConfiguration config, CoordTransform transformer,
|
||||||
String groupName, ObjUtils.LevelOfDetail LOD) {
|
T component, String groupName, ObjUtils.LevelOfDetail LOD) {
|
||||||
ExporterFactory<T> factory = null;
|
ExporterFactory<T> factory = null;
|
||||||
Class<?> currentClass = component.getClass();
|
Class<?> currentClass = component.getClass();
|
||||||
|
|
||||||
@ -176,12 +184,12 @@ public class OBJExporterFactory {
|
|||||||
throw new IllegalArgumentException("Unsupported component type: " + component.getClass().getName());
|
throw new IllegalArgumentException("Unsupported component type: " + component.getClass().getName());
|
||||||
}
|
}
|
||||||
|
|
||||||
final RocketComponentExporter<T> exporter = factory.create(obj, transformer, component, groupName, LOD);
|
final RocketComponentExporter<T> exporter = factory.create(obj, config, transformer, component, groupName, LOD);
|
||||||
exporter.addToObj();
|
exporter.addToObj();
|
||||||
}
|
}
|
||||||
|
|
||||||
interface ExporterFactory<T extends RocketComponent> {
|
interface ExporterFactory<T extends RocketComponent> {
|
||||||
RocketComponentExporter<T> create(DefaultObj obj, CoordTransform transformer, T component, String groupName,
|
RocketComponentExporter<T> create(DefaultObj obj, FlightConfiguration config, CoordTransform transformer,
|
||||||
ObjUtils.LevelOfDetail LOD);
|
T component, String groupName, ObjUtils.LevelOfDetail LOD);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,12 +6,14 @@ import net.sf.openrocket.file.wavefrontobj.ObjUtils;
|
|||||||
import net.sf.openrocket.file.wavefrontobj.export.shapes.CylinderExporter;
|
import net.sf.openrocket.file.wavefrontobj.export.shapes.CylinderExporter;
|
||||||
import net.sf.openrocket.file.wavefrontobj.export.shapes.TubeExporter;
|
import net.sf.openrocket.file.wavefrontobj.export.shapes.TubeExporter;
|
||||||
import net.sf.openrocket.rocketcomponent.BodyTube;
|
import net.sf.openrocket.rocketcomponent.BodyTube;
|
||||||
|
import net.sf.openrocket.rocketcomponent.FlightConfiguration;
|
||||||
|
import net.sf.openrocket.rocketcomponent.InstanceContext;
|
||||||
import net.sf.openrocket.util.Coordinate;
|
import net.sf.openrocket.util.Coordinate;
|
||||||
|
|
||||||
public class BodyTubeExporter extends RocketComponentExporter<BodyTube> {
|
public class BodyTubeExporter extends RocketComponentExporter<BodyTube> {
|
||||||
public BodyTubeExporter(DefaultObj obj, CoordTransform transformer, BodyTube component, String groupName,
|
public BodyTubeExporter(DefaultObj obj, FlightConfiguration config, CoordTransform transformer, BodyTube component,
|
||||||
ObjUtils.LevelOfDetail LOD) {
|
String groupName, ObjUtils.LevelOfDetail LOD) {
|
||||||
super(obj, transformer, component, groupName, LOD);
|
super(obj, config, transformer, component, groupName, LOD);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -20,16 +22,15 @@ public class BodyTubeExporter extends RocketComponentExporter<BodyTube> {
|
|||||||
final float innerRadius = (float) component.getInnerRadius();
|
final float innerRadius = (float) component.getInnerRadius();
|
||||||
final float length = (float) component.getLength();
|
final float length = (float) component.getLength();
|
||||||
final boolean isFilled = component.isFilled();
|
final boolean isFilled = component.isFilled();
|
||||||
final Coordinate[] locations = component.getComponentLocations();
|
|
||||||
|
|
||||||
// Generate the mesh
|
// Generate the mesh
|
||||||
for (Coordinate location : locations) {
|
for (InstanceContext context : config.getActiveInstances().getInstanceContexts(component)) {
|
||||||
generateMesh(outerRadius, innerRadius, length, isFilled, location);
|
generateMesh(outerRadius, innerRadius, length, isFilled, context);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void generateMesh(float outerRadius, float innerRadius, float length, boolean isFilled,
|
private void generateMesh(float outerRadius, float innerRadius, float length, boolean isFilled,
|
||||||
Coordinate location) {
|
InstanceContext context) {
|
||||||
int startIdx = obj.getNumVertices();
|
int startIdx = obj.getNumVertices();
|
||||||
|
|
||||||
if (isFilled || Float.compare(innerRadius, 0) == 0) {
|
if (isFilled || Float.compare(innerRadius, 0) == 0) {
|
||||||
@ -45,6 +46,7 @@ public class BodyTubeExporter extends RocketComponentExporter<BodyTube> {
|
|||||||
int endIdx = Math.max(obj.getNumVertices() - 1, startIdx); // Clamp in case no vertices were added
|
int endIdx = Math.max(obj.getNumVertices() - 1, startIdx); // Clamp in case no vertices were added
|
||||||
|
|
||||||
// Translate the mesh to the position in the rocket
|
// Translate the mesh to the position in the rocket
|
||||||
|
Coordinate location = context.getLocation();
|
||||||
ObjUtils.translateVerticesFromComponentLocation(obj, transformer, startIdx, endIdx, location);
|
ObjUtils.translateVerticesFromComponentLocation(obj, transformer, startIdx, endIdx, location);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,15 +7,17 @@ import net.sf.openrocket.file.wavefrontobj.DefaultObj;
|
|||||||
import net.sf.openrocket.file.wavefrontobj.ObjUtils;
|
import net.sf.openrocket.file.wavefrontobj.ObjUtils;
|
||||||
import net.sf.openrocket.file.wavefrontobj.export.shapes.PolygonExporter;
|
import net.sf.openrocket.file.wavefrontobj.export.shapes.PolygonExporter;
|
||||||
import net.sf.openrocket.rocketcomponent.FinSet;
|
import net.sf.openrocket.rocketcomponent.FinSet;
|
||||||
|
import net.sf.openrocket.rocketcomponent.FlightConfiguration;
|
||||||
|
import net.sf.openrocket.rocketcomponent.InstanceContext;
|
||||||
import net.sf.openrocket.util.Coordinate;
|
import net.sf.openrocket.util.Coordinate;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public class FinSetExporter extends RocketComponentExporter<FinSet> {
|
public class FinSetExporter extends RocketComponentExporter<FinSet> {
|
||||||
public FinSetExporter(@NotNull DefaultObj obj, @NotNull CoordTransform transformer, FinSet component,
|
public FinSetExporter(@NotNull DefaultObj obj, FlightConfiguration config, @NotNull CoordTransform transformer,
|
||||||
String groupName, ObjUtils.LevelOfDetail LOD) {
|
FinSet component, String groupName, ObjUtils.LevelOfDetail LOD) {
|
||||||
super(obj, transformer, component, groupName, LOD);
|
super(obj, config, transformer, component, groupName, LOD);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -32,21 +34,15 @@ public class FinSetExporter extends RocketComponentExporter<FinSet> {
|
|||||||
final FloatPoints floatTabPoints = getPointsAsFloat(tabPointsReversed);
|
final FloatPoints floatTabPoints = getPointsAsFloat(tabPointsReversed);
|
||||||
final float thickness = (float) component.getThickness();
|
final float thickness = (float) component.getThickness();
|
||||||
boolean hasTabs = component.getTabLength() > 0 && component.getTabHeight() > 0;
|
boolean hasTabs = component.getTabLength() > 0 && component.getTabHeight() > 0;
|
||||||
final Coordinate[] locations = component.getComponentLocations();
|
|
||||||
final Coordinate[] angles = component.getComponentAngles();
|
|
||||||
|
|
||||||
if (locations.length != angles.length) {
|
|
||||||
throw new IllegalArgumentException("Number of locations and angles must match");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Generate the fin meshes
|
// Generate the fin meshes
|
||||||
for (int i = 0; i < locations.length; i++) {
|
for (InstanceContext context : config.getActiveInstances().getInstanceContexts(component)) {
|
||||||
generateMesh(floatPoints, floatTabPoints, thickness, hasTabs, locations[i], angles[i]);
|
generateMesh(floatPoints, floatTabPoints, thickness, hasTabs, context);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void generateMesh(FloatPoints floatPoints, FloatPoints floatTabPoints, float thickness,
|
private void generateMesh(FloatPoints floatPoints, FloatPoints floatTabPoints, float thickness,
|
||||||
boolean hasTabs, Coordinate location, Coordinate angle) {
|
boolean hasTabs, InstanceContext context) {
|
||||||
// Generate the mesh
|
// Generate the mesh
|
||||||
final int startIdx = obj.getNumVertices();
|
final int startIdx = obj.getNumVertices();
|
||||||
final int normalsStartIdx = obj.getNumNormals();
|
final int normalsStartIdx = obj.getNumNormals();
|
||||||
@ -77,12 +73,16 @@ public class FinSetExporter extends RocketComponentExporter<FinSet> {
|
|||||||
orig.getX(), orig.getY(), orig.getZ());
|
orig.getX(), orig.getY(), orig.getZ());
|
||||||
|
|
||||||
// Then do the component rotation (axial rotation)
|
// Then do the component rotation (axial rotation)
|
||||||
rot = transformer.convertRot(angle.x, angle.y, angle.z);
|
final double rotX = context.transform.getXrotation();
|
||||||
|
final double rotY = context.transform.getYrotation();
|
||||||
|
final double rotZ = context.transform.getZrotation();
|
||||||
|
rot = transformer.convertRot(rotX, rotY, rotZ);
|
||||||
ObjUtils.rotateVertices(obj, startIdx, endIdx, normalsStartIdx, normalsEndIdx,
|
ObjUtils.rotateVertices(obj, startIdx, endIdx, normalsStartIdx, normalsEndIdx,
|
||||||
rot.getX(), rot.getY(), rot.getZ(),
|
rot.getX(), rot.getY(), rot.getZ(),
|
||||||
orig.getX(), orig.getY(), orig.getZ());
|
orig.getX(), orig.getY(), orig.getZ());
|
||||||
|
|
||||||
// Translate the mesh to the position in the rocket
|
// Translate the mesh to the position in the rocket
|
||||||
|
final Coordinate location = context.getLocation();
|
||||||
ObjUtils.translateVerticesFromComponentLocation(obj, transformer, startIdx, endIdx, location);
|
ObjUtils.translateVerticesFromComponentLocation(obj, transformer, startIdx, endIdx, location);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6,29 +6,30 @@ import net.sf.openrocket.file.wavefrontobj.DefaultObj;
|
|||||||
import net.sf.openrocket.file.wavefrontobj.ObjUtils;
|
import net.sf.openrocket.file.wavefrontobj.ObjUtils;
|
||||||
import net.sf.openrocket.file.wavefrontobj.export.shapes.CylinderExporter;
|
import net.sf.openrocket.file.wavefrontobj.export.shapes.CylinderExporter;
|
||||||
import net.sf.openrocket.file.wavefrontobj.export.shapes.TubeExporter;
|
import net.sf.openrocket.file.wavefrontobj.export.shapes.TubeExporter;
|
||||||
|
import net.sf.openrocket.rocketcomponent.FlightConfiguration;
|
||||||
|
import net.sf.openrocket.rocketcomponent.InstanceContext;
|
||||||
import net.sf.openrocket.rocketcomponent.LaunchLug;
|
import net.sf.openrocket.rocketcomponent.LaunchLug;
|
||||||
import net.sf.openrocket.util.Coordinate;
|
import net.sf.openrocket.util.Coordinate;
|
||||||
|
|
||||||
public class LaunchLugExporter extends RocketComponentExporter<LaunchLug> {
|
public class LaunchLugExporter extends RocketComponentExporter<LaunchLug> {
|
||||||
public LaunchLugExporter(@NotNull DefaultObj obj, @NotNull CoordTransform transformer, LaunchLug component,
|
public LaunchLugExporter(@NotNull DefaultObj obj, FlightConfiguration config, @NotNull CoordTransform transformer,
|
||||||
String groupName, ObjUtils.LevelOfDetail LOD) {
|
LaunchLug component, String groupName, ObjUtils.LevelOfDetail LOD) {
|
||||||
super(obj, transformer, component, groupName, LOD);
|
super(obj, config, transformer, component, groupName, LOD);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void addToObj() {
|
public void addToObj() {
|
||||||
final Coordinate[] locations = component.getComponentLocations();
|
|
||||||
final float outerRadius = (float) component.getOuterRadius();
|
final float outerRadius = (float) component.getOuterRadius();
|
||||||
final float innerRadius = (float) component.getInnerRadius();
|
final float innerRadius = (float) component.getInnerRadius();
|
||||||
final float length = (float) component.getLength();
|
final float length = (float) component.getLength();
|
||||||
|
|
||||||
// Generate the mesh
|
// Generate the mesh
|
||||||
for (Coordinate location : locations) {
|
for (InstanceContext context : config.getActiveInstances().getInstanceContexts(component)) {
|
||||||
generateMesh(outerRadius, innerRadius, length, location);
|
generateMesh(outerRadius, innerRadius, length, context);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void generateMesh(float outerRadius, float innerRadius, float length, Coordinate location) {
|
private void generateMesh(float outerRadius, float innerRadius, float length, InstanceContext context) {
|
||||||
int startIdx = obj.getNumVertices();
|
int startIdx = obj.getNumVertices();
|
||||||
|
|
||||||
// Generate the instance mesh
|
// Generate the instance mesh
|
||||||
@ -45,6 +46,7 @@ public class LaunchLugExporter extends RocketComponentExporter<LaunchLug> {
|
|||||||
int endIdx = Math.max(obj.getNumVertices() - 1, startIdx); // Clamp in case no vertices were added
|
int endIdx = Math.max(obj.getNumVertices() - 1, startIdx); // Clamp in case no vertices were added
|
||||||
|
|
||||||
// Translate the mesh to the position in the rocket
|
// Translate the mesh to the position in the rocket
|
||||||
|
final Coordinate location = context.getLocation();
|
||||||
ObjUtils.translateVerticesFromComponentLocation(obj, transformer, startIdx, endIdx, location);
|
ObjUtils.translateVerticesFromComponentLocation(obj, transformer, startIdx, endIdx, location);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,31 +5,32 @@ 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.DefaultObjFace;
|
||||||
import net.sf.openrocket.file.wavefrontobj.ObjUtils;
|
import net.sf.openrocket.file.wavefrontobj.ObjUtils;
|
||||||
|
import net.sf.openrocket.rocketcomponent.FlightConfiguration;
|
||||||
|
import net.sf.openrocket.rocketcomponent.InstanceContext;
|
||||||
import net.sf.openrocket.rocketcomponent.MassObject;
|
import net.sf.openrocket.rocketcomponent.MassObject;
|
||||||
import net.sf.openrocket.util.Coordinate;
|
import net.sf.openrocket.util.Coordinate;
|
||||||
import net.sf.openrocket.util.RocketComponentUtils;
|
import net.sf.openrocket.util.RocketComponentUtils;
|
||||||
|
|
||||||
public class MassObjectExporter extends RocketComponentExporter<MassObject> {
|
public class MassObjectExporter extends RocketComponentExporter<MassObject> {
|
||||||
public MassObjectExporter(@NotNull DefaultObj obj, @NotNull CoordTransform transformer, MassObject component,
|
public MassObjectExporter(@NotNull DefaultObj obj, FlightConfiguration config, @NotNull CoordTransform transformer,
|
||||||
String groupName, ObjUtils.LevelOfDetail LOD) {
|
MassObject component, String groupName, ObjUtils.LevelOfDetail LOD) {
|
||||||
super(obj, transformer, component, groupName, LOD);
|
super(obj, config, transformer, component, groupName, LOD);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void addToObj() {
|
public void addToObj() {
|
||||||
obj.setActiveGroupNames(groupName);
|
obj.setActiveGroupNames(groupName);
|
||||||
|
|
||||||
final Coordinate[] locations = component.getComponentLocations();
|
|
||||||
final int numSides = LOD.getValue() / 2;
|
final int numSides = LOD.getValue() / 2;
|
||||||
final int numStacks = LOD.getValue() / 2;
|
final int numStacks = LOD.getValue() / 2;
|
||||||
|
|
||||||
// Generate the mesh
|
// Generate the mesh
|
||||||
for (Coordinate location : locations) {
|
for (InstanceContext context : config.getActiveInstances().getInstanceContexts(component)) {
|
||||||
generateMesh(numSides, numStacks, location);
|
generateMesh(numSides, numStacks, context);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void generateMesh(int numSides, int numStacks, Coordinate location) {
|
private void generateMesh(int numSides, int numStacks, InstanceContext context) {
|
||||||
// Other meshes may have been added to the obj, so we need to keep track of the starting indices
|
// Other meshes may have been added to the obj, so we need to keep track of the starting indices
|
||||||
int startIdx = obj.getNumVertices();
|
int startIdx = obj.getNumVertices();
|
||||||
int normalsStartIdx = obj.getNumNormals();
|
int normalsStartIdx = obj.getNumNormals();
|
||||||
@ -134,6 +135,7 @@ public class MassObjectExporter extends RocketComponentExporter<MassObject> {
|
|||||||
|
|
||||||
// Translate the mesh to the position in the rocket
|
// Translate the mesh to the position in the rocket
|
||||||
// We will create an offset location that has the same effect as the axial rotation of the mass object
|
// We will create an offset location that has the same effect as the axial rotation of the mass object
|
||||||
|
final Coordinate location = context.getLocation();
|
||||||
Coordinate offsetLocation = getOffsetLocation(location);
|
Coordinate offsetLocation = getOffsetLocation(location);
|
||||||
ObjUtils.translateVerticesFromComponentLocation(obj, transformer, startIdx, endIdx, offsetLocation);
|
ObjUtils.translateVerticesFromComponentLocation(obj, transformer, startIdx, endIdx, offsetLocation);
|
||||||
}
|
}
|
||||||
|
@ -8,6 +8,8 @@ import net.sf.openrocket.file.wavefrontobj.DefaultObjFace;
|
|||||||
import net.sf.openrocket.file.wavefrontobj.ObjUtils;
|
import net.sf.openrocket.file.wavefrontobj.ObjUtils;
|
||||||
import net.sf.openrocket.file.wavefrontobj.export.shapes.CylinderExporter;
|
import net.sf.openrocket.file.wavefrontobj.export.shapes.CylinderExporter;
|
||||||
import net.sf.openrocket.file.wavefrontobj.export.shapes.DiskExporter;
|
import net.sf.openrocket.file.wavefrontobj.export.shapes.DiskExporter;
|
||||||
|
import net.sf.openrocket.rocketcomponent.FlightConfiguration;
|
||||||
|
import net.sf.openrocket.rocketcomponent.InstanceContext;
|
||||||
import net.sf.openrocket.rocketcomponent.RailButton;
|
import net.sf.openrocket.rocketcomponent.RailButton;
|
||||||
import net.sf.openrocket.util.Coordinate;
|
import net.sf.openrocket.util.Coordinate;
|
||||||
|
|
||||||
@ -23,9 +25,9 @@ public class RailButtonExporter extends RocketComponentExporter<RailButton> {
|
|||||||
* @param groupName The name of the group to export to
|
* @param groupName The name of the group to export to
|
||||||
* @param LOD Level of detail to use for the export (e.g. '80')
|
* @param LOD Level of detail to use for the export (e.g. '80')
|
||||||
*/
|
*/
|
||||||
public RailButtonExporter(@NotNull DefaultObj obj, @NotNull CoordTransform transformer, RailButton component,
|
public RailButtonExporter(@NotNull DefaultObj obj, FlightConfiguration config, @NotNull CoordTransform transformer,
|
||||||
String groupName, ObjUtils.LevelOfDetail LOD) {
|
RailButton component, String groupName, ObjUtils.LevelOfDetail LOD) {
|
||||||
super(obj, transformer, component, groupName, LOD);
|
super(obj, config, transformer, component, groupName, LOD);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -38,18 +40,15 @@ public class RailButtonExporter extends RocketComponentExporter<RailButton> {
|
|||||||
final float innerHeight = (float) component.getInnerHeight();
|
final float innerHeight = (float) component.getInnerHeight();
|
||||||
final float flangeHeight = (float) component.getFlangeHeight();
|
final float flangeHeight = (float) component.getFlangeHeight();
|
||||||
final float screwHeight = (float) component.getScrewHeight();
|
final float screwHeight = (float) component.getScrewHeight();
|
||||||
final Coordinate[] locations = component.getComponentLocations();
|
|
||||||
final Coordinate[] angles = component.getComponentAngles();
|
|
||||||
|
|
||||||
// Generate the mesh
|
// Generate the mesh
|
||||||
for (int i = 0; i < locations.length; i++) {
|
for (InstanceContext context : config.getActiveInstances().getInstanceContexts(component)) {
|
||||||
generateMesh(outerRadius, innerRadius, baseHeight, innerHeight, flangeHeight, screwHeight,
|
generateMesh(outerRadius, innerRadius, baseHeight, innerHeight, flangeHeight, screwHeight, context);
|
||||||
locations[i], angles[i]);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void generateMesh(float outerRadius, float innerRadius, float baseHeight, float innerHeight, float flangeHeight,
|
private void generateMesh(float outerRadius, float innerRadius, float baseHeight, float innerHeight, float flangeHeight,
|
||||||
float screwHeight, Coordinate location, Coordinate angle) {
|
float screwHeight, InstanceContext context) {
|
||||||
final int startIdx = obj.getNumVertices();
|
final int startIdx = obj.getNumVertices();
|
||||||
final int normalStartIdx = obj.getNumNormals();
|
final int normalStartIdx = obj.getNumNormals();
|
||||||
|
|
||||||
@ -109,16 +108,17 @@ public class RailButtonExporter extends RocketComponentExporter<RailButton> {
|
|||||||
rot.getX(), rot.getY(), rot.getZ(),
|
rot.getX(), rot.getY(), rot.getZ(),
|
||||||
orig.getX(), orig.getY(), orig.getZ());
|
orig.getX(), orig.getY(), orig.getZ());
|
||||||
|
|
||||||
// Then do the axial rotation
|
// Then do the component rotation (axial rotation)
|
||||||
rX = angle.x + component.getAngleOffset();
|
final double rotX = context.transform.getXrotation() + component.getAngleOffset();
|
||||||
rY = 0;
|
final double rotY = context.transform.getYrotation();
|
||||||
rZ = 0;
|
final double rotZ = context.transform.getZrotation();
|
||||||
rot = transformer.convertRot(rX, rY, rZ);
|
rot = transformer.convertRot(rotX, rotY, rotZ);
|
||||||
ObjUtils.rotateVertices(obj, startIdx, endIdx, normalStartIdx, normalEndIdx,
|
ObjUtils.rotateVertices(obj, startIdx, endIdx, normalStartIdx, normalEndIdx,
|
||||||
rot.getX(), rot.getY(), rot.getZ(),
|
rot.getX(), rot.getY(), rot.getZ(),
|
||||||
orig.getX(), orig.getY(), orig.getZ());
|
orig.getX(), orig.getY(), orig.getZ());
|
||||||
|
|
||||||
// Translate the mesh to the position in the rocket
|
// Translate the mesh to the position in the rocket
|
||||||
|
final Coordinate location = context.getLocation();
|
||||||
ObjUtils.translateVerticesFromComponentLocation(obj, transformer, startIdx, endIdx, location);
|
ObjUtils.translateVerticesFromComponentLocation(obj, transformer, startIdx, endIdx, location);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6,13 +6,15 @@ import net.sf.openrocket.file.wavefrontobj.DefaultObj;
|
|||||||
import net.sf.openrocket.file.wavefrontobj.ObjUtils;
|
import net.sf.openrocket.file.wavefrontobj.ObjUtils;
|
||||||
import net.sf.openrocket.file.wavefrontobj.export.shapes.CylinderExporter;
|
import net.sf.openrocket.file.wavefrontobj.export.shapes.CylinderExporter;
|
||||||
import net.sf.openrocket.file.wavefrontobj.export.shapes.TubeExporter;
|
import net.sf.openrocket.file.wavefrontobj.export.shapes.TubeExporter;
|
||||||
|
import net.sf.openrocket.rocketcomponent.FlightConfiguration;
|
||||||
|
import net.sf.openrocket.rocketcomponent.InstanceContext;
|
||||||
import net.sf.openrocket.rocketcomponent.RingComponent;
|
import net.sf.openrocket.rocketcomponent.RingComponent;
|
||||||
import net.sf.openrocket.util.Coordinate;
|
import net.sf.openrocket.util.Coordinate;
|
||||||
|
|
||||||
public class RingComponentExporter extends RocketComponentExporter<RingComponent> {
|
public class RingComponentExporter extends RocketComponentExporter<RingComponent> {
|
||||||
public RingComponentExporter(@NotNull DefaultObj obj, @NotNull CoordTransform transformer, RingComponent component,
|
public RingComponentExporter(@NotNull DefaultObj obj, FlightConfiguration config, @NotNull CoordTransform transformer,
|
||||||
String groupName, ObjUtils.LevelOfDetail LOD) {
|
RingComponent component, String groupName, ObjUtils.LevelOfDetail LOD) {
|
||||||
super(obj, transformer, component, groupName, LOD);
|
super(obj, config, transformer, component, groupName, LOD);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -20,15 +22,14 @@ public class RingComponentExporter extends RocketComponentExporter<RingComponent
|
|||||||
final float outerRadius = (float) component.getOuterRadius();
|
final float outerRadius = (float) component.getOuterRadius();
|
||||||
final float innerRadius = (float) component.getInnerRadius();
|
final float innerRadius = (float) component.getInnerRadius();
|
||||||
final float length = (float) component.getLength();
|
final float length = (float) component.getLength();
|
||||||
final Coordinate[] locations = component.getComponentLocations();
|
|
||||||
|
|
||||||
// Generate the mesh
|
// Generate the mesh
|
||||||
for (Coordinate location : locations) {
|
for (InstanceContext context : config.getActiveInstances().getInstanceContexts(component)) {
|
||||||
generateMesh(outerRadius, innerRadius, length, location);
|
generateMesh(outerRadius, innerRadius, length, context);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void generateMesh(float outerRadius, float innerRadius, float length, Coordinate location) {
|
private void generateMesh(float outerRadius, float innerRadius, float length, InstanceContext context) {
|
||||||
int startIdx = obj.getNumVertices();
|
int startIdx = obj.getNumVertices();
|
||||||
|
|
||||||
if (Float.compare(innerRadius, 0) == 0) {
|
if (Float.compare(innerRadius, 0) == 0) {
|
||||||
@ -44,6 +45,7 @@ public class RingComponentExporter extends RocketComponentExporter<RingComponent
|
|||||||
int endIdx = Math.max(obj.getNumVertices() - 1, startIdx); // Clamp in case no vertices were added
|
int endIdx = Math.max(obj.getNumVertices() - 1, startIdx); // Clamp in case no vertices were added
|
||||||
|
|
||||||
// Translate the mesh to the position in the rocket
|
// Translate the mesh to the position in the rocket
|
||||||
|
final Coordinate location = context.getLocation();
|
||||||
ObjUtils.translateVerticesFromComponentLocation(obj, transformer, startIdx, endIdx, location);
|
ObjUtils.translateVerticesFromComponentLocation(obj, transformer, startIdx, endIdx, location);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,7 @@ 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.ObjUtils;
|
import net.sf.openrocket.file.wavefrontobj.ObjUtils;
|
||||||
import net.sf.openrocket.file.wavefrontobj.export.OBJExporterFactory;
|
import net.sf.openrocket.file.wavefrontobj.export.OBJExporterFactory;
|
||||||
|
import net.sf.openrocket.rocketcomponent.FlightConfiguration;
|
||||||
import net.sf.openrocket.rocketcomponent.RocketComponent;
|
import net.sf.openrocket.rocketcomponent.RocketComponent;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -15,6 +16,7 @@ import net.sf.openrocket.rocketcomponent.RocketComponent;
|
|||||||
*/
|
*/
|
||||||
public abstract class RocketComponentExporter<T extends RocketComponent> {
|
public abstract class RocketComponentExporter<T extends RocketComponent> {
|
||||||
protected final DefaultObj obj;
|
protected final DefaultObj obj;
|
||||||
|
protected final FlightConfiguration config;
|
||||||
protected final T component;
|
protected final T component;
|
||||||
protected final String groupName;
|
protected final String groupName;
|
||||||
protected final ObjUtils.LevelOfDetail LOD;
|
protected final ObjUtils.LevelOfDetail LOD;
|
||||||
@ -23,14 +25,16 @@ public abstract class RocketComponentExporter<T extends RocketComponent> {
|
|||||||
/**
|
/**
|
||||||
* Wavefront OBJ exporter for a rocket component.
|
* Wavefront OBJ exporter for a rocket component.
|
||||||
* @param obj The OBJ to export to
|
* @param obj The OBJ to export to
|
||||||
|
* @param config The flight configuration to use for the export
|
||||||
* @param transformer Coordinate system transformer to use to switch from the OpenRocket coordinate system to a custom OBJ coordinate system
|
* @param transformer Coordinate system transformer to use to switch from the OpenRocket coordinate system to a custom OBJ coordinate system
|
||||||
* @param component The component to export
|
* @param component The component to export
|
||||||
* @param groupName The name of the group to export to
|
* @param groupName The name of the group to export to
|
||||||
* @param LOD Level of detail to use for the export (e.g. '80')
|
* @param LOD Level of detail to use for the export (e.g. '80')
|
||||||
*/
|
*/
|
||||||
public RocketComponentExporter(@NotNull DefaultObj obj, @NotNull CoordTransform transformer, T component,
|
public RocketComponentExporter(@NotNull DefaultObj obj, @NotNull FlightConfiguration config, @NotNull CoordTransform transformer,
|
||||||
String groupName, ObjUtils.LevelOfDetail LOD) {
|
T component, String groupName, ObjUtils.LevelOfDetail LOD) {
|
||||||
this.obj = obj;
|
this.obj = obj;
|
||||||
|
this.config = config;
|
||||||
this.component = component;
|
this.component = component;
|
||||||
this.groupName = groupName;
|
this.groupName = groupName;
|
||||||
this.LOD = LOD;
|
this.LOD = LOD;
|
||||||
|
@ -9,6 +9,8 @@ import net.sf.openrocket.file.wavefrontobj.ObjUtils;
|
|||||||
import net.sf.openrocket.file.wavefrontobj.export.shapes.CylinderExporter;
|
import net.sf.openrocket.file.wavefrontobj.export.shapes.CylinderExporter;
|
||||||
import net.sf.openrocket.file.wavefrontobj.export.shapes.DiskExporter;
|
import net.sf.openrocket.file.wavefrontobj.export.shapes.DiskExporter;
|
||||||
import net.sf.openrocket.file.wavefrontobj.export.shapes.TubeExporter;
|
import net.sf.openrocket.file.wavefrontobj.export.shapes.TubeExporter;
|
||||||
|
import net.sf.openrocket.rocketcomponent.FlightConfiguration;
|
||||||
|
import net.sf.openrocket.rocketcomponent.InstanceContext;
|
||||||
import net.sf.openrocket.rocketcomponent.Transition;
|
import net.sf.openrocket.rocketcomponent.Transition;
|
||||||
import net.sf.openrocket.util.Coordinate;
|
import net.sf.openrocket.util.Coordinate;
|
||||||
|
|
||||||
@ -19,9 +21,9 @@ public class TransitionExporter extends RocketComponentExporter<Transition> {
|
|||||||
private static final double RADIUS_EPSILON = 1e-4;
|
private static final double RADIUS_EPSILON = 1e-4;
|
||||||
private final int nrOfSides;
|
private final int nrOfSides;
|
||||||
|
|
||||||
public TransitionExporter(@NotNull DefaultObj obj, @NotNull CoordTransform transformer, Transition component,
|
public TransitionExporter(@NotNull DefaultObj obj, FlightConfiguration config, @NotNull CoordTransform transformer,
|
||||||
String groupName, ObjUtils.LevelOfDetail LOD) {
|
Transition component, String groupName, ObjUtils.LevelOfDetail LOD) {
|
||||||
super(obj, transformer, component, groupName, LOD);
|
super(obj, config, transformer, component, groupName, LOD);
|
||||||
this.nrOfSides = LOD.getNrOfSides(Math.max(component.getForeRadius(), component.getAftRadius()));
|
this.nrOfSides = LOD.getNrOfSides(Math.max(component.getForeRadius(), component.getAftRadius()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -29,15 +31,13 @@ public class TransitionExporter extends RocketComponentExporter<Transition> {
|
|||||||
public void addToObj() {
|
public void addToObj() {
|
||||||
obj.setActiveGroupNames(groupName);
|
obj.setActiveGroupNames(groupName);
|
||||||
|
|
||||||
final Coordinate[] locations = component.getComponentLocations();
|
|
||||||
|
|
||||||
// Generate the mesh
|
// Generate the mesh
|
||||||
for (Coordinate location : locations) {
|
for (InstanceContext context : config.getActiveInstances().getInstanceContexts(component)) {
|
||||||
generateMesh(location);
|
generateMesh(context);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void generateMesh(Coordinate location) {
|
private void generateMesh(InstanceContext context) {
|
||||||
int startIdx = obj.getNumVertices();
|
int startIdx = obj.getNumVertices();
|
||||||
|
|
||||||
final boolean hasForeShoulder = Double.compare(component.getForeShoulderRadius(), 0) > 0
|
final boolean hasForeShoulder = Double.compare(component.getForeShoulderRadius(), 0) > 0
|
||||||
@ -99,6 +99,7 @@ public class TransitionExporter extends RocketComponentExporter<Transition> {
|
|||||||
int endIdx = Math.max(obj.getNumVertices() - 1, startIdx); // Clamp in case no vertices were added
|
int endIdx = Math.max(obj.getNumVertices() - 1, startIdx); // Clamp in case no vertices were added
|
||||||
|
|
||||||
// Translate the mesh to the position in the rocket
|
// Translate the mesh to the position in the rocket
|
||||||
|
final Coordinate location = context.getLocation();
|
||||||
ObjUtils.translateVerticesFromComponentLocation(obj, transformer, startIdx, endIdx, location);
|
ObjUtils.translateVerticesFromComponentLocation(obj, transformer, startIdx, endIdx, location);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,13 +5,15 @@ 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.ObjUtils;
|
import net.sf.openrocket.file.wavefrontobj.ObjUtils;
|
||||||
import net.sf.openrocket.file.wavefrontobj.export.shapes.TubeExporter;
|
import net.sf.openrocket.file.wavefrontobj.export.shapes.TubeExporter;
|
||||||
|
import net.sf.openrocket.rocketcomponent.FlightConfiguration;
|
||||||
|
import net.sf.openrocket.rocketcomponent.InstanceContext;
|
||||||
import net.sf.openrocket.rocketcomponent.TubeFinSet;
|
import net.sf.openrocket.rocketcomponent.TubeFinSet;
|
||||||
import net.sf.openrocket.util.Coordinate;
|
import net.sf.openrocket.util.Coordinate;
|
||||||
|
|
||||||
public class TubeFinSetExporter extends RocketComponentExporter<TubeFinSet> {
|
public class TubeFinSetExporter extends RocketComponentExporter<TubeFinSet> {
|
||||||
public TubeFinSetExporter(@NotNull DefaultObj obj, @NotNull CoordTransform transformer, TubeFinSet component, String groupName,
|
public TubeFinSetExporter(@NotNull DefaultObj obj, FlightConfiguration config, @NotNull CoordTransform transformer,
|
||||||
ObjUtils.LevelOfDetail LOD) {
|
TubeFinSet component, String groupName, ObjUtils.LevelOfDetail LOD) {
|
||||||
super(obj, transformer, component, groupName, LOD);
|
super(obj, config, transformer, component, groupName, LOD);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -21,20 +23,14 @@ public class TubeFinSetExporter extends RocketComponentExporter<TubeFinSet> {
|
|||||||
final float outerRadius = (float) component.getOuterRadius();
|
final float outerRadius = (float) component.getOuterRadius();
|
||||||
final float innerRadius = (float) component.getInnerRadius();
|
final float innerRadius = (float) component.getInnerRadius();
|
||||||
final float length = (float) component.getLength();
|
final float length = (float) component.getLength();
|
||||||
final Coordinate[] locations = component.getComponentLocations();
|
|
||||||
final double[] angles = component.getInstanceAngles();
|
|
||||||
|
|
||||||
if (locations.length != angles.length) {
|
|
||||||
throw new IllegalArgumentException("Number of locations and angles must match");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Generate the fin meshes
|
// Generate the fin meshes
|
||||||
for (int i = 0; i < locations.length; i++) {
|
for (InstanceContext context : config.getActiveInstances().getInstanceContexts(component)) {
|
||||||
generateMesh(outerRadius, innerRadius, length, locations[i], angles[i]);
|
generateMesh(outerRadius, innerRadius, length, context);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void generateMesh(float outerRadius, float innerRadius, float length, Coordinate location, double angle) {
|
private void generateMesh(float outerRadius, float innerRadius, float length, InstanceContext context) {
|
||||||
// Create the fin meshes
|
// Create the fin meshes
|
||||||
final int startIdx = obj.getNumVertices();
|
final int startIdx = obj.getNumVertices();
|
||||||
|
|
||||||
@ -45,14 +41,16 @@ public class TubeFinSetExporter extends RocketComponentExporter<TubeFinSet> {
|
|||||||
|
|
||||||
// Translate the mesh to the position in the rocket
|
// Translate the mesh to the position in the rocket
|
||||||
// We will create an offset location that has the same effect as the axial rotation of the launch lug
|
// We will create an offset location that has the same effect as the axial rotation of the launch lug
|
||||||
Coordinate offsetLocation = getOffsetLocation(outerRadius, location, angle);
|
final double rotX = context.transform.getXrotation();
|
||||||
|
final Coordinate location = context.getLocation();
|
||||||
|
Coordinate offsetLocation = getOffsetLocation(outerRadius, location, rotX);
|
||||||
ObjUtils.translateVerticesFromComponentLocation(obj, transformer, startIdx, endIdx, offsetLocation);
|
ObjUtils.translateVerticesFromComponentLocation(obj, transformer, startIdx, endIdx, offsetLocation);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Coordinate getOffsetLocation(float outerRadius, Coordinate location, double angle) {
|
private static Coordinate getOffsetLocation(float outerRadius, Coordinate location, double rotX) {
|
||||||
// ! This is all still referenced to the OpenRocket coordinate system, not the OBJ one
|
// ! This is all still referenced to the OpenRocket coordinate system, not the OBJ one
|
||||||
final float dy = outerRadius * (float) Math.cos(angle);
|
final float dy = outerRadius * (float) Math.cos(rotX);
|
||||||
final float dz = outerRadius * (float) Math.sin(angle);
|
final float dz = outerRadius * (float) Math.sin(rotX);
|
||||||
final double x = location.x;
|
final double x = location.x;
|
||||||
final double y = location.y + dy;
|
final double y = location.y + dy;
|
||||||
final double z = location.z + dz;
|
final double z = location.z + dz;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user