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));
}