shithub: riscv

Download patch

ref: f57c46456b04992bd06a71425d8074e38a32c230
parent: ea1d75e67581f9a65abddbe2f03af70ea8eb1e1a
author: rodri <rgl@antares-labs.eu>
date: Tue Jun 20 05:47:04 EDT 2023

libgeometry: fix rframe xforms

the manual was also modified to better explain how they work.

--- a/sys/man/2/geometry
+++ b/sys/man/2/geometry
@@ -565,16 +565,22 @@
 .IR n -dimensional
 space is made out of n+1 points, one being the origin
 .IR p ,
-relative to some other frame of reference, and the remaining being the
+and the remaining being the
 basis vectors
 .I b1,⋯,bn
 that define the metric within that frame.
 .PP
-Every one of these routines assumes the origin reference frame
-.B O
-has an orthonormal basis when performing an inverse transformation;
-it's up to the user to apply a forward transformation to the resulting
-point with the proper reference frame if that's not the case.
+The origin point and the bases are all defined in terms of an origin
+frame of reference O. Applying a forward transformation
+.RI ( rframexform
+and
+.IR rframexform3 )
+to a point relative to O will result in a point relative to the new frame.
+Applying an inverse transformation
+.RI ( invrframexform
+and
+.IR invrframexform3 )
+to that same point—now defined in terms of the new frame—will bring it back to O.
 .TP
 Name
 Description
@@ -582,34 +588,32 @@
 .B rframexform(\fIp\fP,\fIrf\fP)
 Transforms the point
 .IR p ,
-relative to origin O, into the frame of reference
-.I rf
-with origin in
-.BR rf.p ,
-which is itself also relative to O. It then returns the new 2D point.
+relative to some origin frame of reference O, into the frame of reference
+.IR rf .
+It then returns the new 2D point.
 .TP
 .B rframexform3(\fIp\fP,\fIrf\fP)
 Transforms the point
 .IR p ,
-relative to origin O, into the frame of reference
-.I rf
-with origin in
-.BR rf.p ,
-which is itself also relative to O. It then returns the new 3D point.
+relative to some origin frame of reference O, into the frame of reference
+.IR rf .
+It then returns the new 3D point.
 .TP
 .B invrframexform(\fIp\fP,\fIrf\fP)
 Transforms the point
 .IR p ,
 relative to
-.BR rf.p ,
-into the frame of reference O, assumed to have an orthonormal basis.
+.IR rf ,
+into a point relative to the origin frame of reference O.
+It then returns the new 2D point.
 .TP
 .B invrframexform3(\fIp\fP,\fIrf\fP)
 Transforms the point
 .IR p ,
 relative to
-.BR rf.p ,
-into the frame of reference O, assumed to have an orthonormal basis.
+.IR rf ,
+into a point relative to the origin frame of reference O.
+It then returns the new 3D point.
 .SS Triangles
 .TP
 Name
@@ -650,27 +654,29 @@
 #include <draw.h>
 #include <geometry.h>
 
-RFrame screenrf;
+RFrame worldrf;
 
-Point
-toscreen(Point2 p)
+/* from screen... */
+Point2
+toworld(Point p)
 {
-	p = invrframexform(p, screenrf);
-	return Pt(p.x,p.y);
+	return rframexform(p, worldrf);
 }
 
-Point2
-fromscreen(Point p)
+/* ...to screen */
+Point
+fromworld(Point2 p)
 {
-	return rframexform(Pt2(p.x,p.y,1), screenrf);
+	p = invrframexform(Pt2(p.x,p.y,1), worldrf);
+	return Pt(p.x,p.y);
 }
 
 void
 main(void)
-	screenrf.p = Pt2(screen->r.min.x+Dx(screen->r)/2,screen->r.max.y-Dy(screen->r)/2,1);
-	screenrf.bx = Vec2(1, 0);
-	screenrf.by = Vec2(0,-1);
+	worldrf.p = Pt2(screen->r.min.x+Dx(screen->r)/2,screen->r.max.y-Dy(screen->r)/2,1);
+	worldrf.bx = Vec2(1, 0);
+	worldrf.by = Vec2(0,-1);
 .EE
 .PP
@@ -721,7 +727,7 @@
 	mulm(T, R); /* rotate, then translate */
 	p = ship->mdl.pts;
 	for(i = 0; i < nelem(pts)-1; i++)
-		pts[i] = toscreen(xform(p[i], T));
+		pts[i] = fromworld(xform(p[i], T));
 	pts[i] = pts[0];
 	draw(screen, screen->r, display->white, nil, ZP);
 	poly(screen, pts, nelem(pts), 0, 0, 0, display->black, ZP);
@@ -764,7 +770,7 @@
 redraw(void)
