X-Git-Url: http://git.hungrycats.org/cgi-bin/gitweb.cgi?p=xscreensaver;a=blobdiff_plain;f=hacks%2Fglx%2Fengine.c;h=f2a956f5438341f0dc1642b5b0e00776bad74a88;hp=4b9b1d4da76b6be07d93a61606db710bce6af53f;hb=96a411663168b0ba5432b407a83be55f3df0c802;hpb=40eacb5812ef7c0e3374fb139afbb4f5bc8bbfb5 diff --git a/hacks/glx/engine.c b/hacks/glx/engine.c index 4b9b1d4d..f2a956f5 100644 --- a/hacks/glx/engine.c +++ b/hacks/glx/engine.c @@ -35,16 +35,21 @@ /* insert defaults here */ #define DEF_ENGINE "(none)" +#define DEF_TITLES "False" +#define DEF_SPIN "True" +#define DEF_WANDER "True" #define DEFAULTS "*delay: 10000 \n" \ "*showFPS: False \n" \ "*move: True \n" \ "*spin: True \n" \ "*engine: " DEF_ENGINE "\n" \ + "*titles: " DEF_TITLES "\n" \ + "*titleFont: -*-times-bold-r-normal-*-180-*\n" \ -# include "xlockmore.h" /* from the xscreensaver distribution */ +# include "xlockmore.h" /* from the xscreensaver distribution */ #else /* !STANDALONE */ -# include "xlock.h" /* from the xlockmore distribution */ +# include "xlock.h" /* from the xlockmore distribution */ #endif /* !STANDALONE */ #include "rotator.h" @@ -70,19 +75,23 @@ static char *which_engine; static int move; static int movepaused = 0; static int spin; +static Bool do_titles; static XrmOptionDescRec opts[] = { - {"-engine", ".engine.engine", XrmoptionSepArg, DEF_ENGINE }, - {"-move", ".engine.move", XrmoptionNoArg, (caddr_t) "true" }, - {"+move", ".engine.move", XrmoptionNoArg, (caddr_t) "false" }, - {"-spin", ".engine.spin", XrmoptionNoArg, (caddr_t) "true" }, - {"+spin", ".engine.spin", XrmoptionNoArg, (caddr_t) "false" }, + {"-engine", ".engine.engine", XrmoptionSepArg, DEF_ENGINE }, + {"-move", ".engine.move", XrmoptionNoArg, (caddr_t) "True" }, + {"+move", ".engine.move", XrmoptionNoArg, (caddr_t) "False" }, + {"-spin", ".engine.spin", XrmoptionNoArg, (caddr_t) "True" }, + {"+spin", ".engine.spin", XrmoptionNoArg, (caddr_t) "False" }, + { "-titles", ".engine.titles", XrmoptionNoArg, (caddr_t) "True" }, + { "+titles", ".engine.titles", XrmoptionNoArg, (caddr_t) "False" }, }; static argtype vars[] = { {(caddr_t *) &which_engine, "engine", "Engine", DEF_ENGINE, t_String}, - {(caddr_t *) &move, "move", "Move", "True", t_Bool}, - {(caddr_t *) &spin, "spin", "Spin", "True", t_Bool}, + {(caddr_t *) &move, "move", "Move", DEF_WANDER, t_Bool}, + {(caddr_t *) &spin, "spin", "Spin", DEF_SPIN, t_Bool}, + {(caddr_t *) &do_titles, "titles", "Titles", DEF_TITLES, t_Bool}, }; ModeSpecOpt engine_opts = {countof(opts), opts, countof(vars), vars, NULL}; @@ -108,6 +117,9 @@ typedef struct { rotator *rot; trackball_state *trackball; Bool button_down_p; + XFontStruct *xfont; + GLuint font_dlist; + char *engine_name; } Engine; static Engine *engine = NULL; @@ -175,10 +187,11 @@ float tan_table[TWOREV]; * To avoid going completely insane, we also reorder these so the newly * renumbered cylinder 0 is always first: 0-3-4-1-2-5 * - * For a flat 6, the included angle is 180 degrees (0 would be a inline engine). - * Because these are all four-stroke engines, each piston goes through - * 720 degrees of rotation for each time the spark plug sparks, so in this case, - * we would use the following angles: + * For a flat 6, the included angle is 180 degrees (0 would be a inline + * engine). Because these are all four-stroke engines, each piston goes + * through 720 degrees of rotation for each time the spark plug sparks, + * so in this case, we would use the following angles: + * * cylinder firing order angle * -------- ------------ ----- * 0 0 0 @@ -240,7 +253,7 @@ engine_type engines[] = { /* given a number of cylinders and an included angle, finds matching engine */ int find_engine(const char *name) { - int i; + unsigned int i; if (!name || !*name || !strcasecmp (name, "(none)")) return (random() % countof(engines)); @@ -269,9 +282,10 @@ int find_engine(const char *name) in one frame can be a bit harsh.. */ -void make_tables(void) { -int i; -float f; +void make_tables(void) +{ + int i; + float f; f = ONEREV / (M_PI * 2); for (i = 0 ; i <= TWOREV ; i++) { @@ -290,16 +304,17 @@ float f; /* angle is how far around the axis to go (up to 360) */ void cylinder (GLfloat x, GLfloat y, GLfloat z, - float length, float outer, float inner, int endcaps, int sang, int eang) { -int a; /* current angle around cylinder */ -int b = 0; /* previous */ -int angle, norm, step, sangle; -float z1, y1, z2, y2, ex=0; -float y3, z3; -float Z1, Y1, Z2, Y2, xl, Y3, Z3; -GLfloat y2c[TWOREV], z2c[TWOREV]; -GLfloat ony, onz; /* previous normals */ -int nsegs, tube = 0; + float length, float outer, float inner, int endcaps, int sang, int eang) +{ + int a; /* current angle around cylinder */ + int b = 0; /* previous */ + int angle, norm, step, sangle; + float z1, y1, z2, y2, ex=0; + float y3, z3; + float Z1, Y1, Z2, Y2, xl, Y3, Z3; + GLfloat y2c[TWOREV], z2c[TWOREV]; + GLfloat ony, onz; /* previous normals */ + int nsegs, tube = 0; glPushMatrix(); nsegs = outer*(MAX(win_w, win_h)/200); @@ -436,7 +451,8 @@ int nsegs, tube = 0; } /* this is just a convenience function to make a solid rod */ -void rod (GLfloat x, GLfloat y, GLfloat z, float length, float diameter) { +void rod (GLfloat x, GLfloat y, GLfloat z, float length, float diameter) +{ cylinder(x, y, z, length, diameter, diameter, 3, 0, ONEREV); } @@ -461,10 +477,11 @@ GLvoid normal(GLfloat v1[], GLfloat v2[], GLfloat v3[], void Rect(GLfloat x, GLfloat y, GLfloat z, GLfloat w, GLfloat h, - GLfloat t) { -GLfloat yh; -GLfloat xw; -GLfloat zt; + GLfloat t) +{ + GLfloat yh; + GLfloat xw; + GLfloat zt; yh = y+h; xw = x+w; zt = z - t; @@ -507,9 +524,10 @@ GLfloat zt; glEnd(); } -void makepiston(void) { -GLfloat colour[] = {0.6, 0.6, 0.6, 1.0}; -int i; +void makepiston(void) +{ + GLfloat colour[] = {0.6, 0.6, 0.6, 1.0}; + int i; i = glGenLists(1); glNewList(i, GL_COMPILE); @@ -525,17 +543,19 @@ int i; glEndList(); } -void CrankBit(GLfloat x) { +void CrankBit(GLfloat x) +{ Rect(x, -1.4, 0.5, 0.2, 1.8, 1); cylinder(x, -0.5, 0, 0.2, 2, 2, 1, 60, 120); } -void boom(GLfloat x, GLfloat y, int s) { -static GLfloat red[] = {0, 0, 0, 0.9}; -static GLfloat lpos[] = {0, 0, 0, 1}; -static GLfloat d = 0, wd; -int flameOut = 720/ENG.speed/ENG.cylinders; -static int time = 0; +void boom(GLfloat x, GLfloat y, int s) +{ + static GLfloat red[] = {0, 0, 0, 0.9}; + static GLfloat lpos[] = {0, 0, 0, 1}; + static GLfloat d = 0, wd; + int flameOut = 720/ENG.speed/ENG.cylinders; + static int time = 0; if (time == 0 && s) { red[0] = red[1] = 0; @@ -575,17 +595,17 @@ static int time = 0; glDisable(GL_BLEND); } -void display(Engine *e) { - -static int a = 0; -GLfloat zb, yb; -static GLfloat ln[730], yp[730], ang[730]; -static int ln_init = 0; -static int lastPlug = 0; -int half; -int sides; -int j, b; -static float rightSide; +void display(Engine *e) +{ + static int a = 0; + GLfloat zb, yb; + static GLfloat ln[730], yp[730], ang[730]; + static int ln_init = 0; + static int lastPlug = 0; + int half; + int sides; + int j, b; + static float rightSide; glEnable(GL_LIGHTING); glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); @@ -672,8 +692,10 @@ static float rightSide; b = (a+HALFREV+ENG.pistonAngle[j+half]) % TWOREV; glPushMatrix(); glRotatef(ang[b], 0, 1, 0); - rod(-cos_table[b], -crankWidth/2-crankOffset*(j+half), -sin_table[b], - ln[b], 0.2); + rod(-cos_table[b], + -crankWidth/2-crankOffset*(j+half), + -sin_table[b], + ln[b], 0.2); glPopMatrix(); } glPopMatrix(); @@ -736,11 +758,12 @@ static float rightSide; glFlush(); } -void makeshaft (void) { -int i; -int j; -const static float crankThick = 0.2; -const static float crankDiam = 0.3; +void makeshaft (void) +{ + int i; + int j; + static const float crankThick = 0.2; + static const float crankDiam = 0.3; i = glGenLists(1); glNewList(i, GL_COMPILE); @@ -757,10 +780,11 @@ const static float crankDiam = 0.3; */ rod(-2, 0, 0, 2, crankDiam); - /* Each crank is crankWidth units wide and the total width of a cylinder assembly - * is 3.3 units. For inline engines, there is just a single crank per cylinder - * width. For other engine configurations, there is a crank between each pair - * of adjacent cylinders on one side of the engine, so the crankOffset length is + /* Each crank is crankWidth units wide and the total width of a + * cylinder assembly is 3.3 units. For inline engines, there is just + * a single crank per cylinder width. For other engine + * configurations, there is a crank between each pair of adjacent + * cylinders on one side of the engine, so the crankOffset length is * halved. */ crankOffset = 3.3; @@ -793,9 +817,93 @@ const static float crankDiam = 0.3; glEndList(); } -void reshape_engine(ModeInfo *mi, int width, int height) +static void +load_font (ModeInfo *mi, char *res, XFontStruct **fontP, GLuint *dlistP) { + const char *font = get_string_resource (res, "Font"); + XFontStruct *f; + Font id; + int first, last; + + if (!font) font = "-*-times-bold-r-normal-*-180-*"; + + f = XLoadQueryFont(mi->dpy, font); + if (!f) f = XLoadQueryFont(mi->dpy, "fixed"); + + id = f->fid; + first = f->min_char_or_byte2; + last = f->max_char_or_byte2; + + clear_gl_error (); + *dlistP = glGenLists ((GLuint) last+1); + check_gl_error ("glGenLists"); + glXUseXFont(id, first, last-first+1, *dlistP + first); + check_gl_error ("glXUseXFont"); + + *fontP = f; +} + + +static void +print_title_string (ModeInfo *mi, const char *string, GLfloat x, GLfloat y) +{ + Engine *e = &engine[MI_SCREEN(mi)]; + XFontStruct *font = e->xfont; + GLfloat line_height = font->ascent + font->descent; + + y -= line_height; + glPushAttrib (GL_TRANSFORM_BIT | /* for matrix contents */ + GL_ENABLE_BIT); /* for various glDisable calls */ + glDisable (GL_LIGHTING); + glDisable (GL_DEPTH_TEST); + { + glMatrixMode(GL_PROJECTION); + glPushMatrix(); + { + glLoadIdentity(); + + glMatrixMode(GL_MODELVIEW); + glPushMatrix(); + { + unsigned int i; + int x2 = x; + glLoadIdentity(); + + gluOrtho2D (0, mi->xgwa.width, 0, mi->xgwa.height); + + glRasterPos2f (x, y); + for (i = 0; i < strlen(string); i++) + { + char c = string[i]; + if (c == '\n') + { + glRasterPos2f (x, (y -= line_height)); + x2 = x; + } + else + { + glCallList (e->font_dlist + (int)(c)); + x2 += (font->per_char + ? font->per_char[c - font->min_char_or_byte2].width + : font->min_bounds.width); + } + } + } + glPopMatrix(); + } + glMatrixMode(GL_PROJECTION); + glPopMatrix(); + } + glPopAttrib(); + + glMatrixMode(GL_MODELVIEW); +} + + + +void reshape_engine(ModeInfo *mi, int width, int height) +{ glViewport(0,0,(GLint)width, (GLint) height); glMatrixMode(GL_PROJECTION); glLoadIdentity(); @@ -807,8 +915,8 @@ void reshape_engine(ModeInfo *mi, int width, int height) void init_engine(ModeInfo *mi) { -int screen = MI_SCREEN(mi); -Engine *e; + int screen = MI_SCREEN(mi); + Engine *e; if (engine == NULL) { if ((engine = (Engine *) calloc(MI_NUM_SCREENS(mi), @@ -865,11 +973,24 @@ Engine *e; glEnable(GL_NORMALIZE); make_tables(); engineType = find_engine(which_engine); + + e->engine_name = malloc(200); + sprintf (e->engine_name, + "%s\n%s%d%s", + engines[engineType].engineName, + (engines[engineType].includedAngle == 0 ? "" : + engines[engineType].includedAngle == 180 ? "Flat " : "V"), + engines[engineType].cylinders, + (engines[engineType].includedAngle == 0 ? " Cylinder" : "") + ); + makeshaft(); makepiston(); + load_font (mi, "titleFont", &e->xfont, &e->font_dlist); } -Bool engine_handle_event (ModeInfo *mi, XEvent *event) { +Bool engine_handle_event (ModeInfo *mi, XEvent *event) +{ Engine *e = &engine[MI_SCREEN(mi)]; if (event->xany.type == ButtonPress && @@ -898,26 +1019,31 @@ Bool engine_handle_event (ModeInfo *mi, XEvent *event) { return False; } -void draw_engine(ModeInfo *mi) { -Engine *e = &engine[MI_SCREEN(mi)]; -Window w = MI_WINDOW(mi); -Display *disp = MI_DISPLAY(mi); +void draw_engine(ModeInfo *mi) +{ + Engine *e = &engine[MI_SCREEN(mi)]; + Window w = MI_WINDOW(mi); + Display *disp = MI_DISPLAY(mi); if (!e->glx_context) - return; + return; glXMakeCurrent(disp, w, *(e->glx_context)); display(e); + if (do_titles) + print_title_string (mi, e->engine_name, + 10, mi->xgwa.height - 10); + if(mi->fps_p) do_fps(mi); glFinish(); glXSwapBuffers(disp, w); } -void release_engine(ModeInfo *mi) { - +void release_engine(ModeInfo *mi) +{ if (engine != NULL) { (void) free((void *) engine); engine = NULL;