mirror of
https://github.com/panda3d/panda3d.git
synced 2025-10-03 02:15:43 -04:00
pgraph lod, sequence nodes
This commit is contained in:
parent
6cdf757749
commit
8b743a58fe
@ -942,8 +942,8 @@ begin_decal_base_first() {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
CPT(RenderState) GraphicsStateGuardian::
|
||||
begin_decal_nested() {
|
||||
// We keep the depth buffer off during this operation, although
|
||||
// perhaps it doesn't matter so much here.
|
||||
// We should keep the depth buffer off during this operation, so
|
||||
// that decals on decals will render properly.
|
||||
static CPT(RenderState) decal_nested;
|
||||
if (decal_nested == (const RenderState *)NULL) {
|
||||
decal_nested = RenderState::make
|
||||
|
@ -10,11 +10,13 @@
|
||||
|
||||
#define SOURCES \
|
||||
config_egg2pg.h \
|
||||
eggBinner.h \
|
||||
qpeggLoader.h \
|
||||
qpload_egg_file.h
|
||||
|
||||
#define INCLUDED_SOURCES \
|
||||
config_egg2pg.cxx \
|
||||
eggBinner.cxx \
|
||||
qpeggLoader.cxx \
|
||||
qpload_egg_file.cxx
|
||||
|
||||
@ -26,6 +28,7 @@
|
||||
|
||||
#define INSTALL_HEADERS \
|
||||
config_egg2pg.h \
|
||||
eggBinner.h \
|
||||
qpeggLoader.h \
|
||||
qpload_egg_file.h
|
||||
|
||||
|
@ -1,2 +1,2 @@
|
||||
#include "config_egg2pg.cxx"
|
||||
#include "qpeggLoader.cxx"
|
||||
#include "eggBinner.cxx"
|
||||
|
@ -1 +1,3 @@
|
||||
#include "qpeggLoader.cxx"
|
||||
#include "qpload_egg_file.cxx"
|
||||
|
||||
|
@ -18,10 +18,9 @@
|
||||
|
||||
#include "eggBinner.h"
|
||||
|
||||
#include <eggSwitchCondition.h>
|
||||
#include <eggGroup.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include "eggSwitchCondition.h"
|
||||
#include "eggGroup.h"
|
||||
#include "dcast.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: EggBinner::get_bin_number
|
@ -19,9 +19,9 @@
|
||||
#ifndef EGGBINNER_H
|
||||
#define EGGBINNER_H
|
||||
|
||||
#include <pandabase.h>
|
||||
#include "pandabase.h"
|
||||
|
||||
#include <eggBinMaker.h>
|
||||
#include "eggBinMaker.h"
|
||||
|
||||
///////////////////////////////////////////////////////////////////
|
||||
// Class : EggBinner
|
@ -35,6 +35,8 @@
|
||||
#include "materialAttrib.h"
|
||||
#include "materialPool.h"
|
||||
#include "qpgeomNode.h"
|
||||
#include "qpsequenceNode.h"
|
||||
#include "qplodNode.h"
|
||||
#include "string_utils.h"
|
||||
#include "eggPrimitive.h"
|
||||
#include "eggPoint.h"
|
||||
@ -45,41 +47,40 @@
|
||||
#include "eggPolygon.h"
|
||||
#include "eggBin.h"
|
||||
#include "eggTable.h"
|
||||
#include "eggBinner.h"
|
||||
#include "nodeChain.h"
|
||||
|
||||
#include <ctype.h>
|
||||
#include <algorithm>
|
||||
|
||||
/*
|
||||
// This class is used in make_node(EggBin *) to sort LOD instances in
|
||||
// order by switching distance.
|
||||
class LODInstance {
|
||||
public:
|
||||
LODInstance(EggNode *egg_node, RenderRelation *arc);
|
||||
LODInstance(EggNode *egg_node);
|
||||
bool operator < (const LODInstance &other) const {
|
||||
return _d->_switch_in < other._d->_switch_in;
|
||||
}
|
||||
|
||||
RenderRelation *_arc;
|
||||
EggNode *_egg_node;
|
||||
const EggSwitchConditionDistance *_d;
|
||||
};
|
||||
|
||||
LODInstance::
|
||||
LODInstance(EggNode *egg_node, RenderRelation *arc) {
|
||||
assert(arc != NULL);
|
||||
_arc = arc;
|
||||
LODInstance(EggNode *egg_node) {
|
||||
nassertv(egg_node != NULL);
|
||||
_egg_node = egg_node;
|
||||
|
||||
// We expect this egg node to be an EggGroup with an LOD
|
||||
// specification. That's what the EggBinner collected together,
|
||||
// after all.
|
||||
EggGroup *egg_group = DCAST(EggGroup, egg_node);
|
||||
assert(egg_group->has_lod());
|
||||
nassertv(egg_group->has_lod());
|
||||
const EggSwitchCondition &sw = egg_group->get_lod();
|
||||
|
||||
// For now, this is the only kind of switch condition there is.
|
||||
_d = DCAST(EggSwitchConditionDistance, &sw);
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
@ -116,11 +117,9 @@ void qpEggLoader::
|
||||
build_graph() {
|
||||
// _deferred_arcs.clear();
|
||||
|
||||
/*
|
||||
// First, bin up the LOD nodes.
|
||||
EggBinner binner;
|
||||
binner.make_bins(&_data);
|
||||
*/
|
||||
|
||||
// Then load up all of the textures.
|
||||
load_textures();
|
||||
@ -1201,23 +1200,18 @@ make_node(EggPrimitive *egg_prim, PandaNode *parent) {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
PandaNode *qpEggLoader::
|
||||
make_node(EggBin *egg_bin, PandaNode *parent) {
|
||||
return (PandaNode *)NULL;
|
||||
/*
|
||||
// Presently, an EggBin can only mean an LOD node (i.e. a parent of
|
||||
// one or more EggGroups with LOD specifications). Later it might
|
||||
// mean other things as well.
|
||||
|
||||
assert((EggBinner::BinNumber)egg_bin->get_bin_number() == EggBinner::BN_lod);
|
||||
LODNode *lod_node = new LODNode;
|
||||
lod_node->set_name(egg_bin->get_name());
|
||||
nassertr((EggBinner::BinNumber)egg_bin->get_bin_number() == EggBinner::BN_lod, NULL);
|
||||
qpLODNode *lod_node = new qpLODNode(egg_bin->get_name());
|
||||
|
||||
pvector<LODInstance> instances;
|
||||
|
||||
EggGroup::const_iterator ci;
|
||||
for (ci = egg_bin->begin(); ci != egg_bin->end(); ++ci) {
|
||||
PandaNode *arc = make_node(*ci, lod_node);
|
||||
assert(arc != (PandaNode *)NULL);
|
||||
LODInstance instance(*ci, arc);
|
||||
LODInstance instance(*ci);
|
||||
instances.push_back(instance);
|
||||
}
|
||||
|
||||
@ -1228,26 +1222,24 @@ make_node(EggBin *egg_bin, PandaNode *parent) {
|
||||
if (!instances.empty()) {
|
||||
// Set up the LOD node's center. All of the children should have
|
||||
// the same center, because that's how we binned them.
|
||||
lod_node->_lod._center = LCAST(float, instances[0]._d->_center);
|
||||
lod_node->set_center(LCAST(float, instances[0]._d->_center));
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < instances.size(); i++) {
|
||||
// Put the children in the proper order within the scene graph.
|
||||
// Create the children in the proper order within the scene graph.
|
||||
const LODInstance &instance = instances[i];
|
||||
make_node(instance._egg_node, lod_node);
|
||||
|
||||
// All of the children should have the same center, because that's
|
||||
// how we binned them.
|
||||
assert(lod_node->_lod._center.almost_equal
|
||||
(LCAST(float, instance._d->_center), 0.01));
|
||||
|
||||
instance._arc->set_sort(i);
|
||||
nassertr(lod_node->get_center().almost_equal
|
||||
(LCAST(float, instance._d->_center), 0.01), NULL);
|
||||
|
||||
// Tell the LOD node about this child's switching distances.
|
||||
lod_node->add_switch(instance._d->_switch_in, instance._d->_switch_out);
|
||||
}
|
||||
|
||||
return create_group_arc(egg_bin, parent, lod_node);
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
@ -1379,16 +1371,14 @@ make_node(EggGroup *egg_group, PandaNode *parent) {
|
||||
|
||||
} else if (egg_group->get_switch_flag() &&
|
||||
egg_group->get_switch_fps() != 0.0) {
|
||||
/*
|
||||
// Create a sequence node.
|
||||
node = new SequenceNode(1.0 / egg_group->get_switch_fps());
|
||||
node->set_name(egg_group->get_name());
|
||||
node = new qpSequenceNode(egg_group->get_switch_fps(),
|
||||
egg_group->get_name());
|
||||
|
||||
EggGroup::const_iterator ci;
|
||||
for (ci = egg_group->begin(); ci != egg_group->end(); ++ci) {
|
||||
make_node(*ci, node);
|
||||
}
|
||||
*/
|
||||
|
||||
} else if (egg_group->get_model_flag() || egg_group->get_dcs_flag()) {
|
||||
// A model or DCS flag; create a model node.
|
||||
|
@ -13,13 +13,13 @@
|
||||
#define SOURCES \
|
||||
animBundleMaker.h characterMaker.h computedVerticesMaker.I \
|
||||
computedVerticesMaker.h config_egg2sg.h \
|
||||
deferredArcProperty.h deferredArcTraverser.h eggBinner.h \
|
||||
deferredArcProperty.h deferredArcTraverser.h \
|
||||
eggLoader.h load_egg_file.h loaderFileTypeEgg.h
|
||||
|
||||
#define INCLUDED_SOURCES \
|
||||
animBundleMaker.cxx characterMaker.cxx computedVerticesMaker.cxx \
|
||||
config_egg2sg.cxx deferredArcProperty.cxx \
|
||||
deferredArcTraverser.cxx eggBinner.cxx eggLoader.cxx \
|
||||
deferredArcTraverser.cxx eggLoader.cxx \
|
||||
load_egg_file.cxx loaderFileTypeEgg.cxx
|
||||
|
||||
#define INSTALL_HEADERS \
|
||||
|
@ -1,6 +1,5 @@
|
||||
|
||||
#include "config_egg2sg.cxx"
|
||||
#include "eggBinner.cxx"
|
||||
#include "eggLoader.cxx"
|
||||
#include "load_egg_file.cxx"
|
||||
#include "loaderFileTypeEgg.cxx"
|
||||
|
@ -21,6 +21,7 @@
|
||||
cullHandler.h cullHandler.I \
|
||||
cullResult.h cullResult.I \
|
||||
qpcullTraverser.h qpcullTraverser.I \
|
||||
cullTraverserData.h cullTraverserData.I \
|
||||
cullableObject.h cullableObject.I \
|
||||
decalAttrib.h decalAttrib.I \
|
||||
depthTestAttrib.h depthTestAttrib.I \
|
||||
@ -28,12 +29,15 @@
|
||||
drawCullHandler.h drawCullHandler.I \
|
||||
qpgeomNode.h qpgeomNode.I \
|
||||
qplensNode.h qplensNode.I \
|
||||
qplodNode.h qplodNode.I \
|
||||
materialAttrib.h materialAttrib.I \
|
||||
nodeChain.h nodeChain.I \
|
||||
nodeChainComponent.h nodeChainComponent.I \
|
||||
pandaNode.h pandaNode.I \
|
||||
renderAttrib.h renderAttrib.I \
|
||||
renderState.h renderState.I \
|
||||
selectiveChildNode.h selectiveChildNode.I \
|
||||
qpsequenceNode.h qpsequenceNode.I \
|
||||
textureApplyAttrib.h textureApplyAttrib.I \
|
||||
textureAttrib.h textureAttrib.I \
|
||||
transformState.h transformState.I \
|
||||
@ -56,6 +60,7 @@
|
||||
cullHandler.cxx \
|
||||
cullResult.cxx \
|
||||
qpcullTraverser.cxx \
|
||||
cullTraverserData.cxx \
|
||||
cullableObject.cxx \
|
||||
decalAttrib.cxx \
|
||||
depthTestAttrib.cxx \
|
||||
@ -63,12 +68,15 @@
|
||||
drawCullHandler.cxx \
|
||||
qpgeomNode.cxx \
|
||||
qplensNode.cxx \
|
||||
qplodNode.cxx \
|
||||
materialAttrib.cxx \
|
||||
nodeChain.cxx \
|
||||
nodeChainComponent.cxx \
|
||||
pandaNode.cxx \
|
||||
renderAttrib.cxx \
|
||||
renderState.cxx \
|
||||
selectiveChildNode.cxx \
|
||||
qpsequenceNode.cxx \
|
||||
textureApplyAttrib.cxx \
|
||||
textureAttrib.cxx \
|
||||
transformState.cxx \
|
||||
@ -96,6 +104,7 @@
|
||||
cullHandler.h cullHandler.I \
|
||||
cullResult.h cullResult.I \
|
||||
qpcullTraverser.h qpcullTraverser.I \
|
||||
cullTraverserData.h cullTraverserData.I \
|
||||
cullableObject.h cullableObject.I \
|
||||
decalAttrib.h decalAttrib.I \
|
||||
depthTestAttrib.h depthTestAttrib.I \
|
||||
@ -103,12 +112,15 @@
|
||||
drawCullHandler.h drawCullHandler.I \
|
||||
qpgeomNode.h qpgeomNode.I \
|
||||
qplensNode.h qplensNode.I \
|
||||
qplodNode.h qplodNode.I \
|
||||
materialAttrib.h materialAttrib.I \
|
||||
nodeChain.h nodeChain.I \
|
||||
nodeChainComponent.h nodeChainComponent.I \
|
||||
pandaNode.h pandaNode.I \
|
||||
renderAttrib.h renderAttrib.I \
|
||||
renderState.h renderState.I \
|
||||
selectiveChildNode.h selectiveChildNode.I \
|
||||
qpsequenceNode.h qpsequenceNode.I \
|
||||
textureApplyAttrib.h textureApplyAttrib.I \
|
||||
textureAttrib.h textureAttrib.I \
|
||||
transformState.h transformState.I \
|
||||
|
@ -33,12 +33,15 @@
|
||||
#include "depthWriteAttrib.h"
|
||||
#include "qpgeomNode.h"
|
||||
#include "qplensNode.h"
|
||||
#include "qplodNode.h"
|
||||
#include "materialAttrib.h"
|
||||
#include "nodeChain.h"
|
||||
#include "nodeChainComponent.h"
|
||||
#include "pandaNode.h"
|
||||
#include "renderAttrib.h"
|
||||
#include "renderState.h"
|
||||
#include "selectiveChildNode.h"
|
||||
#include "qpsequenceNode.h"
|
||||
#include "textureApplyAttrib.h"
|
||||
#include "textureAttrib.h"
|
||||
#include "transformState.h"
|
||||
@ -90,18 +93,22 @@ init_libpgraph() {
|
||||
DepthWriteAttrib::init_type();
|
||||
qpGeomNode::init_type();
|
||||
qpLensNode::init_type();
|
||||
qpLODNode::init_type();
|
||||
MaterialAttrib::init_type();
|
||||
NodeChain::init_type();
|
||||
NodeChainComponent::init_type();
|
||||
PandaNode::init_type();
|
||||
RenderAttrib::init_type();
|
||||
RenderState::init_type();
|
||||
SelectiveChildNode::init_type();
|
||||
qpSequenceNode::init_type();
|
||||
TextureApplyAttrib::init_type();
|
||||
TextureAttrib::init_type();
|
||||
TransformState::init_type();
|
||||
TransparencyAttrib::init_type();
|
||||
|
||||
BillboardAttrib::register_with_read_factory();
|
||||
qpCamera::register_with_read_factory();
|
||||
ColorAttrib::register_with_read_factory();
|
||||
ColorWriteAttrib::register_with_read_factory();
|
||||
CullBinAttrib::register_with_read_factory();
|
||||
@ -110,9 +117,12 @@ init_libpgraph() {
|
||||
DepthTestAttrib::register_with_read_factory();
|
||||
DepthWriteAttrib::register_with_read_factory();
|
||||
qpGeomNode::register_with_read_factory();
|
||||
qpLensNode::register_with_read_factory();
|
||||
qpLODNode::register_with_read_factory();
|
||||
MaterialAttrib::register_with_read_factory();
|
||||
PandaNode::register_with_read_factory();
|
||||
RenderState::register_with_read_factory();
|
||||
qpSequenceNode::register_with_read_factory();
|
||||
TextureApplyAttrib::register_with_read_factory();
|
||||
TextureAttrib::register_with_read_factory();
|
||||
TransformState::register_with_read_factory();
|
||||
|
97
panda/src/pgraph/cullTraverserData.I
Normal file
97
panda/src/pgraph/cullTraverserData.I
Normal file
@ -0,0 +1,97 @@
|
||||
// Filename: cullTraverserData.I
|
||||
// Created by: drose (06Mar02)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
|
||||
//
|
||||
// All use of this software is subject to the terms of the Panda 3d
|
||||
// Software license. You should have received a copy of this license
|
||||
// along with this source code; you will also find a current copy of
|
||||
// the license at http://www.panda3d.org/license.txt .
|
||||
//
|
||||
// To contact the maintainers of this program write to
|
||||
// panda3d@yahoogroups.com .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CullTraverserData::Constructor
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE CullTraverserData::
|
||||
CullTraverserData(const TransformState *render_transform,
|
||||
const TransformState *net_transform,
|
||||
const RenderState *state,
|
||||
GeometricBoundingVolume *view_frustum,
|
||||
GeometricBoundingVolume *guard_band,
|
||||
const TransformState *camera_transform) :
|
||||
_render_transform(render_transform),
|
||||
_net_transform(net_transform),
|
||||
_state(state),
|
||||
_view_frustum(view_frustum),
|
||||
_guard_band(guard_band),
|
||||
_camera_transform(camera_transform)
|
||||
{
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CullTraverserData::Copy Constructor
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE CullTraverserData::
|
||||
CullTraverserData(const CullTraverserData ©) :
|
||||
_render_transform(copy._render_transform),
|
||||
_net_transform(copy._net_transform),
|
||||
_state(copy._state),
|
||||
_view_frustum(copy._view_frustum),
|
||||
_guard_band(copy._guard_band),
|
||||
_camera_transform(copy._camera_transform)
|
||||
{
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CullTraverserData::Copy Assignment Operator
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void CullTraverserData::
|
||||
operator = (const CullTraverserData ©) {
|
||||
_render_transform = copy._render_transform;
|
||||
_net_transform = copy._net_transform;
|
||||
_state = copy._state;
|
||||
_view_frustum = copy._view_frustum;
|
||||
_guard_band = copy._guard_band;
|
||||
_camera_transform = copy._camera_transform;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CullTraverserData::Destructor
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE CullTraverserData::
|
||||
~CullTraverserData() {
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CullTraverserData::is_in_view
|
||||
// Access: Public
|
||||
// Description: Returns true if the 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(PandaNode *node) {
|
||||
if (_view_frustum == (GeometricBoundingVolume *)NULL) {
|
||||
// If we don't have a frustum, we're always in.
|
||||
return true;
|
||||
}
|
||||
return is_in_view_impl(node);
|
||||
}
|
158
panda/src/pgraph/cullTraverserData.cxx
Normal file
158
panda/src/pgraph/cullTraverserData.cxx
Normal file
@ -0,0 +1,158 @@
|
||||
// Filename: cullTraverserData.cxx
|
||||
// Created by: drose (06Mar02)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
|
||||
//
|
||||
// All use of this software is subject to the terms of the Panda 3d
|
||||
// Software license. You should have received a copy of this license
|
||||
// along with this source code; you will also find a current copy of
|
||||
// the license at http://www.panda3d.org/license.txt .
|
||||
//
|
||||
// To contact the maintainers of this program write to
|
||||
// panda3d@yahoogroups.com .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "cullTraverserData.h"
|
||||
#include "config_pgraph.h"
|
||||
#include "pandaNode.h"
|
||||
#include "colorAttrib.h"
|
||||
#include "textureAttrib.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CullTraverserData::apply_transform_and_state
|
||||
// Access: Public
|
||||
// Description: Applies the transform and state from the indicated
|
||||
// node onto the current data. This also evaluates
|
||||
// billboards, etc.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void CullTraverserData::
|
||||
apply_transform_and_state(PandaNode *node) {
|
||||
const TransformState *node_transform = node->get_transform();
|
||||
if (!node_transform->is_identity()) {
|
||||
_render_transform = _render_transform->compose(node_transform);
|
||||
_net_transform = _net_transform->compose(node_transform);
|
||||
|
||||
if ((_view_frustum != (GeometricBoundingVolume *)NULL) ||
|
||||
(_guard_band != (GeometricBoundingVolume *)NULL)) {
|
||||
// We need to move the viewing frustums into the node's
|
||||
// coordinate space by applying the node's inverse transform.
|
||||
if (node_transform->is_singular()) {
|
||||
// But we can't invert a singular transform! Instead of
|
||||
// trying, we'll just give up on frustum culling from this
|
||||
// point down.
|
||||
_view_frustum = (GeometricBoundingVolume *)NULL;
|
||||
_guard_band = (GeometricBoundingVolume *)NULL;
|
||||
|
||||
} else {
|
||||
CPT(TransformState) inv_transform =
|
||||
node_transform->invert_compose(TransformState::make_identity());
|
||||
|
||||
// Copy the bounding volumes for the frustums so we can
|
||||
// transform them.
|
||||
if (_view_frustum != (GeometricBoundingVolume *)NULL) {
|
||||
_view_frustum = DCAST(GeometricBoundingVolume, _view_frustum->make_copy());
|
||||
_view_frustum->xform(inv_transform->get_mat());
|
||||
}
|
||||
|
||||
if (_guard_band != (GeometricBoundingVolume *)NULL) {
|
||||
_guard_band = DCAST(GeometricBoundingVolume, _guard_band->make_copy());
|
||||
_guard_band->xform(inv_transform->get_mat());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const RenderState *node_state = node->get_state();
|
||||
_state = _state->compose(node_state);
|
||||
|
||||
const BillboardAttrib *billboard = node_state->get_billboard();
|
||||
if (billboard != (const BillboardAttrib *)NULL) {
|
||||
// Got to apply a billboard transform here.
|
||||
CPT(TransformState) billboard_transform =
|
||||
billboard->do_billboard(_net_transform, _camera_transform);
|
||||
_render_transform = _render_transform->compose(billboard_transform);
|
||||
_net_transform = _net_transform->compose(billboard_transform);
|
||||
|
||||
// We can't reliably cull within a billboard, because the geometry
|
||||
// might get rotated out of its bounding volume. So once we get
|
||||
// within a billboard, we consider it all visible.
|
||||
_view_frustum = (GeometricBoundingVolume *)NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CullTraverserData::is_in_view_impl
|
||||
// Access: Private
|
||||
// Description: The private implementation of is_in_view().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool CullTraverserData::
|
||||
is_in_view_impl(PandaNode *node) {
|
||||
// By the time we get here, we know we have a viewing frustum.
|
||||
nassertr(_view_frustum != (GeometricBoundingVolume *)NULL, true);
|
||||
|
||||
const BoundingVolume &node_volume = node->get_bound();
|
||||
nassertr(node_volume.is_of_type(GeometricBoundingVolume::get_class_type()), false);
|
||||
const GeometricBoundingVolume *node_gbv =
|
||||
DCAST(GeometricBoundingVolume, &node_volume);
|
||||
|
||||
int result = _view_frustum->contains(node_gbv);
|
||||
if (result == BoundingVolume::IF_no_intersection) {
|
||||
// No intersection at all. Cull.
|
||||
if (!qpfake_view_frustum_cull) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// If we have fake view-frustum culling enabled, instead of
|
||||
// actually culling an object we simply force it to be drawn in
|
||||
// red wireframe.
|
||||
_view_frustum = (GeometricBoundingVolume *)NULL;
|
||||
CPT(RenderState) fake_effect = get_fake_view_frustum_cull_effect();
|
||||
_state = _state->compose(fake_effect);
|
||||
|
||||
} else if ((result & BoundingVolume::IF_all) != 0) {
|
||||
// The node and its descendants are completely enclosed within
|
||||
// the frustum. No need to cull further.
|
||||
_view_frustum = (GeometricBoundingVolume *)NULL;
|
||||
|
||||
} else {
|
||||
if (node->is_final()) {
|
||||
// The bounding volume is partially, but not completely,
|
||||
// within the viewing frustum. Normally we'd keep testing
|
||||
// child bounding volumes as we continue down. But this node
|
||||
// has the "final" flag, so the user is claiming that there is
|
||||
// some important reason we should consider everything visible
|
||||
// at this point. So be it.
|
||||
_view_frustum = (GeometricBoundingVolume *)NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CullTraverserData::get_fake_view_frustum_cull_effect
|
||||
// Access: Private, Static
|
||||
// Description: Returns a RenderState for rendering stuff in red
|
||||
// wireframe, strictly for the fake_view_frustum_cull
|
||||
// effect.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
CPT(RenderState) CullTraverserData::
|
||||
get_fake_view_frustum_cull_effect() {
|
||||
// Once someone asks for this pointer, we hold its reference count
|
||||
// and never free it.
|
||||
static CPT(RenderState) effect = (const RenderState *)NULL;
|
||||
if (effect == (const RenderState *)NULL) {
|
||||
effect = RenderState::make
|
||||
(ColorAttrib::make_flat(Colorf(1.0f, 0.0f, 0.0f, 1.0f)),
|
||||
TextureAttrib::make_off(),
|
||||
1000);
|
||||
}
|
||||
return effect;
|
||||
}
|
||||
|
79
panda/src/pgraph/cullTraverserData.h
Normal file
79
panda/src/pgraph/cullTraverserData.h
Normal file
@ -0,0 +1,79 @@
|
||||
// Filename: cullTraverserData.h
|
||||
// Created by: drose (06Mar02)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
|
||||
//
|
||||
// All use of this software is subject to the terms of the Panda 3d
|
||||
// Software license. You should have received a copy of this license
|
||||
// along with this source code; you will also find a current copy of
|
||||
// the license at http://www.panda3d.org/license.txt .
|
||||
//
|
||||
// To contact the maintainers of this program write to
|
||||
// panda3d@yahoogroups.com .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef CULLTRAVERSERDATA_H
|
||||
#define CULLTRAVERSERDATA_H
|
||||
|
||||
#include "pandabase.h"
|
||||
|
||||
#include "renderState.h"
|
||||
#include "transformState.h"
|
||||
#include "geometricBoundingVolume.h"
|
||||
#include "pointerTo.h"
|
||||
|
||||
class PandaNode;
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : CullTraverserData
|
||||
// Description : This collects together the pieces of data that are
|
||||
// accumulated for each node while walking the scene
|
||||
// graph during the cull traversal.
|
||||
//
|
||||
// Having this as a separate object simplifies the
|
||||
// parameter list to CullTraverser::r_traverse(), as
|
||||
// well as to other functions like
|
||||
// PandaNode::cull_callback(). It also makes it easier
|
||||
// to add cull parameters, and provides a place to
|
||||
// abstract out some of the cull behavior (like
|
||||
// view-frustum culling).
|
||||
////////////////////////////////////////////////////////////////////
|
||||
class EXPCL_PANDA CullTraverserData {
|
||||
public:
|
||||
INLINE CullTraverserData(const TransformState *render_transform,
|
||||
const TransformState *net_transform,
|
||||
const RenderState *state,
|
||||
GeometricBoundingVolume *view_frustum,
|
||||
GeometricBoundingVolume *guard_band,
|
||||
const TransformState *camera_transform);
|
||||
INLINE CullTraverserData(const CullTraverserData ©);
|
||||
INLINE void operator = (const CullTraverserData ©);
|
||||
INLINE ~CullTraverserData();
|
||||
|
||||
INLINE bool is_in_view(PandaNode *node);
|
||||
void apply_transform_and_state(PandaNode *node);
|
||||
|
||||
CPT(TransformState) _render_transform;
|
||||
CPT(TransformState) _net_transform;
|
||||
CPT(RenderState) _state;
|
||||
PT(GeometricBoundingVolume) _view_frustum;
|
||||
PT(GeometricBoundingVolume) _guard_band;
|
||||
|
||||
// This one is not modified during traversal, so it doesn't need to
|
||||
// be reference counted (we trust the original owner of this pointer
|
||||
// to reference count it and hold it during the lifetime of the
|
||||
// traversal).
|
||||
const TransformState *_camera_transform;
|
||||
|
||||
private:
|
||||
bool is_in_view_impl(PandaNode *node);
|
||||
static CPT(RenderState) get_fake_view_frustum_cull_effect();
|
||||
};
|
||||
|
||||
#include "cullTraverserData.I"
|
||||
|
||||
#endif
|
@ -19,7 +19,8 @@
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CullableObject::Constructor
|
||||
// Access: Public
|
||||
// Description:
|
||||
// Description: Creates an empty CullableObject whose pointers can be
|
||||
// filled in later.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE CullableObject::
|
||||
CullableObject(CullableObject *next) :
|
||||
@ -27,6 +28,25 @@ CullableObject(CullableObject *next) :
|
||||
{
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CullableObject::Constructor
|
||||
// Access: Public
|
||||
// Description: Creates a CullableObject based on the ith Geom from
|
||||
// the indicated GeomNode, with the render state from
|
||||
// the indicated CullTraverserData.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE CullableObject::
|
||||
CullableObject(const CullTraverserData &data,
|
||||
qpGeomNode *geom_node, int i,
|
||||
CullableObject *next) :
|
||||
_geom(geom_node->get_geom(i)),
|
||||
_state(data._state->compose(geom_node->get_geom_state(i))),
|
||||
_transform(data._render_transform),
|
||||
_next(next)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CullableObject::Copy Constructor
|
||||
// Access: Private
|
||||
|
@ -26,6 +26,8 @@
|
||||
#include "transformState.h"
|
||||
#include "pointerTo.h"
|
||||
#include "referenceCount.h"
|
||||
#include "qpgeomNode.h"
|
||||
#include "cullTraverserData.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : CullableObject
|
||||
@ -37,6 +39,14 @@
|
||||
class EXPCL_PANDA CullableObject {
|
||||
public:
|
||||
INLINE CullableObject(CullableObject *next = NULL);
|
||||
INLINE CullableObject(const CullTraverserData &data,
|
||||
qpGeomNode *geom_node, int i,
|
||||
CullableObject *next = NULL);
|
||||
|
||||
// We will allocate and destroy hundreds or thousands of these a
|
||||
// frame during the normal course of rendering. As an optimization,
|
||||
// then, we should consider implementing operator new and delete
|
||||
// here to minimize this overhead. Should be simple.
|
||||
|
||||
private:
|
||||
INLINE CullableObject(const CullableObject ©);
|
||||
|
@ -234,6 +234,97 @@ combine_with(PandaNode *other) {
|
||||
return (PandaNode *)NULL;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PandaNode::has_cull_callback
|
||||
// Access: Public, Virtual
|
||||
// Description: Should be overridden by derived classes to return
|
||||
// true if cull_callback() has been defined. Otherwise,
|
||||
// returns false to indicate cull_callback() does not
|
||||
// need to be called for this node during the cull
|
||||
// traversal.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool PandaNode::
|
||||
has_cull_callback() const {
|
||||
return false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PandaNode::cull_callback
|
||||
// Access: Public, Virtual
|
||||
// Description: If has_cull_callback() returns true, this function
|
||||
// will be called during the cull traversal to perform
|
||||
// any additional operations that should be performed at
|
||||
// cull time. This may include additional manipulation
|
||||
// of render state or additional visible/invisible
|
||||
// decisions, or any other arbitrary operation.
|
||||
//
|
||||
// By the time this function is called, the node has
|
||||
// already passed the bounding-volume test for the
|
||||
// viewing frustum, and the node's transform and state
|
||||
// have already been applied to the indicated
|
||||
// CullTraverserData object.
|
||||
//
|
||||
// The return value is true if this node should be
|
||||
// visible, or false if it should be culled.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool PandaNode::
|
||||
cull_callback(CullTraverserData &) {
|
||||
return true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PandaNode::has_selective_visibility
|
||||
// Access: Public, Virtual
|
||||
// Description: Should be overridden by derived classes to return
|
||||
// true if this kind of node has some restrictions on
|
||||
// the set of children that should be rendered. Node
|
||||
// with this property include LODNodes, SwitchNodes, and
|
||||
// SequenceNodes.
|
||||
//
|
||||
// If this function returns true,
|
||||
// get_first_visible_child() and
|
||||
// get_next_visible_child() will be called to walk
|
||||
// through the list of children during cull, instead of
|
||||
// iterating through the entire list. This method is
|
||||
// called after cull_callback(), so cull_callback() may
|
||||
// be responsible for the decisions as to which children
|
||||
// are visible at the moment.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool PandaNode::
|
||||
has_selective_visibility() const {
|
||||
return false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PandaNode::get_first_visible_child
|
||||
// Access: Public, Virtual
|
||||
// Description: Returns the index number of the first visible child
|
||||
// of this node, or a number >= get_num_children() if
|
||||
// there are no visible children of this node. This is
|
||||
// called during the cull traversal, but only if
|
||||
// has_selective_visibility() has already returned true.
|
||||
// See has_selective_visibility().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
int PandaNode::
|
||||
get_first_visible_child() const {
|
||||
return 0;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PandaNode::get_next_visible_child
|
||||
// Access: Public, Virtual
|
||||
// Description: Returns the index number of the next visible child
|
||||
// of this node following the indicated child, or a
|
||||
// number >= get_num_children() if there are no more
|
||||
// visible children of this node. See
|
||||
// has_selective_visibility() and
|
||||
// get_first_visible_child().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
int PandaNode::
|
||||
get_next_visible_child(int n) const {
|
||||
return n + 1;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PandaNode::find_child
|
||||
// Access: Published
|
||||
|
@ -38,6 +38,7 @@
|
||||
#include "notify.h"
|
||||
|
||||
class NodeChainComponent;
|
||||
class CullTraverserData;
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : PandaNode
|
||||
@ -65,6 +66,12 @@ public:
|
||||
virtual void xform(const LMatrix4f &mat);
|
||||
virtual PandaNode *combine_with(PandaNode *other);
|
||||
|
||||
virtual bool has_cull_callback() const;
|
||||
virtual bool cull_callback(CullTraverserData &data);
|
||||
virtual bool has_selective_visibility() const;
|
||||
virtual int get_first_visible_child() const;
|
||||
virtual int get_next_visible_child(int n) const;
|
||||
|
||||
PUBLISHED:
|
||||
INLINE int get_num_parents() const;
|
||||
INLINE PandaNode *get_parent(int n) const;
|
||||
|
@ -13,5 +13,6 @@
|
||||
#include "cullHandler.cxx"
|
||||
#include "cullResult.cxx"
|
||||
#include "qpcullTraverser.cxx"
|
||||
#include "cullTraverserData.cxx"
|
||||
#include "cullableObject.cxx"
|
||||
|
||||
|
@ -4,12 +4,15 @@
|
||||
#include "drawCullHandler.cxx"
|
||||
#include "qpgeomNode.cxx"
|
||||
#include "qplensNode.cxx"
|
||||
#include "qplodNode.cxx"
|
||||
#include "materialAttrib.cxx"
|
||||
#include "nodeChain.cxx"
|
||||
#include "nodeChainComponent.cxx"
|
||||
#include "pandaNode.cxx"
|
||||
#include "renderAttrib.cxx"
|
||||
#include "renderState.cxx"
|
||||
#include "selectiveChildNode.cxx"
|
||||
#include "qpsequenceNode.cxx"
|
||||
#include "test_pgraph.cxx"
|
||||
#include "textureApplyAttrib.cxx"
|
||||
#include "textureAttrib.cxx"
|
||||
|
@ -141,3 +141,57 @@ remove_display_region(DisplayRegion *display_region) {
|
||||
_display_regions.erase(dri);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: qpCamera::register_with_read_factory
|
||||
// Access: Public, Static
|
||||
// Description: Tells the BamReader how to create objects of type
|
||||
// qpCamera.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void qpCamera::
|
||||
register_with_read_factory() {
|
||||
BamReader::get_factory()->register_factory(get_class_type(), make_from_bam);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: qpCamera::write_datagram
|
||||
// Access: Public, Virtual
|
||||
// Description: Writes the contents of this object to the datagram
|
||||
// for shipping out to a Bam file.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void qpCamera::
|
||||
write_datagram(BamWriter *manager, Datagram &dg) {
|
||||
qpLensNode::write_datagram(manager, dg);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: qpCamera::make_from_bam
|
||||
// Access: Protected, Static
|
||||
// Description: This function is called by the BamReader's factory
|
||||
// when a new object of type qpCamera is encountered
|
||||
// in the Bam file. It should create the qpCamera
|
||||
// and extract its information from the file.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
TypedWritable *qpCamera::
|
||||
make_from_bam(const FactoryParams ¶ms) {
|
||||
qpCamera *node = new qpCamera("");
|
||||
DatagramIterator scan;
|
||||
BamReader *manager;
|
||||
|
||||
parse_params(params, scan, manager);
|
||||
node->fillin(scan, manager);
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: qpCamera::fillin
|
||||
// Access: Protected
|
||||
// Description: This internal function is called by make_from_bam to
|
||||
// read in all of the relevant data from the BamFile for
|
||||
// the new qpCamera.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void qpCamera::
|
||||
fillin(DatagramIterator &scan, BamReader *manager) {
|
||||
qpLensNode::fillin(scan, manager);
|
||||
}
|
||||
|
@ -16,8 +16,8 @@
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef QPCAMERA_H
|
||||
#define QPCAMERA_H
|
||||
#ifndef qpCAMERA_H
|
||||
#define qpCAMERA_H
|
||||
|
||||
#include "pandabase.h"
|
||||
|
||||
@ -65,6 +65,14 @@ private:
|
||||
typedef pvector<DisplayRegion *> DisplayRegions;
|
||||
DisplayRegions _display_regions;
|
||||
|
||||
public:
|
||||
static void register_with_read_factory();
|
||||
virtual void write_datagram(BamWriter *manager, Datagram &dg);
|
||||
|
||||
protected:
|
||||
static TypedWritable *make_from_bam(const FactoryParams ¶ms);
|
||||
void fillin(DatagramIterator &scan, BamReader *manager);
|
||||
|
||||
public:
|
||||
static TypeHandle get_class_type() {
|
||||
return _type_handle;
|
||||
|
@ -17,14 +17,13 @@
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "qpcullTraverser.h"
|
||||
#include "cullTraverserData.h"
|
||||
#include "transformState.h"
|
||||
#include "renderState.h"
|
||||
#include "billboardAttrib.h"
|
||||
#include "cullHandler.h"
|
||||
#include "dcast.h"
|
||||
#include "qpgeomNode.h"
|
||||
#include "colorAttrib.h"
|
||||
#include "textureAttrib.h"
|
||||
#include "config_pgraph.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
@ -130,8 +129,10 @@ void qpCullTraverser::
|
||||
traverse(PandaNode *root) {
|
||||
nassertv(_cull_handler != (CullHandler *)NULL);
|
||||
|
||||
r_traverse(root, _render_transform, TransformState::make_identity(),
|
||||
_initial_state, _view_frustum, _guard_band);
|
||||
CullTraverserData data(_render_transform, TransformState::make_identity(),
|
||||
_initial_state, _view_frustum, _guard_band,
|
||||
_camera_transform);
|
||||
r_traverse(root, data);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
@ -140,135 +141,56 @@ traverse(PandaNode *root) {
|
||||
// Description: The recursive traversal implementation.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void qpCullTraverser::
|
||||
r_traverse(PandaNode *node,
|
||||
const TransformState *render_transform,
|
||||
const TransformState *net_transform,
|
||||
const RenderState *state,
|
||||
GeometricBoundingVolume *view_frustum,
|
||||
GeometricBoundingVolume *guard_band) {
|
||||
CPT(RenderState) next_state = state;
|
||||
r_traverse(PandaNode *node, const CullTraverserData &data) {
|
||||
CullTraverserData next_data(data);
|
||||
|
||||
if (view_frustum != (GeometricBoundingVolume *)NULL) {
|
||||
// If we have a viewing frustum, check to see if the node's
|
||||
// bounding volume falls within it.
|
||||
const BoundingVolume &node_volume = node->get_bound();
|
||||
nassertv(node_volume.is_of_type(GeometricBoundingVolume::get_class_type()));
|
||||
const GeometricBoundingVolume *node_gbv =
|
||||
DCAST(GeometricBoundingVolume, &node_volume);
|
||||
// Most nodes will have no transform or state, and will not
|
||||
// contain decals or require a special cull callback. As an
|
||||
// optimization, we should tag nodes with these properties as
|
||||
// being "fancy", and skip this processing for non-fancy nodes.
|
||||
|
||||
int result = view_frustum->contains(node_gbv);
|
||||
if (result == BoundingVolume::IF_no_intersection) {
|
||||
// No intersection at all. Cull.
|
||||
if (!qpfake_view_frustum_cull) {
|
||||
if (next_data.is_in_view(node)) {
|
||||
next_data.apply_transform_and_state(node);
|
||||
|
||||
if (node->has_cull_callback()) {
|
||||
if (!node->cull_callback(next_data)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// If we have fake view-frustum culling enabled, instead of
|
||||
// actually culling an object we simply force it to be drawn in
|
||||
// red wireframe.
|
||||
view_frustum = (GeometricBoundingVolume *)NULL;
|
||||
CPT(RenderState) fake_effect = get_fake_view_frustum_cull_effect();
|
||||
next_state = next_state->compose(fake_effect);
|
||||
|
||||
} else if ((result & BoundingVolume::IF_all) != 0) {
|
||||
// The node and its descendants are completely enclosed within
|
||||
// the frustum. No need to cull further.
|
||||
view_frustum = (GeometricBoundingVolume *)NULL;
|
||||
|
||||
} else {
|
||||
if (node->is_final()) {
|
||||
// The bounding volume is partially, but not completely,
|
||||
// within the viewing frustum. Normally we'd keep testing
|
||||
// child bounding volumes as we continue down. But this node
|
||||
// has the "final" flag, so the user is claiming that there is
|
||||
// some important reason we should consider everything visible
|
||||
// at this point. So be it.
|
||||
view_frustum = (GeometricBoundingVolume *)NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CPT(TransformState) next_render_transform = render_transform;
|
||||
CPT(TransformState) next_net_transform = net_transform;
|
||||
PT(GeometricBoundingVolume) next_view_frustum = view_frustum;
|
||||
PT(GeometricBoundingVolume) next_guard_band = guard_band;
|
||||
const RenderState *node_state = node->get_state();
|
||||
if (node_state->has_decal()) {
|
||||
start_decal(node, next_data);
|
||||
|
||||
} else {
|
||||
if (node->is_geom_node()) {
|
||||
qpGeomNode *geom_node = DCAST(qpGeomNode, node);
|
||||
|
||||
// Get all the Geoms, with no decalling.
|
||||
int num_geoms = geom_node->get_num_geoms();
|
||||
for (int i = 0; i < num_geoms; i++) {
|
||||
CullableObject *object = new CullableObject(next_data, geom_node, i);
|
||||
_cull_handler->record_object(object);
|
||||
}
|
||||
}
|
||||
|
||||
const TransformState *node_transform = node->get_transform();
|
||||
if (!node_transform->is_identity()) {
|
||||
next_render_transform = render_transform->compose(node_transform);
|
||||
next_net_transform = net_transform->compose(node_transform);
|
||||
|
||||
if ((view_frustum != (GeometricBoundingVolume *)NULL) ||
|
||||
(guard_band != (GeometricBoundingVolume *)NULL)) {
|
||||
// We need to move the viewing frustums into the node's
|
||||
// coordinate space by applying the node's inverse transform.
|
||||
if (node_transform->is_singular()) {
|
||||
// But we can't invert a singular transform! Instead of
|
||||
// trying, we'll just give up on frustum culling from this
|
||||
// point down.
|
||||
view_frustum = (GeometricBoundingVolume *)NULL;
|
||||
guard_band = (GeometricBoundingVolume *)NULL;
|
||||
// Now visit all the node's children.
|
||||
PandaNode::Children cr = node->get_children();
|
||||
int num_children = cr.get_num_children();
|
||||
if (node->has_selective_visibility()) {
|
||||
int i = node->get_first_visible_child();
|
||||
while (i < num_children) {
|
||||
r_traverse(cr.get_child(i), next_data);
|
||||
i = node->get_next_visible_child(i);
|
||||
}
|
||||
|
||||
} else {
|
||||
CPT(TransformState) inv_transform =
|
||||
node_transform->invert_compose(TransformState::make_identity());
|
||||
|
||||
if (view_frustum != (GeometricBoundingVolume *)NULL) {
|
||||
next_view_frustum = DCAST(GeometricBoundingVolume, view_frustum->make_copy());
|
||||
next_view_frustum->xform(inv_transform->get_mat());
|
||||
}
|
||||
|
||||
if (guard_band != (GeometricBoundingVolume *)NULL) {
|
||||
next_guard_band = DCAST(GeometricBoundingVolume, guard_band->make_copy());
|
||||
next_guard_band->xform(inv_transform->get_mat());
|
||||
for (int i = 0; i < num_children; i++) {
|
||||
r_traverse(cr.get_child(i), next_data);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const RenderState *node_state = node->get_state();
|
||||
next_state = next_state->compose(node_state);
|
||||
|
||||
const BillboardAttrib *billboard = node_state->get_billboard();
|
||||
if (billboard != (const BillboardAttrib *)NULL) {
|
||||
// Got to apply a billboard transform here.
|
||||
CPT(TransformState) billboard_transform =
|
||||
billboard->do_billboard(net_transform, _camera_transform);
|
||||
next_render_transform = next_render_transform->compose(billboard_transform);
|
||||
next_net_transform = next_net_transform->compose(billboard_transform);
|
||||
|
||||
// We can't reliably cull within a billboard, because the geometry
|
||||
// might get rotated out of its bounding volume. So once we get
|
||||
// within a billboard, we consider it all visible.
|
||||
next_view_frustum = (GeometricBoundingVolume *)NULL;
|
||||
}
|
||||
|
||||
if (node_state->has_decal()) {
|
||||
start_decal(node, next_render_transform, next_state);
|
||||
|
||||
} else {
|
||||
if (node->is_geom_node()) {
|
||||
qpGeomNode *geom_node = DCAST(qpGeomNode, node);
|
||||
|
||||
// Get all the Geoms, with no decalling.
|
||||
int num_geoms = geom_node->get_num_geoms();
|
||||
for (int i = 0; i < num_geoms; i++) {
|
||||
CullableObject *object = new CullableObject;
|
||||
object->_geom = geom_node->get_geom(i);
|
||||
object->_state = next_state->compose(geom_node->get_geom_state(i));
|
||||
object->_transform = next_render_transform;
|
||||
_cull_handler->record_object(object);
|
||||
}
|
||||
}
|
||||
|
||||
// Now visit all the node's children.
|
||||
PandaNode::Children cr = node->get_children();
|
||||
int num_children = cr.get_num_children();
|
||||
for (int i = 0; i < num_children; i++) {
|
||||
r_traverse(cr.get_child(i), next_render_transform, next_net_transform,
|
||||
next_state, next_view_frustum, next_guard_band);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
@ -276,16 +198,10 @@ r_traverse(PandaNode *node,
|
||||
// Access: Private
|
||||
// Description: Collects a base node and all of the decals applied to
|
||||
// it. This involves recursing below the base GeomNode
|
||||
// to find all the decal geoms; we don't bother to apply
|
||||
// any view-frustum culling at this point, and we don't
|
||||
// presently support billboards or LOD's within the
|
||||
// decals. Hard to justify the duplicate code this
|
||||
// would require.
|
||||
// to find all the decal geoms.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void qpCullTraverser::
|
||||
start_decal(PandaNode *node,
|
||||
const TransformState *render_transform,
|
||||
const RenderState *state) {
|
||||
start_decal(PandaNode *node, const CullTraverserData &data) {
|
||||
if (!node->is_geom_node()) {
|
||||
pgraph_cat.error()
|
||||
<< "DecalAttrib applied to " << *node << ", not a GeomNode.\n";
|
||||
@ -297,17 +213,22 @@ start_decal(PandaNode *node,
|
||||
// CullableObject node, followed by all of the decal Geoms, in
|
||||
// order.
|
||||
|
||||
const TransformState *next_render_transform = render_transform;
|
||||
const RenderState *next_state = state;
|
||||
|
||||
// Since the CullableObject is a linked list which gets built in
|
||||
// LIFO order, we start with the decals.
|
||||
CullableObject *decals = (CullableObject *)NULL;
|
||||
PandaNode::Children cr = node->get_children();
|
||||
int num_children = cr.get_num_children();
|
||||
for (int i = num_children - 1; i >= 0; i--) {
|
||||
decals =
|
||||
r_get_decals(cr.get_child(i), next_render_transform, next_state, decals);
|
||||
if (node->has_selective_visibility()) {
|
||||
int i = node->get_first_visible_child();
|
||||
while (i < num_children) {
|
||||
decals = r_get_decals(cr.get_child(i), data, decals);
|
||||
i = node->get_next_visible_child(i);
|
||||
}
|
||||
|
||||
} else {
|
||||
for (int i = num_children - 1; i >= 0; i--) {
|
||||
decals = r_get_decals(cr.get_child(i), data, decals);
|
||||
}
|
||||
}
|
||||
|
||||
// Now create a new, empty CullableObject to separate the decals
|
||||
@ -317,14 +238,9 @@ start_decal(PandaNode *node,
|
||||
// And now get the base Geoms, again in reverse order.
|
||||
CullableObject *object = separator;
|
||||
qpGeomNode *geom_node = DCAST(qpGeomNode, node);
|
||||
|
||||
// Get all the Geoms, with no decalling.
|
||||
int num_geoms = geom_node->get_num_geoms();
|
||||
for (int i = num_geoms - 1; i >= 0; i--) {
|
||||
object = new CullableObject(object);
|
||||
object->_geom = geom_node->get_geom(i);
|
||||
object->_state = next_state->compose(geom_node->get_geom_state(i));
|
||||
object->_transform = next_render_transform;
|
||||
object = new CullableObject(data, geom_node, i, object);
|
||||
}
|
||||
|
||||
if (object != separator) {
|
||||
@ -345,60 +261,39 @@ start_decal(PandaNode *node,
|
||||
// they were encountered in the scene graph).
|
||||
////////////////////////////////////////////////////////////////////
|
||||
CullableObject *qpCullTraverser::
|
||||
r_get_decals(PandaNode *node,
|
||||
const TransformState *render_transform,
|
||||
const RenderState *state,
|
||||
r_get_decals(PandaNode *node, const CullTraverserData &data,
|
||||
CullableObject *decals) {
|
||||
const TransformState *node_transform = node->get_transform();
|
||||
const RenderState *node_state = node->get_state();
|
||||
CullTraverserData next_data(data);
|
||||
|
||||
CPT(TransformState) next_render_transform =
|
||||
render_transform->compose(node_transform);
|
||||
CPT(RenderState) next_state =
|
||||
state->compose(node_state);
|
||||
if (next_data.is_in_view(node)) {
|
||||
next_data.apply_transform_and_state(node);
|
||||
|
||||
// First, visit all of the node's children.
|
||||
PandaNode::Children cr = node->get_children();
|
||||
int num_children = cr.get_num_children();
|
||||
for (int i = num_children - 1; i >= 0; i--) {
|
||||
decals =
|
||||
r_get_decals(cr.get_child(i), next_render_transform, next_state, decals);
|
||||
}
|
||||
// First, visit all of the node's children.
|
||||
PandaNode::Children cr = node->get_children();
|
||||
int num_children = cr.get_num_children();
|
||||
if (node->has_selective_visibility()) {
|
||||
int i = node->get_first_visible_child();
|
||||
while (i < num_children) {
|
||||
decals = r_get_decals(cr.get_child(i), next_data, decals);
|
||||
i = node->get_next_visible_child(i);
|
||||
}
|
||||
|
||||
} else {
|
||||
for (int i = num_children - 1; i >= 0; i--) {
|
||||
decals = r_get_decals(cr.get_child(i), next_data, decals);
|
||||
}
|
||||
}
|
||||
|
||||
// Now, tack on any geoms within the node.
|
||||
if (node->is_geom_node()) {
|
||||
qpGeomNode *geom_node = DCAST(qpGeomNode, node);
|
||||
|
||||
int num_geoms = geom_node->get_num_geoms();
|
||||
for (int i = num_geoms - 1; i >= 0; i--) {
|
||||
decals = new CullableObject(decals);
|
||||
decals->_geom = geom_node->get_geom(i);
|
||||
decals->_state = next_state->compose(geom_node->get_geom_state(i));
|
||||
decals->_transform = next_render_transform;
|
||||
// Now, tack on any geoms within the node.
|
||||
if (node->is_geom_node()) {
|
||||
qpGeomNode *geom_node = DCAST(qpGeomNode, node);
|
||||
|
||||
int num_geoms = geom_node->get_num_geoms();
|
||||
for (int i = num_geoms - 1; i >= 0; i--) {
|
||||
decals = new CullableObject(next_data, geom_node, i, decals);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return decals;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: qpCullTraverser::get_fake_view_frustum_cull_effect
|
||||
// Access: Private, Static
|
||||
// Description: Returns a RenderState for rendering stuff in red
|
||||
// wireframe, strictly for the fake_view_frustum_cull
|
||||
// effect.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
CPT(RenderState) qpCullTraverser::
|
||||
get_fake_view_frustum_cull_effect() {
|
||||
// Once someone asks for this pointer, we hold its reference count
|
||||
// and never free it.
|
||||
static CPT(RenderState) effect = (const RenderState *)NULL;
|
||||
if (effect == (const RenderState *)NULL) {
|
||||
effect = RenderState::make
|
||||
(ColorAttrib::make_flat(Colorf(1.0f, 0.0f, 0.0f, 1.0f)),
|
||||
TextureAttrib::make_off(),
|
||||
1000);
|
||||
}
|
||||
return effect;
|
||||
}
|
||||
|
||||
|
@ -28,6 +28,7 @@
|
||||
|
||||
class PandaNode;
|
||||
class CullHandler;
|
||||
class CullTraverserData;
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : CullTraverser
|
||||
@ -51,21 +52,12 @@ public:
|
||||
void traverse(PandaNode *root);
|
||||
|
||||
private:
|
||||
void r_traverse(PandaNode *node, const TransformState *render_transform,
|
||||
const TransformState *net_transform,
|
||||
const RenderState *state,
|
||||
GeometricBoundingVolume *view_frustum,
|
||||
GeometricBoundingVolume *guard_band);
|
||||
void start_decal(PandaNode *node,
|
||||
const TransformState *render_transform,
|
||||
const RenderState *state);
|
||||
CullableObject *r_get_decals(PandaNode *node,
|
||||
const TransformState *render_transform,
|
||||
const RenderState *state,
|
||||
void r_traverse(PandaNode *node, const CullTraverserData &data);
|
||||
void start_decal(PandaNode *node, const CullTraverserData &data);
|
||||
CullableObject *r_get_decals(PandaNode *node,
|
||||
const CullTraverserData &data,
|
||||
CullableObject *decals);
|
||||
|
||||
static CPT(RenderState) get_fake_view_frustum_cull_effect();
|
||||
|
||||
CPT(RenderState) _initial_state;
|
||||
CPT(TransformState) _camera_transform;
|
||||
CPT(TransformState) _render_transform;
|
||||
|
@ -80,3 +80,70 @@ write(ostream &out, int indent_level) const {
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: qpLensNode::register_with_read_factory
|
||||
// Access: Public, Static
|
||||
// Description: Tells the BamReader how to create objects of type
|
||||
// qpLensNode.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void qpLensNode::
|
||||
register_with_read_factory() {
|
||||
BamReader::get_factory()->register_factory(get_class_type(), make_from_bam);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: qpLensNode::write_datagram
|
||||
// Access: Public, Virtual
|
||||
// Description: Writes the contents of this object to the datagram
|
||||
// for shipping out to a Bam file.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void qpLensNode::
|
||||
write_datagram(BamWriter *manager, Datagram &dg) {
|
||||
PandaNode::write_datagram(manager, dg);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: qpLensNode::complete_pointers
|
||||
// Access: Public, Virtual
|
||||
// Description: Receives an array of pointers, one for each time
|
||||
// manager->read_pointer() was called in fillin().
|
||||
// Returns the number of pointers processed.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
int qpLensNode::
|
||||
complete_pointers(TypedWritable **p_list, BamReader *manager) {
|
||||
int pi = PandaNode::complete_pointers(p_list, manager);
|
||||
|
||||
return pi;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: qpLensNode::make_from_bam
|
||||
// Access: Protected, Static
|
||||
// Description: This function is called by the BamReader's factory
|
||||
// when a new object of type qpLensNode is encountered
|
||||
// in the Bam file. It should create the qpLensNode
|
||||
// and extract its information from the file.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
TypedWritable *qpLensNode::
|
||||
make_from_bam(const FactoryParams ¶ms) {
|
||||
qpLensNode *node = new qpLensNode("");
|
||||
DatagramIterator scan;
|
||||
BamReader *manager;
|
||||
|
||||
parse_params(params, scan, manager);
|
||||
node->fillin(scan, manager);
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: qpLensNode::fillin
|
||||
// Access: Protected
|
||||
// Description: This internal function is called by make_from_bam to
|
||||
// read in all of the relevant data from the BamFile for
|
||||
// the new qpLensNode.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void qpLensNode::
|
||||
fillin(DatagramIterator &scan, BamReader *manager) {
|
||||
PandaNode::fillin(scan, manager);
|
||||
}
|
||||
|
@ -16,8 +16,8 @@
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef QPLENSNODE_H
|
||||
#define QPLENSNODE_H
|
||||
#ifndef qpLENSNODE_H
|
||||
#define qpLENSNODE_H
|
||||
|
||||
#include "pandabase.h"
|
||||
|
||||
@ -55,6 +55,16 @@ PUBLISHED:
|
||||
protected:
|
||||
PT(Lens) _lens;
|
||||
|
||||
public:
|
||||
static void register_with_read_factory();
|
||||
virtual void write_datagram(BamWriter *manager, Datagram &dg);
|
||||
virtual int complete_pointers(TypedWritable **plist,
|
||||
BamReader *manager);
|
||||
|
||||
protected:
|
||||
static TypedWritable *make_from_bam(const FactoryParams ¶ms);
|
||||
void fillin(DatagramIterator &scan, BamReader *manager);
|
||||
|
||||
public:
|
||||
static TypeHandle get_class_type() {
|
||||
return _type_handle;
|
||||
|
163
panda/src/pgraph/qplodNode.I
Normal file
163
panda/src/pgraph/qplodNode.I
Normal file
@ -0,0 +1,163 @@
|
||||
// Filename: qplodNode.I
|
||||
// Created by: drose (06Mar02)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
|
||||
//
|
||||
// All use of this software is subject to the terms of the Panda 3d
|
||||
// Software license. You should have received a copy of this license
|
||||
// along with this source code; you will also find a current copy of
|
||||
// the license at http://www.panda3d.org/license.txt .
|
||||
//
|
||||
// To contact the maintainers of this program write to
|
||||
// panda3d@yahoogroups.com .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: qpLODNode::CData::Constructor
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE qpLODNode::CData::
|
||||
CData() {
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: qpLODNode::CData::Copy Constructor
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE qpLODNode::CData::
|
||||
CData(const qpLODNode::CData ©) :
|
||||
_lod(copy._lod)
|
||||
{
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: qpLODNode::Constructor
|
||||
// Access: Published
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE qpLODNode::
|
||||
qpLODNode(const string &name) :
|
||||
SelectiveChildNode(name)
|
||||
{
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: qpLODNode::add_switch
|
||||
// Access: Published
|
||||
// Description: Adds a switch range to the qpLODNode. This implies
|
||||
// that the corresponding child node has been parented
|
||||
// to the node.
|
||||
//
|
||||
// The sense of in vs. out distances is as if the object
|
||||
// were coming towards you from far away: it switches
|
||||
// "in" at the far distance, and switches "out" at the
|
||||
// close distance. Thus, "in" should be larger than
|
||||
// "out".
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void qpLODNode::
|
||||
add_switch(float in, float out) {
|
||||
CDWriter cdata(_cycler);
|
||||
cdata->_lod._switch_vector.push_back(LODSwitch(in, out));
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: qpLODNode::set_switch
|
||||
// Access: Published
|
||||
// Description: Changes the switching range of a particular child of
|
||||
// the qpLODNode. See add_switch().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE bool qpLODNode::
|
||||
set_switch(int index, float in, float out) {
|
||||
CDWriter cdata(_cycler);
|
||||
nassertr(index >= 0 && index < (int)cdata->_lod._switch_vector.size(), false);
|
||||
cdata->_lod._switch_vector[index].set_range(in, out);
|
||||
return true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: qpLODNode::clear_switches
|
||||
// Access: Published
|
||||
// Description: Removes the set of switching ranges for the qpLODNode,
|
||||
// presumably in conjunction with removing all of its
|
||||
// children. See add_switch().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void qpLODNode::
|
||||
clear_switches(void) {
|
||||
CDWriter cdata(_cycler);
|
||||
cdata->_lod._switch_vector.erase(cdata->_lod._switch_vector.begin(),
|
||||
cdata->_lod._switch_vector.end());
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: qpLODNode::get_num_switches
|
||||
// Access: Published
|
||||
// Description: Returns the number of switch ranges added to the
|
||||
// qpLODNode. This should correspond to the number of
|
||||
// children of the node in order for the qpLODNode to
|
||||
// function correctly.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE int qpLODNode::
|
||||
get_num_switches() const {
|
||||
CDReader cdata(_cycler);
|
||||
return cdata->_lod._switch_vector.size();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: qpLODNode::get_in
|
||||
// Access: Published
|
||||
// Description: Returns the "in" distance of the indicated switch
|
||||
// range. This should be larger than the "out" distance
|
||||
// of the same range.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE float qpLODNode::
|
||||
get_in(int index) const {
|
||||
CDReader cdata(_cycler);
|
||||
nassertr(index >= 0 && index < (int)cdata->_lod._switch_vector.size(), 0.0);
|
||||
return cdata->_lod._switch_vector[index].get_in();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: qpLODNode::get_out
|
||||
// Access: Published
|
||||
// Description: Returns the "out" distance of the indicated switch
|
||||
// range. This should be smaller than the "in" distance
|
||||
// of the same range.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE float qpLODNode::
|
||||
get_out(int index) const {
|
||||
CDReader cdata(_cycler);
|
||||
nassertr(index >= 0 && index < (int)cdata->_lod._switch_vector.size(), 0.0);
|
||||
return cdata->_lod._switch_vector[index].get_out();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: qpLODNode::set_center
|
||||
// Access: Published
|
||||
// Description: Specifies the center of the LOD. This is the point
|
||||
// that is compared to the camera (in camera space) to
|
||||
// determine the particular LOD that should be chosen.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void qpLODNode::
|
||||
set_center(const LPoint3f ¢er) {
|
||||
CDWriter cdata(_cycler);
|
||||
cdata->_lod._center = center;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: qpLODNode::get_center
|
||||
// Access: Published
|
||||
// Description: Returns the center of the LOD. This is the point
|
||||
// that is compared to the camera (in camera space) to
|
||||
// determine the particular LOD that should be chosen.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE const LPoint3f &qpLODNode::
|
||||
get_center() const {
|
||||
CDReader cdata(_cycler);
|
||||
return cdata->_lod._center;
|
||||
}
|
218
panda/src/pgraph/qplodNode.cxx
Normal file
218
panda/src/pgraph/qplodNode.cxx
Normal file
@ -0,0 +1,218 @@
|
||||
// Filename: qplodNode.cxx
|
||||
// Created by: drose (06Mar02)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
|
||||
//
|
||||
// All use of this software is subject to the terms of the Panda 3d
|
||||
// Software license. You should have received a copy of this license
|
||||
// along with this source code; you will also find a current copy of
|
||||
// the license at http://www.panda3d.org/license.txt .
|
||||
//
|
||||
// To contact the maintainers of this program write to
|
||||
// panda3d@yahoogroups.com .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "qplodNode.h"
|
||||
#include "cullTraverserData.h"
|
||||
|
||||
TypeHandle qpLODNode::_type_handle;
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: qpLODNode::CData::make_copy
|
||||
// Access: Public, Virtual
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
CycleData *qpLODNode::CData::
|
||||
make_copy() const {
|
||||
return new CData(*this);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: qpLODNode::Copy Constructor
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
qpLODNode::
|
||||
qpLODNode(const qpLODNode ©) :
|
||||
SelectiveChildNode(copy)
|
||||
{
|
||||
CDWriter cdata(_cycler);
|
||||
CDReader cdata_copy(copy._cycler);
|
||||
|
||||
cdata->_lod = cdata_copy->_lod;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: qpLODNode::Copy Assignment Operator
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void qpLODNode::
|
||||
operator = (const qpLODNode ©) {
|
||||
SelectiveChildNode::operator = (copy);
|
||||
|
||||
CDWriter cdata(_cycler);
|
||||
CDReader cdata_copy(copy._cycler);
|
||||
|
||||
cdata->_lod = cdata_copy->_lod;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: qpLODNode::make_copy
|
||||
// Access: Public, Virtual
|
||||
// Description: Returns a newly-allocated Node that is a shallow copy
|
||||
// of this one. It will be a different Node pointer,
|
||||
// but its internal data may or may not be shared with
|
||||
// that of the original Node.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
PandaNode *qpLODNode::
|
||||
make_copy() const {
|
||||
return new qpLODNode(*this);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: qpLODNode::xform
|
||||
// Access: Public, Virtual
|
||||
// Description: Transforms the contents of this PandaNode by the
|
||||
// indicated matrix, if it means anything to do so. For
|
||||
// most kinds of PandaNodes, this does nothing.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void qpLODNode::
|
||||
xform(const LMatrix4f &mat) {
|
||||
CDWriter cdata(_cycler);
|
||||
cdata->_lod.xform(mat);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: qpLODNode::has_cull_callback
|
||||
// Access: Public, Virtual
|
||||
// Description: Should be overridden by derived classes to return
|
||||
// true if cull_callback() has been defined. Otherwise,
|
||||
// returns false to indicate cull_callback() does not
|
||||
// need to be called for this node during the cull
|
||||
// traversal.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool qpLODNode::
|
||||
has_cull_callback() const {
|
||||
return true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: qpLODNode::cull_callback
|
||||
// Access: Public, Virtual
|
||||
// Description: If has_cull_callback() returns true, this function
|
||||
// will be called during the cull traversal to perform
|
||||
// any additional operations that should be performed at
|
||||
// cull time. This may include additional manipulation
|
||||
// of render state or additional visible/invisible
|
||||
// decisions, or any other arbitrary operation.
|
||||
//
|
||||
// By the time this function is called, the node has
|
||||
// already passed the bounding-volume test for the
|
||||
// viewing frustum, and the node's transform and state
|
||||
// have already been applied to the indicated
|
||||
// CullTraverserData object.
|
||||
//
|
||||
// The return value is true if this node should be
|
||||
// visible, or false if it should be culled.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool qpLODNode::
|
||||
cull_callback(CullTraverserData &data) {
|
||||
if (data._net_transform->is_singular()) {
|
||||
// If we're under a singular transform, we can't compute the LOD;
|
||||
// select none of them instead.
|
||||
select_child(get_num_children());
|
||||
|
||||
} else {
|
||||
CDReader cdata(_cycler);
|
||||
LPoint3f camera_pos(0, 0, 0);
|
||||
|
||||
// Get the LOD center in camera space
|
||||
CPT(TransformState) rel_transform =
|
||||
data._net_transform->invert_compose(data._camera_transform);
|
||||
LPoint3f center = cdata->_lod._center * rel_transform->get_mat();
|
||||
|
||||
// Determine which child to traverse
|
||||
int index = cdata->_lod.compute_child(camera_pos, center);
|
||||
select_child(index);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: qpLODNode::output
|
||||
// Access: Public, Virtual
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void qpLODNode::
|
||||
output(ostream &out) const {
|
||||
SelectiveChildNode::output(out);
|
||||
CDReader cdata(_cycler);
|
||||
out << " ";
|
||||
cdata->_lod.output(out);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: qpLODNode::register_with_read_factory
|
||||
// Access: Public, Static
|
||||
// Description: Tells the BamReader how to create objects of type
|
||||
// qpLODNode.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void qpLODNode::
|
||||
register_with_read_factory() {
|
||||
BamReader::get_factory()->register_factory(get_class_type(), make_from_bam);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: qpLODNode::write_datagram
|
||||
// Access: Public, Virtual
|
||||
// Description: Writes the contents of this object to the datagram
|
||||
// for shipping out to a Bam file.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void qpLODNode::
|
||||
write_datagram(BamWriter *manager, Datagram &dg) {
|
||||
SelectiveChildNode::write_datagram(manager, dg);
|
||||
|
||||
CDReader cdata(_cycler);
|
||||
cdata->_lod.write_datagram(dg);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: qpLODNode::make_from_bam
|
||||
// Access: Protected, Static
|
||||
// Description: This function is called by the BamReader's factory
|
||||
// when a new object of type qpLODNode is encountered
|
||||
// in the Bam file. It should create the qpLODNode
|
||||
// and extract its information from the file.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
TypedWritable *qpLODNode::
|
||||
make_from_bam(const FactoryParams ¶ms) {
|
||||
qpLODNode *node = new qpLODNode("");
|
||||
DatagramIterator scan;
|
||||
BamReader *manager;
|
||||
|
||||
parse_params(params, scan, manager);
|
||||
node->fillin(scan, manager);
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: qpLODNode::fillin
|
||||
// Access: Protected
|
||||
// Description: This internal function is called by make_from_bam to
|
||||
// read in all of the relevant data from the BamFile for
|
||||
// the new qpLODNode.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void qpLODNode::
|
||||
fillin(DatagramIterator &scan, BamReader *manager) {
|
||||
SelectiveChildNode::fillin(scan, manager);
|
||||
|
||||
CDWriter cdata(_cycler);
|
||||
cdata->_lod.read_datagram(scan);
|
||||
}
|
109
panda/src/pgraph/qplodNode.h
Normal file
109
panda/src/pgraph/qplodNode.h
Normal file
@ -0,0 +1,109 @@
|
||||
// Filename: qplodNode.h
|
||||
// Created by: drose (06Mar02)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
|
||||
//
|
||||
// All use of this software is subject to the terms of the Panda 3d
|
||||
// Software license. You should have received a copy of this license
|
||||
// along with this source code; you will also find a current copy of
|
||||
// the license at http://www.panda3d.org/license.txt .
|
||||
//
|
||||
// To contact the maintainers of this program write to
|
||||
// panda3d@yahoogroups.com .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef qpLODNODE_H
|
||||
#define qpLODNODE_H
|
||||
|
||||
#include "pandabase.h"
|
||||
|
||||
#include "selectiveChildNode.h"
|
||||
|
||||
#include "LOD.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : qpLODNode
|
||||
// Description : A Level-of-Detail node. This selects only one of its
|
||||
// children for rendering, according to the distance
|
||||
// from the camera and the table indicated in the
|
||||
// associated LOD object.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
class EXPCL_PANDA qpLODNode : public SelectiveChildNode {
|
||||
PUBLISHED:
|
||||
INLINE qpLODNode(const string &name);
|
||||
|
||||
public:
|
||||
INLINE qpLODNode(const qpLODNode ©);
|
||||
INLINE void operator = (const qpLODNode ©);
|
||||
|
||||
virtual PandaNode *make_copy() const;
|
||||
virtual void xform(const LMatrix4f &mat);
|
||||
virtual bool has_cull_callback() const;
|
||||
virtual bool cull_callback(CullTraverserData &data);
|
||||
|
||||
virtual void output(ostream &out) const;
|
||||
|
||||
PUBLISHED:
|
||||
// The sense of in vs. out distances is as if the object were coming
|
||||
// towards you from far away: it switches "in" at the far distance,
|
||||
// and switches "out" at the close distance. Thus, "in" should be
|
||||
// larger than "out".
|
||||
|
||||
INLINE void add_switch(float in, float out);
|
||||
INLINE bool set_switch(int index, float in, float out);
|
||||
INLINE void clear_switches(void);
|
||||
|
||||
INLINE int get_num_switches() const;
|
||||
INLINE float get_in(int index) const;
|
||||
INLINE float get_out(int index) const;
|
||||
|
||||
INLINE void set_center(const LPoint3f ¢er);
|
||||
INLINE const LPoint3f &get_center() const;
|
||||
|
||||
public:
|
||||
static void register_with_read_factory();
|
||||
virtual void write_datagram(BamWriter *manager, Datagram &dg);
|
||||
|
||||
protected:
|
||||
static TypedWritable *make_from_bam(const FactoryParams ¶ms);
|
||||
void fillin(DatagramIterator &scan, BamReader *manager);
|
||||
|
||||
private:
|
||||
class EXPCL_PANDA CData : public CycleData {
|
||||
public:
|
||||
INLINE CData();
|
||||
INLINE CData(const CData ©);
|
||||
virtual CycleData *make_copy() const;
|
||||
|
||||
LOD _lod;
|
||||
};
|
||||
|
||||
PipelineCycler<CData> _cycler;
|
||||
typedef CycleDataReader<CData> CDReader;
|
||||
typedef CycleDataWriter<CData> CDWriter;
|
||||
|
||||
public:
|
||||
static TypeHandle get_class_type() {
|
||||
return _type_handle;
|
||||
}
|
||||
static void init_type() {
|
||||
SelectiveChildNode::init_type();
|
||||
register_type(_type_handle, "qpLODNode",
|
||||
SelectiveChildNode::get_class_type());
|
||||
}
|
||||
virtual TypeHandle get_type() const {
|
||||
return get_class_type();
|
||||
}
|
||||
virtual TypeHandle force_init_type() {init_type(); return get_class_type();}
|
||||
|
||||
private:
|
||||
static TypeHandle _type_handle;
|
||||
};
|
||||
|
||||
#include "qplodNode.I"
|
||||
|
||||
#endif
|
130
panda/src/pgraph/qpsequenceNode.I
Normal file
130
panda/src/pgraph/qpsequenceNode.I
Normal file
@ -0,0 +1,130 @@
|
||||
// Filename: qpsequenceNode.I
|
||||
// Created by: drose (06Mar02)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
|
||||
//
|
||||
// All use of this software is subject to the terms of the Panda 3d
|
||||
// Software license. You should have received a copy of this license
|
||||
// along with this source code; you will also find a current copy of
|
||||
// the license at http://www.panda3d.org/license.txt .
|
||||
//
|
||||
// To contact the maintainers of this program write to
|
||||
// panda3d@yahoogroups.com .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: qpSequenceNode::CData::Constructor
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE qpSequenceNode::CData::
|
||||
CData() {
|
||||
_cycle_rate = 0.0f;
|
||||
_frame_offset = 0.0f;
|
||||
_start_time = 0.0f;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: qpSequenceNode::CData::Copy Constructor
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE qpSequenceNode::CData::
|
||||
CData(const qpSequenceNode::CData ©) :
|
||||
_cycle_rate(copy._cycle_rate),
|
||||
_frame_offset(copy._frame_offset),
|
||||
_start_time(copy._start_time)
|
||||
{
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: qpSequenceNode::Constructor
|
||||
// Access: Published
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE qpSequenceNode::
|
||||
qpSequenceNode(float cycle_rate, const string &name) :
|
||||
SelectiveChildNode(name)
|
||||
{
|
||||
CDWriter cdata(_cycler);
|
||||
cdata->_cycle_rate = cycle_rate;
|
||||
cdata->_frame_offset = 0.0f;
|
||||
|
||||
float now = ClockObject::get_global_clock()->get_frame_time();
|
||||
cdata->_start_time = now;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: qpSequenceNode::set_cycle_rate
|
||||
// Access: Published
|
||||
// Description: Sets the rate of cycling for the children of the
|
||||
// SequenceNode, in cycles per second.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void qpSequenceNode::
|
||||
set_cycle_rate(float cycle_rate) {
|
||||
// Do some fussing so we keep the same frame visible while we
|
||||
// change this.
|
||||
CDWriter cdata(_cycler);
|
||||
float now = ClockObject::get_global_clock()->get_frame_time();
|
||||
cdata->_frame_offset = calc_frame(now);
|
||||
cdata->_start_time = now;
|
||||
cdata->_cycle_rate = cycle_rate;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: qpSequenceNode::get_cycle_rate
|
||||
// Access: Published
|
||||
// Description: Returns the rate of cycling for the children of the
|
||||
// SequenceNode, in cycles per second.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE float qpSequenceNode::
|
||||
get_cycle_rate() const {
|
||||
CDReader cdata(_cycler);
|
||||
return cdata->_cycle_rate;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: qpSequenceNode::get_visible_child
|
||||
// Access: Published
|
||||
// Description: Returns the index of the child that should be visible
|
||||
// for this particular frame, if there are any children.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE int qpSequenceNode::
|
||||
get_visible_child() const {
|
||||
int num_children = get_num_children();
|
||||
if (num_children == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
float frame = calc_frame();
|
||||
|
||||
return ((int)frame) % num_children;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: qpSequenceNode::calc_frame
|
||||
// Access: Private
|
||||
// Description: Returns the floating-point frame number at the
|
||||
// indicated time.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE float qpSequenceNode::
|
||||
calc_frame(float now) const {
|
||||
CDReader cdata(_cycler);
|
||||
return (now - cdata->_start_time) * cdata->_cycle_rate + cdata->_frame_offset;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: qpSequenceNode::calc_frame
|
||||
// Access: Private
|
||||
// Description: Returns the floating-point frame number at the
|
||||
// current time.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE float qpSequenceNode::
|
||||
calc_frame() const {
|
||||
return calc_frame(ClockObject::get_global_clock()->get_frame_time());
|
||||
}
|
183
panda/src/pgraph/qpsequenceNode.cxx
Normal file
183
panda/src/pgraph/qpsequenceNode.cxx
Normal file
@ -0,0 +1,183 @@
|
||||
// Filename: qpsequenceNode.cxx
|
||||
// Created by: drose (06Mar02)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
|
||||
//
|
||||
// All use of this software is subject to the terms of the Panda 3d
|
||||
// Software license. You should have received a copy of this license
|
||||
// along with this source code; you will also find a current copy of
|
||||
// the license at http://www.panda3d.org/license.txt .
|
||||
//
|
||||
// To contact the maintainers of this program write to
|
||||
// panda3d@yahoogroups.com .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "pandabase.h"
|
||||
#include "qpsequenceNode.h"
|
||||
|
||||
TypeHandle qpSequenceNode::_type_handle;
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: qpSequenceNode::CData::make_copy
|
||||
// Access: Public, Virtual
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
CycleData *qpSequenceNode::CData::
|
||||
make_copy() const {
|
||||
return new CData(*this);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: qpSequenceNode::Copy Constructor
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
qpSequenceNode::
|
||||
qpSequenceNode(const qpSequenceNode ©) :
|
||||
SelectiveChildNode(copy)
|
||||
{
|
||||
CDWriter cdata(_cycler);
|
||||
CDReader cdata_copy(copy._cycler);
|
||||
|
||||
cdata->_cycle_rate = cdata_copy->_cycle_rate;
|
||||
cdata->_start_time = cdata_copy->_start_time;
|
||||
cdata->_frame_offset = cdata_copy->_frame_offset;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: qpSequenceNode::Copy Assignment Operator
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void qpSequenceNode::
|
||||
operator = (const qpSequenceNode ©) {
|
||||
SelectiveChildNode::operator = (copy);
|
||||
|
||||
CDWriter cdata(_cycler);
|
||||
CDReader cdata_copy(copy._cycler);
|
||||
|
||||
cdata->_cycle_rate = cdata_copy->_cycle_rate;
|
||||
cdata->_start_time = cdata_copy->_start_time;
|
||||
cdata->_frame_offset = cdata_copy->_frame_offset;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: qpSequenceNode::make_copy
|
||||
// Access: Public, Virtual
|
||||
// Description: Returns a newly-allocated Node that is a shallow copy
|
||||
// of this one. It will be a different Node pointer,
|
||||
// but its internal data may or may not be shared with
|
||||
// that of the original Node.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
PandaNode *qpSequenceNode::
|
||||
make_copy() const {
|
||||
return new qpSequenceNode(*this);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: qpSequenceNode::has_cull_callback
|
||||
// Access: Public, Virtual
|
||||
// Description: Should be overridden by derived classes to return
|
||||
// true if cull_callback() has been defined. Otherwise,
|
||||
// returns false to indicate cull_callback() does not
|
||||
// need to be called for this node during the cull
|
||||
// traversal.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool qpSequenceNode::
|
||||
has_cull_callback() const {
|
||||
return true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: qpSequenceNode::cull_callback
|
||||
// Access: Public, Virtual
|
||||
// Description: If has_cull_callback() returns true, this function
|
||||
// will be called during the cull traversal to perform
|
||||
// any additional operations that should be performed at
|
||||
// cull time. This may include additional manipulation
|
||||
// of render state or additional visible/invisible
|
||||
// decisions, or any other arbitrary operation.
|
||||
//
|
||||
// By the time this function is called, the node has
|
||||
// already passed the bounding-volume test for the
|
||||
// viewing frustum, and the node's transform and state
|
||||
// have already been applied to the indicated
|
||||
// CullTraverserData object.
|
||||
//
|
||||
// The return value is true if this node should be
|
||||
// visible, or false if it should be culled.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool qpSequenceNode::
|
||||
cull_callback(CullTraverserData &) {
|
||||
select_child(get_visible_child());
|
||||
return true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: qpSequenceNode::register_with_read_factory
|
||||
// Access: Public, Static
|
||||
// Description: Tells the BamReader how to create objects of type
|
||||
// qpSequenceNode.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void qpSequenceNode::
|
||||
register_with_read_factory() {
|
||||
BamReader::get_factory()->register_factory(get_class_type(), make_from_bam);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: qpSequenceNode::write_datagram
|
||||
// Access: Public, Virtual
|
||||
// Description: Writes the contents of this object to the datagram
|
||||
// for shipping out to a Bam file.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void qpSequenceNode::
|
||||
write_datagram(BamWriter *manager, Datagram &dg) {
|
||||
SelectiveChildNode::write_datagram(manager, dg);
|
||||
|
||||
CDReader cdata(_cycler);
|
||||
dg.add_float32(cdata->_cycle_rate);
|
||||
dg.add_float32(calc_frame());
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: qpSequenceNode::make_from_bam
|
||||
// Access: Protected, Static
|
||||
// Description: This function is called by the BamReader's factory
|
||||
// when a new object of type qpSequenceNode is encountered
|
||||
// in the Bam file. It should create the qpSequenceNode
|
||||
// and extract its information from the file.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
TypedWritable *qpSequenceNode::
|
||||
make_from_bam(const FactoryParams ¶ms) {
|
||||
qpSequenceNode *node = new qpSequenceNode(0.0f, "");
|
||||
DatagramIterator scan;
|
||||
BamReader *manager;
|
||||
|
||||
parse_params(params, scan, manager);
|
||||
node->fillin(scan, manager);
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: qpSequenceNode::fillin
|
||||
// Access: Protected
|
||||
// Description: This internal function is called by make_from_bam to
|
||||
// read in all of the relevant data from the BamFile for
|
||||
// the new qpSequenceNode.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void qpSequenceNode::
|
||||
fillin(DatagramIterator &scan, BamReader *manager) {
|
||||
SelectiveChildNode::fillin(scan, manager);
|
||||
|
||||
CDWriter cdata(_cycler);
|
||||
cdata->_cycle_rate = scan.get_float32();
|
||||
cdata->_frame_offset = scan.get_float32();
|
||||
|
||||
float now = ClockObject::get_global_clock()->get_frame_time();
|
||||
cdata->_start_time = now;
|
||||
}
|
98
panda/src/pgraph/qpsequenceNode.h
Normal file
98
panda/src/pgraph/qpsequenceNode.h
Normal file
@ -0,0 +1,98 @@
|
||||
// Filename: qpsequenceNode.h
|
||||
// Created by: drose (06Mar02)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
|
||||
//
|
||||
// All use of this software is subject to the terms of the Panda 3d
|
||||
// Software license. You should have received a copy of this license
|
||||
// along with this source code; you will also find a current copy of
|
||||
// the license at http://www.panda3d.org/license.txt .
|
||||
//
|
||||
// To contact the maintainers of this program write to
|
||||
// panda3d@yahoogroups.com .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef qpSEQUENCENODE_H
|
||||
#define qpSEQUENCENODE_H
|
||||
|
||||
#include "pandabase.h"
|
||||
|
||||
#include "selectiveChildNode.h"
|
||||
#include "clockObject.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : SequenceNode
|
||||
// Description : A node that automatically cycles through rendering
|
||||
// each one of its children according to its frame rate.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
class EXPCL_PANDA qpSequenceNode : public SelectiveChildNode {
|
||||
PUBLISHED:
|
||||
INLINE qpSequenceNode(float cycle_rate, const string &name);
|
||||
|
||||
public:
|
||||
qpSequenceNode(const qpSequenceNode ©);
|
||||
void operator = (const qpSequenceNode ©);
|
||||
|
||||
virtual PandaNode *make_copy() const;
|
||||
|
||||
virtual bool has_cull_callback() const;
|
||||
virtual bool cull_callback(CullTraverserData &data);
|
||||
|
||||
PUBLISHED:
|
||||
INLINE void set_cycle_rate(float cycle_rate);
|
||||
INLINE float get_cycle_rate() const;
|
||||
|
||||
INLINE int get_visible_child() const;
|
||||
|
||||
private:
|
||||
INLINE float calc_frame(float now) const;
|
||||
INLINE float calc_frame() const;
|
||||
|
||||
class EXPCL_PANDA CData : public CycleData {
|
||||
public:
|
||||
INLINE CData();
|
||||
INLINE CData(const CData ©);
|
||||
virtual CycleData *make_copy() const;
|
||||
|
||||
float _cycle_rate;
|
||||
float _frame_offset;
|
||||
float _start_time;
|
||||
};
|
||||
|
||||
PipelineCycler<CData> _cycler;
|
||||
typedef CycleDataReader<CData> CDReader;
|
||||
typedef CycleDataWriter<CData> CDWriter;
|
||||
|
||||
public:
|
||||
static void register_with_read_factory();
|
||||
virtual void write_datagram(BamWriter *manager, Datagram &dg);
|
||||
|
||||
protected:
|
||||
static TypedWritable *make_from_bam(const FactoryParams ¶ms);
|
||||
void fillin(DatagramIterator &scan, BamReader *manager);
|
||||
|
||||
public:
|
||||
static TypeHandle get_class_type() {
|
||||
return _type_handle;
|
||||
}
|
||||
static void init_type() {
|
||||
SelectiveChildNode::init_type();
|
||||
register_type(_type_handle, "qpSequenceNode",
|
||||
SelectiveChildNode::get_class_type());
|
||||
}
|
||||
virtual TypeHandle get_type() const {
|
||||
return get_class_type();
|
||||
}
|
||||
virtual TypeHandle force_init_type() {init_type(); return get_class_type();}
|
||||
|
||||
private:
|
||||
static TypeHandle _type_handle;
|
||||
};
|
||||
|
||||
#include "qpsequenceNode.I"
|
||||
|
||||
#endif
|
65
panda/src/pgraph/selectiveChildNode.I
Normal file
65
panda/src/pgraph/selectiveChildNode.I
Normal file
@ -0,0 +1,65 @@
|
||||
// Filename: selectiveChildNode.I
|
||||
// Created by: drose (06Mar02)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
|
||||
//
|
||||
// All use of this software is subject to the terms of the Panda 3d
|
||||
// Software license. You should have received a copy of this license
|
||||
// along with this source code; you will also find a current copy of
|
||||
// the license at http://www.panda3d.org/license.txt .
|
||||
//
|
||||
// To contact the maintainers of this program write to
|
||||
// panda3d@yahoogroups.com .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: SelectiveChildNode::Constructor
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE SelectiveChildNode::
|
||||
SelectiveChildNode(const string &name) :
|
||||
PandaNode(name),
|
||||
_selected_child(0)
|
||||
{
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: SelectiveChildNode::Copy Constructor
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE SelectiveChildNode::
|
||||
SelectiveChildNode(const SelectiveChildNode ©) :
|
||||
PandaNode(copy),
|
||||
_selected_child(copy._selected_child)
|
||||
{
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: SelectiveChildNode::Copy Assignment Operator
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void SelectiveChildNode::
|
||||
operator = (const SelectiveChildNode ©) {
|
||||
PandaNode::operator = (copy);
|
||||
_selected_child = copy._selected_child;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: SelectiveChildNode::select_child
|
||||
// Access: Protected
|
||||
// Description: Selects the indicated child for rendering. This is
|
||||
// normally called during the cull_callback() method,
|
||||
// but it may be called at any time.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void SelectiveChildNode::
|
||||
select_child(int n) {
|
||||
_selected_child = n;
|
||||
}
|
75
panda/src/pgraph/selectiveChildNode.cxx
Normal file
75
panda/src/pgraph/selectiveChildNode.cxx
Normal file
@ -0,0 +1,75 @@
|
||||
// Filename: selectiveChildNode.cxx
|
||||
// Created by: drose (06Mar02)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
|
||||
//
|
||||
// All use of this software is subject to the terms of the Panda 3d
|
||||
// Software license. You should have received a copy of this license
|
||||
// along with this source code; you will also find a current copy of
|
||||
// the license at http://www.panda3d.org/license.txt .
|
||||
//
|
||||
// To contact the maintainers of this program write to
|
||||
// panda3d@yahoogroups.com .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "selectiveChildNode.h"
|
||||
|
||||
TypeHandle SelectiveChildNode::_type_handle;
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: SelectiveChildNode::has_selective_visibility
|
||||
// Access: Public, Virtual
|
||||
// Description: Should be overridden by derived classes to return
|
||||
// true if this kind of node has some restrictions on
|
||||
// the set of children that should be rendered. Node
|
||||
// with this property include LODNodes, SwitchNodes, and
|
||||
// SequenceNodes.
|
||||
//
|
||||
// If this function returns true,
|
||||
// get_first_visible_child() and
|
||||
// get_next_visible_child() will be called to walk
|
||||
// through the list of children during cull, instead of
|
||||
// iterating through the entire list. This method is
|
||||
// called after cull_callback(), so cull_callback() may
|
||||
// be responsible for the decisions as to which children
|
||||
// are visible at the moment.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool SelectiveChildNode::
|
||||
has_selective_visibility() const {
|
||||
return true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: SelectiveChildNode::get_first_visible_child
|
||||
// Access: Public, Virtual
|
||||
// Description: Returns the index number of the first visible child
|
||||
// of this node, or a number >= get_num_children() if
|
||||
// there are no visible children of this node. This is
|
||||
// called during the cull traversal, but only if
|
||||
// has_selective_visibility() has already returned true.
|
||||
// See has_selective_visibility().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
int SelectiveChildNode::
|
||||
get_first_visible_child() const {
|
||||
return _selected_child;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: SelectiveChildNode::get_next_visible_child
|
||||
// Access: Public, Virtual
|
||||
// Description: Returns the index number of the next visible child
|
||||
// of this node following the indicated child, or a
|
||||
// number >= get_num_children() if there are no more
|
||||
// visible children of this node. See
|
||||
// has_selective_visibility() and
|
||||
// get_first_visible_child().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
int SelectiveChildNode::
|
||||
get_next_visible_child(int n) const {
|
||||
return get_num_children();
|
||||
}
|
69
panda/src/pgraph/selectiveChildNode.h
Normal file
69
panda/src/pgraph/selectiveChildNode.h
Normal file
@ -0,0 +1,69 @@
|
||||
// Filename: selectiveChildNode.h
|
||||
// Created by: drose (06Mar02)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
|
||||
//
|
||||
// All use of this software is subject to the terms of the Panda 3d
|
||||
// Software license. You should have received a copy of this license
|
||||
// along with this source code; you will also find a current copy of
|
||||
// the license at http://www.panda3d.org/license.txt .
|
||||
//
|
||||
// To contact the maintainers of this program write to
|
||||
// panda3d@yahoogroups.com .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef SELECTIVECHILDNODE_H
|
||||
#define SELECTIVECHILDNODE_H
|
||||
|
||||
#include "pandabase.h"
|
||||
|
||||
#include "pandaNode.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : SelectiveChildNode
|
||||
// Description : A base class for nodes like LODNode and SequenceNode
|
||||
// that select only one visible child at a time.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
class EXPCL_PANDA SelectiveChildNode : public PandaNode {
|
||||
PUBLISHED:
|
||||
INLINE SelectiveChildNode(const string &name);
|
||||
|
||||
public:
|
||||
INLINE SelectiveChildNode(const SelectiveChildNode ©);
|
||||
INLINE void operator = (const SelectiveChildNode ©);
|
||||
|
||||
virtual bool has_selective_visibility() const;
|
||||
virtual int get_first_visible_child() const;
|
||||
virtual int get_next_visible_child(int n) const;
|
||||
|
||||
protected:
|
||||
INLINE void select_child(int n);
|
||||
|
||||
private:
|
||||
int _selected_child;
|
||||
|
||||
public:
|
||||
static TypeHandle get_class_type() {
|
||||
return _type_handle;
|
||||
}
|
||||
static void init_type() {
|
||||
PandaNode::init_type();
|
||||
register_type(_type_handle, "SelectiveChildNode",
|
||||
PandaNode::get_class_type());
|
||||
}
|
||||
virtual TypeHandle get_type() const {
|
||||
return get_class_type();
|
||||
}
|
||||
virtual TypeHandle force_init_type() {init_type(); return get_class_type();}
|
||||
|
||||
private:
|
||||
static TypeHandle _type_handle;
|
||||
};
|
||||
|
||||
#include "selectiveChildNode.I"
|
||||
|
||||
#endif
|
@ -480,6 +480,9 @@ do_compose(const TransformState *other) const {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
CPT(TransformState) TransformState::
|
||||
do_invert_compose(const TransformState *other) const {
|
||||
// Perhaps we should cache the inverse matrix operation separately,
|
||||
// as a further optimization.
|
||||
|
||||
LMatrix4f new_mat;
|
||||
new_mat.invert_from(get_mat());
|
||||
new_mat = other->get_mat() * new_mat;
|
||||
|
Loading…
x
Reference in New Issue
Block a user