commit 0f91019ec56fe855be84fdd8905550fee74d4cde
parent 200b8e120f87b0e8c110d15078bc145ea3f2bc3e
Author: glenda <glenda@device>
Date: Sun, 6 Nov 2022 21:58:16 +0000
cubes: render ⅙-th of a cube
Diffstat:
M | src/cubes/cubes.c | | | 258 | +++++++++++++++++++++++++++---------------------------------------------------- |
1 file changed, 88 insertions(+), 170 deletions(-)
diff --git a/src/cubes/cubes.c b/src/cubes/cubes.c
@@ -4,139 +4,113 @@
#include <event.h>
#include <geometry.h>
-#define OTSize (64 * 64 * 64)
+/*
+ * given 640 resolution and 80 digrees FoV,
+ * single pixel will be 0.125 digrees wide.
+ * 360/.125 = 2880 - amount of pixels needed
+ * for full circle.
+ * Small enough amount to precompute all possible
+ * angles for every possible direction
+ */
-#define QTSize (64 * 64)
+#define OTSize (64 * 64 * 64)
#define CSWidth 640
#define CSHeight 640
#define CSSize (CSWidth * CSHeight)
-typedef struct Cube Cube;
-typedef struct Vect Vect;
-struct Cube {
- Point3 min; Point3 max;
-};
-
-struct Vect {
- Point3 pos; Point3 dir;
-};
-
-typedef union Quad Quad;
-
-union Quad {
- s32int p[4];
- struct {
- s32int tl;
- s32int tr;
- s32int bl;
- s32int br;
- };
-};
-
u32int otree[OTSize];
u32int imgbuf[CSSize];
-Quad qtree[QTSize];
+Image *img;
+vlong n;
+char *s;
-Cube cube;
-Vect view;
+typedef struct Raydef Raydef;
+struct Raydef {
+ double O[3];
+ double D[3];
+};
-void
-qtinit(void)
-{
- s32int data[] = {
- 0x00000001, 0x00000000, 0x00000000, 0x00000002,
- 0x00000000, 0x00000002, 0x00000000, 0x00000002,
- 0xffff0000, 0xff00ff00, 0xff0000ff, 0xff00ffff,
- };
- memcpy(qtree, data, sizeof(data));
-}
+typedef struct Boxdef Boxdef;
+struct Boxdef {
+ double min[3];
+ double max[3];
+};
-s32int
-getqt(double X, double Y)
-{
- unsigned int i = 0;
- for (; i < sizeof(qtree);) {
- Quad q = qtree[i];
- s32int r = q.p[(X > 0) | ((Y > 0) << 1)];
- if (r <= 0) return r;
- double DX, DY;
- DX = (X > 0) ? -1 : 1;
- DY = (Y > 0) ? -1 : 1;
-
- X = X * 2 + DX;
- Y = Y * 2 + DY;
- i = r;
- }
- return 0;
-}
+Boxdef box = {{0,0,0}, {1,1,1}};
+Raydef view = {{10,20,30}, {-1,-2,-3}};
-void
-otinit(void)
+Raydef
+raynorm(Raydef r)
{
- int i, x,y,z;
- double X,Y,Z;
- for (i = 0; i < OTSize; i++) {
- x = i % 64;
- y = (i / 64) % 64;
- z = i / 64 / 64;
- X = -1 + (double)x / 32;
- Y = -1 + (double)y / 32;
- Z = -1 + (double)z / 32;
-
- if ((X*X + Y*Y + Z*Z) < 1) {
- otree[i] = 0xffff0000;
- } else {
- otree[i] = 0x00000000;
- }
+ double d = r.D[0] * r.D[0] + r.D[1] * r.D[1] + r.D[2] * r.D[2];
+ if (d != 0) {
+ r.D[0] /= d;
+ r.D[1] /= d;
+ r.D[2] /= d;
}
+ return r;
}
-void
-initscene(void)
-{
- otinit();
- qtinit();
- cube = (Cube){
- (Point3){-1, -1, -1, 1},
- (Point3){ 1, 1, 1, 1},
- };
- view = (Vect){
- (Point3){10, 20, 30, 1},
- (Point3){0, 0, 0, 1},
- };
-}
-
-int m[3][3];
-Point pts[3];
-Image *img;
-vlong n;
-char *s;
-
-void
-triangle(int i)
+/*
+ * Ray is O + Dt, where O is origin and D is direction
+ * Box is defined by 2 boundary points, M, N (min and max)
+ * which translates into 6 planes:
+ * x = Nx; x = Mx; y = Ny; y = My; z = Nz; z = Mz
+ * Intersections of ray and planes:
+ * Tn = (Bn - On)/Dn; where B (as in boundary) is either M or N,
+ * and n stands for axis (x,y,z)
+ * (beware division by zero!)
+ *
+ */
+
+Raydef
+intersectY(Raydef ray, double Y)
{
- int X = i % CSWidth;
- int Y = i / CSWidth;
-
- #define l(m) (m[0] * X + m[1] * Y + m[2])
- #define istriag ((l(m[0]) > 0) && (l(m[1]) > 0) && (l(m[2]) > 0))
- #define isline ((l(m[0]) <= 10) || (l(m[1]) <= 10) || (l(m[2]) <= 10))
-
- imgbuf[i] = istriag ? 0x00ff7f00 : (imgbuf[i] / 2) &0xffff0000;
-
-
- #undef l
- #undef istriag
- #undef isline
+ Raydef ref;
+ double t;
+ if (ray.D[1] >= Y) {
+ Raydef ret = {
+ {Inf(ray.D[0]), Inf(ray.D[1]), Inf(ray.D[2])},
+ {ray.D[0], ray.D[1], ray.D[2]},
+ };
+ return ret;
+ }
+ t = (Y-ray.O[1]) / ray.D[1];
+ ref.O[0] = ray.O[0] + ray.D[0] * t;
+ ref.O[1] = Y;
+ ref.O[2] = ray.O[2] + ray.D[2] * t;
+ ref.D[0] = ray.D[0];
+ ref.D[1] = -ray.D[1];
+ ref.D[2] = ray.D[2];
+ return ref;
}
void
vrender(void)
{
- int i;
- for (i = 0; i < CSSize; i++) triangle(i);
+ int i, x, y;
+ double X, Y;
+ for (i = 0, y = 0; y < CSHeight; y++) {
+ Y = (double)(y) / CSHeight;
+ for (x = 0; x < CSWidth; x++, i++) {
+ X = (double)(x) / CSWidth;
+ // TODO: generate camera ray properly
+ Raydef r = {
+ .O {0, 0, 0},
+ .D {-1 + X * 2, 1 - Y * 2, 2}
+ };
+ r = intersectY(r, 0);
+
+ if (isInf(r.O[0], 0) != 0) imgbuf[i] = 0x004f7fff;
+ else {
+ double d = sqrt((r.D[1] * r.D[1]) / (r.D[0] * r.D[0] + r.D[2] * r.D[2]));
+ int br = 0xff * d;
+ imgbuf[i] = (br << 16) + (br << 8) + (br);
+ }
+ }
+ }
}
void
@@ -145,12 +119,6 @@ redraw(Image *)
draw(screen, screen->r, display->white, nil, ZP);
draw(screen, screen->r, img, nil, ZP);
- //Point dp = screen->r.min;
-
- //line(screen, addpt(dp, pts[0]), addpt(dp, pts[1]), 0, 0, 0, display->white, ZP);
- //line(screen, addpt(dp, pts[1]), addpt(dp, pts[2]), 0, 0, 0, display->white, ZP);
- //line(screen, addpt(dp, pts[2]), addpt(dp, pts[0]), 0, 0, 0, display->white, ZP);
-
string(screen, screen->r.min, display->white, ZP, font, s);
}
@@ -163,78 +131,28 @@ eresized(int new)
}
void
-randomize_pts(void)
-{
- pts[0] = Pt(nrand(640), nrand(640));
- pts[1] = Pt(nrand(640), nrand(640));
- pts[2] = Pt(nrand(640), nrand(640));
-}
-
-void
-pts2linear(void)
-{
-#define lconv(m, u, w) \
- m[0] = w.y - u.y, \
- m[1] = u.x - w.x, \
- m[2] = - m[0] * u.x - m[1] * u.y
-
- lconv(m[0], pts[0], pts[1]);
- lconv(m[1], pts[1], pts[2]);
- lconv(m[2], pts[2], pts[0]);
-
-#undef lconv
-}
-
-void
-normalize(void)
-{
-#define l(m, u) (m[0] * u.x + m[1] * u.y + m[2])
-#define invert(m) m[0] = -m[0], m[1] = -m[1], m[2] = -m[2];
-
- if (l(m[0], pts[2]) < 0) invert(m[0]);
- if (l(m[1], pts[0]) < 0) invert(m[1]);
- if (l(m[2], pts[1]) < 0) invert(m[2]);
-
-#undef l
-#undef invert
-}
-
-
-void
main(void)
{
-
+ view = raynorm(view);
srand(nsec());
-
- initscene();
- n = nsec();
- vrender();
- n = nsec() - n;
s = smprint("render time %lld nsec", n);
initdraw(nil, 0, "cubes");
img = allocimage(display, Rect(0, 0, CSWidth, CSHeight), XRGB32, 0, DRed);
- randomize_pts();
- pts2linear();
- normalize();
n = nsec(); vrender(); n = nsec() - n;
- loadimage(img, img->r, (uchar *)imgbuf, CSSize * 4);
s = smprint("render time %lld nsec", n);
+ loadimage(img, img->r, (uchar *)imgbuf, CSSize * 4);
redraw(img);
Event e;
einit(Emouse);
- int timer = etimer(0, 125);
+ int timer = etimer(0, 500);
for(;;) {
int key = event(&e);
if (key == timer) {
-
- randomize_pts();
- pts2linear();
- normalize();
n = nsec(); vrender(); n = nsec() - n;
- loadimage(img, img->r, (uchar *)imgbuf, CSSize * 4);
free(s); s = smprint("render time %lld nsec", n);
+ loadimage(img, img->r, (uchar *)imgbuf, CSSize * 4);
redraw(img);
}
}