stew

a monorepo of some sort
git clone git://git.nsmpr.xyz/stew.git
Log | Files | Refs

cubes.c (4505B)


      1 #include <u.h>
      2 #include <libc.h>
      3 #include <draw.h>
      4 #include <event.h>
      5 #include <geometry.h>
      6 
      7 /*
      8  * given 640 resolution and 80 digrees FoV,
      9  * single pixel will be 0.125 digrees wide.
     10  * 360/.125 = 2880 - amount of pixels needed
     11  * for full circle.
     12  * Small enough amount to precompute all possible
     13  * angles for every possible direction
     14  */
     15 
     16 #define OTSize (64 * 64 * 64)
     17 
     18 #define CSWidth 640
     19 #define CSHeight 640
     20 #define CSSize (CSWidth * CSHeight)
     21 
     22 u32int otree[OTSize];
     23 u32int imgbuf[CSSize];
     24 
     25 Image *img;
     26 vlong n;
     27 char *s;
     28 
     29 typedef struct Raydef Raydef;
     30 struct Raydef {
     31 	double O[3];
     32 	double D[3];
     33 };
     34 
     35 typedef struct Boxdef Boxdef;
     36 struct Boxdef {
     37 	double min[3];
     38 	double max[3];
     39 };
     40 
     41 Boxdef box = {{0,0,0}, {1,1,1}};
     42 Raydef view = {{10,20,30}, {-1,-2,-3}};
     43 
     44 Raydef
     45 raynorm(Raydef r)
     46 {
     47 	double d = r.D[0] * r.D[0] + r.D[1] * r.D[1] + r.D[2] * r.D[2];
     48 	if (d != 0) {
     49 		r.D[0] /= d;
     50 		r.D[1] /= d;
     51 		r.D[2] /= d;
     52 	}
     53 	return r;
     54 }
     55 
     56 /*
     57  * Ray is O + Dt, where O is origin and D is direction
     58  * Box is defined by 2 boundary points, M, N (min and max)
     59  * which translates into 6 planes:
     60  *   x = Nx; x = Mx; y = Ny; y = My; z = Nz; z = Mz
     61  * Intersections of ray and planes:
     62  *  Tn = (Bn - On)/Dn; where B (as in boundary) is either M or N,
     63  *    and n stands for axis (x,y,z)
     64  *  (beware division by zero!)
     65  * 
     66  */
     67 
     68 Raydef
     69 intersectX(Raydef ray, double X)
     70 {
     71 	Raydef ref;
     72 	double t;
     73 	if (ray.D[0] >= X) {
     74 		Raydef ret = {
     75 		  {Inf(ray.D[0]), Inf(ray.D[1]), Inf(ray.D[2])},
     76 		  {ray.D[0], ray.D[1], ray.D[2]},
     77 		};
     78 		return ret;
     79 	}
     80 	t = (X-ray.O[0]) / ray.D[0];
     81 	ref.O[0] = X;
     82 	ref.O[1] = ray.O[1] + ray.D[1] * t;
     83 	ref.O[2] = ray.O[2] + ray.D[2] * t;
     84 	ref.D[0] = -ray.D[0];
     85 	ref.D[1] = ray.D[1];
     86 	ref.D[2] = ray.D[2];
     87 	return ref;
     88 }
     89 
     90 Raydef
     91 intersectY(Raydef ray, double Y)
     92 {
     93 	Raydef ref;
     94 	double t;
     95 	if (ray.D[1] >= Y) {
     96 		Raydef ret = {
     97 		  {Inf(ray.D[0]), Inf(ray.D[1]), Inf(ray.D[2])},
     98 		  {ray.D[0], ray.D[1], ray.D[2]},
     99 		};
    100 		return ret;
    101 	}
    102 	t = (Y-ray.O[1]) / ray.D[1];
    103 	ref.O[0] = ray.O[0] + ray.D[0] * t;
    104 	ref.O[1] = Y;
    105 	ref.O[2] = ray.O[2] + ray.D[2] * t;
    106 	ref.D[0] = ray.D[0];
    107 	ref.D[1] = -ray.D[1];
    108 	ref.D[2] = ray.D[2];
    109 	return ref;
    110 }
    111 
    112 Raydef
    113 intersectZ(Raydef ray, double Z)
    114 {
    115 	Raydef ref;
    116 	double t;
    117 	if (ray.D[2] >= Z) {
    118 		Raydef ret = {
    119 		  {Inf(ray.D[0]), Inf(ray.D[1]), Inf(ray.D[2])},
    120 		  {ray.D[0], ray.D[1], ray.D[2]},
    121 		};
    122 		return ret;
    123 	}
    124 	t = (Z-ray.O[0]) / ray.D[0];
    125 	ref.O[0] = ray.O[0] + ray.D[0] * t;
    126 	ref.O[1] = ray.O[1] + ray.D[1] * t;
    127 	ref.O[2] = Z;
    128 	ref.D[0] = ray.D[0];
    129 	ref.D[1] = ray.D[1];
    130 	ref.D[2] = -ray.D[2];
    131 	return ref;
    132 }
    133 
    134 void
    135 vrender(void)
    136 {
    137 	int i, j, x, y;
    138 	double X, Y;
    139 	for (i = 0, y = 0; y < CSHeight; y++) {
    140 		Y = (double)(y) / CSHeight;
    141 		for (x = 0; x < CSWidth; x++, i++) {
    142 			X = (double)(x) / CSWidth;
    143 			// TODO: generate camera ray properly
    144 			Raydef r = {
    145 				.O {10, 10, 10},
    146 				.D {-1 + X * 2, 1 - Y * 2, 2}
    147 			};
    148 			Raydef  ref[6];
    149 			ref[0] = intersectX(r, 0);
    150 			ref[1] = intersectY(r, 0);
    151 			ref[2] = intersectZ(r, 0);
    152 
    153 			ref[3] = intersectX(r, 0);
    154 			ref[4] = intersectY(r, 0);
    155 			ref[5] = intersectZ(r, 0);
    156 
    157 			Raydef one; // = infray
    158 			for (j = 0; j < 6; j++) {
    159 				// check boundary;
    160 				if ((ref[j].O[0] < 0) || (ref[j].O[1] < 0) || (ref[j].O[2] < 0))
    161 					continue;
    162 				// todo check distance;
    163 				one = ref[j];
    164 			}
    165 			if (isInf(ref[0].O[0], 0) != 0) imgbuf[i] = 0x004f7fff;
    166 			else {
    167 				double d = sqrt((ref[0].D[1] * ref[0].D[1])
    168 				  / (ref[0].D[0] * ref[0].D[0] + ref[0].D[2] * ref[0].D[2]));
    169 				int br = 0xff * d;
    170 				imgbuf[i] = (br << 16) + (br << 8) + (br);
    171 			}
    172 		}
    173 	}
    174 }
    175 
    176 void
    177 redraw(Image *)
    178 {
    179 	draw(screen, screen->r, display->white, nil, ZP);
    180 	draw(screen, screen->r, img, nil, ZP);
    181 
    182 	string(screen, screen->r.min, display->white, ZP, font, s);
    183 }
    184 
    185 void
    186 eresized(int new)
    187 {
    188 	if(new && getwindow(display, Refnone) < 0)
    189 		sysfatal("can't reattach to window");
    190 	redraw(screen);
    191 }
    192 
    193 void
    194 main(void)
    195 {
    196 	view = raynorm(view);
    197 	srand(nsec());
    198 	s = smprint("render time %lld nsec", n);
    199 	initdraw(nil, 0, "cubes");
    200 	img = allocimage(display, Rect(0, 0, CSWidth, CSHeight), XRGB32, 0, DRed);
    201 
    202 	n = nsec(); vrender(); n = nsec() - n;
    203 	s = smprint("render time %lld nsec", n);
    204 	loadimage(img, img->r, (uchar *)imgbuf, CSSize * 4);
    205 	redraw(img);
    206 
    207 	Event e;
    208 	einit(Emouse);
    209 	int timer = etimer(0, 500);
    210 	for(;;) {
    211 		int key = event(&e);
    212 		if (key == timer) {
    213 			n = nsec(); vrender(); n = nsec() - n;
    214 			free(s); s = smprint("render time %lld nsec", n);
    215 			loadimage(img, img->r, (uchar *)imgbuf, CSSize * 4);
    216 			redraw(img);
    217 		}
    218 	}
    219 }