Warning: Attempt to read property "date" on null in /usr/local/www/websvn.planix.org/blame.php on line 247

Warning: Attempt to read property "msg" on null in /usr/local/www/websvn.planix.org/blame.php on line 247
WebSVN – planix.SVN – Blame – /os/branches/feature_fixcpp/sys/src/libgeometry/qball.c – Rev 2

Subversion Repositories planix.SVN

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 1
/*
2
 * Ken Shoemake's Quaternion rotation controller
3
 */
4
#include <u.h>
5
#include <libc.h>
6
#include <draw.h>
7
#include <event.h>
8
#include <geometry.h>
9
#define	BORDER	4
10
static Point ctlcen;		/* center of qball */
11
static int ctlrad;		/* radius of qball */
12
static Quaternion *axis;	/* constraint plane orientation, 0 if none */
13
/*
14
 * Convert a mouse point into a unit quaternion, flattening if
15
 * constrained to a particular plane.
16
 */
17
static Quaternion mouseq(Point p){
18
	double qx=(double)(p.x-ctlcen.x)/ctlrad;
19
	double qy=(double)(p.y-ctlcen.y)/ctlrad;
20
	double rsq=qx*qx+qy*qy;
21
	double l;
22
	Quaternion q;
23
	if(rsq>1){
24
		rsq=sqrt(rsq);
25
		q.r=0.;
26
		q.i=qx/rsq;
27
		q.j=qy/rsq;
28
		q.k=0.;
29
	}
30
	else{
31
		q.r=0.;
32
		q.i=qx;
33
		q.j=qy;
34
		q.k=sqrt(1.-rsq);
35
	}
36
	if(axis){
37
		l=q.i*axis->i+q.j*axis->j+q.k*axis->k;
38
		q.i-=l*axis->i;
39
		q.j-=l*axis->j;
40
		q.k-=l*axis->k;
41
		l=sqrt(q.i*q.i+q.j*q.j+q.k*q.k);
42
		if(l!=0.){
43
			q.i/=l;
44
			q.j/=l;
45
			q.k/=l;
46
		}
47
	}
48
	return q;
49
}
50
void qball(Rectangle r, Mouse *m, Quaternion *result, void (*redraw)(void), Quaternion *ap){
51
	Quaternion q, down;
52
	Point rad;
53
	axis=ap;
54
	ctlcen=divpt(addpt(r.min, r.max), 2);
55
	rad=divpt(subpt(r.max, r.min), 2);
56
	ctlrad=(rad.x<rad.y?rad.x:rad.y)-BORDER;
57
	down=qinv(mouseq(m->xy));
58
	q=*result;
59
	for(;;){
60
		*m=emouse();
61
		if(!m->buttons) break;
62
		*result=qmul(q, qmul(down, mouseq(m->xy)));
63
		(*redraw)();
64
	}
65
}