396 lines
14 KiB
C++
396 lines
14 KiB
C++
/* SPDX-FileCopyrightText: 2006 NaN Holding BV. All rights reserved.
|
|
*
|
|
* SPDX-License-Identifier: GPL-2.0-or-later */
|
|
|
|
#pragma once
|
|
|
|
/** \file
|
|
* \ingroup bli
|
|
*/
|
|
|
|
#include "BLI_sys_types.h"
|
|
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
#endif
|
|
|
|
struct BVHTree;
|
|
struct DistProjectedAABBPrecalc;
|
|
|
|
typedef struct BVHTree BVHTree;
|
|
#define USE_KDOPBVH_WATERTIGHT
|
|
|
|
typedef struct BVHTreeAxisRange {
|
|
union {
|
|
struct {
|
|
float min, max;
|
|
};
|
|
/* alternate access */
|
|
float range[2];
|
|
};
|
|
} BVHTreeAxisRange;
|
|
|
|
typedef struct BVHTreeOverlap {
|
|
int indexA;
|
|
int indexB;
|
|
} BVHTreeOverlap;
|
|
|
|
typedef struct BVHTreeNearest {
|
|
/** The index of the nearest found
|
|
* (untouched if none is found within a dist radius from the given coordinates) */
|
|
int index;
|
|
/** Nearest coordinates
|
|
* (untouched it none is found within a dist radius from the given coordinates). */
|
|
float co[3];
|
|
/** Normal at nearest coordinates
|
|
* (untouched it none is found within a dist radius from the given coordinates). */
|
|
float no[3];
|
|
/** squared distance to search around */
|
|
float dist_sq;
|
|
int flags;
|
|
} BVHTreeNearest;
|
|
|
|
typedef struct BVHTreeRay {
|
|
/** ray origin */
|
|
float origin[3];
|
|
/** ray direction */
|
|
float direction[3];
|
|
/** radius around ray */
|
|
float radius;
|
|
#ifdef USE_KDOPBVH_WATERTIGHT
|
|
struct IsectRayPrecalc *isect_precalc;
|
|
#endif
|
|
} BVHTreeRay;
|
|
|
|
typedef struct BVHTreeRayHit {
|
|
/** Index of the tree node (untouched if no hit is found). */
|
|
int index;
|
|
/** Coordinates of the hit point. */
|
|
float co[3];
|
|
/** Normal on hit point. */
|
|
float no[3];
|
|
/** Distance to the hit point. */
|
|
float dist;
|
|
} BVHTreeRayHit;
|
|
|
|
enum {
|
|
BVH_OVERLAP_USE_THREADING = (1 << 0),
|
|
BVH_OVERLAP_RETURN_PAIRS = (1 << 1),
|
|
/* Use a specialized self-overlap traversal to only test and output every
|
|
* pair once, rather than twice in different order as usual. */
|
|
BVH_OVERLAP_SELF = (1 << 2),
|
|
};
|
|
enum {
|
|
/* Use a priority queue to process nodes in the optimal order (for slow callbacks) */
|
|
BVH_NEAREST_OPTIMAL_ORDER = (1 << 0),
|
|
};
|
|
enum {
|
|
/* calculate IsectRayPrecalc data */
|
|
BVH_RAYCAST_WATERTIGHT = (1 << 0),
|
|
};
|
|
#define BVH_RAYCAST_DEFAULT (BVH_RAYCAST_WATERTIGHT)
|
|
#define BVH_RAYCAST_DIST_MAX (FLT_MAX / 2.0f)
|
|
|
|
/**
|
|
* Callback must update nearest in case it finds a nearest result.
|
|
*/
|
|
typedef void (*BVHTree_NearestPointCallback)(void *userdata,
|
|
int index,
|
|
const float co[3],
|
|
BVHTreeNearest *nearest);
|
|
|
|
/**
|
|
* Callback must update hit in case it finds a nearest successful hit.
|
|
*/
|
|
typedef void (*BVHTree_RayCastCallback)(void *userdata,
|
|
int index,
|
|
const BVHTreeRay *ray,
|
|
BVHTreeRayHit *hit);
|
|
|
|
/**
|
|
* Callback to check if 2 nodes overlap (use thread if intersection results need to be stored).
|
|
*/
|
|
typedef bool (*BVHTree_OverlapCallback)(void *userdata, int index_a, int index_b, int thread);
|
|
|
|
/**
|
|
* Callback to range search query.
|
|
*/
|
|
typedef void (*BVHTree_RangeQuery)(void *userdata, int index, const float co[3], float dist_sq);
|
|
|
|
/**
|
|
* Callback to find nearest projected.
|
|
*/
|
|
typedef void (*BVHTree_NearestProjectedCallback)(void *userdata,
|
|
int index,
|
|
const struct DistProjectedAABBPrecalc *precalc,
|
|
const float (*clip_plane)[4],
|
|
int clip_plane_len,
|
|
BVHTreeNearest *nearest);
|
|
|
|
/* callbacks to BLI_bvhtree_walk_dfs */
|
|
|
|
/**
|
|
* Return true to traverse into this nodes children, else skip.
|
|
*/
|
|
typedef bool (*BVHTree_WalkParentCallback)(const BVHTreeAxisRange *bounds, void *userdata);
|
|
/**
|
|
* Return true to keep walking, else early-exit the search.
|
|
*/
|
|
typedef bool (*BVHTree_WalkLeafCallback)(const BVHTreeAxisRange *bounds,
|
|
int index,
|
|
void *userdata);
|
|
/**
|
|
* Return true to search (min, max) else (max, min).
|
|
*/
|
|
typedef bool (*BVHTree_WalkOrderCallback)(const BVHTreeAxisRange *bounds,
|
|
char axis,
|
|
void *userdata);
|
|
|
|
/**
|
|
* \note many callers don't check for `NULL` return.
|
|
*/
|
|
BVHTree *BLI_bvhtree_new(int maxsize, float epsilon, char tree_type, char axis);
|
|
void BLI_bvhtree_free(BVHTree *tree);
|
|
|
|
/**
|
|
* Construct: first insert points, then call balance.
|
|
*/
|
|
void BLI_bvhtree_insert(BVHTree *tree, int index, const float co[3], int numpoints);
|
|
void BLI_bvhtree_balance(BVHTree *tree);
|
|
|
|
/**
|
|
* Update: first update points/nodes, then call update_tree to refit the bounding volumes.
|
|
* \note call before #BLI_bvhtree_update_tree().
|
|
*/
|
|
bool BLI_bvhtree_update_node(
|
|
BVHTree *tree, int index, const float co[3], const float co_moving[3], int numpoints);
|
|
/**
|
|
* Call #BLI_bvhtree_update_node() first for every node/point/triangle.
|
|
*
|
|
* Note that this does not rebalance the tree, so if the shape of the mesh changes
|
|
* too much, operations on the tree may become suboptimal.
|
|
*/
|
|
void BLI_bvhtree_update_tree(BVHTree *tree);
|
|
|
|
/**
|
|
* Use to check the total number of threads #BLI_bvhtree_overlap will use.
|
|
*
|
|
* \warning Must be the first tree passed to #BLI_bvhtree_overlap!
|
|
*/
|
|
int BLI_bvhtree_overlap_thread_num(const BVHTree *tree);
|
|
|
|
/**
|
|
* Collision/overlap: check two trees if they overlap,
|
|
* alloc's *overlap with length of the int return value.
|
|
*
|
|
* \param callback: optional, to test the overlap before adding (must be thread-safe!).
|
|
*/
|
|
BVHTreeOverlap *BLI_bvhtree_overlap_ex(const BVHTree *tree1,
|
|
const BVHTree *tree2,
|
|
uint *r_overlap_num,
|
|
BVHTree_OverlapCallback callback,
|
|
void *userdata,
|
|
uint max_interactions,
|
|
int flag);
|
|
BVHTreeOverlap *BLI_bvhtree_overlap(const BVHTree *tree1,
|
|
const BVHTree *tree2,
|
|
unsigned int *r_overlap_num,
|
|
BVHTree_OverlapCallback callback,
|
|
void *userdata);
|
|
/**
|
|
* Compute overlaps of the tree with itself. This is faster than #BLI_bvhtree_overlap
|
|
* because it only tests and returns each symmetrical pair once.
|
|
*/
|
|
BVHTreeOverlap *BLI_bvhtree_overlap_self(const BVHTree *tree,
|
|
unsigned int *r_overlap_num,
|
|
BVHTree_OverlapCallback callback,
|
|
void *userdata);
|
|
|
|
int *BLI_bvhtree_intersect_plane(const BVHTree *tree, float plane[4], uint *r_intersect_num);
|
|
|
|
/**
|
|
* Number of times #BLI_bvhtree_insert has been called.
|
|
* mainly useful for asserts functions to check we added the correct number.
|
|
*/
|
|
int BLI_bvhtree_get_len(const BVHTree *tree);
|
|
/**
|
|
* Maximum number of children that a node can have.
|
|
*/
|
|
int BLI_bvhtree_get_tree_type(const BVHTree *tree);
|
|
float BLI_bvhtree_get_epsilon(const BVHTree *tree);
|
|
/**
|
|
* This function returns the bounding box of the BVH tree.
|
|
*/
|
|
void BLI_bvhtree_get_bounding_box(const BVHTree *tree, float r_bb_min[3], float r_bb_max[3]);
|
|
|
|
/**
|
|
* Find nearest node to the given coordinates
|
|
* (if nearest is given it will only search nodes where
|
|
* square distance is smaller than nearest->dist).
|
|
*/
|
|
int BLI_bvhtree_find_nearest_ex(const BVHTree *tree,
|
|
const float co[3],
|
|
BVHTreeNearest *nearest,
|
|
BVHTree_NearestPointCallback callback,
|
|
void *userdata,
|
|
int flag);
|
|
int BLI_bvhtree_find_nearest(const BVHTree *tree,
|
|
const float co[3],
|
|
BVHTreeNearest *nearest,
|
|
BVHTree_NearestPointCallback callback,
|
|
void *userdata);
|
|
|
|
/**
|
|
* Find the first node nearby.
|
|
* Favors speed over quality since it doesn't find the best target node.
|
|
*/
|
|
int BLI_bvhtree_find_nearest_first(const BVHTree *tree,
|
|
const float co[3],
|
|
float dist_sq,
|
|
BVHTree_NearestPointCallback callback,
|
|
void *userdata);
|
|
|
|
int BLI_bvhtree_ray_cast_ex(const BVHTree *tree,
|
|
const float co[3],
|
|
const float dir[3],
|
|
float radius,
|
|
BVHTreeRayHit *hit,
|
|
BVHTree_RayCastCallback callback,
|
|
void *userdata,
|
|
int flag);
|
|
int BLI_bvhtree_ray_cast(const BVHTree *tree,
|
|
const float co[3],
|
|
const float dir[3],
|
|
float radius,
|
|
BVHTreeRayHit *hit,
|
|
BVHTree_RayCastCallback callback,
|
|
void *userdata);
|
|
|
|
/**
|
|
* Calls the callback for every ray intersection
|
|
*
|
|
* \note Using a \a callback which resets or never sets the #BVHTreeRayHit index & dist works too,
|
|
* however using this function means existing generic callbacks can be used from custom callbacks
|
|
* without having to handle resetting the hit beforehand.
|
|
* It also avoid redundant argument and return value which aren't meaningful
|
|
* when collecting multiple hits.
|
|
*/
|
|
void BLI_bvhtree_ray_cast_all_ex(const BVHTree *tree,
|
|
const float co[3],
|
|
const float dir[3],
|
|
float radius,
|
|
float hit_dist,
|
|
BVHTree_RayCastCallback callback,
|
|
void *userdata,
|
|
int flag);
|
|
void BLI_bvhtree_ray_cast_all(const BVHTree *tree,
|
|
const float co[3],
|
|
const float dir[3],
|
|
float radius,
|
|
float hit_dist,
|
|
BVHTree_RayCastCallback callback,
|
|
void *userdata);
|
|
|
|
float BLI_bvhtree_bb_raycast(const float bv[6],
|
|
const float light_start[3],
|
|
const float light_end[3],
|
|
float pos[3]);
|
|
|
|
/**
|
|
* Range query.
|
|
*/
|
|
int BLI_bvhtree_range_query(const BVHTree *tree,
|
|
const float co[3],
|
|
float radius,
|
|
BVHTree_RangeQuery callback,
|
|
void *userdata);
|
|
|
|
int BLI_bvhtree_find_nearest_projected(const BVHTree *tree,
|
|
float projmat[4][4],
|
|
float winsize[2],
|
|
float mval[2],
|
|
float (*clip_planes)[4],
|
|
int clip_plane_len,
|
|
BVHTreeNearest *nearest,
|
|
BVHTree_NearestProjectedCallback callback,
|
|
void *userdata);
|
|
|
|
/**
|
|
* This is a generic function to perform a depth first search on the #BVHTree
|
|
* where the search order and nodes traversed depend on callbacks passed in.
|
|
*
|
|
* \param tree: Tree to walk.
|
|
* \param walk_parent_cb: Callback on a parents bound-box to test if it should be traversed.
|
|
* \param walk_leaf_cb: Callback to test leaf nodes, callback must store its own result,
|
|
* returning false exits early.
|
|
* \param walk_order_cb: Callback that indicates which direction to search,
|
|
* either from the node with the lower or higher K-DOP axis value.
|
|
* \param userdata: Argument passed to all callbacks.
|
|
*/
|
|
void BLI_bvhtree_walk_dfs(const BVHTree *tree,
|
|
BVHTree_WalkParentCallback walk_parent_cb,
|
|
BVHTree_WalkLeafCallback walk_leaf_cb,
|
|
BVHTree_WalkOrderCallback walk_order_cb,
|
|
void *userdata);
|
|
|
|
/**
|
|
* Expose for BVH callbacks to use.
|
|
*/
|
|
extern const float bvhtree_kdop_axes[13][3];
|
|
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif
|
|
|
|
#ifdef __cplusplus
|
|
|
|
# include "BLI_function_ref.hh"
|
|
# include "BLI_math_vector.hh"
|
|
|
|
namespace blender {
|
|
|
|
using BVHTree_RayCastCallback_CPP =
|
|
FunctionRef<void(int index, const BVHTreeRay &ray, BVHTreeRayHit &hit)>;
|
|
|
|
inline void BLI_bvhtree_ray_cast_all_cpp(const BVHTree &tree,
|
|
const float3 co,
|
|
const float3 dir,
|
|
float radius,
|
|
float hit_dist,
|
|
BVHTree_RayCastCallback_CPP fn)
|
|
{
|
|
BLI_bvhtree_ray_cast_all(
|
|
&tree,
|
|
co,
|
|
dir,
|
|
radius,
|
|
hit_dist,
|
|
[](void *userdata, int index, const BVHTreeRay *ray, BVHTreeRayHit *hit) {
|
|
BVHTree_RayCastCallback_CPP fn = *static_cast<BVHTree_RayCastCallback_CPP *>(userdata);
|
|
fn(index, *ray, *hit);
|
|
},
|
|
&fn);
|
|
}
|
|
|
|
using BVHTree_RangeQuery_CPP = FunctionRef<void(int index, const float3 &co, float dist_sq)>;
|
|
|
|
inline void BLI_bvhtree_range_query_cpp(const BVHTree &tree,
|
|
const float3 co,
|
|
float radius,
|
|
BVHTree_RangeQuery_CPP fn)
|
|
{
|
|
BLI_bvhtree_range_query(
|
|
&tree,
|
|
co,
|
|
radius,
|
|
[](void *userdata, const int index, const float co[3], const float dist_sq) {
|
|
BVHTree_RangeQuery_CPP fn = *static_cast<BVHTree_RangeQuery_CPP *>(userdata);
|
|
fn(index, co, dist_sq);
|
|
},
|
|
&fn);
|
|
}
|
|
|
|
} // namespace blender
|
|
|
|
#endif
|