Merge pull request #1241 from JoePfeiffer/fix-1229
Process entire part tree when finding active contexts
This commit is contained in:
commit
57ffff40a8
@ -64,6 +64,7 @@ public class FlightConfiguration implements FlightConfigurableParameter<FlightCo
|
||||
final protected HashMap<Integer, StageFlags> stages = new HashMap<Integer, StageFlags>();
|
||||
final protected HashMap<MotorConfigurationId, MotorConfiguration> motors = new HashMap<MotorConfigurationId, MotorConfiguration>();
|
||||
final private Collection<MotorConfiguration> activeMotors = new ArrayList<MotorConfiguration>();
|
||||
final private InstanceMap activeInstances = new InstanceMap();
|
||||
|
||||
private int boundsModID = -1;
|
||||
private BoundingBox cachedBounds = new BoundingBox();
|
||||
@ -101,6 +102,7 @@ public class FlightConfiguration implements FlightConfigurableParameter<FlightCo
|
||||
|
||||
updateStages();
|
||||
updateMotors();
|
||||
updateActiveInstances();
|
||||
}
|
||||
|
||||
public Rocket getRocket() {
|
||||
@ -121,12 +123,14 @@ public class FlightConfiguration implements FlightConfigurableParameter<FlightCo
|
||||
cur.active = _active;
|
||||
}
|
||||
updateMotors();
|
||||
updateActiveInstances();
|
||||
}
|
||||
|
||||
public void copyStages(FlightConfiguration other) {
|
||||
for (StageFlags cur : other.stages.values())
|
||||
stages.put(cur.stageNumber, new StageFlags(cur.stageNumber, cur.active));
|
||||
updateMotors();
|
||||
updateActiveInstances();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -137,6 +141,7 @@ public class FlightConfiguration implements FlightConfigurableParameter<FlightCo
|
||||
public void clearStage(final int stageNumber) {
|
||||
_setStageActive( stageNumber, false );
|
||||
updateMotors();
|
||||
updateActiveInstances();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -163,6 +168,7 @@ public class FlightConfiguration implements FlightConfigurableParameter<FlightCo
|
||||
_setStageActive(i, true);
|
||||
}
|
||||
updateMotors();
|
||||
updateActiveInstances();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -174,6 +180,7 @@ public class FlightConfiguration implements FlightConfigurableParameter<FlightCo
|
||||
_setAllStages(false);
|
||||
_setStageActive(stageNumber, true);
|
||||
updateMotors();
|
||||
updateActiveInstances();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -196,9 +203,11 @@ public class FlightConfiguration implements FlightConfigurableParameter<FlightCo
|
||||
if ((0 <= stageNumber) && (stages.containsKey(stageNumber))) {
|
||||
StageFlags flags = stages.get(stageNumber);
|
||||
flags.active = !flags.active;
|
||||
updateMotors();
|
||||
updateActiveInstances();
|
||||
|
||||
return;
|
||||
}
|
||||
updateMotors();
|
||||
log.error("error: attempt to retrieve via a bad stage number: " + stageNumber);
|
||||
}
|
||||
|
||||
@ -286,21 +295,22 @@ public class FlightConfiguration implements FlightConfigurableParameter<FlightCo
|
||||
return toReturn;
|
||||
}
|
||||
|
||||
public InstanceMap getActiveInstances() {
|
||||
return activeInstances;
|
||||
}
|
||||
|
||||
/*
|
||||
* Generates a read-only, instance-aware collection of the components for this rocket & configuration
|
||||
*
|
||||
* TODO: swap in this function for the 'getActiveComponents() function, above; ONLY WHEN READY / MATURE!
|
||||
*/
|
||||
public InstanceMap getActiveInstances() {
|
||||
InstanceMap contexts = new InstanceMap();
|
||||
getActiveContextListAt( this.rocket, contexts, Transformation.IDENTITY);
|
||||
return contexts;
|
||||
private void updateActiveInstances() {
|
||||
activeInstances.clear();
|
||||
getActiveContextListAt( this.rocket, activeInstances, Transformation.IDENTITY);
|
||||
}
|
||||
|
||||
private InstanceMap getActiveContextListAt(final RocketComponent component, final InstanceMap results, final Transformation parentTransform ){
|
||||
final boolean active = this.isComponentActive(component);
|
||||
if (!active)
|
||||
return results;
|
||||
|
||||
final int instanceCount = component.getInstanceCount();
|
||||
final Coordinate[] allOffsets = component.getInstanceOffsets();
|
||||
final double[] allAngles = component.getInstanceAngles();
|
||||
@ -314,9 +324,11 @@ public class FlightConfiguration implements FlightConfigurableParameter<FlightCo
|
||||
final Transformation angleTransform = Transformation.getAxialRotation(allAngles[currentInstanceNumber]);
|
||||
final Transformation currentTransform = componentTransform.applyTransformation(offsetTransform)
|
||||
.applyTransformation(angleTransform);
|
||||
|
||||
// constructs entry in-place
|
||||
results.emplace(component, active, currentInstanceNumber, currentTransform);
|
||||
|
||||
// constructs entry in-place if this component is active
|
||||
if (this.isComponentActive(component)) {
|
||||
results.emplace(component, this.isComponentActive(component), currentInstanceNumber, currentTransform);
|
||||
}
|
||||
|
||||
for(RocketComponent child : component.getChildren()) {
|
||||
getActiveContextListAt(child, results, currentTransform);
|
||||
@ -401,6 +413,7 @@ public class FlightConfiguration implements FlightConfigurableParameter<FlightCo
|
||||
|
||||
updateStages();
|
||||
updateMotors();
|
||||
updateActiveInstances();
|
||||
}
|
||||
|
||||
private void updateStages() {
|
||||
@ -531,6 +544,7 @@ public class FlightConfiguration implements FlightConfigurableParameter<FlightCo
|
||||
public void update(){
|
||||
updateStages();
|
||||
updateMotors();
|
||||
updateActiveInstances();
|
||||
}
|
||||
|
||||
/////////////// Helper methods ///////////////
|
||||
@ -604,35 +618,12 @@ public class FlightConfiguration implements FlightConfigurableParameter<FlightCo
|
||||
}
|
||||
|
||||
for (InstanceContext context : contexts) {
|
||||
/*
|
||||
* If the instance is not active in the current context, then
|
||||
* skip the bound calculations. This is mildly confusing since
|
||||
* getActiveInstances() implies that it will only return the
|
||||
* instances that are active, but it returns all instances and
|
||||
* the context indicates if it is active or not.
|
||||
*/
|
||||
if (!context.active) {
|
||||
// break out of per-instance loop.
|
||||
break;
|
||||
}
|
||||
|
||||
componentBounds.update(instanceBounds.transform(context.transform));
|
||||
}
|
||||
} else {
|
||||
// Legacy Case: These components do not implement the BoxBounded Interface.
|
||||
Collection<Coordinate> instanceCoordinates = component.getComponentBounds();
|
||||
for (InstanceContext context : contexts) {
|
||||
/*
|
||||
* If the instance is not active in the current context, then
|
||||
* skip the bound calculations. This is mildly confusing since
|
||||
* getActiveInstances() implies that it will only return the
|
||||
* instances that are active, but it returns all instances and
|
||||
* the context indicates if it is active or not.
|
||||
*/
|
||||
if (!context.active) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Collection<Coordinate> transformedCoords = new ArrayList<>(instanceCoordinates);
|
||||
// mutating. Transforms coordinates in place.
|
||||
context.transform.transform(instanceCoordinates);
|
||||
|
@ -26,9 +26,8 @@ public class InstanceContext {
|
||||
return component.hashCode();
|
||||
}
|
||||
|
||||
public InstanceContext(final RocketComponent _component, final boolean _active, final int _instanceNumber, final Transformation _transform) {
|
||||
public InstanceContext(final RocketComponent _component, final int _instanceNumber, final Transformation _transform) {
|
||||
component = _component;
|
||||
active = _active;
|
||||
instanceNumber = _instanceNumber;
|
||||
transform = _transform;
|
||||
|
||||
@ -48,7 +47,6 @@ public class InstanceContext {
|
||||
|
||||
// ==== public ====
|
||||
final public RocketComponent component;
|
||||
final public boolean active;
|
||||
final public int instanceNumber;
|
||||
final public Transformation transform;
|
||||
|
||||
|
@ -34,7 +34,7 @@ public class InstanceMap extends HashMap<RocketComponent, ArrayList<InstanceCont
|
||||
put(key, new ArrayList<InstanceContext>());
|
||||
}
|
||||
|
||||
final InstanceContext context = new InstanceContext(component, active, number, xform);
|
||||
final InstanceContext context = new InstanceContext(component, number, xform);
|
||||
get(key).add(context);
|
||||
}
|
||||
|
||||
|
@ -66,7 +66,6 @@ import net.sf.openrocket.simulation.listeners.SimulationListener;
|
||||
import net.sf.openrocket.startup.Application;
|
||||
|
||||
public class TestRockets {
|
||||
|
||||
public final static FlightConfigurationId TEST_FCID_0 = new FlightConfigurationId("d010716e-ce0e-469d-ae46-190f3653ebbf");
|
||||
public final static FlightConfigurationId TEST_FCID_1 = new FlightConfigurationId("f41bee5b-ebb8-4d92-bce7-53001577a313");
|
||||
public final static FlightConfigurationId TEST_FCID_2 = new FlightConfigurationId("3e8d1280-53c2-4234-89a7-de215ef5cd69");
|
||||
@ -1705,30 +1704,32 @@ public class TestRockets {
|
||||
|
||||
// find the body and fins
|
||||
final InstanceMap imap = rocket.getSelectedConfiguration().getActiveInstances();
|
||||
for(Map.Entry<RocketComponent, ArrayList<InstanceContext>> entry: imap.entrySet() ) {
|
||||
RocketComponent c = entry.getKey();
|
||||
RocketComponent c = null;
|
||||
for(Map.Entry<RocketComponent, ArrayList<InstanceContext>> entry: imap.entrySet() ) {
|
||||
c = entry.getKey();
|
||||
if (c instanceof TrapezoidFinSet) {
|
||||
final TrapezoidFinSet fins = (TrapezoidFinSet) c;
|
||||
final BodyTube body = (BodyTube) fins.getParent();
|
||||
body.removeChild(fins);
|
||||
|
||||
// create a PodSet to hook the fins to
|
||||
PodSet podset = new PodSet();
|
||||
podset.setInstanceCount(fins.getFinCount());
|
||||
|
||||
body.addChild(podset);
|
||||
|
||||
// put a phantom body tube on the pods
|
||||
BodyTube podBody = new BodyTube(fins.getRootChord(), 0);
|
||||
podBody.setName("Pod Body");
|
||||
podset.addChild(podBody);
|
||||
|
||||
// change the number of fins to 1 and put the revised
|
||||
// finset on the podbody
|
||||
fins.setFinCount(1);
|
||||
podBody.addChild(fins);
|
||||
break;
|
||||
}
|
||||
}
|
||||
final TrapezoidFinSet fins = (TrapezoidFinSet) c;
|
||||
final BodyTube body = (BodyTube) fins.getParent();
|
||||
body.removeChild(fins);
|
||||
|
||||
// create a PodSet to hook the fins to
|
||||
PodSet podset = new PodSet();
|
||||
podset.setInstanceCount(fins.getFinCount());
|
||||
|
||||
body.addChild(podset);
|
||||
|
||||
// put a phantom body tube on the pods
|
||||
BodyTube podBody = new BodyTube(fins.getRootChord(), 0);
|
||||
podBody.setName("Pod Body");
|
||||
podset.addChild(podBody);
|
||||
|
||||
// change the number of fins to 1 and put the revised
|
||||
// finset on the podbody
|
||||
fins.setFinCount(1);
|
||||
podBody.addChild(fins);
|
||||
|
||||
return rocket;
|
||||
}
|
||||
|
@ -85,21 +85,19 @@ public abstract class RocketRenderer {
|
||||
if (ignore != null && ignore.contains(comp))
|
||||
continue;
|
||||
|
||||
if( geom.active ) {
|
||||
final int hashCode = comp.hashCode();
|
||||
|
||||
selectionMap.put(hashCode, comp);
|
||||
|
||||
gl.glColor4ub((byte) ((hashCode >> 24) & 0xFF), // red channel (LSB)
|
||||
(byte) ((hashCode >> 16) & 0xFF), // green channel
|
||||
(byte) ((hashCode >> 8) & 0xFF), // blue channel
|
||||
(byte) ((hashCode) & 0xFF)); // alpha channel (MSB)
|
||||
|
||||
if (isDrawnTransparent(comp)) {
|
||||
geom.render(gl, Surface.INSIDE);
|
||||
} else {
|
||||
geom.render(gl, Surface.ALL);
|
||||
}
|
||||
final int hashCode = comp.hashCode();
|
||||
|
||||
selectionMap.put(hashCode, comp);
|
||||
|
||||
gl.glColor4ub((byte) ((hashCode >> 24) & 0xFF), // red channel (LSB)
|
||||
(byte) ((hashCode >> 16) & 0xFF), // green channel
|
||||
(byte) ((hashCode >> 8) & 0xFF), // blue channel
|
||||
(byte) ((hashCode) & 0xFF)); // alpha channel (MSB)
|
||||
|
||||
if (isDrawnTransparent(comp)) {
|
||||
geom.render(gl, Surface.INSIDE);
|
||||
} else {
|
||||
geom.render(gl, Surface.ALL);
|
||||
}
|
||||
}
|
||||
|
||||
@ -186,7 +184,6 @@ public abstract class RocketRenderer {
|
||||
|
||||
for(InstanceContext context: contextList ) {
|
||||
Geometry instanceGeometry = cr.getComponentGeometry( comp, context.transform );
|
||||
instanceGeometry.active = context.active;
|
||||
treeGeometry.add( instanceGeometry );
|
||||
}
|
||||
}
|
||||
@ -196,19 +193,15 @@ public abstract class RocketRenderer {
|
||||
private void renderTree( GL2 gl, final Collection<Geometry> geometryList){
|
||||
//cycle through opaque components first, then transparent to preserve proper depth testing
|
||||
for(Geometry geom: geometryList ) {
|
||||
if( geom.active ) {
|
||||
//if not transparent
|
||||
if( !isDrawnTransparent( (RocketComponent)geom.obj) ){
|
||||
renderComponent(gl, geom, 1.0f);
|
||||
}
|
||||
//if not transparent
|
||||
if( !isDrawnTransparent( (RocketComponent)geom.obj) ){
|
||||
renderComponent(gl, geom, 1.0f);
|
||||
}
|
||||
}
|
||||
for(Geometry geom: geometryList ) {
|
||||
if( geom.active ) {
|
||||
if( isDrawnTransparent( (RocketComponent)geom.obj) ){
|
||||
// Draw T&T front faces blended, without depth test
|
||||
renderComponent(gl, geom, 0.2f);
|
||||
}
|
||||
if( isDrawnTransparent( (RocketComponent)geom.obj) ){
|
||||
// Draw T&T front faces blended, without depth test
|
||||
renderComponent(gl, geom, 0.2f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -25,8 +25,6 @@ public abstract class Geometry {
|
||||
public final Object obj;
|
||||
public final Transformation transform;
|
||||
|
||||
public boolean active;
|
||||
|
||||
public abstract void render(GL2 gl, Surface which );
|
||||
|
||||
private Geometry() {
|
||||
|
@ -378,11 +378,7 @@ public class RocketFigure extends AbstractScaleFigure {
|
||||
|
||||
for(InstanceContext context: contextList ) {
|
||||
final Transformation currentTransform = this.axialRotation.applyTransformation(context.transform);
|
||||
|
||||
// generate shape for this component, if active
|
||||
if( context.active ) {
|
||||
allShapes = addThisShape( allShapes, this.currentViewType, comp, currentTransform);
|
||||
}
|
||||
allShapes = addThisShape( allShapes, this.currentViewType, comp, currentTransform);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user