mirror of
https://github.com/panda3d/panda3d.git
synced 2025-10-04 10:54:24 -04:00
239 lines
6.7 KiB
C++
239 lines
6.7 KiB
C++
// Filename: directRenderTraverser.cxx
|
|
// Created by: drose (18Feb99)
|
|
//
|
|
////////////////////////////////////////////////////////////////////
|
|
|
|
#include "directRenderTraverser.h"
|
|
#include "config_sgraphutil.h"
|
|
#include "frustumCullTraverser.h"
|
|
|
|
#include <wrt.h>
|
|
#include <geomNode.h>
|
|
#include <graphicsStateGuardian.h>
|
|
#include <geometricBoundingVolume.h>
|
|
#include <projectionNode.h>
|
|
#include <projection.h>
|
|
#include <colorTransition.h>
|
|
#include <renderModeTransition.h>
|
|
#include <textureTransition.h>
|
|
#include <transformTransition.h>
|
|
#include <allAttributesWrapper.h>
|
|
#include <allTransitionsWrapper.h>
|
|
#include <transformTransition.h>
|
|
#include <nodeTransitionWrapper.h>
|
|
#include <decalTransition.h>
|
|
#include <decalAttribute.h>
|
|
#include <pStatTimer.h>
|
|
#include <config_sgattrib.h> // for support_decals
|
|
|
|
TypeHandle DirectRenderTraverser::_type_handle;
|
|
PStatCollector DirectRenderTraverser::_draw_pcollector =
|
|
PStatCollector("Draw", RGBColorf(1,0,0), 20);
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: DirectRenderTraverser::Constructor
|
|
// Access: Public
|
|
// Description:
|
|
////////////////////////////////////////////////////////////////////
|
|
DirectRenderTraverser::
|
|
DirectRenderTraverser(GraphicsStateGuardian *gsg, TypeHandle graph_type,
|
|
const ArcChain &arc_chain) :
|
|
RenderTraverser(gsg, graph_type, arc_chain)
|
|
{
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: DirectRenderTraverser::Destructor
|
|
// Access: Public, Virtual
|
|
// Description:
|
|
////////////////////////////////////////////////////////////////////
|
|
DirectRenderTraverser::
|
|
~DirectRenderTraverser() {
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: DirectRenderTraverser::traverse
|
|
// Access: Public, Virtual
|
|
// Description: This performs a normal, complete render traversal
|
|
// using this DirectRenderTraverser object.
|
|
////////////////////////////////////////////////////////////////////
|
|
void DirectRenderTraverser::
|
|
traverse(Node *root,
|
|
const AllAttributesWrapper &initial_state,
|
|
const AllTransitionsWrapper &net_trans) {
|
|
// Statistics
|
|
PStatTimer timer(_draw_pcollector);
|
|
|
|
AllAttributesWrapper render_state;
|
|
render_state.apply_from(initial_state, net_trans);
|
|
|
|
DirectRenderLevelState level_state;
|
|
|
|
#ifndef NDEBUG
|
|
if (support_decals != SD_off)
|
|
#endif
|
|
{
|
|
DecalAttribute *decal_attrib;
|
|
if (get_attribute_into(decal_attrib, render_state,
|
|
DecalTransition::get_class_type())) {
|
|
level_state._decal_mode = decal_attrib->is_on();
|
|
}
|
|
}
|
|
|
|
// Determine the relative transform matrix from the camera to our
|
|
// starting node. This is important for proper view-frustum
|
|
// culling.
|
|
LMatrix4f rel_from_camera;
|
|
NodeTransitionWrapper ntw(TransformTransition::get_class_type());
|
|
wrt(_gsg->get_current_projection_node(), root, begin(), end(),
|
|
ntw, get_graph_type());
|
|
const TransformTransition *tt;
|
|
if (get_transition_into(tt, ntw)) {
|
|
rel_from_camera = tt->get_matrix();
|
|
} else {
|
|
// No relative transform.
|
|
rel_from_camera = LMatrix4f::ident_mat();
|
|
}
|
|
|
|
fc_traverse(_arc_chain, root, rel_from_camera, *this,
|
|
render_state, level_state, _gsg, _graph_type);
|
|
|
|
if (level_state._decal_mode &&
|
|
root->is_of_type(GeomNode::get_class_type())) {
|
|
#ifndef NDEBUG
|
|
if (support_decals == SD_hide) {
|
|
return;
|
|
}
|
|
#endif
|
|
// Close the decal.
|
|
_gsg->end_decal(DCAST(GeomNode, root));
|
|
}
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: DirectRenderTraverser::reached_node
|
|
// Access:
|
|
// Description:
|
|
////////////////////////////////////////////////////////////////////
|
|
bool DirectRenderTraverser::
|
|
reached_node(Node *node, AllAttributesWrapper &render_state,
|
|
DirectRenderLevelState &level_state) {
|
|
if (implicit_app_traversal) {
|
|
node->app_traverse();
|
|
}
|
|
node->draw_traverse();
|
|
|
|
level_state._decal_mode = false;
|
|
|
|
AllTransitionsWrapper new_trans;
|
|
|
|
#ifndef NDEBUG
|
|
if (support_subrender == SD_on)
|
|
#endif
|
|
{
|
|
if (!node->sub_render(render_state, new_trans, this)) {
|
|
return false;
|
|
}
|
|
render_state.apply_in_place(new_trans);
|
|
}
|
|
|
|
if (node->is_of_type(GeomNode::get_class_type())) {
|
|
_gsg->set_state(render_state.get_attributes(), true);
|
|
// Make sure the current display region is still in effect.
|
|
_gsg->prepare_display_region();
|
|
|
|
GeomNode *geom = DCAST(GeomNode, node);
|
|
|
|
// We must make decals a special case, because they're so strange.
|
|
#ifndef NDEBUG
|
|
if (support_decals != SD_off)
|
|
#endif
|
|
{
|
|
DecalAttribute *decal_attrib;
|
|
if (get_attribute_into(decal_attrib, render_state,
|
|
DecalTransition::get_class_type())) {
|
|
level_state._decal_mode = decal_attrib->is_on();
|
|
}
|
|
}
|
|
|
|
if (level_state._decal_mode) {
|
|
#ifndef NDEBUG
|
|
if (support_decals == SD_hide) {
|
|
level_state._decal_mode = false;
|
|
geom->draw(_gsg);
|
|
return false;
|
|
}
|
|
#endif
|
|
_gsg->begin_decal(geom);
|
|
|
|
} else {
|
|
geom->draw(_gsg);
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: DirectRenderTraverser::forward_arc
|
|
// Access:
|
|
// Description:
|
|
////////////////////////////////////////////////////////////////////
|
|
bool DirectRenderTraverser::
|
|
forward_arc(NodeRelation *arc, AllTransitionsWrapper &trans,
|
|
AllAttributesWrapper &, AllAttributesWrapper &post,
|
|
DirectRenderLevelState &) {
|
|
bool carry_on = true;
|
|
|
|
// Go through all the transitions on the arc and sub_render() on
|
|
// each one. For most transition types, this will be a no-op and
|
|
// return true. For Shader types, this will fire off another render
|
|
// and return false.
|
|
|
|
mark_forward_arc(arc);
|
|
|
|
#ifndef NDEBUG
|
|
if (support_subrender == SD_on)
|
|
#endif
|
|
{
|
|
AllTransitionsWrapper::const_iterator nti;
|
|
for (nti = trans.begin(); nti != trans.end(); ++nti) {
|
|
NodeTransition *t = (*nti).second.get_trans();
|
|
AllTransitionsWrapper new_trans;
|
|
if (!t->sub_render(arc, post, new_trans, this)) {
|
|
carry_on = false;
|
|
}
|
|
post.apply_in_place(new_trans);
|
|
}
|
|
}
|
|
|
|
if (!carry_on) {
|
|
mark_backward_arc(arc);
|
|
}
|
|
|
|
return carry_on;
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: DirectRenderTraverser::backward_arc
|
|
// Access:
|
|
// Description:
|
|
////////////////////////////////////////////////////////////////////
|
|
void DirectRenderTraverser::
|
|
backward_arc(NodeRelation *arc, AllTransitionsWrapper &,
|
|
AllAttributesWrapper &, AllAttributesWrapper &post,
|
|
const DirectRenderLevelState &level_state) {
|
|
mark_backward_arc(arc);
|
|
if (level_state._decal_mode) {
|
|
// Reset the state to redraw the base geometry.
|
|
_gsg->set_state(post.get_attributes(), true);
|
|
_gsg->prepare_display_region();
|
|
_gsg->end_decal(DCAST(GeomNode, arc->get_child()));
|
|
}
|
|
}
|
|
|