New Grizzly code using LXOutput framework
[SugarCubes.git] / _PandaDriver.pde
index 2d28cd693e12bea5c300d0c604dcfbe0ba07f40a..26ac3d74c49aedfdb306290417044f9119ec7baf 100644 (file)
@@ -1,6 +1,7 @@
 import netP5.*;
 import oscP5.*;
 
+
 /**
  *     DOUBLE BLACK DIAMOND        DOUBLE BLACK DIAMOND
  *
@@ -24,12 +25,21 @@ public static class PandaDriver {
   
   // 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;
@@ -38,10 +48,12 @@ public static class PandaDriver {
   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!!!!!!!!!!!!!
@@ -84,10 +96,17 @@ public static class PandaDriver {
    * corner of the cube the data wire comes in.
    */
   private final static int[][] CUBE_STRIP_ORDERINGS = new int[][] {
+//    {  2,  1,  0,  3, 13, 12, 15, 14,  4,  7,  6,  5, 11, 10,  9,  8 }, // FRONT_LEFT
+//    {  6,  5,  4,  7,  1,  0,  3,  2,  8, 11, 10,  9, 15, 14, 13, 12 }, // FRONT_RIGHT
+//    { 14, 13, 12, 15,  9,  8, 11, 10,  0,  3,  2,  1,  7,  6,  5,  4 }, // REAR_LEFT
+//    { 10,  9,  8, 11,  5,  4,  7,  6, 12, 15, 14, 13,  3,  2,  1,  0 }, // REAR_RIGHT
+
+
     {  2,  1,  0,  3, 13, 12, 15, 14,  4,  7,  6,  5, 11, 10,  9,  8 }, // FRONT_LEFT
     {  6,  5,  4,  7,  1,  0,  3,  2,  8, 11, 10,  9, 15, 14, 13, 12 }, // FRONT_RIGHT
     { 14, 13, 12, 15,  9,  8, 11, 10,  0,  3,  2,  1,  7,  6,  5,  4 }, // REAR_LEFT
-    { 10,  9,  8, 11,  5,  4,  7,  6, 12, 15, 14, 13,  3,  2,  1,  0 }, // REAR_RIGHT
+    {  9,  8, 11,  5,  4,  7,  6, 10, 14,  2,  1,  0,  3, 13, 12, 15 }, // REAR_RIGHT
+
   };
   
   private final static int[][] BASS_STRIP_ORDERING = {
@@ -161,9 +180,15 @@ public static class PandaDriver {
     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) {
@@ -171,15 +196,16 @@ public static class PandaDriver {
     }
   }
     
-  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 channels
     for (ChannelMapping channel : pm.channelList) {
       ++ci;
       int pi = ci * ChannelMapping.PIXELS_PER_CHANNEL;
@@ -204,6 +230,9 @@ public static class PandaDriver {
                 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
@@ -263,12 +292,20 @@ public static class PandaDriver {
   }
   
   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) {
-      for (Point p : s.points) {
+      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 {
@@ -291,6 +328,10 @@ public static class PandaDriver {
       }
     }
   }
+  
+  public boolean isEnabled() {
+    return this.enabled;
+  }
 
   public void disable() {
     setEnabled(false);
@@ -304,43 +345,92 @@ public static class PandaDriver {
     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();
     }