commit ed01060152eba67eaa0f16605563c2de333d938d from: rsc date: Tue Jan 04 22:13:32 2005 UTC 3d color cube commit - cb003809883f69642b4b561671dc5539dae22e0a commit + ed01060152eba67eaa0f16605563c2de333d938d blob - /dev/null blob + a7f4d928443b98938bf11a452dc3598bfee3e7f2 (mode 644) --- /dev/null +++ src/cmd/draw/cmapcube.c @@ -0,0 +1,226 @@ +#include +#include +#include +#include +#include + +typedef struct Vert{ + Point3 world; + Point3 screen; + int color; +}Vert; + +int nocubes; +int ncolor; +Quaternion q; +Image *image; +Image *bg; +Image *color[256]; +Rectangle viewrect; +int prevsel; + +int +cmp(Vert *a, Vert *b) +{ + if(a->screen.z>b->screen.z) + return -1; + if(a->screen.zscreen.z) + return 1; + return 0; +} + +/* crummy hack */ +void +readcolmap(Display *d, RGB *cmap) +{ + int i, rgb, r, g, b; + + for(i=0; i<256; i++){ + rgb = cmap2rgb(i); + r = rgb>>16; + g = (rgb>>8)&0xFF; + b = rgb & 0xFF; + cmap[i].red = r|(r<<8)|(r<<16)|(r<<24); + cmap[i].green = g|(g<<8)|(g<<16)|(g<<24); + cmap[i].blue = b|(b<<8)|(b<<16)|(b<<24); + } +} + +void +colorspace(RGB *cmap, Vert *v) +{ + Space *view; + int i; + + for(i=0;i!=ncolor;i++){ + v[i].world.x=(cmap[i].red>>24)/255.-.5; + v[i].world.y=(cmap[i].green>>24)/255.-.5; + v[i].world.z=(cmap[i].blue>>24)/255.-.5; + v[i].world.w=1.; + v[i].color=i; + } + view = pushmat(0); + viewport(view, viewrect, 1.); + persp(view, 30., 3., 7.); + look(view, (Point3){0., 0., -5., 1.}, (Point3){0., 0., 0., 1.}, + (Point3){0., 1., 0., 1.}); + qrot(view, q); + for(i=0;i!=ncolor;i++) + v[i].screen = xformpointd(v[i].world, 0, view); + popmat(view); +} + +void +line3(Vert a, Vert b) +{ + line(image, Pt(a.screen.x, a.screen.y), Pt(b.screen.x, b.screen.y), 0, 0, 0, display->white, ZP); +} + + +void +redraw(void) +{ + int i, m; + RGB cmap[256]; + Vert v[256]; + + readcolmap(display, cmap); + colorspace(cmap, v); + draw(image, image->r, bg, nil, Pt(0, 0)); + m = Dx(viewrect)/2; + if(m > Dy(viewrect)/2) + m = Dy(viewrect)/2; + ellipse(image, addpt(viewrect.min, divpt(Pt(Dx(viewrect), Dy(viewrect)), 2)), + m, m, 1, display->white, ZP); + + line3(v[0], v[0x36]); + line3(v[0x36], v[0x32]); + line3(v[0x32], v[0x3F]); + line3(v[0x3F], v[0]); + + line3(v[0xF0], v[0xF3]); + line3(v[0xF3], v[0xFF]); + line3(v[0xFF], v[0xFC]); + line3(v[0xFC], v[0xF0]); + + line3(v[0], v[0xF0]); + line3(v[0x36], v[0xF3]); + line3(v[0x32], v[0xFF]); + line3(v[0x3F], v[0xFC]); + + qsort(v, ncolor, sizeof(Vert), (int(*)(const void*, const void*))cmp); + if(!nocubes) + for(i=0; i!=ncolor; i++) + draw(image, rectaddpt(Rect(-3, -3, 4, 4), Pt(v[i].screen.x, v[i].screen.y)), + color[v[i].color], nil, Pt(0, 0)); + draw(screen, image->r, image, nil, image->r.min); + flushimage(display, 1); +} + +void +eresized(int new) +{ + int dx, dy; + + if(new && getwindow(display, Refnone) < 0){ + fprint(2, "colors: can't reattach to window: %r\n"); + exits("reshaped"); + } + draw(screen, screen->r, display->black, nil, ZP); + replclipr(screen, 0, insetrect(screen->r, 3)); + viewrect = screen->clipr; + viewrect.min.y += stringsize(font, "0i").y + 5; + if(image) + freeimage(image); + image = allocimage(display, viewrect, screen->chan, 0, DNofill); + dx = viewrect.max.x-viewrect.min.x; + dy = viewrect.max.y-viewrect.min.y; + if(dx>dy){ + viewrect.min.x=(viewrect.min.x+viewrect.max.x-dy)/2; + viewrect.max.x=viewrect.min.x+dy; + } + else{ + viewrect.min.y=(viewrect.min.y+viewrect.max.y-dx)/2; + viewrect.max.y=viewrect.min.y+dx; + } + if(image==nil){ + fprint(2, "can't allocate image\n"); + exits("bad allocimage"); + } + prevsel = -1; + redraw(); +} + +void main(int argc, char **argv){ + Vert v[256]; + RGB cmap[256]; + char buf[100]; + Point p; + Mouse m; + int i; + ulong bgcol; + + bgcol = DNofill; + ARGBEGIN{ + case 'n': + nocubes = 1; + break; + case 'b': + bgcol = DBlack; + break; + case 'w': + bgcol = DWhite; + break; + }ARGEND + + initdraw(0,0,0); + ncolor=256; + for(i=0;i!=ncolor;i++) + color[i] = allocimage(display, Rect(0, 0, 1, 1), CMAP8, 1, cmap2rgba(i)); + if(bgcol==DNofill){ + bg = allocimage(display, Rect(0, 0, 2, 2), screen->chan, 1, DWhite); + draw(bg, Rect(0, 0, 1, 1), color[0], nil, Pt(0, 0)); + draw(bg, Rect(1, 1, 2, 2), color[0], nil, Pt(0, 0)); + }else + bg = allocimage(display, Rect(0,0,1,1), screen->chan, 1, bgcol); + + q=(Quaternion){1.,0.,0.,0.}; + einit(Emouse); + eresized(0); + + for(;;){ + m = emouse(); + if(m.buttons&1) + qball(viewrect, &m, &q, redraw, 0); + else if(m.buttons & 2){ + readcolmap(display, cmap); + colorspace(cmap, v); + qsort(v, ncolor, sizeof(Vert), (int(*)(const void*, const void*))cmp); + while(m.buttons){ + for(i=ncolor-1; i!=0; i--){ + if(ptinrect(m.xy, rectaddpt(Rect(-3, -3, 4, 4), Pt(v[i].screen.x, v[i].screen.y)))){ + i = v[i].color; + if(i == prevsel) + break; + sprint(buf, "index %3d r %3ld g %3ld b %3ld", + i, + cmap[i].red>>24, + cmap[i].green>>24, + cmap[i].blue>>24); + p = addpt(screen->r.min, Pt(2,2)); + draw(screen, Rpt(p, addpt(p, stringsize(font, buf))), display->black, nil, p); + string(screen, p, display->white, ZP, font, buf); + prevsel = i; + break; + } + } + m = emouse(); + } + }else if(m.buttons&4){ + do + m = emouse(); + while(m.buttons); + exits(0); + } + } +}