summaryrefslogtreecommitdiff
path: root/src/modules/sparkler/bsp.c
diff options
context:
space:
mode:
authorVito Caputo <vcaputo@pengaru.com>2020-09-11 00:48:13 -0700
committerVito Caputo <vcaputo@pengaru.com>2020-09-11 01:05:40 -0700
commit85127285bff6983665275fe14d3c2b80b36a872a (patch)
tree0215b33ee3b1101b9300d790f15914fa4e2bfcdf /src/modules/sparkler/bsp.c
parenta9f489265c1ebbc67a3f675d1a79a2254345b489 (diff)
module/sparkler: implement some BSP drawing settings
This commit adds a few settings for visualizing the octree BSP: show_bsp_leafs (on/off): Draw wireframe cubes around octree leaf nodes show_bsp_leafs_min_depth (0,4,6,8,10): Set minimum octree depth for leaf nodes displayed show_bsp_matches (on/off): Draw lines connecting BSP search matches show_bsp_matches_affected_only (on/off): Limit drawn BSP search matches to only matches actually affected by the simulation The code implementing this stuff is a bit crufty, fb_fragment_t had to be pulled down to the sim ops for example and whether that actually results in drawing occurring during the sim phase depends on the config used and how the particle implementations react to the config... it's just gross. This matters because the caller used to know only the draw phase touched fb_fragment_t, and because of that the fragment was zeroed after sim and before draw in parallel. But now the caller needs to know if the config would make sim do some drawing, and do the fragment zeroing before sim instead, and skip the zero before draw to not lose what sim drew. It's icky, but I'll leave it for now, at least it's isolated to the sparkler.
Diffstat (limited to 'src/modules/sparkler/bsp.c')
-rw-r--r--src/modules/sparkler/bsp.c56
1 files changed, 56 insertions, 0 deletions
diff --git a/src/modules/sparkler/bsp.c b/src/modules/sparkler/bsp.c
index ae5a20e..f55501a 100644
--- a/src/modules/sparkler/bsp.c
+++ b/src/modules/sparkler/bsp.c
@@ -574,3 +574,59 @@ void bsp_search_sphere(bsp_t *bsp, v3f_t *center, float radius_min, float radius
_bsp_search_sphere(bsp, &bsp->root, &search, &aabb_min, &aabb_max);
}
+
+
+static void _bsp_walk_leaves(const bsp_t *bsp, const bsp_node_t *node, unsigned depth, const v3f_t *aabb_min, const v3f_t *aabb_max, void (*cb)(const bsp_t *bsp, const list_head_t *occupants, unsigned depth, const v3f_t *bv_min, const v3f_t *bv_max, void *cb_data), void *cb_data)
+{
+ v3f_t oaabb_min, oaabb_max;
+
+ /* if node is a leaf, call cb with the occupants, then return. */
+ if (!node->octrants)
+ return cb(bsp, &node->occupants, depth, aabb_min, aabb_max, cb_data);
+
+ /* node is a parent, recur on each octrant with appropriately adjusted aabb_min:aabb_max values */
+ /* if any of the octrants absolutely overlaps the search sphere, skip the others by returning. */
+#define walk_octrant(_oid, _aabb_min, _aabb_max) \
+ _bsp_walk_leaves(bsp, &node->octrants[_oid], depth + 1, _aabb_min, _aabb_max, cb, cb_data);
+
+ /* OCT_XL_YL_ZL and OCT_XR_YR_ZR AABBs don't require tedious composition */
+ walk_octrant(OCT_XL_YL_ZL, aabb_min, &node->center);
+ walk_octrant(OCT_XR_YR_ZR, &node->center, aabb_max);
+
+ /* the rest are stitched together requiring temp storage and tedium */
+ v3f_set(&oaabb_min, node->center.x, aabb_min->y, aabb_min->z);
+ v3f_set(&oaabb_max, aabb_max->x, node->center.y, node->center.z);
+ walk_octrant(OCT_XR_YL_ZL, &oaabb_min, &oaabb_max);
+
+ v3f_set(&oaabb_min, aabb_min->x, node->center.y, aabb_min->z);
+ v3f_set(&oaabb_max, node->center.x, aabb_max->y, node->center.z);
+ walk_octrant(OCT_XL_YR_ZL, &oaabb_min, &oaabb_max);
+
+ v3f_set(&oaabb_min, node->center.x, node->center.y, aabb_min->z);
+ v3f_set(&oaabb_max, aabb_max->x, aabb_max->y, node->center.z);
+ walk_octrant(OCT_XR_YR_ZL, &oaabb_min, &oaabb_max);
+
+ v3f_set(&oaabb_min, aabb_min->x, aabb_min->y, node->center.z);
+ v3f_set(&oaabb_max, node->center.x, node->center.y, aabb_max->z);
+ walk_octrant(OCT_XL_YL_ZR, &oaabb_min, &oaabb_max);
+
+ v3f_set(&oaabb_min, node->center.x, aabb_min->y, node->center.z);
+ v3f_set(&oaabb_max, aabb_max->x, node->center.y, aabb_max->z);
+ walk_octrant(OCT_XR_YL_ZR, &oaabb_min, &oaabb_max);
+
+ v3f_set(&oaabb_min, aabb_min->x, node->center.y, node->center.z);
+ v3f_set(&oaabb_max, node->center.x, aabb_max->y, aabb_max->z);
+ walk_octrant(OCT_XL_YR_ZR, &oaabb_min, &oaabb_max);
+
+#undef walk_octrant
+}
+
+
+/* traverse the bsp tree calling cb for every leaf node, no discriminating of positions */
+void bsp_walk_leaves(const bsp_t *bsp, void (*cb)(const bsp_t *bsp, const list_head_t *occupants, unsigned depth, const v3f_t *bv_min, const v3f_t *bv_max, void *cb_data), void *cb_data)
+{
+ v3f_t aabb_min = v3f_init(-1.0f, -1.0f, -1.0f);
+ v3f_t aabb_max = v3f_init(1.0f, 1.0f, 1.0f);
+
+ _bsp_walk_leaves(bsp, &bsp->root, 0, &aabb_min, &aabb_max, cb, cb_data);
+}
© All Rights Reserved