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