Plan 9 from Bell Labs’s /usr/web/sources/contrib/andrey/glenda.c

Copyright © 2021 Plan 9 Foundation.
Distributed under the MIT License.
Download the Plan 9 distribution.


/*
 * Ported to Plan 9 from XScreensaver by mirtchov@cpsc.ucalgary.ca, 10/03
 * 
 * modified with extra glendas: 11/03
 */

/* plan9-related stuff */
#include "plan9.h"
Image *glenda;
Image *mask;

ulong frames = 0;
vlong tbegin, tend;



#define POINT_COUNT 16
#define LINE_COUNT 32

#define ANGLE_SCALE 0.001

struct line_info
{
	char li_ip;
	char li_iq;
	char li_color;
	char li_pad;
};

struct point_state
{
	short old_x, old_y;
	short new_x, new_y;
};

struct hyper_state
{
	char hs_stop;
	char hs_icon;
	char hs_resize;
	char hs_redraw;
	float hs_two_observer_z;
	float hs_offset_x;
	float hs_offset_y;
	float hs_unit_scale;
	int hs_delay;
	double hs_cos_xy, hs_sin_xy;
	double hs_cos_xz, hs_sin_xz;
	double hs_cos_yz, hs_sin_yz;
	double hs_cos_xw, hs_sin_xw;
	double hs_cos_yw, hs_sin_yw;
	double hs_cos_zw, hs_sin_zw;
	double hs_ref_ax, hs_ref_ay, hs_ref_az, hs_ref_aw;
	double hs_ref_bx, hs_ref_by, hs_ref_bz, hs_ref_bw;
	double hs_ref_cx, hs_ref_cy, hs_ref_cz, hs_ref_cw;
	double hs_ref_dx, hs_ref_dy, hs_ref_dz, hs_ref_dw;
	struct point_state hs_points[POINT_COUNT];
};

static const struct line_info line_table[LINE_COUNT];

static void init (struct hyper_state *hs);
static void hyper (struct hyper_state *hs);
static void check_events (struct hyper_state *hs);
static void set_sizes (struct hyper_state *hs, int width, int height);

static struct hyper_state hyper_state;

void
screenhack (void)
{
	struct hyper_state *hs;

	hs = &hyper_state;

	init (hs);

	hyper (hs);
}


static void
init (struct hyper_state *hs)
{
	int delay, width, height;
	float observer_z;


	observer_z = frand()*5.0;
	if (observer_z < 1.125)
		observer_z = 1.125;
	hs->hs_two_observer_z = 2.0 * observer_z;

	width = Dx(screen->r);
	height = Dy(screen->r);
	set_sizes (hs, width, height);

	delay = 10;
	hs->hs_delay = delay;


	hs->hs_ref_ax = 1.0, hs->hs_ref_ay = 0.0, hs->hs_ref_az = 0.0, hs->hs_ref_aw = 0.0;
	hs->hs_ref_bx = 0.0, hs->hs_ref_by = 1.0, hs->hs_ref_bz = 0.0, hs->hs_ref_bw = 0.0;
	hs->hs_ref_cx = 0.0, hs->hs_ref_cy = 0.0, hs->hs_ref_cz = 1.0, hs->hs_ref_cw = 0.0;
	hs->hs_ref_dx = 0.0, hs->hs_ref_dy = 0.0, hs->hs_ref_dz = 0.0, hs->hs_ref_dw = 1.0;

	{
		double xy;
		double xz;
		double yz;
		double xw;
		double yw;
		double zw;
		double cos_xy, sin_xy;
		double cos_xz, sin_xz;
		double cos_yz, sin_yz;
		double cos_xw, sin_xw;
		double cos_yw, sin_yw;
		double cos_zw, sin_zw;

/*		xy = 3 * ANGLE_SCALE;
		xz = 5 * ANGLE_SCALE;
		yz = 0 * ANGLE_SCALE;
		xw = 0 * ANGLE_SCALE;
		yw = 10 * ANGLE_SCALE;
		zw = 0 * ANGLE_SCALE;
*/
		xy = (nrand(3)+2) * ANGLE_SCALE;
		xz = (nrand(7)+2) * ANGLE_SCALE;
		yz = nrand(3) * ANGLE_SCALE;
		xw = nrand(5) * ANGLE_SCALE;
		yw = (nrand(10)+5) * ANGLE_SCALE;
		zw = nrand(3) * ANGLE_SCALE;

		cos_xy = cos (xy), sin_xy = sin (xy);
		hs->hs_cos_xy = cos_xy, hs->hs_sin_xy = sin_xy;
		cos_xz = cos (xz), sin_xz = sin (xz);
		hs->hs_cos_xz = cos_xz, hs->hs_sin_xz = sin_xz;
		cos_yz = cos (yz), sin_yz = sin (yz);
		hs->hs_cos_yz = cos_yz, hs->hs_sin_yz = sin_yz;
		cos_xw = cos (xw), sin_xw = sin (xw);
		hs->hs_cos_xw = cos_xw, hs->hs_sin_xw = sin_xw;
		cos_yw = cos (yw), sin_yw = sin (yw);
		hs->hs_cos_yw = cos_yw, hs->hs_sin_yw = sin_yw;
		cos_zw = cos (zw), sin_zw = sin (zw);
		hs->hs_cos_zw = cos_zw, hs->hs_sin_zw = sin_zw;
	}
}


