164 lines
4.7 KiB
Text
164 lines
4.7 KiB
Text
|
/**
|
||
|
* PANDA 3D SOFTWARE
|
||
|
* Copyright (c) Carnegie Mellon University. All rights reserved.
|
||
|
*
|
||
|
* All use of this software is subject to the terms of the revised BSD
|
||
|
* license. You should have received a copy of this license along
|
||
|
* with this source code in a file named "LICENSE."
|
||
|
*
|
||
|
* @file cullTraverserData.I
|
||
|
* @author drose
|
||
|
* @date 2002-03-06
|
||
|
*/
|
||
|
|
||
|
/**
|
||
|
*
|
||
|
*/
|
||
|
INLINE CullTraverserData::
|
||
|
CullTraverserData(const NodePath &start,
|
||
|
const TransformState *net_transform,
|
||
|
const RenderState *state,
|
||
|
GeometricBoundingVolume *view_frustum,
|
||
|
Thread *current_thread) :
|
||
|
_next(nullptr),
|
||
|
_start(start._head),
|
||
|
_node_reader(start.node(), current_thread),
|
||
|
_net_transform(net_transform),
|
||
|
_state(state),
|
||
|
_view_frustum(view_frustum),
|
||
|
_cull_planes(CullPlanes::make_empty()),
|
||
|
_draw_mask(DrawMask::all_on()),
|
||
|
_portal_depth(0)
|
||
|
{
|
||
|
// Only update the bounding volume if we're going to end up needing it.
|
||
|
bool check_bounds = (view_frustum != nullptr);
|
||
|
_node_reader.check_cached(check_bounds);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* This constructor creates a CullTraverserData object that reflects the next
|
||
|
* node down in the traversal.
|
||
|
*/
|
||
|
INLINE CullTraverserData::
|
||
|
CullTraverserData(const CullTraverserData &parent, PandaNode *child) :
|
||
|
_next(&parent),
|
||
|
#ifdef _DEBUG
|
||
|
_start(nullptr),
|
||
|
#endif
|
||
|
_node_reader(child, parent._node_reader.get_current_thread()),
|
||
|
_net_transform(parent._net_transform),
|
||
|
_state(parent._state),
|
||
|
_view_frustum(parent._view_frustum),
|
||
|
_cull_planes(parent._cull_planes),
|
||
|
_draw_mask(parent._draw_mask),
|
||
|
_portal_depth(parent._portal_depth)
|
||
|
{
|
||
|
// Only update the bounding volume if we're going to end up needing it.
|
||
|
bool check_bounds = !_cull_planes->is_empty() ||
|
||
|
(_view_frustum != nullptr);
|
||
|
_node_reader.check_cached(check_bounds);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Returns the node traversed to so far.
|
||
|
*/
|
||
|
INLINE PandaNode *CullTraverserData::
|
||
|
node() const {
|
||
|
return (PandaNode *)_node_reader.get_node();
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Returns the PipelineReader for the node traversed to so far.
|
||
|
*/
|
||
|
INLINE PandaNodePipelineReader *CullTraverserData::
|
||
|
node_reader() {
|
||
|
return &_node_reader;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Returns the PipelineReader for the node traversed to so far.
|
||
|
*/
|
||
|
INLINE const PandaNodePipelineReader *CullTraverserData::
|
||
|
node_reader() const {
|
||
|
return &_node_reader;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Constructs and returns an actual NodePath that represents the same path we
|
||
|
* have just traversed.
|
||
|
*/
|
||
|
INLINE NodePath CullTraverserData::
|
||
|
get_node_path() const {
|
||
|
NodePath result;
|
||
|
result._head = r_get_node_path();
|
||
|
nassertr(result._head != nullptr, NodePath::fail());
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Returns the modelview transform: the relative transform from the camera to
|
||
|
* the model.
|
||
|
*/
|
||
|
INLINE CPT(TransformState) CullTraverserData::
|
||
|
get_modelview_transform(const CullTraverser *trav) const {
|
||
|
return trav->get_world_transform()->compose(_net_transform);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Returns the internal transform: the modelview transform in the GSG's
|
||
|
* internal coordinate system.
|
||
|
*/
|
||
|
INLINE CPT(TransformState) CullTraverserData::
|
||
|
get_internal_transform(const CullTraverser *trav) const {
|
||
|
return trav->get_scene()->get_cs_world_transform()->compose(_net_transform);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Returns the net transform: the relative transform from root of the scene
|
||
|
* graph to the current node.
|
||
|
*/
|
||
|
INLINE const TransformState *CullTraverserData::
|
||
|
get_net_transform(const CullTraverser *) const {
|
||
|
return _net_transform;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Returns true if the current node is within the view frustum, false
|
||
|
* otherwise. If the node's bounding volume falls completely within the view
|
||
|
* frustum, this will also reset the view frustum pointer, saving some work
|
||
|
* for future nodes.
|
||
|
*/
|
||
|
INLINE bool CullTraverserData::
|
||
|
is_in_view(const DrawMask &camera_mask) {
|
||
|
if (_node_reader.get_transform()->is_invalid()) {
|
||
|
// If the transform is invalid, forget it.
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
if (!_node_reader.compare_draw_mask(_draw_mask, camera_mask)) {
|
||
|
// If there are no draw bits in common with the camera, the node is out.
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
if (_view_frustum == nullptr &&
|
||
|
_cull_planes->is_empty()) {
|
||
|
// If the transform is valid, but we don't have a frustum or any clip
|
||
|
// planes or occluders, it's always in.
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
// Otherwise, compare the bounding volume to the frustum.
|
||
|
return is_in_view_impl();
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Returns true if this particular node is hidden, even though we might be
|
||
|
* traversing past this node to find a child node that has had show_through()
|
||
|
* called for it. If this returns true, the node should not be rendered.
|
||
|
*/
|
||
|
INLINE bool CullTraverserData::
|
||
|
is_this_node_hidden(const DrawMask &camera_mask) const {
|
||
|
return (_draw_mask & PandaNode::get_overall_bit()).is_zero() ||
|
||
|
(_draw_mask & camera_mask).is_zero();
|
||
|
}
|