commit ac987898a7ba9232ea93a66c700b7dd11a26ae9d
parent c4fc8b85361ac902d5dd7741e0c2f9b016441b03
Author: Vincent Forest <vincent.forest@meso-star.com>
Date: Thu, 10 May 2018 15:19:55 +0200
Update the svx_hit data structure
The distance attribute of the hit structure becomes a 2 dimensional
array that stores the distance from the ray origin to the entry and exit
point of the ray against the hit voxel. These distances are clamped
against the submitted ray range.
Diffstat:
3 files changed, 39 insertions(+), 24 deletions(-)
diff --git a/src/svx.h b/src/svx.h
@@ -130,14 +130,16 @@ static const struct svx_tree_desc SVX_TREE_DESC_NULL =
SVX_TREE_DESC_NULL__;
struct svx_hit {
- double distance; /* Distance from the ray origin to the impacted voxel */
+ /* Distance from the ray origin the the voxel entry/exit point, respectively.
+ * These distances are clamped against the ray-range. */
+ double distance[2];
struct svx_voxel voxel; /* Intersected voxel */
};
-#define SVX_HIT_NULL__ {DBL_MAX, SVX_VOXEL_NULL__}
+#define SVX_HIT_NULL__ {{DBL_MAX,-DBL_MAX}, SVX_VOXEL_NULL__}
static const struct svx_hit SVX_HIT_NULL = SVX_HIT_NULL__;
-#define SVX_HIT_NONE(Hit) ((Hit)->distance >= DBL_MAX)
+#define SVX_HIT_NONE(Hit) ((Hit)->distance[0] > (Hit)->distance[1])
/* Function to invoke on a leaf */
typedef void
diff --git a/src/svx_octree_trace_ray.c b/src/svx_octree_trace_ray.c
@@ -58,7 +58,8 @@ static FINLINE void
setup_hit
(struct svx_tree* oct,
const struct buffer_index iattr, /* Index toward the voxel attributes */
- const double distance, /* Hit distance */
+ const double distance_min, /* Dst from ray org to the voxel entry point */
+ const double distance_max, /* Dst from ray_org to the voxel exit point */
const float corner[3], /* Corner of the current voxel in [1, 2]^3 space */
const double scale_exp2, /* Size of the voxel in [1, 2]^3] space */
const size_t depth, /* Depth of the voxel in the octree hierarchy */
@@ -68,9 +69,10 @@ setup_hit
{
double low[3], upp[3];
ASSERT(oct && corner && hit);
- ASSERT(distance > 0);
+ ASSERT(distance_min >= 0 && distance_min <= distance_max);
- hit->distance = distance;
+ hit->distance[0] = distance_min;
+ hit->distance[1] = distance_max;
hit->voxel.data = buffer_get_attr(&oct->buffer, iattr);
hit->voxel.depth = depth,
hit->voxel.id = buffer_absolute_attr_index(&oct->buffer, iattr);
@@ -243,13 +245,12 @@ trace_ray
* check the current hit */
if(is_leaf || challenge) {
struct svx_hit hit_tmp;
- const double dst = t_min <= ray->range[0] ? t_max_child : t_min;
const size_t depth = SCALE_MAX - scale;
const struct buffer_index iattr = buffer_get_child_attr_index
(&oct->buffer, inode, (int)ichild_adjusted);
- setup_hit(oct, iattr, dst, corner, scale_exp2, depth, is_leaf,
- ray->octant_mask, &hit_tmp);
+ setup_hit(oct, iattr, t_min, t_max_child, corner, scale_exp2, depth,
+ is_leaf, ray->octant_mask, &hit_tmp);
if(is_leaf || challenge(&hit_tmp, context)) {
go_deeper = 0;
diff --git a/src/test_svx_octree_trace_ray.c b/src/test_svx_octree_trace_ray.c
@@ -20,6 +20,7 @@
#include <math.h>
+#include <rsys/clock_time.h>
#include <rsys/double2.h>
#include <rsys/double3.h>
#include <rsys/image.h>
@@ -236,11 +237,13 @@ hit_challenge(const struct svx_hit* hit, void* context)
static void
draw_image(FILE* stream, struct svx_tree* oct, const struct scene* scn)
{
+ char buf[32];
+ struct time t0, t1;
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 pos[3] = { 0,-1.5, 0};
const double tgt[3] = { 0, 0, 0};
const double up[3] = { 0, 0, 1};
struct image img;
@@ -255,6 +258,7 @@ draw_image(FILE* stream, struct svx_tree* oct, const struct scene* scn)
IMAGE_RGB8, NULL) == RES_OK);
pixels = (unsigned char*)img.pixels;
+ time_current(&t0);
FOR_EACH(iy, 0, height) {
pix[1] = (double)iy / (double)height;
FOR_EACH(ix, 0, width) {
@@ -272,9 +276,9 @@ draw_image(FILE* stream, struct svx_tree* oct, const struct scene* scn)
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];
+ N[0] = (r.org[0] + hit.distance[0] * r.dir[0]) - scn->sphere_pos[0];
+ N[1] = (r.org[1] + hit.distance[0] * r.dir[1]) - scn->sphere_pos[1];
+ N[2] = (r.org[2] + hit.distance[0] * r.dir[2]) - scn->sphere_pos[2];
CHK(d3_normalize(N, N) != 0);
N[0] = fabs(N[0]);
N[1] = fabs(N[1]);
@@ -285,6 +289,9 @@ draw_image(FILE* stream, struct svx_tree* oct, const struct scene* scn)
}
}
}
+ time_sub(&t0, time_current(&t1), &t0);
+ time_dump(&t0, TIME_ALL, NULL, buf, sizeof(buf));
+ fprintf(stderr, "Render time: %s\n", buf);
CHK(image_write_ppm_stream(&img, 0, stream) == RES_OK);
image_release(&img);
@@ -303,7 +310,7 @@ main(int argc, char** argv)
struct svx_hit hit2 = SVX_HIT_NULL;
const double lower[3] = {-1,-1,-1};
const double upper[3] = { 1, 1, 1};
- const size_t def[3] = {32, 32, 32};
+ const size_t def[3] = {32,32,32};
double scnsz[3];
double vxsz;
double dst;
@@ -347,7 +354,8 @@ main(int argc, char** argv)
r.org[0] = 0;
CHK(RT(oct, r.org, r.dir, r.range, NULL, NULL, NULL, &hit) == RES_OK);
CHK(!SVX_HIT_NONE(&hit));
- CHK(eq_eps(hit.distance, hit.voxel.lower[1] - r.org[1], 1.e-6));
+ CHK(eq_eps(hit.distance[0], hit.voxel.lower[1] - r.org[1], 1.e-6));
+ CHK(eq_eps(hit.distance[1], hit.voxel.upper[1] - r.org[1], 1.e-6));
CHK(hit.voxel.is_leaf);
CHK(*(char*)hit.voxel.data == 0);
@@ -358,17 +366,18 @@ main(int argc, char** argv)
CHK(!SVX_VOXEL_EQ(&hit.voxel, &hit2.voxel));
CHK(hit2.voxel.is_leaf == 0);
CHK(*(char*)hit2.voxel.data == 1);
- CHK(eq_eps(hit.distance, hit2.distance, 1.e-6));
+ CHK(eq_eps(hit.distance[0], hit2.distance[0], 1.e-6));
/* Use filter function to discard leaves with a value == 0 */
CHK(RT(oct, r.org, r.dir, r.range, NULL, hit_filter, &r, &hit) == RES_OK);
CHK(!SVX_HIT_NONE(&hit));
- CHK(eq_eps(hit.distance, hit.voxel.lower[1] - r.org[1], 1.e-6));
+ CHK(eq_eps(hit.distance[0], hit.voxel.lower[1] - r.org[1], 1.e-6));
+ CHK(eq_eps(hit.distance[1], hit.voxel.upper[1] - r.org[1], 1.e-6));
CHK(hit.voxel.is_leaf);
CHK(*(char*)hit.voxel.data == 1);
- /* Use th ray range to vvoid the intersection closest voxel */
- r.range[1] = nextafter(hit.distance, -1);
+ /* Use th ray range to avoid the intersection with the closest voxel */
+ r.range[1] = nextafter(hit.distance[0], -1);
CHK(RT(oct, r.org, r.dir, r.range, NULL, hit_filter, &r, &hit) == RES_OK);
CHK(SVX_HIT_NONE(&hit));
@@ -385,26 +394,29 @@ main(int argc, char** argv)
CHK(!SVX_HIT_NONE(&hit2));
CHK(!SVX_VOXEL_EQ(&hit.voxel, &hit2.voxel));
vxsz = hit2.voxel.upper[1] - hit2.voxel.lower[1];
- CHK(eq_eps(hit2.distance, dst + vxsz, 1.e-6));
+ CHK(eq_eps(hit2.distance[0], r.range[0], 1.e-6));
+ CHK(eq_eps(hit2.distance[1], dst + vxsz, 1.e-6));
CHK(*(char*)hit.voxel.data == 1);
CHK(hit.voxel.is_leaf);
/* Adjust the ray range to hit the interior of the closest voxel */
- r.range[0] = nextafter(hit.distance, DBL_MAX);
+ r.range[0] = nextafter(hit.distance[0], DBL_MAX);
CHK(RT(oct, r.org, r.dir, r.range, NULL, hit_filter, &r, &hit2) == RES_OK);
CHK(!SVX_HIT_NONE(&hit2));
CHK(SVX_VOXEL_EQ(&hit.voxel, &hit2.voxel));
- CHK(eq_eps(hit2.distance, dst, 1.e-6));
+ CHK(eq_eps(hit2.distance[0], r.range[0], 1.e-6));
+ CHK(eq_eps(hit2.distance[1], dst, 1.e-6));
CHK(*(char*)hit.voxel.data == 1);
CHK(hit.voxel.is_leaf);
/* Discard the closest voxel with the filter function */
r.range[0] = 0;
CHK(RT(oct, r.org, r.dir, r.range, NULL, hit_filter2, &hit.voxel, &hit2) == RES_OK);
- CHK(eq_eps(hit2.distance, hit2.voxel.lower[1] - r.org[1], 1.e-6));
+ CHK(eq_eps(hit2.distance[0], hit2.voxel.lower[1] - r.org[1], 1.e-6));
+ CHK(eq_eps(hit2.distance[1], hit2.voxel.upper[1] - r.org[1], 1.e-6));
CHK(!SVX_HIT_NONE(&hit2));
CHK(!SVX_VOXEL_EQ(&hit.voxel, &hit2.voxel));
- CHK(eq_eps(hit2.distance, dst, 1.e-6));
+ CHK(eq_eps(hit2.distance[0], dst, 1.e-6));
CHK(*(char*)hit.voxel.data == 1);
CHK(hit.voxel.is_leaf);