| … | … | @@ -519,7 +519,37 @@ void DCTerrain::_ready() { |
| 519 | 519 | // here — _ready() only fires once but ENTER_TREE handles lifecycle. |
| 520 | 520 | } |
| 521 | 521 | |
| 522 | Dictionary DCTerrain::get_scalar_query_counts() const { |
| 523 | Dictionary d; |
| 524 | d["sample_density"] = (int64_t)n_sample_density_.load(std::memory_order_relaxed); |
| 525 | d["eval_with_edits"] = (int64_t)n_eval_with_edits_.load(std::memory_order_relaxed); |
| 526 | d["collision_mode"] = (int)collision_mode_; |
| 527 | return d; |
| 528 | } |
| 529 | |
| 530 | void DCTerrain::reset_scalar_query_counts() { |
| 531 | n_sample_density_.store(0, std::memory_order_relaxed); |
| 532 | n_eval_with_edits_.store(0, std::memory_order_relaxed); |
| 533 | } |
| 534 | |
| 522 | 535 | void DCTerrain::_process(double delta) { |
| 536 | // DC_SCALAR_PROFILE=1 prints the scalar query rate once a second. Off by |
| 537 | // default and env-gated rather than a property, so measuring costs no game |
| 538 | // script change and normal runs get no extra log line. #64 NEXT 3. |
| 539 | if (scalar_profile_accum_ == 0.0) { |
| 540 | scalar_profile_on_ = OS::get_singleton()->get_environment("DC_SCALAR_PROFILE") == "1"; |
| 541 | } |
| 542 | if (scalar_profile_on_) { |
| 543 | scalar_profile_accum_ += delta; |
| 544 | if (scalar_profile_accum_ >= 1.0) { |
| 545 | UtilityFunctions::print( |
| 546 | "DC_SCALAR_PROFILE ", (double)scalar_profile_accum_, "s: sample_density=", |
| 547 | (int64_t)n_sample_density_.load(std::memory_order_relaxed), |
| 548 | " eval_with_edits=", (int64_t)n_eval_with_edits_.load(std::memory_order_relaxed), |
| 549 | " collision_mode=", (int)collision_mode_); |
| 550 | scalar_profile_accum_ = 0.0001; |
| 551 | } |
| 552 | } |
| 523 | 553 | if (!is_inside_tree()) return; |
| 524 | 554 | |
| 525 | 555 | frame_counter_++; |
| … | … | @@ -3162,6 +3192,7 @@ PackedFloat32Array DCTerrain::debug_gpu_density(const Vector3 &origin, float vox |
| 3162 | 3192 | } |
| 3163 | 3193 | |
| 3164 | 3194 | float DCTerrain::sample_density(const Vector3 &position) const { |
| 3195 | n_sample_density_.fetch_add(1, std::memory_order_relaxed); |
| 3165 | 3196 | float d = generator_ptr_->evaluate(position.x, position.y, position.z, 0.0f); |
| 3166 | 3197 | if (config_.edits && !config_.edits->empty()) { |
| 3167 | 3198 | d = DCEditList::apply(*config_.edits, position.x, position.y, position.z, d); |
| … | … | @@ -3176,6 +3207,7 @@ float DCTerrain::sample_density(const Vector3 &position) const { |
| 3176 | 3207 | // Single-point queries: O(all_edits) is fine (one call, not 32K). |
| 3177 | 3208 | // --------------------------------------------------------------------------- |
| 3178 | 3209 | float DCTerrain::_eval_with_edits(float x, float y, float z) const { |
| 3210 | n_eval_with_edits_.fetch_add(1, std::memory_order_relaxed); |
| 3179 | 3211 | float d = generator_ptr_->evaluate(x, y, z, 0.0f); |
| 3180 | 3212 | if (config_.edits && !config_.edits->empty()) { |
| 3181 | 3213 | d = DCEditList::apply(*config_.edits, x, y, z, d); |
| … | … | @@ -4377,6 +4409,8 @@ void DCTerrain::_bind_methods() { |
| 4377 | 4409 | // there is no way for a test, or a map script, to ask whether the terrain |
| 4378 | 4410 | // on screen is the one the assigned generator describes. |
| 4379 | 4411 | ClassDB::bind_method(D_METHOD("is_using_builtin_generator"), &DCTerrain::is_using_builtin_generator); |
| 4412 | ClassDB::bind_method(D_METHOD("get_scalar_query_counts"), &DCTerrain::get_scalar_query_counts); |
| 4413 | ClassDB::bind_method(D_METHOD("reset_scalar_query_counts"), &DCTerrain::reset_scalar_query_counts); |
| 4380 | 4414 | ClassDB::bind_method(D_METHOD("sample_density", "position"), &DCTerrain::sample_density); |
| 4381 | 4415 | ClassDB::bind_method(D_METHOD("debug_gpu_density", "origin", "voxel_size", "cells"), &DCTerrain::debug_gpu_density); |
| 4382 | 4416 | ClassDB::bind_method(D_METHOD("debug_collision_faces", "center", "radius"), &DCTerrain::debug_collision_faces); |