commit 3467e2d3dda84ea28cd0d10ac16c1759d7c09fb3
parent d01a4ad76131dd4e236fb569823dae267dcd27cc
Author: Vincent Forest <vincent.forest@meso-star.com>
Date: Fri, 6 Apr 2018 10:01:48 +0200
Push further the trace_ray test
Use the svx_octree_trace_ray function to draw an image of a volumic
scene.
Diffstat:
1 file changed, 104 insertions(+), 2 deletions(-)
diff --git a/src/test_svx_octree_trace_ray.c b/src/test_svx_octree_trace_ray.c
@@ -22,8 +22,14 @@
#include <rsys/double2.h>
#include <rsys/double3.h>
+#include <rsys/image.h>
#include <rsys/math.h>
+struct camera {
+ double pos[3];
+ double x[3], y[3], z[3]; /* Frame */
+};
+
struct ray {
double org[3];
double dir[3];
@@ -37,6 +43,43 @@ struct scene {
double sphere_radius;
};
+static void
+camera_init
+ (struct camera* cam,
+ const double pos[3],
+ const double tgt[3],
+ const double up[3],
+ const double proj_ratio)
+{
+ const double fov_x = PI * 0.25;
+ double d = 0.0;
+ CHK(cam != NULL);
+
+ d3_set(cam->pos, pos);
+ d = d3_normalize(cam->z, d3_sub(cam->z, tgt, pos)); CHK(d != 0);
+ d = d3_normalize(cam->x, d3_cross(cam->x, cam->z, up)); CHK(d != 0);
+ d = d3_normalize(cam->y, d3_cross(cam->y, cam->z, cam->x)); CHK(d != 0);
+ d3_divd(cam->z, cam->z, tan(fov_x*0.5));
+ d3_divd(cam->y, cam->y, proj_ratio);
+}
+
+static void
+camera_ray
+ (const struct camera* cam,
+ const double pixel[2],
+ struct ray* ray)
+{
+ double x[3], y[3], f;
+ CHK(cam && pixel && ray);
+
+ d3_muld(x, cam->x, pixel[0]*2.0 - 1.0);
+ d3_muld(y, cam->y, pixel[1]*2.0 - 1.0);
+ d3_add(ray->dir, d3_add(ray->dir, x, y), cam->z);
+ f = d3_normalize(ray->dir, ray->dir); CHK(f != 0);
+ d3_set(ray->org, cam->pos);
+ d2(ray->range, 0, INF);
+}
+
static char
sphere_intersect_aabb
(const double pos[3], /* Sphere position */
@@ -118,7 +161,7 @@ voxels_challenge_merge(const void* voxels[], const size_t nvoxels, void* ctx)
return merge;
}
-static void
+static INLINE void
write_scalars
(const struct svx_voxel* leaf,
const size_t ileaf,
@@ -190,6 +233,63 @@ hit_challenge(const struct svx_hit* hit, void* context)
return 1;
}
+static void
+draw_image(FILE* stream, struct svx_octree* oct, const struct scene* scn)
+{
+ struct camera cam;
+ unsigned char* pixels = NULL;
+ const size_t width = 512;
+ const size_t height = 512;
+ const double pos[3] = { 0,-2, 0};
+ const double tgt[3] = { 0, 0, 0};
+ const double up[3] = { 0, 0, 1};
+ struct image img;
+ double pix[2];
+ size_t ix, iy;
+
+ CHK(oct);
+ camera_init(&cam, pos, tgt, up, (double)width/(double)height);
+
+ image_init(NULL, &img);
+ CHK(image_setup(&img, width, height, sizeof_image_format(IMAGE_RGB8)*width,
+ IMAGE_RGB8, NULL) == RES_OK);
+ pixels = (unsigned char*)img.pixels;
+
+ FOR_EACH(iy, 0, height) {
+ pix[1] = (double)iy / (double)height;
+ FOR_EACH(ix, 0, width) {
+ struct svx_hit hit;
+ struct ray r;
+ size_t ipix = (iy*width + ix)*3/*#channels per pixel*/;
+ pix[0] = (double)ix / (double)width;
+ camera_ray(&cam, pix, &r);
+
+ CHK(svx_octree_trace_ray
+ (oct, r.org, r.dir, r.range, NULL, hit_filter, &r, &hit) == RES_OK);
+ if(SVX_HIT_NONE(&hit)) {
+ pixels[ipix+0] = 0;
+ pixels[ipix+1] = 0;
+ pixels[ipix+2] = 0;
+ } else {
+ double N[3];
+ N[0] = (r.org[0] + hit.distance * r.dir[0]) - scn->sphere_pos[0];
+ N[1] = (r.org[1] + hit.distance * r.dir[1]) - scn->sphere_pos[1];
+ N[2] = (r.org[2] + hit.distance * r.dir[2]) - scn->sphere_pos[2];
+ CHK(d3_normalize(N, N) != 0);
+ N[0] = fabs(N[0]);
+ N[1] = fabs(N[1]);
+ N[2] = fabs(N[2]);
+ pixels[ipix+0] = (unsigned char)(N[0] * 255.0);
+ pixels[ipix+1] = (unsigned char)(N[1] * 255.0);
+ pixels[ipix+2] = (unsigned char)(N[2] * 255.0);
+ }
+ }
+ }
+
+ CHK(image_write_ppm_stream(&img, 0, stream) == RES_OK);
+ image_release(&img);
+}
+
int
main(int argc, char** argv)
{
@@ -235,7 +335,7 @@ main(int argc, char** argv)
CHK(svx_octree_create(dev, lower, upper, def, &voxel_desc, &oct) == RES_OK);
- dump_data(stdout, oct, CHAR, 1, write_scalars);
+ /*dump_data(stdout, oct, CHAR, 1, write_scalars);*/
#define RT svx_octree_trace_ray
d3(r.org, -5,-5, 0);
@@ -314,6 +414,8 @@ main(int argc, char** argv)
CHK(SVX_HIT_NONE(&hit));
CHK(accum != 0);
+ draw_image(stdout, oct, &scn);
+
CHK(svx_octree_ref_put(oct) == RES_OK);
CHK(svx_device_ref_put(dev) == RES_OK);
CHK(mem_allocated_size() == 0);