shithub: 3dee

Download patch

ref: c46b7a3e97390bbe8803afbb70b307362f9123f0
parent: 702e1d92ff4e270f5be88d1b5b190c4de758a101
author: rodri <rgl@antares-labs.eu>
date: Wed May 15 10:44:58 EDT 2024

fix the qball.

--- a/dat.h
+++ b/dat.h
@@ -28,5 +28,6 @@
 	Scambx, Scamby, Scambz,
 	Sfps,
 	Sframes,
+	Sorient,
 	Se
 };
--- a/fns.h
+++ b/fns.h
@@ -2,4 +2,4 @@
 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*);
--- a/mkfile
+++ b/mkfile
@@ -7,7 +7,7 @@
 
 OFILES=\
 	alloc.$O\
-	qb.$O\
+	qball.$O\
 
 HFILES=dat.h fns.h
 
--- a/qb.c
+++ /dev/null
@@ -1,86 +1,0 @@
-/*
- * Ken Shoemake's Quaternion rotation controller
- * “Arcball Rotation Control”, Graphics Gems IV § III.1, pp. 175-192, August 1994.
- */
-#include <u.h>
-#include <libc.h>
-#include <bio.h>
-#include <thread.h>
-#include <draw.h>
-#include <memdraw.h>
-#include <mouse.h>
-#include <keyboard.h>
-#include <geometry.h>
-#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)));
-}
--- /dev/null
+++ b/qball.c
@@ -1,0 +1,80 @@
+/*
+ * Ken Shoemake's Quaternion rotation controller
+ * “Arcball Rotation Control”, Graphics Gems IV § III.1, pp. 175-192, August 1994.
+ */
+#include <u.h>
+#include <libc.h>
+#include <bio.h>
+#include <thread.h>
+#include <draw.h>
+#include <memdraw.h>
+#include <mouse.h>
+#include <keyboard.h>
+#include <geometry.h>
+#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);
+}
--- a/vis.c
+++ b/vis.c
@@ -50,6 +50,7 @@
 Model *model;
 Entity *subject;
 Scene *scene;
+Mouse om;
 Quaternion orient = {1,0,0,0};
 
 Camera cams[4], *maincam;
@@ -452,6 +453,7 @@
 	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 @@
 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 @@
 		zoomin();
 	if((mctl->buttons & 16) != 0)
 		zoomout();
+	om = mctl->Mouse;
 }
 
 void