hypercube-0.3.12
[polytopiary:hypercube.git] / hypercube.c
1 /*
2 hypercube -- interaction in four dimensions.
3 Copyright (C) 2006 Claude Heiland-Allen
4
5 This program is free software; you can redistribute it and/or
6 modify it under the terms of the GNU General Public License
7 as published by the Free Software Foundation; either version 2
8 of the License, or (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
18 */
19 /* test rendering */
20
21 #include <stdlib.h>
22 #include <sys/poll.h>
23
24 #include <lo/lo.h>
25
26 #include <SDL.h>
27
28 #include "cube4d.h"
29 #include "dynamics.h"
30 #include "fixed.h"
31 #include "geometry.h"
32 #include "palette.h"
33 #include "r2sdl.h"
34 #include "raster.h"
35 #include "render.h"
36 #include "sdl2png.h"
37 #include "stack.h"
38
39 int d1 = 512;
40 int d2 = 1024;
41 int a[4][4] = {
42     { 0, 0, 0, 0 },
43     { 0, 0, 0, 0 },
44     { 0, 0, 0, 0 },
45     { 0, 0, 0, 0 }
46 };
47
48 int running = 1;
49
50
51 void osc_error_handler(int n, const char *msg, const char *path) {
52     printf("liblo server error %d in path %s: %s\n", n, path, msg);
53 }
54
55 int osc_quit_handler(
56     const char *path, const char *types,
57     lo_arg **argv, int argc, void *data, void *user_data
58 ) {
59     running = 0;
60     return (0);
61 }
62
63 int osc_rotate_inc_handler(
64     const char *path, const char *types,
65     lo_arg **argv, int argc, void *data, void *user_data
66 ) {
67     int dim1 = argv[0]->i;
68     int dim2 = argv[1]->i;
69     if (
70         0 <= dim1 && dim1 < 4 &&
71         0 <= dim2 && dim2 < 4 &&
72         dim1 < dim2
73     ) {
74         a[dim1][dim2]++;
75     }
76     return (0);
77 }
78
79 int osc_rotate_dec_handler(
80     const char *path, const char *types,
81     lo_arg **argv, int argc, void *data, void *user_data
82 ) {
83     int dim1 = argv[0]->i;
84     int dim2 = argv[1]->i;
85     if (
86         0 <= dim1 && dim1 < 4 &&
87         0 <= dim2 && dim2 < 4 &&
88         dim1 < dim2
89     ) {
90         a[dim1][dim2]--;
91     }
92     return (0);
93 }
94
95 int osc_rotate_zero_handler(
96     const char *path, const char *types,
97     lo_arg **argv, int argc, void *data, void *user_data
98 ) {
99     int dim1 = argv[0]->i;
100     int dim2 = argv[1]->i;
101     if (
102         0 <= dim1 && dim1 < 4 &&
103         0 <= dim2 && dim2 < 4 &&
104         dim1 < dim2
105     ) {
106         a[dim1][dim2]=0;
107     }
108     return (0);
109 }
110
111
112 void osc_send_v2(lo_address sender, c4d2dv *v2) {
113     int i;
114     for (i = 0; i < 16; i++) {
115         lo_send(sender, "/hypercube/vertex2d", "iff",
116             i, (float) (*v2)[i][0], (float) (*v2)[i][1]
117         );
118     }
119 }
120
121 int main(int argc, char **argv) {
122
123     int w, h, t;
124     raster *rb = NULL;
125     raster *tb = NULL;
126     rgb256 p;
127     c4dv v4;
128     c4d2dv v2;
129     int paused = 0;
130     int save = 0;
131     SDL_Event event;
132     SDL_Surface *surface = NULL;
133     
134     int oscfd;
135     char *oscrport;
136     lo_server oscserver;
137     struct pollfd pollfds[1];
138
139     char *oscsport;
140     lo_address sender;
141     
142     char filename[64];
143     char *fileformat = "hypercube-%08d.png";
144     int filecount = 0;
145     int savecount = 512;
146
147     if (argc != 8) exit(1);
148
149     w = atoi(argv[1]);
150     h = atoi(argv[2]);
151     d1 = atoi(argv[3]);
152     d2 = atoi(argv[4]);
153     savecount = atoi(argv[5]);
154     oscrport = argv[6];
155
156     oscsport = argv[7];
157
158     w = w < 64 ? 64 : w;
159     h = h < 64 ? 64 : h;
160     d1 = d1 < 512 ? 512 : d1;
161     d2 = d2 < 512 ? 512 : d2;
162     savecount = savecount < 1 ? 1 : savecount;
163
164     oscserver = lo_server_new(oscrport, osc_error_handler);
165     lo_server_add_method(oscserver, "/hypercube/rotate/inc",  "ii", osc_rotate_inc_handler, NULL);
166     lo_server_add_method(oscserver, "/hypercube/rotate/dec",  "ii", osc_rotate_dec_handler, NULL);
167     lo_server_add_method(oscserver, "/hypercube/rotate/zero", "ii", osc_rotate_zero_handler, NULL);
168     lo_server_add_method(oscserver, "/hypercube/quit", "", osc_quit_handler, NULL);
169     oscfd = lo_server_get_socket_fd(oscserver);
170
171     sender = lo_address_new(NULL, oscsport);
172
173     if ((surface = r2sdl_begin(w, h))) {
174         SDL_WM_SetCaption("Hypercube", "Hypercube");
175         f_init();
176         cube4d_init();
177         d_init();
178         rb = r_alloc(w, h);
179         tb = r_alloc(w, h);
180         
181         t = 0;
182         while (running) {
183             if (!paused) {
184                 r_clear(rb, 0);
185                 p_planar8bit(&p, t);
186                 d_transform(
187                     &cube4d_vertex, &v4,
188                     a[0][1], a[0][2], a[0][3], a[1][2], a[1][3], a[2][3]
189                 );
190                 n_project(&v4, d1, d2, &v2);
191                 n_scale2screen(&v2, w, h);
192                 n_layered(rb, tb, &v2);
193                 n_wireframe(rb, &v2, 0);
194                 r2sdl_setpalette(&p);
195                 r2sdl_display(rb);
196                 t++;
197                 osc_send_v2(sender, &v2);
198             }
199             if (save) {
200                 snprintf(filename, 60, fileformat, filecount++);
201                 sdl2png(filename, surface);
202                 save--;
203             }
204             while (SDL_PollEvent(&event)) {
205                 switch (event.type) {
206                 case SDL_QUIT:
207                     running = 0;
208                     break;
209                 case SDL_KEYDOWN:
210                     switch (event.key.keysym.sym) {
211                     case SDLK_ESCAPE: running = 0; break;
212                     case SDLK_SPACE: paused = !paused; break;
213                     case SDLK_PRINT: save = savecount; break;
214                     case SDLK_q: a[0][1]++; break;
215                     case SDLK_w: a[0][2]++; break;
216                     case SDLK_e: a[0][3]++; break;
217                     case SDLK_r: a[1][2]++; break;
218                     case SDLK_t: a[1][3]++; break;
219                     case SDLK_y: a[2][3]++; break;
220                     case SDLK_a: a[0][1]=0; break;
221                     case SDLK_s: a[0][2]=0; break;
222                     case SDLK_d: a[0][3]=0; break;
223                     case SDLK_f: a[1][2]=0; break;
224                     case SDLK_g: a[1][3]=0; break;
225                     case SDLK_h: a[2][3]=0; break;
226                     case SDLK_z: a[0][1]--; break;
227                     case SDLK_x: a[0][2]--; break;
228                     case SDLK_c: a[0][3]--; break;
229                     case SDLK_v: a[1][2]--; break;
230                     case SDLK_b: a[1][3]--; break;
231                     case SDLK_n: a[2][3]--; break;
232                     default: break;
233                     }
234                     break;
235                 default:
236                     break;
237                 }
238             }
239             pollfds[0].fd = oscfd;
240             pollfds[0].events = POLLIN | POLLPRI;
241             if (poll(pollfds, 1, 0) > 0) {
242                 lo_server_recv_noblock(oscserver, 0);
243             }
244             SDL_Delay(40);
245         }
246
247         r_free(tb);
248         r_free(rb);
249         r2sdl_end();
250     }
251
252     return (0);
253 }
254
255 /* EOF */
256