Skip to content
Newer
Older
100644 297 lines (259 sloc) 6.76 KB
8678e0d @potatono Minor changes
potatono authored
1 import hypermedia.net.*;
2
98a419a @madsrune Original version for BM 2010
madsrune authored
3 /**
4 * This sketch emulates the Disorient Art Car Wash Electronic Sign
5 * At Burning Man 2010. The sign is a 64' x 16' 32x8 pixel grid.
6 *
7 * Listens on port 58082 for UDP packets. Packet is expected
8 * to start with 1, followed by 256 bytes. I believe the 1
9 * signifies a new frame, but this emulator just expects 257
10 * bytes.
11 *
12 * Tested with Scott's drawer code. Scotts stuff expects the
13 * LeoPlayer to be listening at IP 192.168.1.130, so you'll
14 * need to add that as an IP on the machine running the
15 * emulator.
16 *
17 * (c)2010 Justin Day
18 *
19 * You may use under a CC+Attribution License.
20 *
21 **/
cf7848c @potatono Generalized a bit more. Addressing modes.
potatono authored
22
98a419a @madsrune Original version for BM 2010
madsrune authored
23 import hypermedia.net.*;
24
25 // constants
26 int Y_AXIS = 1;
27 int X_AXIS = 2;
28
cf7848c @potatono Generalized a bit more. Addressing modes.
potatono authored
29 // These are the addressing schemes, which vary with how the sign is constructed.
30 // The comments are describing how the pixel addresses are laid out in order. Keep
31 // in mind that if the sign is in vertical mode that the pixels go from top to bottom
32 // not left to right. The comments assume the pixels per channel are 8.
33 int ADDRESSING_NORMAL = 1; // 0-256
34 int ADDRESSING_FLIPFLOP = 2; // 0-7, 15-8, 16-23, 31-24...
35 int ADDRESSING_HALF = 3; // 0-7, 128-135, 8-15, 136-143...
36
37 // Configuration
38 int PIXELS_PER_CHANNEL = 8;
39 int ADDRESSING = ADDRESSING_FLIPFLOP;
40 int HEIGHT = 16;
c11a363 @madsrune Changed width to 16.
madsrune authored
41 int WIDTH = 16;
cf7848c @potatono Generalized a bit more. Addressing modes.
potatono authored
42 int BOARD_SPACING = 20;
c11a363 @madsrune Changed width to 16.
madsrune authored
43 int CHANNEL_SPACING = 20;
cf7848c @potatono Generalized a bit more. Addressing modes.
potatono authored
44 boolean VERTICAL = true; // set to false when panels are mounted horizontally
e15b1b2 @madsrune Added support for horizontal mounting and configurable size
madsrune authored
45
98a419a @madsrune Original version for BM 2010
madsrune authored
46 // privates
47 UDP udp;
48 int[] state;
49 int crawl = -1;
50 boolean demoMode = true;
51 boolean nightMode = true;
cf7848c @potatono Generalized a bit more. Addressing modes.
potatono authored
52 int top = 200;
53 int left = 40;
98a419a @madsrune Original version for BM 2010
madsrune authored
54
55 void setup() {
cf7848c @potatono Generalized a bit more. Addressing modes.
potatono authored
56 if (VERTICAL) {
57 left = 360 - (WIDTH * (CHANNEL_SPACING/2));
58 top = 360 - (HEIGHT * BOARD_SPACING);
59 }
60 else {
61 left = 360 - (WIDTH * (BOARD_SPACING/2));
62 top = 360 - (HEIGHT * CHANNEL_SPACING);
63 }
64
65
98a419a @madsrune Original version for BM 2010
madsrune authored
66 udp = new UDP( this, 58082 );
67 udp.listen( true );
68
69 // Sign is 64' (10 pixels per foot plus buffer)
70 // By 16' (Lots more buffer)
71 size(720,480);
72
73 paintBackground();
74 paintSign();
75 initState();
76 paintBoards();
77 frameRate(30);
78 }
79
80 void paintBackground() {
81 color sky1, sky2, sky3;
82
83 if (nightMode) {
84 sky1 = color(0,0,0);
85 sky2 = color(0,0,50);
86 sky3 = color(0,0,100);
87 }
88 else {
89 sky1 = color(0,0,0);
90 sky2 = color(100,100,200);
91 sky3 = color(200,200,255);
92 }
93 color ply1 = color(30,10,10);
94 color ply2 = color(130,100,100);
95
96 setGradient(0,0,720,100,sky1,sky2,Y_AXIS);
97 fill(sky2); noStroke(); rect(0,100,720,80);
98 setGradient(0,180,720,140,sky2,sky3,Y_AXIS);
99 setGradient(0,320,720,160,ply1,ply2,Y_AXIS);
100
101 if (nightMode) {
102 for (int i=0; i<100; i++) {
103 int x = (int)random(720);
104 int y = (int)random(320);
105 fill(random(100));
106 rect(x,y,2,2);
107 }
108 }
109
110 }
111
112 void paintSign() {
113 noFill();
114 stroke(0);
cf7848c @potatono Generalized a bit more. Addressing modes.
potatono authored
115
116 if (VERTICAL)
117 {
118 rect(left,top,WIDTH*CHANNEL_SPACING,HEIGHT*BOARD_SPACING);
119 }
120 else
121 {
122 rect(left,top,WIDTH*BOARD_SPACING,HEIGHT*CHANNEL_SPACING);
123 }
98a419a @madsrune Original version for BM 2010
madsrune authored
124
125 fill(nightMode ? 50 : 150);
e15b1b2 @madsrune Added support for horizontal mounting and configurable size
madsrune authored
126 if (VERTICAL)
127 {
128 for (int i=0; i<WIDTH; i++) {
cf7848c @potatono Generalized a bit more. Addressing modes.
potatono authored
129 rect(left+i*CHANNEL_SPACING+(CHANNEL_SPACING/2),top,6,HEIGHT*BOARD_SPACING);
e15b1b2 @madsrune Added support for horizontal mounting and configurable size
madsrune authored
130 }
131 }
132 else
133 {
134 for (int i=0; i<HEIGHT; i++) {
cf7848c @potatono Generalized a bit more. Addressing modes.
potatono authored
135 rect(left,top+i*CHANNEL_SPACING+(CHANNEL_SPACING/2),WIDTH*BOARD_SPACING,6);
e15b1b2 @madsrune Added support for horizontal mounting and configurable size
madsrune authored
136 }
98a419a @madsrune Original version for BM 2010
madsrune authored
137 }
138 }
139
140 void initState() {
141 state = new int[256];
142 for (int i=0; i<256; i++) {
143 state[i] = 0;
144 }
145 }
146
cf7848c @potatono Generalized a bit more. Addressing modes.
potatono authored
147 int getAddress(int x, int y) {
148 if (VERTICAL) {
149 if (ADDRESSING == ADDRESSING_NORMAL) {
150 return (x * HEIGHT + y);
151 }
152 else if (ADDRESSING == ADDRESSING_HALF) {
153 return ((y % PIXELS_PER_CHANNEL) + floor(y / PIXELS_PER_CHANNEL)*PIXELS_PER_CHANNEL*WIDTH + x*PIXELS_PER_CHANNEL);
154 }
155 else if (ADDRESSING == ADDRESSING_FLIPFLOP) {
156 if (y>=PIXELS_PER_CHANNEL) {
157 int endAddress = (x+1) * HEIGHT - 1;
158 int address = endAddress - (y % PIXELS_PER_CHANNEL);
159 return address;
160 }
161 else {
162 return (x * HEIGHT + y);
163 }
164 }
165 }
166 else {
167 if (ADDRESSING == ADDRESSING_NORMAL) {
168 return (y * WIDTH + x);
169 }
170 else if (ADDRESSING == ADDRESSING_HALF) {
171 return ((x % PIXELS_PER_CHANNEL) + floor(x / PIXELS_PER_CHANNEL)*PIXELS_PER_CHANNEL*HEIGHT + y*PIXELS_PER_CHANNEL);
172 }
173 else if (ADDRESSING == ADDRESSING_FLIPFLOP) {
174 if (x>=PIXELS_PER_CHANNEL) {
175 int endAddress = (y+1) * WIDTH - 1;
176 int address = endAddress - (x % PIXELS_PER_CHANNEL);
177 return address;
178 }
179 else {
180 return (y * HEIGHT + x);
181 }
182 }
183 }
184
185 return 0;
186 }
187
188
98a419a @madsrune Original version for BM 2010
madsrune authored
189 void paintBoards() {
190 noStroke();
191
192 int i;
e15b1b2 @madsrune Added support for horizontal mounting and configurable size
madsrune authored
193 for (int y=0; y<HEIGHT; y++) {
194 for (int x=0; x<WIDTH; x++) {
cf7848c @potatono Generalized a bit more. Addressing modes.
potatono authored
195 i = getAddress(x,y);
e15b1b2 @madsrune Added support for horizontal mounting and configurable size
madsrune authored
196
98a419a @madsrune Original version for BM 2010
madsrune authored
197 fill(state[i], state[i]/255.0*100, 0);
198
cf7848c @potatono Generalized a bit more. Addressing modes.
potatono authored
199 // FIXME
200 if (VERTICAL) {
201 rect(x*CHANNEL_SPACING+left+(CHANNEL_SPACING/2),y*BOARD_SPACING+top+(BOARD_SPACING/2),7,6);
202 }
203 else {
204 rect(x*BOARD_SPACING+left+(BOARD_SPACING/2),y*CHANNEL_SPACING+top+(CHANNEL_SPACING/2),7,6);
205 }
98a419a @madsrune Original version for BM 2010
madsrune authored
206 }
207 }
208 }
209
210 void runDemo() {
211 if (crawl == -1 && state[0] < 255) {
e15b1b2 @madsrune Added support for horizontal mounting and configurable size
madsrune authored
212 for (int i=0; i<WIDTH*HEIGHT; i++) {
98a419a @madsrune Original version for BM 2010
madsrune authored
213 state[i]+=8;
214 }
215 }
216 else {
217 crawl++;
e15b1b2 @madsrune Added support for horizontal mounting and configurable size
madsrune authored
218 for (int i=0; i<WIDTH*HEIGHT; i++) {
98a419a @madsrune Original version for BM 2010
madsrune authored
219 state[i] = (crawl == i) ? 255 : 0;
220 }
e15b1b2 @madsrune Added support for horizontal mounting and configurable size
madsrune authored
221 if (crawl>=WIDTH*HEIGHT)
98a419a @madsrune Original version for BM 2010
madsrune authored
222 crawl = -1;
223 }
224 }
225
226 void draw () {
227 if (demoMode) {
228 runDemo();
229 }
230
231 paintBoards();
232 }
233
234 void receive(byte[] data, String ip, int port) {
235 if (demoMode) {
236 println("Started receiving data from " + ip + ". Demo mode disabled.");
237 demoMode = false;
238 }
239
240 if (data[0] == 1) {
241 if (data.length < 257) {
242 println("Packet size mismatch. Expected 257, got " + data.length);
243 }
244
245 for (int i=1; i<data.length; i++) {
246 state[i-1] = convertByte(data[i]);
247 }
248 }
249 else {
250 println("Packet header mismatch. Expected 1, got " + data[0]);
251 }
252 }
253
254 int convertByte(byte b) {
255 return (b<0) ? 256+b : b;
256 }
257
258 void setGradient(int x, int y, float w, float h, color c1, color c2, int axis ){
259 // calculate differences between color components
260 float deltaR = red(c2)-red(c1);
261 float deltaG = green(c2)-green(c1);
262 float deltaB = blue(c2)-blue(c1);
263
264 // choose axis
265 if(axis == Y_AXIS){
266 /*nested for loops set pixels
267 in a basic table structure */
268 // column
269 for (int i=x; i<=(x+w); i++){
270 // row
271 for (int j = y; j<=(y+h); j++){
272 color c = color(
273 (red(c1)+(j-y)*(deltaR/h)),
274 (green(c1)+(j-y)*(deltaG/h)),
275 (blue(c1)+(j-y)*(deltaB/h))
276 );
277 set(i, j, c);
278 }
279 }
280 }
281 else if(axis == X_AXIS){
282 // column
283 for (int i=y; i<=(y+h); i++){
284 // row
285 for (int j = x; j<=(x+w); j++){
286 color c = color(
287 (red(c1)+(j-x)*(deltaR/h)),
288 (green(c1)+(j-x)*(deltaG/h)),
289 (blue(c1)+(j-x)*(deltaB/h))
290 );
291 set(j, i, c);
292 }
293 }
294 }
295 }
296
Something went wrong with that request. Please try again.