xref: /plan9/sys/src/libgeometry/transform.c (revision 219b2ee8daee37f4aad58d63f21287faa8e4ffdc)
1*219b2ee8SDavid du Colombier /*
2*219b2ee8SDavid du Colombier  * The following routines transform points and planes from one space
3*219b2ee8SDavid du Colombier  * to another.  Points and planes are represented by their
4*219b2ee8SDavid du Colombier  * homogeneous coordinates, stored in variables of type Point3.
5*219b2ee8SDavid du Colombier  */
6*219b2ee8SDavid du Colombier #include <u.h>
7*219b2ee8SDavid du Colombier #include <libc.h>
8*219b2ee8SDavid du Colombier #include <libg.h>
9*219b2ee8SDavid du Colombier #include <geometry.h>
10*219b2ee8SDavid du Colombier /*
11*219b2ee8SDavid du Colombier  * Transform point p.
12*219b2ee8SDavid du Colombier  */
13*219b2ee8SDavid du Colombier Point3 xformpoint(Point3 p, Space *to, Space *from){
14*219b2ee8SDavid du Colombier 	Point3 q, r;
15*219b2ee8SDavid du Colombier 	register double *m;
16*219b2ee8SDavid du Colombier 	if(from){
17*219b2ee8SDavid du Colombier 		m=&from->t[0][0];
18*219b2ee8SDavid du Colombier 		q.x=*m++*p.x; q.x+=*m++*p.y; q.x+=*m++*p.z; q.x+=*m++*p.w;
19*219b2ee8SDavid du Colombier 		q.y=*m++*p.x; q.y+=*m++*p.y; q.y+=*m++*p.z; q.y+=*m++*p.w;
20*219b2ee8SDavid du Colombier 		q.z=*m++*p.x; q.z+=*m++*p.y; q.z+=*m++*p.z; q.z+=*m++*p.w;
21*219b2ee8SDavid du Colombier 		q.w=*m++*p.x; q.w+=*m++*p.y; q.w+=*m++*p.z; q.w+=*m  *p.w;
22*219b2ee8SDavid du Colombier 	}
23*219b2ee8SDavid du Colombier 	else
24*219b2ee8SDavid du Colombier 		q=p;
25*219b2ee8SDavid du Colombier 	if(to){
26*219b2ee8SDavid du Colombier 		m=&to->tinv[0][0];
27*219b2ee8SDavid du Colombier 		r.x=*m++*q.x; r.x+=*m++*q.y; r.x+=*m++*q.z; r.x+=*m++*q.w;
28*219b2ee8SDavid du Colombier 		r.y=*m++*q.x; r.y+=*m++*q.y; r.y+=*m++*q.z; r.y+=*m++*q.w;
29*219b2ee8SDavid du Colombier 		r.z=*m++*q.x; r.z+=*m++*q.y; r.z+=*m++*q.z; r.z+=*m++*q.w;
30*219b2ee8SDavid du Colombier 		r.w=*m++*q.x; r.w+=*m++*q.y; r.w+=*m++*q.z; r.w+=*m  *q.w;
31*219b2ee8SDavid du Colombier 	}
32*219b2ee8SDavid du Colombier 	else
33*219b2ee8SDavid du Colombier 		r=q;
34*219b2ee8SDavid du Colombier 	return r;
35*219b2ee8SDavid du Colombier }
36*219b2ee8SDavid du Colombier /*
37*219b2ee8SDavid du Colombier  * Transform point p with perspective division.
38*219b2ee8SDavid du Colombier  */
39*219b2ee8SDavid du Colombier Point3 xformpointd(Point3 p, Space *to, Space *from){
40*219b2ee8SDavid du Colombier 	p=xformpoint(p, to, from);
41*219b2ee8SDavid du Colombier 	if(p.w!=0){
42*219b2ee8SDavid du Colombier 		p.x/=p.w;
43*219b2ee8SDavid du Colombier 		p.y/=p.w;
44*219b2ee8SDavid du Colombier 		p.z/=p.w;
45*219b2ee8SDavid du Colombier 		p.w=1;
46*219b2ee8SDavid du Colombier 	}
47*219b2ee8SDavid du Colombier 	return p;
48*219b2ee8SDavid du Colombier }
49*219b2ee8SDavid du Colombier /*
50*219b2ee8SDavid du Colombier  * Transform plane p -- same as xformpoint, except multiply on the
51*219b2ee8SDavid du Colombier  * other side by the inverse matrix.
52*219b2ee8SDavid du Colombier  */
53*219b2ee8SDavid du Colombier Point3 xformplane(Point3 p, Space *to, Space *from){
54*219b2ee8SDavid du Colombier 	Point3 q, r;
55*219b2ee8SDavid du Colombier 	register double *m;
56*219b2ee8SDavid du Colombier 	if(from){
57*219b2ee8SDavid du Colombier 		m=&from->tinv[0][0];
58*219b2ee8SDavid du Colombier 		q.x =*m++*p.x; q.y =*m++*p.x; q.z =*m++*p.x; q.w =*m++*p.x;
59*219b2ee8SDavid du Colombier 		q.x+=*m++*p.y; q.y+=*m++*p.y; q.z+=*m++*p.y; q.w+=*m++*p.y;
60*219b2ee8SDavid du Colombier 		q.x+=*m++*p.z; q.y+=*m++*p.z; q.z+=*m++*p.z; q.w+=*m++*p.z;
61*219b2ee8SDavid du Colombier 		q.x+=*m++*p.w; q.y+=*m++*p.w; q.z+=*m++*p.w; q.w+=*m  *p.w;
62*219b2ee8SDavid du Colombier 	}
63*219b2ee8SDavid du Colombier 	else
64*219b2ee8SDavid du Colombier 		q=p;
65*219b2ee8SDavid du Colombier 	if(to){
66*219b2ee8SDavid du Colombier 		m=&to->t[0][0];
67*219b2ee8SDavid du Colombier 		r.x =*m++*q.x; r.y =*m++*q.x; r.z =*m++*q.x; r.w =*m++*q.x;
68*219b2ee8SDavid du Colombier 		r.x+=*m++*q.y; r.y+=*m++*q.y; r.z+=*m++*q.y; r.w+=*m++*q.y;
69*219b2ee8SDavid du Colombier 		r.x+=*m++*q.z; r.y+=*m++*q.z; r.z+=*m++*q.z; r.w+=*m++*q.z;
70*219b2ee8SDavid du Colombier 		r.x+=*m++*q.w; r.y+=*m++*q.w; r.z+=*m++*q.w; r.w+=*m  *q.w;
71*219b2ee8SDavid du Colombier 	}
72*219b2ee8SDavid du Colombier 	else
73*219b2ee8SDavid du Colombier 		r=q;
74*219b2ee8SDavid du Colombier 	return r;
75*219b2ee8SDavid du Colombier }
76