Commit df901498 authored by Martin Maina Mbuthia's avatar Martin Maina Mbuthia
Browse files

change directory for named pipes

parents 2dc00721 4f053ef8
/**
* The FLIGHT GUI window that draws the stairwell of the Packard
* building at Stanford with FLIGHT's Fractal Flyers. The Fractal
* Flyers visualize light colors and wing position.
*
* @author Philip Levis <pal@cs.stanford.edu>
*/
class UIFlightDrawer extends UI3dComponent implements GeometryConstants {
// These variables are all derived from constants in GeometryConstants -pal
// The X offset of the vertical bars on the front window. These are
// used as reference points for drawing the overhead pipes as well
// as the front window bars.
private final float[] VBAR_OFFSETS;
// The Y offset of the horizontal bars on the front window. These are
// used as reference points for drawing the front window as well as
// drawing Fractal Flyers that are hanging off the front window.
private final float[] HBAR_OFFSETS;
// The X and Z offset of reference points on the back wall. These
// correspond to a subset of the VBAR_OFFSETS, but rotated -P/4 along
// the Y axis.
private final float[] BACK_WALL_OFFSETS;
FlightModel model;
UIFlightDrawer(FlightModel model) {
super();
this.model = model;
VBAR_OFFSETS = new float[GeometryConstants.FRONT_WINDOW_VBAR_SPACINGS.length];
float xPos = 0.0;
for (int i = 0; i < GeometryConstants.FRONT_WINDOW_VBAR_SPACINGS.length; i++) {
xPos += GeometryConstants.FRONT_WINDOW_VBAR_SPACINGS[i];
VBAR_OFFSETS[i] = xPos;
}
HBAR_OFFSETS = new float[GeometryConstants.FRONT_WINDOW_HBAR_SPACINGS.length];
float yPos = 0.0;
for (int i = 0; i < GeometryConstants.FRONT_WINDOW_HBAR_SPACINGS.length; i++) {
yPos += GeometryConstants.FRONT_WINDOW_HBAR_SPACINGS[i];
HBAR_OFFSETS[i] = yPos;
}
BACK_WALL_OFFSETS = new float[GeometryConstants.BACK_WALL_SPACINGS.length];
yPos = 0;
for (int i = 0; i < GeometryConstants.BACK_WALL_SPACINGS.length; i++) {
yPos += GeometryConstants.BACK_WALL_SPACINGS[i];
BACK_WALL_OFFSETS[i] = yPos;
}
}
protected void onDraw(UI ui, PGraphics pg) {
try {
pg.pushMatrix();
drawBuilding(pg);
drawFlyers(pg);
pg.popMatrix();
} catch (Exception e) {
e.printStackTrace();
throw e;
}
}
/**
* Draw all of the Fractal Flyers.
*
*/
private void drawFlyers(PGraphics pg) {
computeFlyerLightsAndWings();
// We draw each flyer by first computing a geometric
// transformation (matrix) for its position and orientation,
// drawing it, then popping the tranformation. This allows the
// draw code to just operate in a normalized coordinate space. -pal
for (Flyer flyer : model.getFlyers()) {
pg.pushMatrix();
float x = flyer.getX();
float y = flyer.getY();
float z = flyer.getZ();
pg.translate(x, y, z);
pg.rotateY(-flyer.getRotation() * (float)Math.PI / 180);
pg.rotateZ(-flyer.getTilt() * (float)Math.PI / 180);
drawFlyer(pg, flyer);
pg.popMatrix();
}
}
/**
* Draw one Fractal Flyer at (0,0,0). its long dimension
* along the X axis, its narrow dimension along the Z axis,
* 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();
// (0, 0, 0) should be at the hanging point, so transate forward
// to that point
pg.translate(FLYER_HANGING_OFFSET, 0, 0);
pg.noStroke();
// top plate
pg.fill(#a0a0a0);
pg.beginShape();
pg.vertex(0, 0, 0);
pg.vertex(3.33f, 0, 4.04f);
pg.vertex(26.26, 0, 0);
pg.vertex(3.33f, 0, -4.04f);
pg.endShape(CLOSE);
// Left wing
Wing leftWing = flyer.getLeftWing();
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
float langle = (float)leftWing.getSkew() / 90f * PI / 2f;
pg.rotateX(langle);
pg.beginShape();
pg.vertex(0, 0, 0);
pg.vertex(cos(PI/3f) * 7.87f, 0, sin(PI/3f) * 7.87f);
pg.vertex(23.036, 0, 0);
pg.endShape(CLOSE);
pg.popMatrix();
// Right wing
Wing rightWing = flyer.getRightWing();
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
float rangle = (float)rightWing.getSkew() / 90f * PI / 2f;
pg.rotateX(-rangle);
pg.beginShape();
pg.vertex(0, 0, 0);
pg.vertex(cos(PI/3f) * 7.87f, 0, - sin(PI/3f) * 7.87f);
pg.vertex(23.036, 0, 0);
pg.endShape(CLOSE);
pg.popMatrix();
// Body shell
pg.fill(colors[bodyLightIndex(flyer.getIndex())]);
pg.beginShape();
pg.vertex(0, 0, 0);
pg.vertex(3.33f, 0, 4.04f);
pg.vertex(5.29f, -4.39f, 0);
pg.endShape(CLOSE);
pg.beginShape();
pg.vertex(0, 0, 0);
pg.vertex(3.33f, 0, -4.04f);
pg.vertex(5.29f, -4.39f, 0);
pg.endShape(CLOSE);
pg.beginShape();
pg.vertex(26.26, 0, 0);
pg.vertex(3.33f, 0, 4.04f);
pg.vertex(5.29f, -4.39f, 0);
pg.endShape(CLOSE);
pg.beginShape();
pg.vertex(26.26, 0, 0);
pg.vertex(3.33f, 0, -4.04f);
pg.vertex(5.29f, -4.39f, 0);
pg.endShape(CLOSE);
pg.popMatrix();
}
/**
* A hook for UI-specific additions to the visualization of the Fractal
* Flyers. Used, for example, to allow the UI to highlight a Fractal
* Flyer that has been selected in the physical layout tool.
*/
private void computeFlyerLightsAndWings() {
//flyerHighlighter.highlight();
}
/** Draws the Packard stairwell: the walls, the ceiling pipes, and
* the stairs themselves. Assumes that (0, 0, 0) is the narrow
* corner (left, if facing it from the outside), the front window
* runs along the X axis, and -Z is in front of the building.
*/
private void drawBuilding(PGraphics pg) {
drawWalls(pg);
drawCeiling(pg);
drawStairs(pg);
}
/**
* Draws a cylinder of radius r and height h, with one end
* centered at (0, 0, 0) and the other at (0, 0, h). If you want
* to move the cylinder, call this method having set up a matrix
* so these coordinates are at your desired position. Used to draw
* pipes in the ceiling of the stairwell. Uses whatever fill color
* was specified before calling.
*/
private void drawCylinder(PGraphics pg, float r, float h) {
int sides = 36;
float angle = 360 / sides;
// draw top shape
beginShape();
for (int i = 0; i < sides; i++) {
float x = cos( radians( i * angle ) ) * r;
float y = sin( radians( i * angle ) ) * r;
vertex( x, y, 0 );
}
endShape(CLOSE);
// draw bottom shape
beginShape();
for (int i = 0; i < sides; i++) {
float x = cos( radians( i * angle ) ) * r;
float y = sin( radians( i * angle ) ) * r;
vertex( x, y, h );
}
endShape(CLOSE);
// draw body
beginShape(TRIANGLE_STRIP);
for (int i = 0; i < sides + 1; i++) {
float x = cos( radians( i * angle ) ) * r;
float y = sin( radians( i * angle ) ) * r;
vertex( x, y, h);
vertex( x, y, 0);
}
endShape(CLOSE);
}
/** Draw a ceiling pipe from (x0, z0) to (x1, z1). Y is constant,
* at GeometryConstants.FRONT_WINDOW_NADIR_HEIGHT (the height of
* the pipe superstructure).
*/
private void drawCeilingPipe(PGraphics pg, float x0, float z0, float x1, float z1) {
pg.noStroke();
pg.fill(#c0c0c0);
pg.pushMatrix();
float y0 = FRONT_WINDOW_NADIR_HEIGHT + GeometryConstants.FRONT_WINDOW_BAR_WIDTH / 2.0f;
float y1 = FRONT_WINDOW_NADIR_HEIGHT + GeometryConstants.FRONT_WINDOW_BAR_WIDTH / 2.0f;
float xAngle = atan((x1 - x0)/(z1 - z0));
float length = sqrt((x1 - x0) * (x1 - x0) + (z1 - z0) * (z1 - z0));
pg.translate(x0, y0, z0);
pg.rotateY(xAngle);
drawCylinder(pg, 0.5f * GeometryConstants.FEET, length);
pg.popMatrix();
}
/**
* Draw all of the ceiling pipes. Their placement is based on the
* prow architectural drawing in the project repository. Four pipes
* stretch from the front window to the back wall, while four other
* pipes join with these to form two internal triangles.
*/
private void drawCeiling(PGraphics pg) {
// Because the back wall is at a 45 degree angle to the front window,
// the X and Z displacement is the same. -pal
// Draw straight pipes
for (int i = 0; i < BACK_WALL_OFFSETS.length; i++) {
float backWallOffset = BACK_WALL_OFFSETS[i] * 0.707;
// Straight pipe across
drawCeilingPipe(pg,
VBAR_OFFSETS[i * 2], 0.0,
backWallOffset, backWallOffset);
if (i == 1 || i == 2) {
float nextFX = VBAR_OFFSETS[2 * (i + 1)];
float nextFZ = 0.0f;
float nextBX = BACK_WALL_OFFSETS[i + 1] * 0.707;
float nextBZ = BACK_WALL_OFFSETS[i + 1] * 0.707;
float midpointX = nextFX + ((nextBX - nextFX) / 2.0);
float midpointZ = nextFZ + ((nextBZ - nextFZ)/ 2.0f);
// Two pipes of the V that meet at next one
drawCeilingPipe(pg,
VBAR_OFFSETS[i * 2], 0.0,
midpointX, midpointZ);
drawCeilingPipe(pg,
midpointX, midpointZ,
backWallOffset, backWallOffset);
}
}
}
/** Draw a flight of up or down stairs at a given yOffset (floor
* height). Facing the stairs from the back wall, up stairs are
* on the left (-x) while down stairs are on the right (+x). It
* also draws half of the corner platform.
*/
private void drawStairFlight(PGraphics pg, float yOffset, boolean up) {
pg.fill(#202020);
pg.pushMatrix();
pg.translate(0, yOffset, 0);
if (up) {
pg.pushMatrix();
pg.translate(-168.0f + 126.0f * sin(PI/8f),
0,
32.0f + 126f * cos(PI/8f));
pg.rotateY(PI/8f);
pg.beginShape();
pg.vertex(0, 0, 0);
pg.vertex(0, 90f, 186f);
// This 128 is a hacked constant. I got sick of trying
// to do the triginometry. -pal
pg.vertex(0, 90f, 186f + 128f);
pg.vertex(69f, 90f, 186f);
pg.vertex(69f, 0, 0);
pg.endShape(CLOSE);
pg.popMatrix();
} else {
pg.pushMatrix();
pg.translate(168.0f - 126.0f * sin(PI/8f),
0,
32.0f + 126f * cos(PI/8f));
pg.rotateY(-PI/8f);
pg.beginShape();
pg.vertex(0, 0, 0);
pg.vertex(0, -90f, 186f);
// This 128 is a hacked constant. I got sick of trying
// to do the triginometry. -pal
pg.vertex(0, -90f, 186f + 128f);
pg.vertex(-69f, -90f, 186f);
pg.vertex(-69f, 0, 0);
pg.endShape(CLOSE);
pg.popMatrix();
}
pg.popMatrix();
}
/** Draw a platform against the interior wall at a given yOffset;
* this is the platform that the doors from the interior of
* the building open on to, so you can take stairs up and down.
* Constants taken from the DWG model of the stairwell in the
* repository.
*/
private void drawPlatform(PGraphics pg, float yOffset) {
pg.fill(#202020);
pg.pushMatrix();
pg.translate(0, yOffset, 0);
pg.beginShape();
pg.vertex(126.0f, 0, 0.0f);
pg.vertex(126.0f, 0, 32.0f);
pg.vertex(168.0f, 0, 32.0f);
pg.vertex(168.0f - 126.0f * sin(PI/8f),
0,
32.0f + 126f * cos(PI/8f));
pg.vertex(168.0f - 126.0f * sin(PI/8f) - 69f * sin(5f / 8f * PI),
0,
32f + 126f * cos(PI/8f) + 69f * cos(5f / 8f * PI));
pg.vertex(168.0f - 126.0f * sin(PI/8f) - 69f * sin(5f / 8f * PI) + 21f * sin(PI/8f),
0,
32f + 126f * cos(PI/8f) + 69f * cos(5f / 8f * PI) - 21f * cos(PI/8f));
pg.vertex(-168.0f + 126.0f * sin(PI/8f) + 69f * sin(5f / 8f * PI) - 21f * sin(PI/8f),
0,
32f + 126f * cos(PI/8f) + 69f * cos(5f / 8f * PI) - 21f * cos(PI/8f));
pg.vertex(-168.0f + 126.0f * sin(PI/8f) + 69f * sin(5f / 8f * PI),
0,
32f + 126f * cos(PI/8f) + 69f * cos(5f / 8f * PI));
pg.vertex(-168.0f + 126.0f * sin(PI/8),
0,
32.0f + 126f * cos(PI/8));
pg.vertex(-168.0f, 0, 32.0f);
pg.vertex(-126.0f, 0, 32.0f);
pg.vertex(-126.0f, 0, 0.0f);
pg.endShape(CLOSE);
pg.popMatrix();
}
/**
* Draw all of the stairs: the platforms on the ground floor, floor 2,
* and floor 3 as well as the stairs that connec them.
*/
private void drawStairs(PGraphics pg) {
pg.pushMatrix();
// Translate to the midpoint of the center wall that
// the stair platforms are on; this is halfway between
// the end of the front wall (WIDTH) and the end of the back wall
// (0.707 * WIDTH) -pal
pg.translate(FRONT_WINDOW_WIDTH * (1f + 0.707) / 2f,
0f,
FRONT_WINDOW_WIDTH * (0.707) / 2f);
// The stairwell is 45 degrees; this means the mid angle from the
// center of the stair wall -22.5 degrees from along the X axis,
// so -(PI/4 + P/16)
pg.rotateY(- 5.0f/8.0f * PI);
drawPlatform(pg, 0f);
drawPlatform(pg, 180f);
drawPlatform(pg, 360f);
drawStairFlight(pg, 0, true);
drawStairFlight(pg, 180f, false);
drawStairFlight(pg, 180f, true);
drawStairFlight(pg, 360f, false);
pg.popMatrix();
}
/**
* Draw the back wall in white and the latticework on the front
* window.
*/
private void drawWalls(PGraphics pg) {
pg.fill(#c0c0c0);
pg.stroke(#202020);
// Vertical bars: need a polygon not a rectangle
// because their top has an angle with the roof.
for (int i = 0; i < VBAR_OFFSETS.length; i++) {
float offset = VBAR_OFFSETS[i];
float center = FRONT_WINDOW_VBAR_HEIGHTS[i];
pg.beginShape();
pg.vertex(offset, 0.0);
pg.vertex(offset + FRONT_WINDOW_BAR_WIDTH, 0);
pg.vertex(offset + FRONT_WINDOW_BAR_WIDTH, center);
pg.vertex(offset, center);
pg.endShape(CLOSE);
}
// Horizontal bars
for (float offset: HBAR_OFFSETS) {
pg.rect(0,
offset,
FRONT_WINDOW_WIDTH,
FRONT_WINDOW_BAR_WIDTH);
}
//Top roof edge bar
pg.beginShape();
pg.vertex(0, FRONT_WINDOW_CORNER_HEIGHT, 0);
for (int i = 0; i < VBAR_OFFSETS.length; i++) {
pg.vertex(VBAR_OFFSETS[i] + FRONT_WINDOW_BAR_WIDTH, FRONT_WINDOW_VBAR_HEIGHTS[i], 0);
}
for (int i = VBAR_OFFSETS.length - 1; i >= 0; i--) {
pg.vertex(VBAR_OFFSETS[i] + FRONT_WINDOW_TOP_WIDTH, FRONT_WINDOW_VBAR_HEIGHTS[i] + FRONT_WINDOW_TOP_WIDTH, 0);
}
pg.vertex(0, FRONT_WINDOW_CORNER_HEIGHT + FRONT_WINDOW_TOP_WIDTH, 0);
pg.endShape(CLOSE);
// Bottom floor: 45 degree angle means back corner is at sqrt(2)
pg.beginShape();
pg.fill(#808080);
pg.vertex(0, -2, 0);
pg.vertex(FRONT_WINDOW_WIDTH, -2, 0);
pg.vertex(FRONT_WINDOW_WIDTH * 0.707, -2, FRONT_WINDOW_WIDTH * 0.707);
pg.endShape(CLOSE);
// Back wall: 45 degree angle means far corner is at sqrt(2)
pg.fill(#f0f0f0);
pg.beginShape();
pg.vertex(0, 0, 0);
pg.vertex(0, FRONT_WINDOW_CORNER_HEIGHT, 0);
pg.vertex(FRONT_WINDOW_WIDTH * 0.707,
FRONT_WINDOW_CORNER_HEIGHT,
FRONT_WINDOW_CORNER_HEIGHT * 0.707);
pg.vertex(FRONT_WINDOW_WIDTH * 0.707,
0,
FRONT_WINDOW_CORNER_HEIGHT * 0.707);
pg.endShape(CLOSE);
}
}
/** Top-level Processing sketch for running the FLIGHT GUI. To run
* this, load it in Processing. Other sketches contain supporting code.
*
* @author Philip Levis <pal@cs.stanford.edu>
*/
import heronarts.lx.*;
import heronarts.lx.audio.*;
import heronarts.lx.color.LXColor;
import heronarts.lx.effect.*;
import heronarts.lx.model.*;
import heronarts.lx.output.*;
import heronarts.lx.parameter.*;
import heronarts.lx.pattern.*;
import heronarts.lx.studio.LXStudio;
import heronarts.lx.transform.*;
import heronarts.lx.modulator.*;
import heronarts.p3lx.*;
import heronarts.p3lx.ui.*;
import heronarts.p3lx.ui.component.*;
import heronarts.p3lx.ui.control.*;
import processing.opengl.*;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.PrintWriter;
import java.io.Reader;
import java.io.Writer;
import java.util.Arrays;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
final static int SECONDS = 1000;
final static int MINUTES = 60*SECONDS;
static FlyerConfig[] flyerConfigurations;
FlightModel model;
ProcessingEngine pengine;
LXStudio lx;
UI3dContext viewContext;
// A FlyerHighlighter is an Effect that highlights a particular
// Fractal Flyer: flyerHighlighter is used to show which one you are
// moving around in the UI. -pal
FlyerHighlighter flyerHighlighter;
class ProcessingEngine extends FlightEngine {
ProcessingEngine(String projectPath, FlightModel model, LXStudio lx) {
super(projectPath, model, lx);
}
}
// Derived from Mark Slee's LXStudioApp example
private static final String WINDOW_TITLE = "FLIGHT Graphical UI";
private static int WIDTH = 1280;
private static int HEIGHT = 800;
private static boolean FULLSCREEN = false;
/**
* Required by Processing. Sets up the graphics context/window size
* and tells Processing to use a 3D optimized graphics engine.
*/
void settings() { size(WIDTH, HEIGHT, P3D); }
/**
* Given an array of FlyerConfigs, builds the LXModel with flyers,
* wings, and lights. Initializes the wings and bodies to red
* and blue as defaults.
*/
void initializeModel(FlyerConfig[] flyers) {
model = new Model(flyers).getFlightModel();
List<LightSamplePointModel> wingLights = model.getAllWingsLights();
}
/**
* Loads the Flyer configuration JSON file
* for their positions and metadata, creates the data model from this
* information, and creates an LXStudio instance. This method is required
* and called by Processing.
*/
void setup() {
frameRate(90);
System.out.println("Starting LXStudio; initialized Fractal Flyer data model from " + Config.FLYER_CONFIG_FILE);
IO io = new IO(sketchPath());
flyerConfigurations = io.loadConfigFile(Config.FLYER_CONFIG_FILE);
initializeModel(flyerConfigurations);
lx = new LXStudio(this, model);
}
/**
* Creates the ProcessingEngine that triggers Patterns and generally
* controls FLIGHT. This method is required and called by Processing.
*/
void initializeUI(LXStudio lx, LXStudio.UI ui) {
pengine = new ProcessingEngine(sketchPath(), model, lx);
lx.engine.setThreaded(true);
}
/**
* Creates the FLIGHT GUI. This method is required and called by