import netP5.*;
import oscP5.*;
+
/**
* DOUBLE BLACK DIAMOND DOUBLE BLACK DIAMOND
*
// IP address
public final String ip;
+
+ public PandaMapping pm;
+
+ private final static int PORT = 779;
+
+ private final DatagramSocket socket;
// Address to send to
private final NetAddress address;
// Whether board output is enabled
private boolean enabled = false;
+
+ // Frame count for Grizzlies
+ private int frameNum = 1;
// OSC message
private final OscMessage message;
private final int[] points;
// Packet data
- private final byte[] packet = new byte[4*352]; // magic number, our UDP packet size
+ private final byte[] packet = new byte[4*280]; // magic number, our UDP packet size
private static final int NO_POINT = -1;
+ private Model _model;
+
////////////////////////////////////////////////////////////////
//
// READ THIS RIGHT NOW BEFORE YOU MODIFY THE BELOW!!!!!!!!!!!!!
this.ip = ip;
// Initialize our OSC output stuff
- address = new NetAddress(ip, 9001);
+ address = new NetAddress(ip, 779);
message = new OscMessage("/shady/pointbuffer");
+ try {
+ socket = new DatagramSocket();
+ } catch (Exception x) {
+ throw new RuntimeException(x);
+ }
+
// Build the array of points, initialize all to nothing
points = new int[PandaMapping.PIXELS_PER_BOARD];
for (int i = 0; i < points.length; ++i) {
}
}
- public PandaDriver(String ip, Model model, PandaMapping pm) {
+ public PandaDriver(String ip, Model model, PandaMapping _pm) {
this(ip);
-
+ pm = _pm;
+ _model = model;
// Ok, we are initialized, time to build the array if points in order to
// send out. We start at the head of our point buffer, and work our way
// down. This is the order in which points will be sent down the wire.
int ci = -1;
- // Iterate through all our channels
+ // Iterate through all our channelq s
for (ChannelMapping channel : pm.channelList) {
++ci;
int pi = ci * ChannelMapping.PIXELS_PER_CHANNEL;
case REAR_RIGHT: stripOrderIndex = 3; break;
}
+ // TODO(mcslee): clean up, ordering always consistent now
+ stripOrderIndex = 2;
+
// Iterate through all the strips on the cube and add the points
for (int stripIndex : CUBE_STRIP_ORDERINGS[stripOrderIndex]) {
// We go backwards here... in the model strips go clockwise, but
}
private int mapStrip(Strip s, int direction, int[] points, int pi) {
+ return mapStrip(s, direction, points, pi, s.points.size());
+ }
+
+ private int mapStrip(Strip s, int direction, int[] points, int pi, int len) {
if (direction == FORWARD) {
+ int i = 0;
for (LXPoint p : s.points) {
points[pi++] = p.index;
+ if (++i >= len) {
+ break;
+ }
}
} else if (direction == BACKWARD) {
- for (int i = s.points.size()-1; i >= 0; --i) {
+ for (int i = len-1; i >= 0; --i) {
points[pi++] = s.points.get(i).index;
}
} else {
setEnabled(!enabled);
}
+ private final int[] GRIZZLY_STRIP_ORDERING = new int[] { 9, 8, 11, 5, 4, 7, 6, 10, 14, 2, 1, 0, 3, 13, 12, 15 };
+
public final void send(int[] colors) {
if (!enabled) {
return;
}
+ frameNum++;
int len = 0;
int packetNum = 0;
- for (int index : points) {
- int c = (index < 0) ? 0 : colors[index];
- byte r = (byte) ((c >> 16) & 0xFF);
- byte g = (byte) ((c >> 8) & 0xFF);
- byte b = (byte) ((c) & 0xFF);
- packet[len++] = 0; // alpha channel, unused but makes for 4-byte alignment
- packet[len++] = r;
- packet[len++] = g;
- packet[len++] = b;
-
- // Flush once packet is full buffer size
- if (len >= packet.length) {
- sendPacket(packetNum++);
- len = 0;
+ for (ChannelMapping channel : pm.channelList) {
+ for (int rawCubeIndex : channel.objectIndices) {
+ if (rawCubeIndex > 0) {
+ Cube cube = _model.getCubeByRawIndex(rawCubeIndex);
+
+ // TODO(mcslee): clean this up, precompute paths
+ for (int stripIndex : GRIZZLY_STRIP_ORDERING) {
+ Strip strip = cube.strips.get(stripIndex);
+ int stripLen = ((stripIndex == 9) || (stripIndex == 16)) ? 15 : 16;
+ for (int i = stripLen-1; i >= 0; --i) {
+ int c = colors[strip.points.get(i).index];
+ byte r = (byte) ((c >> 16) & 0xFF);
+ byte g = (byte) ((c >> 8) & 0xFF);
+ byte b = (byte) ((c) & 0xFF);
+ packet[len++] = (byte) 0; // alpha channel, unused but makes for 4-byte alignment
+ packet[len++] = (byte) r;
+ packet[len++] = (byte) g;
+ packet[len++] = (byte) b;
+ }
+ }
+
+// for (LXPoint p : cube.points) {
+// int c = (p.index < 0) ? 0 : colors[p.index];
+// byte r = (byte) ((c >> 16) & 0xFF);
+// byte g = (byte) ((c >> 8) & 0xFF);
+// byte b = (byte) ((c) & 0xFF);
+// packet[len++] = (byte) 0; // alpha channel, unused but makes for 4-byte alignment
+// packet[len++] = (byte) r;
+// packet[len++] = (byte) g;
+// packet[len++] = (byte) b;
+// }
+ }
}
+ // println("Packet number: " + packetNum);
+ sendPacket(frameNum, packetNum++);
+ len = 0;
}
+ // for (int index : points) {
+ // int c = (index < 0) ? 0 : colors[index];
+ // byte r = (byte) ((c >> 16) & 0xFF);
+ // byte g = (byte) ((c >> 8) & 0xFF);
+ // byte b = (byte) ((c) & 0xFF);
+ // packet[len++] = 0; // alpha channel, unused but makes for 4-byte alignment
+ // packet[len++] = r;
+ // packet[len++] = g;
+ // packet[len++] = b;
- // Flush any remaining data
- if (len > 0) {
- sendPacket(packetNum++);
- }
+ // // Flush once packet is full buffer size
+ // if (len >= packet.length) {
+ // sendPacket(packetNum++);
+ // len = 0;
+ // }
+ // }
+
+ // // Flush any remaining data
+ // if (len > 0) {
+ // sendPacket(packetNum++);
+ // }
}
- private void sendPacket(int packetNum) {
+ private void sendPacket(int frameNum, int packetNum) {
+ // println("Sending frame #" + frameNum + ", channel # " + packetNum);
message.clearArguments();
+ message.add(frameNum);
+ message.add(0xDEADBEEF);
message.add(packetNum);
+ message.add(0xFEEDBEEF);
message.add(packet.length);
message.add(packet);
+ message.add(0xBEFFFFEB);
+
try {
- OscP5.flush(message, address);
+ // OscP5.flush(message, address); // new DatagramSocket every time, no thanks
+ byte[] bytes = message.getBytes();
+ DatagramPacket packet = new DatagramPacket(bytes, bytes.length, address.inetaddress(), PORT);
+ socket.send(packet);
} catch (Exception x) {
x.printStackTrace();
}