Created
June 2, 2014 20:50
-
-
Save dln/a19c2b9365ba816a5675 to your computer and use it in GitHub Desktop.
Hack for xscreensaver I did a long time ago.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* A screen saver hack to display the CodeFactory logotype | |
* in a jiggling fashion with a lil bit o bounce... *grin* | |
* | |
* Daniel Lundin <daniel@codefactory.se> | |
* | |
* Copyright 2001 Seven relatively short dudes and a pale chick | |
* | |
* This software is released under Disgruntled Catholic License v6.66 | |
* Redistribution prohibited without authorization from the pope. | |
* Under special circumstances under which should such authorization | |
* request be denied or otherwise unable to achieve, redistribution may be | |
* authorized by the reader herself. | |
* | |
*/ | |
#include <math.h> | |
#include "screenhack.h" | |
#define ABS(a) (((a)<0) ? -(a) : (a)) | |
#define MIN(x,y) ((x)>(y)?(y):(x)) | |
#define MAX(x,y) ((x)<(y)?(y):(x)) | |
#define INT_MAX 2147483647 | |
#define ROLL_ROT_SPEED 0.01 | |
#define PITCH_ROT_SPEED 0.02 | |
#define YAW_ROT_SPEED 0.01 | |
char *progclass = "CFLogo"; | |
char *defaults [] = { | |
"*ncolors: 256", /* number of colours used */ | |
"*delay: 10", | |
0 | |
}; | |
XrmOptionDescRec options [] = { | |
{ "-ncolors", ".ncolors", XrmoptionSepArg, 0 }, | |
{ "-delay", ".delay", XrmoptionSepArg, 0 }, | |
{ 0, 0, 0, 0 } | |
}; | |
typedef struct { | |
double x,y,z; /* Coords */ | |
double rx,ry,rz; /* Rotated float */ | |
int px,py,pz; /* Projected coords */ | |
} cfpoint; | |
typedef struct { | |
cfpoint *src; /* Source cfpoint */ | |
cfpoint *dst; /* Destination cfpoint */ | |
} cfline; | |
typedef struct { | |
int minx, miny; /* Upper left corner */ | |
int maxx,maxy; /* Lower right corner */ | |
} cfcliprect; | |
typedef struct { | |
cfpoint *points; /* Points */ | |
cfline *lines; /* Lines */ | |
uint numpts; /* Number of points */ | |
uint numlines; /* Number of lines */ | |
cfpoint pos; /* Object position in 3D space */ | |
cfpoint dir; /* Delta movement */ | |
cfpoint min; /* Bounding box corner */ | |
cfpoint max; /* Other bounding box corner */ | |
float roll,pitch,yaw; /* Rotation along all axes */ | |
float roll_delta, /* Rotational speed */ | |
pitch_delta, | |
yaw_delta; | |
cfcliprect clip; /* Box for XCopyArea blitting */ | |
cfcliprect prev_clip; /* Last clip box (for clearing) */ | |
} cfobject; | |
/* A simple cube */ | |
static cfpoint obj[] = { | |
{-140, 140, -40, 0,0,0,0,0}, | |
{-140, -140, -40, 0,0,0,0,0}, | |
{-70, -140, -40, 0,0,0,0,0}, | |
{-70, 30, -40, 0,0,0,0,0}, | |
{ 0, -20, -40, 0,0,0,0,0}, | |
{ 0, 30, -40, 0,0,0,0,0}, | |
{ 70, -20, -40, 0,0,0,0,0}, | |
{ 70, 30, -40, 0,0,0,0,0}, | |
{ 140, -20, -40, 0,0,0,0,0}, | |
{ 140, 140, -40, 0,0,0,0,0}, /* 9 */ | |
{-140, 140, 40, 0,0,0,0,0}, | |
{-140, -140, 40, 0,0,0,0,0}, | |
{-70, -140, 40, 0,0,0,0,0}, | |
{-70, 30, 40, 0,0,0,0,0}, | |
{ 0, -20, 40, 0,0,0,0,0}, | |
{ 0, 30, 40, 0,0,0,0,0}, | |
{ 70, -20, 40, 0,0,0,0,0}, | |
{ 70, 30, 40, 0,0,0,0,0}, | |
{ 140, -20, 40, 0,0,0,0,0}, | |
{ 140, 140, 40, 0,0,0,0,0} /* 9 */ | |
}; | |
/* Lines for the cube */ | |
static cfline obj_lines[] = { | |
{&obj[0], &obj[1]}, | |
{&obj[1], &obj[2]}, | |
{&obj[2], &obj[3]}, | |
{&obj[3], &obj[4]}, | |
{&obj[4], &obj[5]}, | |
{&obj[5], &obj[6]}, | |
{&obj[6], &obj[7]}, | |
{&obj[7], &obj[8]}, | |
{&obj[8], &obj[9]}, | |
{&obj[9], &obj[0]}, | |
{&obj[10], &obj[11]}, | |
{&obj[11], &obj[12]}, | |
{&obj[12], &obj[13]}, | |
{&obj[13], &obj[14]}, | |
{&obj[14], &obj[15]}, | |
{&obj[15], &obj[16]}, | |
{&obj[16], &obj[17]}, | |
{&obj[17], &obj[18]}, | |
{&obj[18], &obj[19]}, | |
{&obj[19], &obj[10]}, | |
{&obj[10], &obj[0]}, | |
{&obj[11], &obj[1]}, | |
{&obj[12], &obj[2]}, | |
{&obj[13], &obj[3]}, | |
{&obj[14], &obj[4]}, | |
{&obj[15], &obj[5]}, | |
{&obj[16], &obj[6]}, | |
{&obj[17], &obj[7]}, | |
{&obj[18], &obj[8]}, | |
{&obj[19], &obj[9]} | |
}; | |
/* Logo object to toy around with */ | |
static cfobject logo_object = { | |
obj, | |
obj_lines, | |
sizeof (obj) / sizeof (cfpoint), | |
sizeof (obj_lines) / sizeof (cfline), | |
{300, 200, 0}, /* Position */ | |
{3.53, 2.35, 4}, /* Direction */ | |
{15,15,-450}, {640,400,10}, /* Bounding box */ | |
0, 0, 0, /* Rotation along all axes */ | |
ROLL_ROT_SPEED, PITCH_ROT_SPEED, YAW_ROT_SPEED, | |
{INT_MAX,INT_MAX,0,0}, | |
{INT_MAX,INT_MAX,0,0} | |
}; | |
/* delay (usec) between iterations */ | |
int delay=1; | |
uint numcolors; | |
Colormap cmap; | |
XColor* pal; | |
GC* gcs; | |
/* Rotate object and project it in 2D in rotatedPoints. */ | |
void rotate_obj (cfobject *obj) { | |
float sinY, cosY, cosX, sinX, cosZ, sinZ; | |
float tmpY; | |
float distance; | |
cfpoint *point; | |
ulong i; | |
obj->roll += obj->roll_delta; | |
if (obj->roll > M_PI * 2) | |
obj->roll = obj->roll - M_PI * 2; | |
obj->pitch += obj->pitch_delta; | |
if (obj->pitch > M_PI * 2) | |
obj->pitch = obj->pitch - M_PI * 2; | |
obj->yaw += obj->yaw_delta; | |
if (obj->yaw > M_PI * 2) | |
obj->yaw = obj->yaw - M_PI * 2; | |
cosY = cos (obj->pitch); | |
sinY = sin (obj->pitch); | |
cosX = cos (obj->roll); | |
sinX = sin (obj->roll); | |
cosZ = cos (obj->yaw); | |
sinZ = sin (obj->yaw); | |
/* Move the object */ | |
if (obj->pos.x > obj->max.x) | |
obj->dir.x = - ABS (obj->dir.x); | |
if (obj->pos.x < obj->min.x) | |
obj->dir.x = ABS (obj->dir.x); | |
if (obj->pos.y < obj->min.y ) | |
obj->dir.y = ABS (obj->dir.y); | |
if (obj->pos.y > obj->max.y) | |
obj->dir.y = - ABS (obj->dir.y); | |
else | |
obj->dir.y += 0.9; | |
if (obj->pos.z > obj->max.z) | |
obj->dir.z = - ABS (obj->dir.z); | |
if (obj->pos.z < obj->min.z) | |
obj->dir.z = ABS (obj->dir.z); | |
obj->pos.x = obj->pos.x + obj->dir.x; | |
obj->pos.y = obj->pos.y + obj->dir.y; | |
obj->pos.z = obj->pos.z + obj->dir.z; | |
/* Store previous clipping area */ | |
memcpy ( &(obj->prev_clip), &(obj->clip), sizeof (cfcliprect)); | |
/* Reset clipping area */ | |
obj->clip.maxx = 0; | |
obj->clip.minx = INT_MAX; | |
obj->clip.maxy = 0; | |
obj->clip.miny = INT_MAX; | |
for ( i = 0; i<obj->numpts; i++) { | |
point = &(obj->points[i]); | |
/* Rotate around Z axis */ | |
point->rx = point->x*cosZ - point->y*sinZ; | |
point->ry = point->x*sinZ + point->y*cosZ; | |
/* Rotate around Y axis */ | |
point->rz = point->rx*sinY + point->z*cosY; | |
point->rx = point->rx*cosY - point->z*sinY; | |
/* Rotate around X axis */ | |
tmpY=point->ry; /* Store rotated Y coordinate */ | |
point->ry = point->rz*sinX + tmpY*cosX; | |
point->rz = point->rz*cosX - tmpY*sinX; | |
/* Slimy-effect */ | |
point->rx=point->rx * (1 - 0.04 * (ABS (obj->dir.y) / 12) | |
* cos ((1 - ABS (obj->dir.y) / 5) * M_PI * 2 | |
- point->ry / 25)); | |
point->ry=point->ry * (1 - 0.05 * (ABS (obj->dir.y) / 12) | |
* cos ((1 - ABS (obj->dir.y) / 5) * M_PI * 2 | |
- point->ry / 25)); | |
point->rz=point->rz * (1 - 0.02 * (ABS (obj->dir.y) / 12) | |
* cos ((1 - ABS (obj->dir.y) / 5) * M_PI * 2 | |
- point->ry / 25)); | |
/* Add (fake) perspective projection */ | |
point->pz = point->rz + obj->pos.z; | |
distance = 250/(250-(float)(point->pz)); | |
point->px = distance * point->rx + obj->pos.x; | |
point->py = distance * point->ry + obj->pos.y; | |
/* Adjust clip rect if point is outside */ | |
if (point->px > obj->clip.maxx) | |
obj->clip.maxx = point->px; | |
if (point->py > obj->clip.maxy) | |
obj->clip.maxy = point->py; | |
if (point->px < obj->clip.minx) | |
obj->clip.minx = point->px; | |
if (point->py < obj->clip.miny) | |
obj->clip.miny = point->py; | |
} | |
} | |
#ifdef DEBUG | |
static float maxz,minz = 0; | |
#endif | |
/* Draw object. */ | |
void draw_obj (cfobject *obj, Display *dpy, Drawable d) { | |
uint i,j; | |
cfline *line; | |
for (i=0; i<obj->numlines; i++) | |
{ | |
line = &obj->lines[i]; | |
j = numcolors * ((line->src->rz + 202)/410); | |
#ifdef DEBUG | |
if (minz > line->src->rz) | |
minz = line->src->rz; | |
if (maxz < line->src->rz) | |
maxz = line->src->rz; | |
#endif | |
if (j >= numcolors ) | |
j = numcolors - 1; | |
if (j < 0 ) | |
j = 0; | |
XDrawLine (dpy, d, gcs[j], | |
line->src->px, line->src->py, | |
line->dst->px, line->dst->py); | |
} | |
#ifdef DEBUG | |
printf ("%f,%f\n", minz, maxz); | |
#endif | |
} | |
cfobject * | |
split_object_lines (cfobject *src) | |
{ | |
uint i,j,k; | |
cfobject *nobj; | |
nobj = malloc (sizeof (cfobject)); | |
if (nobj != NULL) | |
{ | |
/* Start with a copy of SRC */ | |
memcpy (nobj, src, sizeof (cfobject)); | |
if (nobj != NULL) | |
{ | |
/* Calculate number of lines and points in subvidied object */ | |
nobj->numlines = src->numlines * 2; | |
/* totalpts = totallines * ((1 << divs) - 1) + src->numpts; */ | |
/* Be pessimistic and let the optimize_object clean up later */ | |
nobj->numpts = nobj->numlines * 2; | |
nobj->points = malloc (sizeof (cfpoint) * nobj->numpts); | |
nobj->lines = malloc (sizeof (cfline) * nobj->numpts); | |
j = k = 0; | |
for (i=0; i<src->numlines; i++) | |
{ | |
memcpy (&(nobj->points[j]), src->lines[i].src, | |
sizeof (cfpoint)); | |
j++; | |
memcpy (&(nobj->points[j]), src->lines[i].dst, | |
sizeof (cfpoint)); | |
j++; | |
nobj->points[j].x = (nobj->points[j-1].x | |
+ nobj->points[j-2].x) / 2; | |
nobj->points[j].y = (nobj->points[j-1].y | |
+ nobj->points[j-2].y) / 2; | |
nobj->points[j].z = (nobj->points[j-1].z | |
+ nobj->points[j-2].z) / 2; | |
j++; | |
nobj->lines[k].src = &(nobj->points[j-3]); | |
nobj->lines[k].dst = &(nobj->points[j-1]); | |
k++; | |
nobj->lines[k].src = &(nobj->points[j-2]); | |
nobj->lines[k].dst = &(nobj->points[j-1]); | |
k++; | |
} | |
} | |
} | |
return nobj; | |
} | |
cfobject * | |
subdivide_object (cfobject *src, uint divs) | |
{ | |
uint i; | |
cfobject *result; | |
cfobject *tmp; | |
result = src; | |
for (i=0; i<divs; i++) | |
{ | |
tmp = result; | |
result = split_object_lines (tmp); | |
if (tmp != src) | |
free (tmp); | |
} | |
return result; | |
} | |
void | |
screenhack (Display *dpy, Window window) | |
{ | |
XGCValues gcv; | |
int delay = get_integer_resource ("delay", "Integer"); | |
int i; | |
GC erase_gc = 0; | |
XWindowAttributes xgwa; | |
Pixmap b=0; | |
cfobject *theobject; | |
cfcliprect clipping; | |
theobject = subdivide_object (&logo_object, 5); | |
if ( theobject != NULL ) | |
{ | |
XGetWindowAttributes (dpy, window, &xgwa); | |
b = XCreatePixmap (dpy, window, xgwa.width, | |
xgwa.height, xgwa.depth); | |
gcv.foreground = get_pixel_resource ("background", "Background", | |
dpy, xgwa.colormap); | |
erase_gc = XCreateGC (dpy, b, GCForeground, &gcv); | |
/* Mix us some colors */ | |
cmap = xgwa.colormap; | |
numcolors = get_integer_resource("ncolors", "Integer"); | |
if(numcolors < 2) | |
numcolors = 2; | |
pal = calloc(numcolors, sizeof(XColor)); | |
make_color_ramp(dpy, cmap, | |
200, 1, 0, | |
200, 0, 1, | |
pal, &(numcolors), | |
False, True, False); | |
gcs = calloc(numcolors, sizeof(GC)); | |
gcv.line_width = 1; | |
for(i = 0; i < numcolors; i++) { | |
gcv.foreground =pal[i].pixel; | |
gcs[i] = XCreateGC(dpy, b, GCForeground|GCLineWidth, &gcv); | |
} | |
theobject->min.x = 15; | |
theobject->min.y = 15; | |
theobject->min.z = -350; | |
theobject->max.x = xgwa.width-15; | |
theobject->max.y = xgwa.height-15; | |
theobject->max.z = 30; | |
theobject->pos.x = xgwa.width/2; | |
theobject->pos.y = xgwa.height - 400; | |
theobject->pos.z = 0; | |
while (1) | |
{ | |
XFillRectangle (dpy, b, erase_gc, 0, 0, xgwa.width, xgwa.height); | |
rotate_obj (theobject); | |
draw_obj (theobject, dpy, b); | |
clipping.minx = MIN(theobject->clip.minx, | |
theobject->prev_clip.minx) - 4 ; | |
clipping.miny = MIN(theobject->clip.miny, | |
theobject->prev_clip.miny) - 4; | |
clipping.maxx = MAX(theobject->clip.maxx, | |
theobject->prev_clip.maxx) + 4; | |
clipping.maxy = MAX(theobject->clip.maxy, | |
theobject->prev_clip.maxy) + 4; | |
XCopyArea (dpy, b, window, erase_gc, | |
clipping.minx, | |
clipping.miny, | |
clipping.maxx - clipping.minx, | |
clipping.maxy - clipping.miny, | |
clipping.minx, | |
clipping.miny); | |
XSync (dpy, False); | |
screenhack_handle_events (dpy); | |
if (delay) | |
usleep (delay); | |
} | |
free (theobject); | |
free (pal); | |
free (gcs); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment