From c46b7a3e97390bbe8803afbb70b307362f9123f0 Mon Sep 17 00:00:00 2001 From: rodri Date: Wed, 15 May 2024 14:44:58 +0000 Subject: fix the qball. --- dat.h | 1 + fns.h | 2 +- mkfile | 2 +- qb.c | 86 ----------------------------------------------------------------- qball.c | 80 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ vis.c | 9 +++---- 6 files changed, 87 insertions(+), 93 deletions(-) delete mode 100644 qb.c create mode 100644 qball.c diff --git a/dat.h b/dat.h index 5c9b45b..bad9c4d 100644 --- a/dat.h +++ b/dat.h @@ -28,5 +28,6 @@ enum { Scambx, Scamby, Scambz, Sfps, Sframes, + Sorient, Se }; diff --git a/fns.h b/fns.h index d89bef9..a506140 100644 --- a/fns.h +++ b/fns.h @@ -2,4 +2,4 @@ void *emalloc(ulong); void *erealloc(void*, ulong); Image *eallocimage(Display*, Rectangle, ulong, int, ulong); Memimage *eallocmemimage(Rectangle, ulong); -void qb(Rectangle, Point, Point, Quaternion*, Quaternion*); +void qball(Rectangle, Point, Point, Quaternion*, Quaternion*); diff --git a/mkfile b/mkfile index 2c9c8d7..2761b48 100644 --- a/mkfile +++ b/mkfile @@ -7,7 +7,7 @@ TARG=\ OFILES=\ alloc.$O\ - qb.$O\ + qball.$O\ HFILES=dat.h fns.h diff --git a/qb.c b/qb.c deleted file mode 100644 index 1485b9a..0000000 --- a/qb.c +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Ken Shoemake's Quaternion rotation controller - * “Arcball Rotation Control”, Graphics Gems IV § III.1, pp. 175-192, August 1994. - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "libobj/obj.h" -#include "libgraphics/graphics.h" -#include "fns.h" - -static int -min(int a, int b) -{ - return a < b? a: b; -} - -/* - * Convert a mouse point into a unit quaternion, flattening if - * constrained to a particular plane. - */ -static Quaternion -mouseq(Point2 p, Quaternion *axis) -{ - double l; - Quaternion q; - double rsq = p.x*p.x + p.y*p.y; /* quadrance */ - - if(rsq > 1){ /* outside the sphere */ - rsq = sqrt(rsq); - q.r = 0; - q.i = p.x/rsq; - q.j = p.y/rsq; - q.k = 0; - }else{ /* within the sphere */ - q.r = 0; - q.i = p.x; - q.j = p.y; - q.k = sqrt(1 - rsq); - } - - if(axis != nil){ - l = dotq(q, *axis); - q.i -= l*axis->i; - q.j -= l*axis->j; - q.k -= l*axis->k; - l = qlen(q); - if(l != 0){ - q.i /= l; - q.j /= l; - q.k /= l; - } - } - - return q; -} - -void -qb(Rectangle r, Point p0, Point p1, Quaternion *orient, Quaternion *axis) -{ - Quaternion q, down; - Point2 rmin, rmax; - Point2 s0, s1; /* screen coords */ - Point2 v0, v1; /* unit sphere coords */ - Point2 ctlcen; /* controller center */ - double ctlrad; /* controller radius */ - - rmin = Vec2(r.min.x, r.min.y); - rmax = Vec2(r.max.x, r.max.y); - s0 = Vec2(p0.x, p0.y); - s1 = Vec2(p1.x, p1.y); - ctlcen = divpt2(addpt2(rmin, rmax), 2); - ctlrad = min(Dx(r), Dy(r)); - v0 = divpt2(subpt2(s0, ctlcen), ctlrad); - down = invq(mouseq(v0, axis)); - - q = *orient; - v1 = divpt2(subpt2(s1, ctlcen), ctlrad); - *orient = mulq(q, mulq(down, mouseq(v1, axis))); -} diff --git a/qball.c b/qball.c new file mode 100644 index 0000000..9248f5f --- /dev/null +++ b/qball.c @@ -0,0 +1,80 @@ +/* + * Ken Shoemake's Quaternion rotation controller + * “Arcball Rotation Control”, Graphics Gems IV § III.1, pp. 175-192, August 1994. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "libobj/obj.h" +#include "libgraphics/graphics.h" +#include "fns.h" + +#define MIN(a, b) ((a)<(b)?(a):(b)) + +/* + * Convert a mouse point into a unit quaternion, flattening if + * constrained to a particular plane. + */ +static Quaternion +mouseq(Point2 p, Quaternion *axis) +{ + double l; + Quaternion q; + double rsq = p.x*p.x + p.y*p.y; /* quadrance */ + + q.r = 0; + if(rsq > 1){ /* outside the sphere */ + rsq = 1/sqrt(rsq); + q.i = p.x*rsq; + q.j = p.y*rsq; + q.k = 0; + }else{ + q.i = p.x; + q.j = p.y; + q.k = sqrt(1 - rsq); + } + + if(axis != nil){ + l = dotq(q, *axis); + q.i -= l*axis->i; + q.j -= l*axis->j; + q.k -= l*axis->k; + l = qlen(q); + if(l != 0){ + q.i /= l; + q.j /= l; + q.k /= l; + } + } + + return q; +} + +void +qball(Rectangle r, Point p0, Point p1, Quaternion *orient, Quaternion *axis) +{ + Quaternion qdown, qdrag; + Point2 rmin, rmax; + Point2 v0, v1; /* unit sphere coords */ + Point2 ctlcen; /* controller center */ + double ctlrad; /* controller radius */ + + if(orient == nil) + return; + + rmin = Vec2(r.min.x, r.min.y); + rmax = Vec2(r.max.x, r.max.y); + ctlcen = divpt2(addpt2(rmin, rmax), 2); + ctlrad = MIN(Dx(r)/2, Dy(r)/2); + v0 = divpt2(Vec2(p0.x-ctlcen.x, ctlcen.y-p0.y), ctlrad); + v1 = divpt2(Vec2(p1.x-ctlcen.x, ctlcen.y-p1.y), ctlrad); + qdown = mouseq(v0, axis); + qdrag = mulq(mouseq(v1, axis), qdown); + *orient = mulq(qdrag, *orient); +} diff --git a/vis.c b/vis.c index 96879eb..5796b32 100644 --- a/vis.c +++ b/vis.c @@ -50,6 +50,7 @@ Shadertab *shader; Model *model; Entity *subject; Scene *scene; +Mouse om; Quaternion orient = {1,0,0,0}; Camera cams[4], *maincam; @@ -452,6 +453,7 @@ drawstats(void) snprint(stats[Scambz], sizeof(stats[Scambz]), "bz %V", maincam->bz); snprint(stats[Sfps], sizeof(stats[Sfps]), "FPS %.0f/%.0f/%.0f/%.0f", !maincam->stats.max? 0: 1e9/maincam->stats.max, !maincam->stats.avg? 0: 1e9/maincam->stats.avg, !maincam->stats.min? 0: 1e9/maincam->stats.min, !maincam->stats.v? 0: 1e9/maincam->stats.v); snprint(stats[Sframes], sizeof(stats[Sframes]), "frame %llud", maincam->stats.nframes); + snprint(stats[Sorient], sizeof(stats[Sorient]), "ℍ %V", (Point3)orient); for(i = 0; i < Se; i++) stringbg(screen, addpt(screen->r.min, Pt(10,10 + i*font->height)), display->black, ZP, font, stats[i], display->white, ZP); } @@ -518,12 +520,8 @@ drawproc(void *) void lmb(void) { - static Mouse om; - if((om.buttons^mctl->buttons) == 0) - qb(screen->r, om.xy, mctl->xy, &orient, nil); - - om = mctl->Mouse; + qball(screen->r, om.xy, mctl->xy, &orient, nil); } void @@ -602,6 +600,7 @@ mouse(void) zoomin(); if((mctl->buttons & 16) != 0) zoomout(); + om = mctl->Mouse; } void -- cgit v1.2.3