-/* bouncingcow, Copyright (c) 2003 Jamie Zawinski <jwz@jwz.org>
+/* bouncingcow, Copyright (c) 2003-2018 Jamie Zawinski <jwz@jwz.org>
*
* Permission to use, copy, modify, distribute, and sell this software and its
* documentation for any purpose is hereby granted without fee, provided that
* Boing, boing, boing. Cow, cow, cow.
*/
-#include <X11/Intrinsic.h>
-
-extern XtAppContext app;
-
-#define PROGCLASS "BouncingCow"
-#define HACK_INIT init_cow
-#define HACK_DRAW draw_cows
-#define HACK_RESHAPE reshape_cow
-#define HACK_HANDLE_EVENT cow_handle_event
-#define EVENT_MASK PointerMotionMask
-#define sws_opts xlockmore_opts
-
-#define DEF_SPEED "1.0"
-#define DEF_TEXTURE "(none)"
-
#define DEFAULTS "*delay: 30000 \n" \
"*count: 1 \n" \
"*showFPS: False \n" \
"*wireframe: False \n" \
- "*speed: " DEF_SPEED " \n" \
- "*texture: " DEF_TEXTURE "\n" \
-/* #define DEBUG */
+# define free_cow 0
+# define release_cow 0
+#define DEF_SPEED "1.0"
+#define DEF_TEXTURE "(none)"
#undef countof
#define countof(x) (sizeof((x))/sizeof((*x)))
#include "xlockmore.h"
#include "rotator.h"
#include "gltrackball.h"
-#include "xpm-ximage.h"
+#include "ximage-loader.h"
#include <ctype.h>
#ifdef USE_GL /* whole file */
-#include <GL/glu.h>
-
-
#include "gllist.h"
extern struct gllist
*cow_face, *cow_hide, *cow_hoofs, *cow_horns, *cow_tail, *cow_udder;
-struct gllist **all_objs[] = {
+static struct gllist **all_objs[] = {
&cow_face, &cow_hide, &cow_hoofs, &cow_horns, &cow_tail, &cow_udder
};
static XrmOptionDescRec opts[] = {
{ "-speed", ".speed", XrmoptionSepArg, 0 },
{"-texture", ".texture", XrmoptionSepArg, 0 },
- {"+texture", ".texture", XrmoptionNoArg, (caddr_t) "(none)" },
+ {"+texture", ".texture", XrmoptionNoArg, "(none)" },
};
static argtype vars[] = {
- {(caddr_t *) &speed, "speed", "Speed", DEF_SPEED, t_Float},
- {(caddr_t *) &do_texture, "texture", "Texture", DEF_TEXTURE, t_String},
+ {&speed, "speed", "Speed", DEF_SPEED, t_Float},
+ {&do_texture, "texture", "Texture", DEF_TEXTURE, t_String},
};
-ModeSpecOpt sws_opts = {countof(opts), opts, countof(vars), vars, NULL};
+ENTRYPOINT ModeSpecOpt cow_opts = {countof(opts), opts, countof(vars), vars, NULL};
#define BOTTOM 28.0
/* Window management, etc
*/
-void
+ENTRYPOINT void
reshape_cow (ModeInfo *mi, int width, int height)
{
GLfloat h = (GLfloat) height / (GLfloat) width;
+ int y = 0;
- glViewport (0, 0, (GLint) width, (GLint) height);
+ if (width > height * 5) { /* tiny window: show middle */
+ height = width * 9/16;
+ y = -height/2;
+ h = height / (GLfloat) width;
+ }
+
+ glViewport (0, y, (GLint) width, (GLint) height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
}
-Bool
+ENTRYPOINT Bool
cow_handle_event (ModeInfo *mi, XEvent *event)
{
cow_configuration *bp = &bps[MI_SCREEN(mi)];
- if (event->xany.type == ButtonPress &&
- event->xbutton.button & Button1)
- {
- bp->button_down_p = True;
- gltrackball_start (bp->trackball,
- event->xbutton.x, event->xbutton.y,
- MI_WIDTH (mi), MI_HEIGHT (mi));
- return True;
- }
- else if (event->xany.type == ButtonRelease &&
- event->xbutton.button & Button1)
- {
- bp->button_down_p = False;
- return True;
- }
- else if (event->xany.type == MotionNotify &&
- bp->button_down_p)
- {
- gltrackball_track (bp->trackball,
- event->xmotion.x, event->xmotion.y,
- MI_WIDTH (mi), MI_HEIGHT (mi));
- return True;
- }
+ if (gltrackball_event_handler (event, bp->trackball,
+ MI_WIDTH (mi), MI_HEIGHT (mi),
+ &bp->button_down_p))
+ return True;
return False;
}
{
Display *dpy = mi->dpy;
Visual *visual = mi->xgwa.visual;
- Colormap cmap = mi->xgwa.colormap;
char buf[1024];
XImage *image;
return False;
}
- image = xpm_file_to_ximage (dpy, visual, cmap, filename);
+ image = file_to_ximage (dpy, visual, filename);
+ if (!image) return False;
clear_gl_error();
glTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA,
image->width, image->height, 0,
- GL_RGBA,
- /* GL_UNSIGNED_BYTE, */
- GL_UNSIGNED_INT_8_8_8_8_REV,
- image->data);
+ GL_RGBA, GL_UNSIGNED_BYTE, image->data);
sprintf (buf, "texture: %.100s (%dx%d)",
filename, image->width, image->height);
check_gl_error(buf);
glPixelStorei (GL_UNPACK_ALIGNMENT, 4);
glPixelStorei (GL_UNPACK_ROW_LENGTH, image->width);
- glTexEnvf (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
- glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
- glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
- glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
- glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
-
- glEnable(GL_TEXTURE_GEN_S);
- glEnable(GL_TEXTURE_GEN_T);
- glEnable(GL_TEXTURE_2D);
+
return True;
}
-void
+ENTRYPOINT void
init_cow (ModeInfo *mi)
{
cow_configuration *bp;
int wire = MI_IS_WIREFRAME(mi);
int i;
+ Bool tex_p = False;
- if (!bps) {
- bps = (cow_configuration *)
- calloc (MI_NUM_SCREENS(mi), sizeof (cow_configuration));
- if (!bps) {
- fprintf(stderr, "%s: out of memory\n", progname);
- exit(1);
- }
-
- bp = &bps[MI_SCREEN(mi)];
- }
+ MI_INIT (mi, bps);
bp = &bps[MI_SCREEN(mi)];
glLightfv(GL_LIGHT0, GL_SPECULAR, spc);
}
- bp->trackball = gltrackball_init ();
+ bp->trackball = gltrackball_init (False);
bp->dlists = (GLuint *) calloc (countof(all_objs)+1, sizeof(GLuint));
for (i = 0; i < countof(all_objs); i++)
bp->dlists[i] = glGenLists (1);
+ tex_p = load_texture (mi, do_texture);
+ if (tex_p)
+ glBindTexture (GL_TEXTURE_2D, bp->texture);
+
for (i = 0; i < countof(all_objs); i++)
{
GLfloat black[4] = {0, 0, 0, 1};
- struct gllist *gll = *all_objs[i];
- if (wire)
- gll->primitive = GL_LINE_LOOP;
+ const struct gllist *gll = *all_objs[i];
glNewList (bp->dlists[i], GL_COMPILE);
- glMatrixMode(GL_MODELVIEW);
- glPushMatrix();
- glMatrixMode(GL_TEXTURE);
- glPushMatrix();
- glMatrixMode(GL_MODELVIEW);
-
- glBindTexture (GL_TEXTURE_2D, 0);
+ glDisable (GL_TEXTURE_2D);
if (i == HIDE)
{
GLfloat color[4] = {0.63, 0.43, 0.36, 1.00};
-
- if (load_texture (mi, do_texture))
+ if (tex_p)
{
- glBindTexture (GL_TEXTURE_2D, bp->texture);
- glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
- glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
- glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
-
- /* approximately line it up with ../images/earth.xpm */
- glMatrixMode(GL_TEXTURE);
- glTranslatef(0.45, 0.58, 0);
- glScalef(0.08, 0.16, 1);
- glRotatef(-5, 0, 0, 1);
- glMatrixMode(GL_MODELVIEW);
-
/* if we have a texture, make the base color be white. */
color[0] = color[1] = color[2] = 1.0;
- }
+ glTexGeni (GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
+ glTexGeni (GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
+ glTexEnvf (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
+ glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP_TO_EDGE);
+ glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP_TO_EDGE);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glEnable(GL_TEXTURE_GEN_S);
+ glEnable(GL_TEXTURE_GEN_T);
+ glEnable(GL_TEXTURE_2D);
+
+ /* approximately line it up with ../images/earth.png */
+ glMatrixMode (GL_TEXTURE);
+ glLoadIdentity();
+ glTranslatef (0.45, 0.58, 0);
+ glScalef (0.08, 0.16, 1);
+ glRotatef (-5, 0, 0, 1);
+ glMatrixMode (GL_MODELVIEW);
+ }
glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, color);
glMaterialfv (GL_FRONT_AND_BACK, GL_SPECULAR, black);
- glMaterialf (GL_FRONT_AND_BACK, GL_SHININESS, 128);
- }
+ glMaterialf (GL_FRONT_AND_BACK, GL_SHININESS, 128);
+ }
else if (i == TAIL)
{
GLfloat color[4] = {0.63, 0.43, 0.36, 1.00};
glMaterialf (GL_FRONT_AND_BACK, GL_SHININESS, shiny);
}
- renderList (gll);
-
- glMatrixMode(GL_TEXTURE);
- glPopMatrix();
- glMatrixMode(GL_MODELVIEW);
- glPopMatrix();
+ renderList (gll, wire);
glEndList ();
}
glPushMatrix();
glTranslatef (f->x, f->y, f->z);
+ gltrackball_rotate (bp->trackball);
+
glRotatef (y * 360, 0.0, 1.0, 0.0);
if (f->spinner_p)
{
-void
-draw_cows (ModeInfo *mi)
+ENTRYPOINT void
+draw_cow (ModeInfo *mi)
{
cow_configuration *bp = &bps[MI_SCREEN(mi)];
Display *dpy = MI_DISPLAY(mi);
if (!bp->glx_context)
return;
+ glXMakeCurrent(MI_DISPLAY(mi), MI_WINDOW(mi), *(bp->glx_context));
+
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glPushMatrix ();
- gltrackball_rotate (bp->trackball);
+
+# ifdef HAVE_MOBILE /* Keep it the same relative size when rotated. */
+ {
+ GLfloat h = MI_HEIGHT(mi) / (GLfloat) MI_WIDTH(mi);
+ int o = (int) current_device_rotation();
+ if (o != 0 && o != 180 && o != -180)
+ glScalef (1/h, 1/h, 1/h);
+ glRotatef(o, 0, 0, 1);
+ }
+# endif
glScalef (0.5, 0.5, 0.5);
glXSwapBuffers(dpy, window);
}
+XSCREENSAVER_MODULE_2 ("BouncingCow", bouncingcow, cow)
+
#endif /* USE_GL */