diff --git a/core/math/aabb.h b/core/math/aabb.h index 474304eae207..24908ae59d1f 100644 --- a/core/math/aabb.h +++ b/core/math/aabb.h @@ -107,6 +107,9 @@ class AABB { Variant intersects_segment_bind(const Vector3 &p_from, const Vector3 &p_to) const; Variant intersects_ray_bind(const Vector3 &p_from, const Vector3 &p_dir) const; + _FORCE_INLINE_ void quantize(float p_unit); + _FORCE_INLINE_ AABB quantized(float p_unit) const; + _FORCE_INLINE_ void set_end(const Vector3 &p_end) { size = p_end - position; } @@ -427,4 +430,28 @@ void AABB::grow_by(real_t p_amount) { size.z += 2.0 * p_amount; } +void AABB::quantize(float p_unit) { + size += position; + + position.x -= Math::fposmodp(position.x, p_unit); + position.y -= Math::fposmodp(position.y, p_unit); + position.z -= Math::fposmodp(position.z, p_unit); + + size.x -= Math::fposmodp(size.x, p_unit); + size.y -= Math::fposmodp(size.y, p_unit); + size.z -= Math::fposmodp(size.z, p_unit); + + size.x += p_unit; + size.y += p_unit; + size.z += p_unit; + + size -= position; +} + +AABB AABB::quantized(float p_unit) const { + AABB ret = *this; + ret.quantize(p_unit); + return ret; +} + #endif // AABB_H diff --git a/core/math/dynamic_bvh.cpp b/core/math/dynamic_bvh.cpp index a53f8d1eb8e3..e66de5037d96 100644 --- a/core/math/dynamic_bvh.cpp +++ b/core/math/dynamic_bvh.cpp @@ -351,17 +351,17 @@ void DynamicBVH::_update(Node *leaf, int lookahead) { _insert_leaf(root, leaf); } -void DynamicBVH::update(const ID &p_id, const AABB &p_box) { - ERR_FAIL_COND(!p_id.is_valid()); +bool DynamicBVH::update(const ID &p_id, const AABB &p_box) { + ERR_FAIL_COND_V(!p_id.is_valid(), false); Node *leaf = p_id.node; Volume volume; volume.min = p_box.position; volume.max = p_box.position + p_box.size; - if ((leaf->volume.min == volume.min) && (leaf->volume.max == volume.max)) { + if (leaf->volume.min.is_equal_approx(volume.min) && leaf->volume.max.is_equal_approx(volume.max)) { // noop - return; + return false; } Node *base = _remove_leaf(leaf); @@ -375,6 +375,7 @@ void DynamicBVH::update(const ID &p_id, const AABB &p_box) { } leaf->volume = volume; _insert_leaf(base, leaf); + return true; } void DynamicBVH::remove(const ID &p_id) { diff --git a/core/math/dynamic_bvh.h b/core/math/dynamic_bvh.h index cdea51c674ac..968badc093dd 100644 --- a/core/math/dynamic_bvh.h +++ b/core/math/dynamic_bvh.h @@ -281,7 +281,7 @@ class DynamicBVH { void optimize_top_down(int bu_threshold = 128); void optimize_incremental(int passes); ID insert(const AABB &p_box, void *p_userdata); - void update(const ID &p_id, const AABB &p_box); + bool update(const ID &p_id, const AABB &p_box); void remove(const ID &p_id); void get_elements(List *r_elements); diff --git a/core/math/math_funcs.h b/core/math/math_funcs.h index 827637bf2bec..471aa5899640 100644 --- a/core/math/math_funcs.h +++ b/core/math/math_funcs.h @@ -198,6 +198,23 @@ class Math { value += 0.0; return value; } + static _ALWAYS_INLINE_ float fposmodp(float p_x, float p_y) { + float value = Math::fmod(p_x, p_y); + if (value < 0) { + value += p_y; + } + value += 0.0; + return value; + } + static _ALWAYS_INLINE_ double fposmodp(double p_x, double p_y) { + double value = Math::fmod(p_x, p_y); + if (value < 0) { + value += p_y; + } + value += 0.0; + return value; + } + static _ALWAYS_INLINE_ int posmod(int p_x, int p_y) { int value = p_x % p_y; if ((value < 0 && p_y > 0) || (value > 0 && p_y < 0)) { diff --git a/servers/rendering/renderer_scene_cull.cpp b/servers/rendering/renderer_scene_cull.cpp index 8bb9e6b8b07f..be2eb7158198 100644 --- a/servers/rendering/renderer_scene_cull.cpp +++ b/servers/rendering/renderer_scene_cull.cpp @@ -1065,20 +1065,37 @@ void RendererSceneCull::_update_instance(Instance *p_instance) { p_instance->transformed_aabb = new_aabb; if (p_instance->scenario == nullptr || !p_instance->visible || Math::is_zero_approx(p_instance->transform.basis.determinant())) { + p_instance->prev_transformed_aabb = p_instance->transformed_aabb; return; } + //quantize to improve moving object performance + AABB bvh_aabb = p_instance->transformed_aabb; + + if (p_instance->indexer_id.is_valid() && bvh_aabb != p_instance->prev_transformed_aabb) { + //assume motion, see if bounds need to be quantized + AABB motion_aabb = bvh_aabb.merge(p_instance->prev_transformed_aabb); + float motion_longest_axis = motion_aabb.get_longest_axis_size(); + float longest_axis = p_instance->transformed_aabb.get_longest_axis_size(); + + if (motion_longest_axis < longest_axis * 2) { + //moved but not a lot, use motion aabb quantizing + float quantize_size = Math::pow(2.0, Math::ceil(Math::log(motion_longest_axis) / Math::log(2.0))) * 0.5; //one fifth + bvh_aabb.quantize(quantize_size); + } + } + if (!p_instance->indexer_id.is_valid()) { if ((1 << p_instance->base_type) & RS::INSTANCE_GEOMETRY_MASK) { - p_instance->indexer_id = p_instance->scenario->indexers[Scenario::INDEXER_GEOMETRY].insert(p_instance->transformed_aabb, p_instance); + p_instance->indexer_id = p_instance->scenario->indexers[Scenario::INDEXER_GEOMETRY].insert(bvh_aabb, p_instance); } else { - p_instance->indexer_id = p_instance->scenario->indexers[Scenario::INDEXER_VOLUMES].insert(p_instance->transformed_aabb, p_instance); + p_instance->indexer_id = p_instance->scenario->indexers[Scenario::INDEXER_VOLUMES].insert(bvh_aabb, p_instance); } } else { if ((1 << p_instance->base_type) & RS::INSTANCE_GEOMETRY_MASK) { - p_instance->scenario->indexers[Scenario::INDEXER_GEOMETRY].update(p_instance->indexer_id, p_instance->transformed_aabb); + p_instance->scenario->indexers[Scenario::INDEXER_GEOMETRY].update(p_instance->indexer_id, bvh_aabb); } else { - p_instance->scenario->indexers[Scenario::INDEXER_VOLUMES].update(p_instance->indexer_id, p_instance->transformed_aabb); + p_instance->scenario->indexers[Scenario::INDEXER_VOLUMES].update(p_instance->indexer_id, bvh_aabb); } } @@ -1124,6 +1141,8 @@ void RendererSceneCull::_update_instance(Instance *p_instance) { } pair.pair(); + + p_instance->prev_transformed_aabb = p_instance->transformed_aabb; } void RendererSceneCull::_unpair_instance(Instance *p_instance) { diff --git a/servers/rendering/renderer_scene_render.h b/servers/rendering/renderer_scene_render.h index f8b70e3ad40b..19ab7a392be1 100644 --- a/servers/rendering/renderer_scene_render.h +++ b/servers/rendering/renderer_scene_render.h @@ -172,6 +172,7 @@ class RendererSceneRender { AABB aabb; AABB transformed_aabb; + AABB prev_transformed_aabb; struct InstanceShaderParameter { int32_t index = -1;