aboutsummaryrefslogtreecommitdiff
path: root/src/cmd/draw
diff options
context:
space:
mode:
authorrsc <devnull@localhost>2005-01-04 22:13:32 +0000
committerrsc <devnull@localhost>2005-01-04 22:13:32 +0000
commited01060152eba67eaa0f16605563c2de333d938d (patch)
treecdc3ddc2e2c3e43c5a00e6c4a8bae37f43c0a746 /src/cmd/draw
parentcb003809883f69642b4b561671dc5539dae22e0a (diff)
downloadplan9port-ed01060152eba67eaa0f16605563c2de333d938d.tar.gz
plan9port-ed01060152eba67eaa0f16605563c2de333d938d.tar.bz2
plan9port-ed01060152eba67eaa0f16605563c2de333d938d.zip
3d color cube
Diffstat (limited to 'src/cmd/draw')
-rw-r--r--src/cmd/draw/cmapcube.c226
1 files changed, 226 insertions, 0 deletions
diff --git a/src/cmd/draw/cmapcube.c b/src/cmd/draw/cmapcube.c
new file mode 100644
index 00000000..a7f4d928
--- /dev/null
+++ b/src/cmd/draw/cmapcube.c
@@ -0,0 +1,226 @@
+#include <u.h>
+#include <libc.h>
+#include <draw.h>
+#include <event.h>
+#include <geometry.h>
+
+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.z<b->screen.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);
+ }
+ }
+}