From ff88c093d0092176e173e1bf6cbcd96df07f7e0c Mon Sep 17 00:00:00 2001 From: rodri Date: Sat, 24 Aug 2024 21:48:35 +0000 Subject: med: use an orbiting camera. add a 3d compass. --- med.c | 105 +++++++++++++++++++++++++++++++++++++++++++++++++++--------------- vis.c | 2 +- 2 files changed, 82 insertions(+), 25 deletions(-) diff --git a/med.c b/med.c index 8ecb72b..e0e83ce 100644 --- a/med.c +++ b/med.c @@ -47,6 +47,14 @@ struct Camcfg int ptype; }; +typedef struct Compass Compass; +struct Compass +{ + Camera *cam; + Scene *scn; +}; +Compass compass; /* 3d compass */ + Rune keys[Ke] = { [K↑] = Kup, [K↓] = Kdown, @@ -77,7 +85,6 @@ Model *model; Shadertab *shader; QLock scenelk; Mouse om; -Quaternion orient = {1,0,0,0}; Camera *cam; Camcfg camcfg = { @@ -87,6 +94,12 @@ Camcfg camcfg = { 40*DEG, 0.01, 10, PERSPECTIVE }; Point3 center = {0,0,0,1}; +RFrame3 ONF3 = { /* default orthonormal rframe */ + 0,0,0,1, + 1,0,0,0, + 0,1,0,0, + 0,0,1,0 +}; LightSource light; /* global point light */ static int doprof; @@ -206,7 +219,7 @@ addcube(void) } static void -addbasis(void) +addbasis(Scene *s) { Entity *e; Model *m; @@ -214,7 +227,7 @@ addbasis(void) m = newmodel(); e = newentity("basis", m); - e->RFrame3 = subject->RFrame3; + e->RFrame3 = ONF3; memset(prims, 0, sizeof prims); prims[0].type = prims[1].type = prims[2].type = PLine; @@ -231,7 +244,24 @@ addbasis(void) m->addprim(m, prims[1]); m->addprim(m, prims[2]); - scene->addent(scene, e); + s->addent(s, e); +} + +static void +setupcompass(Compass *c, Rectangle r, Renderer *rctl) +{ + static int scale = 3; + + r.max.x = r.min.x + Dx(r)/scale; + r.max.y = r.min.y + Dy(r)/scale; + + c->cam = Cam(rectsubpt(r, r.min), rctl, PERSPECTIVE, 30*DEG, 0.1, 10); + c->cam->view->p = Pt2(r.min.x,r.min.y,1); + c->cam->view->setscale(c->cam->view, scale, scale); + + c->scn = newscene(nil); + addbasis(c->scn); + placecamera(c->cam, c->scn, camcfg.p, center, Vec3(0,1,0)); } Point3 @@ -405,7 +435,7 @@ identvshader(VSparams *sp) Color identshader(FSparams *sp) { - Color tc, c; + Color tc; if(sp->su->entity->mdl->tex != nil && sp->v.uv.w != 0) tc = sampletexture(sp->su->entity->mdl->tex, sp->v.uv, tsampler); @@ -414,10 +444,7 @@ identshader(FSparams *sp) else tc = Pt3(1,1,1,1); - c = modulapt3(sp->v.c, tc); - c.a = 1; - - return c; + return modulapt3(sp->v.c, tc); } Shadertab shadertab[] = { @@ -493,6 +520,7 @@ renderproc(void *) qlock(&scenelk); shootcamera(cam, shader); qunlock(&scenelk); + shootcamera(compass.cam, getshader("ident")); if(doprof) fprint(2, "R %llud %llud\nE %llud %llud\nT %llud %llud\nr %llud %llud\n\n", cam->times.R[cam->times.cur-1].t0, cam->times.R[cam->times.cur-1].t1, @@ -503,6 +531,7 @@ renderproc(void *) if(Δt > HZ2MS(60)*1000000ULL){ lockdisplay(display); cam->view->draw(cam->view, screenb); + compass.cam->view->draw(compass.cam->view, screenb); unlockdisplay(display); nbsend(drawc, nil); t0 += Δt; @@ -524,19 +553,28 @@ drawproc(void *) void lmb(void) { + static Quaternion orient = {1,0,0,0}; Quaternion Δorient; - Entity *e; + Point3 p; if((om.buttons^mctl->buttons) == 0){ Δorient = orient; qball(screen->r, om.xy, mctl->xy, &orient, nil); - Δorient = mulq(orient, invq(Δorient)); - - for(e = scene->ents.next; e != &scene->ents; e = e->next){ - e->bx = vcs2world(cam, Vecquat(mulq(mulq(Δorient, Quatvec(0, world2vcs(cam, e->bx))), invq(Δorient)))); - e->by = vcs2world(cam, Vecquat(mulq(mulq(Δorient, Quatvec(0, world2vcs(cam, e->by))), invq(Δorient)))); - e->bz = vcs2world(cam, Vecquat(mulq(mulq(Δorient, Quatvec(0, world2vcs(cam, e->bz))), invq(Δorient)))); - } + Δorient = mulq(Δorient, invq(orient)); + + /* orbit camera around the center */ + p = subpt3(cam->p, center); + p = vcs2world(cam, Vecquat(mulq(mulq(Δorient, Quatvec(0, world2vcs(cam, p))), invq(Δorient)))); + p.w = cam->p.w; + movecamera(cam, p); + aimcamera(cam, center); + + /* same for the compass */ + p = subpt3(compass.cam->p, center); + p = vcs2world(compass.cam, Vecquat(mulq(mulq(Δorient, Quatvec(0, world2vcs(compass.cam, p))), invq(Δorient)))); + p.w = compass.cam->p.w; + movecamera(compass.cam, p); + aimcamera(compass.cam, center); } } @@ -707,18 +745,36 @@ handlekeys(void) movecamera(cam, mulpt3(cam->by, 0.1)); if(kdown & 1<by, -0.1)); - if(kdown & 1<bx, 1*DEG); - if(kdown & 1<p, compass.cam->bx, 1*DEG)); + rotatecamera(compass.cam, compass.cam->bx, 1*DEG); + } + if(kdown & 1<bx, -1*DEG); - if(kdown & 1<p, compass.cam->bx, -1*DEG)); + rotatecamera(compass.cam, compass.cam->bx, -1*DEG); + } + if(kdown & 1<by, 1*DEG); - if(kdown & 1<p, compass.cam->by, 1*DEG)); + rotatecamera(compass.cam, compass.cam->by, 1*DEG); + } + if(kdown & 1<by, -1*DEG); - if(kdown & 1<p, compass.cam->by, -1*DEG)); + rotatecamera(compass.cam, compass.cam->by, -1*DEG); + } + if(kdown & 1<bz, 1*DEG); - if(kdown & 1<p, compass.cam->bz, 1*DEG)); + rotatecamera(compass.cam, compass.cam->bz, 1*DEG); + } + if(kdown & 1<bz, -1*DEG); + movecamera(compass.cam, qrotate(compass.cam->p, compass.cam->bz, -1*DEG)); + rotatecamera(compass.cam, compass.cam->bz, -1*DEG); + } if(kdown & 1<addent(scene, subject); - addbasis(); if(memimageinit() != 0) sysfatal("memimageinit: %r"); @@ -809,6 +864,8 @@ threadmain(int argc, char *argv[]) light.type = LightPoint; tsampler = neartexsampler; + setupcompass(&compass, rectaddpt(Rect(0,0,100,100), subpt(screenb->r.max, Pt(100,100))), rctl); + kctl = emalloc(sizeof *kctl); kctl->c = chancreate(sizeof(Rune), 16); keyc = chancreate(sizeof(void*), 1); diff --git a/vis.c b/vis.c index afc8354..dbd08f1 100644 --- a/vis.c +++ b/vis.c @@ -656,8 +656,8 @@ ul2col(ulong l) void lmb(void) { - Entity *e; Quaternion Δorient; + Entity *e; if((om.buttons^mctl->buttons) == 0){ Δorient = orient; -- cgit v1.2.3