xref: /plan9/sys/src/libgeometry/transform.c (revision 7dd7cddf99dd7472612f1413b4da293630e6b1bc)
1219b2ee8SDavid du Colombier /*
2219b2ee8SDavid du Colombier  * The following routines transform points and planes from one space
3219b2ee8SDavid du Colombier  * to another.  Points and planes are represented by their
4219b2ee8SDavid du Colombier  * homogeneous coordinates, stored in variables of type Point3.
5219b2ee8SDavid du Colombier  */
6219b2ee8SDavid du Colombier #include <u.h>
7219b2ee8SDavid du Colombier #include <libc.h>
8*7dd7cddfSDavid du Colombier #include <draw.h>
9219b2ee8SDavid du Colombier #include <geometry.h>
10219b2ee8SDavid du Colombier /*
11219b2ee8SDavid du Colombier  * Transform point p.
12219b2ee8SDavid du Colombier  */
xformpoint(Point3 p,Space * to,Space * from)13219b2ee8SDavid du Colombier Point3 xformpoint(Point3 p, Space *to, Space *from){
14219b2ee8SDavid du Colombier 	Point3 q, r;
15219b2ee8SDavid du Colombier 	register double *m;
16219b2ee8SDavid du Colombier 	if(from){
17219b2ee8SDavid du Colombier 		m=&from->t[0][0];
18219b2ee8SDavid du Colombier 		q.x=*m++*p.x; q.x+=*m++*p.y; q.x+=*m++*p.z; q.x+=*m++*p.w;
19219b2ee8SDavid du Colombier 		q.y=*m++*p.x; q.y+=*m++*p.y; q.y+=*m++*p.z; q.y+=*m++*p.w;
20219b2ee8SDavid du Colombier 		q.z=*m++*p.x; q.z+=*m++*p.y; q.z+=*m++*p.z; q.z+=*m++*p.w;
21219b2ee8SDavid du Colombier 		q.w=*m++*p.x; q.w+=*m++*p.y; q.w+=*m++*p.z; q.w+=*m  *p.w;
22219b2ee8SDavid du Colombier 	}
23219b2ee8SDavid du Colombier 	else
24219b2ee8SDavid du Colombier 		q=p;
25219b2ee8SDavid du Colombier 	if(to){
26219b2ee8SDavid du Colombier 		m=&to->tinv[0][0];
27219b2ee8SDavid du Colombier 		r.x=*m++*q.x; r.x+=*m++*q.y; r.x+=*m++*q.z; r.x+=*m++*q.w;
28219b2ee8SDavid du Colombier 		r.y=*m++*q.x; r.y+=*m++*q.y; r.y+=*m++*q.z; r.y+=*m++*q.w;
29219b2ee8SDavid du Colombier 		r.z=*m++*q.x; r.z+=*m++*q.y; r.z+=*m++*q.z; r.z+=*m++*q.w;
30219b2ee8SDavid du Colombier 		r.w=*m++*q.x; r.w+=*m++*q.y; r.w+=*m++*q.z; r.w+=*m  *q.w;
31219b2ee8SDavid du Colombier 	}
32219b2ee8SDavid du Colombier 	else
33219b2ee8SDavid du Colombier 		r=q;
34219b2ee8SDavid du Colombier 	return r;
35219b2ee8SDavid du Colombier }
36219b2ee8SDavid du Colombier /*
37219b2ee8SDavid du Colombier  * Transform point p with perspective division.
38219b2ee8SDavid du Colombier  */
xformpointd(Point3 p,Space * to,Space * from)39219b2ee8SDavid du Colombier Point3 xformpointd(Point3 p, Space *to, Space *from){
40219b2ee8SDavid du Colombier 	p=xformpoint(p, to, from);
41219b2ee8SDavid du Colombier 	if(p.w!=0){
42219b2ee8SDavid du Colombier 		p.x/=p.w;
43219b2ee8SDavid du Colombier 		p.y/=p.w;
44219b2ee8SDavid du Colombier 		p.z/=p.w;
45219b2ee8SDavid du Colombier 		p.w=1;
46219b2ee8SDavid du Colombier 	}
47219b2ee8SDavid du Colombier 	return p;
48219b2ee8SDavid du Colombier }
49219b2ee8SDavid du Colombier /*
50219b2ee8SDavid du Colombier  * Transform plane p -- same as xformpoint, except multiply on the
51219b2ee8SDavid du Colombier  * other side by the inverse matrix.
52219b2ee8SDavid du Colombier  */
xformplane(Point3 p,Space * to,Space * from)53219b2ee8SDavid du Colombier Point3 xformplane(Point3 p, Space *to, Space *from){
54219b2ee8SDavid du Colombier 	Point3 q, r;
55219b2ee8SDavid du Colombier 	register double *m;
56219b2ee8SDavid du Colombier 	if(from){
57219b2ee8SDavid du Colombier 		m=&from->tinv[0][0];
58219b2ee8SDavid du Colombier 		q.x =*m++*p.x; q.y =*m++*p.x; q.z =*m++*p.x; q.w =*m++*p.x;
59219b2ee8SDavid du Colombier 		q.x+=*m++*p.y; q.y+=*m++*p.y; q.z+=*m++*p.y; q.w+=*m++*p.y;
60219b2ee8SDavid du Colombier 		q.x+=*m++*p.z; q.y+=*m++*p.z; q.z+=*m++*p.z; q.w+=*m++*p.z;
61219b2ee8SDavid du Colombier 		q.x+=*m++*p.w; q.y+=*m++*p.w; q.z+=*m++*p.w; q.w+=*m  *p.w;
62219b2ee8SDavid du Colombier 	}
63219b2ee8SDavid du Colombier 	else
64219b2ee8SDavid du Colombier 		q=p;
65219b2ee8SDavid du Colombier 	if(to){
66219b2ee8SDavid du Colombier 		m=&to->t[0][0];
67219b2ee8SDavid du Colombier 		r.x =*m++*q.x; r.y =*m++*q.x; r.z =*m++*q.x; r.w =*m++*q.x;
68219b2ee8SDavid du Colombier 		r.x+=*m++*q.y; r.y+=*m++*q.y; r.z+=*m++*q.y; r.w+=*m++*q.y;
69219b2ee8SDavid du Colombier 		r.x+=*m++*q.z; r.y+=*m++*q.z; r.z+=*m++*q.z; r.w+=*m++*q.z;
70219b2ee8SDavid du Colombier 		r.x+=*m++*q.w; r.y+=*m++*q.w; r.z+=*m++*q.w; r.w+=*m  *q.w;
71219b2ee8SDavid du Colombier 	}
72219b2ee8SDavid du Colombier 	else
73219b2ee8SDavid du Colombier 		r=q;
74219b2ee8SDavid du Colombier 	return r;
75219b2ee8SDavid du Colombier }
76