-		pts[i] = toscreen(invrframexform(p[i], *ship));
+		pts[i] = fromworld(invrframexform(p[i], *ship));
 main(void)
--- a/sys/src/libgeometry/rframe.c
+++ b/sys/src/libgeometry/rframe.c
@@ -2,15 +2,72 @@
 #include <libc.h>
 #include <geometry.h>
 
+/*
+ * implicit identity origin rframes
+ *
+ * 	static RFrame IRF2 = {
+ * 		.p  = {0,0,1},
+ * 		.bx = {1,0,0},
+ * 		.by = {0,1,0},
+ * 	};
+ * 	
+ * 	static RFrame3 IRF3 = {
+ * 		.p  = {0,0,0,1},
+ * 		.bx = {1,0,0,0},
+ * 		.by = {0,1,0,0},
+ * 		.bz = {0,0,1,0},
+ * 	};
+ *
+ * these rframes are used on every xform to keep the points in the
+ * correct plane (i.e. with proper w values); they are written here as a
+ * reference for future changes. the bases are ignored since they turn
+ * into an unnecessary identity xform.
+ *
+ * the implicitness comes from the fact that using the _irf* filters
+ * makes the rframexform equivalent to:
+ * 	rframexform(invrframexform(p, IRF), rf);
+ * and the invrframexform to:
+ * 	rframexform(invrframexform(p, rf), IRF);
+ */
+
+static Point2
+_irfxform(Point2 p)
+{
+	p.w--;
+	return p;
+}
+
+static Point2
+_irfxform⁻¹(Point2 p)
+{
+	p.w++;
+	return p;
+}
+
+static Point3
+_irfxform3(Point3 p)
+{
+	p.w--;
+	return p;
+}
+
+static Point3
+_irfxform3⁻¹(Point3 p)
+{
+	p.w++;
+	return p;
+}
+
 Point2
 rframexform(Point2 p, RFrame rf)
 {
 	Matrix m = {
-		rf.bx.x, rf.bx.y, -dotvec2(rf.bx, rf.p),
-		rf.by.x, rf.by.y, -dotvec2(rf.by, rf.p),
+		rf.bx.x, rf.by.x, 0,
+		rf.bx.y, rf.by.y, 0,
 		0, 0, 1,
 	};
-	return xform(p, m);
+	invm(m);
+	return xform(subpt2(_irfxform⁻¹(p), rf.p), m);
 }
 
 Point3
@@ -17,12 +74,13 @@
 rframexform3(Point3 p, RFrame3 rf)
 {
 	Matrix3 m = {
-		rf.bx.x, rf.bx.y, rf.bx.z, -dotvec3(rf.bx, rf.p),
-		rf.by.x, rf.by.y, rf.by.z, -dotvec3(rf.by, rf.p),
-		rf.bz.x, rf.bz.y, rf.bz.z, -dotvec3(rf.bz, rf.p),
+		rf.bx.x, rf.by.x, rf.bz.x, 0,
+		rf.bx.y, rf.by.y, rf.bz.y, 0,
+		rf.bx.z, rf.by.z, rf.bz.z, 0,
 		0, 0, 0, 1,
 	};
-	return xform3(p, m);
+	invm3(m);
+	return xform3(subpt3(_irfxform3⁻¹(p), rf.p), m);
 }
 
 Point2
@@ -29,12 +87,11 @@
 invrframexform(Point2 p, RFrame rf)
 {
 	Matrix m = {
-		rf.bx.x, rf.bx.y, -dotvec2(rf.bx, rf.p),
-		rf.by.x, rf.by.y, -dotvec2(rf.by, rf.p),
+		rf.bx.x, rf.by.x, 0,
+		rf.bx.y, rf.by.y, 0,
 		0, 0, 1,
 	};
-	invm(m);
-	return xform(p, m);
+	return _irfxform(addpt2(xform(p, m), rf.p));
 }
 
 Point3
@@ -41,11 +98,10 @@
 invrframexform3(Point3 p, RFrame3 rf)
 {
 	Matrix3 m = {
-		rf.bx.x, rf.bx.y, rf.bx.z, -dotvec3(rf.bx, rf.p),
-		rf.by.x, rf.by.y, rf.by.z, -dotvec3(rf.by, rf.p),
-		rf.bz.x, rf.bz.y, rf.bz.z, -dotvec3(rf.bz, rf.p),
+		rf.bx.x, rf.by.x, rf.bz.x, 0,
+		rf.bx.y, rf.by.y, rf.bz.y, 0,
+		rf.bx.z, rf.by.z, rf.bz.z, 0,
 		0, 0, 0, 1,
 	};
-	invm3(m);
-	return xform3(p, m);
+	return _irfxform3(addpt3(xform3(p, m), rf.p));
 }