Support for Dynamic BVH as 2D Physics broadphase
List of changes: - Modified bvh class to handle 2D and 3D as a template - Changes in Rect2, Vector2, Vector3 interface to uniformize template calls - New option in Project Settings to enable BVH for 2D Physics (enabled by default like in 3D)
This commit is contained in:
parent
595a74ca79
commit
d8f681029f
|
@ -48,9 +48,9 @@
|
|||
|
||||
#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 {
|
||||
|
||||
public:
|
||||
|
@ -88,7 +88,7 @@ public:
|
|||
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
|
||||
// of waiting for update, so only uncomment this if there are bugs.
|
||||
|
@ -108,7 +108,7 @@ public:
|
|||
|
||||
if (USE_PAIRS) {
|
||||
// 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.grow_by(tree._pairing_expansion);
|
||||
|
||||
|
@ -125,7 +125,7 @@ public:
|
|||
////////////////////////////////////////////////////
|
||||
// wrapper versions that use uint32_t instead of handle
|
||||
// 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;
|
||||
h.set(p_handle);
|
||||
move(h, p_aabb);
|
||||
|
@ -143,7 +143,7 @@ public:
|
|||
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;
|
||||
h.set(p_handle);
|
||||
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 (USE_PAIRS) {
|
||||
|
@ -207,7 +207,7 @@ public:
|
|||
void force_collision_check(BVHHandle p_handle) {
|
||||
if (USE_PAIRS) {
|
||||
// the aabb should already be up to date in the BVH
|
||||
AABB aabb;
|
||||
Bounds aabb;
|
||||
item_get_AABB(p_handle, aabb);
|
||||
|
||||
// add it as changed even if aabb not different
|
||||
|
@ -221,7 +221,7 @@ public:
|
|||
// these should be read as set_visible for render trees,
|
||||
// but generically this makes items add or remove from the
|
||||
// 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
|
||||
// a redundant copy of the aabb.
|
||||
// returns success
|
||||
|
@ -294,7 +294,7 @@ public:
|
|||
// 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.
|
||||
// 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);
|
||||
|
||||
// passing false disables the optimization which prevents collision checks if
|
||||
|
@ -311,7 +311,7 @@ public:
|
|||
}
|
||||
|
||||
// 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;
|
||||
|
||||
params.result_count_overall = 0;
|
||||
|
@ -328,7 +328,7 @@ public:
|
|||
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;
|
||||
|
||||
params.result_count_overall = 0;
|
||||
|
@ -346,7 +346,7 @@ public:
|
|||
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;
|
||||
|
||||
params.result_count_overall = 0;
|
||||
|
@ -396,7 +396,7 @@ private:
|
|||
return;
|
||||
}
|
||||
|
||||
AABB bb;
|
||||
Bounds bb;
|
||||
|
||||
typename BVHTREE_CLASS::CullParams params;
|
||||
|
||||
|
@ -411,8 +411,8 @@ private:
|
|||
const BVHHandle &h = changed_items[n];
|
||||
|
||||
// use the expanded aabb for pairing
|
||||
const AABB &expanded_aabb = tree._pairs[h.id()].expanded_aabb;
|
||||
BVH_ABB abb;
|
||||
const Bounds &expanded_aabb = tree._pairs[h.id()].expanded_aabb;
|
||||
BVHABB_CLASS abb;
|
||||
abb.from(expanded_aabb);
|
||||
|
||||
// find all the existing paired aabbs that are no longer
|
||||
|
@ -457,8 +457,8 @@ private:
|
|||
}
|
||||
|
||||
public:
|
||||
void item_get_AABB(BVHHandle p_handle, AABB &r_aabb) {
|
||||
BVH_ABB abb;
|
||||
void item_get_AABB(BVHHandle p_handle, Bounds &r_aabb) {
|
||||
BVHABB_CLASS abb;
|
||||
tree.item_get_ABB(p_handle, abb);
|
||||
abb.to(r_aabb);
|
||||
}
|
||||
|
@ -494,8 +494,8 @@ private:
|
|||
}
|
||||
|
||||
// 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) {
|
||||
BVH_ABB abb_to;
|
||||
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) {
|
||||
BVHABB_CLASS abb_to;
|
||||
tree.item_get_ABB(p_to, abb_to);
|
||||
|
||||
// do they overlap?
|
||||
|
@ -526,10 +526,10 @@ private:
|
|||
|
||||
// find all the existing paired aabbs that are no longer
|
||||
// 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()];
|
||||
|
||||
BVH_ABB abb_from = expanded_abb_from;
|
||||
BVHABB_CLASS abb_from = expanded_abb_from;
|
||||
|
||||
// remove from pairing list for every partner
|
||||
for (unsigned int n = 0; n < p_from.extended_pairs.size(); n++) {
|
||||
|
@ -608,7 +608,7 @@ private:
|
|||
_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,
|
||||
// so all types must be added to the list
|
||||
|
@ -616,7 +616,7 @@ private:
|
|||
// aabb check with expanded aabb. This greatly decreases processing
|
||||
// at the cost of slightly less accurate pairing checks
|
||||
// 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
|
||||
// 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
|
||||
|
||||
// special optimized version of axis aligned bounding box
|
||||
template <class Bounds = AABB, class Point = Vector3>
|
||||
struct BVH_ABB {
|
||||
struct ConvexHull {
|
||||
// convex hulls (optional)
|
||||
|
@ -42,8 +43,8 @@ struct BVH_ABB {
|
|||
};
|
||||
|
||||
struct Segment {
|
||||
Vector3 from;
|
||||
Vector3 to;
|
||||
Point from;
|
||||
Point to;
|
||||
};
|
||||
|
||||
enum IntersectResult {
|
||||
|
@ -53,49 +54,50 @@ struct BVH_ABB {
|
|||
};
|
||||
|
||||
// we store mins with a negative value in order to test them with SIMD
|
||||
Vector3 min;
|
||||
Vector3 neg_max;
|
||||
Point min;
|
||||
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 (*this == o) == false; }
|
||||
|
||||
void set(const Vector3 &_min, const Vector3 &_max) {
|
||||
void set(const Point &_min, const Point &_max) {
|
||||
min = _min;
|
||||
neg_max = -_max;
|
||||
}
|
||||
|
||||
// to and from standard AABB
|
||||
void from(const AABB &p_aabb) {
|
||||
void from(const Bounds &p_aabb) {
|
||||
min = p_aabb.position;
|
||||
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.size = calculate_size();
|
||||
}
|
||||
|
||||
void merge(const BVH_ABB &p_o) {
|
||||
neg_max.x = MIN(neg_max.x, p_o.neg_max.x);
|
||||
neg_max.y = MIN(neg_max.y, p_o.neg_max.y);
|
||||
neg_max.z = MIN(neg_max.z, p_o.neg_max.z);
|
||||
|
||||
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);
|
||||
for (int axis = 0; axis < Point::AXIS_COUNT; ++axis) {
|
||||
neg_max[axis] = MIN(neg_max[axis], p_o.neg_max[axis]);
|
||||
min[axis] = MIN(min[axis], p_o.min[axis]);
|
||||
}
|
||||
}
|
||||
|
||||
Vector3 calculate_size() const {
|
||||
Point calculate_size() const {
|
||||
return -neg_max - min;
|
||||
}
|
||||
|
||||
Vector3 calculate_centre() const {
|
||||
return Vector3((calculate_size() * 0.5) + min);
|
||||
Point calculate_centre() const {
|
||||
return Point((calculate_size() * 0.5) + min);
|
||||
}
|
||||
|
||||
real_t get_proximity_to(const BVH_ABB &p_b) const {
|
||||
const Vector3 d = (min - neg_max) - (p_b.min - p_b.neg_max);
|
||||
return (Math::abs(d.x) + Math::abs(d.y) + Math::abs(d.z));
|
||||
const Point d = (min - neg_max) - (p_b.min - p_b.neg_max);
|
||||
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 {
|
||||
|
@ -158,7 +160,7 @@ struct BVH_ABB {
|
|||
}
|
||||
|
||||
bool intersects_convex_partial(const ConvexHull &p_hull) const {
|
||||
AABB bb;
|
||||
Bounds bb;
|
||||
to(bb);
|
||||
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 {
|
||||
// use half extents routine
|
||||
AABB bb;
|
||||
Bounds bb;
|
||||
to(bb);
|
||||
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 {
|
||||
AABB bb;
|
||||
Bounds bb;
|
||||
to(bb);
|
||||
return bb.intersects_segment(p_s.from, p_s.to);
|
||||
}
|
||||
|
||||
bool intersects_point(const Vector3 &p_pt) const {
|
||||
if (_vector3_any_lessthan(-p_pt, neg_max)) return false;
|
||||
if (_vector3_any_lessthan(p_pt, min)) return false;
|
||||
bool intersects_point(const Point &p_pt) const {
|
||||
if (_any_lessthan(-p_pt, neg_max)) return false;
|
||||
if (_any_lessthan(p_pt, min)) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool intersects(const BVH_ABB &p_o) const {
|
||||
if (_vector3_any_morethan(p_o.min, -neg_max)) return false;
|
||||
if (_vector3_any_morethan(min, -p_o.neg_max)) return false;
|
||||
if (_any_morethan(p_o.min, -neg_max)) return false;
|
||||
if (_any_morethan(min, -p_o.neg_max)) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool is_other_within(const BVH_ABB &p_o) const {
|
||||
if (_vector3_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.neg_max, neg_max)) return false;
|
||||
if (_any_lessthan(p_o.min, min)) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
void grow(const Vector3 &p_change) {
|
||||
void grow(const Point &p_change) {
|
||||
neg_max -= p_change;
|
||||
min -= 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
|
||||
{
|
||||
Vector3 d = calculate_size();
|
||||
// Actually surface area metric.
|
||||
float get_area() const {
|
||||
Point d = calculate_size();
|
||||
return 2.0f * (d.x * d.y + d.y * d.z + d.z * d.x);
|
||||
}
|
||||
|
||||
void set_to_max_opposite_extents() {
|
||||
neg_max = Vector3(FLT_MAX, FLT_MAX, FLT_MAX);
|
||||
neg_max.set_all(FLT_MAX);
|
||||
min = neg_max;
|
||||
}
|
||||
|
||||
bool _vector3_any_morethan(const Vector3 &p_a, const Vector3 &p_b) const {
|
||||
if (p_a.x > p_b.x) return true;
|
||||
if (p_a.y > p_b.y) return true;
|
||||
if (p_a.z > p_b.z) return true;
|
||||
bool _any_morethan(const Point &p_a, const Point &p_b) const {
|
||||
for (int axis = 0; axis < Point::AXIS_COUNT; ++axis) {
|
||||
if (p_a[axis] > p_b[axis]) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool _vector3_any_lessthan(const Vector3 &p_a, const Vector3 &p_b) const {
|
||||
if (p_a.x < p_b.x) return true;
|
||||
if (p_a.y < p_b.y) return true;
|
||||
if (p_a.z < p_b.z) return true;
|
||||
bool _any_lessthan(const Point &p_a, const Point &p_b) const {
|
||||
for (int axis = 0; axis < Point::AXIS_COUNT; ++axis) {
|
||||
if (p_a[axis] < p_b[axis]) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
|
|
@ -15,9 +15,9 @@ struct CullParams {
|
|||
|
||||
// optional components for different tests
|
||||
Vector3 point;
|
||||
BVH_ABB abb;
|
||||
typename BVH_ABB::ConvexHull hull;
|
||||
typename BVH_ABB::Segment segment;
|
||||
BVHABB_CLASS abb;
|
||||
typename BVHABB_CLASS::ConvexHull hull;
|
||||
typename BVHABB_CLASS::Segment segment;
|
||||
|
||||
// when collision testing, non pairable moving items
|
||||
// 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
|
||||
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)) {
|
||||
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++) {
|
||||
|
||||
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)) {
|
||||
|
||||
|
@ -339,7 +339,7 @@ bool _cull_aabb_iterative(uint32_t p_node_id, CullParams &r_params, bool p_fully
|
|||
}
|
||||
} else {
|
||||
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)) {
|
||||
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++) {
|
||||
|
||||
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)) {
|
||||
// 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) {
|
||||
|
||||
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) {
|
||||
default: {
|
||||
continue; // miss, just move on to the next node in the stack
|
||||
} break;
|
||||
case BVH_ABB::IR_PARTIAL: {
|
||||
case BVHABB_CLASS::IR_PARTIAL: {
|
||||
} break;
|
||||
case BVH_ABB::IR_FULL: {
|
||||
case BVHABB_CLASS::IR_FULL: {
|
||||
ccp.fully_within = true;
|
||||
} break;
|
||||
}
|
||||
|
@ -478,7 +478,7 @@ bool _cull_convex_iterative(uint32_t p_node_id, CullParams &r_params, bool p_ful
|
|||
// test children individually
|
||||
for (int n = 0; n < leaf.num_items; 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)) {
|
||||
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;
|
||||
|
||||
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)) {
|
||||
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
|
||||
// test children individually
|
||||
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)) {
|
||||
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]);
|
||||
}
|
||||
|
||||
String _debug_aabb_to_string(const BVH_ABB &aabb) const {
|
||||
String _debug_aabb_to_string(const BVHABB_CLASS &aabb) const {
|
||||
String sz = "(";
|
||||
sz += itos(aabb.min.x);
|
||||
sz += " ~ ";
|
||||
|
|
|
@ -12,10 +12,10 @@ void _integrity_check_all() {
|
|||
void _integrity_check_up(uint32_t p_node_id) {
|
||||
TNode &node = _nodes[p_node_id];
|
||||
|
||||
BVH_ABB abb = node.aabb;
|
||||
BVHABB_CLASS abb = node.aabb;
|
||||
node_update_aabb(node);
|
||||
|
||||
BVH_ABB abb2 = node.aabb;
|
||||
BVHABB_CLASS abb2 = node.aabb;
|
||||
abb2.expand(-_node_expansion);
|
||||
|
||||
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);
|
||||
|
||||
// remove and reinsert
|
||||
BVH_ABB abb;
|
||||
BVHABB_CLASS abb;
|
||||
node_remove_item(p_ref_id, &abb);
|
||||
|
||||
// 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
|
||||
BVH_ABB _logic_abb_merge(const BVH_ABB &a, const BVH_ABB &b) {
|
||||
BVH_ABB c = a;
|
||||
BVHABB_CLASS _logic_abb_merge(const BVHABB_CLASS &a, const BVHABB_CLASS &b) {
|
||||
BVHABB_CLASS c = a;
|
||||
c.merge(b);
|
||||
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
|
||||
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) {
|
||||
BVH_ASSERT(p_node_id != BVHCommon::INVALID);
|
||||
|
|
|
@ -14,10 +14,10 @@ struct ItemPairs {
|
|||
void clear() {
|
||||
num_pairs = 0;
|
||||
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
|
||||
int32_t num_pairs;
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
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
|
||||
VERBOSE_PRINT("\nitem_add BEFORE");
|
||||
_debug_recursive_print_tree(0);
|
||||
VERBOSE_PRINT("\n");
|
||||
#endif
|
||||
|
||||
BVH_ABB abb;
|
||||
BVHABB_CLASS abb;
|
||||
abb.from(p_aabb);
|
||||
|
||||
// handle to be filled with the new item ref
|
||||
|
@ -101,7 +101,7 @@ void _debug_print_refs() {
|
|||
}
|
||||
|
||||
// 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();
|
||||
|
||||
// get the reference
|
||||
|
@ -110,7 +110,7 @@ bool item_move(BVHHandle p_handle, const AABB &p_aabb) {
|
|||
return false;
|
||||
}
|
||||
|
||||
BVH_ABB abb;
|
||||
BVHABB_CLASS abb;
|
||||
abb.from(p_aabb);
|
||||
|
||||
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
|
||||
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?
|
||||
if (leaf_abb == abb) {
|
||||
|
@ -203,7 +203,7 @@ void item_remove(BVHHandle p_handle) {
|
|||
}
|
||||
|
||||
// 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();
|
||||
ItemRef &ref = _refs[ref_id];
|
||||
if (ref.is_active()) {
|
||||
|
@ -212,7 +212,7 @@ bool item_activate(BVHHandle p_handle, const AABB &p_aabb) {
|
|||
}
|
||||
|
||||
// add to tree
|
||||
BVH_ABB abb;
|
||||
BVHABB_CLASS abb;
|
||||
abb.from(p_aabb);
|
||||
|
||||
_current_tree = _handle_get_tree_id(p_handle);
|
||||
|
@ -236,7 +236,7 @@ bool item_deactivate(BVHHandle p_handle) {
|
|||
}
|
||||
|
||||
// remove from tree
|
||||
BVH_ABB abb;
|
||||
BVHABB_CLASS abb;
|
||||
node_remove_item(ref_id, &abb);
|
||||
|
||||
// mark as inactive
|
||||
|
@ -269,7 +269,7 @@ bool item_is_pairable(const BVHHandle &p_handle) {
|
|||
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?
|
||||
uint32_t ref_id = p_handle.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
|
||||
TNode &tnode = _nodes[ref.tnode_id];
|
||||
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
|
||||
_current_tree = _handle_get_tree_id(p_handle);
|
||||
|
@ -377,7 +377,7 @@ void update() {
|
|||
//#define BVH_ALLOW_AUTO_EXPANSION
|
||||
#ifdef BVH_ALLOW_AUTO_EXPANSION
|
||||
if (_auto_node_expansion || _auto_pairing_expansion) {
|
||||
BVH_ABB world_bound;
|
||||
BVHABB_CLASS world_bound;
|
||||
world_bound.set_to_max_opposite_extents();
|
||||
|
||||
bool bound_valid = false;
|
||||
|
@ -392,7 +392,7 @@ void update() {
|
|||
|
||||
// if there are no nodes, do nothing, but if there are...
|
||||
if (bound_valid) {
|
||||
AABB bb;
|
||||
Bounds bb;
|
||||
world_bound.to(bb);
|
||||
real_t size = bb.get_longest_axis_size();
|
||||
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
void _debug_node_verify_bound(uint32_t 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);
|
||||
|
||||
BVH_ABB abb_after = node.aabb;
|
||||
BVHABB_CLASS abb_after = node.aabb;
|
||||
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
|
||||
if (MAX_ITEMS < 4) {
|
||||
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;
|
||||
}
|
||||
|
||||
Vector3 centre = full_bound.calculate_centre();
|
||||
Vector3 size = full_bound.calculate_size();
|
||||
Point centre = full_bound.calculate_centre();
|
||||
Point size = full_bound.calculate_size();
|
||||
|
||||
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) {
|
||||
BVH_ABB groupb_aabb;
|
||||
void _split_leaf_sort_groups(int &num_a, int &num_b, uint16_t *group_a, uint16_t *group_b, const BVHABB_CLASS *temp_bounds) {
|
||||
BVHABB_CLASS groupb_aabb;
|
||||
groupb_aabb.set_to_max_opposite_extents();
|
||||
for (int n = 0; n < num_b; n++) {
|
||||
int which = group_b[n];
|
||||
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;
|
||||
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];
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
// 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");
|
||||
|
||||
// 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);
|
||||
|
||||
// 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_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];
|
||||
|
||||
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);
|
||||
//const Item &source_item = orig_leaf.get_item(which);
|
||||
_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];
|
||||
|
||||
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);
|
||||
//const Item &source_item = orig_leaf.get_item(which);
|
||||
_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
|
||||
struct Item {
|
||||
BVH_ABB aabb;
|
||||
BVHABB_CLASS aabb;
|
||||
uint32_t item_ref_id;
|
||||
};
|
||||
|
||||
|
@ -43,12 +43,12 @@ private:
|
|||
uint16_t dirty;
|
||||
// separate data orientated lists for faster SIMD traversal
|
||||
uint32_t item_ref_ids[MAX_ITEMS];
|
||||
BVH_ABB aabbs[MAX_ITEMS];
|
||||
BVHABB_CLASS aabbs[MAX_ITEMS];
|
||||
|
||||
public:
|
||||
// accessors
|
||||
BVH_ABB &get_aabb(uint32_t p_id) { return aabbs[p_id]; }
|
||||
const BVH_ABB &get_aabb(uint32_t p_id) const { return aabbs[p_id]; }
|
||||
BVHABB_CLASS &get_aabb(uint32_t p_id) { 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]; }
|
||||
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
|
||||
struct TNode {
|
||||
BVH_ABB aabb;
|
||||
BVHABB_CLASS aabb;
|
||||
// either number of children if positive
|
||||
// or leaf id if negative (leaf id 0 is disallowed)
|
||||
union {
|
||||
|
|
|
@ -48,6 +48,8 @@
|
|||
#include "core/print_string.h"
|
||||
#include <limits.h>
|
||||
|
||||
#define BVHABB_CLASS BVH_ABB<Bounds, Point>
|
||||
|
||||
// never do these checks in release
|
||||
#if defined(TOOLS_ENABLED) && defined(DEBUG_ENABLED)
|
||||
//#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 {
|
||||
friend class BVH;
|
||||
|
||||
|
@ -269,7 +271,7 @@ private:
|
|||
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
|
||||
ItemRef &ref = _refs[p_ref_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!
|
||||
// (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
|
||||
// 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
|
||||
// which are important in determining the bound. Any other aabb
|
||||
// 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);
|
||||
bool refit = true;
|
||||
|
||||
|
@ -348,7 +350,7 @@ private:
|
|||
|
||||
// returns true if needs refit of PARENT tree only, the node itself AABB is calculated
|
||||
// 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];
|
||||
ref.tnode_id = p_node_id;
|
||||
|
||||
|
@ -362,7 +364,7 @@ private:
|
|||
bool needs_refit = true;
|
||||
|
||||
// expand bound now
|
||||
BVH_ABB expanded = p_aabb;
|
||||
BVHABB_CLASS expanded = p_aabb;
|
||||
expanded.expand(_node_expansion);
|
||||
|
||||
// the bound will only be valid if there is an item in there already
|
||||
|
@ -390,7 +392,7 @@ private:
|
|||
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;
|
||||
TNode *child_node = _nodes.request(child_node_id);
|
||||
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; }
|
||||
|
||||
inline Rect2 grow(real_t p_by) const {
|
||||
|
||||
Rect2 g = *this;
|
||||
g.position.x -= p_by;
|
||||
g.position.y -= p_by;
|
||||
g.size.width += p_by * 2;
|
||||
g.size.height += p_by * 2;
|
||||
g.grow_by(p_by);
|
||||
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 {
|
||||
Rect2 g = *this;
|
||||
g = g.grow_individual((MARGIN_LEFT == p_margin) ? p_amount : 0,
|
||||
|
|
|
@ -37,6 +37,7 @@
|
|||
struct Vector2i;
|
||||
|
||||
struct Vector2 {
|
||||
static const int AXIS_COUNT = 2;
|
||||
|
||||
enum Axis {
|
||||
AXIS_X,
|
||||
|
@ -44,12 +45,18 @@ struct Vector2 {
|
|||
};
|
||||
|
||||
union {
|
||||
real_t x;
|
||||
real_t width;
|
||||
};
|
||||
union {
|
||||
real_t y;
|
||||
real_t height;
|
||||
struct {
|
||||
union {
|
||||
real_t x;
|
||||
real_t width;
|
||||
};
|
||||
union {
|
||||
real_t y;
|
||||
real_t height;
|
||||
};
|
||||
};
|
||||
|
||||
real_t coord[2];
|
||||
};
|
||||
|
||||
_FORCE_INLINE_ real_t &operator[](int p_idx) {
|
||||
|
@ -59,6 +66,18 @@ struct Vector2 {
|
|||
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();
|
||||
Vector2 normalized() const;
|
||||
bool is_normalized() const;
|
||||
|
|
|
@ -54,15 +54,6 @@ real_t Vector3::get_axis(int p_axis) const {
|
|||
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) {
|
||||
|
||||
x = Math::stepify(x, p_val.x);
|
||||
|
|
|
@ -37,6 +37,7 @@
|
|||
class Basis;
|
||||
|
||||
struct Vector3 {
|
||||
static const int AXIS_COUNT = 3;
|
||||
|
||||
enum Axis {
|
||||
AXIS_X,
|
||||
|
@ -67,8 +68,17 @@ struct Vector3 {
|
|||
void set_axis(int p_axis, real_t p_value);
|
||||
real_t get_axis(int p_axis) const;
|
||||
|
||||
int min_axis() const;
|
||||
int max_axis() const;
|
||||
_FORCE_INLINE_ void set_all(real_t p_value) {
|
||||
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_squared() const;
|
||||
|
|
|
@ -935,9 +935,11 @@
|
|||
</member>
|
||||
<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.
|
||||
[b]Note:[/b] Not used if [member ProjectSettings.physics/2d/use_bvh] is enabled.
|
||||
</member>
|
||||
<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).
|
||||
[b]Note:[/b] Not used if [member ProjectSettings.physics/2d/use_bvh] is enabled.
|
||||
</member>
|
||||
<member name="physics/2d/default_angular_damp" type="float" setter="" getter="" default="1.0">
|
||||
The default angular damp in 2D.
|
||||
|
@ -965,6 +967,7 @@
|
|||
</member>
|
||||
<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.
|
||||
[b]Note:[/b] Not used if [member ProjectSettings.physics/2d/use_bvh] is enabled.
|
||||
</member>
|
||||
<member name="physics/2d/physics_engine" type="String" setter="" getter="" default=""DEFAULT"">
|
||||
Sets which physics engine to use for 2D physics.
|
||||
|
@ -983,6 +986,9 @@
|
|||
<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].
|
||||
</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">
|
||||
Sets whether the 3D physics world will be created with support for [SoftBody] physics. Only applies to the Bullet physics engine.
|
||||
</member>
|
||||
|
@ -1011,7 +1017,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.
|
||||
</member>
|
||||
<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 name="physics/3d/physics_engine" type="String" setter="" getter="" default=""DEFAULT"">
|
||||
Sets which physics engine to use for 3D physics.
|
||||
|
|
|
@ -30,7 +30,7 @@
|
|||
|
||||
#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++;
|
||||
|
||||
|
|
|
@ -82,7 +82,7 @@ class BroadPhase2DBasic : public BroadPhase2DSW {
|
|||
|
||||
public:
|
||||
// 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 set_static(ID p_id, bool p_static);
|
||||
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
|
|
@ -317,7 +317,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++;
|
||||
|
||||
|
@ -633,15 +633,15 @@ BroadPhase2DSW *BroadPhase2DHashGrid::_create() {
|
|||
|
||||
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"));
|
||||
hash_table_size = Math::larger_prime(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"));
|
||||
|
||||
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"));
|
||||
|
||||
for (uint32_t i = 0; i < hash_table_size; i++)
|
||||
|
|
|
@ -168,7 +168,7 @@ class BroadPhase2DHashGrid : public BroadPhase2DSW {
|
|||
void _check_motion(Element *p_elem);
|
||||
|
||||
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 set_static(ID p_id, bool p_static);
|
||||
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);
|
||||
|
||||
// 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 set_static(ID p_id, bool p_static) = 0;
|
||||
virtual void remove(ID p_id) = 0;
|
||||
|
|
|
@ -187,19 +187,19 @@ void CollisionObject2DSW::_update_shapes() {
|
|||
if (s.disabled)
|
||||
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..
|
||||
Rect2 shape_aabb = s.shape->get_aabb();
|
||||
Transform2D xform = transform * s.xform;
|
||||
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 = 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)
|
||||
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..
|
||||
Rect2 shape_aabb = s.shape->get_aabb();
|
||||
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
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -30,6 +30,7 @@
|
|||
|
||||
#include "physics_2d_server_sw.h"
|
||||
#include "broad_phase_2d_basic.h"
|
||||
#include "broad_phase_2d_bvh.h"
|
||||
#include "broad_phase_2d_hash_grid.h"
|
||||
#include "collision_solver_2d_sw.h"
|
||||
#include "core/os/os.h"
|
||||
|
@ -1440,8 +1441,19 @@ Physics2DServerSW *Physics2DServerSW::singletonsw = NULL;
|
|||
Physics2DServerSW::Physics2DServerSW() {
|
||||
|
||||
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;
|
||||
island_count = 0;
|
||||
|
@ -1450,7 +1462,7 @@ Physics2DServerSW::Physics2DServerSW() {
|
|||
#ifdef NO_THREADS
|
||||
using_threads = false;
|
||||
#else
|
||||
using_threads = int(ProjectSettings::get_singleton()->get("physics/2d/thread_model")) == 2;
|
||||
using_threads = int(GLOBAL_GET("physics/2d/thread_model")) == 2;
|
||||
#endif
|
||||
flushing_queries = false;
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue