plan9port

fork of plan9port with libvec, libstr and libsdb
Log | Files | Refs | README | LICENSE

cmapcube.c (4957B)


      1 #include <u.h>
      2 #include <libc.h>
      3 #include <draw.h>
      4 #include <event.h>
      5 #include <geometry.h>
      6 
      7 typedef struct Vert{
      8 	Point3 world;
      9 	Point3 screen;
     10 	int color;
     11 }Vert;
     12 
     13 int		nocubes;
     14 int		ncolor;
     15 Quaternion	q = {1.,0.,0.,0.};
     16 Image		*image;
     17 Image		*bg;
     18 Image		*color[256];
     19 Rectangle	viewrect;
     20 int		prevsel;
     21 
     22 Point3
     23 p3(double x, double y, double z, double w)
     24 {
     25 	Point3 p;
     26 
     27 	p.x = x;
     28 	p.y = y;
     29 	p.z = z;
     30 	p.w = w;
     31 	return p;
     32 }
     33 
     34 int
     35 cmp(Vert *a, Vert *b)
     36 {
     37 	if(a->screen.z>b->screen.z)
     38 		return -1;
     39 	if(a->screen.z<b->screen.z)
     40 		return 1;
     41 	return 0;
     42 }
     43 
     44 /* crummy hack */
     45 void
     46 readcolmap(Display *d, RGB *cmap)
     47 {
     48 	int i, rgb, r, g, b;
     49 
     50 	for(i=0; i<256; i++){
     51 		rgb = cmap2rgb(i);
     52 		r = rgb>>16;
     53 		g = (rgb>>8)&0xFF;
     54 		b = rgb & 0xFF;
     55 		cmap[i].red = r|(r<<8)|(r<<16)|(r<<24);
     56 		cmap[i].green = g|(g<<8)|(g<<16)|(g<<24);
     57 		cmap[i].blue = b|(b<<8)|(b<<16)|(b<<24);
     58 	}
     59 }
     60 
     61 void
     62 colorspace(RGB *cmap, Vert *v)
     63 {
     64 	Space *view;
     65 	int i;
     66 
     67 	for(i=0;i!=ncolor;i++){
     68 		v[i].world.x=(cmap[i].red>>24)/255.-.5;
     69 		v[i].world.y=(cmap[i].green>>24)/255.-.5;
     70 		v[i].world.z=(cmap[i].blue>>24)/255.-.5;
     71 		v[i].world.w=1.;
     72 		v[i].color=i;
     73 	}
     74 	view = pushmat(0);
     75 	viewport(view, viewrect, 1.);
     76 	persp(view, 30., 3., 7.);
     77 	look(view, p3(0., 0., -5., 1.), p3(0., 0., 0., 1.),
     78 		p3(0., 1., 0., 1.));
     79 	qrot(view, q);
     80 	for(i=0;i!=ncolor;i++)
     81 		v[i].screen = xformpointd(v[i].world, 0, view);
     82 	popmat(view);
     83 }
     84 
     85 void
     86 line3(Vert a, Vert b)
     87 {
     88 	line(image, Pt(a.screen.x, a.screen.y), Pt(b.screen.x, b.screen.y), 0, 0, 0, display->white, ZP);
     89 }
     90 
     91 
     92 void
     93 redraw(void)
     94 {
     95 	int i, m;
     96 	RGB cmap[256];
     97 	Vert v[256];
     98 
     99 	readcolmap(display, cmap);
    100 	colorspace(cmap, v);
    101 	draw(image, image->r, bg, nil, Pt(0, 0));
    102 	m = Dx(viewrect)/2;
    103 	if(m > Dy(viewrect)/2)
    104 		m = Dy(viewrect)/2;
    105 	ellipse(image, addpt(viewrect.min, divpt(Pt(Dx(viewrect), Dy(viewrect)), 2)),
    106 		m, m, 1, display->white, ZP);
    107 
    108 	line3(v[0], v[0x36]);
    109 	line3(v[0x36], v[0x32]);
    110 	line3(v[0x32], v[0x3F]);
    111 	line3(v[0x3F], v[0]);
    112 
    113 	line3(v[0xF0], v[0xF3]);
    114 	line3(v[0xF3], v[0xFF]);
    115 	line3(v[0xFF], v[0xFC]);
    116 	line3(v[0xFC], v[0xF0]);
    117 
    118 	line3(v[0], v[0xF0]);
    119 	line3(v[0x36], v[0xF3]);
    120 	line3(v[0x32], v[0xFF]);
    121 	line3(v[0x3F], v[0xFC]);
    122 
    123 	qsort(v, ncolor, sizeof(Vert), (int(*)(const void*, const void*))cmp);
    124 	if(!nocubes)
    125 		for(i=0; i!=ncolor; i++)
    126 			draw(image, rectaddpt(Rect(-3, -3, 4, 4), Pt(v[i].screen.x, v[i].screen.y)),
    127 				color[v[i].color], nil, Pt(0, 0));
    128 	draw(screen, image->r, image, nil, image->r.min);
    129 	flushimage(display, 1);
    130 }
    131 
    132 void
    133 eresized(int new)
    134 {
    135 	int dx, dy;
    136 
    137 	if(new && getwindow(display, Refnone) < 0){
    138 		fprint(2, "colors: can't reattach to window: %r\n");
    139 		exits("reshaped");
    140 	}
    141 	draw(screen, screen->r, display->black, nil, ZP);
    142 	replclipr(screen, 0, insetrect(screen->r, 3));
    143 	viewrect = screen->clipr;
    144 	viewrect.min.y += stringsize(font, "0i").y + 5;
    145 	if(image)
    146 		freeimage(image);
    147 	image = allocimage(display, viewrect, screen->chan, 0, DNofill);
    148 	dx = viewrect.max.x-viewrect.min.x;
    149 	dy = viewrect.max.y-viewrect.min.y;
    150 	if(dx>dy){
    151 		viewrect.min.x=(viewrect.min.x+viewrect.max.x-dy)/2;
    152 		viewrect.max.x=viewrect.min.x+dy;
    153 	}
    154 	else{
    155 		viewrect.min.y=(viewrect.min.y+viewrect.max.y-dx)/2;
    156 		viewrect.max.y=viewrect.min.y+dx;
    157 	}
    158 	if(image==nil){
    159 		fprint(2, "can't allocate image\n");
    160 		exits("bad allocimage");
    161 	}
    162 	prevsel = -1;
    163 	redraw();
    164 }
    165 
    166 void main(int argc, char **argv){
    167 	Vert v[256];
    168 	RGB cmap[256];
    169 	char buf[100];
    170 	Point p;
    171 	Mouse m;
    172 	int i;
    173 	ulong bgcol;
    174 
    175 	bgcol = DNofill;
    176 	ARGBEGIN{
    177 	case 'n':
    178 		nocubes = 1;
    179 		break;
    180 	case 'b':
    181 		bgcol = DBlack;
    182 		break;
    183 	case 'w':
    184 		bgcol = DWhite;
    185 		break;
    186 	}ARGEND
    187 
    188 	if(initdraw(0,0,0) < 0)
    189 		sysfatal("initdraw: %r");
    190 	ncolor=256;
    191 	for(i=0;i!=ncolor;i++)
    192 		color[i] = allocimage(display, Rect(0, 0, 1, 1), CMAP8, 1, cmap2rgba(i));
    193 	if(bgcol==DNofill){
    194 		bg = allocimage(display, Rect(0, 0, 2, 2), screen->chan, 1, DWhite);
    195 		draw(bg, Rect(0, 0, 1, 1), color[0], nil, Pt(0, 0));
    196 		draw(bg, Rect(1, 1, 2, 2), color[0], nil, Pt(0, 0));
    197 	}else
    198 		bg = allocimage(display, Rect(0,0,1,1), screen->chan, 1, bgcol);
    199 
    200 	einit(Emouse);
    201 	eresized(0);
    202 
    203 	for(;;){
    204 		m = emouse();
    205 		if(m.buttons&1)
    206 			qball(viewrect, &m, &q, redraw, 0);
    207 		else if(m.buttons & 2){
    208 			readcolmap(display, cmap);
    209 			colorspace(cmap, v);
    210 			qsort(v, ncolor, sizeof(Vert), (int(*)(const void*, const void*))cmp);
    211 			while(m.buttons){
    212 				for(i=ncolor-1; i!=0; i--){
    213 					if(ptinrect(m.xy, rectaddpt(Rect(-3, -3, 4, 4), Pt(v[i].screen.x, v[i].screen.y)))){
    214 						i = v[i].color;
    215 						if(i == prevsel)
    216 							break;
    217 						sprint(buf, "index %3d r %3ld g %3ld b %3ld",
    218 							i,
    219 							cmap[i].red>>24,
    220 							cmap[i].green>>24,
    221 							cmap[i].blue>>24);
    222 						p = addpt(screen->r.min, Pt(2,2));
    223 						draw(screen, Rpt(p, addpt(p, stringsize(font, buf))), display->black, nil, p);
    224 						string(screen, p, display->white, ZP, font, buf);
    225 						prevsel = i;
    226 						break;
    227 					}
    228 				}
    229 				m = emouse();
    230 			}
    231 		}else if(m.buttons&4){
    232 			do
    233 				m = emouse();
    234 			while(m.buttons);
    235 			exits(0);
    236 		}
    237 	}
    238 }