1 #include <stdlib.h>
2 #include <stdio.h>
3 #include <math.h>
4 #include <sys/time.h>
5 #include <string.h>
6 #include <unistd.h>
7 #include <stdlib.h>
8 #include <stdio.h>
9 #include <math.h>
10 #include <string.h>
11
12 #include <signal.h>
13
14 #include "psys2d.h"
15 #include "gfx-x.h"
16
17 /*#include "math-help.h" */
18 int cleanup_and_exit=0;
19 static int paused=0;
20
21
22 static void ilimit(char *, int *, int, int);
23 static void show_usage(char *);
24 static void renderpsys(Gfx *, Particle_Sys *, unsigned char );
25
ilimit(char * name,int * var,int min,int max)26 static void ilimit(char *name, int *var, int min, int max) {
27 /* Range limit an integer between min/max sets to closest
28 gives an explanation if *name is a non null (string) */
29 if (!name) {
30 *var=((*var)>max)?max:(*var);
31 *var=((*var)<min)?min:(*var);
32 } else if (*var>max) {
33 printf("Limiting %s to max %d from %d\n", name, max, *var);
34 *var=max;
35 } else if (*var<min) {
36 printf("Limiting %s to min %d from %d\n", name, min, *var);
37 *var=min;
38 }
39 }
40
show_usage(char * progname)41 static void show_usage(char *progname) {
42 printf("%s\n",progname);
43 printf("\t-h : Show this help\n");
44 printf("\t-l <num> : Only show <num> frames\n");
45 printf("\t-n <num> : set number of particles to <num>\n");
46 printf("\t-x <xres> : set x resolution\n");
47 printf("\t-y <yres> : set y resolution\n");
48 printf("\t-r : run in root window\n");
49 printf("\t-m : randomly change force modes\n");
50 printf("\t-b <0-255>: Set particle brightness\n");
51 printf("\t-f : Show frames per second\n");
52 printf("\t-c <color>: Run with a colormap based on a given color\n"
53 "\t : e.g. -c 0xffaa66 for shades of orange\ne"
54 "\t : -c 0xaaccff for shades of something?!\n");
55 printf("hello world!\n");
56 exit(0);
57 }
58
renderpsys(Gfx * g,Particle_Sys * psys,unsigned char brightness)59 static void renderpsys(Gfx *g, Particle_Sys *psys, unsigned char brightness) {
60 Particle *p = psys->p;
61 int pcount=psys->n_particles;
62 /* can render to anywhere between 1 and xmax - 2 ( because we don't want
63 particles to actually HIT the edges of the window as that messes with
64 the blur algorithm - well, it makes it harder to write it if we can't
65 just assume the left and right columns are always going to be zero.
66 range is therefore MAX: (xmax - 1) MIN : 1
67 1 -> xmax-1
68 p->x is 0.0->1.0
69 hence : 1 + p->x * (cb->xmax - 3) */
70 while (pcount --) {
71 p=psys->p + pcount;
72 // using the #defined version
73 // gfx_add_pixel(g,
74
75 GFX_ADD_PIXEL(g,
76 (int)(1 + p->x * (g->xres-3)),
77 (int)(2 + p->y * (g->yres-3)),
78 brightness);
79 }
80 }
81
setexitevt()82 void setexitevt() {
83 /* signal handler function to set flag
84 to shut down program down immediately */
85 cleanup_and_exit=1;
86 }
87
signalhandler()88 void signalhandler() {
89 /* catch all/any/everything!
90 (might want to use sigaction for portability) */
91 signal(SIGHUP,setexitevt);
92 signal(SIGINT,setexitevt);
93 signal(SIGKILL,setexitevt);
94 signal(SIGPIPE,setexitevt);
95 signal(SIGALRM,setexitevt);
96 signal(SIGTERM,setexitevt);
97 signal(SIGXCPU,setexitevt);
98 signal(SIGXFSZ,setexitevt);
99 signal(SIGVTALRM,setexitevt);
100 signal(SIGPROF,setexitevt);
101
102 signal(SIGUSR1,setexitevt);
103 signal(SIGUSR2,setexitevt);
104 }
105
106
handle_keyboard_io(Gfx * g,Particle_Sys * p,int showkeys)107 void handle_keyboard_io(Gfx *g, Particle_Sys *p, int showkeys) {
108 int key;
109
110 int RENDKEY = 'R';
111 int DECKEY1 = '9';
112 int INCKEY1 = '0';
113 int DECKEY2 = 'o';
114 int INCKEY2 = 'p';
115 int DECKEY3 = 'l';
116 int INCKEY3 = ';';
117 int DECKEY4 = '.';
118 int INCKEY4 = '/';
119 int NEXFKEY = 'n';
120 int RESETKEY = 'r';
121 int DFLTKEY = 'd';
122 int QUITKEY = 'q';
123 int GRAVKEY = 'g';
124 int MODE1= '1';
125 int MODE2= '2';
126 int MODE3= '3';
127 int MODE4= '4';
128 int MODE5= '5';
129 int WHATKEY='h';
130
131 int PAUSEKEY=' ';
132
133 while ((key =gfx_getkey(g)) || (showkeys==1)) {
134 /* increase or decrease the control variables for the current force system */
135 if (key==DECKEY1) { psys_dec_var(p, 0); key=0;}
136 if (key==INCKEY1) { psys_inc_var(p, 0); key=0;}
137
138 if (key==DECKEY2) { psys_dec_var(p, 1); key=0;}
139 if (key==INCKEY2) { psys_inc_var(p, 1); key=0;}
140
141 if (key==RENDKEY) { g->renderer=!g->renderer; }
142 if (key==DECKEY3) { psys_dec_var(p, 2); key=0;}
143 if (key==INCKEY3) { psys_inc_var(p, 2); key=0;}
144
145 if (key==DECKEY4) { psys_dec_var(p, 3); key=0;}
146 if (key==INCKEY4) { psys_inc_var(p, 3); key=0;}
147
148 if (key==NEXFKEY) { psys_set_rnd(p); key=0;}
149
150 if (key==RESETKEY) { psys_reset_all_particles(p); key=0;}
151
152 if (key==DFLTKEY) { psys_reset_defaults(p); key=0;}
153
154 if (key==QUITKEY) { cleanup_and_exit=1; key=0;}
155
156 if (key==GRAVKEY) { psys_toggle_gravity(p); key=0;}
157
158 if (key==MODE1) { psys_set_gra(p); key =0; }
159
160 if (key==MODE2) { psys_set_ang(p); key =0; }
161
162 if (key==MODE3) { psys_set_oth(p); key =0; }
163
164 if (key==MODE4) { psys_set_spr(p); key =0; }
165
166 if (key==MODE5) { psys_set_stf(p); key =0; }
167
168 if (key==PAUSEKEY) { paused=!paused; key=0; }
169
170 if ((key==WHATKEY) || (showkeys==1)) {
171 showkeys=0;
172 printf("\n\n\n ---- KEYBOARD CONTOLS ----\n");
173 printf(" (Just press them randomly!)\n");
174 printf("CURRENT FORCE SYSTEM PARAMETER CONTROLS:\n");
175 printf(" Decrease/Increase variable 1 : '%c' / '%c'\n",DECKEY1,INCKEY1);
176 printf(" Decrease/Increase variable 2 : '%c' / '%c'\n",DECKEY2,INCKEY2);
177 printf(" Decrease/Increase variable 3 : '%c' / '%c'\n",DECKEY3,INCKEY3);
178 printf(" Decrease/Increase variable 4 : '%c' / '%c'\n",DECKEY4,INCKEY4);
179 printf(" Restore to defaults : '%c'\n", DFLTKEY);
180
181 printf("\nFORCE SYSTEM:\n");
182 printf(" grav : '%c'\n", MODE1);
183 printf(" angular : '%c'\n", MODE2);
184 printf(" other (weird) : '%c'\n", MODE3);
185 printf(" spring : '%c'\n", MODE4);
186 printf(" cheesy starfield : '%c'\n", MODE5);
187 printf(" Random : '%c'\n", NEXFKEY);
188 printf(" Display this info : '%c'\n", WHATKEY);
189
190 printf("\nGENERAL:\n");
191 printf(" Reset positions + velocities : '%c'\n", RESETKEY);
192 printf(" Switch to other renderer : '%c'\n", RENDKEY);
193 printf(" Toggle vertical gravity : '%c'\n", GRAVKEY);
194 printf(" PAUSE/UNPAUSE : '%c'\n", PAUSEKEY);
195
196 printf("QUIT : '%c'\n", QUITKEY);
197 printf("\n\n\n\n");
198 printf("run program with -h to see a list of command line options\n");
199 printf(" e.g. -x 800 -y 600 or somesuch.\n\n\n");
200
201 printf("Any and all feedback is really welcome, so please \n");
202 printf("send patches, advice, ideas, thoughts etc. to\n");
203 printf("\tsr@pepcross.com\n");
204 printf("\n\n");
205
206 key=0;
207 }
208 #ifdef DEBUG
209 if (key) printf("I don't know how to handle %c\n", key);
210 #endif
211 }
212 }
213
214
main(int argc,char * argv[])215 int main(int argc, char *argv[]) {
216 int showusage=0;
217 int optchar;
218 Particle_Sys psys;
219
220 struct timeval tp1,tp2;
221 struct timezone tz;
222
223 Gfx g;
224
225 g.default_xres = 800;
226 g.default_yres = 600;
227
228 /* Defaults for Particle System */
229 int fperforcesys=0;
230 /* Defaults for imaging */
231 unsigned char brightness=50;
232
233 /* Variables required by frames/per/second calculations */
234 int frame=0;
235 int framelimit=0;
236
237 signalhandler();
238
239 showusage=0;
240
241 gettimeofday(&tp1,&tz); // get starttime
242 g.renderer = (tp1.tv_usec)&01; // randomize which renderer we use
243
244 psys.n_particles=5000;
245 psys_set_defaults(&psys);
246 g.base_colour=0xccaaff;
247 g.rootwin=0;
248
249 /* DUMB ARGUMENT HANDLING */
250 while ((optchar = getopt(argc, argv, "i:m:fhRrn:x:y:b:c:l:")) != -1)
251 switch (optchar) {
252 case 'm' : fperforcesys=atoi(optarg); break;
253 case 'l' : framelimit =atoi(optarg); break;
254 case 'r' : g.rootwin =1; break;
255 case 'R' : g.renderer =1; break;
256 case 'n' : psys.n_particles=atoi(optarg); break;
257 case 'x' : g.xres=atoi(optarg); break;
258 case 'y' : g.yres=atoi(optarg); break;
259 case 'h' : showusage=1; break;
260 case 'b' : brightness=atoi(optarg); break;
261 case 'c' : g.base_colour=strtol(optarg,0,16); break;
262 case 'i' : psys.loadimage=(char *) malloc (strlen(optarg)); strcpy(psys.loadimage, optarg); break;
263 default: showusage=1;
264 }
265 argc -= optind;
266 argv += optind;
267 if (showusage)
268 show_usage(argv[-optind]);
269
270 if (framelimit)
271 printf("Showing %d frames and quitting\n", framelimit);
272
273 ilimit("Number of frames before changing to next force mode", &fperforcesys, 0, 10000);
274 ilimit("Number of frames to show", &framelimit, 0, 10000);
275
276 ilimit("numParticles", &(psys.n_particles), 1, 2000000);
277 #ifdef DEBUG
278 printf("Running with brightness %d\n", brightness);
279 #endif
280
281 /* Setup structures */
282 if (!gfx_SetupGfx(&g)) {
283 fprintf(stderr, "Unable to initialise graphics routines\n");
284 return 1;
285 }
286 psys_create_particles(&psys);
287 /* Main loop - FIXME, should a use proper Xlib event loop really */
288
289 handle_keyboard_io(&g, &psys, 1);
290
291 // init
292 tz.tz_minuteswest=tz.tz_dsttime=0; /* Ignore timezone */
293 gettimeofday(&tp1, &tz);
294 gettimeofday(&tp2, &tz);
295
296
297 // per frame
298 int delay =0;
299 while (cleanup_and_exit==0 && (!framelimit || (frame<framelimit)) ) {
300 float frametime;
301 gettimeofday(&tp1,&tz); // get starttime
302 if ((fperforcesys) && (frame % fperforcesys))
303 psys_set_rnd(&psys); // randomise force system
304 if (!paused) psys_automovep(&psys); // move particles
305 if (!paused) renderpsys(&g, &psys,brightness); // put particles into image
306 if (!paused) render_blurred_buffer(&g); // draw image
307 handle_keyboard_io(&g, &psys,0);
308 gfx_display_image(&g);
309 frame++;
310 gettimeofday(&tp2,&tz); // get endtime
311 frametime = (tp2.tv_sec - tp1.tv_sec)*1000000 + (tp2.tv_usec - tp1.tv_usec);
312 delay=(1000000/24)-frametime; // the 30 here is the target fps
313 usleep(delay>0?delay:0);
314 }
315
316 if (cleanup_and_exit!=0)
317 printf("Exiting due to received signal\n");
318
319 gfx_cleanup(&g);
320 return 1;
321 }
322
323
324