commit 91b1381d6b978f013543e5329adf6faec4c2424e
parent 9c6537cbdee20b55e9a1683b6b11e4125c6632d4
Author: Vincent Forest <vincent.forest@meso-star.com>
Date: Tue, 6 Feb 2018 12:43:35 +0100
Implement the htvox_scene_at function
Diffstat:
2 files changed, 77 insertions(+), 1 deletion(-)
diff --git a/src/htvox.h b/src/htvox.h
@@ -17,6 +17,7 @@
#define HTVOX_H
#include <rsys/rsys.h>
+#include <float.h>
/* Library symbol management */
#if defined(HTVOX_SHARED_BUILD) /* Build shared library */
@@ -41,6 +42,11 @@ struct htvox_voxel {
size_t id; /* Indentifier of the voxel */
};
+#define HTVOX_VOXEL_NULL__ { DBL_MAX, SIZE_MAX }
+static const struct htvox_voxel HTVOX_VOXEL_NULL = HTVOX_VOXEL_NULL__;
+
+#define HTVOX_VOXEL_NONE(Voxel) ((Voxel)->id == HTVOX_VOXEL_NULL.id)
+
struct htvox_hit {
double distance; /* Distance from the ray origin to the impacted voxel */
struct htvox_voxel voxel; /* Intersected voxel */
diff --git a/src/htvox_scene.c b/src/htvox_scene.c
@@ -561,7 +561,7 @@ res_T
htvox_scene_for_each_voxel
(struct htvox_scene* scn,
void (*func)
- (const double val,
+ (const double val,
const size_t ivoxel,
const double low[3],
const double upp[3],
@@ -640,3 +640,73 @@ htvox_scene_for_each_voxel
return RES_OK;
}
+res_T
+htvox_scene_at
+ (struct htvox_scene* scn,
+ const double position[3],
+ struct htvox_voxel* voxel)
+{
+ struct octree_index inode;
+ double scale_exp2;
+ double low[3];
+ double pos[3];
+
+ if(!scn || !position || !voxel) return RES_BAD_ARG;
+
+ *voxel = HTVOX_VOXEL_NULL;
+
+ if(position[0] > scn->upper[0] || position[0] < scn->lower[0]
+ || position[1] > scn->upper[1] || position[1] < scn->lower[1]
+ || position[2] > scn->upper[2] || position[2] < scn->lower[2]) {
+ return RES_OK;
+ }
+
+ /* Transform the position in the normalized octree space,
+ * i.e. octree lies in [0, 1]^2 */
+ pos[0] = (position[0] - scn->oclow[0]) / (scn->ocupp[0] - scn->oclow[0]);
+ pos[1] = (position[1] - scn->oclow[1]) / (scn->ocupp[1] - scn->oclow[1]);
+ pos[2] = (position[2] - scn->oclow[2]) / (scn->ocupp[2] - scn->oclow[2]);
+
+ /* Initialized the lower left corner of the current node */
+ low[0] = 0;
+ low[1] = 0;
+ low[2] = 0;
+
+ scale_exp2 = 0.5;
+ do {
+ struct octree_xnode* node = octree_buffer_get_node(&scn->buffer, inode);
+
+ if(OCTREE_XNODE_IS_LEAF(node)) { /* Reach a leaf */
+ const size_t page_nvoxs = scn->buffer.pagesize/sizeof(double);
+ struct octree_index ileaf;
+
+ ileaf = octree_buffer_get_child_index(&scn->buffer, inode, 0);
+ voxel->data = *octree_buffer_get_leaf(&scn->buffer, ileaf);
+ voxel->id = ileaf.ipage * page_nvoxs + ileaf.inode;
+
+ } else {
+ double mid[3];
+ int ichild = 0;
+
+ ASSERT(!OCTREE_XNODE_IS_EMPTY(node));
+
+ /* Compute the middle point of the node */
+ mid[0] = low[0] + scale_exp2;
+ mid[1] = low[1] + scale_exp2;
+ mid[2] = low[2] + scale_exp2;
+
+ /* Define the child of the current node into which pos `lies' and compute
+ * its lower left corner */
+ if(pos[0] > mid[0]) { ichild |= 4; low[0] += mid[0]; }
+ if(pos[1] > mid[1]) { ichild |= 2; low[1] += mid[1]; }
+ if(pos[2] > mid[2]) { ichild |= 1; low[2] += mid[2]; }
+
+ /* Fetch the child node */
+ inode = octree_buffer_get_child_index(&scn->buffer, inode, ichild);
+ scale_exp2 *= 0.5;
+ }
+ } while(HTVOX_VOXEL_NONE(voxel));
+
+ return RES_OK;
+}
+