Merge pull request #48314 from nekomatata/physics-2d-dynamic-bvh
[3.x] Support for Dynamic BVH as 2D Physics broadphase
This commit is contained in:
commit
32cc022267
|
@ -48,9 +48,9 @@
|
||||||
|
|
||||||
#include "bvh_tree.h"
|
#include "bvh_tree.h"
|
||||||
|
|
||||||
#define BVHTREE_CLASS BVH_Tree<T, 2, MAX_ITEMS, USE_PAIRS>
|
#define BVHTREE_CLASS BVH_Tree<T, 2, MAX_ITEMS, USE_PAIRS, Bounds, Point>
|
||||||
|
|
||||||
template <class T, bool USE_PAIRS = false, int MAX_ITEMS = 32>
|
template <class T, bool USE_PAIRS = false, int MAX_ITEMS = 32, class Bounds = AABB, class Point = Vector3>
|
||||||
class BVH_Manager {
|
class BVH_Manager {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
@ -88,7 +88,7 @@ public:
|
||||||
unpair_callback_userdata = p_userdata;
|
unpair_callback_userdata = p_userdata;
|
||||||
}
|
}
|
||||||
|
|
||||||
BVHHandle create(T *p_userdata, bool p_active, const AABB &p_aabb = AABB(), int p_subindex = 0, bool p_pairable = false, uint32_t p_pairable_type = 0, uint32_t p_pairable_mask = 1) {
|
BVHHandle create(T *p_userdata, bool p_active, const Bounds &p_aabb = Bounds(), int p_subindex = 0, bool p_pairable = false, uint32_t p_pairable_type = 0, uint32_t p_pairable_mask = 1) {
|
||||||
|
|
||||||
// not sure if absolutely necessary to flush collisions here. It will cost performance to, instead
|
// not sure if absolutely necessary to flush collisions here. It will cost performance to, instead
|
||||||
// of waiting for update, so only uncomment this if there are bugs.
|
// of waiting for update, so only uncomment this if there are bugs.
|
||||||
|
@ -108,7 +108,7 @@ public:
|
||||||
|
|
||||||
if (USE_PAIRS) {
|
if (USE_PAIRS) {
|
||||||
// for safety initialize the expanded AABB
|
// for safety initialize the expanded AABB
|
||||||
AABB &expanded_aabb = tree._pairs[h.id()].expanded_aabb;
|
Bounds &expanded_aabb = tree._pairs[h.id()].expanded_aabb;
|
||||||
expanded_aabb = p_aabb;
|
expanded_aabb = p_aabb;
|
||||||
expanded_aabb.grow_by(tree._pairing_expansion);
|
expanded_aabb.grow_by(tree._pairing_expansion);
|
||||||
|
|
||||||
|
@ -125,7 +125,7 @@ public:
|
||||||
////////////////////////////////////////////////////
|
////////////////////////////////////////////////////
|
||||||
// wrapper versions that use uint32_t instead of handle
|
// wrapper versions that use uint32_t instead of handle
|
||||||
// for backward compatibility. Less type safe
|
// for backward compatibility. Less type safe
|
||||||
void move(uint32_t p_handle, const AABB &p_aabb) {
|
void move(uint32_t p_handle, const Bounds &p_aabb) {
|
||||||
BVHHandle h;
|
BVHHandle h;
|
||||||
h.set(p_handle);
|
h.set(p_handle);
|
||||||
move(h, p_aabb);
|
move(h, p_aabb);
|
||||||
|
@ -143,7 +143,7 @@ public:
|
||||||
force_collision_check(h);
|
force_collision_check(h);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool activate(uint32_t p_handle, const AABB &p_aabb, bool p_delay_collision_check = false) {
|
bool activate(uint32_t p_handle, const Bounds &p_aabb, bool p_delay_collision_check = false) {
|
||||||
BVHHandle h;
|
BVHHandle h;
|
||||||
h.set(p_handle);
|
h.set(p_handle);
|
||||||
return activate(h, p_aabb, p_delay_collision_check);
|
return activate(h, p_aabb, p_delay_collision_check);
|
||||||
|
@ -180,7 +180,7 @@ public:
|
||||||
|
|
||||||
////////////////////////////////////////////////////
|
////////////////////////////////////////////////////
|
||||||
|
|
||||||
void move(BVHHandle p_handle, const AABB &p_aabb) {
|
void move(BVHHandle p_handle, const Bounds &p_aabb) {
|
||||||
|
|
||||||
if (tree.item_move(p_handle, p_aabb)) {
|
if (tree.item_move(p_handle, p_aabb)) {
|
||||||
if (USE_PAIRS) {
|
if (USE_PAIRS) {
|
||||||
|
@ -207,7 +207,7 @@ public:
|
||||||
void force_collision_check(BVHHandle p_handle) {
|
void force_collision_check(BVHHandle p_handle) {
|
||||||
if (USE_PAIRS) {
|
if (USE_PAIRS) {
|
||||||
// the aabb should already be up to date in the BVH
|
// the aabb should already be up to date in the BVH
|
||||||
AABB aabb;
|
Bounds aabb;
|
||||||
item_get_AABB(p_handle, aabb);
|
item_get_AABB(p_handle, aabb);
|
||||||
|
|
||||||
// add it as changed even if aabb not different
|
// add it as changed even if aabb not different
|
||||||
|
@ -221,7 +221,7 @@ public:
|
||||||
// these should be read as set_visible for render trees,
|
// these should be read as set_visible for render trees,
|
||||||
// but generically this makes items add or remove from the
|
// but generically this makes items add or remove from the
|
||||||
// tree internally, to speed things up by ignoring inactive items
|
// tree internally, to speed things up by ignoring inactive items
|
||||||
bool activate(BVHHandle p_handle, const AABB &p_aabb, bool p_delay_collision_check = false) {
|
bool activate(BVHHandle p_handle, const Bounds &p_aabb, bool p_delay_collision_check = false) {
|
||||||
// sending the aabb here prevents the need for the BVH to maintain
|
// sending the aabb here prevents the need for the BVH to maintain
|
||||||
// a redundant copy of the aabb.
|
// a redundant copy of the aabb.
|
||||||
// returns success
|
// returns success
|
||||||
|
@ -294,7 +294,7 @@ public:
|
||||||
// when the pairable state changes, we need to force a collision check because newly pairable
|
// when the pairable state changes, we need to force a collision check because newly pairable
|
||||||
// items may be in collision, and unpairable items might move out of collision.
|
// items may be in collision, and unpairable items might move out of collision.
|
||||||
// We cannot depend on waiting for the next update, because that may come much later.
|
// We cannot depend on waiting for the next update, because that may come much later.
|
||||||
AABB aabb;
|
Bounds aabb;
|
||||||
item_get_AABB(p_handle, aabb);
|
item_get_AABB(p_handle, aabb);
|
||||||
|
|
||||||
// passing false disables the optimization which prevents collision checks if
|
// passing false disables the optimization which prevents collision checks if
|
||||||
|
@ -311,7 +311,7 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
// cull tests
|
// cull tests
|
||||||
int cull_aabb(const AABB &p_aabb, T **p_result_array, int p_result_max, int *p_subindex_array = nullptr, uint32_t p_mask = 0xFFFFFFFF) {
|
int cull_aabb(const Bounds &p_aabb, T **p_result_array, int p_result_max, int *p_subindex_array = nullptr, uint32_t p_mask = 0xFFFFFFFF) {
|
||||||
typename BVHTREE_CLASS::CullParams params;
|
typename BVHTREE_CLASS::CullParams params;
|
||||||
|
|
||||||
params.result_count_overall = 0;
|
params.result_count_overall = 0;
|
||||||
|
@ -328,7 +328,7 @@ public:
|
||||||
return params.result_count_overall;
|
return params.result_count_overall;
|
||||||
}
|
}
|
||||||
|
|
||||||
int cull_segment(const Vector3 &p_from, const Vector3 &p_to, T **p_result_array, int p_result_max, int *p_subindex_array = nullptr, uint32_t p_mask = 0xFFFFFFFF) {
|
int cull_segment(const Point &p_from, const Point &p_to, T **p_result_array, int p_result_max, int *p_subindex_array = nullptr, uint32_t p_mask = 0xFFFFFFFF) {
|
||||||
typename BVHTREE_CLASS::CullParams params;
|
typename BVHTREE_CLASS::CullParams params;
|
||||||
|
|
||||||
params.result_count_overall = 0;
|
params.result_count_overall = 0;
|
||||||
|
@ -346,7 +346,7 @@ public:
|
||||||
return params.result_count_overall;
|
return params.result_count_overall;
|
||||||
}
|
}
|
||||||
|
|
||||||
int cull_point(const Vector3 &p_point, T **p_result_array, int p_result_max, int *p_subindex_array = nullptr, uint32_t p_mask = 0xFFFFFFFF) {
|
int cull_point(const Point &p_point, T **p_result_array, int p_result_max, int *p_subindex_array = nullptr, uint32_t p_mask = 0xFFFFFFFF) {
|
||||||
typename BVHTREE_CLASS::CullParams params;
|
typename BVHTREE_CLASS::CullParams params;
|
||||||
|
|
||||||
params.result_count_overall = 0;
|
params.result_count_overall = 0;
|
||||||
|
@ -396,7 +396,7 @@ private:
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
AABB bb;
|
Bounds bb;
|
||||||
|
|
||||||
typename BVHTREE_CLASS::CullParams params;
|
typename BVHTREE_CLASS::CullParams params;
|
||||||
|
|
||||||
|
@ -411,8 +411,8 @@ private:
|
||||||
const BVHHandle &h = changed_items[n];
|
const BVHHandle &h = changed_items[n];
|
||||||
|
|
||||||
// use the expanded aabb for pairing
|
// use the expanded aabb for pairing
|
||||||
const AABB &expanded_aabb = tree._pairs[h.id()].expanded_aabb;
|
const Bounds &expanded_aabb = tree._pairs[h.id()].expanded_aabb;
|
||||||
BVH_ABB abb;
|
BVHABB_CLASS abb;
|
||||||
abb.from(expanded_aabb);
|
abb.from(expanded_aabb);
|
||||||
|
|
||||||
// find all the existing paired aabbs that are no longer
|
// find all the existing paired aabbs that are no longer
|
||||||
|
@ -457,8 +457,8 @@ private:
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void item_get_AABB(BVHHandle p_handle, AABB &r_aabb) {
|
void item_get_AABB(BVHHandle p_handle, Bounds &r_aabb) {
|
||||||
BVH_ABB abb;
|
BVHABB_CLASS abb;
|
||||||
tree.item_get_ABB(p_handle, abb);
|
tree.item_get_ABB(p_handle, abb);
|
||||||
abb.to(r_aabb);
|
abb.to(r_aabb);
|
||||||
}
|
}
|
||||||
|
@ -494,8 +494,8 @@ private:
|
||||||
}
|
}
|
||||||
|
|
||||||
// returns true if unpair
|
// returns true if unpair
|
||||||
bool _find_leavers_process_pair(typename BVHTREE_CLASS::ItemPairs &p_pairs_from, const BVH_ABB &p_abb_from, BVHHandle p_from, BVHHandle p_to, bool p_full_check) {
|
bool _find_leavers_process_pair(typename BVHTREE_CLASS::ItemPairs &p_pairs_from, const BVHABB_CLASS &p_abb_from, BVHHandle p_from, BVHHandle p_to, bool p_full_check) {
|
||||||
BVH_ABB abb_to;
|
BVHABB_CLASS abb_to;
|
||||||
tree.item_get_ABB(p_to, abb_to);
|
tree.item_get_ABB(p_to, abb_to);
|
||||||
|
|
||||||
// do they overlap?
|
// do they overlap?
|
||||||
|
@ -526,10 +526,10 @@ private:
|
||||||
|
|
||||||
// find all the existing paired aabbs that are no longer
|
// find all the existing paired aabbs that are no longer
|
||||||
// paired, and send callbacks
|
// paired, and send callbacks
|
||||||
void _find_leavers(BVHHandle p_handle, const BVH_ABB &expanded_abb_from, bool p_full_check) {
|
void _find_leavers(BVHHandle p_handle, const BVHABB_CLASS &expanded_abb_from, bool p_full_check) {
|
||||||
typename BVHTREE_CLASS::ItemPairs &p_from = tree._pairs[p_handle.id()];
|
typename BVHTREE_CLASS::ItemPairs &p_from = tree._pairs[p_handle.id()];
|
||||||
|
|
||||||
BVH_ABB abb_from = expanded_abb_from;
|
BVHABB_CLASS abb_from = expanded_abb_from;
|
||||||
|
|
||||||
// remove from pairing list for every partner
|
// remove from pairing list for every partner
|
||||||
for (unsigned int n = 0; n < p_from.extended_pairs.size(); n++) {
|
for (unsigned int n = 0; n < p_from.extended_pairs.size(); n++) {
|
||||||
|
@ -608,7 +608,7 @@ private:
|
||||||
_tick++;
|
_tick++;
|
||||||
}
|
}
|
||||||
|
|
||||||
void _add_changed_item(BVHHandle p_handle, const AABB &aabb, bool p_check_aabb = true) {
|
void _add_changed_item(BVHHandle p_handle, const Bounds &aabb, bool p_check_aabb = true) {
|
||||||
|
|
||||||
// Note that non pairable items can pair with pairable,
|
// Note that non pairable items can pair with pairable,
|
||||||
// so all types must be added to the list
|
// so all types must be added to the list
|
||||||
|
@ -616,7 +616,7 @@ private:
|
||||||
// aabb check with expanded aabb. This greatly decreases processing
|
// aabb check with expanded aabb. This greatly decreases processing
|
||||||
// at the cost of slightly less accurate pairing checks
|
// at the cost of slightly less accurate pairing checks
|
||||||
// Note this pairing AABB is separate from the AABB in the actual tree
|
// Note this pairing AABB is separate from the AABB in the actual tree
|
||||||
AABB &expanded_aabb = tree._pairs[p_handle.id()].expanded_aabb;
|
Bounds &expanded_aabb = tree._pairs[p_handle.id()].expanded_aabb;
|
||||||
|
|
||||||
// passing p_check_aabb false disables the optimization which prevents collision checks if
|
// passing p_check_aabb false disables the optimization which prevents collision checks if
|
||||||
// the aabb hasn't changed. This is needed where set_pairable has been called, but the position
|
// the aabb hasn't changed. This is needed where set_pairable has been called, but the position
|
||||||
|
|
|
@ -32,6 +32,7 @@
|
||||||
#define BVH_ABB_H
|
#define BVH_ABB_H
|
||||||
|
|
||||||
// special optimized version of axis aligned bounding box
|
// special optimized version of axis aligned bounding box
|
||||||
|
template <class Bounds = AABB, class Point = Vector3>
|
||||||
struct BVH_ABB {
|
struct BVH_ABB {
|
||||||
struct ConvexHull {
|
struct ConvexHull {
|
||||||
// convex hulls (optional)
|
// convex hulls (optional)
|
||||||
|
@ -42,8 +43,8 @@ struct BVH_ABB {
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Segment {
|
struct Segment {
|
||||||
Vector3 from;
|
Point from;
|
||||||
Vector3 to;
|
Point to;
|
||||||
};
|
};
|
||||||
|
|
||||||
enum IntersectResult {
|
enum IntersectResult {
|
||||||
|
@ -53,49 +54,50 @@ struct BVH_ABB {
|
||||||
};
|
};
|
||||||
|
|
||||||
// we store mins with a negative value in order to test them with SIMD
|
// we store mins with a negative value in order to test them with SIMD
|
||||||
Vector3 min;
|
Point min;
|
||||||
Vector3 neg_max;
|
Point neg_max;
|
||||||
|
|
||||||
bool operator==(const BVH_ABB &o) const { return (min == o.min) && (neg_max == o.neg_max); }
|
bool operator==(const BVH_ABB &o) const { return (min == o.min) && (neg_max == o.neg_max); }
|
||||||
bool operator!=(const BVH_ABB &o) const { return (*this == o) == false; }
|
bool operator!=(const BVH_ABB &o) const { return (*this == o) == false; }
|
||||||
|
|
||||||
void set(const Vector3 &_min, const Vector3 &_max) {
|
void set(const Point &_min, const Point &_max) {
|
||||||
min = _min;
|
min = _min;
|
||||||
neg_max = -_max;
|
neg_max = -_max;
|
||||||
}
|
}
|
||||||
|
|
||||||
// to and from standard AABB
|
// to and from standard AABB
|
||||||
void from(const AABB &p_aabb) {
|
void from(const Bounds &p_aabb) {
|
||||||
min = p_aabb.position;
|
min = p_aabb.position;
|
||||||
neg_max = -(p_aabb.position + p_aabb.size);
|
neg_max = -(p_aabb.position + p_aabb.size);
|
||||||
}
|
}
|
||||||
|
|
||||||
void to(AABB &r_aabb) const {
|
void to(Bounds &r_aabb) const {
|
||||||
r_aabb.position = min;
|
r_aabb.position = min;
|
||||||
r_aabb.size = calculate_size();
|
r_aabb.size = calculate_size();
|
||||||
}
|
}
|
||||||
|
|
||||||
void merge(const BVH_ABB &p_o) {
|
void merge(const BVH_ABB &p_o) {
|
||||||
neg_max.x = MIN(neg_max.x, p_o.neg_max.x);
|
for (int axis = 0; axis < Point::AXIS_COUNT; ++axis) {
|
||||||
neg_max.y = MIN(neg_max.y, p_o.neg_max.y);
|
neg_max[axis] = MIN(neg_max[axis], p_o.neg_max[axis]);
|
||||||
neg_max.z = MIN(neg_max.z, p_o.neg_max.z);
|
min[axis] = MIN(min[axis], p_o.min[axis]);
|
||||||
|
}
|
||||||
min.x = MIN(min.x, p_o.min.x);
|
|
||||||
min.y = MIN(min.y, p_o.min.y);
|
|
||||||
min.z = MIN(min.z, p_o.min.z);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Vector3 calculate_size() const {
|
Point calculate_size() const {
|
||||||
return -neg_max - min;
|
return -neg_max - min;
|
||||||
}
|
}
|
||||||
|
|
||||||
Vector3 calculate_centre() const {
|
Point calculate_centre() const {
|
||||||
return Vector3((calculate_size() * 0.5) + min);
|
return Point((calculate_size() * 0.5) + min);
|
||||||
}
|
}
|
||||||
|
|
||||||
real_t get_proximity_to(const BVH_ABB &p_b) const {
|
real_t get_proximity_to(const BVH_ABB &p_b) const {
|
||||||
const Vector3 d = (min - neg_max) - (p_b.min - p_b.neg_max);
|
const Point d = (min - neg_max) - (p_b.min - p_b.neg_max);
|
||||||
return (Math::abs(d.x) + Math::abs(d.y) + Math::abs(d.z));
|
real_t proximity = 0.0;
|
||||||
|
for (int axis = 0; axis < Point::AXIS_COUNT; ++axis) {
|
||||||
|
proximity += Math::abs(d[axis]);
|
||||||
|
}
|
||||||
|
return proximity;
|
||||||
}
|
}
|
||||||
|
|
||||||
int select_by_proximity(const BVH_ABB &p_a, const BVH_ABB &p_b) const {
|
int select_by_proximity(const BVH_ABB &p_a, const BVH_ABB &p_b) const {
|
||||||
|
@ -158,7 +160,7 @@ struct BVH_ABB {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool intersects_convex_partial(const ConvexHull &p_hull) const {
|
bool intersects_convex_partial(const ConvexHull &p_hull) const {
|
||||||
AABB bb;
|
Bounds bb;
|
||||||
to(bb);
|
to(bb);
|
||||||
return bb.intersects_convex_shape(p_hull.planes, p_hull.num_planes, p_hull.points, p_hull.num_points);
|
return bb.intersects_convex_shape(p_hull.planes, p_hull.num_planes, p_hull.points, p_hull.num_points);
|
||||||
}
|
}
|
||||||
|
@ -178,7 +180,7 @@ struct BVH_ABB {
|
||||||
|
|
||||||
bool is_within_convex(const ConvexHull &p_hull) const {
|
bool is_within_convex(const ConvexHull &p_hull) const {
|
||||||
// use half extents routine
|
// use half extents routine
|
||||||
AABB bb;
|
Bounds bb;
|
||||||
to(bb);
|
to(bb);
|
||||||
return bb.inside_convex_shape(p_hull.planes, p_hull.num_planes);
|
return bb.inside_convex_shape(p_hull.planes, p_hull.num_planes);
|
||||||
}
|
}
|
||||||
|
@ -192,59 +194,66 @@ struct BVH_ABB {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool intersects_segment(const Segment &p_s) const {
|
bool intersects_segment(const Segment &p_s) const {
|
||||||
AABB bb;
|
Bounds bb;
|
||||||
to(bb);
|
to(bb);
|
||||||
return bb.intersects_segment(p_s.from, p_s.to);
|
return bb.intersects_segment(p_s.from, p_s.to);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool intersects_point(const Vector3 &p_pt) const {
|
bool intersects_point(const Point &p_pt) const {
|
||||||
if (_vector3_any_lessthan(-p_pt, neg_max)) return false;
|
if (_any_lessthan(-p_pt, neg_max)) return false;
|
||||||
if (_vector3_any_lessthan(p_pt, min)) return false;
|
if (_any_lessthan(p_pt, min)) return false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool intersects(const BVH_ABB &p_o) const {
|
bool intersects(const BVH_ABB &p_o) const {
|
||||||
if (_vector3_any_morethan(p_o.min, -neg_max)) return false;
|
if (_any_morethan(p_o.min, -neg_max)) return false;
|
||||||
if (_vector3_any_morethan(min, -p_o.neg_max)) return false;
|
if (_any_morethan(min, -p_o.neg_max)) return false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool is_other_within(const BVH_ABB &p_o) const {
|
bool is_other_within(const BVH_ABB &p_o) const {
|
||||||
if (_vector3_any_lessthan(p_o.neg_max, neg_max)) return false;
|
if (_any_lessthan(p_o.neg_max, neg_max)) return false;
|
||||||
if (_vector3_any_lessthan(p_o.min, min)) return false;
|
if (_any_lessthan(p_o.min, min)) return false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void grow(const Vector3 &p_change) {
|
void grow(const Point &p_change) {
|
||||||
neg_max -= p_change;
|
neg_max -= p_change;
|
||||||
min -= p_change;
|
min -= p_change;
|
||||||
}
|
}
|
||||||
|
|
||||||
void expand(real_t p_change) {
|
void expand(real_t p_change) {
|
||||||
grow(Vector3(p_change, p_change, p_change));
|
Point change;
|
||||||
|
change.set_all(p_change);
|
||||||
|
grow(change);
|
||||||
}
|
}
|
||||||
|
|
||||||
float get_area() const // actually surface area metric
|
// Actually surface area metric.
|
||||||
{
|
float get_area() const {
|
||||||
Vector3 d = calculate_size();
|
Point d = calculate_size();
|
||||||
return 2.0f * (d.x * d.y + d.y * d.z + d.z * d.x);
|
return 2.0f * (d.x * d.y + d.y * d.z + d.z * d.x);
|
||||||
}
|
}
|
||||||
|
|
||||||
void set_to_max_opposite_extents() {
|
void set_to_max_opposite_extents() {
|
||||||
neg_max = Vector3(FLT_MAX, FLT_MAX, FLT_MAX);
|
neg_max.set_all(FLT_MAX);
|
||||||
min = neg_max;
|
min = neg_max;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool _vector3_any_morethan(const Vector3 &p_a, const Vector3 &p_b) const {
|
bool _any_morethan(const Point &p_a, const Point &p_b) const {
|
||||||
if (p_a.x > p_b.x) return true;
|
for (int axis = 0; axis < Point::AXIS_COUNT; ++axis) {
|
||||||
if (p_a.y > p_b.y) return true;
|
if (p_a[axis] > p_b[axis]) {
|
||||||
if (p_a.z > p_b.z) return true;
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool _vector3_any_lessthan(const Vector3 &p_a, const Vector3 &p_b) const {
|
bool _any_lessthan(const Point &p_a, const Point &p_b) const {
|
||||||
if (p_a.x < p_b.x) return true;
|
for (int axis = 0; axis < Point::AXIS_COUNT; ++axis) {
|
||||||
if (p_a.y < p_b.y) return true;
|
if (p_a[axis] < p_b[axis]) {
|
||||||
if (p_a.z < p_b.z) return true;
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -15,9 +15,9 @@ struct CullParams {
|
||||||
|
|
||||||
// optional components for different tests
|
// optional components for different tests
|
||||||
Vector3 point;
|
Vector3 point;
|
||||||
BVH_ABB abb;
|
BVHABB_CLASS abb;
|
||||||
typename BVH_ABB::ConvexHull hull;
|
typename BVHABB_CLASS::ConvexHull hull;
|
||||||
typename BVH_ABB::Segment segment;
|
typename BVHABB_CLASS::Segment segment;
|
||||||
|
|
||||||
// when collision testing, non pairable moving items
|
// when collision testing, non pairable moving items
|
||||||
// only need to be tested against the pairable tree.
|
// only need to be tested against the pairable tree.
|
||||||
|
@ -200,7 +200,7 @@ bool _cull_segment_iterative(uint32_t p_node_id, CullParams &r_params) {
|
||||||
|
|
||||||
// test children individually
|
// test children individually
|
||||||
for (int n = 0; n < leaf.num_items; n++) {
|
for (int n = 0; n < leaf.num_items; n++) {
|
||||||
const BVH_ABB &aabb = leaf.get_aabb(n);
|
const BVHABB_CLASS &aabb = leaf.get_aabb(n);
|
||||||
|
|
||||||
if (aabb.intersects_segment(r_params.segment)) {
|
if (aabb.intersects_segment(r_params.segment)) {
|
||||||
uint32_t child_id = leaf.get_item_ref_id(n);
|
uint32_t child_id = leaf.get_item_ref_id(n);
|
||||||
|
@ -214,7 +214,7 @@ bool _cull_segment_iterative(uint32_t p_node_id, CullParams &r_params) {
|
||||||
for (int n = 0; n < tnode.num_children; n++) {
|
for (int n = 0; n < tnode.num_children; n++) {
|
||||||
|
|
||||||
uint32_t child_id = tnode.children[n];
|
uint32_t child_id = tnode.children[n];
|
||||||
const BVH_ABB &child_abb = _nodes[child_id].aabb;
|
const BVHABB_CLASS &child_abb = _nodes[child_id].aabb;
|
||||||
|
|
||||||
if (child_abb.intersects_segment(r_params.segment)) {
|
if (child_abb.intersects_segment(r_params.segment)) {
|
||||||
|
|
||||||
|
@ -339,7 +339,7 @@ bool _cull_aabb_iterative(uint32_t p_node_id, CullParams &r_params, bool p_fully
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for (int n = 0; n < leaf.num_items; n++) {
|
for (int n = 0; n < leaf.num_items; n++) {
|
||||||
const BVH_ABB &aabb = leaf.get_aabb(n);
|
const BVHABB_CLASS &aabb = leaf.get_aabb(n);
|
||||||
|
|
||||||
if (aabb.intersects(r_params.abb)) {
|
if (aabb.intersects(r_params.abb)) {
|
||||||
uint32_t child_id = leaf.get_item_ref_id(n);
|
uint32_t child_id = leaf.get_item_ref_id(n);
|
||||||
|
@ -355,7 +355,7 @@ bool _cull_aabb_iterative(uint32_t p_node_id, CullParams &r_params, bool p_fully
|
||||||
for (int n = 0; n < tnode.num_children; n++) {
|
for (int n = 0; n < tnode.num_children; n++) {
|
||||||
|
|
||||||
uint32_t child_id = tnode.children[n];
|
uint32_t child_id = tnode.children[n];
|
||||||
const BVH_ABB &child_abb = _nodes[child_id].aabb;
|
const BVHABB_CLASS &child_abb = _nodes[child_id].aabb;
|
||||||
|
|
||||||
if (child_abb.intersects(r_params.abb)) {
|
if (child_abb.intersects(r_params.abb)) {
|
||||||
// is the node totally within the aabb?
|
// is the node totally within the aabb?
|
||||||
|
@ -421,15 +421,15 @@ bool _cull_convex_iterative(uint32_t p_node_id, CullParams &r_params, bool p_ful
|
||||||
|
|
||||||
if (!ccp.fully_within) {
|
if (!ccp.fully_within) {
|
||||||
|
|
||||||
typename BVH_ABB::IntersectResult res = tnode.aabb.intersects_convex(r_params.hull);
|
typename BVHABB_CLASS::IntersectResult res = tnode.aabb.intersects_convex(r_params.hull);
|
||||||
|
|
||||||
switch (res) {
|
switch (res) {
|
||||||
default: {
|
default: {
|
||||||
continue; // miss, just move on to the next node in the stack
|
continue; // miss, just move on to the next node in the stack
|
||||||
} break;
|
} break;
|
||||||
case BVH_ABB::IR_PARTIAL: {
|
case BVHABB_CLASS::IR_PARTIAL: {
|
||||||
} break;
|
} break;
|
||||||
case BVH_ABB::IR_FULL: {
|
case BVHABB_CLASS::IR_FULL: {
|
||||||
ccp.fully_within = true;
|
ccp.fully_within = true;
|
||||||
} break;
|
} break;
|
||||||
}
|
}
|
||||||
|
@ -478,7 +478,7 @@ bool _cull_convex_iterative(uint32_t p_node_id, CullParams &r_params, bool p_ful
|
||||||
// test children individually
|
// test children individually
|
||||||
for (int n = 0; n < leaf.num_items; n++) {
|
for (int n = 0; n < leaf.num_items; n++) {
|
||||||
//const Item &item = leaf.get_item(n);
|
//const Item &item = leaf.get_item(n);
|
||||||
const BVH_ABB &aabb = leaf.get_aabb(n);
|
const BVHABB_CLASS &aabb = leaf.get_aabb(n);
|
||||||
|
|
||||||
if (aabb.intersects_convex_optimized(r_params.hull, plane_ids, num_planes)) {
|
if (aabb.intersects_convex_optimized(r_params.hull, plane_ids, num_planes)) {
|
||||||
uint32_t child_id = leaf.get_item_ref_id(n);
|
uint32_t child_id = leaf.get_item_ref_id(n);
|
||||||
|
@ -496,7 +496,7 @@ bool _cull_convex_iterative(uint32_t p_node_id, CullParams &r_params, bool p_ful
|
||||||
uint32_t test_count = 0;
|
uint32_t test_count = 0;
|
||||||
|
|
||||||
for (int n = 0; n < leaf.num_items; n++) {
|
for (int n = 0; n < leaf.num_items; n++) {
|
||||||
const BVH_ABB &aabb = leaf.get_aabb(n);
|
const BVHABB_CLASS &aabb = leaf.get_aabb(n);
|
||||||
|
|
||||||
if (aabb.intersects_convex_partial(r_params.hull)) {
|
if (aabb.intersects_convex_partial(r_params.hull)) {
|
||||||
uint32_t child_id = leaf.get_item_ref_id(n);
|
uint32_t child_id = leaf.get_item_ref_id(n);
|
||||||
|
@ -511,7 +511,7 @@ bool _cull_convex_iterative(uint32_t p_node_id, CullParams &r_params, bool p_ful
|
||||||
// not BVH_CONVEX_CULL_OPTIMIZED
|
// not BVH_CONVEX_CULL_OPTIMIZED
|
||||||
// test children individually
|
// test children individually
|
||||||
for (int n = 0; n < leaf.num_items; n++) {
|
for (int n = 0; n < leaf.num_items; n++) {
|
||||||
const BVH_ABB &aabb = leaf.get_aabb(n);
|
const BVHABB_CLASS &aabb = leaf.get_aabb(n);
|
||||||
|
|
||||||
if (aabb.intersects_convex_partial(r_params.hull)) {
|
if (aabb.intersects_convex_partial(r_params.hull)) {
|
||||||
uint32_t child_id = leaf.get_item_ref_id(n);
|
uint32_t child_id = leaf.get_item_ref_id(n);
|
||||||
|
|
|
@ -5,7 +5,7 @@ void _debug_recursive_print_tree(int p_tree_id) const {
|
||||||
_debug_recursive_print_tree_node(_root_node_id[p_tree_id]);
|
_debug_recursive_print_tree_node(_root_node_id[p_tree_id]);
|
||||||
}
|
}
|
||||||
|
|
||||||
String _debug_aabb_to_string(const BVH_ABB &aabb) const {
|
String _debug_aabb_to_string(const BVHABB_CLASS &aabb) const {
|
||||||
String sz = "(";
|
String sz = "(";
|
||||||
sz += itos(aabb.min.x);
|
sz += itos(aabb.min.x);
|
||||||
sz += " ~ ";
|
sz += " ~ ";
|
||||||
|
|
|
@ -12,10 +12,10 @@ void _integrity_check_all() {
|
||||||
void _integrity_check_up(uint32_t p_node_id) {
|
void _integrity_check_up(uint32_t p_node_id) {
|
||||||
TNode &node = _nodes[p_node_id];
|
TNode &node = _nodes[p_node_id];
|
||||||
|
|
||||||
BVH_ABB abb = node.aabb;
|
BVHABB_CLASS abb = node.aabb;
|
||||||
node_update_aabb(node);
|
node_update_aabb(node);
|
||||||
|
|
||||||
BVH_ABB abb2 = node.aabb;
|
BVHABB_CLASS abb2 = node.aabb;
|
||||||
abb2.expand(-_node_expansion);
|
abb2.expand(-_node_expansion);
|
||||||
|
|
||||||
CRASH_COND(!abb.is_other_within(abb2));
|
CRASH_COND(!abb.is_other_within(abb2));
|
||||||
|
|
|
@ -21,7 +21,7 @@ void _logic_item_remove_and_reinsert(uint32_t p_ref_id) {
|
||||||
_current_tree = _handle_get_tree_id(temp_handle);
|
_current_tree = _handle_get_tree_id(temp_handle);
|
||||||
|
|
||||||
// remove and reinsert
|
// remove and reinsert
|
||||||
BVH_ABB abb;
|
BVHABB_CLASS abb;
|
||||||
node_remove_item(p_ref_id, &abb);
|
node_remove_item(p_ref_id, &abb);
|
||||||
|
|
||||||
// we must choose where to add to tree
|
// we must choose where to add to tree
|
||||||
|
@ -32,8 +32,8 @@ void _logic_item_remove_and_reinsert(uint32_t p_ref_id) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// from randy gaul balance function
|
// from randy gaul balance function
|
||||||
BVH_ABB _logic_abb_merge(const BVH_ABB &a, const BVH_ABB &b) {
|
BVHABB_CLASS _logic_abb_merge(const BVHABB_CLASS &a, const BVHABB_CLASS &b) {
|
||||||
BVH_ABB c = a;
|
BVHABB_CLASS c = a;
|
||||||
c.merge(b);
|
c.merge(b);
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
|
@ -192,7 +192,7 @@ int32_t _logic_balance(int32_t iA) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// either choose an existing node to add item to, or create a new node and return this
|
// either choose an existing node to add item to, or create a new node and return this
|
||||||
uint32_t _logic_choose_item_add_node(uint32_t p_node_id, const BVH_ABB &p_aabb) {
|
uint32_t _logic_choose_item_add_node(uint32_t p_node_id, const BVHABB_CLASS &p_aabb) {
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
BVH_ASSERT(p_node_id != BVHCommon::INVALID);
|
BVH_ASSERT(p_node_id != BVHCommon::INVALID);
|
||||||
|
|
|
@ -14,10 +14,10 @@ struct ItemPairs {
|
||||||
void clear() {
|
void clear() {
|
||||||
num_pairs = 0;
|
num_pairs = 0;
|
||||||
extended_pairs.reset();
|
extended_pairs.reset();
|
||||||
expanded_aabb = AABB();
|
expanded_aabb = Bounds();
|
||||||
}
|
}
|
||||||
|
|
||||||
AABB expanded_aabb;
|
Bounds expanded_aabb;
|
||||||
|
|
||||||
// maybe we can just use the number in the vector TODO
|
// maybe we can just use the number in the vector TODO
|
||||||
int32_t num_pairs;
|
int32_t num_pairs;
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
public:
|
public:
|
||||||
BVHHandle item_add(T *p_userdata, bool p_active, const AABB &p_aabb, int32_t p_subindex, bool p_pairable, uint32_t p_pairable_type, uint32_t p_pairable_mask, bool p_invisible = false) {
|
BVHHandle item_add(T *p_userdata, bool p_active, const Bounds &p_aabb, int32_t p_subindex, bool p_pairable, uint32_t p_pairable_type, uint32_t p_pairable_mask, bool p_invisible = false) {
|
||||||
#ifdef BVH_VERBOSE_TREE
|
#ifdef BVH_VERBOSE_TREE
|
||||||
VERBOSE_PRINT("\nitem_add BEFORE");
|
VERBOSE_PRINT("\nitem_add BEFORE");
|
||||||
_debug_recursive_print_tree(0);
|
_debug_recursive_print_tree(0);
|
||||||
VERBOSE_PRINT("\n");
|
VERBOSE_PRINT("\n");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
BVH_ABB abb;
|
BVHABB_CLASS abb;
|
||||||
abb.from(p_aabb);
|
abb.from(p_aabb);
|
||||||
|
|
||||||
// handle to be filled with the new item ref
|
// handle to be filled with the new item ref
|
||||||
|
@ -101,7 +101,7 @@ void _debug_print_refs() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// returns false if noop
|
// returns false if noop
|
||||||
bool item_move(BVHHandle p_handle, const AABB &p_aabb) {
|
bool item_move(BVHHandle p_handle, const Bounds &p_aabb) {
|
||||||
uint32_t ref_id = p_handle.id();
|
uint32_t ref_id = p_handle.id();
|
||||||
|
|
||||||
// get the reference
|
// get the reference
|
||||||
|
@ -110,7 +110,7 @@ bool item_move(BVHHandle p_handle, const AABB &p_aabb) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
BVH_ABB abb;
|
BVHABB_CLASS abb;
|
||||||
abb.from(p_aabb);
|
abb.from(p_aabb);
|
||||||
|
|
||||||
BVH_ASSERT(ref.tnode_id != BVHCommon::INVALID);
|
BVH_ASSERT(ref.tnode_id != BVHCommon::INVALID);
|
||||||
|
@ -124,7 +124,7 @@ bool item_move(BVHHandle p_handle, const AABB &p_aabb) {
|
||||||
// for accurate collision detection
|
// for accurate collision detection
|
||||||
TLeaf &leaf = _node_get_leaf(tnode);
|
TLeaf &leaf = _node_get_leaf(tnode);
|
||||||
|
|
||||||
BVH_ABB &leaf_abb = leaf.get_aabb(ref.item_id);
|
BVHABB_CLASS &leaf_abb = leaf.get_aabb(ref.item_id);
|
||||||
|
|
||||||
// no change?
|
// no change?
|
||||||
if (leaf_abb == abb) {
|
if (leaf_abb == abb) {
|
||||||
|
@ -203,7 +203,7 @@ void item_remove(BVHHandle p_handle) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// returns success
|
// returns success
|
||||||
bool item_activate(BVHHandle p_handle, const AABB &p_aabb) {
|
bool item_activate(BVHHandle p_handle, const Bounds &p_aabb) {
|
||||||
uint32_t ref_id = p_handle.id();
|
uint32_t ref_id = p_handle.id();
|
||||||
ItemRef &ref = _refs[ref_id];
|
ItemRef &ref = _refs[ref_id];
|
||||||
if (ref.is_active()) {
|
if (ref.is_active()) {
|
||||||
|
@ -212,7 +212,7 @@ bool item_activate(BVHHandle p_handle, const AABB &p_aabb) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// add to tree
|
// add to tree
|
||||||
BVH_ABB abb;
|
BVHABB_CLASS abb;
|
||||||
abb.from(p_aabb);
|
abb.from(p_aabb);
|
||||||
|
|
||||||
_current_tree = _handle_get_tree_id(p_handle);
|
_current_tree = _handle_get_tree_id(p_handle);
|
||||||
|
@ -236,7 +236,7 @@ bool item_deactivate(BVHHandle p_handle) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// remove from tree
|
// remove from tree
|
||||||
BVH_ABB abb;
|
BVHABB_CLASS abb;
|
||||||
node_remove_item(ref_id, &abb);
|
node_remove_item(ref_id, &abb);
|
||||||
|
|
||||||
// mark as inactive
|
// mark as inactive
|
||||||
|
@ -269,7 +269,7 @@ bool item_is_pairable(const BVHHandle &p_handle) {
|
||||||
return extra.pairable != 0;
|
return extra.pairable != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void item_get_ABB(const BVHHandle &p_handle, BVH_ABB &r_abb) {
|
void item_get_ABB(const BVHHandle &p_handle, BVHABB_CLASS &r_abb) {
|
||||||
// change tree?
|
// change tree?
|
||||||
uint32_t ref_id = p_handle.id();
|
uint32_t ref_id = p_handle.id();
|
||||||
const ItemRef &ref = _refs[ref_id];
|
const ItemRef &ref = _refs[ref_id];
|
||||||
|
@ -297,7 +297,7 @@ void item_set_pairable(const BVHHandle &p_handle, bool p_pairable, uint32_t p_pa
|
||||||
// record abb
|
// record abb
|
||||||
TNode &tnode = _nodes[ref.tnode_id];
|
TNode &tnode = _nodes[ref.tnode_id];
|
||||||
TLeaf &leaf = _node_get_leaf(tnode);
|
TLeaf &leaf = _node_get_leaf(tnode);
|
||||||
BVH_ABB abb = leaf.get_aabb(ref.item_id);
|
BVHABB_CLASS abb = leaf.get_aabb(ref.item_id);
|
||||||
|
|
||||||
// make sure current tree is correct prior to changing
|
// make sure current tree is correct prior to changing
|
||||||
_current_tree = _handle_get_tree_id(p_handle);
|
_current_tree = _handle_get_tree_id(p_handle);
|
||||||
|
@ -377,7 +377,7 @@ void update() {
|
||||||
//#define BVH_ALLOW_AUTO_EXPANSION
|
//#define BVH_ALLOW_AUTO_EXPANSION
|
||||||
#ifdef BVH_ALLOW_AUTO_EXPANSION
|
#ifdef BVH_ALLOW_AUTO_EXPANSION
|
||||||
if (_auto_node_expansion || _auto_pairing_expansion) {
|
if (_auto_node_expansion || _auto_pairing_expansion) {
|
||||||
BVH_ABB world_bound;
|
BVHABB_CLASS world_bound;
|
||||||
world_bound.set_to_max_opposite_extents();
|
world_bound.set_to_max_opposite_extents();
|
||||||
|
|
||||||
bool bound_valid = false;
|
bool bound_valid = false;
|
||||||
|
@ -392,7 +392,7 @@ void update() {
|
||||||
|
|
||||||
// if there are no nodes, do nothing, but if there are...
|
// if there are no nodes, do nothing, but if there are...
|
||||||
if (bound_valid) {
|
if (bound_valid) {
|
||||||
AABB bb;
|
Bounds bb;
|
||||||
world_bound.to(bb);
|
world_bound.to(bb);
|
||||||
real_t size = bb.get_longest_axis_size();
|
real_t size = bb.get_longest_axis_size();
|
||||||
|
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
void _debug_node_verify_bound(uint32_t p_node_id) {
|
void _debug_node_verify_bound(uint32_t p_node_id) {
|
||||||
TNode &node = _nodes[p_node_id];
|
TNode &node = _nodes[p_node_id];
|
||||||
BVH_ABB abb_before = node.aabb;
|
BVHABB_CLASS abb_before = node.aabb;
|
||||||
|
|
||||||
node_update_aabb(node);
|
node_update_aabb(node);
|
||||||
|
|
||||||
BVH_ABB abb_after = node.aabb;
|
BVHABB_CLASS abb_after = node.aabb;
|
||||||
CRASH_COND(abb_before != abb_after);
|
CRASH_COND(abb_before != abb_after);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -11,7 +11,7 @@ void _split_inform_references(uint32_t p_node_id) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void _split_leaf_sort_groups_simple(int &num_a, int &num_b, uint16_t *group_a, uint16_t *group_b, const BVH_ABB *temp_bounds, const BVH_ABB full_bound) {
|
void _split_leaf_sort_groups_simple(int &num_a, int &num_b, uint16_t *group_a, uint16_t *group_b, const BVHABB_CLASS *temp_bounds, const BVHABB_CLASS full_bound) {
|
||||||
// special case for low leaf sizes .. should static compile out
|
// special case for low leaf sizes .. should static compile out
|
||||||
if (MAX_ITEMS < 4) {
|
if (MAX_ITEMS < 4) {
|
||||||
uint32_t ind = group_a[0];
|
uint32_t ind = group_a[0];
|
||||||
|
@ -25,8 +25,8 @@ void _split_leaf_sort_groups_simple(int &num_a, int &num_b, uint16_t *group_a, u
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Vector3 centre = full_bound.calculate_centre();
|
Point centre = full_bound.calculate_centre();
|
||||||
Vector3 size = full_bound.calculate_size();
|
Point size = full_bound.calculate_size();
|
||||||
|
|
||||||
int order[3];
|
int order[3];
|
||||||
|
|
||||||
|
@ -135,16 +135,16 @@ void _split_leaf_sort_groups_simple(int &num_a, int &num_b, uint16_t *group_a, u
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void _split_leaf_sort_groups(int &num_a, int &num_b, uint16_t *group_a, uint16_t *group_b, const BVH_ABB *temp_bounds) {
|
void _split_leaf_sort_groups(int &num_a, int &num_b, uint16_t *group_a, uint16_t *group_b, const BVHABB_CLASS *temp_bounds) {
|
||||||
BVH_ABB groupb_aabb;
|
BVHABB_CLASS groupb_aabb;
|
||||||
groupb_aabb.set_to_max_opposite_extents();
|
groupb_aabb.set_to_max_opposite_extents();
|
||||||
for (int n = 0; n < num_b; n++) {
|
for (int n = 0; n < num_b; n++) {
|
||||||
int which = group_b[n];
|
int which = group_b[n];
|
||||||
groupb_aabb.merge(temp_bounds[which]);
|
groupb_aabb.merge(temp_bounds[which]);
|
||||||
}
|
}
|
||||||
BVH_ABB groupb_aabb_new;
|
BVHABB_CLASS groupb_aabb_new;
|
||||||
|
|
||||||
BVH_ABB rest_aabb;
|
BVHABB_CLASS rest_aabb;
|
||||||
|
|
||||||
float best_size = FLT_MAX;
|
float best_size = FLT_MAX;
|
||||||
int best_candidate = -1;
|
int best_candidate = -1;
|
||||||
|
@ -181,12 +181,12 @@ void _split_leaf_sort_groups(int &num_a, int &num_b, uint16_t *group_a, uint16_t
|
||||||
group_a[best_candidate] = group_a[num_a];
|
group_a[best_candidate] = group_a[num_a];
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t split_leaf(uint32_t p_node_id, const BVH_ABB &p_added_item_aabb) {
|
uint32_t split_leaf(uint32_t p_node_id, const BVHABB_CLASS &p_added_item_aabb) {
|
||||||
return split_leaf_complex(p_node_id, p_added_item_aabb);
|
return split_leaf_complex(p_node_id, p_added_item_aabb);
|
||||||
}
|
}
|
||||||
|
|
||||||
// aabb is the new inserted node
|
// aabb is the new inserted node
|
||||||
uint32_t split_leaf_complex(uint32_t p_node_id, const BVH_ABB &p_added_item_aabb) {
|
uint32_t split_leaf_complex(uint32_t p_node_id, const BVHABB_CLASS &p_added_item_aabb) {
|
||||||
VERBOSE_PRINT("split_leaf");
|
VERBOSE_PRINT("split_leaf");
|
||||||
|
|
||||||
// note the tnode before and AFTER splitting may be a different address
|
// note the tnode before and AFTER splitting may be a different address
|
||||||
|
@ -231,7 +231,7 @@ uint32_t split_leaf_complex(uint32_t p_node_id, const BVH_ABB &p_added_item_aabb
|
||||||
uint16_t *group_b = (uint16_t *)alloca(sizeof(uint16_t) * max_children);
|
uint16_t *group_b = (uint16_t *)alloca(sizeof(uint16_t) * max_children);
|
||||||
|
|
||||||
// we are copying the ABBs. This is ugly, but we need one extra for the inserted item...
|
// we are copying the ABBs. This is ugly, but we need one extra for the inserted item...
|
||||||
BVH_ABB *temp_bounds = (BVH_ABB *)alloca(sizeof(BVH_ABB) * max_children);
|
BVHABB_CLASS *temp_bounds = (BVHABB_CLASS *)alloca(sizeof(BVHABB_CLASS) * max_children);
|
||||||
|
|
||||||
int num_a = max_children;
|
int num_a = max_children;
|
||||||
int num_b = 0;
|
int num_b = 0;
|
||||||
|
@ -257,7 +257,7 @@ uint32_t split_leaf_complex(uint32_t p_node_id, const BVH_ABB &p_added_item_aabb
|
||||||
int which = group_a[n];
|
int which = group_a[n];
|
||||||
|
|
||||||
if (which != wildcard) {
|
if (which != wildcard) {
|
||||||
const BVH_ABB &source_item_aabb = orig_leaf.get_aabb(which);
|
const BVHABB_CLASS &source_item_aabb = orig_leaf.get_aabb(which);
|
||||||
uint32_t source_item_ref_id = orig_leaf.get_item_ref_id(which);
|
uint32_t source_item_ref_id = orig_leaf.get_item_ref_id(which);
|
||||||
//const Item &source_item = orig_leaf.get_item(which);
|
//const Item &source_item = orig_leaf.get_item(which);
|
||||||
_node_add_item(tnode.children[0], source_item_ref_id, source_item_aabb);
|
_node_add_item(tnode.children[0], source_item_ref_id, source_item_aabb);
|
||||||
|
@ -269,7 +269,7 @@ uint32_t split_leaf_complex(uint32_t p_node_id, const BVH_ABB &p_added_item_aabb
|
||||||
int which = group_b[n];
|
int which = group_b[n];
|
||||||
|
|
||||||
if (which != wildcard) {
|
if (which != wildcard) {
|
||||||
const BVH_ABB &source_item_aabb = orig_leaf.get_aabb(which);
|
const BVHABB_CLASS &source_item_aabb = orig_leaf.get_aabb(which);
|
||||||
uint32_t source_item_ref_id = orig_leaf.get_item_ref_id(which);
|
uint32_t source_item_ref_id = orig_leaf.get_item_ref_id(which);
|
||||||
//const Item &source_item = orig_leaf.get_item(which);
|
//const Item &source_item = orig_leaf.get_item(which);
|
||||||
_node_add_item(tnode.children[1], source_item_ref_id, source_item_aabb);
|
_node_add_item(tnode.children[1], source_item_ref_id, source_item_aabb);
|
||||||
|
|
|
@ -31,7 +31,7 @@ struct ItemExtra {
|
||||||
|
|
||||||
// this is an item OR a child node depending on whether a leaf node
|
// this is an item OR a child node depending on whether a leaf node
|
||||||
struct Item {
|
struct Item {
|
||||||
BVH_ABB aabb;
|
BVHABB_CLASS aabb;
|
||||||
uint32_t item_ref_id;
|
uint32_t item_ref_id;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -43,12 +43,12 @@ private:
|
||||||
uint16_t dirty;
|
uint16_t dirty;
|
||||||
// separate data orientated lists for faster SIMD traversal
|
// separate data orientated lists for faster SIMD traversal
|
||||||
uint32_t item_ref_ids[MAX_ITEMS];
|
uint32_t item_ref_ids[MAX_ITEMS];
|
||||||
BVH_ABB aabbs[MAX_ITEMS];
|
BVHABB_CLASS aabbs[MAX_ITEMS];
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// accessors
|
// accessors
|
||||||
BVH_ABB &get_aabb(uint32_t p_id) { return aabbs[p_id]; }
|
BVHABB_CLASS &get_aabb(uint32_t p_id) { return aabbs[p_id]; }
|
||||||
const BVH_ABB &get_aabb(uint32_t p_id) const { return aabbs[p_id]; }
|
const BVHABB_CLASS &get_aabb(uint32_t p_id) const { return aabbs[p_id]; }
|
||||||
|
|
||||||
uint32_t &get_item_ref_id(uint32_t p_id) { return item_ref_ids[p_id]; }
|
uint32_t &get_item_ref_id(uint32_t p_id) { return item_ref_ids[p_id]; }
|
||||||
const uint32_t &get_item_ref_id(uint32_t p_id) const { return item_ref_ids[p_id]; }
|
const uint32_t &get_item_ref_id(uint32_t p_id) const { return item_ref_ids[p_id]; }
|
||||||
|
@ -81,7 +81,7 @@ public:
|
||||||
|
|
||||||
// tree node
|
// tree node
|
||||||
struct TNode {
|
struct TNode {
|
||||||
BVH_ABB aabb;
|
BVHABB_CLASS aabb;
|
||||||
// either number of children if positive
|
// either number of children if positive
|
||||||
// or leaf id if negative (leaf id 0 is disallowed)
|
// or leaf id if negative (leaf id 0 is disallowed)
|
||||||
union {
|
union {
|
||||||
|
|
|
@ -48,6 +48,8 @@
|
||||||
#include "core/print_string.h"
|
#include "core/print_string.h"
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
|
|
||||||
|
#define BVHABB_CLASS BVH_ABB<Bounds, Point>
|
||||||
|
|
||||||
// never do these checks in release
|
// never do these checks in release
|
||||||
#if defined(TOOLS_ENABLED) && defined(DEBUG_ENABLED)
|
#if defined(TOOLS_ENABLED) && defined(DEBUG_ENABLED)
|
||||||
//#define BVH_VERBOSE
|
//#define BVH_VERBOSE
|
||||||
|
@ -146,7 +148,7 @@ public:
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template <class T, int MAX_CHILDREN, int MAX_ITEMS, bool USE_PAIRS = false>
|
template <class T, int MAX_CHILDREN, int MAX_ITEMS, bool USE_PAIRS = false, class Bounds = AABB, class Point = Vector3>
|
||||||
class BVH_Tree {
|
class BVH_Tree {
|
||||||
friend class BVH;
|
friend class BVH;
|
||||||
|
|
||||||
|
@ -269,7 +271,7 @@ private:
|
||||||
node.neg_leaf_id = -(int)child_leaf_id;
|
node.neg_leaf_id = -(int)child_leaf_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
void node_remove_item(uint32_t p_ref_id, BVH_ABB *r_old_aabb = nullptr) {
|
void node_remove_item(uint32_t p_ref_id, BVHABB_CLASS *r_old_aabb = nullptr) {
|
||||||
// get the reference
|
// get the reference
|
||||||
ItemRef &ref = _refs[p_ref_id];
|
ItemRef &ref = _refs[p_ref_id];
|
||||||
uint32_t owner_node_id = ref.tnode_id;
|
uint32_t owner_node_id = ref.tnode_id;
|
||||||
|
@ -286,7 +288,7 @@ private:
|
||||||
|
|
||||||
// if the aabb is not determining the corner size, then there is no need to refit!
|
// if the aabb is not determining the corner size, then there is no need to refit!
|
||||||
// (optimization, as merging AABBs takes a lot of time)
|
// (optimization, as merging AABBs takes a lot of time)
|
||||||
const BVH_ABB &old_aabb = leaf.get_aabb(ref.item_id);
|
const BVHABB_CLASS &old_aabb = leaf.get_aabb(ref.item_id);
|
||||||
|
|
||||||
// shrink a little to prevent using corner aabbs
|
// shrink a little to prevent using corner aabbs
|
||||||
// in order to miss the corners first we shrink by node_expansion
|
// in order to miss the corners first we shrink by node_expansion
|
||||||
|
@ -294,7 +296,7 @@ private:
|
||||||
// shrink by an epsilon, in order to miss out the very corner aabbs
|
// shrink by an epsilon, in order to miss out the very corner aabbs
|
||||||
// which are important in determining the bound. Any other aabb
|
// which are important in determining the bound. Any other aabb
|
||||||
// within this can be removed and not affect the overall bound.
|
// within this can be removed and not affect the overall bound.
|
||||||
BVH_ABB node_bound = tnode.aabb;
|
BVHABB_CLASS node_bound = tnode.aabb;
|
||||||
node_bound.expand(-_node_expansion - 0.001f);
|
node_bound.expand(-_node_expansion - 0.001f);
|
||||||
bool refit = true;
|
bool refit = true;
|
||||||
|
|
||||||
|
@ -348,7 +350,7 @@ private:
|
||||||
|
|
||||||
// returns true if needs refit of PARENT tree only, the node itself AABB is calculated
|
// returns true if needs refit of PARENT tree only, the node itself AABB is calculated
|
||||||
// within this routine
|
// within this routine
|
||||||
bool _node_add_item(uint32_t p_node_id, uint32_t p_ref_id, const BVH_ABB &p_aabb) {
|
bool _node_add_item(uint32_t p_node_id, uint32_t p_ref_id, const BVHABB_CLASS &p_aabb) {
|
||||||
ItemRef &ref = _refs[p_ref_id];
|
ItemRef &ref = _refs[p_ref_id];
|
||||||
ref.tnode_id = p_node_id;
|
ref.tnode_id = p_node_id;
|
||||||
|
|
||||||
|
@ -362,7 +364,7 @@ private:
|
||||||
bool needs_refit = true;
|
bool needs_refit = true;
|
||||||
|
|
||||||
// expand bound now
|
// expand bound now
|
||||||
BVH_ABB expanded = p_aabb;
|
BVHABB_CLASS expanded = p_aabb;
|
||||||
expanded.expand(_node_expansion);
|
expanded.expand(_node_expansion);
|
||||||
|
|
||||||
// the bound will only be valid if there is an item in there already
|
// the bound will only be valid if there is an item in there already
|
||||||
|
@ -390,7 +392,7 @@ private:
|
||||||
return needs_refit;
|
return needs_refit;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t _node_create_another_child(uint32_t p_node_id, const BVH_ABB &p_aabb) {
|
uint32_t _node_create_another_child(uint32_t p_node_id, const BVHABB_CLASS &p_aabb) {
|
||||||
uint32_t child_node_id;
|
uint32_t child_node_id;
|
||||||
TNode *child_node = _nodes.request(child_node_id);
|
TNode *child_node = _nodes.request(child_node_id);
|
||||||
child_node->clear();
|
child_node->clear();
|
||||||
|
|
|
@ -170,15 +170,18 @@ struct Rect2 {
|
||||||
bool operator!=(const Rect2 &p_rect) const { return position != p_rect.position || size != p_rect.size; }
|
bool operator!=(const Rect2 &p_rect) const { return position != p_rect.position || size != p_rect.size; }
|
||||||
|
|
||||||
inline Rect2 grow(real_t p_by) const {
|
inline Rect2 grow(real_t p_by) const {
|
||||||
|
|
||||||
Rect2 g = *this;
|
Rect2 g = *this;
|
||||||
g.position.x -= p_by;
|
g.grow_by(p_by);
|
||||||
g.position.y -= p_by;
|
|
||||||
g.size.width += p_by * 2;
|
|
||||||
g.size.height += p_by * 2;
|
|
||||||
return g;
|
return g;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline void grow_by(real_t p_by) {
|
||||||
|
position.x -= p_by;
|
||||||
|
position.y -= p_by;
|
||||||
|
size.width += p_by * 2;
|
||||||
|
size.height += p_by * 2;
|
||||||
|
}
|
||||||
|
|
||||||
inline Rect2 grow_margin(Margin p_margin, real_t p_amount) const {
|
inline Rect2 grow_margin(Margin p_margin, real_t p_amount) const {
|
||||||
Rect2 g = *this;
|
Rect2 g = *this;
|
||||||
g = g.grow_individual((MARGIN_LEFT == p_margin) ? p_amount : 0,
|
g = g.grow_individual((MARGIN_LEFT == p_margin) ? p_amount : 0,
|
||||||
|
|
|
@ -37,6 +37,7 @@
|
||||||
struct Vector2i;
|
struct Vector2i;
|
||||||
|
|
||||||
struct Vector2 {
|
struct Vector2 {
|
||||||
|
static const int AXIS_COUNT = 2;
|
||||||
|
|
||||||
enum Axis {
|
enum Axis {
|
||||||
AXIS_X,
|
AXIS_X,
|
||||||
|
@ -44,12 +45,18 @@ struct Vector2 {
|
||||||
};
|
};
|
||||||
|
|
||||||
union {
|
union {
|
||||||
real_t x;
|
struct {
|
||||||
real_t width;
|
union {
|
||||||
};
|
real_t x;
|
||||||
union {
|
real_t width;
|
||||||
real_t y;
|
};
|
||||||
real_t height;
|
union {
|
||||||
|
real_t y;
|
||||||
|
real_t height;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
real_t coord[2];
|
||||||
};
|
};
|
||||||
|
|
||||||
_FORCE_INLINE_ real_t &operator[](int p_idx) {
|
_FORCE_INLINE_ real_t &operator[](int p_idx) {
|
||||||
|
@ -59,6 +66,18 @@ struct Vector2 {
|
||||||
return p_idx ? y : x;
|
return p_idx ? y : x;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_FORCE_INLINE_ void set_all(real_t p_value) {
|
||||||
|
x = y = p_value;
|
||||||
|
}
|
||||||
|
|
||||||
|
_FORCE_INLINE_ int min_axis() const {
|
||||||
|
return x < y ? 0 : 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
_FORCE_INLINE_ int max_axis() const {
|
||||||
|
return x < y ? 1 : 0;
|
||||||
|
}
|
||||||
|
|
||||||
void normalize();
|
void normalize();
|
||||||
Vector2 normalized() const;
|
Vector2 normalized() const;
|
||||||
bool is_normalized() const;
|
bool is_normalized() const;
|
||||||
|
|
|
@ -54,15 +54,6 @@ real_t Vector3::get_axis(int p_axis) const {
|
||||||
return operator[](p_axis);
|
return operator[](p_axis);
|
||||||
}
|
}
|
||||||
|
|
||||||
int Vector3::min_axis() const {
|
|
||||||
|
|
||||||
return x < y ? (x < z ? 0 : 2) : (y < z ? 1 : 2);
|
|
||||||
}
|
|
||||||
int Vector3::max_axis() const {
|
|
||||||
|
|
||||||
return x < y ? (y < z ? 2 : 1) : (x < z ? 2 : 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Vector3::snap(Vector3 p_val) {
|
void Vector3::snap(Vector3 p_val) {
|
||||||
|
|
||||||
x = Math::stepify(x, p_val.x);
|
x = Math::stepify(x, p_val.x);
|
||||||
|
|
|
@ -37,6 +37,7 @@
|
||||||
class Basis;
|
class Basis;
|
||||||
|
|
||||||
struct Vector3 {
|
struct Vector3 {
|
||||||
|
static const int AXIS_COUNT = 3;
|
||||||
|
|
||||||
enum Axis {
|
enum Axis {
|
||||||
AXIS_X,
|
AXIS_X,
|
||||||
|
@ -67,8 +68,17 @@ struct Vector3 {
|
||||||
void set_axis(int p_axis, real_t p_value);
|
void set_axis(int p_axis, real_t p_value);
|
||||||
real_t get_axis(int p_axis) const;
|
real_t get_axis(int p_axis) const;
|
||||||
|
|
||||||
int min_axis() const;
|
_FORCE_INLINE_ void set_all(real_t p_value) {
|
||||||
int max_axis() const;
|
x = y = z = p_value;
|
||||||
|
}
|
||||||
|
|
||||||
|
_FORCE_INLINE_ int min_axis() const {
|
||||||
|
return x < y ? (x < z ? 0 : 2) : (y < z ? 1 : 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
_FORCE_INLINE_ int max_axis() const {
|
||||||
|
return x < y ? (y < z ? 2 : 1) : (x < z ? 2 : 0);
|
||||||
|
}
|
||||||
|
|
||||||
_FORCE_INLINE_ real_t length() const;
|
_FORCE_INLINE_ real_t length() const;
|
||||||
_FORCE_INLINE_ real_t length_squared() const;
|
_FORCE_INLINE_ real_t length_squared() const;
|
||||||
|
|
|
@ -936,9 +936,11 @@
|
||||||
</member>
|
</member>
|
||||||
<member name="physics/2d/bp_hash_table_size" type="int" setter="" getter="" default="4096">
|
<member name="physics/2d/bp_hash_table_size" type="int" setter="" getter="" default="4096">
|
||||||
Size of the hash table used for the broad-phase 2D hash grid algorithm.
|
Size of the hash table used for the broad-phase 2D hash grid algorithm.
|
||||||
|
[b]Note:[/b] Not used if [member ProjectSettings.physics/2d/use_bvh] is enabled.
|
||||||
</member>
|
</member>
|
||||||
<member name="physics/2d/cell_size" type="int" setter="" getter="" default="128">
|
<member name="physics/2d/cell_size" type="int" setter="" getter="" default="128">
|
||||||
Cell size used for the broad-phase 2D hash grid algorithm (in pixels).
|
Cell size used for the broad-phase 2D hash grid algorithm (in pixels).
|
||||||
|
[b]Note:[/b] Not used if [member ProjectSettings.physics/2d/use_bvh] is enabled.
|
||||||
</member>
|
</member>
|
||||||
<member name="physics/2d/default_angular_damp" type="float" setter="" getter="" default="1.0">
|
<member name="physics/2d/default_angular_damp" type="float" setter="" getter="" default="1.0">
|
||||||
The default angular damp in 2D.
|
The default angular damp in 2D.
|
||||||
|
@ -966,6 +968,7 @@
|
||||||
</member>
|
</member>
|
||||||
<member name="physics/2d/large_object_surface_threshold_in_cells" type="int" setter="" getter="" default="512">
|
<member name="physics/2d/large_object_surface_threshold_in_cells" type="int" setter="" getter="" default="512">
|
||||||
Threshold defining the surface size that constitutes a large object with regard to cells in the broad-phase 2D hash grid algorithm.
|
Threshold defining the surface size that constitutes a large object with regard to cells in the broad-phase 2D hash grid algorithm.
|
||||||
|
[b]Note:[/b] Not used if [member ProjectSettings.physics/2d/use_bvh] is enabled.
|
||||||
</member>
|
</member>
|
||||||
<member name="physics/2d/physics_engine" type="String" setter="" getter="" default=""DEFAULT"">
|
<member name="physics/2d/physics_engine" type="String" setter="" getter="" default=""DEFAULT"">
|
||||||
Sets which physics engine to use for 2D physics.
|
Sets which physics engine to use for 2D physics.
|
||||||
|
@ -984,6 +987,9 @@
|
||||||
<member name="physics/2d/time_before_sleep" type="float" setter="" getter="" default="0.5">
|
<member name="physics/2d/time_before_sleep" type="float" setter="" getter="" default="0.5">
|
||||||
Time (in seconds) of inactivity before which a 2D physics body will put to sleep. See [constant Physics2DServer.SPACE_PARAM_BODY_TIME_TO_SLEEP].
|
Time (in seconds) of inactivity before which a 2D physics body will put to sleep. See [constant Physics2DServer.SPACE_PARAM_BODY_TIME_TO_SLEEP].
|
||||||
</member>
|
</member>
|
||||||
|
<member name="physics/2d/use_bvh" type="bool" setter="" getter="" default="true">
|
||||||
|
Enables the use of bounding volume hierarchy instead of hash grid for 2D physics spatial partitioning. This may give better performance.
|
||||||
|
</member>
|
||||||
<member name="physics/3d/active_soft_world" type="bool" setter="" getter="" default="true">
|
<member name="physics/3d/active_soft_world" type="bool" setter="" getter="" default="true">
|
||||||
Sets whether the 3D physics world will be created with support for [SoftBody] physics. Only applies to the Bullet physics engine.
|
Sets whether the 3D physics world will be created with support for [SoftBody] physics. Only applies to the Bullet physics engine.
|
||||||
</member>
|
</member>
|
||||||
|
@ -1012,7 +1018,7 @@
|
||||||
[b]Note:[/b] Good values are in the range [code]0[/code] to [code]1[/code]. At value [code]0[/code] objects will keep moving with the same velocity. Values greater than [code]1[/code] will aim to reduce the velocity to [code]0[/code] in less than a second e.g. a value of [code]2[/code] will aim to reduce the velocity to [code]0[/code] in half a second. A value equal to or greater than the physics frame rate ([member ProjectSettings.physics/common/physics_fps], [code]60[/code] by default) will bring the object to a stop in one iteration.
|
[b]Note:[/b] Good values are in the range [code]0[/code] to [code]1[/code]. At value [code]0[/code] objects will keep moving with the same velocity. Values greater than [code]1[/code] will aim to reduce the velocity to [code]0[/code] in less than a second e.g. a value of [code]2[/code] will aim to reduce the velocity to [code]0[/code] in half a second. A value equal to or greater than the physics frame rate ([member ProjectSettings.physics/common/physics_fps], [code]60[/code] by default) will bring the object to a stop in one iteration.
|
||||||
</member>
|
</member>
|
||||||
<member name="physics/3d/godot_physics/use_bvh" type="bool" setter="" getter="" default="true">
|
<member name="physics/3d/godot_physics/use_bvh" type="bool" setter="" getter="" default="true">
|
||||||
Enables the use of bounding volume hierarchy instead of octree for physics spatial partitioning. This may give better performance.
|
Enables the use of bounding volume hierarchy instead of octree for 3D physics spatial partitioning. This may give better performance.
|
||||||
</member>
|
</member>
|
||||||
<member name="physics/3d/physics_engine" type="String" setter="" getter="" default=""DEFAULT"">
|
<member name="physics/3d/physics_engine" type="String" setter="" getter="" default=""DEFAULT"">
|
||||||
Sets which physics engine to use for 3D physics.
|
Sets which physics engine to use for 3D physics.
|
||||||
|
|
|
@ -30,7 +30,7 @@
|
||||||
|
|
||||||
#include "broad_phase_2d_basic.h"
|
#include "broad_phase_2d_basic.h"
|
||||||
|
|
||||||
BroadPhase2DBasic::ID BroadPhase2DBasic::create(CollisionObject2DSW *p_object_, int p_subindex) {
|
BroadPhase2DBasic::ID BroadPhase2DBasic::create(CollisionObject2DSW *p_object_, int p_subindex, const Rect2 &p_aabb, bool p_static) {
|
||||||
|
|
||||||
current++;
|
current++;
|
||||||
|
|
||||||
|
|
|
@ -82,7 +82,7 @@ class BroadPhase2DBasic : public BroadPhase2DSW {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// 0 is an invalid ID
|
// 0 is an invalid ID
|
||||||
virtual ID create(CollisionObject2DSW *p_object_, int p_subindex = 0);
|
virtual ID create(CollisionObject2DSW *p_object_, int p_subindex = 0, const Rect2 &p_aabb = Rect2(), bool p_static = false);
|
||||||
virtual void move(ID p_id, const Rect2 &p_aabb);
|
virtual void move(ID p_id, const Rect2 &p_aabb);
|
||||||
virtual void set_static(ID p_id, bool p_static);
|
virtual void set_static(ID p_id, bool p_static);
|
||||||
virtual void remove(ID p_id);
|
virtual void remove(ID p_id);
|
||||||
|
|
|
@ -0,0 +1,126 @@
|
||||||
|
/*************************************************************************/
|
||||||
|
/* broad_phase_2d_bvh.cpp */
|
||||||
|
/*************************************************************************/
|
||||||
|
/* This file is part of: */
|
||||||
|
/* GODOT ENGINE */
|
||||||
|
/* https://godotengine.org */
|
||||||
|
/*************************************************************************/
|
||||||
|
/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
|
||||||
|
/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
|
||||||
|
/* */
|
||||||
|
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||||
|
/* a copy of this software and associated documentation files (the */
|
||||||
|
/* "Software"), to deal in the Software without restriction, including */
|
||||||
|
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||||
|
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||||
|
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||||
|
/* the following conditions: */
|
||||||
|
/* */
|
||||||
|
/* The above copyright notice and this permission notice shall be */
|
||||||
|
/* included in all copies or substantial portions of the Software. */
|
||||||
|
/* */
|
||||||
|
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||||
|
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||||
|
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||||
|
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||||
|
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||||
|
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||||
|
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||||
|
/*************************************************************************/
|
||||||
|
|
||||||
|
#include "broad_phase_2d_bvh.h"
|
||||||
|
#include "collision_object_2d_sw.h"
|
||||||
|
#include "core/project_settings.h"
|
||||||
|
|
||||||
|
BroadPhase2DSW::ID BroadPhase2DBVH::create(CollisionObject2DSW *p_object, int p_subindex, const Rect2 &p_aabb, bool p_static) {
|
||||||
|
|
||||||
|
ID oid = bvh.create(p_object, true, p_aabb, p_subindex, !p_static, 1 << p_object->get_type(), p_static ? 0 : 0xFFFFF); // Pair everything, don't care?
|
||||||
|
return oid + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void BroadPhase2DBVH::move(ID p_id, const Rect2 &p_aabb) {
|
||||||
|
|
||||||
|
bvh.move(p_id - 1, p_aabb);
|
||||||
|
}
|
||||||
|
|
||||||
|
void BroadPhase2DBVH::set_static(ID p_id, bool p_static) {
|
||||||
|
|
||||||
|
CollisionObject2DSW *it = bvh.get(p_id - 1);
|
||||||
|
bvh.set_pairable(p_id - 1, !p_static, 1 << it->get_type(), p_static ? 0 : 0xFFFFF); // Pair everything, don't care?
|
||||||
|
}
|
||||||
|
void BroadPhase2DBVH::remove(ID p_id) {
|
||||||
|
|
||||||
|
bvh.erase(p_id - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
CollisionObject2DSW *BroadPhase2DBVH::get_object(ID p_id) const {
|
||||||
|
|
||||||
|
CollisionObject2DSW *it = bvh.get(p_id - 1);
|
||||||
|
ERR_FAIL_COND_V(!it, NULL);
|
||||||
|
return it;
|
||||||
|
}
|
||||||
|
bool BroadPhase2DBVH::is_static(ID p_id) const {
|
||||||
|
|
||||||
|
return !bvh.is_pairable(p_id - 1);
|
||||||
|
}
|
||||||
|
int BroadPhase2DBVH::get_subindex(ID p_id) const {
|
||||||
|
|
||||||
|
return bvh.get_subindex(p_id - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
int BroadPhase2DBVH::cull_segment(const Vector2 &p_from, const Vector2 &p_to, CollisionObject2DSW **p_results, int p_max_results, int *p_result_indices) {
|
||||||
|
|
||||||
|
return bvh.cull_segment(p_from, p_to, p_results, p_max_results, p_result_indices);
|
||||||
|
}
|
||||||
|
|
||||||
|
int BroadPhase2DBVH::cull_aabb(const Rect2 &p_aabb, CollisionObject2DSW **p_results, int p_max_results, int *p_result_indices) {
|
||||||
|
|
||||||
|
return bvh.cull_aabb(p_aabb, p_results, p_max_results, p_result_indices);
|
||||||
|
}
|
||||||
|
|
||||||
|
void *BroadPhase2DBVH::_pair_callback(void *self, uint32_t p_A, CollisionObject2DSW *p_object_A, int subindex_A, uint32_t p_B, CollisionObject2DSW *p_object_B, int subindex_B) {
|
||||||
|
|
||||||
|
BroadPhase2DBVH *bpo = (BroadPhase2DBVH *)(self);
|
||||||
|
if (!bpo->pair_callback)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
return bpo->pair_callback(p_object_A, subindex_A, p_object_B, subindex_B, bpo->pair_userdata);
|
||||||
|
}
|
||||||
|
|
||||||
|
void BroadPhase2DBVH::_unpair_callback(void *self, uint32_t p_A, CollisionObject2DSW *p_object_A, int subindex_A, uint32_t p_B, CollisionObject2DSW *p_object_B, int subindex_B, void *pairdata) {
|
||||||
|
|
||||||
|
BroadPhase2DBVH *bpo = (BroadPhase2DBVH *)(self);
|
||||||
|
if (!bpo->unpair_callback)
|
||||||
|
return;
|
||||||
|
|
||||||
|
bpo->unpair_callback(p_object_A, subindex_A, p_object_B, subindex_B, pairdata, bpo->unpair_userdata);
|
||||||
|
}
|
||||||
|
|
||||||
|
void BroadPhase2DBVH::set_pair_callback(PairCallback p_pair_callback, void *p_userdata) {
|
||||||
|
|
||||||
|
pair_callback = p_pair_callback;
|
||||||
|
pair_userdata = p_userdata;
|
||||||
|
}
|
||||||
|
|
||||||
|
void BroadPhase2DBVH::set_unpair_callback(UnpairCallback p_unpair_callback, void *p_userdata) {
|
||||||
|
|
||||||
|
unpair_callback = p_unpair_callback;
|
||||||
|
unpair_userdata = p_userdata;
|
||||||
|
}
|
||||||
|
|
||||||
|
void BroadPhase2DBVH::update() {
|
||||||
|
bvh.update();
|
||||||
|
}
|
||||||
|
|
||||||
|
BroadPhase2DSW *BroadPhase2DBVH::_create() {
|
||||||
|
|
||||||
|
return memnew(BroadPhase2DBVH);
|
||||||
|
}
|
||||||
|
|
||||||
|
BroadPhase2DBVH::BroadPhase2DBVH() {
|
||||||
|
bvh.set_pair_callback(_pair_callback, this);
|
||||||
|
bvh.set_unpair_callback(_unpair_callback, this);
|
||||||
|
pair_callback = NULL;
|
||||||
|
pair_userdata = NULL;
|
||||||
|
unpair_userdata = NULL;
|
||||||
|
}
|
|
@ -0,0 +1,74 @@
|
||||||
|
/*************************************************************************/
|
||||||
|
/* broad_phase_2d_bvh.h */
|
||||||
|
/*************************************************************************/
|
||||||
|
/* This file is part of: */
|
||||||
|
/* GODOT ENGINE */
|
||||||
|
/* https://godotengine.org */
|
||||||
|
/*************************************************************************/
|
||||||
|
/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
|
||||||
|
/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
|
||||||
|
/* */
|
||||||
|
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||||
|
/* a copy of this software and associated documentation files (the */
|
||||||
|
/* "Software"), to deal in the Software without restriction, including */
|
||||||
|
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||||
|
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||||
|
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||||
|
/* the following conditions: */
|
||||||
|
/* */
|
||||||
|
/* The above copyright notice and this permission notice shall be */
|
||||||
|
/* included in all copies or substantial portions of the Software. */
|
||||||
|
/* */
|
||||||
|
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||||
|
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||||
|
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||||
|
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||||
|
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||||
|
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||||
|
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||||
|
/*************************************************************************/
|
||||||
|
|
||||||
|
#ifndef BROAD_PHASE_2D_BVH_H
|
||||||
|
#define BROAD_PHASE_2D_BVH_H
|
||||||
|
|
||||||
|
#include "broad_phase_2d_sw.h"
|
||||||
|
#include "core/math/bvh.h"
|
||||||
|
#include "core/math/rect2.h"
|
||||||
|
#include "core/math/vector2.h"
|
||||||
|
|
||||||
|
class BroadPhase2DBVH : public BroadPhase2DSW {
|
||||||
|
|
||||||
|
BVH_Manager<CollisionObject2DSW, true, 128, Rect2, Vector2> bvh;
|
||||||
|
|
||||||
|
static void *_pair_callback(void *, uint32_t, CollisionObject2DSW *, int, uint32_t, CollisionObject2DSW *, int);
|
||||||
|
static void _unpair_callback(void *, uint32_t, CollisionObject2DSW *, int, uint32_t, CollisionObject2DSW *, int, void *);
|
||||||
|
|
||||||
|
PairCallback pair_callback;
|
||||||
|
void *pair_userdata;
|
||||||
|
UnpairCallback unpair_callback;
|
||||||
|
void *unpair_userdata;
|
||||||
|
|
||||||
|
public:
|
||||||
|
// 0 is an invalid ID
|
||||||
|
virtual ID create(CollisionObject2DSW *p_object, int p_subindex = 0, const Rect2 &p_aabb = Rect2(), bool p_static = false);
|
||||||
|
virtual void move(ID p_id, const Rect2 &p_aabb);
|
||||||
|
virtual void set_static(ID p_id, bool p_static);
|
||||||
|
virtual void remove(ID p_id);
|
||||||
|
|
||||||
|
virtual CollisionObject2DSW *get_object(ID p_id) const;
|
||||||
|
virtual bool is_static(ID p_id) const;
|
||||||
|
virtual int get_subindex(ID p_id) const;
|
||||||
|
|
||||||
|
virtual int cull_segment(const Vector2 &p_from, const Vector2 &p_to, CollisionObject2DSW **p_results, int p_max_results, int *p_result_indices = NULL);
|
||||||
|
virtual int cull_aabb(const Rect2 &p_aabb, CollisionObject2DSW **p_results, int p_max_results, int *p_result_indices = NULL);
|
||||||
|
|
||||||
|
virtual void set_pair_callback(PairCallback p_pair_callback, void *p_userdata);
|
||||||
|
virtual void set_unpair_callback(UnpairCallback p_unpair_callback, void *p_userdata);
|
||||||
|
|
||||||
|
virtual void update();
|
||||||
|
|
||||||
|
static BroadPhase2DSW *_create();
|
||||||
|
BroadPhase2DBVH();
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // BROAD_PHASE_2D_BVH_H
|
|
@ -307,7 +307,7 @@ void BroadPhase2DHashGrid::_exit_grid(Element *p_elem, const Rect2 &p_rect, bool
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
BroadPhase2DHashGrid::ID BroadPhase2DHashGrid::create(CollisionObject2DSW *p_object, int p_subindex) {
|
BroadPhase2DHashGrid::ID BroadPhase2DHashGrid::create(CollisionObject2DSW *p_object, int p_subindex, const Rect2 &p_aabb, bool p_static) {
|
||||||
|
|
||||||
current++;
|
current++;
|
||||||
|
|
||||||
|
@ -637,15 +637,15 @@ BroadPhase2DSW *BroadPhase2DHashGrid::_create() {
|
||||||
|
|
||||||
BroadPhase2DHashGrid::BroadPhase2DHashGrid() {
|
BroadPhase2DHashGrid::BroadPhase2DHashGrid() {
|
||||||
|
|
||||||
hash_table_size = GLOBAL_DEF("physics/2d/bp_hash_table_size", 4096);
|
hash_table_size = GLOBAL_GET("physics/2d/bp_hash_table_size");
|
||||||
ProjectSettings::get_singleton()->set_custom_property_info("physics/2d/bp_hash_table_size", PropertyInfo(Variant::INT, "physics/2d/bp_hash_table_size", PROPERTY_HINT_RANGE, "0,8192,1,or_greater"));
|
ProjectSettings::get_singleton()->set_custom_property_info("physics/2d/bp_hash_table_size", PropertyInfo(Variant::INT, "physics/2d/bp_hash_table_size", PROPERTY_HINT_RANGE, "0,8192,1,or_greater"));
|
||||||
hash_table_size = Math::larger_prime(hash_table_size);
|
hash_table_size = Math::larger_prime(hash_table_size);
|
||||||
hash_table = memnew_arr(PosBin *, hash_table_size);
|
hash_table = memnew_arr(PosBin *, hash_table_size);
|
||||||
|
|
||||||
cell_size = GLOBAL_DEF("physics/2d/cell_size", 128);
|
cell_size = GLOBAL_GET("physics/2d/cell_size");
|
||||||
ProjectSettings::get_singleton()->set_custom_property_info("physics/2d/cell_size", PropertyInfo(Variant::INT, "physics/2d/cell_size", PROPERTY_HINT_RANGE, "0,512,1,or_greater"));
|
ProjectSettings::get_singleton()->set_custom_property_info("physics/2d/cell_size", PropertyInfo(Variant::INT, "physics/2d/cell_size", PROPERTY_HINT_RANGE, "0,512,1,or_greater"));
|
||||||
|
|
||||||
large_object_min_surface = GLOBAL_DEF("physics/2d/large_object_surface_threshold_in_cells", 512);
|
large_object_min_surface = GLOBAL_GET("physics/2d/large_object_surface_threshold_in_cells");
|
||||||
ProjectSettings::get_singleton()->set_custom_property_info("physics/2d/large_object_surface_threshold_in_cells", PropertyInfo(Variant::INT, "physics/2d/large_object_surface_threshold_in_cells", PROPERTY_HINT_RANGE, "0,1024,1,or_greater"));
|
ProjectSettings::get_singleton()->set_custom_property_info("physics/2d/large_object_surface_threshold_in_cells", PropertyInfo(Variant::INT, "physics/2d/large_object_surface_threshold_in_cells", PROPERTY_HINT_RANGE, "0,1024,1,or_greater"));
|
||||||
|
|
||||||
for (uint32_t i = 0; i < hash_table_size; i++)
|
for (uint32_t i = 0; i < hash_table_size; i++)
|
||||||
|
|
|
@ -175,7 +175,7 @@ class BroadPhase2DHashGrid : public BroadPhase2DSW {
|
||||||
void _check_motion(Element *p_elem);
|
void _check_motion(Element *p_elem);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
virtual ID create(CollisionObject2DSW *p_object, int p_subindex = 0);
|
virtual ID create(CollisionObject2DSW *p_object, int p_subindex = 0, const Rect2 &p_aabb = Rect2(), bool p_static = false);
|
||||||
virtual void move(ID p_id, const Rect2 &p_aabb);
|
virtual void move(ID p_id, const Rect2 &p_aabb);
|
||||||
virtual void set_static(ID p_id, bool p_static);
|
virtual void set_static(ID p_id, bool p_static);
|
||||||
virtual void remove(ID p_id);
|
virtual void remove(ID p_id);
|
||||||
|
|
|
@ -49,7 +49,7 @@ public:
|
||||||
typedef void (*UnpairCallback)(CollisionObject2DSW *A, int p_subindex_A, CollisionObject2DSW *B, int p_subindex_B, void *p_data, void *p_userdata);
|
typedef void (*UnpairCallback)(CollisionObject2DSW *A, int p_subindex_A, CollisionObject2DSW *B, int p_subindex_B, void *p_data, void *p_userdata);
|
||||||
|
|
||||||
// 0 is an invalid ID
|
// 0 is an invalid ID
|
||||||
virtual ID create(CollisionObject2DSW *p_object_, int p_subindex = 0) = 0;
|
virtual ID create(CollisionObject2DSW *p_object_, int p_subindex = 0, const Rect2 &p_aabb = Rect2(), bool p_static = false) = 0;
|
||||||
virtual void move(ID p_id, const Rect2 &p_aabb) = 0;
|
virtual void move(ID p_id, const Rect2 &p_aabb) = 0;
|
||||||
virtual void set_static(ID p_id, bool p_static) = 0;
|
virtual void set_static(ID p_id, bool p_static) = 0;
|
||||||
virtual void remove(ID p_id) = 0;
|
virtual void remove(ID p_id) = 0;
|
||||||
|
|
|
@ -187,19 +187,19 @@ void CollisionObject2DSW::_update_shapes() {
|
||||||
if (s.disabled)
|
if (s.disabled)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (s.bpid == 0) {
|
|
||||||
s.bpid = space->get_broadphase()->create(this, i);
|
|
||||||
space->get_broadphase()->set_static(s.bpid, _static);
|
|
||||||
}
|
|
||||||
|
|
||||||
//not quite correct, should compute the next matrix..
|
//not quite correct, should compute the next matrix..
|
||||||
Rect2 shape_aabb = s.shape->get_aabb();
|
Rect2 shape_aabb = s.shape->get_aabb();
|
||||||
Transform2D xform = transform * s.xform;
|
Transform2D xform = transform * s.xform;
|
||||||
shape_aabb = xform.xform(shape_aabb);
|
shape_aabb = xform.xform(shape_aabb);
|
||||||
|
shape_aabb.grow_by((s.aabb_cache.size.x + s.aabb_cache.size.y) * 0.5 * 0.05);
|
||||||
s.aabb_cache = shape_aabb;
|
s.aabb_cache = shape_aabb;
|
||||||
s.aabb_cache = s.aabb_cache.grow((s.aabb_cache.size.x + s.aabb_cache.size.y) * 0.5 * 0.05);
|
|
||||||
|
|
||||||
space->get_broadphase()->move(s.bpid, s.aabb_cache);
|
if (s.bpid == 0) {
|
||||||
|
s.bpid = space->get_broadphase()->create(this, i, shape_aabb, _static);
|
||||||
|
space->get_broadphase()->set_static(s.bpid, _static);
|
||||||
|
}
|
||||||
|
|
||||||
|
space->get_broadphase()->move(s.bpid, shape_aabb);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -214,11 +214,6 @@ void CollisionObject2DSW::_update_shapes_with_motion(const Vector2 &p_motion) {
|
||||||
if (s.disabled)
|
if (s.disabled)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (s.bpid == 0) {
|
|
||||||
s.bpid = space->get_broadphase()->create(this, i);
|
|
||||||
space->get_broadphase()->set_static(s.bpid, _static);
|
|
||||||
}
|
|
||||||
|
|
||||||
//not quite correct, should compute the next matrix..
|
//not quite correct, should compute the next matrix..
|
||||||
Rect2 shape_aabb = s.shape->get_aabb();
|
Rect2 shape_aabb = s.shape->get_aabb();
|
||||||
Transform2D xform = transform * s.xform;
|
Transform2D xform = transform * s.xform;
|
||||||
|
@ -226,6 +221,11 @@ void CollisionObject2DSW::_update_shapes_with_motion(const Vector2 &p_motion) {
|
||||||
shape_aabb = shape_aabb.merge(Rect2(shape_aabb.position + p_motion, shape_aabb.size)); //use motion
|
shape_aabb = shape_aabb.merge(Rect2(shape_aabb.position + p_motion, shape_aabb.size)); //use motion
|
||||||
s.aabb_cache = shape_aabb;
|
s.aabb_cache = shape_aabb;
|
||||||
|
|
||||||
|
if (s.bpid == 0) {
|
||||||
|
s.bpid = space->get_broadphase()->create(this, i, shape_aabb, _static);
|
||||||
|
space->get_broadphase()->set_static(s.bpid, _static);
|
||||||
|
}
|
||||||
|
|
||||||
space->get_broadphase()->move(s.bpid, shape_aabb);
|
space->get_broadphase()->move(s.bpid, shape_aabb);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,6 +30,7 @@
|
||||||
|
|
||||||
#include "physics_2d_server_sw.h"
|
#include "physics_2d_server_sw.h"
|
||||||
#include "broad_phase_2d_basic.h"
|
#include "broad_phase_2d_basic.h"
|
||||||
|
#include "broad_phase_2d_bvh.h"
|
||||||
#include "broad_phase_2d_hash_grid.h"
|
#include "broad_phase_2d_hash_grid.h"
|
||||||
#include "collision_solver_2d_sw.h"
|
#include "collision_solver_2d_sw.h"
|
||||||
#include "core/os/os.h"
|
#include "core/os/os.h"
|
||||||
|
@ -1440,8 +1441,19 @@ Physics2DServerSW *Physics2DServerSW::singletonsw = NULL;
|
||||||
Physics2DServerSW::Physics2DServerSW() {
|
Physics2DServerSW::Physics2DServerSW() {
|
||||||
|
|
||||||
singletonsw = this;
|
singletonsw = this;
|
||||||
BroadPhase2DSW::create_func = BroadPhase2DHashGrid::_create;
|
|
||||||
//BroadPhase2DSW::create_func=BroadPhase2DBasic::_create;
|
GLOBAL_DEF("physics/2d/use_bvh", true);
|
||||||
|
GLOBAL_DEF("physics/2d/bp_hash_table_size", 4096);
|
||||||
|
GLOBAL_DEF("physics/2d/cell_size", 128);
|
||||||
|
GLOBAL_DEF("physics/2d/large_object_surface_threshold_in_cells", 512);
|
||||||
|
|
||||||
|
bool use_bvh = GLOBAL_GET("physics/2d/use_bvh");
|
||||||
|
|
||||||
|
if (use_bvh) {
|
||||||
|
BroadPhase2DSW::create_func = BroadPhase2DBVH::_create;
|
||||||
|
} else {
|
||||||
|
BroadPhase2DSW::create_func = BroadPhase2DHashGrid::_create;
|
||||||
|
}
|
||||||
|
|
||||||
active = true;
|
active = true;
|
||||||
island_count = 0;
|
island_count = 0;
|
||||||
|
@ -1450,7 +1462,7 @@ Physics2DServerSW::Physics2DServerSW() {
|
||||||
#ifdef NO_THREADS
|
#ifdef NO_THREADS
|
||||||
using_threads = false;
|
using_threads = false;
|
||||||
#else
|
#else
|
||||||
using_threads = int(ProjectSettings::get_singleton()->get("physics/2d/thread_model")) == 2;
|
using_threads = int(GLOBAL_GET("physics/2d/thread_model")) == 2;
|
||||||
#endif
|
#endif
|
||||||
flushing_queries = false;
|
flushing_queries = false;
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue