Commit 7de01609 authored by Philip Levis's avatar Philip Levis
Browse files

Phew!

Merge branch 'dev/engine-ashley' of code.stanford.edu:plevis/ee185 into dev/pal
parents 02563489 04278f79
......@@ -92,6 +92,8 @@ class UIFlightDrawer extends UI3dComponent implements GeometryConstants {
* and its body hanging down in the Y axis.
*/
private void drawFlyer(PGraphics pg, Flyer flyer) {
LXEngine.Frame frame = lx.getUIFrame();
int colors[] = frame.getColors();
// All of these values are in inches, taken from
// FRACTAL_FLYER/drawings/body-dimensions-for-ui-graphics.pdf
pg.pushMatrix();
......@@ -111,8 +113,7 @@ class UIFlightDrawer extends UI3dComponent implements GeometryConstants {
// Left wing
Wing leftWing = flyer.getLeftWing();
List<LightSamplePoint> leftLights = leftWing.getLightPoints();
pg.fill(leftLights.get(0).getColor()); // Just use point 0 for the wing for now
pg.fill(colors[wingLightIndex(flyer.getIndex(), false, 0)]); // Just use point 0 for the wing for now
pg.pushMatrix();
pg.translate(4.01, 0, 4.96);
pg.rotateY(PI/18); // The wing edge is 10 degrees from centerline
......@@ -127,8 +128,7 @@ class UIFlightDrawer extends UI3dComponent implements GeometryConstants {
// Right wing
Wing rightWing = flyer.getRightWing();
List<LightSamplePoint> rightLights = rightWing.getLightPoints();
pg.fill(rightLights.get(0).getColor()); // Just use point 0 for the wing for now
pg.fill(colors[wingLightIndex(flyer.getIndex(), true, 0)]); // Just use point 0 for the wing for now
pg.pushMatrix();
pg.translate(4.01, 0, -4.96);
pg.rotateY(- PI/18); // The wing edge is 10 degrees from centerline
......@@ -142,8 +142,7 @@ class UIFlightDrawer extends UI3dComponent implements GeometryConstants {
pg.popMatrix();
// Body shell
LightSamplePoint bodyLight = model.getFlyerBodyLight(flyer.getIndex());
pg.fill(bodyLight.getColor());
pg.fill(colors[bodyLightIndex(flyer.getIndex())]);
pg.beginShape();
pg.vertex(0, 0, 0);
......
......@@ -80,14 +80,7 @@ void settings() { size(WIDTH, HEIGHT, P3D); }
*/
void initializeModel(FlyerConfig[] flyers) {
model = new Model(flyers).getFlightModel();
List<LightSamplePoint> wingLights = model.getAllWingsLights();
for (LightSamplePoint light: wingLights) {
light.setColor(LXColor.hsb(0, 0.5, 0.8));
}
List<LightSamplePoint> bodyLights = model.getAllBodyLights();
for (LightSamplePoint light: bodyLights) {
light.setColor(LXColor.hsb(0.7, 0.5, 0.8));
}
List<LightSamplePointModel> wingLights = model.getAllWingsLights();
}
/**
......
import heronarts.lx.LX;
import heronarts.lx.effect.LXEffect;
import heronarts.lx.model.LXModel;
import heronarts.lx.effect.LXModelEffect;
import heronarts.lx.model.LXPoint;
abstract class Effect extends LXEffect {
abstract class Effect extends LXModelEffect<FlightModel> {
protected FlightModel model;
Effect(LX lx) {
super(lx);
model = (FlightModel)lx.getModel();
}
@Override
public void loop(double deltaMs) {
if (isEnabled()) {
super.loop(deltaMs);
}
// REVIEW(mcslee): this is already handled by LXEffect
// unclear if there's some different goal here?
// @Override
// public void loop(double deltaMs) {
// if (isEnabled()) {
// super.loop(deltaMs);
// }
// }
/**
* Get the current color at this point
*
* @param p Point
* @return Current color of this point
*/
public int getColor(LXPoint p) {
return this.colors[p.index];
}
/**
* Update the color for the given point
*
* @param p Point
* @param color The color to set for this point
*/
public void setColor(LXPoint p, int color) {
this.colors[p.index] = color;
}
// REVIEW(mcslee): I would suggest collapsing your distinction between
// the interface and class, then these metohds will just work without
// an extra layer of method call abstraction around LXPoint, the above
// methods should be sufficient
// public int getColor(LightSamplePoint p) {
// return this.colors[p.getIndex()];
// }
//
// public void setColor(LightSamplePoint p, int color) {
// this.colors[p.getIndex()] = color;
// }
@Override
public void onModelChanged(LXModel model) {
super.onModelChanged(model);
this.model = (FlightModel)model;
}
}
......@@ -13,45 +13,51 @@ abstract interface Flight extends GeometryConstants {
* pattern getters for all flyers
*/
/* ------------- all flyers, motion ------------- */
List<Wing> getAllWings();
List<Wing> getAllLeftWings();
List<Wing> getAllRightWings();
List<? extends Wing> getAllWings();
List<? extends Wing> getAllLeftWings();
List<? extends Wing> getAllRightWings();
int[] getAllWingsSkew();
int[] getAllLeftWingsSkew();
int[] getAllRightWingsSkew();
/* ------------- all flyers, lights ------------- */
List<LightSamplePoint> getAllLights();
List<? extends LightSamplePoint> getAllLights();
List<LightSamplePoint> getAllBodyLights();
List<LightSamplePoint> getAllWingsLights();
List<LightSamplePoint> getAllWingsPositionIndexedLights(int positionIndex); // head
List<? extends LightSamplePoint> getAllBodyLights();
List<? extends LightSamplePoint> getAllWingsLights();
List<? extends LightSamplePoint> getAllWingsPositionIndexedLights(int positionIndex); // head
// left wings
List<LightSamplePoint> getAllLeftWingLights();
List<LightSamplePoint> getAllLeftWingPositionIndexedLights(int positionIndex);
List<? extends LightSamplePoint> getAllLeftWingLights();
List<? extends LightSamplePoint> getAllLeftWingPositionIndexedLights(int positionIndex);
// right wings
List<LightSamplePoint> getAllRightWingLights();
List<LightSamplePoint> getAllRightWingPositionIndexedLights(int positionIndex);
List<? extends LightSamplePoint> getAllRightWingLights();
List<? extends LightSamplePoint> getAllRightWingPositionIndexedLights(int positionIndex);
/**
* pattern getters for individual flyers
*/
/* ------------- one flyer, motion ------------- */
List<? extends Wing> getFlyerWings(int flyerIndex);
Wing getFlyerLeftWing(int flyerIndex);
Wing getFlyerRightWing(int flyerIndex);
List<Wing> getFlyerWings(int flyerIndex);
int[] getFlyerWingsSkew(int flyerIndex);
int getFlyerLeftWingSkew(int flyerIndex);
int getFlyerRightWingSkew(int flyerIndex);
/* ------------- one flyer, lights ------------- */
List<LightSamplePoint> getFlyerLights(int flyerIndex);
List<? extends LightSamplePoint> getFlyerLights(int flyerIndex);
LightSamplePoint getFlyerBodyLight(int flyerIndex);
List<LightSamplePoint> getFlyerWingsLights(int flyerIndex);
List<LightSamplePoint> getFlyerWingsPositionIndexedLights(int flyerIndex, int positionIndex);
List<? extends LightSamplePoint> getFlyerWingsLights(int flyerIndex);
List<? extends LightSamplePoint> getFlyerWingsPositionIndexedLights(int flyerIndex, int positionIndex);
List<LightSamplePoint> getFlyerLeftWingLights(int flyerIndex);
List<? extends LightSamplePoint> getFlyerLeftWingLights(int flyerIndex);
LightSamplePoint getFlyerLeftWingPositionIndexedLights(int flyerIndex, int positionIndex);
List<LightSamplePoint> getFlyerRightWingLights(int flyerIndex);
List<? extends LightSamplePoint> getFlyerRightWingLights(int flyerIndex);
LightSamplePoint getFlyerRightWingPositionIndexedLights(int flyerIndex, int positionIndex);
......@@ -68,5 +74,5 @@ abstract interface Flight extends GeometryConstants {
*/
FlyerConfig[] getFlyerConfigs();
List<Flyer> getFlyers();
List<? extends Flyer> getFlyers();
}
\ No newline at end of file
import java.util.List;
import heronarts.lx.model.LXModel;
import heronarts.lx.model.LXPoint;
abstract interface Flyer extends GeometryConstants {
public final static int PIXELS_PER_BODY =
NUM_LIGHT_POINTS_PER_FLYER;
LightSamplePoint.LightCorners.BODY.numPixels;
int getIndex();
......@@ -27,7 +25,7 @@ abstract interface Flyer extends GeometryConstants {
LXPoint getBodyLightPoint();
List<LightSamplePoint> getLightPoints();
// List<? extends LXPoint> getLightPoints();
FlyerConfig getConfig();
......
......@@ -4,9 +4,11 @@ import heronarts.lx.color.LXColor;
import heronarts.lx.parameter.BooleanParameter;
import heronarts.lx.parameter.DiscreteParameter;
import heronarts.lx.parameter.LXParameter;
import heronarts.lx.parameter.LXParameterListener;
import heronarts.lx.modulator.QuadraticEnvelope;
import java.util.List;
import java.util.ArrayList;
class FlyerHighlighter extends Effect {
final FlyerConfig[] flyerConfigurations;
......@@ -18,24 +20,42 @@ class FlyerHighlighter extends Effect {
super(lx);
flyerConfigurations = configs;
flyerIndex = new DiscreteParameter("FLYER", flyerConfigurations.length);
flyerIndex.addListener(new LXParameterListener() {
public void onParameterChanged(LXParameter parameter) {
strobe.setStartValue(100);
strobe.trigger();
}
});
// REVIEW(mcslee): add the parameter to the component, and your effect
// will automatically be registered as a listener
addParameter("flyerIndex", flyerIndex);
// flyerIndex.addListener(new LXParameterListener() {
// public void onParameterChanged(LXParameter parameter) {
// strobe.setStartValue(100);
// strobe.trigger();
// }
// });
addModulator(strobe).start();
addLayer(new HighlightLayer());
}
// REVIEW(mcslee): automatically receive these changes from our
// registered parameter
@Override
public void onParameterChanged(LXParameter p) {
if (p == flyerIndex) {
strobe.setStartValue(100);
strobe.trigger();
}
}
FlyerConfig getConfig() {
return flyerConfigurations[flyerIndex.getValuei()];
}
Flyer getFlyer() {
FlyerModel getFlyer() {
return model.getFlyer(flyerIndex.getValuei());
}
List<LightSamplePointModel> getFlyerLightPoints() {
return model.getFlyerLights(flyerIndex.getValuei());
}
void reloadModel() {
Model m = new Model(flyerConfigurations);
lx.setModel(m.getFlightModel());
......@@ -46,23 +66,31 @@ class FlyerHighlighter extends Effect {
}
void highlight() {
// REVIEW(mcslee): looks redunant with HighlightLayer below?
if (isEnabled()) {
for (LightSamplePoint point: model.getFlyerLights(getFlyer().getIndex())) {
int oldColor = point.getColor();
for (LightSamplePointModel point : getFlyerLightPoints()) {
int oldColor = getColor(point);
float val = strobe.getValuef();
int highlightColor = lx.hsb(0, 0, val);
int highlightColor = LX.hsb(0, 0, val);
int newColor = LXColor.blend(oldColor,
highlightColor,
LXColor.Blend.ADD);
point.setColor(newColor);
setColor(point, newColor);
}
}
}
public void run(double deltaMs) {}
// REVIEW(mcslee): this doesn't do anything
// public void run(double deltaMs) {}
@Override
public void run(double deltaMs, double foo) {}
public void run(double deltaMs, double enabledAmount) {
// REVIEW(mcslee): this is where your effect logic should be
}
// REVIEW(mcslee): not sure there's any reason for a layer here, put this logic in
// the run(double deltaMs, double foo)
class HighlightLayer extends LXLayer {
HighlightLayer() {
......@@ -72,14 +100,14 @@ class FlyerHighlighter extends Effect {
@Override
public void run(double deltaMs) {
if (isEnabled()) {
for (LightSamplePoint point: ((FlightModel) model).getFlyerLights(getFlyer().getIndex())) {
int oldColor = point.getColor();
for (LightSamplePointModel point : getFlyerLightPoints()) {
int oldColor = getColor(point);
float val = strobe.getValuef();
int highlightColor = lx.hsb(0, 0, val);
int highlightColor = LX.hsb(0, 0, val);
int newColor = LXColor.blend(oldColor,
highlightColor,
LXColor.Blend.ADD);
point.setColor(newColor);
FlyerHighlighter.this.setColor(point, newColor);
}
}
}
......
......@@ -13,18 +13,18 @@ import heronarts.lx.model.LXPoint;
import heronarts.lx.output.LXOutput;
import java.awt.Color;
/*
* Generates python command for fractal flyer
* TODO change colour representation in model from string to value
*/
public class Generator extends LXOutput implements GeometryConstants {
final Flight flight;
final List<Flyer> flyers;
final FlightModel flight;
final List<FlyerModel> flyers;
final DataInput[] in;
final PrintStream[] out;
protected int[] frameColors;
static final String LEFT_WING_POS = "wing_angle(LEFT, %s)\n";
static final String RIGHT_WING_POS = "wing_angle(RIGHT, %s)\n";
static final String LEFT_WING_LEDs = "wing_leds(LEFT, (%d, %d, %d), (%d, %d, %d), (%d, %d, %d))\n";
......@@ -32,7 +32,7 @@ public class Generator extends LXOutput implements GeometryConstants {
static final String BODY_LED = "body_leds((%d, %d, %d))";
Generator(LX lx, Flight flight, DataInput[] inSockets, PrintStream[] outSockets) {
Generator(LX lx, FlightModel flight, DataInput[] inSockets, PrintStream[] outSockets) {
super(lx);
this.flight = flight;
this.flyers = this.flight.getFlyers();
......@@ -40,10 +40,20 @@ public class Generator extends LXOutput implements GeometryConstants {
this.out = outSockets;
}
private Color[] getRGBColors(List<LightSamplePoint> points) {
private Color getRGBColor(LightSamplePointModel point) {
return new Color(this.frameColors[point.getIndex()]);
}
private Color[] getRGBColors(List<LightSamplePointModel> points) {
// REVIEW(mcslee) - unclear benefit to making dynamic copies with java.awt.Color on every frame...
// consider using int[] and you have the LXColor.red()/LXColor.green()/LXColor.blue() methods
// which are simlar to java.awt.Color.getRed(), etc.
//
// There's no fundamental problem with what you're doing here, but you're just going to be putting
// the garbage collector to work
Color[] ledColors = new Color[points.size()];
for (int i = 0; i < points.size(); i++) {
ledColors[i] = new Color((points.get(i)).getColor());
ledColors[i] = new Color(this.frameColors[points.get(i).getIndex()]);
}
return ledColors;
}
......@@ -63,41 +73,30 @@ public class Generator extends LXOutput implements GeometryConstants {
* Perhaps that should be handled by engine
*/
private ArrayList<String> generateCommands(Flyer flyer) {
private ArrayList<String> generateCommands(int flyerIndex) {
/*
* String s = "hello %s!";
* s = String.format(s, "world");
* assertEquals(s, "hello world!");
*/
// Wing[] wings = flyer.getWings();
Wing lWing = flyer.getLeftWing();
Wing rWing = flyer.getRightWing();
int leftWingPos = flight.getFlyerLeftWingSkew(flyerIndex);
int rightWingPos = flight.getFlyerRightWingSkew(flyerIndex);
LightSamplePointModel bodyLightPoint = flight.getFlyerBodyLight(flyerIndex);
int leftWingPos = lWing.getSkew();
int rightWingPos = rWing.getSkew();
LXPoint bodyLightPoint = flyer.getBodyLightPoint();
List<LightSamplePoint> leftLEDs = lWing.getLightPoints();
List<LightSamplePoint> rightLEDs = rWing.getLightPoints();
List<LightSamplePointModel> leftLEDs = flight.getFlyerLeftWingLights(flyerIndex);
List<LightSamplePointModel> rightLEDs = flight.getFlyerRightWingLights(flyerIndex);
ArrayList<String> commands = new ArrayList<String>();
Color[] leftLights = getRGBColors(leftLEDs);
Color[] rightLights = getRGBColors(rightLEDs);
Color bodyLED = getRGBColor(bodyLightPoint);
Color bodyLED = new Color(((LightSamplePoint) bodyLightPoint).getColor());
// if (leftWingPos >= 0) {
// commands.add(String.format(LEFT_WING_POS, leftWingPos));
// }
//
// if (rightWingPos >= 0) {
// commands.add(String.format(RIGHT_WING_POS, rightWingPos));
// }
commands.add(String.format(LEFT_WING_POS, leftWingPos));
commands.add(String.format(RIGHT_WING_POS, rightWingPos));
commands.add(String.format(BODY_LED,
bodyLED.getRed(), bodyLED.getGreen(), bodyLED.getBlue()));
......@@ -121,9 +120,14 @@ public class Generator extends LXOutput implements GeometryConstants {
protected void onSend(int[] colors, double brightness) {
// super.onSend(colors, brightness);
// REVIEW(mcslee): here we are being given the engine's composited and mixed
// colors for this frame
this.frameColors = colors;
for (int i=0; i<flyers.size(); i++) {
ArrayList<String> commands = generateCommands(flyers.get(i));
for (String command: commands) {
ArrayList<String> commands = generateCommands(i);
for (String command : commands) {
try {
// out[i].println(command);
} catch (Exception e) {
......
......@@ -2,7 +2,8 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import heronarts.lx.model.LXPoint;
import heronarts.lx.transform.LXVector;
import heronarts.lx.color.LXColor;
interface GeometryConstants {
......@@ -51,6 +52,7 @@ interface GeometryConstants {
(float)(7 * FEET + 10.0 + 1.0/2.0),
(float)(7 * FEET + 10.0 + 1.0/2.0)
};
final static float[] BACK_WALL_SPACINGS = {
(float)(6 * FEET + 11.0 + 3.0/16.0),
(float)(13 * FEET + 10.0 + 5.0/16.0),
......@@ -105,7 +107,6 @@ interface GeometryConstants {
/**
* Body LED dimensions
*/
// TODO (achen) am i interpreting this right?
public final static float LENGTH_BODY_CROSS = 22 * INCHES;
public final static float WIDTH_BODY_CROSS = (float) (3.8125 * INCHES);
public final static float DEPTH_BODY_CROSS = (float) (.394 * INCHES);
......@@ -118,91 +119,31 @@ interface GeometryConstants {
final static float SIDE_EDGE_DISTANCE = (float) (18.04 * INCHES);
final static float INNER_EDGE_DISTANCE = (float) (20.69 * INCHES);
final static float WING_THICKNESS_MM = 8;
// List<LXPoint> wingPoints = new ArrayList<LXPoint>(Arrays.asList(
// new LXPoint(3.480, 0.152, 0),
// new LXPoint(0.005, 6.297, 0),
// new LXPoint(0.148, 6.542, 0),
// new LXPoint(20.841, 6.539, 0),
// new LXPoint(20.919, 6.179, 0),
// new LXPoint(3.974, 0.005, 0)
//// 3.480 0.152
//// 0.005 6.297
//// 0.148 6.542
//// 20.841 6.539
//// 20.919 6.179
//// 3.974 0.005
// ));
// float wingVertices[] = {
// 3.480f, 0.152f, 0f,
// 0.005f, 6.297f, 0f,
// 0.148f, 6.542f, 0f,
// 20.841f, 6.539f, 0f,
// 20.919f, 6.179f, 0f,
// 3.974f, 0.005f, 0f
//};
// float leftWingLightVertices[] = {
// 0f, 20.88f, 0f, // head
// -6.42f, 16.49f, 0f, // side
// 0f, 0f, 0f // tail
// };
//
// LXMatrix leftWingLightMatrix = new LXMatrix(leftWingLightVertices);
//
// LXTransform transformToRightWingLightMatrix = new LXTransform(leftWingLightMatrix);
//
//
//
// float rightWingLightVerticesTransform[] = {
// -1f, 0f, 0f, // head
// -1f, 0f, 0f, // side
// -1f, 0f, 0f // tail
// };
// LXMatrix rightWingLightTransform = new LXMatrix(rightWingLightVerticesTransform);
//
// LXMatrix rightWingLightMatrix = leftWingLightMatrix.multiply(rightWingLightTransform);
// LXModel wing = new LXModel(wingPoints);
// List<LXPoint> wingLightPoints = new ArrayList<LXPoint>(Arrays.asList(
// new LXPoint(-1, 20.88, 0), // left head
// new LXPoint(-7.42, 16.49, 0), // left side
// new LXPoint(-1, 0, 0), // left tail
// new LXPoint(1, 20.88, 0), // right head
// new LXPoint(7.42, 16.49, 0), // right side
// new LXPoint(1, 0, 0), // right tail
// new LXPoint(0, 16.49, 0) // body
// ));
List<LXPoint> lightGeometryPoints = new ArrayList<LXPoint>(Arrays.asList(
new LXPoint(4.011, -4.967, 0), // left head
new LXPoint(9.116, -11.173, 0), // left side
new LXPoint(26.741, -0.987, 0), // left tail
new LXPoint(4.011, 4.967, 0), // right head
new LXPoint(9.116, 11.173, 0), // right side
new LXPoint(26.741, 0.987, 0), // right tail
new LXPoint(5.288, 0, 0) // body
List<LXVector> lightGeometryPoints = new ArrayList<LXVector>(Arrays.asList(
new LXVector(4.011f, -4.967f, 0f), // left head
new LXVector(9.116f, -11.173f, 0f), // left side
new LXVector(26.741f, -0.987f, 0f), // left tail
new LXVector(4.011f, 4.967f, 0f), // right head
new LXVector(9.116f, 11.173f, 0f), // right side
new LXVector(26.741f, 0.987f, 0f), // right tail
new LXVector(5.288f, 0f, 0f) // body
));
List<LXPoint> bodyGeometryPoints = new ArrayList<LXPoint>(Arrays.asList(
new LXPoint(0, 0, 0), // head
new LXPoint(3.333, 4.040, 0), // right side
new LXPoint(3.333, -4.040, 0), // left side
new LXPoint(26.259, 0, 0), // tail
new LXPoint(5.288, 0, -4.394) // body tip
List<LXVector> bodyGeometryPoints = new ArrayList<LXVector>(Arrays.asList(
new LXVector(0f, 0f, 0f), // head
new LXVector(3.333f, 4.040f, 0f), // right side
new LXVector(3.333f, -4.040f, 0f), // left side
new LXVector(26.259f, 0f, 0f), // tail
new LXVector(5.288f, 0f, -4.394f) // body tip
));
// LXModelBuilder wingModelBuilder = new LXModelBuilder();
// LXModel wingLights = new LXModel(wingLightPoints);
public default List<LXVector> buildLights() {
return new ArrayList<LXVector>(lightGeometryPoints);
}
}
import heronarts.lx.model.LXPoint;
abstract interface LightSamplePoint extends GeometryConstants {
/**
* Index of this lightPoint in color buffer, colors[lightPoint.getIndex()]
*/