static void
hyper (struct hyper_state *hs)
{
	int roted;

	roted = 0;

	tbegin = nsec();

	for (;;)
	{
		int icon;
		int resize;
		char moved[POINT_COUNT];
		int redraw = 0;
		int stop;
		int delay;

		check_events (hs);

		icon = hs->hs_icon;
		resize = hs->hs_resize;
		if (icon || !(roted | resize))
			goto skip1;

		{
			float observer_z;
			float unit_scale;
			float offset_x;
			float offset_y;
			double az, bz, cz, dz;
			double sum_z;
			double ax, bx, cx, dx;
			double sum_x;
			double ay, by, cy, dy;
			double sum_y;
			struct point_state *ps;
			int old_x;
			int old_y;
			double mul;
			double xf;
			double yf;
			int new_x;
			int new_y;
			int mov;


#define compute(as,bs,cs,ds,i) \
  az = hs->hs_ref_az; bz = hs->hs_ref_bz; cz = hs->hs_ref_cz; dz = hs->hs_ref_dz; \
  ax = hs->hs_ref_ax; bx = hs->hs_ref_bx; cx = hs->hs_ref_cx; dx = hs->hs_ref_dx; \
  ay = hs->hs_ref_ay; by = hs->hs_ref_by; cy = hs->hs_ref_cy; dy = hs->hs_ref_dy; \
  sum_z = as az bs bz cs cz ds dz; \
  observer_z = hs->hs_two_observer_z; \
  unit_scale = hs->hs_unit_scale; \
  sum_x = as ax bs bx cs cx ds dx; \
  sum_y = as ay bs by cs cy ds dy; \
  ps = &hs->hs_points[i]; \
  mul = unit_scale / (observer_z - sum_z); \
  offset_x = hs->hs_offset_x; \
  offset_y = hs->hs_offset_y; \
  old_x = ps->new_x; \
  old_y = ps->new_y; \
  xf = sum_x * mul + offset_x; \
  yf = sum_y * mul + offset_y; \
  new_x = (int)(xf+0.5); \
  new_y = (int)(yf+0.5); \
  ps->old_x = old_x; \
  ps->old_y = old_y; \
  ps->new_x = new_x; \
  ps->new_y = new_y; \
  mov = old_x != new_x || old_y != new_y; \
  moved[i] = mov;

			compute (-, -, -, -, 0);
			compute (-, -, -, +, 1);
			compute (-, -, +, -, 2);
			compute (-, -, +, +, 3);
			compute (-, +, -, -, 4);
			compute (-, +, -, +, 5);
			compute (-, +, +, -, 6);
			compute (-, +, +, +, 7);
			compute (+, -, -, -, 8);
			compute (+, -, -, +, 9);
			compute (+, -, +, -, 10);
			compute (+, -, +, +, 11);
			compute (+, +, -, -, 12);
			compute (+, +, -, +, 13);
			compute (+, +, +, -, 14);
			compute (+, +, +, +, 15);
		}

skip1:
		icon = hs->hs_icon;
		if (icon || !(roted | redraw))
			goto skip2;

		{
			int i, p_x, p_y;
			for (i = 0; i < POINT_COUNT; i++) {
				p_x = hs->hs_points[i].old_x;
				p_y = hs->hs_points[i].old_y;
				if(p_x == 0 && p_y == 0)
					continue;
				draw(screen, 
					rectaddpt(Rect(p_x-24, p_y-24, p_x+24, p_y+24), screen->r.min),
					colors[i], mask, ZP);
				p_x = hs->hs_points[i].new_x;
				p_y = hs->hs_points[i].new_y;
				draw(screen, 
					rectaddpt(Rect(p_x-24, p_y-24, p_x+24, p_y+24), screen->r.min),
					glenda, mask, ZP);
				}

			flushimage(display, 1);
		}

skip2:
		stop = hs->hs_stop;
		roted = 0;
		if (stop)
			goto skip3;

		roted = 1;

		{
			double cos_a;
			double sin_a;
			double old_u;
			double old_v;
			double new_u;
			double new_v;

			/* If you get error messages about the following forms, and you think you're
    using an ANSI C conforming compiler, then you're mistaken.  Possibly you're
    mixing an ANSI compiler with a non-ANSI preprocessor, or vice versa.
    Regardless, your system is broken; it's not a bug in this program.
  */

#define rotate(name,dim0,dim1) \
  old_u = hs->hs_ref_/**/name/**/dim0; \
  old_v = hs->hs_ref_/**/name/**/dim1; \
  new_u = old_u * cos_a + old_v * sin_a; \
  new_v = old_v * cos_a - old_u * sin_a; \
  hs->hs_ref_/**/name/**/dim0 = new_u; \
  hs->hs_ref_/**/name/**/dim1 = new_v;

#define rotates(dim0,dim1) \
  if (hs->hs_sin_/**/dim0/**/dim1 != 0) { \
    cos_a = hs->hs_cos_/**/dim0/**/dim1; \
    sin_a = hs->hs_sin_/**/dim0/**/dim1; \
    rotate(a,dim0,dim1); \
    rotate(b,dim0,dim1); \
    rotate(c,dim0,dim1); \
    rotate(d,dim0,dim1); \
  }

			rotates (x,y);
			rotates (x,z);
			rotates (y,z);
			rotates (x,w);
			rotates (y,w);
			rotates (z,w);
		}

skip3:
		/* stop = hs->hs_stop; */
		delay = hs->hs_delay;
		if (stop && delay < 10)
			delay = 10;

		frames++;
		if (delay > 0)
			sleep (delay);
	}
}


