separate out RenderEffect from RenderAttrib

This commit is contained in:
David Rose 2002-03-14 19:24:42 +00:00
parent d5dce0be83
commit 9a7e4b319c
27 changed files with 1761 additions and 299 deletions

View File

@ -26,11 +26,11 @@
#include "textureAttrib.h"
#include "textureApplyAttrib.h"
#include "texturePool.h"
#include "billboardAttrib.h"
#include "billboardEffect.h"
#include "cullFaceAttrib.h"
#include "cullBinAttrib.h"
#include "transparencyAttrib.h"
#include "decalAttrib.h"
#include "decalEffect.h"
#include "depthTestAttrib.h"
#include "depthWriteAttrib.h"
#include "materialAttrib.h"
@ -197,8 +197,8 @@ reparent_decals() {
}
}
// Finally, set the DecalAttrib on the base geometry.
geom_parent.node()->set_attrib(DecalAttrib::make());
// Finally, set the DecalEffect on the base geometry.
geom_parent.node()->set_effect(DecalEffect::make());
}
}
}
@ -1428,15 +1428,15 @@ create_group_arc(EggGroup *egg_group, PandaNode *parent, PandaNode *node) {
// If the group has a billboard flag, apply that.
switch (egg_group->get_billboard_type()) {
case EggGroup::BT_point_camera_relative:
node->set_attrib(BillboardAttrib::make_point_eye());
node->set_effect(BillboardEffect::make_point_eye());
break;
case EggGroup::BT_point_world_relative:
node->set_attrib(BillboardAttrib::make_point_world());
node->set_effect(BillboardEffect::make_point_world());
break;
case EggGroup::BT_axis:
node->set_attrib(BillboardAttrib::make_axis());
node->set_effect(BillboardEffect::make_axis());
break;
case EggGroup::BT_none:

View File

@ -6,7 +6,7 @@
#define TARGET pgraph
#define SOURCES \
billboardAttrib.h billboardAttrib.I \
billboardEffect.h billboardEffect.I \
binCullHandler.h binCullHandler.I \
qpcamera.h qpcamera.I \
colorAttrib.h colorAttrib.I \
@ -23,7 +23,7 @@
qpcullTraverser.h qpcullTraverser.I \
cullTraverserData.h cullTraverserData.I \
cullableObject.h cullableObject.I \
decalAttrib.h decalAttrib.I \
decalEffect.h decalEffect.I \
depthTestAttrib.h depthTestAttrib.I \
depthWriteAttrib.h depthWriteAttrib.I \
drawCullHandler.h drawCullHandler.I \
@ -39,6 +39,8 @@
qpnodePathComponent.h qpnodePathComponent.I \
pandaNode.h pandaNode.I \
renderAttrib.h renderAttrib.I \
renderEffect.h renderEffect.I \
renderEffects.h renderEffects.I \
renderState.h renderState.I \
selectiveChildNode.h selectiveChildNode.I \
qpsequenceNode.h qpsequenceNode.I \
@ -49,7 +51,7 @@
#define COMBINED_SOURCES $[TARGET]_composite1.cxx $[TARGET]_composite2.cxx
#define INCLUDED_SOURCES \
billboardAttrib.cxx \
billboardEffect.cxx \
binCullHandler.cxx \
qpcamera.cxx \
colorAttrib.cxx \
@ -66,7 +68,7 @@
qpcullTraverser.cxx \
cullTraverserData.cxx \
cullableObject.cxx \
decalAttrib.cxx \
decalEffect.cxx \
depthTestAttrib.cxx \
depthWriteAttrib.cxx \
drawCullHandler.cxx \
@ -82,6 +84,8 @@
qpnodePathComponent.cxx \
pandaNode.cxx \
renderAttrib.cxx \
renderEffect.cxx \
renderEffects.cxx \
renderState.cxx \
selectiveChildNode.cxx \
qpsequenceNode.cxx \
@ -97,7 +101,7 @@
#endif
#define INSTALL_HEADERS \
billboardAttrib.h billboardAttrib.I \
billboardEffect.h billboardEffect.I \
binCullHandler.h binCullHandler.I \
qpcamera.h qpcamera.I \
colorAttrib.h colorAttrib.I \
@ -114,7 +118,7 @@
qpcullTraverser.h qpcullTraverser.I \
cullTraverserData.h cullTraverserData.I \
cullableObject.h cullableObject.I \
decalAttrib.h decalAttrib.I \
decalEffect.h decalEffect.I \
depthTestAttrib.h depthTestAttrib.I \
depthWriteAttrib.h depthWriteAttrib.I \
drawCullHandler.h drawCullHandler.I \
@ -127,6 +131,8 @@
qpnodePathComponent.h qpnodePathComponent.I \
pandaNode.h pandaNode.I \
renderAttrib.h renderAttrib.I \
renderEffect.h renderEffect.I \
renderEffects.h renderEffects.I \
renderState.h renderState.I \
selectiveChildNode.h selectiveChildNode.I \
qpsequenceNode.h qpsequenceNode.I \

View File

@ -1,5 +1,5 @@
// Filename: billboardAttrib.I
// Created by: drose (27Feb02)
// Filename: billboardEffect.I
// Created by: drose (14Mar02)
//
////////////////////////////////////////////////////////////////////
//
@ -18,136 +18,136 @@
////////////////////////////////////////////////////////////////////
// Function: BillboardAttrib::Constructor
// Function: BillboardEffect::Constructor
// Access: Private
// Description: Use BillboardAttrib::make() to construct a new
// BillboardAttrib object.
// Description: Use BillboardEffect::make() to construct a new
// BillboardEffect object.
////////////////////////////////////////////////////////////////////
INLINE BillboardAttrib::
BillboardAttrib() {
INLINE BillboardEffect::
BillboardEffect() {
_off = true;
}
////////////////////////////////////////////////////////////////////
// Function: BillboardAttrib::make_axis
// Function: BillboardEffect::make_axis
// Access: Published, Static
// Description: A convenience function to make a typical
// axis-rotating billboard.
////////////////////////////////////////////////////////////////////
INLINE CPT(RenderAttrib) BillboardAttrib::
INLINE CPT(RenderEffect) BillboardEffect::
make_axis() {
return make(LVector3f::up(), false, true,
0.0f, qpNodePath(), LPoint3f(0.0f, 0.0f, 0.0f));
}
////////////////////////////////////////////////////////////////////
// Function: BillboardAttrib::make_point_eye
// Function: BillboardEffect::make_point_eye
// Access: Published, Static
// Description: A convenience function to make a typical
// eye-relative point-rotating billboard.
////////////////////////////////////////////////////////////////////
INLINE CPT(RenderAttrib) BillboardAttrib::
INLINE CPT(RenderEffect) BillboardEffect::
make_point_eye() {
return make(LVector3f::up(), true, false,
0.0f, qpNodePath(), LPoint3f(0.0f, 0.0f, 0.0f));
}
////////////////////////////////////////////////////////////////////
// Function: BillboardAttrib::make_point_world
// Function: BillboardEffect::make_point_world
// Access: Published, Static
// Description: A convenience function to make a typical
// world-relative point-rotating billboard.
////////////////////////////////////////////////////////////////////
INLINE CPT(RenderAttrib) BillboardAttrib::
INLINE CPT(RenderEffect) BillboardEffect::
make_point_world() {
return make(LVector3f::up(), false, false,
0.0f, qpNodePath(), LPoint3f(0.0f, 0.0f, 0.0f));
}
////////////////////////////////////////////////////////////////////
// Function: BillboardAttrib::is_off
// Function: BillboardEffect::is_off
// Access: Published
// Description: Returns true if the BillboardAttrib is an 'off'
// BillboardAttrib, indicating that it does not enable
// billboarding. This kind of BillboardAttrib isn't
// Description: Returns true if the BillboardEffect is an 'off'
// BillboardEffect, indicating that it does not enable
// billboarding. This kind of BillboardEffect isn't
// particularly useful and isn't normally created or
// stored in the graph; it might be implicitly
// discovered as the result of a
// qpNodePath::get_rel_state().
////////////////////////////////////////////////////////////////////
INLINE bool BillboardAttrib::
INLINE bool BillboardEffect::
is_off() const {
return _off;
}
////////////////////////////////////////////////////////////////////
// Function: BillboardAttrib::get_up_vector
// Function: BillboardEffect::get_up_vector
// Access: Published
// Description: Returns the up vector in effect for this billboard.
////////////////////////////////////////////////////////////////////
INLINE const LVector3f &BillboardAttrib::
INLINE const LVector3f &BillboardEffect::
get_up_vector() const {
return _up_vector;
}
////////////////////////////////////////////////////////////////////
// Function: BillboardAttrib::get_eye_relative
// Function: BillboardEffect::get_eye_relative
// Access: Published
// Description: Returns true if this billboard interprets the up
// vector relative to the camera, or false if it is
// relative to the world.
////////////////////////////////////////////////////////////////////
INLINE bool BillboardAttrib::
INLINE bool BillboardEffect::
get_eye_relative() const {
return _eye_relative;
}
////////////////////////////////////////////////////////////////////
// Function: BillboardAttrib::get_axial_rotate
// Function: BillboardEffect::get_axial_rotate
// Access: Published
// Description: Returns true if this billboard rotates only around
// the axis of the up vector, or false if it rotates
// freely in three dimensions.
////////////////////////////////////////////////////////////////////
INLINE bool BillboardAttrib::
INLINE bool BillboardEffect::
get_axial_rotate() const {
return _axial_rotate;
}
////////////////////////////////////////////////////////////////////
// Function: BillboardAttrib::get_offset
// Function: BillboardEffect::get_offset
// Access: Published
// Description: Returns the distance toward the camera (or the
// look_at_point) the billboard is moved towards, after
// rotating. This can be used to ensure the billboard
// is not obscured by nearby geometry.
////////////////////////////////////////////////////////////////////
INLINE float BillboardAttrib::
INLINE float BillboardEffect::
get_offset() const {
return _offset;
}
////////////////////////////////////////////////////////////////////
// Function: BillboardAttrib::get_look_at
// Function: BillboardEffect::get_look_at
// Access: Published
// Description: Returns the node this billboard will rotate to look
// towards. If this is empty, it means the billboard
// will rotate towards the current camera node, wherever
// that might be.
////////////////////////////////////////////////////////////////////
INLINE const qpNodePath &BillboardAttrib::
INLINE const qpNodePath &BillboardEffect::
get_look_at() const {
return _look_at;
}
////////////////////////////////////////////////////////////////////
// Function: BillboardAttrib::get_look_at_point
// Function: BillboardEffect::get_look_at_point
// Access: Published
// Description: Returns the point, relative to the look_at node,
// towards which the billboard will rotate. Normally
// this is (0, 0, 0).
////////////////////////////////////////////////////////////////////
INLINE const LPoint3f &BillboardAttrib::
INLINE const LPoint3f &BillboardEffect::
get_look_at_point() const {
return _look_at_point;
}

View File

@ -1,5 +1,5 @@
// Filename: billboardAttrib.cxx
// Created by: drose (27Feb02)
// Filename: billboardEffect.cxx
// Created by: drose (14Mar02)
//
////////////////////////////////////////////////////////////////////
//
@ -16,42 +16,54 @@
//
////////////////////////////////////////////////////////////////////
#include "billboardAttrib.h"
#include "billboardEffect.h"
#include "look_at.h"
#include "bamReader.h"
#include "bamWriter.h"
#include "datagram.h"
#include "datagramIterator.h"
TypeHandle BillboardAttrib::_type_handle;
TypeHandle BillboardEffect::_type_handle;
////////////////////////////////////////////////////////////////////
// Function: BillboardAttrib::make
// Function: BillboardEffect::make
// Access: Published, Static
// Description: Constructs a new BillboardAttrib object with the
// Description: Constructs a new BillboardEffect object with the
// indicated properties.
////////////////////////////////////////////////////////////////////
CPT(RenderAttrib) BillboardAttrib::
CPT(RenderEffect) BillboardEffect::
make(const LVector3f &up_vector, bool eye_relative,
bool axial_rotate, float offset, const qpNodePath &look_at,
const LPoint3f &look_at_point) {
BillboardAttrib *attrib = new BillboardAttrib;
attrib->_up_vector = up_vector;
attrib->_eye_relative = eye_relative;
attrib->_axial_rotate = axial_rotate;
attrib->_offset = offset;
attrib->_look_at = look_at;
attrib->_look_at_point = look_at_point;
attrib->_off = false;
return return_new(attrib);
BillboardEffect *effect = new BillboardEffect;
effect->_up_vector = up_vector;
effect->_eye_relative = eye_relative;
effect->_axial_rotate = axial_rotate;
effect->_offset = offset;
effect->_look_at = look_at;
effect->_look_at_point = look_at_point;
effect->_off = false;
return return_new(effect);
}
////////////////////////////////////////////////////////////////////
// Function: BillboardAttrib::output
// Function: BillboardEffect::safe_to_combine
// Access: Public, Virtual
// Description: Returns true if this kind of effect can safely be
// combined with sibling nodes that share the exact same
// effect, or false if this is not a good idea.
////////////////////////////////////////////////////////////////////
bool BillboardEffect::
safe_to_combine() const {
return true;
}
////////////////////////////////////////////////////////////////////
// Function: BillboardEffect::output
// Access: Public, Virtual
// Description:
////////////////////////////////////////////////////////////////////
void BillboardAttrib::
void BillboardEffect::
output(ostream &out) const {
out << get_type() << ":";
if (is_off()) {
@ -82,13 +94,13 @@ output(ostream &out) const {
}
////////////////////////////////////////////////////////////////////
// Function: BillboardAttrib::do_billboard
// Function: BillboardEffect::do_billboard
// Access: Public
// Description: Computes the appropriate transform to apply to the
// billboarded geometry, given its current net
// transform, and the camera's inverse net transform.
////////////////////////////////////////////////////////////////////
CPT(TransformState) BillboardAttrib::
CPT(TransformState) BillboardEffect::
do_billboard(const TransformState *net_transform,
const TransformState *camera_transform) const {
// Determine the relative transform to our camera (or other look_at
@ -141,23 +153,23 @@ do_billboard(const TransformState *net_transform,
}
////////////////////////////////////////////////////////////////////
// Function: BillboardAttrib::compare_to_impl
// Function: BillboardEffect::compare_to_impl
// Access: Protected, Virtual
// Description: Intended to be overridden by derived BillboardAttrib
// Description: Intended to be overridden by derived BillboardEffect
// types to return a unique number indicating whether
// this BillboardAttrib is equivalent to the other one.
// this BillboardEffect is equivalent to the other one.
//
// This should return 0 if the two BillboardAttrib objects
// This should return 0 if the two BillboardEffect objects
// are equivalent, a number less than zero if this one
// should be sorted before the other one, and a number
// greater than zero otherwise.
//
// This will only be called with two BillboardAttrib
// This will only be called with two BillboardEffect
// objects whose get_type() functions return the same.
////////////////////////////////////////////////////////////////////
int BillboardAttrib::
compare_to_impl(const RenderAttrib *other) const {
const BillboardAttrib *ta;
int BillboardEffect::
compare_to_impl(const RenderEffect *other) const {
const BillboardEffect *ta;
DCAST_INTO_R(ta, other, 0);
if (_axial_rotate != ta->_axial_rotate) {
@ -185,41 +197,41 @@ compare_to_impl(const RenderAttrib *other) const {
}
////////////////////////////////////////////////////////////////////
// Function: BillboardAttrib::make_default_impl
// Function: BillboardEffect::make_default_impl
// Access: Protected, Virtual
// Description: Intended to be overridden by derived BillboardAttrib
// Description: Intended to be overridden by derived BillboardEffect
// types to specify what the default property for a
// BillboardAttrib of this type should be.
// BillboardEffect of this type should be.
//
// This should return a newly-allocated BillboardAttrib of
// This should return a newly-allocated BillboardEffect of
// the same type that corresponds to whatever the
// standard default for this kind of BillboardAttrib is.
// standard default for this kind of BillboardEffect is.
////////////////////////////////////////////////////////////////////
RenderAttrib *BillboardAttrib::
RenderEffect *BillboardEffect::
make_default_impl() const {
return new BillboardAttrib;
return new BillboardEffect;
}
////////////////////////////////////////////////////////////////////
// Function: BillboardAttrib::register_with_read_factory
// Function: BillboardEffect::register_with_read_factory
// Access: Public, Static
// Description: Tells the BamReader how to create objects of type
// BillboardAttrib.
// BillboardEffect.
////////////////////////////////////////////////////////////////////
void BillboardAttrib::
void BillboardEffect::
register_with_read_factory() {
BamReader::get_factory()->register_factory(get_class_type(), make_from_bam);
}
////////////////////////////////////////////////////////////////////
// Function: BillboardAttrib::write_datagram
// Function: BillboardEffect::write_datagram
// Access: Public, Virtual
// Description: Writes the contents of this object to the datagram
// for shipping out to a Bam file.
////////////////////////////////////////////////////////////////////
void BillboardAttrib::
void BillboardEffect::
write_datagram(BamWriter *manager, Datagram &dg) {
RenderAttrib::write_datagram(manager, dg);
RenderEffect::write_datagram(manager, dg);
dg.add_bool(_off);
_up_vector.write_datagram(dg);
@ -233,35 +245,35 @@ write_datagram(BamWriter *manager, Datagram &dg) {
}
////////////////////////////////////////////////////////////////////
// Function: BillboardAttrib::make_from_bam
// Function: BillboardEffect::make_from_bam
// Access: Protected, Static
// Description: This function is called by the BamReader's factory
// when a new object of type BillboardAttrib is encountered
// in the Bam file. It should create the BillboardAttrib
// when a new object of type BillboardEffect is encountered
// in the Bam file. It should create the BillboardEffect
// and extract its information from the file.
////////////////////////////////////////////////////////////////////
TypedWritable *BillboardAttrib::
TypedWritable *BillboardEffect::
make_from_bam(const FactoryParams &params) {
BillboardAttrib *attrib = new BillboardAttrib;
BillboardEffect *effect = new BillboardEffect;
DatagramIterator scan;
BamReader *manager;
parse_params(params, scan, manager);
attrib->fillin(scan, manager);
effect->fillin(scan, manager);
return attrib;
return effect;
}
////////////////////////////////////////////////////////////////////
// Function: BillboardAttrib::fillin
// Function: BillboardEffect::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 BillboardAttrib.
// the new BillboardEffect.
////////////////////////////////////////////////////////////////////
void BillboardAttrib::
void BillboardEffect::
fillin(DatagramIterator &scan, BamReader *manager) {
RenderAttrib::fillin(scan, manager);
RenderEffect::fillin(scan, manager);
_off = scan.get_bool();
_up_vector.read_datagram(scan);

View File

@ -1,5 +1,5 @@
// Filename: billboardAttrib.h
// Created by: drose (27Feb02)
// Filename: billboardEffect.h
// Created by: drose (14Mar02)
//
////////////////////////////////////////////////////////////////////
//
@ -16,35 +16,35 @@
//
////////////////////////////////////////////////////////////////////
#ifndef BILLBOARDATTRIB_H
#define BILLBOARDATTRIB_H
#ifndef BILLBOARDEFFECT_H
#define BILLBOARDEFFECT_H
#include "pandabase.h"
#include "renderAttrib.h"
#include "renderEffect.h"
#include "luse.h"
#include "qpnodePath.h"
////////////////////////////////////////////////////////////////////
// Class : BillboardAttrib
// Class : BillboardEffect
// Description : Indicates that geometry at this node should
// automatically rotate to face the camera, or any other
// arbitrary node.
////////////////////////////////////////////////////////////////////
class EXPCL_PANDA BillboardAttrib : public RenderAttrib {
class EXPCL_PANDA BillboardEffect : public RenderEffect {
private:
INLINE BillboardAttrib();
INLINE BillboardEffect();
PUBLISHED:
static CPT(RenderAttrib) make(const LVector3f &up_vector,
static CPT(RenderEffect) make(const LVector3f &up_vector,
bool eye_relative,
bool axial_rotate,
float offset,
const qpNodePath &look_at,
const LPoint3f &look_at_point);
INLINE static CPT(RenderAttrib) make_axis();
INLINE static CPT(RenderAttrib) make_point_eye();
INLINE static CPT(RenderAttrib) make_point_world();
INLINE static CPT(RenderEffect) make_axis();
INLINE static CPT(RenderEffect) make_point_eye();
INLINE static CPT(RenderEffect) make_point_world();
INLINE bool is_off() const;
INLINE const LVector3f &get_up_vector() const;
@ -55,14 +55,15 @@ PUBLISHED:
INLINE const LPoint3f &get_look_at_point() const;
public:
virtual bool safe_to_combine() const;
virtual void output(ostream &out) const;
CPT(TransformState) do_billboard(const TransformState *net_transform,
const TransformState *camera_transform) const;
protected:
virtual int compare_to_impl(const RenderAttrib *other) const;
virtual RenderAttrib *make_default_impl() const;
virtual int compare_to_impl(const RenderEffect *other) const;
virtual RenderEffect *make_default_impl() const;
private:
bool _off;
@ -86,9 +87,9 @@ public:
return _type_handle;
}
static void init_type() {
RenderAttrib::init_type();
register_type(_type_handle, "BillboardAttrib",
RenderAttrib::get_class_type());
RenderEffect::init_type();
register_type(_type_handle, "BillboardEffect",
RenderEffect::get_class_type());
}
virtual TypeHandle get_type() const {
return get_class_type();
@ -99,7 +100,7 @@ private:
static TypeHandle _type_handle;
};
#include "billboardAttrib.I"
#include "billboardEffect.I"
#endif

View File

@ -18,7 +18,7 @@
#include "config_pgraph.h"
#include "billboardAttrib.h"
#include "billboardEffect.h"
#include "qpcamera.h"
#include "colorAttrib.h"
#include "colorWriteAttrib.h"
@ -29,7 +29,7 @@
#include "cullBinUnsorted.h"
#include "qpcullTraverser.h"
#include "cullableObject.h"
#include "decalAttrib.h"
#include "decalEffect.h"
#include "depthTestAttrib.h"
#include "depthWriteAttrib.h"
#include "qpgeomNode.h"
@ -40,6 +40,8 @@
#include "qpnodePathComponent.h"
#include "pandaNode.h"
#include "renderAttrib.h"
#include "renderEffect.h"
#include "renderEffects.h"
#include "renderState.h"
#include "selectiveChildNode.h"
#include "qpsequenceNode.h"
@ -79,7 +81,7 @@ init_libpgraph() {
}
initialized = true;
BillboardAttrib::init_type();
BillboardEffect::init_type();
qpCamera::init_type();
ColorAttrib::init_type();
ColorWriteAttrib::init_type();
@ -90,7 +92,7 @@ init_libpgraph() {
CullBinUnsorted::init_type();
qpCullTraverser::init_type();
CullableObject::init_type();
DecalAttrib::init_type();
DecalEffect::init_type();
DepthTestAttrib::init_type();
DepthWriteAttrib::init_type();
qpGeomNode::init_type();
@ -101,6 +103,8 @@ init_libpgraph() {
qpNodePathComponent::init_type();
PandaNode::init_type();
RenderAttrib::init_type();
RenderEffect::init_type();
RenderEffects::init_type();
RenderState::init_type();
SelectiveChildNode::init_type();
qpSequenceNode::init_type();
@ -109,13 +113,13 @@ init_libpgraph() {
TransformState::init_type();
TransparencyAttrib::init_type();
BillboardAttrib::register_with_read_factory();
BillboardEffect::register_with_read_factory();
qpCamera::register_with_read_factory();
ColorAttrib::register_with_read_factory();
ColorWriteAttrib::register_with_read_factory();
CullBinAttrib::register_with_read_factory();
CullFaceAttrib::register_with_read_factory();
DecalAttrib::register_with_read_factory();
DecalEffect::register_with_read_factory();
DepthTestAttrib::register_with_read_factory();
DepthWriteAttrib::register_with_read_factory();
qpGeomNode::register_with_read_factory();
@ -123,6 +127,7 @@ init_libpgraph() {
qpLODNode::register_with_read_factory();
MaterialAttrib::register_with_read_factory();
PandaNode::register_with_read_factory();
RenderEffects::register_with_read_factory();
RenderState::register_with_read_factory();
qpSequenceNode::register_with_read_factory();
TextureApplyAttrib::register_with_read_factory();

View File

@ -22,6 +22,7 @@
#include "pandaNode.h"
#include "colorAttrib.h"
#include "textureAttrib.h"
#include "billboardEffect.h"
////////////////////////////////////////////////////////////////////
// Function: CullTraverserData::apply_transform_and_state
@ -67,11 +68,11 @@ apply_transform_and_state(qpCullTraverser *trav, PandaNode *node) {
}
}
const RenderState *node_state = node->get_state();
_state = _state->compose(node_state);
_state = _state->compose(node->get_state());
const BillboardAttrib *billboard = node_state->get_billboard();
if (billboard != (const BillboardAttrib *)NULL) {
const RenderEffects *node_effects = node->get_effects();
const BillboardEffect *billboard = node_effects->get_billboard();
if (billboard != (const BillboardEffect *)NULL) {
// Got to apply a billboard transform here.
CPT(TransformState) billboard_transform =
billboard->do_billboard(_net_transform, trav->get_camera_transform());

View File

@ -1,5 +1,5 @@
// Filename: decalAttrib.I
// Created by: drose (04Mar02)
// Filename: decalEffect.I
// Created by: drose (14Mar02)
//
////////////////////////////////////////////////////////////////////
//
@ -18,11 +18,11 @@
////////////////////////////////////////////////////////////////////
// Function: DecalAttrib::Constructor
// Function: DecalEffect::Constructor
// Access: Private
// Description: Use DecalAttrib::make() to construct a new
// DecalAttrib object.
// Description: Use DecalEffect::make() to construct a new
// DecalEffect object.
////////////////////////////////////////////////////////////////////
INLINE DecalAttrib::
DecalAttrib() {
INLINE DecalEffect::
DecalEffect() {
}

View File

@ -1,5 +1,5 @@
// Filename: decalAttrib.cxx
// Created by: drose (04Mar02)
// Filename: decalEffect.cxx
// Created by: drose (14Mar02)
//
////////////////////////////////////////////////////////////////////
//
@ -16,113 +16,113 @@
//
////////////////////////////////////////////////////////////////////
#include "decalAttrib.h"
#include "decalEffect.h"
#include "bamReader.h"
#include "bamWriter.h"
#include "datagram.h"
#include "datagramIterator.h"
TypeHandle DecalAttrib::_type_handle;
TypeHandle DecalEffect::_type_handle;
////////////////////////////////////////////////////////////////////
// Function: DecalAttrib::make
// Function: DecalEffect::make
// Access: Published, Static
// Description: Constructs a new DecalAttrib object.
// Description: Constructs a new DecalEffect object.
////////////////////////////////////////////////////////////////////
CPT(RenderAttrib) DecalAttrib::
CPT(RenderEffect) DecalEffect::
make() {
DecalAttrib *attrib = new DecalAttrib;
return return_new(attrib);
DecalEffect *effect = new DecalEffect;
return return_new(effect);
}
////////////////////////////////////////////////////////////////////
// Function: DecalAttrib::compare_to_impl
// Function: DecalEffect::compare_to_impl
// Access: Protected, Virtual
// Description: Intended to be overridden by derived DecalAttrib
// Description: Intended to be overridden by derived DecalEffect
// types to return a unique number indicating whether
// this DecalAttrib is equivalent to the other one.
// this DecalEffect is equivalent to the other one.
//
// This should return 0 if the two DecalAttrib objects
// This should return 0 if the two DecalEffect objects
// are equivalent, a number less than zero if this one
// should be sorted before the other one, and a number
// greater than zero otherwise.
//
// This will only be called with two DecalAttrib
// This will only be called with two DecalEffect
// objects whose get_type() functions return the same.
////////////////////////////////////////////////////////////////////
int DecalAttrib::
compare_to_impl(const RenderAttrib *other) const {
// All DecalAttribs are equivalent--there are no properties to
int DecalEffect::
compare_to_impl(const RenderEffect *other) const {
// All DecalEffects are equivalent--there are no properties to
// store.
return 0;
}
////////////////////////////////////////////////////////////////////
// Function: DecalAttrib::make_default_impl
// Function: DecalEffect::make_default_impl
// Access: Protected, Virtual
// Description: Intended to be overridden by derived DecalAttrib
// Description: Intended to be overridden by derived DecalEffect
// types to specify what the default property for a
// DecalAttrib of this type should be.
// DecalEffect of this type should be.
//
// This should return a newly-allocated DecalAttrib of
// This should return a newly-allocated DecalEffect of
// the same type that corresponds to whatever the
// standard default for this kind of DecalAttrib is.
// standard default for this kind of DecalEffect is.
////////////////////////////////////////////////////////////////////
RenderAttrib *DecalAttrib::
RenderEffect *DecalEffect::
make_default_impl() const {
return new DecalAttrib;
return new DecalEffect;
}
////////////////////////////////////////////////////////////////////
// Function: DecalAttrib::register_with_read_factory
// Function: DecalEffect::register_with_read_factory
// Access: Public, Static
// Description: Tells the BamReader how to create objects of type
// DecalAttrib.
// DecalEffect.
////////////////////////////////////////////////////////////////////
void DecalAttrib::
void DecalEffect::
register_with_read_factory() {
BamReader::get_factory()->register_factory(get_class_type(), make_from_bam);
}
////////////////////////////////////////////////////////////////////
// Function: DecalAttrib::write_datagram
// Function: DecalEffect::write_datagram
// Access: Public, Virtual
// Description: Writes the contents of this object to the datagram
// for shipping out to a Bam file.
////////////////////////////////////////////////////////////////////
void DecalAttrib::
void DecalEffect::
write_datagram(BamWriter *manager, Datagram &dg) {
RenderAttrib::write_datagram(manager, dg);
RenderEffect::write_datagram(manager, dg);
}
////////////////////////////////////////////////////////////////////
// Function: DecalAttrib::make_from_bam
// Function: DecalEffect::make_from_bam
// Access: Protected, Static
// Description: This function is called by the BamReader's factory
// when a new object of type DecalAttrib is encountered
// in the Bam file. It should create the DecalAttrib
// when a new object of type DecalEffect is encountered
// in the Bam file. It should create the DecalEffect
// and extract its information from the file.
////////////////////////////////////////////////////////////////////
TypedWritable *DecalAttrib::
TypedWritable *DecalEffect::
make_from_bam(const FactoryParams &params) {
DecalAttrib *attrib = new DecalAttrib;
DecalEffect *effect = new DecalEffect;
DatagramIterator scan;
BamReader *manager;
parse_params(params, scan, manager);
attrib->fillin(scan, manager);
effect->fillin(scan, manager);
return attrib;
return effect;
}
////////////////////////////////////////////////////////////////////
// Function: DecalAttrib::fillin
// Function: DecalEffect::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 DecalAttrib.
// the new DecalEffect.
////////////////////////////////////////////////////////////////////
void DecalAttrib::
void DecalEffect::
fillin(DatagramIterator &scan, BamReader *manager) {
RenderAttrib::fillin(scan, manager);
RenderEffect::fillin(scan, manager);
}

View File

@ -1,5 +1,5 @@
// Filename: decalAttrib.h
// Created by: drose (04Mar02)
// Filename: decalEffect.h
// Created by: drose (14Mar02)
//
////////////////////////////////////////////////////////////////////
//
@ -16,29 +16,29 @@
//
////////////////////////////////////////////////////////////////////
#ifndef DECALATTRIB_H
#define DECALATTRIB_H
#ifndef DECALEFFECT_H
#define DECALEFFECT_H
#include "pandabase.h"
#include "renderAttrib.h"
#include "renderEffect.h"
////////////////////////////////////////////////////////////////////
// Class : DecalAttrib
// Class : DecalEffect
// Description : Applied to a GeomNode to indicate that the children
// of this GeomNode are coplanar and should be drawn as
// decals (eliminating Z-fighting).
////////////////////////////////////////////////////////////////////
class EXPCL_PANDA DecalAttrib : public RenderAttrib {
class EXPCL_PANDA DecalEffect : public RenderEffect {
private:
INLINE DecalAttrib();
INLINE DecalEffect();
PUBLISHED:
static CPT(RenderAttrib) make();
static CPT(RenderEffect) make();
protected:
virtual int compare_to_impl(const RenderAttrib *other) const;
virtual RenderAttrib *make_default_impl() const;
virtual int compare_to_impl(const RenderEffect *other) const;
virtual RenderEffect *make_default_impl() const;
public:
static void register_with_read_factory();
@ -53,9 +53,9 @@ public:
return _type_handle;
}
static void init_type() {
RenderAttrib::init_type();
register_type(_type_handle, "DecalAttrib",
RenderAttrib::get_class_type());
RenderEffect::init_type();
register_type(_type_handle, "DecalEffect",
RenderEffect::get_class_type());
}
virtual TypeHandle get_type() const {
return get_class_type();
@ -66,7 +66,7 @@ private:
static TypeHandle _type_handle;
};
#include "decalAttrib.I"
#include "decalEffect.I"
#endif

View File

@ -106,6 +106,7 @@ get_parent() const {
INLINE PandaNode::CData::
CData() {
_state = RenderState::make_empty();
_effects = RenderEffects::make_empty();
_transform = TransformState::make_identity();
_draw_mask = DrawMask::all_on();
}
@ -122,6 +123,7 @@ CData(const PandaNode::CData &copy) :
_up(copy._up),
_paths(copy._paths),
_state(copy._state),
_effects(copy._effects),
_transform(copy._transform),
_draw_mask(copy._draw_mask)
{
@ -409,6 +411,61 @@ clear_attrib(TypeHandle type) {
cdata->_state = cdata->_state->remove_attrib(type);
}
////////////////////////////////////////////////////////////////////
// Function: PandaNode::set_effect
// Access: Published
// Description: Adds the indicated render effect to the scene
// graph on this node. If there was already an effect
// of the same type, it is replaced.
////////////////////////////////////////////////////////////////////
INLINE void PandaNode::
set_effect(const RenderEffect *effect) {
CDWriter cdata(_cycler);
cdata->_effects = cdata->_effects->add_effect(effect);
}
////////////////////////////////////////////////////////////////////
// Function: PandaNode::get_effect
// Access: Published
// Description: Returns the render effect of the indicated type,
// if it is defined on the node, or NULL if it is not.
////////////////////////////////////////////////////////////////////
INLINE const RenderEffect *PandaNode::
get_effect(TypeHandle type) const {
CDReader cdata(_cycler);
int index = cdata->_effects->find_effect(type);
if (index >= 0) {
return cdata->_effects->get_effect(index);
}
return NULL;
}
////////////////////////////////////////////////////////////////////
// Function: PandaNode::has_effect
// Access: Published
// Description: Returns true if there is a render effect of the
// indicated type defined on this node, or false if
// there is not.
////////////////////////////////////////////////////////////////////
INLINE bool PandaNode::
has_effect(TypeHandle type) const {
CDReader cdata(_cycler);
int index = cdata->_effects->find_effect(type);
return (index >= 0);
}
////////////////////////////////////////////////////////////////////
// Function: PandaNode::clear_effect
// Access: Published
// Description: Removes the render effect of the given type from
// this node.
////////////////////////////////////////////////////////////////////
INLINE void PandaNode::
clear_effect(TypeHandle type) {
CDWriter cdata(_cycler);
cdata->_effects = cdata->_effects->remove_effect(type);
}
////////////////////////////////////////////////////////////////////
// Function: PandaNode::set_state
// Access: Published
@ -454,6 +511,43 @@ clear_state() {
cdata->_state = RenderState::make_empty();
}
////////////////////////////////////////////////////////////////////
// Function: PandaNode::set_effects
// Access: Published
// Description: Sets the complete RenderEffects that will be applied
// this node. This completely replaces whatever has
// been set on this node via repeated calls to
// set_attrib().
////////////////////////////////////////////////////////////////////
INLINE void PandaNode::
set_effects(const RenderEffects *effects) {
CDWriter cdata(_cycler);
cdata->_effects = effects;
}
////////////////////////////////////////////////////////////////////
// Function: PandaNode::get_effects
// Access: Published
// Description: Returns the complete RenderEffects that will be
// applied to this node.
////////////////////////////////////////////////////////////////////
INLINE const RenderEffects *PandaNode::
get_effects() const {
CDReader cdata(_cycler);
return cdata->_effects;
}
////////////////////////////////////////////////////////////////////
// Function: PandaNode::clear_effects
// Access: Published
// Description: Resets this node to have no render effects.
////////////////////////////////////////////////////////////////////
INLINE void PandaNode::
clear_effects() {
CDWriter cdata(_cycler);
cdata->_effects = RenderEffects::make_empty();
}
////////////////////////////////////////////////////////////////////
// Function: PandaNode::set_transform
// Access: Published
@ -463,10 +557,8 @@ clear_state() {
////////////////////////////////////////////////////////////////////
INLINE void PandaNode::
set_transform(const TransformState *transform) {
{
CDWriter cdata(_cycler);
cdata->_transform = transform;
}
CDWriter cdata(_cycler);
cdata->_transform = transform;
mark_bound_stale();
}

View File

@ -47,6 +47,7 @@ make_copy() const {
void PandaNode::CData::
write_datagram(BamWriter *manager, Datagram &dg) const {
manager->write_pointer(dg, _state);
manager->write_pointer(dg, _effects);
manager->write_pointer(dg, _transform);
dg.add_uint32(_draw_mask.get_word());
@ -67,10 +68,12 @@ int PandaNode::CData::
complete_pointers(TypedWritable **p_list, BamReader *manager) {
int pi = CycleData::complete_pointers(p_list, manager);
// Get the state and transform pointers.
// Get the state, effects, and transform pointers.
_state = DCAST(RenderState, p_list[pi++]);
_effects = DCAST(RenderEffects, p_list[pi++]);
_transform = DCAST(TransformState, p_list[pi++]);
// Get the parent and child pointers.
pi += complete_up_list(_up, p_list + pi, manager);
pi += complete_down_list(_down, p_list + pi, manager);
pi += complete_down_list(_stashed, p_list + pi, manager);
@ -87,12 +90,14 @@ complete_pointers(TypedWritable **p_list, BamReader *manager) {
////////////////////////////////////////////////////////////////////
void PandaNode::CData::
fillin(DatagramIterator &scan, BamReader *manager) {
// Read the state and transform pointers.
// Read the state, effects, and transform pointers.
manager->read_pointer(scan);
manager->read_pointer(scan);
manager->read_pointer(scan);
_draw_mask.set_word(scan.get_uint32());
// Read the parent and child pointers.
fillin_up_list(_up, scan, manager);
fillin_down_list(_down, scan, manager);
fillin_down_list(_stashed, scan, manager);
@ -304,6 +309,7 @@ PandaNode(const PandaNode &copy) :
CDReader copy_cdata(copy._cycler);
CDWriter cdata(_cycler);
cdata->_state = copy_cdata->_state;
cdata->_effects = copy_cdata->_effects;
cdata->_transform = copy_cdata->_transform;
}
@ -989,6 +995,9 @@ write(ostream &out, int indent_level) const {
if (!cdata->_state->is_empty()) {
out << " " << *cdata->_state;
}
if (!cdata->_effects->is_empty()) {
out << " " << *cdata->_effects;
}
out << "\n";
}
@ -1159,8 +1168,6 @@ r_copy_subgraph(PandaNode::InstanceMap &inst_map) const {
}
copy->r_copy_children(this, inst_map);
copy->set_state(get_state());
copy->set_transform(get_transform());
return copy;
}
@ -1528,6 +1535,9 @@ r_list_descendants(ostream &out, int indent_level) const {
if (!cdata->_state->is_empty()) {
out << " " << *cdata->_state;
}
if (!cdata->_effects->is_empty()) {
out << " " << *cdata->_effects;
}
out << "\n";
Down::const_iterator di;

View File

@ -26,6 +26,7 @@
#include "cycleDataWriter.h"
#include "pipelineCycler.h"
#include "renderState.h"
#include "renderEffects.h"
#include "transformState.h"
#include "drawMask.h"
#include "typedWritable.h"
@ -106,10 +107,19 @@ PUBLISHED:
INLINE bool has_attrib(TypeHandle type) const;
INLINE void clear_attrib(TypeHandle type);
INLINE void set_effect(const RenderEffect *effect);
INLINE const RenderEffect *get_effect(TypeHandle type) const;
INLINE bool has_effect(TypeHandle type) const;
INLINE void clear_effect(TypeHandle type);
INLINE void set_state(const RenderState *state);
INLINE const RenderState *get_state() const;
INLINE void clear_state();
INLINE void set_effects(const RenderEffects *effects);
INLINE const RenderEffects *get_effects() const;
INLINE void clear_effects();
INLINE void set_transform(const TransformState *transform);
INLINE const TransformState *get_transform() const;
INLINE void clear_transform();
@ -245,6 +255,7 @@ private:
Paths _paths;
CPT(RenderState) _state;
CPT(RenderEffects) _effects;
CPT(TransformState) _transform;
DrawMask _draw_mask;
};

View File

@ -1,4 +1,4 @@
#include "billboardAttrib.cxx"
#include "billboardEffect.cxx"
#include "binCullHandler.cxx"
#include "qpcamera.cxx"
#include "colorAttrib.cxx"

View File

@ -1,4 +1,4 @@
#include "decalAttrib.cxx"
#include "decalEffect.cxx"
#include "depthTestAttrib.cxx"
#include "depthWriteAttrib.cxx"
#include "drawCullHandler.cxx"
@ -14,6 +14,8 @@
#include "qpnodePathComponent.cxx"
#include "pandaNode.cxx"
#include "renderAttrib.cxx"
#include "renderEffect.cxx"
#include "renderEffects.cxx"
#include "renderState.cxx"
#include "selectiveChildNode.cxx"
#include "qpsequenceNode.cxx"

View File

@ -20,7 +20,6 @@
#include "cullTraverserData.h"
#include "transformState.h"
#include "renderState.h"
#include "billboardAttrib.h"
#include "cullHandler.h"
#include "dcast.h"
#include "qpgeomNode.h"
@ -116,8 +115,8 @@ traverse(PandaNode *node, const CullTraverserData &data) {
////////////////////////////////////////////////////////////////////
void qpCullTraverser::
traverse_below(PandaNode *node, const CullTraverserData &data) {
const RenderState *node_state = node->get_state();
if (node_state->has_decal()) {
const RenderEffects *node_effects = node->get_effects();
if (node_effects->has_decal()) {
start_decal(node, data);
} else {
@ -161,7 +160,7 @@ void qpCullTraverser::
start_decal(PandaNode *node, const CullTraverserData &data) {
if (!node->is_geom_node()) {
pgraph_cat.error()
<< "DecalAttrib applied to " << *node << ", not a GeomNode.\n";
<< "DecalEffect applied to " << *node << ", not a GeomNode.\n";
return;
}

View File

@ -27,7 +27,7 @@
#include "textureAttrib.h"
#include "materialAttrib.h"
#include "cullFaceAttrib.h"
#include "billboardAttrib.h"
#include "billboardEffect.h"
#include "transparencyAttrib.h"
#include "materialPool.h"
#include "look_at.h"
@ -1981,10 +1981,10 @@ do_billboard_point_world(const qpNodePath &camera, float offset) {
void qpNodePath::
set_billboard_axis(float offset) {
nassertv(!is_empty());
CPT(RenderAttrib) billboard = BillboardAttrib::make
CPT(RenderEffect) billboard = BillboardEffect::make
(LVector3f::up(), false, true,
offset, qpNodePath(), LPoint3f(0.0f, 0.0f, 0.0f));
node()->set_attrib(billboard);
node()->set_effect(billboard);
}
////////////////////////////////////////////////////////////////////
@ -1998,10 +1998,10 @@ set_billboard_axis(float offset) {
void qpNodePath::
set_billboard_point_eye(float offset) {
nassertv(!is_empty());
CPT(RenderAttrib) billboard = BillboardAttrib::make
CPT(RenderEffect) billboard = BillboardEffect::make
(LVector3f::up(), true, false,
offset, qpNodePath(), LPoint3f(0.0f, 0.0f, 0.0f));
node()->set_attrib(billboard);
node()->set_effect(billboard);
}
////////////////////////////////////////////////////////////////////
@ -2014,33 +2014,33 @@ set_billboard_point_eye(float offset) {
void qpNodePath::
set_billboard_point_world(float offset) {
nassertv(!is_empty());
CPT(RenderAttrib) billboard = BillboardAttrib::make
CPT(RenderEffect) billboard = BillboardEffect::make
(LVector3f::up(), false, false,
offset, qpNodePath(), LPoint3f(0.0f, 0.0f, 0.0f));
node()->set_attrib(billboard);
node()->set_effect(billboard);
}
////////////////////////////////////////////////////////////////////
// Function: qpNodePath::clear_billboard
// Access: Published
// Description: Removes any billboard attributes from the node.
// Description: Removes any billboard effect from the node.
////////////////////////////////////////////////////////////////////
void qpNodePath::
clear_billboard() {
nassertv(!is_empty());
node()->clear_attrib(BillboardAttrib::get_class_type());
node()->clear_effect(BillboardEffect::get_class_type());
}
////////////////////////////////////////////////////////////////////
// Function: qpNodePath::has_billboard
// Access: Published
// Description: Returns true if there is any billboard attribute on
// Description: Returns true if there is any billboard effect on
// the node.
////////////////////////////////////////////////////////////////////
bool qpNodePath::
has_billboard() const {
nassertr(!is_empty(), false);
return node()->has_attrib(BillboardAttrib::get_class_type());
return node()->has_effect(BillboardEffect::get_class_type());
}
////////////////////////////////////////////////////////////////////

View File

@ -36,6 +36,16 @@ class GraphicsStateGuardianBase;
// geometry. This includes TextureAttrib, ColorAttrib,
// etc.
//
// RenderAttrib represents render attributes that always
// propagate down to the leaves without regard to the
// particular node they are assigned to. A RenderAttrib
// will have the same effect on a leaf node whether it
// is assigned to the graph at the leaf or several nodes
// above. This is different from RenderEffect, which
// represents a particular render property that is
// applied immediately to the node on which it is
// encountered, like billboarding or decaling.
//
// You should not attempt to create or modify a
// RenderAttrib directly; instead, use the make() method
// of the appropriate kind of attrib you want. This

View File

@ -0,0 +1,44 @@
// Filename: renderEffect.I
// Created by: drose (14Mar02)
//
////////////////////////////////////////////////////////////////////
//
// 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: RenderEffect::compare_to
// Access: Public
// Description: Provides an arbitrary ordering among all unique
// RenderEffects, so we can store the essentially
// different ones in a big set and throw away the rest.
//
// This method is not needed outside of the RenderEffect
// class because all equivalent RenderEffect objects are
// guaranteed to share the same pointer; thus, a pointer
// comparison is always sufficient.
////////////////////////////////////////////////////////////////////
INLINE int RenderEffect::
compare_to(const RenderEffect &other) const {
// First, we compare the types; if they are of different types then
// they sort differently.
TypeHandle type = get_type();
TypeHandle other_type = other.get_type();
if (type != other_type) {
return type.get_index() - other_type.get_index();
}
// We only call compare_to_impl() if they have the same type.
return compare_to_impl(&other);
}

View File

@ -0,0 +1,257 @@
// Filename: renderEffect.cxx
// Created by: drose (14Mar02)
//
////////////////////////////////////////////////////////////////////
//
// 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 "renderEffect.h"
#include "bamReader.h"
#include "indent.h"
RenderEffect::Effects RenderEffect::_effects;
TypeHandle RenderEffect::_type_handle;
////////////////////////////////////////////////////////////////////
// Function: RenderEffect::Constructor
// Access: Protected
// Description:
////////////////////////////////////////////////////////////////////
RenderEffect::
RenderEffect() {
_saved_entry = _effects.end();
}
////////////////////////////////////////////////////////////////////
// Function: RenderEffect::Copy Constructor
// Access: Private
// Description: RenderEffects are not meant to be copied.
////////////////////////////////////////////////////////////////////
RenderEffect::
RenderEffect(const RenderEffect &) {
nassertv(false);
}
////////////////////////////////////////////////////////////////////
// Function: RenderEffect::Copy Assignment Operator
// Access: Private
// Description: RenderEffects are not meant to be copied.
////////////////////////////////////////////////////////////////////
void RenderEffect::
operator = (const RenderEffect &) {
nassertv(false);
}
////////////////////////////////////////////////////////////////////
// Function: RenderEffect::Destructor
// Access: Public, Virtual
// Description: The destructor is responsible for removing the
// RenderEffect from the global set if it is there.
////////////////////////////////////////////////////////////////////
RenderEffect::
~RenderEffect() {
if (_saved_entry != _effects.end()) {
_effects.erase(_saved_entry);
_saved_entry = _effects.end();
}
}
////////////////////////////////////////////////////////////////////
// Function: RenderEffect::safe_to_transform
// Access: Public, Virtual
// Description: Returns true if it is generally safe to transform
// this particular kind of RenderEffect by calling the
// xform() method, false otherwise. For instance, it's
// usually a bad idea to attempt to xform a Character.
////////////////////////////////////////////////////////////////////
bool RenderEffect::
safe_to_transform() const {
return true;
}
////////////////////////////////////////////////////////////////////
// Function: RenderEffect::safe_to_combine
// Access: Public, Virtual
// Description: Returns true if this kind of effect can safely be
// combined with sibling nodes that share the exact same
// effect, or false if this is not a good idea.
////////////////////////////////////////////////////////////////////
bool RenderEffect::
safe_to_combine() const {
return false;
}
////////////////////////////////////////////////////////////////////
// Function: RenderEffect::xform
// Access: Public, Virtual
// Description: Returns a new RenderEffect transformed by the
// indicated matrix.
////////////////////////////////////////////////////////////////////
CPT(RenderEffect) RenderEffect::
xform(const LMatrix4f &) const {
return this;
}
////////////////////////////////////////////////////////////////////
// Function: RenderEffect::output
// Access: Published, Virtual
// Description:
////////////////////////////////////////////////////////////////////
void RenderEffect::
output(ostream &out) const {
out << get_type();
}
////////////////////////////////////////////////////////////////////
// Function: RenderEffect::write
// Access: Published, Virtual
// Description:
////////////////////////////////////////////////////////////////////
void RenderEffect::
write(ostream &out, int indent_level) const {
indent(out, indent_level) << *this << "\n";
}
////////////////////////////////////////////////////////////////////
// Function: RenderEffect::return_new
// Access: Protected, Static
// Description: This function is used by derived RenderEffect types
// to share a common RenderEffect pointer for all
// equivalent RenderEffect objects.
//
// The make() function of the derived type should create
// a new RenderEffect and pass it through return_new(),
// which will either save the pointer and return it
// unchanged (if this is the first similar such object)
// or delete it and return an equivalent pointer (if
// there was already a similar object saved).
////////////////////////////////////////////////////////////////////
CPT(RenderEffect) RenderEffect::
return_new(RenderEffect *effect) {
nassertr(effect != (RenderEffect *)NULL, effect);
// This should be a newly allocated pointer, not one that was used
// for anything else.
nassertr(effect->_saved_entry == _effects.end(), effect);
// Save the effect in a local PointerTo so that it will be freed at
// the end of this function if no one else uses it.
CPT(RenderEffect) pt_effect = effect;
pair<Effects::iterator, bool> result = _effects.insert(effect);
if (result.second) {
// The effect was inserted; save the iterator and return the
// input effect.
effect->_saved_entry = result.first;
return pt_effect;
}
// The effect was not inserted; there must be an equivalent one
// already in the set. Return that one.
return *(result.first);
}
////////////////////////////////////////////////////////////////////
// Function: RenderEffect::compare_to_impl
// Access: Protected, Virtual
// Description: Intended to be overridden by derived RenderEffect
// types to return a unique number indicating whether
// this RenderEffect is equivalent to the other one.
//
// This should return 0 if the two RenderEffect objects
// are equivalent, a number less than zero if this one
// should be sorted before the other one, and a number
// greater than zero otherwise.
//
// This will only be called with two RenderEffect
// objects whose get_type() functions return the same.
////////////////////////////////////////////////////////////////////
int RenderEffect::
compare_to_impl(const RenderEffect *other) const {
return 0;
}
////////////////////////////////////////////////////////////////////
// Function: RenderEffect::write_datagram
// Access: Public, Virtual
// Description: Writes the contents of this object to the datagram
// for shipping out to a Bam file.
////////////////////////////////////////////////////////////////////
void RenderEffect::
write_datagram(BamWriter *manager, Datagram &dg) {
TypedWritable::write_datagram(manager, dg);
}
////////////////////////////////////////////////////////////////////
// Function: RenderEffect::change_this
// Access: Public, Static
// Description: Called immediately after complete_pointers(), this
// gives the object a chance to adjust its own pointer
// if desired. Most objects don't change pointers after
// completion, but some need to.
//
// Once this function has been called, the old pointer
// will no longer be accessed.
////////////////////////////////////////////////////////////////////
TypedWritable *RenderEffect::
change_this(TypedWritable *old_ptr, BamReader *manager) {
// First, uniquify the pointer.
RenderEffect *effect = DCAST(RenderEffect, old_ptr);
CPT(RenderEffect) pointer = return_new(effect);
// But now we have a problem, since we have to hold the reference
// count and there's no way to return a TypedWritable while still
// holding the reference count! We work around this by explicitly
// upping the count, and also setting a finalize() callback to down
// it later.
if (pointer == effect) {
pointer->ref();
manager->register_finalize(effect);
}
// We have to cast the pointer back to non-const, because the bam
// reader expects that.
return (RenderEffect *)pointer.p();
}
////////////////////////////////////////////////////////////////////
// Function: RenderEffect::finalize
// Access: Public, Virtual
// Description: Method to ensure that any necessary clean up tasks
// that have to be performed by this object are performed
////////////////////////////////////////////////////////////////////
void RenderEffect::
finalize() {
// Unref the pointer that we explicitly reffed in make_from_bam().
unref();
// We should never get back to zero after unreffing our own count,
// because we expect to have been stored in a pointer somewhere. If
// we do get to zero, it's a memory leak; the way to avoid this is
// to call unref_delete() above instead of unref(), but this is
// dangerous to do from within a virtual function.
nassertv(get_ref_count() != 0);
}
////////////////////////////////////////////////////////////////////
// Function: RenderEffect::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 RenderEffect.
////////////////////////////////////////////////////////////////////
void RenderEffect::
fillin(DatagramIterator &scan, BamReader *manager) {
TypedWritable::fillin(scan, manager);
}

View File

@ -0,0 +1,120 @@
// Filename: renderEffect.h
// Created by: drose (14Mar02)
//
////////////////////////////////////////////////////////////////////
//
// 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 RENDEREFFECT_H
#define RENDEREFFECT_H
#include "pandabase.h"
#include "typedWritableReferenceCount.h"
#include "indirectCompareTo.h"
#include "pointerTo.h"
#include "pset.h"
#include "luse.h"
////////////////////////////////////////////////////////////////////
// Class : RenderEffect
// Description : This is the base class for a number of special render
// effects that may be set on scene graph nodes to
// change the way they render. This includes
// BillboardEffect, DecalEffect, etc.
//
// RenderEffect represents render properties that must
// be applied as soon as they are encountered in the
// scene graph, rather than propagating down to the
// leaves. This is different from RenderAttrib, which
// represents properties like color and texture that
// don't do anything until they propagate down to a
// GeomNode.
//
// You should not attempt to create or modify a
// RenderEffect directly; instead, use the make() method
// of the appropriate kind of effect you want. This
// will allocate and return a new RenderEffect of the
// appropriate type, and it may share pointers if
// possible. Do not modify the new RenderEffect if you
// wish to change its properties; instead, create a new
// one.
////////////////////////////////////////////////////////////////////
class EXPCL_PANDA RenderEffect : public TypedWritableReferenceCount {
protected:
RenderEffect();
private:
RenderEffect(const RenderEffect &copy);
void operator = (const RenderEffect &copy);
public:
virtual ~RenderEffect();
INLINE int compare_to(const RenderEffect &other) const;
virtual bool safe_to_transform() const;
virtual bool safe_to_combine() const;
virtual CPT(RenderEffect) xform(const LMatrix4f &mat) const;
PUBLISHED:
virtual void output(ostream &out) const;
virtual void write(ostream &out, int indent_level) const;
protected:
static CPT(RenderEffect) return_new(RenderEffect *effect);
virtual int compare_to_impl(const RenderEffect *other) const;
private:
typedef pset<const RenderEffect *, IndirectCompareTo<RenderEffect> > Effects;
static Effects _effects;
Effects::iterator _saved_entry;
public:
virtual void write_datagram(BamWriter *manager, Datagram &dg);
static TypedWritable *change_this(TypedWritable *old_ptr, BamReader *manager);
virtual void finalize();
protected:
static TypedWritable *new_from_bam(RenderEffect *effect, BamReader *manager);
void fillin(DatagramIterator &scan, BamReader *manager);
public:
static TypeHandle get_class_type() {
return _type_handle;
}
static void init_type() {
TypedWritableReferenceCount::init_type();
register_type(_type_handle, "RenderEffect",
TypedWritableReferenceCount::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;
};
INLINE ostream &operator << (ostream &out, const RenderEffect &effect) {
effect.output(out);
return out;
}
#include "renderEffect.I"
#endif

View File

@ -0,0 +1,182 @@
// Filename: renderEffects.I
// Created by: drose (14Mar02)
//
////////////////////////////////////////////////////////////////////
//
// 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: RenderEffects::Effect::Constructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
INLINE RenderEffects::Effect::
Effect(const RenderEffect *effect) :
_type(effect->get_type()),
_effect(effect)
{
}
////////////////////////////////////////////////////////////////////
// Function: RenderEffects::Effect::Constructor
// Access: Public
// Description: This constructor is only used when reading the
// RenderEffects from a bam file. At this point, the
// effect pointer is unknown.
////////////////////////////////////////////////////////////////////
INLINE RenderEffects::Effect::
Effect() {
}
////////////////////////////////////////////////////////////////////
// Function: RenderEffects::Effect::Constructor
// Access: Public
// Description: This constructor makes an invalid Effect with no
// RenderEffect pointer; its purpose is just to make an
// object we can use to look up a particular type in the
// Effect set.
////////////////////////////////////////////////////////////////////
INLINE RenderEffects::Effect::
Effect(TypeHandle type) :
_type(type),
_effect(NULL)
{
}
////////////////////////////////////////////////////////////////////
// Function: RenderEffects::Effect::Copy Constructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
INLINE RenderEffects::Effect::
Effect(const Effect &copy) :
_type(copy._type),
_effect(copy._effect)
{
}
////////////////////////////////////////////////////////////////////
// Function: RenderEffects::Effect::Copy Assignment Operator
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
INLINE void RenderEffects::Effect::
operator = (const Effect &copy) {
_type = copy._type;
_effect = copy._effect;
}
////////////////////////////////////////////////////////////////////
// Function: RenderEffects::Effect::operator <
// Access: Public
// Description: This is used by the Effects set to uniquify
// RenderEffects by type. Only one RenderEffect of a
// given type is allowed in the set. This ordering must
// also match the ordering reported by compare_to().
////////////////////////////////////////////////////////////////////
INLINE bool RenderEffects::Effect::
operator < (const Effect &other) const {
return _type < other._type;
}
////////////////////////////////////////////////////////////////////
// Function: RenderEffects::Effect::compare_to
// Access: Public
// Description: Provides an indication of whether a particular
// effect is equivalent to another one, for purposes
// of generating unique RenderEffectss. This should
// compare all properties of the Effect, but it is
// important that the type is compared first, to be
// consistent with the ordering defined by operator <.
////////////////////////////////////////////////////////////////////
INLINE int RenderEffects::Effect::
compare_to(const Effect &other) const {
if (_type != other._type) {
return _type.get_index() - other._type.get_index();
}
return _effect - other._effect;
}
////////////////////////////////////////////////////////////////////
// Function: RenderEffects::is_empty
// Access: Published
// Description: Returns true if the state is empty, false otherwise.
////////////////////////////////////////////////////////////////////
INLINE bool RenderEffects::
is_empty() const {
return _effects.empty();
}
////////////////////////////////////////////////////////////////////
// Function: RenderEffects::get_num_effects
// Access: Published
// Description: Returns the number of separate effects indicated
// in the state.
////////////////////////////////////////////////////////////////////
INLINE int RenderEffects::
get_num_effects() const {
return _effects.size();
}
////////////////////////////////////////////////////////////////////
// Function: RenderEffects::get_effect
// Access: Published
// Description: Returns the nth effect in the state.
////////////////////////////////////////////////////////////////////
INLINE const RenderEffect *RenderEffects::
get_effect(int n) const {
nassertr(n >= 0 && n < (int)_effects.size(), NULL);
return _effects[n]._effect;
}
////////////////////////////////////////////////////////////////////
// Function: RenderEffects::get_billboard
// Access: Public
// Description: This function is provided as an optimization, to
// speed up the render-time checking for the existance
// of a BillboardEffect on this state. It returns a
// pointer to the BillboardEffect, if there is one, or
// NULL if there is not.
////////////////////////////////////////////////////////////////////
INLINE const BillboardEffect *RenderEffects::
get_billboard() const {
if ((_flags & F_checked_billboard) == 0) {
// We pretend this function is const, even though it transparently
// modifies the internal billboard cache.
((RenderEffects *)this)->determine_billboard();
}
return _billboard;
}
////////////////////////////////////////////////////////////////////
// Function: RenderEffects::has_decal
// Access: Public
// Description: This function is provided as an optimization, to
// speed up the render-time checking for the existance
// of a DecalEffect on this state. It returns true if a
// DecalEffect exists, false otherwise. Note that since
// there is no additional information stored on the
// DecalEffect, there's no point in returning it if it
// exists.
////////////////////////////////////////////////////////////////////
INLINE bool RenderEffects::
has_decal() const {
if ((_flags & F_checked_decal) == 0) {
// We pretend this function is const, even though it transparently
// modifies the internal decal cache.
((RenderEffects *)this)->determine_decal();
}
return ((_flags & F_has_decal) != 0);
}

View File

@ -0,0 +1,618 @@
// Filename: renderEffects.cxx
// Created by: drose (14Mar02)
//
////////////////////////////////////////////////////////////////////
//
// 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 "renderEffects.h"
#include "billboardEffect.h"
#include "decalEffect.h"
#include "config_pgraph.h"
#include "bamReader.h"
#include "bamWriter.h"
#include "datagramIterator.h"
#include "indent.h"
#include "compareTo.h"
RenderEffects::States RenderEffects::_states;
CPT(RenderEffects) RenderEffects::_empty_state;
TypeHandle RenderEffects::_type_handle;
////////////////////////////////////////////////////////////////////
// Function: RenderEffects::Constructor
// Access: Protected
// Description: Actually, this could be a private constructor, since
// no one inherits from RenderEffects, but gcc gives us a
// spurious warning if all constructors are private.
////////////////////////////////////////////////////////////////////
RenderEffects::
RenderEffects() {
_saved_entry = _states.end();
_flags = 0;
}
////////////////////////////////////////////////////////////////////
// Function: RenderEffects::Copy Constructor
// Access: Private
// Description: RenderEffectss are not meant to be copied.
////////////////////////////////////////////////////////////////////
RenderEffects::
RenderEffects(const RenderEffects &) {
nassertv(false);
}
////////////////////////////////////////////////////////////////////
// Function: RenderEffects::Copy Assignment Operator
// Access: Private
// Description: RenderEffectss are not meant to be copied.
////////////////////////////////////////////////////////////////////
void RenderEffects::
operator = (const RenderEffects &) {
nassertv(false);
}
////////////////////////////////////////////////////////////////////
// Function: RenderEffects::Destructor
// Access: Public, Virtual
// Description: The destructor is responsible for removing the
// RenderEffects from the global set if it is there.
////////////////////////////////////////////////////////////////////
RenderEffects::
~RenderEffects() {
// Remove the deleted RenderEffects object from the global pool.
if (_saved_entry != _states.end()) {
_states.erase(_saved_entry);
_saved_entry = _states.end();
}
}
////////////////////////////////////////////////////////////////////
// Function: RenderEffects::operator <
// Access: Public
// Description: Provides an arbitrary ordering among all unique
// RenderEffectss, so we can store the essentially
// different ones in a big set and throw away the rest.
//
// This method is not needed outside of the RenderEffects
// class because all equivalent RenderEffects objects are
// guaranteed to share the same pointer; thus, a pointer
// comparison is always sufficient.
////////////////////////////////////////////////////////////////////
bool RenderEffects::
operator < (const RenderEffects &other) const {
// We must compare all the properties of the effects, not just
// the type; thus, we compare them one at a time using compare_to().
return lexicographical_compare(_effects.begin(), _effects.end(),
other._effects.begin(), other._effects.end(),
CompareTo<Effect>());
}
////////////////////////////////////////////////////////////////////
// Function: RenderEffects::safe_to_transform
// Access: Public
// Description: Returns true if all of the effects in this set can
// safely be transformed, and therefore the complete set
// can be transformed, by calling xform().
////////////////////////////////////////////////////////////////////
bool RenderEffects::
safe_to_transform() const {
Effects::const_iterator ai;
for (ai = _effects.begin(); ai != _effects.end(); ++ai) {
const Effect &effect = (*ai);
if (!effect._effect->safe_to_transform()) {
return false;
}
}
return true;
}
////////////////////////////////////////////////////////////////////
// Function: RenderEffects::safe_to_combine
// Access: Public
// Description: Returns true if all of the effects in this set can
// safely be shared with a sibling node that has the
// exact same set of effects, or false if this would be
// bad for any of the effects.
////////////////////////////////////////////////////////////////////
bool RenderEffects::
safe_to_combine() const {
Effects::const_iterator ai;
for (ai = _effects.begin(); ai != _effects.end(); ++ai) {
const Effect &effect = (*ai);
if (!effect._effect->safe_to_combine()) {
return false;
}
}
return true;
}
////////////////////////////////////////////////////////////////////
// Function: RenderEffects::xform
// Access: Public, Virtual
// Description: Returns a new RenderEffects transformed by the
// indicated matrix.
////////////////////////////////////////////////////////////////////
CPT(RenderEffects) RenderEffects::
xform(const LMatrix4f &mat) const {
if (is_empty()) {
return this;
}
RenderEffects *new_state = new RenderEffects;
back_insert_iterator<Effects> result =
back_inserter(new_state->_effects);
Effects::const_iterator ai;
for (ai = _effects.begin(); ai != _effects.end(); ++ai) {
const Effect &effect = (*ai);
Effect new_effect(effect);
new_effect._effect = effect._effect->xform(mat);
*result = new_effect;
++result;
}
return return_new(new_state);
}
////////////////////////////////////////////////////////////////////
// Function: RenderEffects::find_effect
// Access: Published
// Description: Searches for an effect with the indicated type in
// the state, and returns its index if it is found, or
// -1 if it is not.
////////////////////////////////////////////////////////////////////
int RenderEffects::
find_effect(TypeHandle type) const {
Effects::const_iterator ai = _effects.find(Effect(type));
if (ai == _effects.end()) {
return -1;
}
return ai - _effects.begin();
}
////////////////////////////////////////////////////////////////////
// Function: RenderEffects::make_empty
// Access: Published, Static
// Description: Returns a RenderEffects with no effects set.
////////////////////////////////////////////////////////////////////
CPT(RenderEffects) RenderEffects::
make_empty() {
// The empty state is asked for so often, we make it a special case
// and store a pointer forever once we find it the first time.
if (_empty_state == (RenderEffects *)NULL) {
RenderEffects *state = new RenderEffects;
_empty_state = return_new(state);
}
return _empty_state;
}
////////////////////////////////////////////////////////////////////
// Function: RenderEffects::make
// Access: Published, Static
// Description: Returns a RenderEffects with one effect set.
////////////////////////////////////////////////////////////////////
CPT(RenderEffects) RenderEffects::
make(const RenderEffect *effect) {
RenderEffects *state = new RenderEffects;
state->_effects.reserve(1);
state->_effects.insert(Effect(effect));
return return_new(state);
}
////////////////////////////////////////////////////////////////////
// Function: RenderEffects::make
// Access: Published, Static
// Description: Returns a RenderEffects with two effects set.
////////////////////////////////////////////////////////////////////
CPT(RenderEffects) RenderEffects::
make(const RenderEffect *effect1,
const RenderEffect *effect2) {
RenderEffects *state = new RenderEffects;
state->_effects.reserve(2);
state->_effects.push_back(Effect(effect1));
state->_effects.push_back(Effect(effect2));
state->_effects.sort();
return return_new(state);
}
////////////////////////////////////////////////////////////////////
// Function: RenderEffects::make
// Access: Published, Static
// Description: Returns a RenderEffects with three effects set.
////////////////////////////////////////////////////////////////////
CPT(RenderEffects) RenderEffects::
make(const RenderEffect *effect1,
const RenderEffect *effect2,
const RenderEffect *effect3) {
RenderEffects *state = new RenderEffects;
state->_effects.reserve(2);
state->_effects.push_back(Effect(effect1));
state->_effects.push_back(Effect(effect2));
state->_effects.push_back(Effect(effect3));
state->_effects.sort();
return return_new(state);
}
////////////////////////////////////////////////////////////////////
// Function: RenderEffects::make
// Access: Published, Static
// Description: Returns a RenderEffects with four effects set.
////////////////////////////////////////////////////////////////////
CPT(RenderEffects) RenderEffects::
make(const RenderEffect *effect1,
const RenderEffect *effect2,
const RenderEffect *effect3,
const RenderEffect *effect4) {
RenderEffects *state = new RenderEffects;
state->_effects.reserve(2);
state->_effects.push_back(Effect(effect1));
state->_effects.push_back(Effect(effect2));
state->_effects.push_back(Effect(effect3));
state->_effects.push_back(Effect(effect4));
state->_effects.sort();
return return_new(state);
}
////////////////////////////////////////////////////////////////////
// Function: RenderEffects::add_effect
// Access: Published
// Description: Returns a new RenderEffects object that represents the
// same as the source state, with the new RenderEffect
// added. If there is already a RenderEffect with the
// same type, it is replaced.
////////////////////////////////////////////////////////////////////
CPT(RenderEffects) RenderEffects::
add_effect(const RenderEffect *effect) const {
RenderEffects *new_state = new RenderEffects;
back_insert_iterator<Effects> result =
back_inserter(new_state->_effects);
Effect new_effect(effect);
Effects::const_iterator ai = _effects.begin();
while (ai != _effects.end() && (*ai) < new_effect) {
*result = *ai;
++ai;
++result;
}
*result = new_effect;
++result;
if (ai != _effects.end() && !(new_effect < (*ai))) {
// At this point we know:
// !((*ai) < new_effect) && !(new_effect < (*ai))
// which means (*ai) == new_effect--so we should leave it out,
// to avoid duplicating effects in the set.
++ai;
}
while (ai != _effects.end()) {
*result = *ai;
++ai;
++result;
}
return return_new(new_state);
}
////////////////////////////////////////////////////////////////////
// Function: RenderEffects::remove_effect
// Access: Published
// Description: Returns a new RenderEffects object that represents the
// same as the source state, with the indicated
// RenderEffect removed.
////////////////////////////////////////////////////////////////////
CPT(RenderEffects) RenderEffects::
remove_effect(TypeHandle type) const {
RenderEffects *new_state = new RenderEffects;
back_insert_iterator<Effects> result =
back_inserter(new_state->_effects);
Effects::const_iterator ai = _effects.begin();
while (ai != _effects.end()) {
if ((*ai)._type != type) {
*result = *ai;
++result;
}
++ai;
}
return return_new(new_state);
}
////////////////////////////////////////////////////////////////////
// Function: RenderEffects::get_effect
// Access: Published, Virtual
// Description: Looks for a RenderEffect of the indicated type in the
// state, and returns it if it is found, or NULL if it
// is not.
////////////////////////////////////////////////////////////////////
const RenderEffect *RenderEffects::
get_effect(TypeHandle type) const {
Effects::const_iterator ai;
ai = _effects.find(Effect(type));
if (ai != _effects.end()) {
return (*ai)._effect;
}
return NULL;
}
////////////////////////////////////////////////////////////////////
// Function: RenderEffects::output
// Access: Published, Virtual
// Description:
////////////////////////////////////////////////////////////////////
void RenderEffects::
output(ostream &out) const {
out << "E:";
if (_effects.empty()) {
out << "(empty)";
} else {
Effects::const_iterator ai = _effects.begin();
out << "(" << (*ai)._type;
++ai;
while (ai != _effects.end()) {
out << " " << (*ai)._type;
++ai;
}
out << ")";
}
}
////////////////////////////////////////////////////////////////////
// Function: RenderEffects::write
// Access: Published, Virtual
// Description:
////////////////////////////////////////////////////////////////////
void RenderEffects::
write(ostream &out, int indent_level) const {
indent(out, indent_level) << _effects.size() << " effects:\n";
Effects::const_iterator ai;
for (ai = _effects.begin(); ai != _effects.end(); ++ai) {
const Effect &effect = (*ai);
effect._effect->write(out, indent_level + 2);
}
}
////////////////////////////////////////////////////////////////////
// Function: RenderEffects::return_new
// Access: Private, Static
// Description: This function is used to share a common RenderEffects
// pointer for all equivalent RenderEffects objects.
//
// See the similar logic in RenderEffect. The idea is
// to create a new RenderEffects object and pass it
// through this function, which will share the pointer
// with a previously-created RenderEffects object if it is
// equivalent.
////////////////////////////////////////////////////////////////////
CPT(RenderEffects) RenderEffects::
return_new(RenderEffects *state) {
nassertr(state != (RenderEffects *)NULL, state);
// This should be a newly allocated pointer, not one that was used
// for anything else.
nassertr(state->_saved_entry == _states.end(), state);
// Save the state in a local PointerTo so that it will be freed at
// the end of this function if no one else uses it.
CPT(RenderEffects) pt_state = state;
pair<States::iterator, bool> result = _states.insert(state);
if (result.second) {
// The state was inserted; save the iterator and return the
// input state.
state->_saved_entry = result.first;
return pt_state;
}
// The state was not inserted; there must be an equivalent one
// already in the set. Return that one.
return *(result.first);
}
////////////////////////////////////////////////////////////////////
// Function: RenderEffects::determine_billboard
// Access: Private
// Description: This is the private implementation of
// get_billboard().
////////////////////////////////////////////////////////////////////
void RenderEffects::
determine_billboard() {
const RenderEffect *effect = get_effect(BillboardEffect::get_class_type());
_billboard = (const BillboardEffect *)NULL;
if (effect != (const RenderEffect *)NULL) {
_billboard = DCAST(BillboardEffect, effect);
}
_flags |= F_checked_billboard;
}
////////////////////////////////////////////////////////////////////
// Function: RenderEffects::determine_decal
// Access: Private
// Description: This is the private implementation of has_decal().
////////////////////////////////////////////////////////////////////
void RenderEffects::
determine_decal() {
const RenderEffect *effect = get_effect(DecalEffect::get_class_type());
if (effect != (const RenderEffect *)NULL) {
_flags |= F_has_decal;
}
_flags |= F_checked_decal;
}
////////////////////////////////////////////////////////////////////
// Function: RenderEffects::register_with_read_factory
// Access: Public, Static
// Description: Tells the BamReader how to create objects of type
// RenderEffects.
////////////////////////////////////////////////////////////////////
void RenderEffects::
register_with_read_factory() {
BamReader::get_factory()->register_factory(get_class_type(), make_from_bam);
}
////////////////////////////////////////////////////////////////////
// Function: RenderEffects::write_datagram
// Access: Public, Virtual
// Description: Writes the contents of this object to the datagram
// for shipping out to a Bam file.
////////////////////////////////////////////////////////////////////
void RenderEffects::
write_datagram(BamWriter *manager, Datagram &dg) {
TypedWritable::write_datagram(manager, dg);
int num_effects = _effects.size();
nassertv(num_effects == (int)(PN_uint16)num_effects);
dg.add_uint16(num_effects);
Effects::const_iterator ai;
for (ai = _effects.begin(); ai != _effects.end(); ++ai) {
const Effect &effect = (*ai);
manager->write_pointer(dg, effect._effect);
}
}
////////////////////////////////////////////////////////////////////
// Function: RenderEffects::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 RenderEffects::
complete_pointers(TypedWritable **p_list, BamReader *manager) {
int pi = TypedWritable::complete_pointers(p_list, manager);
// Get the effect pointers.
Effects::iterator ai;
for (ai = _effects.begin(); ai != _effects.end(); ++ai) {
Effect &effect = (*ai);
effect._effect = DCAST(RenderEffect, p_list[pi++]);
nassertr(effect._effect != (RenderEffect *)NULL, pi);
effect._type = effect._effect->get_type();
}
// Now make sure the array is properly sorted. (It won't
// necessarily preserve its correct sort after being read from bam,
// because the sort is based on TypeHandle indices, which can change
// from session to session.)
_effects.sort();
return pi;
}
////////////////////////////////////////////////////////////////////
// Function: RenderEffects::change_this
// Access: Public, Static
// Description: Called immediately after complete_pointers(), this
// gives the object a chance to adjust its own pointer
// if desired. Most objects don't change pointers after
// completion, but some need to.
//
// Once this function has been called, the old pointer
// will no longer be accessed.
////////////////////////////////////////////////////////////////////
TypedWritable *RenderEffects::
change_this(TypedWritable *old_ptr, BamReader *manager) {
// First, uniquify the pointer.
RenderEffects *state = DCAST(RenderEffects, old_ptr);
CPT(RenderEffects) pointer = return_new(state);
// But now we have a problem, since we have to hold the reference
// count and there's no way to return a TypedWritable while still
// holding the reference count! We work around this by explicitly
// upping the count, and also setting a finalize() callback to down
// it later.
if (pointer == state) {
pointer->ref();
manager->register_finalize(state);
}
// We have to cast the pointer back to non-const, because the bam
// reader expects that.
return (RenderEffects *)pointer.p();
}
////////////////////////////////////////////////////////////////////
// Function: RenderEffects::finalize
// Access: Public, Virtual
// Description: Called by the BamReader to perform any final actions
// needed for setting up the object after all objects
// have been read and all pointers have been completed.
////////////////////////////////////////////////////////////////////
void RenderEffects::
finalize() {
// Unref the pointer that we explicitly reffed in make_from_bam().
unref();
// We should never get back to zero after unreffing our own count,
// because we expect to have been stored in a pointer somewhere. If
// we do get to zero, it's a memory leak; the way to avoid this is
// to call unref_delete() above instead of unref(), but this is
// dangerous to do from within a virtual function.
nassertv(get_ref_count() != 0);
}
////////////////////////////////////////////////////////////////////
// Function: RenderEffects::make_from_bam
// Access: Protected, Static
// Description: This function is called by the BamReader's factory
// when a new object of type RenderEffects is encountered
// in the Bam file. It should create the RenderEffects
// and extract its information from the file.
////////////////////////////////////////////////////////////////////
TypedWritable *RenderEffects::
make_from_bam(const FactoryParams &params) {
RenderEffects *state = new RenderEffects;
DatagramIterator scan;
BamReader *manager;
parse_params(params, scan, manager);
state->fillin(scan, manager);
manager->register_change_this(change_this, state);
return state;
}
////////////////////////////////////////////////////////////////////
// Function: RenderEffects::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 RenderEffects.
////////////////////////////////////////////////////////////////////
void RenderEffects::
fillin(DatagramIterator &scan, BamReader *manager) {
TypedWritable::fillin(scan, manager);
int num_effects = scan.get_uint16();
// Push back a NULL pointer for each effect for now, until we get
// the actual list of pointers later in complete_pointers().
_effects.reserve(num_effects);
for (int i = 0; i < num_effects; i++) {
manager->read_pointer(scan);
_effects.push_back(Effect());
}
}

View File

@ -0,0 +1,174 @@
// Filename: renderEffects.h
// Created by: drose (14Mar02)
//
////////////////////////////////////////////////////////////////////
//
// 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 RENDEREFFECTS_H
#define RENDEREFFECTS_H
#include "pandabase.h"
#include "renderEffect.h"
#include "typedWritableReferenceCount.h"
#include "pointerTo.h"
#include "indirectLess.h"
#include "ordered_vector.h"
class BillboardEffect;
////////////////////////////////////////////////////////////////////
// Class : RenderEffects
// Description : This represents a unique collection of RenderEffect
// objects that correspond to a particular renderable
// state.
//
// You should not attempt to create or modify a
// RenderEffects object directly. Instead, call one of
// the make() functions to create one for you. And
// instead of modifying a RenderEffects object, create a
// new one.
////////////////////////////////////////////////////////////////////
class EXPCL_PANDA RenderEffects : public TypedWritableReferenceCount {
protected:
RenderEffects();
private:
RenderEffects(const RenderEffects &copy);
void operator = (const RenderEffects &copy);
public:
virtual ~RenderEffects();
bool operator < (const RenderEffects &other) const;
bool safe_to_transform() const;
bool safe_to_combine() const;
CPT(RenderEffects) xform(const LMatrix4f &mat) const;
PUBLISHED:
INLINE bool is_empty() const;
INLINE int get_num_effects() const;
INLINE const RenderEffect *get_effect(int n) const;
int find_effect(TypeHandle type) const;
static CPT(RenderEffects) make_empty();
static CPT(RenderEffects) make(const RenderEffect *effect);
static CPT(RenderEffects) make(const RenderEffect *effect1,
const RenderEffect *effect2);
static CPT(RenderEffects) make(const RenderEffect *effect1,
const RenderEffect *effect2,
const RenderEffect *effect3);
static CPT(RenderEffects) make(const RenderEffect *effect1,
const RenderEffect *effect2,
const RenderEffect *effect3,
const RenderEffect *effect4);
CPT(RenderEffects) add_effect(const RenderEffect *effect) const;
CPT(RenderEffects) remove_effect(TypeHandle type) const;
const RenderEffect *get_effect(TypeHandle type) const;
void output(ostream &out) const;
void write(ostream &out, int indent_level) const;
public:
INLINE const BillboardEffect *get_billboard() const;
INLINE bool has_decal() const;
private:
static CPT(RenderEffects) return_new(RenderEffects *state);
void determine_billboard();
void determine_decal();
private:
typedef pset<const RenderEffects *, IndirectLess<RenderEffects> > States;
static States _states;
static CPT(RenderEffects) _empty_state;
// This iterator records the entry corresponding to this RenderEffects
// object in the above global set. We keep the iterator around so
// we can remove it when the RenderEffects destructs.
States::iterator _saved_entry;
private:
// This is the actual data within the RenderEffects: a set of
// RenderEffects.
class Effect {
public:
INLINE Effect(const RenderEffect *effect);
INLINE Effect();
INLINE Effect(TypeHandle type);
INLINE Effect(const Effect &copy);
INLINE void operator = (const Effect &copy);
INLINE bool operator < (const Effect &other) const;
INLINE int compare_to(const Effect &other) const;
TypeHandle _type;
CPT(RenderEffect) _effect;
};
typedef ov_set<Effect> Effects;
Effects _effects;
// We cache the pointer to the some critical effects stored in
// the state, if they exist.
const BillboardEffect *_billboard;
enum Flags {
F_checked_billboard = 0x0001,
F_checked_decal = 0x0002,
F_has_decal = 0x0004,
};
short _flags;
public:
static void register_with_read_factory();
virtual void write_datagram(BamWriter *manager, Datagram &dg);
virtual int complete_pointers(TypedWritable **plist, BamReader *manager);
static TypedWritable *change_this(TypedWritable *old_ptr, BamReader *manager);
virtual void finalize();
protected:
static TypedWritable *make_from_bam(const FactoryParams &params);
void fillin(DatagramIterator &scan, BamReader *manager);
public:
static TypeHandle get_class_type() {
return _type_handle;
}
static void init_type() {
TypedWritableReferenceCount::init_type();
register_type(_type_handle, "RenderEffects",
TypedWritableReferenceCount::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;
};
INLINE ostream &operator << (ostream &out, const RenderEffects &state) {
state.output(out);
return out;
}
#include "renderEffects.I"
#endif

View File

@ -162,54 +162,14 @@ get_override(int n) const {
return _attributes[n]._override;
}
////////////////////////////////////////////////////////////////////
// Function: RenderState::get_billboard
// Access: Public
// Description: This function is provided as an optimization, to
// speed up the render-time checking for the existance
// of a BillboardAttrib on this state. It returns a
// pointer to the BillboardAttrib, if there is one, or
// NULL if there is not.
////////////////////////////////////////////////////////////////////
INLINE const BillboardAttrib *RenderState::
get_billboard() const {
if ((_flags & F_checked_billboard) == 0) {
// We pretend this function is const, even though it transparently
// modifies the internal billboard cache.
((RenderState *)this)->determine_billboard();
}
return _billboard;
}
////////////////////////////////////////////////////////////////////
// Function: RenderState::has_decal
// Access: Public
// Description: This function is provided as an optimization, to
// speed up the render-time checking for the existance
// of a DecalAttrib on this state. It returns true if a
// DecalAttrib exists, false otherwise. Note that since
// there is no additional information stored on the
// DecalAttrib, there's no point in returning it if it
// exists.
////////////////////////////////////////////////////////////////////
INLINE bool RenderState::
has_decal() const {
if ((_flags & F_checked_decal) == 0) {
// We pretend this function is const, even though it transparently
// modifies the internal decal cache.
((RenderState *)this)->determine_decal();
}
return ((_flags & F_has_decal) != 0);
}
////////////////////////////////////////////////////////////////////
// Function: RenderState::get_bin_index
// Access: Public
// Description: Returns the bin index indicated by the CullBinAttrib,
// if any, associated by this state (or the default bin
// index if there is no CullBinAttrib). As in
// get_billboard(), above, this function is provided as
// an optimization.
// index if there is no CullBinAttrib). This function
// is provided as an optimization for determining this
// at render time.
////////////////////////////////////////////////////////////////////
INLINE int RenderState::
get_bin_index() const {

View File

@ -17,7 +17,6 @@
////////////////////////////////////////////////////////////////////
#include "renderState.h"
#include "billboardAttrib.h"
#include "transparencyAttrib.h"
#include "cullBinAttrib.h"
#include "cullBinManager.h"
@ -868,36 +867,6 @@ do_invert_compose(const RenderState *other) const {
return return_new(new_state);
}
////////////////////////////////////////////////////////////////////
// Function: RenderState::determine_billboard
// Access: Private
// Description: This is the private implementation of
// get_billboard().
////////////////////////////////////////////////////////////////////
void RenderState::
determine_billboard() {
const RenderAttrib *attrib = get_attrib(BillboardAttrib::get_class_type());
_billboard = (const BillboardAttrib *)NULL;
if (attrib != (const RenderAttrib *)NULL) {
_billboard = DCAST(BillboardAttrib, attrib);
}
_flags |= F_checked_billboard;
}
////////////////////////////////////////////////////////////////////
// Function: RenderState::determine_decal
// Access: Private
// Description: This is the private implementation of has_decal().
////////////////////////////////////////////////////////////////////
void RenderState::
determine_decal() {
const RenderAttrib *attrib = get_attrib(DecalAttrib::get_class_type());
if (attrib != (const RenderAttrib *)NULL) {
_flags |= F_has_decal;
}
_flags |= F_checked_decal;
}
////////////////////////////////////////////////////////////////////
// Function: RenderState::determine_bin_index
// Access: Private

View File

@ -28,7 +28,6 @@
#include "ordered_vector.h"
class GraphicsStateGuardianBase;
class BillboardAttrib;
////////////////////////////////////////////////////////////////////
// Class : RenderState
@ -89,8 +88,6 @@ PUBLISHED:
void write(ostream &out, int indent_level) const;
public:
INLINE const BillboardAttrib *get_billboard() const;
INLINE bool has_decal() const;
INLINE int get_bin_index() const;
INLINE int get_draw_order() const;
@ -105,8 +102,6 @@ private:
static CPT(RenderState) return_new(RenderState *state);
CPT(RenderState) do_compose(const RenderState *other) const;
CPT(RenderState) do_invert_compose(const RenderState *other) const;
void determine_billboard();
void determine_decal();
void determine_bin_index();
private:
@ -161,19 +156,13 @@ private:
typedef ov_set<Attribute> Attributes;
Attributes _attributes;
// We cache the pointer to the some critical attributes stored in
// the state, if they exist.
const BillboardAttrib *_billboard;
// We also cache the index to the associated GeomBin.
// We cache the index to the associated CullBin, if there happens to
// be a CullBinAttrib in the state.
int _bin_index;
int _draw_order;
enum Flags {
F_checked_billboard = 0x0001,
F_checked_bin_index = 0x0002,
F_checked_decal = 0x0004,
F_has_decal = 0x0008,
F_checked_bin_index = 0x0001,
};
short _flags;