From 03c53bb33bfcb6a6e2621b35332debce6af296f3 Mon Sep 17 00:00:00 2001 From: rdb Date: Sun, 17 Mar 2019 20:50:17 +0100 Subject: [PATCH] ShaderTerrainMesh: set a bounding volume around the whole terrain This lets one use multiple ShaderTerrainMesh tiles effectively, with Panda automatically disabling ones that are certainly not in view. It may be worth an attempt to call `set_bounds_type(BoundingVolume::BT_box)` or set `bounds-type best` in Config.prc to get a tighter volume. --- panda/src/grutil/shaderTerrainMesh.cxx | 61 +++++++++++++++++++++++++- panda/src/grutil/shaderTerrainMesh.h | 10 +++++ 2 files changed, 69 insertions(+), 2 deletions(-) diff --git a/panda/src/grutil/shaderTerrainMesh.cxx b/panda/src/grutil/shaderTerrainMesh.cxx index e8078f7b68..3aaaccc8b0 100644 --- a/panda/src/grutil/shaderTerrainMesh.cxx +++ b/panda/src/grutil/shaderTerrainMesh.cxx @@ -30,6 +30,7 @@ #include "renderAttrib.h" #include "shaderInput.h" #include "boundingBox.h" +#include "boundingSphere.h" #include "samplerState.h" #include "config_grutil.h" #include "typeHandle.h" @@ -106,8 +107,6 @@ ShaderTerrainMesh::ShaderTerrainMesh() : _update_enabled(true), _heightfield_tex(nullptr) { - set_final(true); - set_bounds(new OmniBoundingVolume()); } /** @@ -563,6 +562,64 @@ void ShaderTerrainMesh::add_for_draw(CullTraverser *trav, CullTraverserData &dat _basic_collector.stop(); } +/** + * This is used to support NodePath::calc_tight_bounds(). It is not intended + * to be called directly, and it has nothing to do with the normal Panda + * bounding-volume computation. + * + * If the node contains any geometry, this updates min_point and max_point to + * enclose its bounding box. found_any is to be set true if the node has any + * geometry at all, or left alone if it has none. This method may be called + * over several nodes, so it may enter with min_point, max_point, and + * found_any already set. + */ +CPT(TransformState) ShaderTerrainMesh:: +calc_tight_bounds(LPoint3 &min_point, LPoint3 &max_point, bool &found_any, + const TransformState *transform, Thread *current_thread) const { + CPT(TransformState) next_transform = + PandaNode::calc_tight_bounds(min_point, max_point, found_any, transform, + current_thread); + + const LMatrix4 &mat = next_transform->get_mat(); + LPoint3 terrain_min_point = LPoint3(0, 0, 0) * mat; + LPoint3 terrain_max_point = LPoint3(1, 1, 1) * mat; + if (!found_any) { + min_point = terrain_min_point; + max_point = terrain_max_point; + found_any = true; + } else { + min_point = min_point.fmin(terrain_min_point); + max_point = max_point.fmax(terrain_max_point); + } + + return next_transform; +} + +/** + * Returns a newly-allocated BoundingVolume that represents the internal + * contents of the node. Should be overridden by PandaNode classes that + * contain something internally. + */ +void ShaderTerrainMesh:: +compute_internal_bounds(CPT(BoundingVolume) &internal_bounds, + int &internal_vertices, + int pipeline_stage, + Thread *current_thread) const { + + BoundingVolume::BoundsType btype = get_bounds_type(); + if (btype == BoundingVolume::BT_default) { + btype = bounds_type; + } + + if (btype == BoundingVolume::BT_sphere) { + internal_bounds = new BoundingSphere(LPoint3(0.5, 0.5, 0.5), csqrt(0.75)); + } else { + internal_bounds = new BoundingBox(LPoint3(0, 0, 0), LPoint3(1, 1, 1)); + } + + internal_vertices = 0; +} + /** * @brief Traverses the quadtree * @details This method traverses the given chunk, deciding whether it should diff --git a/panda/src/grutil/shaderTerrainMesh.h b/panda/src/grutil/shaderTerrainMesh.h index 9c4f8d9a3a..9b08e12c0d 100644 --- a/panda/src/grutil/shaderTerrainMesh.h +++ b/panda/src/grutil/shaderTerrainMesh.h @@ -91,6 +91,16 @@ public: virtual void add_for_draw(CullTraverser *trav, CullTraverserData &data); private: + virtual CPT(TransformState) + calc_tight_bounds(LPoint3 &min_point, LPoint3 &max_point, + bool &found_any, + const TransformState *transform, + Thread *current_thread = Thread::get_current_thread()) const; + + virtual void compute_internal_bounds(CPT(BoundingVolume) &internal_bounds, + int &internal_vertices, + int pipeline_stage, + Thread *current_thread) const; // Chunk data struct Chunk {