static void
check_events (struct hyper_state *hs)
{
  	hs->hs_resize = 0;
  	hs->hs_redraw = 0;
	
	if(ecanmouse()) {
		m = emouse();
		if(m.buttons&4)
			if(emenuhit(3, &m, &menu) == 0)  {
				tend = nsec();
				print("fps: %uf\n", frames/((tend - tbegin)/1000000000.0));
				exits(0);
			}
		if(m.buttons&1)
			hs->hs_stop = hs->hs_stop ? 0 :  1;
		if(m.buttons&2)
			draw(screen, screen->r, display->black, nil, ZP);
	}

}


static void
set_sizes (struct hyper_state *hs, int width, int height)
{
	double observer_z;
	int min_dim;
	double var;
	double offset_x;
	double offset_y;
	double unit_scale;

	observer_z = 0.5 * hs->hs_two_observer_z;
	min_dim = width < height ? width : height;
	var = sqrt(observer_z * observer_z - 1.0);
	offset_x = 0.5 * (double)(width - 1);
	offset_y = 0.5 * (double)(height - 1);
	unit_scale = 0.4 * min_dim * var;
	hs->hs_offset_x = (float)offset_x;
	hs->hs_offset_y = (float)offset_y;
	hs->hs_unit_scale = (float)unit_scale;
}


/* data */

static const struct line_info line_table[LINE_COUNT] =
{
	{ 0, 1, 0, },
	{ 0, 2, 0, },
	{ 1, 3, 0, },
	{ 2, 3, 0, },
	{ 4, 5, 1, },
	{ 4, 6, 1, },
	{ 5, 7, 1, },
	{ 6, 7, 1, },
	{ 0, 4, 4, },
	{ 0, 8, 4, },
	{ 4, 12, 4, },
	{ 8, 12, 4, },
	{ 1, 5, 5, },
	{ 1, 9, 5, },
	{ 5, 13, 5, },
	{ 9, 13, 5, },
	{ 2, 6, 6, },
	{ 2, 10, 6, },
	{ 6, 14, 6, },
	{ 10, 14, 6, },
	{ 3, 7, 7, },
	{ 3, 11, 7, },
	{ 7, 15, 7, },
	{ 11, 15, 7, },
	{ 8, 9, 2, },
	{ 8, 10, 2, },
	{ 9, 11, 2, },
	{ 10, 11, 2, },
	{ 12, 13, 3, },
	{ 12, 14, 3, },
	{ 13, 15, 3, },
	{ 14, 15, 3, },
};

void
eresized(int new)
{

	if(new && getwindow(display, Refnone) < 0) {
		sysfatal("can't reattach to window");
	}

	set_sizes (&hyper_state, Dx(screen->r), Dy(screen->r));
	hyper_state.hs_resize = 1;

	draw(screen, screen->r, display->black, nil, ZP);

}

void 
main(int argc, char **argv)
{
	int i, fd;

	USED(argc, argv);
	srand(time(0)*getpid());


	if(initdraw(nil, nil, "glenda") < 0)
		sysfatal("initdraw failed: %r");

	for(i = 0; i < POINT_COUNT; i++) {
		colors[i] = allocimage(display, Rect(0, 0, 1, 1), screen->chan, 1, 
			cmap2rgba(nrand(128)+64));
	}

	einit(Emouse);
//	eresized(0);

	fd = open("/lib/face/48x48x4/g/glenda.1", OREAD);
	if(fd < 0)
		sysfatal("cannot open /lib/face/48x48x4/g/glenda.1: %r");

	glenda = readimage(display, fd, 0);
	if(glenda == nil)
		sysfatal("cannot load glenda's image: %r");
	close(fd);

	mask = allocimage(display, Rect(0, 0, 48, 48), glenda->chan, 1, DCyan);
	if(mask == nil)
		sysfatal("cannot allocate mask: %r");

	draw(mask, mask->r, display->white, nil, ZP);
	gendraw(mask, mask->r, display->black, ZP, glenda, glenda->r.min);
	freeimage(glenda);
	glenda = display->white;

	draw(screen, screen->r, display->black, nil, ZP);

	screenhack();
}

Bell Labs OSI certified Powered by Plan 9

(Return to Plan 9 Home Page)

Copyright © 2021 Plan 9 Foundation. All Rights Reserved.
Comments to webmaster@9p.io.