X-Git-Url: http://git.hungrycats.org/cgi-bin/gitweb.cgi?p=xscreensaver;a=blobdiff_plain;f=hacks%2Fglx%2Fglcells.c;h=c0cbbbf077e983da3a2aa2baf17bb68914dab880;hp=86355f10dee35b7e2f13875163f6df2997a50c8d;hb=4361b69d3178d7fc98d0388f9a223af6c2651aba;hpb=c8c6deae79b408cffbc88043c766b3bc12cf0f13 diff --git a/hacks/glx/glcells.c b/hacks/glx/glcells.c index 86355f10..c0cbbbf0 100644 --- a/hacks/glx/glcells.c +++ b/hacks/glx/glcells.c @@ -4,7 +4,7 @@ /*- * Cells growing on your screen * - * Copyright (c) 2006 by Matthias Toussaint + * Copyright (c) 2007 by Matthias Toussaint * * Permission to use, copy, modify, and distribute this software and its * documentation for any purpose and without fee is hereby granted, @@ -18,7 +18,10 @@ * event will the author be liable for any lost revenue or profits or * other special, indirect and consequential damages. * - * 2006: Written by Matthias Toussaint + * 2007: Written by Matthias Toussaint + * 0.1 Initial version + * 0.2 Bugfixes (threading) and code cleanup by Jamie Zawinski + * Window scaling bug + performance bug in tick() */ #include /* gettimeofday */ @@ -34,6 +37,7 @@ #define NUM_CELL_SHAPES 10 #define refresh_glcells 0 +#define release_glcells 0 #define glcells_handle_event 0 #define DEF_DELAY "20000" @@ -45,17 +49,20 @@ #define DEF_MINFOOD "5" #define DEF_MAXFOOD "20" #define DEF_DIVIDEAGE "20" -#define DEF_MINDIST "1.40" +#define DEF_MINDIST "1.4" #define DEF_PAUSE "50" #define DEFAULTS "*delay: 30000 \n" \ "*showFPS: False \n" \ "*wireframe: False \n" \ + "*suppressRotationAnimation: True\n" \ #undef countof #define countof(x) (sizeof((x))/sizeof((*x))) -#define USE_VERTEX_ARRAY +#ifndef HAVE_JWZGLES /* glDrawElements unimplemented... */ +# define USE_VERTEX_ARRAY +#endif #define TEX_SIZE 64 @@ -116,11 +123,12 @@ typedef struct /* hacks state */ { GLXContext *glx_context; int width, height; /* current size of viewport */ + double screen_scale; /* we scale content with window size */ int num_cells; /* current number of cell in list */ Cell *cell; /* array of cells */ int cell_polys; GLfloat color[4]; /* current cell color */ - int radius; /* cell radius */ + double radius; /* cell radius */ int move_dist; /* min distance from neighbours for forking */ int max_cells; /* maximum number of cells */ int num_seeds; /* number of initial seeds */ @@ -180,7 +188,7 @@ static argtype vars[] = { {&s_maxfood, "maxfood", "Max Food", DEF_MAXFOOD, t_Int}, {&s_pause, "pause", "Pause at end", DEF_PAUSE, t_Int}, {&s_divideage, "divideage", "Age for duplication (Ticks)", DEF_DIVIDEAGE, t_Int}, - {&s_min_dist, "mindist", "Minimum prefered distance to other cells", DEF_MINDIST, t_Float}, + {&s_min_dist, "mindist", "Minimum preferred distance to other cells", DEF_MINDIST, t_Float}, {&s_keepold, "keepold", "Keep old cells", DEF_KEEPOLD, t_Bool} }; @@ -238,7 +246,9 @@ static Object *create_sphere( State *st, int divisions ); static Object *clone_Object( Object * ); /* return 1 if cell is capable to divide */ static int can_divide( State *st, Cell *cell ); +#ifdef USE_VERTEX_ARRAY static VertexArray *array_from_ObjectSmooth( ObjectSmooth * ); +#endif static void create_nucleus_texture( State *st ); ENTRYPOINT ModeSpecOpt glcells_opts = { countof(opts), opts, countof(vars), vars, @@ -252,7 +262,9 @@ ENTRYPOINT ModeSpecOpt glcells_opts = { countof(opts), opts, */ static inline int random_interval( int min, int max ) { - return min+(random()%(max-min)); + int n = max - min; + if (n == 0) n = 1; + return min+(random()%n); } static inline int random_max( int max ) @@ -416,6 +428,7 @@ static Object *clone_Object( Object *obj ) return ret; } +#ifdef USE_VERTEX_ARRAY static VertexArray *array_from_ObjectSmooth( ObjectSmooth *obj ) { int i, j; @@ -443,6 +456,8 @@ static VertexArray *array_from_ObjectSmooth( ObjectSmooth *obj ) return array; } +#endif /* USE_VERTEX_ARRAY */ + /* create a smoothed version of the given Object by computing average normal vectors for the vertexes @@ -690,8 +705,7 @@ static int render( State *st ) fprintf( stderr, "tick %d\n", usec ); gettimeofday( &tv1, NULL ); #endif - glClearColor( 0, 0, 0, 0 ); - + glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); glDepthFunc(GL_LESS); glEnable(GL_DEPTH_TEST); @@ -706,9 +720,24 @@ static int render( State *st ) glEnable( GL_NORMALIZE ); glPolygonMode( GL_FRONT, GL_FILL ); } else { +# ifndef HAVE_JWZGLES /* #### glPolygonMode other than GL_FILL unimplemented */ glPolygonMode( GL_FRONT, GL_LINE ); +# endif } +# if 0 + if (st->wire) { + glDisable(GL_DEPTH_TEST); + glColor3f (1, 1, 1); + glBegin(GL_LINE_LOOP); + glVertex3f(0, 0, 0); glVertex3f(st->width, 0, 0); + glVertex3f(st->width, st->height, 0); glVertex3f(0, st->height, 0); + glVertex3f(0, 0, 0); glVertex3f(st->width/4, 0, 0); + glVertex3f(st->width/4, st->height/4, 0); glVertex3f(0, st->height/4, 0); + glEnd(); + } +# endif + /* draw the dead cells if choosen */ if (st->keep_old_cells) { for (b=0; bnum_cells; ++b) { @@ -736,6 +765,15 @@ static int render( State *st ) num_paint++; /*glColor3f( fac, fac, fac );*/ +# if 0 + if (st->wire) { + glBegin(GL_LINES); + glVertex3f(0, 0, 0); + glVertex3f(st->cell[b].x, st->cell[b].y, 0); + glEnd(); + } +# endif + glPushMatrix(); glTranslatef( st->cell[b].x, st->cell[b].y, 0.0 ); glRotatef( st->cell[b].rotation, 0.0, 0.0, 1.0 ); @@ -844,6 +882,8 @@ static int create_list( State *st, double fac ) ObjectSmooth *smooth; #ifdef USE_VERTEX_ARRAY VertexArray *vertex_array; +#else + int t, i; #endif int list = glGenLists(1); @@ -892,6 +932,27 @@ static int create_list( State *st, double fac ) static void draw_cell( State *st, int shape ) { +# ifdef HAVE_JWZGLES /* #### glPolygonMode other than GL_FILL unimplemented */ + if (st->wire) { + glDisable(GL_DEPTH_TEST); + glColor3f (1, 1, 1); + glPushMatrix(); + glScalef (0.33, 0.33, 1); + glBegin (GL_LINE_LOOP); + glVertex3f (-1, -1, 0); glVertex3f (-1, 1, 0); + glVertex3f ( 1, 1, 0); glVertex3f ( 1, -1, 0); + glEnd(); + if (shape == 9) { + glBegin (GL_LINES); + glVertex3f (-1, -1, 0); glVertex3f (1, 1, 0); + glVertex3f (-1, 1, 0); glVertex3f (1, -1, 0); + glEnd(); + } + glPopMatrix(); + return; + } +# endif + if (-1 == st->cell_list[shape]) { st->cell_list[shape] = create_list( st, (double)shape/10.0 ); } @@ -951,9 +1012,10 @@ static void draw_nucleus( State *st ) static void create_cells( State *st ) { + int border = (int)(200.0 * st->screen_scale); int i, foodcnt; - int w = st->width-400; - int h = st->height-400; + int w = st->width-2*border; + int h = st->height-2*border; st->color[0] = 0.5 + random_max( 1000 ) * 0.0005; st->color[1] = 0.5 + random_max( 1000 ) * 0.0005; @@ -975,8 +1037,8 @@ static void create_cells( State *st ) st->num_cells = st->num_seeds; for (i=0; inum_cells; ++i) { - st->cell[i].x = 200 + random_max( w ); - st->cell[i].y = 200 + random_max( h ); + st->cell[i].x = border + random_max( w ); + st->cell[i].y = border + random_max( h ); st->cell[i].vx = 0.0; st->cell[i].vy = 0.0; st->cell[i].age = random_max( 0x0f ); @@ -999,6 +1061,7 @@ static void tick( State *st ) int num_living = 0; const double check_dist = 0.75*st->move_dist; const double grow_dist = 0.75*st->radius; + const double adult_radius = st->radius; /* find number of cells capable of division and count living cells @@ -1068,7 +1131,8 @@ static void tick( State *st ) const double dy = st->cell[b].y - st->cell[j].y; if (fabs(dx) < check_dist || fabs(dy) < check_dist) { - const double dist = sqrt( dx*dx+dy*dy ); + const double dist = dx*dx+dy*dy; + /*const double dist = sqrt( dx*dx+dy*dy );*/ if (distcell[b].min_dist = len; /* if not adult (radius too small) */ - if (st->cell[b].radius < st->radius) { + if (st->cell[b].radius < adult_radius) { /* if too small 60% stop shrinking */ - if (st->cell[b].radius < st->radius * 0.6) { + if (st->cell[b].radius < adult_radius * 0.6) { st->cell[b].growth = 1.0; } /* at safe distance we start growing again */ @@ -1130,9 +1194,11 @@ static void tick( State *st ) /* have a snack */ x = ((int)st->cell[b].x)/4; - if (x<0) x=0; if (x>=w4) x = w4-1; + if (x<0) x=0; + if (x>=w4) x = w4-1; y = ((int)st->cell[b].y)/4; - if (y<0) y=0; if (y>=h4) y = h4-1; + if (y<0) y=0; + if (y>=h4) y = h4-1; offset = x+y*w4; @@ -1156,37 +1222,60 @@ ENTRYPOINT void reshape_glcells( ModeInfo *mi, int width, int height ) { State *st = &sstate[MI_SCREEN(mi)]; +# ifdef HAVE_MOBILE + int rot = current_device_rotation(); +# endif st->height = height; st->width = width; - +# ifdef HAVE_MOBILE + st->screen_scale = (double)(width < height ? width : height) / 1600.0; +# else + st->screen_scale = (double)width / 1600.0; +# endif + + st->radius = s_radius; + if (st->radius < 5) st->radius = 5; + if (st->radius > 200) st->radius = 200; + st->radius *= st->screen_scale; + + st->move_dist = s_min_dist; + if (st->move_dist < 1.0) st->move_dist = 1.0; + if (st->move_dist > 3.0) st->move_dist = 3.0; + st->move_dist *= st->radius; + glViewport (0, 0, (GLint) width, (GLint) height); glMatrixMode(GL_PROJECTION); glLoadIdentity(); glOrtho( 0, width, height, 0, 200, 0 ); +# ifdef HAVE_MOBILE + glRotatef (rot, 0, 0, 1); +# endif glMatrixMode(GL_MODELVIEW); glLoadIdentity(); - if (st->food) free( st->food ); st->food = (int *)malloc( ((width*height)/16)*sizeof(int) ); - - create_cells( st ); + /* create_cells( st );*/ + +# ifdef HAVE_MOBILE + glTranslatef (st->width/2, st->height/2, 0); + if (rot == 90 || rot == -90 || rot == 270 || rot == -270) + st->width = height, st->height = width; + glRotatef (rot, 0, 0, 1); + if (st->wire) glScalef(0.8, 0.8, 1); + glTranslatef (-st->width/2, -st->height/2, 0); +# endif } +static void free_glcells( ModeInfo *mi ); + ENTRYPOINT void init_glcells( ModeInfo *mi ) { int i, divisions; State *st=0; - if (!sstate) { - sstate = (State *) - calloc( MI_NUM_SCREENS(mi), sizeof(State) ); - if (!sstate) { - fprintf( stderr, "%s: out of memory\n", progname ); - exit(1); - } - } + MI_INIT(mi, sstate, free_glcells); st = &sstate[MI_SCREEN(mi)]; st->glx_context = init_GL(mi); @@ -1267,31 +1356,36 @@ draw_glcells( ModeInfo *mi ) *(st->glx_context) ); mi->polygon_count = render( st ); - + if (mi->fps_p) do_fps (mi); glFinish(); glXSwapBuffers( dpy, window ); } -ENTRYPOINT void -release_glcells( ModeInfo *mi ) +static void +free_glcells( ModeInfo *mi ) { int i; State *st = &sstate[MI_SCREEN(mi)]; + + if (st->glx_context) { + glXMakeCurrent( MI_DISPLAY(mi), MI_WINDOW(mi), + *(st->glx_context) ); - /* nuke everything before exit */ - if (st->sphere) free_Object( st->sphere ); - if (st->food) free( st->food ); - for (i=0; icell_list[i] != -1) { - glDeleteLists( st->cell_list[i], 1 ); + /* nuke everything before exit */ + if (st->sphere) free_Object( st->sphere ); + if (st->food) free( st->food ); + for (i=0; icell_list[i] != -1) { + glDeleteLists( st->cell_list[i], 1 ); + } } + if (st->cell) free( st->cell ); + free( st->disturbance ); + glDeleteTextures( 1, &st->texture_name ); + free( st->texture ); } - if (st->cell) free( st->cell ); - free( st->disturbance ); - glDeleteTextures( 1, &st->texture_name ); - free( st->texture ); } XSCREENSAVER_MODULE( "GLCells", glcells )