hypercube-0.3.11
[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 int main(int argc, char **argv) {
113
114     int w, h, t;
115     raster *rb = NULL;
116     raster *tb = NULL;
117     rgb256 p;
118     c4dv v4;
119     c4d2dv v2;
120     int paused = 0;
121     int save = 0;
122     SDL_Event event;
123     SDL_Surface *surface = NULL;
124     
125     int oscfd;
126     char *oscport;
127     lo_server oscserver;
128     struct pollfd pollfds[1];
129     
130     char filename[64];
131     char *fileformat = "hypercube-%08d.png";
132     int filecount = 0;
133     int savecount = 512;
134
135     if (argc != 7) exit(1);
136
137     w = atoi(argv[1]);
138     h = atoi(argv[2]);
139     d1 = atoi(argv[3]);
140     d2 = atoi(argv[4]);
141     savecount = atoi(argv[5]);
142     oscport = argv[6];
143
144     w = w < 64 ? 64 : w;
145     h = h < 64 ? 64 : h;
146     d1 = d1 < 512 ? 512 : d1;
147     d2 = d2 < 512 ? 512 : d2;
148     savecount = savecount < 1 ? 1 : savecount;
149
150     oscserver = lo_server_new(oscport, osc_error_handler);
151     lo_server_add_method(oscserver, "/rotate/inc",  "ii", osc_rotate_inc_handler, NULL);
152     lo_server_add_method(oscserver, "/rotate/dec",  "ii", osc_rotate_dec_handler, NULL);
153     lo_server_add_method(oscserver, "/rotate/zero", "ii", osc_rotate_zero_handler, NULL);
154     lo_server_add_method(oscserver, "/quit", "", osc_quit_handler, NULL);
155     oscfd = lo_server_get_socket_fd(oscserver);
156
157     if ((surface = r2sdl_begin(w, h))) {
158         SDL_WM_SetCaption("Hypercube", "Hypercube");
159         f_init();
160         cube4d_init();
161         d_init();
162         rb = r_alloc(w, h);
163         tb = r_alloc(w, h);
164         
165         t = 0;
166         while (running) {
167             if (!paused) {
168                 r_clear(rb, 0);
169                 p_planar8bit(&p, t);
170                 d_transform(
171                     &cube4d_vertex, &v4,
172                     a[0][1], a[0][2], a[0][3], a[1][2], a[1][3], a[2][3]
173                 );
174                 n_project(&v4, d1, d2, &v2);
175                 n_scale2screen(&v2, w, h);
176                 n_layered(rb, tb, &v2);
177                 n_wireframe(rb, &v2, 0);
178                 r2sdl_setpalette(&p);
179                 r2sdl_display(rb);
180                 t++;
181             }
182             if (save) {
183                 snprintf(filename, 60, fileformat, filecount++);
184                 sdl2png(filename, surface);
185                 save--;
186             }
187             while (SDL_PollEvent(&event)) {
188                 switch (event.type) {
189                 case SDL_QUIT:
190                     running = 0;
191                     break;
192                 case SDL_KEYDOWN:
193                     switch (event.key.keysym.sym) {
194                     case SDLK_ESCAPE: running = 0; break;
195                     case SDLK_SPACE: paused = !paused; break;
196                     case SDLK_PRINT: save = savecount; break;
197                     case SDLK_q: a[0][1]++; break;
198                     case SDLK_w: a[0][2]++; break;
199                     case SDLK_e: a[0][3]++; break;
200                     case SDLK_r: a[1][2]++; break;
201                     case SDLK_t: a[1][3]++; break;
202                     case SDLK_y: a[2][3]++; break;
203                     case SDLK_a: a[0][1]=0; break;
204                     case SDLK_s: a[0][2]=0; break;
205                     case SDLK_d: a[0][3]=0; break;
206                     case SDLK_f: a[1][2]=0; break;
207                     case SDLK_g: a[1][3]=0; break;
208                     case SDLK_h: a[2][3]=0; break;
209                     case SDLK_z: a[0][1]--; break;
210                     case SDLK_x: a[0][2]--; break;
211                     case SDLK_c: a[0][3]--; break;
212                     case SDLK_v: a[1][2]--; break;
213                     case SDLK_b: a[1][3]--; break;
214                     case SDLK_n: a[2][3]--; break;
215                     default: break;
216                     }
217                     break;
218                 default:
219                     break;
220                 }
221             }
222             pollfds[0].fd = oscfd;
223             pollfds[0].events = POLLIN | POLLPRI;
224             if (poll(pollfds, 1, 0) > 0) {
225                 lo_server_recv_noblock(oscserver, 0);
226             }
227             SDL_Delay(40);
228         }
229
230         r_free(tb);
231         r_free(rb);
232         r2sdl_end();
233     }
234
235     return (0);
236 }
237
238 /* EOF */
239