From 872a902de4bccbe1686f40e4d969132a80bc84ca Mon Sep 17 00:00:00 2001 From: David Rose Date: Thu, 18 Jan 2001 02:17:07 +0000 Subject: [PATCH] *** empty log message *** --- panda/src/cull/config_cull.cxx | 4 + panda/src/cull/cullTraverser.I | 32 ++- panda/src/cull/cullTraverser.cxx | 150 +++++++++++-- panda/src/cull/cullTraverser.h | 16 +- panda/src/cull/geomBin.I | 87 +++++--- panda/src/cull/geomBin.cxx | 225 ++++++++++++++++---- panda/src/cull/geomBin.h | 35 ++- panda/src/cull/geomBinAttribute.I | 12 +- panda/src/cull/geomBinAttribute.cxx | 12 +- panda/src/cull/geomBinAttribute.h | 8 +- panda/src/cull/geomBinBackToFront.I | 4 +- panda/src/cull/geomBinBackToFront.h | 7 +- panda/src/cull/geomBinFixed.I | 4 +- panda/src/cull/geomBinFixed.h | 7 +- panda/src/cull/geomBinGroup.I | 32 +-- panda/src/cull/geomBinGroup.cxx | 148 +++++++++++++ panda/src/cull/geomBinGroup.h | 15 +- panda/src/cull/geomBinNormal.cxx | 15 +- panda/src/cull/geomBinNormal.h | 6 +- panda/src/cull/geomBinTransition.I | 12 +- panda/src/cull/geomBinTransition.cxx | 68 +++++- panda/src/cull/geomBinTransition.h | 22 +- panda/src/cull/geomBinUnsorted.I | 4 +- panda/src/cull/geomBinUnsorted.h | 6 +- panda/src/doc/eggSyntax.txt | 60 ++++-- panda/src/egg/eggAlphaMode.I | 72 ++++++- panda/src/egg/eggAlphaMode.cxx | 12 ++ panda/src/egg/eggAlphaMode.h | 12 +- panda/src/egg/eggGroup.cxx | 51 +++++ panda/src/egg/eggGroup.h | 4 + panda/src/egg/eggNode.cxx | 53 +++++ panda/src/egg/eggNode.h | 5 + panda/src/egg/eggPrimitive.cxx | 60 ++++++ panda/src/egg/eggPrimitive.h | 4 + panda/src/egg/parser.yxx | 21 +- panda/src/egg2sg/Sources.pp | 2 +- panda/src/egg2sg/eggLoader.cxx | 46 +++- panda/src/express/typeHandle.cxx | 16 ++ panda/src/sgattrib/config_sgattrib.cxx | 17 +- panda/src/sgattrib/depthWriteTransition.cxx | 57 +++++ panda/src/sgattrib/depthWriteTransition.h | 9 + 41 files changed, 1194 insertions(+), 238 deletions(-) diff --git a/panda/src/cull/config_cull.cxx b/panda/src/cull/config_cull.cxx index 15cc4ccc2b..7e1aaf95ac 100644 --- a/panda/src/cull/config_cull.cxx +++ b/panda/src/cull/config_cull.cxx @@ -31,6 +31,10 @@ ConfigureFn(config_cull) { GeomBinAttribute::init_type(); GeomBinFixed::init_type(); DirectRenderTransition::init_type(); + + //Registration of writeable object's creation + //functions with BamReader's factory + GeomBinTransition::register_with_read_factory(); } // Set this true to force all of the caching to blow itself away every diff --git a/panda/src/cull/cullTraverser.I b/panda/src/cull/cullTraverser.I index f64f376b71..a89e61a31b 100644 --- a/panda/src/cull/cullTraverser.I +++ b/panda/src/cull/cullTraverser.I @@ -20,7 +20,8 @@ INLINE void CullTraverser:: set_default_bin(GeomBin *bin) { nassertv(bin != (GeomBin *)NULL); - bin->attach_to(this, bin->get_sort()); + nassertv(bin->is_attached()); + nassertv(bin->get_traverser() == this); _default_bin = bin; } @@ -36,6 +37,35 @@ get_default_bin() const { return _default_bin; } +//////////////////////////////////////////////////////////////////// +// Function: CullTraverser::has_bin +// Access: Public +// Description: Returns true if a bin by the given name has been +// attached to the CullTraverser, false otherwise. +//////////////////////////////////////////////////////////////////// +INLINE bool CullTraverser:: +has_bin(const string &name) const { + return (_toplevel_bins.count(name) != 0); +} + +//////////////////////////////////////////////////////////////////// +// Function: CullTraverser::get_bin +// Access: Public +// Description: Returns the GeomBin that was previously attached to +// the CullTraverser that shares the indicated name, or +// the default bin if no GeomBin with a matching name +// was added. +//////////////////////////////////////////////////////////////////// +INLINE GeomBin *CullTraverser:: +get_bin(const string &name) const { + ToplevelBins::const_iterator tbi; + tbi = _toplevel_bins.find(name); + if (tbi == _toplevel_bins.end()) { + return get_default_bin(); + } + return (*tbi).second; +} + //////////////////////////////////////////////////////////////////// // Function: CullTraverser::draw_geom // Access: Public diff --git a/panda/src/cull/cullTraverser.cxx b/panda/src/cull/cullTraverser.cxx index 98750dcf63..c59f4b615e 100644 --- a/panda/src/cull/cullTraverser.cxx +++ b/panda/src/cull/cullTraverser.cxx @@ -8,6 +8,7 @@ #include "geomBinAttribute.h" #include "cullStateSubtree.h" #include "geomBinNormal.h" +#include "geomBinFixed.h" #include "directRenderTransition.h" #include "config_cull.h" @@ -42,7 +43,15 @@ CullTraverser(GraphicsStateGuardian *gsg, TypeHandle graph_type, const ArcChain &arc_chain) : RenderTraverser(gsg, graph_type, arc_chain) { - _default_bin = new GeomBinNormal("default", this); + GeomBinNormal *default_bin = new GeomBinNormal("default"); + GeomBinFixed *fixed = new GeomBinFixed("fixed"); + fixed->set_sort(30); + + default_bin->set_traverser(this); + fixed->set_traverser(this); + + _default_bin = default_bin; + _nested_count = 0; } @@ -56,12 +65,14 @@ CullTraverser:: // We should detach each of our associated bins when we destruct. // We can't just run a for loop, because this is a self-modifying // operation. - while (!_bins.empty()) { - GeomBin *bin = (*_bins.begin()); + while (!_toplevel_bins.empty()) { + GeomBin *bin = (*_toplevel_bins.begin()).second; nassertv(bin != (GeomBin *)NULL); nassertv(bin->get_traverser() == this); - bin->detach(); + bin->clear_traverser(); } + + nassertv(_sub_bins.empty()); } //////////////////////////////////////////////////////////////////// @@ -86,7 +97,8 @@ traverse(Node *root, << *root << "\n"; } - nassertv(!_bins.empty()); + nassertv(!_toplevel_bins.empty()); + nassertv(!_sub_bins.empty()); bool is_initial = (_nested_count == 0); if (is_initial) { @@ -184,9 +196,9 @@ write(ostream &out, int indent_level) const { } */ - Bins::const_iterator bi; - for (bi = _bins.begin(); bi != _bins.end(); ++bi) { - (*bi)->write(out, indent_level); + ToplevelBins::const_iterator tbi; + for (tbi = _toplevel_bins.begin(); tbi != _toplevel_bins.end(); ++tbi) { + (*tbi).second->write(out, indent_level); } _lookup.write(out, indent_level); } @@ -215,9 +227,9 @@ draw() { << " nonempty states of " << _states.size() << " total.\n"; } - Bins::iterator bi; - for (bi = _bins.begin(); bi != _bins.end(); ++bi) { - (*bi)->clear_current_states(); + SubBins::const_iterator sbi; + for (sbi = _sub_bins.begin(); sbi != _sub_bins.end(); ++sbi) { + (*sbi).second->clear_current_states(); } States::iterator si; @@ -233,7 +245,7 @@ draw() { const GeomBinAttribute *bin_attrib; if (get_attribute_into(bin_attrib, cs->get_attributes(), GeomBinTransition::get_class_type())) { - requested_bin = bin_attrib->get_bin(); + requested_bin = get_bin(bin_attrib->get_bin()); draw_order = bin_attrib->get_draw_order(); } @@ -244,10 +256,10 @@ draw() { if (_gsg != (GraphicsStateGuardian *)NULL) { if (cull_cat.is_debug()) { cull_cat.debug() - << "Drawing " << _bins.size() << " bins.\n"; + << "Drawing " << _sub_bins.size() << " bins.\n"; } - for (bi = _bins.begin(); bi != _bins.end(); ++bi) { - (*bi)->draw(this); + for (sbi = _sub_bins.begin(); sbi != _sub_bins.end(); ++sbi) { + (*sbi).second->draw(this); } } } @@ -394,7 +406,6 @@ forward_arc(NodeRelation *arc, NullTransitionWrapper &, bool is_geom = node->is_of_type(GeomNode::get_class_type()); bool node_has_sub_render = node->has_sub_render(); int arc_num_sub_render = arc->get_num_sub_render_trans(); - bool has_direct_render = arc->has_transition(DirectRenderTransition::get_class_type()); bool has_decal = arc->has_transition(DecalTransition::get_class_type()); if (has_decal) { @@ -403,6 +414,9 @@ forward_arc(NodeRelation *arc, NullTransitionWrapper &, arc_num_sub_render--; } + bool has_direct_render = + arc->has_transition(DirectRenderTransition::get_class_type()); + #ifndef NDEBUG if (support_decals != SD_on) { has_direct_render = has_direct_render && !has_decal; @@ -533,3 +547,107 @@ forward_arc(NodeRelation *arc, NullTransitionWrapper &, return true; } + +//////////////////////////////////////////////////////////////////// +// Function: CullTraverser::attach_toplevel_bin +// Access: Private +// Description: This is intended to be called only by +// GeomBin::attach(). It stores the bin in the +// appropriate structures within the traverser, as a +// toplevel bin, e.g. a bin that may be referenced by +// name from outside the traverser, or one that geometry +// may be explicitly assigned to by name. +//////////////////////////////////////////////////////////////////// +void CullTraverser:: +attach_toplevel_bin(GeomBin *bin) { + if (cull_cat.is_debug()) { + cull_cat.debug() + << "Attaching toplevel bin " << *bin << "\n"; + } + + // Insert the new bin by name. + bool inserted = + _toplevel_bins.insert(ToplevelBins::value_type(bin->get_name(), bin)).second; + + // If this assertion fails, there was already a bin by the same name + // in this traverser, an error condition. + nassertv(inserted); +} + +//////////////////////////////////////////////////////////////////// +// Function: CullTraverser::attach_sub_bin +// Access: Private +// Description: This is intended to be called only by +// GeomBin::attach(). It stores the bin in the +// appropriate structures within the traverser, as a +// sub bin, e.g. a bin that may have geometry assigned +// to it, and may therefore be rendered. +// +// In most cases, a toplevel bin is the same as a sub +// bin, except in the case of a GeomBinGroup, which is a +// toplevel bin that contains a number of sub bins. +//////////////////////////////////////////////////////////////////// +void CullTraverser:: +attach_sub_bin(GeomBin *bin) { + if (cull_cat.is_debug()) { + cull_cat.debug() + << "Attaching sub bin " << *bin << "\n"; + } + + _sub_bins.insert(SubBins::value_type(bin->get_sort(), bin)); +} + +//////////////////////////////////////////////////////////////////// +// Function: CullTraverser::detach_toplevel_bin +// Access: Private +// Description: This is intended to be called only by +// GeomBin::detach(). It removes the bin from the +// appropriate structures within the traverser, as a +// toplevel bin. See attach_toplevel_bin(). +//////////////////////////////////////////////////////////////////// +void CullTraverser:: +detach_toplevel_bin(GeomBin *bin) { + if (cull_cat.is_debug()) { + cull_cat.debug() + << "Detaching toplevel bin " << *bin << "\n"; + } + + ToplevelBins::iterator tbi = _toplevel_bins.find(bin->get_name()); + nassertv(tbi != _toplevel_bins.end()); + _toplevel_bins.erase(tbi); +} + +//////////////////////////////////////////////////////////////////// +// Function: CullTraverser::detach_sub_bin +// Access: Private +// Description: This is intended to be called only by +// GeomBin::detach(). It removes the bin from the +// appropriate structures within the traverser, as a +// sub bin. See attach_sub_bin(). +//////////////////////////////////////////////////////////////////// +void CullTraverser:: +detach_sub_bin(GeomBin *bin) { + if (cull_cat.is_debug()) { + cull_cat.debug() + << "Detaching sub bin " << *bin << "\n"; + } + + // Remove the bin from its place in the sort order list. This will + // be one of the (possibly several) entries in the multimap with the + // same sort value. + pair range; + range = _sub_bins.equal_range(bin->get_sort()); + + SubBins::iterator sbi; + for (sbi = range.first; sbi != range.second; ++sbi) { + GeomBin *consider_bin = (*sbi).second; + nassertv(consider_bin->get_sort() == bin->get_sort()); + + if (consider_bin == bin) { + // Here's the position! + _sub_bins.erase(sbi); + return; + } + } + nassertv(false); +} diff --git a/panda/src/cull/cullTraverser.h b/panda/src/cull/cullTraverser.h index 15b04277a6..f2af51a3c1 100644 --- a/panda/src/cull/cullTraverser.h +++ b/panda/src/cull/cullTraverser.h @@ -43,6 +43,8 @@ public: INLINE void set_default_bin(GeomBin *bin); INLINE GeomBin *get_default_bin() const; + INLINE bool has_bin(const string &name) const; + INLINE GeomBin *get_bin(const string &name) const; virtual void traverse(Node *root, const AllAttributesWrapper &initial_state, @@ -92,10 +94,17 @@ public: const CullLevelState &level_state); private: + void attach_toplevel_bin(GeomBin *bin); + void attach_sub_bin(GeomBin *bin); + void detach_toplevel_bin(GeomBin *bin); + void detach_sub_bin(GeomBin *bin); + AllAttributesWrapper _initial_state; - typedef set Bins; - Bins _bins; + typedef map ToplevelBins; + typedef multimap SubBins; + ToplevelBins _toplevel_bins; + SubBins _sub_bins; PT(GeomBin) _default_bin; typedef set > States; @@ -128,7 +137,8 @@ public: private: static TypeHandle _type_handle; -friend class GeomBin; + friend class GeomBin; + friend class GeomBinGroup; }; #include "cullTraverser.I" diff --git a/panda/src/cull/geomBin.I b/panda/src/cull/geomBin.I index 364ae97c55..0ec92790b1 100644 --- a/panda/src/cull/geomBin.I +++ b/panda/src/cull/geomBin.I @@ -9,24 +9,13 @@ // Description: //////////////////////////////////////////////////////////////////// INLINE GeomBin:: -GeomBin(const string &name, CullTraverser *traverser, int sort) : +GeomBin(const string &name) : Namable(name) { _traverser = (CullTraverser *)NULL; - if (traverser != (CullTraverser *)NULL) { - attach_to(traverser, sort); - } -} - -//////////////////////////////////////////////////////////////////// -// Function: GeomBin::get_traverser -// Access: Public -// Description: Returns a pointer to the CullTraverser this bin is -// currently attached to, or NULL if it is not attached. -//////////////////////////////////////////////////////////////////// -INLINE CullTraverser *GeomBin:: -get_traverser() const { - return _traverser; + _is_attached = false; + _sort = 0; + _parent = (GeomBin *)NULL; } //////////////////////////////////////////////////////////////////// @@ -42,19 +31,65 @@ get_sort() const { } //////////////////////////////////////////////////////////////////// -// Function: GeomBin::set_sort +// Function: GeomBin::has_traverser // Access: Public -// Description: Changes the sort index associated with this -// particular bin. The CullTraverser will render bins -// in order according to their sort index. +// Description: Returns true if the GeomBin is currently attached to +// a traverser, false otherwise. If this is false, and +// the bin is not attached to a parent bin +// (i.e. has_parent() is also false), don't expect the +// bin to be rendered. //////////////////////////////////////////////////////////////////// -INLINE void GeomBin:: -set_sort(int sort) { - if (_traverser != (CullTraverser *)NULL) { - attach_to(_traverser, sort); - } else { - _sort = sort; - } +INLINE bool GeomBin:: +has_traverser() const { + return (_traverser != (CullTraverser *)NULL); +} + +//////////////////////////////////////////////////////////////////// +// Function: GeomBin::get_traverser +// Access: Public +// Description: Returns a pointer to the CullTraverser this bin is +// currently attached to, or NULL if it is not attached. +//////////////////////////////////////////////////////////////////// +INLINE CullTraverser *GeomBin:: +get_traverser() const { + return _traverser; +} + +//////////////////////////////////////////////////////////////////// +// Function: GeomBin::has_parent +// Access: Public +// Description: Returns true if the bin is a child of some +// GeomBinGroup, false if it is a toplevel bin in its +// own right. See GeomBinGroup. +//////////////////////////////////////////////////////////////////// +INLINE bool GeomBin:: +has_parent() const { + return _parent != (GeomBin *)NULL; +} + +//////////////////////////////////////////////////////////////////// +// Function: GeomBin::get_parent +// Access: Public +// Description: Returns the parent pointer of the GeomBin if the bin +// is a child of some GeomBinGropu, or NULL if the bin +// does not have a parent. See GeomBinGroup. +//////////////////////////////////////////////////////////////////// +INLINE GeomBin *GeomBin:: +get_parent() const { + return _parent; +} + +//////////////////////////////////////////////////////////////////// +// Function: GeomBin::is_attached +// Access: Public +// Description: Returns true if the bin is currently attached to a +// CullTraverser, false otherwise. This should always +// be tree if has_traverser() is true, and false if +// has_traverser() is false. +//////////////////////////////////////////////////////////////////// +INLINE bool GeomBin:: +is_attached() const { + return _is_attached; } //////////////////////////////////////////////////////////////////// diff --git a/panda/src/cull/geomBin.cxx b/panda/src/cull/geomBin.cxx index 44407e00f1..66c4387cef 100644 --- a/panda/src/cull/geomBin.cxx +++ b/panda/src/cull/geomBin.cxx @@ -22,49 +22,210 @@ GeomBin:: ~GeomBin() { // We shouldn't be attached to anything when we destruct. If we // are, something went screwy in the reference counting. + nassertv(!_is_attached); nassertv(_traverser == (CullTraverser *)NULL); + + // We also shouldn't be part of any parent bin. + nassertv(_parent == (GeomBin *)NULL); } //////////////////////////////////////////////////////////////////// -// Function: GeomBin::attach_to +// Function: GeomBin::set_name // Access: Public -// Description: Detaches the bin from whichever CullTraverser it is -// currently attached to, and attaches it to the -// indicated CullTraverser instead, at the indicated -// sort level. The CullTraverser will render all of its -// attached GeomBins, in order according to sort level. +// Description: Changes the name of the GeomBin, correctly updating +// the CullTraverser it's attached to. //////////////////////////////////////////////////////////////////// void GeomBin:: -attach_to(CullTraverser *traverser, int sort) { - nassertv(traverser != (CullTraverser *)NULL); - PT(GeomBin) keep = detach(); - _sort = sort; +set_name(const string &name) { + if (name == get_name()) { + return; + } + + // If we're currently attached, we need to need to be unattached + // while we change the name--but only if we're a toplevel bin. A + // nested bin doesn't matter. + if (is_attached() && !has_parent()) { + PT(GeomBin) keep = this; + + nassertv(_traverser != (CullTraverser *)NULL); + _traverser->detach_toplevel_bin(this); + Namable::set_name(name); + _traverser->attach_toplevel_bin(this); + + } else { + Namable::set_name(name); + } +} + +//////////////////////////////////////////////////////////////////// +// Function: GeomBin::clear_name +// Access: Public +// Description: Removes the name of the GeomBin. This also detaches +// it (if it is a toplevel bin), and may therefore +// inadvertently delete it! Be very careful. +//////////////////////////////////////////////////////////////////// +void GeomBin:: +clear_name() { + PT(GeomBin) keep; + + if (is_attached() && !has_parent()) { + cull_cat.warning() + << "GeomBin::clear_name() called on an attached GeomBin.\n"; + keep = detach(); + } + + Namable::clear_name(); +} + +//////////////////////////////////////////////////////////////////// +// Function: GeomBin::set_sort +// Access: Public +// Description: Changes the sort index associated with this +// particular bin. The CullTraverser will render bins +// in order according to their sort index. +//////////////////////////////////////////////////////////////////// +void GeomBin:: +set_sort(int sort) { + if (sort == _sort) { + return; + } + + // If we're currently attached, even if we're a nested bin, we need + // to be unattached while we adjust the sorting order. + if (is_attached()) { + PT(GeomBin) keep = this; + + nassertv(_traverser != (CullTraverser *)NULL); + _traverser->detach_sub_bin(this); + _sort = sort; + _traverser->attach_sub_bin(this); + + } else { + _sort = sort; + } +} + +//////////////////////////////////////////////////////////////////// +// Function: GeomBin::set_traverser +// Access: Public +// Description: Associates the GeomBin with the indicated +// CullTraverser. A particular bin may only be +// associated with one traverser at a time. This is +// normally done only after initially creating the +// GeomBin; it is an error to call set_traverser() more +// than once on the same bin (without calling +// clear_traverser() first). +// +// It is also not necessary (and is an error) to assign +// child bins of a GeomBinGroup to a traverser; just +// assign the parent bin. +// +// This must be called before the GeomBin can be +// rendered; it will thereafter be rendered by the +// indicated traverser. +//////////////////////////////////////////////////////////////////// +void GeomBin:: +set_traverser(CullTraverser *traverser) { + if (traverser == (CullTraverser *)NULL) { + clear_traverser(); + } + + nassertv(!is_attached()); + nassertv(_traverser == (CullTraverser *)NULL); + _traverser = traverser; - _traverser->_bins.insert(this); + attach(); +} + +//////////////////////////////////////////////////////////////////// +// Function: GeomBin::clear_traverser +// Access: Public +// Description: Disassociates the GeomBin with its current traverser. +// The bin will no longer be rendered, and may even be +// deleted if you do not immediately save the returned +// pointer. +//////////////////////////////////////////////////////////////////// +PT(GeomBin) GeomBin:: +clear_traverser() { + PT(GeomBin) keep = this; + + if (is_attached()) { + detach(); + _traverser = (CullTraverser *)NULL; + } + + return keep; +} + +//////////////////////////////////////////////////////////////////// +// Function: GeomBin::attach +// Access: Protected, Virtual +// Description: Formally adds the GeomBin to its indicated Traverser. +//////////////////////////////////////////////////////////////////// +void GeomBin:: +attach() { + nassertv(has_name()); + nassertv(_traverser != (CullTraverser *)NULL); + nassertv(!_is_attached); + + // In the ordinary case, a bin is both a toplevel bin (visible by + // name from the CullTraverser) and a sub bin (directly renderable). + if (!has_parent()) { + _traverser->attach_toplevel_bin(this); + } + _traverser->attach_sub_bin(this); + + _is_attached = true; } //////////////////////////////////////////////////////////////////// // Function: GeomBin::detach -// Access: Public +// Access: Protected, Virtual // Description: Detaches the bin from whichever CullTraverser it is -// currently attached to, if any. The bin will no -// longer be rendered. The return value is a -// PT(GeomBin) that refers to the GeomBin itself; the -// caller should save this pointer in a local PT -// variable to avoid possibly destructing the GeomBin -// (since detaching it may remove the last outstanding -// reference count). +// currently attached to. The bin will no longer be +// rendered. The return value is a PT(GeomBin) that +// refers to the GeomBin itself; the caller should save +// this pointer in a local PT variable to avoid possibly +// destructing the GeomBin (since detaching it may +// remove the last outstanding reference count). //////////////////////////////////////////////////////////////////// PT(GeomBin) GeomBin:: detach() { + nassertr(_is_attached, NULL); + nassertr(_traverser != (CullTraverser *)NULL, NULL); + PT(GeomBin) keep = this; - if (_traverser != (CullTraverser *)NULL) { - _traverser->_bins.erase(this); + + if (!has_parent()) { + _traverser->detach_toplevel_bin(this); } - _traverser = (CullTraverser *)NULL; + _traverser->detach_sub_bin(this); + + _is_attached = false; + return keep; } +//////////////////////////////////////////////////////////////////// +// Function: GeomBin::output +// Access: Public, Virtual +// Description: +//////////////////////////////////////////////////////////////////// +void GeomBin:: +output(ostream &out) const { + out << get_type() << " " << get_name(); +} + +//////////////////////////////////////////////////////////////////// +// Function: GeomBin::output +// Access: Public, Virtual +// Description: +//////////////////////////////////////////////////////////////////// +void GeomBin:: +write(ostream &out, int indent_level) const { + indent(out, indent_level) << *this << "\n"; +} + //////////////////////////////////////////////////////////////////// // Function: GeomBin::remove_state // Access: Public, Virtual @@ -86,23 +247,3 @@ remove_state(CullState *) { << "remove_state() unexpectedly called for " << get_type() << "\n"; nassertv(false); } - -//////////////////////////////////////////////////////////////////// -// Function: GeomBin::output -// Access: Public, Virtual -// Description: -//////////////////////////////////////////////////////////////////// -void GeomBin:: -output(ostream &out) const { - out << get_type() << " " << get_name(); -} - -//////////////////////////////////////////////////////////////////// -// Function: GeomBin::output -// Access: Public, Virtual -// Description: -//////////////////////////////////////////////////////////////////// -void GeomBin:: -write(ostream &out, int indent_level) const { - indent(out, indent_level) << *this << "\n"; -} diff --git a/panda/src/cull/geomBin.h b/panda/src/cull/geomBin.h index 497cc1d0c2..04dc94b77f 100644 --- a/panda/src/cull/geomBin.h +++ b/panda/src/cull/geomBin.h @@ -35,16 +35,29 @@ class CullTraverser; //////////////////////////////////////////////////////////////////// class EXPCL_PANDA GeomBin : public TypedReferenceCount, public Namable { public: - INLINE GeomBin(const string &name, CullTraverser *traverser = NULL, - int sort = 0); + INLINE GeomBin(const string &name); virtual ~GeomBin(); - void attach_to(CullTraverser *traverser, int sort = 0); - PT(GeomBin) detach(); +PUBLISHED: + void set_name(const string &name); + void clear_name(); - INLINE CullTraverser *get_traverser() const; INLINE int get_sort() const; - INLINE void set_sort(int sort); + void set_sort(int sort); + + void set_traverser(CullTraverser *traverser); + INLINE bool has_traverser() const; + INLINE CullTraverser *get_traverser() const; + PT(GeomBin) clear_traverser(); + + INLINE bool has_parent() const; + INLINE GeomBin *get_parent() const; + + virtual void output(ostream &out) const; + virtual void write(ostream &out, int indent_level = 0) const; + +public: + INLINE bool is_attached() const; virtual void clear_current_states()=0; virtual void record_current_state(GraphicsStateGuardian *gsg, @@ -54,15 +67,17 @@ public: virtual void draw(CullTraverser *trav)=0; - virtual void output(ostream &out) const; - virtual void write(ostream &out, int indent_level = 0) const; - protected: INLINE void claim_cull_state(CullState *cs); INLINE void disclaim_cull_state(CullState *cs); + virtual void attach(); + virtual PT(GeomBin) detach(); + CullTraverser *_traverser; + bool _is_attached; int _sort; + GeomBin *_parent; public: static TypeHandle get_class_type() { @@ -82,6 +97,8 @@ public: private: static TypeHandle _type_handle; + + friend class GeomBinGroup; }; INLINE ostream &operator << (ostream &out, const GeomBin &bin) { diff --git a/panda/src/cull/geomBinAttribute.I b/panda/src/cull/geomBinAttribute.I index bb0f63130f..c06524f94b 100644 --- a/panda/src/cull/geomBinAttribute.I +++ b/panda/src/cull/geomBinAttribute.I @@ -18,7 +18,7 @@ GeomBinAttribute() { // Description: //////////////////////////////////////////////////////////////////// INLINE GeomBinAttribute:: -GeomBinAttribute(GeomBin *bin, int draw_order) { +GeomBinAttribute(const string &bin, int draw_order) { set_on(bin, draw_order); } @@ -29,8 +29,8 @@ GeomBinAttribute(GeomBin *bin, int draw_order) { // geomBin. //////////////////////////////////////////////////////////////////// INLINE void GeomBinAttribute:: -set_on(GeomBin *bin, int draw_order) { - nassertv(bin != (GeomBin *)NULL); +set_on(const string &bin, int draw_order) { + nassertv(!bin.empty()); _value = bin; _draw_order = draw_order; OnOffAttribute::set_on(); @@ -39,13 +39,13 @@ set_on(GeomBin *bin, int draw_order) { //////////////////////////////////////////////////////////////////// // Function: GeomBinAttribute::get_bin // Access: Public -// Description: Returns the bin that the GeomBinAttribute +// Description: Returns the bin name that the GeomBinAttribute // represents. It is only valid to call this if is_on() // has returned true. //////////////////////////////////////////////////////////////////// -INLINE PT(GeomBin) GeomBinAttribute:: +INLINE string GeomBinAttribute:: get_bin() const { - nassertr(is_on(), NULL); + nassertr(is_on(), string()); return _value; } diff --git a/panda/src/cull/geomBinAttribute.cxx b/panda/src/cull/geomBinAttribute.cxx index 1da7944bde..d72c93d106 100644 --- a/panda/src/cull/geomBinAttribute.cxx +++ b/panda/src/cull/geomBinAttribute.cxx @@ -9,6 +9,8 @@ #include #include +#include + TypeHandle GeomBinAttribute::_type_handle; //////////////////////////////////////////////////////////////////// @@ -56,7 +58,7 @@ set_value_from(const OnOffTransition *other) { DCAST_INTO_V(ot, other); _value = ot->_value; _draw_order = ot->_draw_order; - nassertv(_value != (GeomBin *)NULL); + nassertv(!_value.empty()); } //////////////////////////////////////////////////////////////////// @@ -69,7 +71,7 @@ compare_values(const OnOffAttribute *other) const { const GeomBinAttribute *ot; DCAST_INTO_R(ot, other, false); if (_value != ot->_value) { - return (int)(_value - ot->_value); + return strcmp(_value.c_str(), ot->_value.c_str()); } return _draw_order - ot->_draw_order; } @@ -81,8 +83,7 @@ compare_values(const OnOffAttribute *other) const { //////////////////////////////////////////////////////////////////// void GeomBinAttribute:: output_value(ostream &out) const { - nassertv(_value != (GeomBin *)NULL); - out << *_value << ":" << _draw_order; + out << _value << ":" << _draw_order; } //////////////////////////////////////////////////////////////////// @@ -93,6 +94,5 @@ output_value(ostream &out) const { //////////////////////////////////////////////////////////////////// void GeomBinAttribute:: write_value(ostream &out, int indent_level) const { - nassertv(_value != (GeomBin *)NULL); - indent(out, indent_level) << *_value << ":" << _draw_order << "\n"; + indent(out, indent_level) << _value << ":" << _draw_order << "\n"; } diff --git a/panda/src/cull/geomBinAttribute.h b/panda/src/cull/geomBinAttribute.h index 53314dd21c..718fdf7b5f 100644 --- a/panda/src/cull/geomBinAttribute.h +++ b/panda/src/cull/geomBinAttribute.h @@ -19,10 +19,10 @@ class EXPCL_PANDA GeomBinAttribute : public OnOffAttribute { public: INLINE GeomBinAttribute(); - INLINE GeomBinAttribute(GeomBin *bin, int draw_order = 0); + INLINE GeomBinAttribute(const string &bin, int draw_order = 0); - INLINE void set_on(GeomBin *bin, int draw_order = 0); - INLINE PT(GeomBin) get_bin() const; + INLINE void set_on(const string &bin, int draw_order = 0); + INLINE string get_bin() const; INLINE int get_draw_order() const; virtual TypeHandle get_handle() const; @@ -35,7 +35,7 @@ protected: virtual void output_value(ostream &out) const; virtual void write_value(ostream &out, int indent_level) const; - PT(GeomBin) _value; + string _value; int _draw_order; public: diff --git a/panda/src/cull/geomBinBackToFront.I b/panda/src/cull/geomBinBackToFront.I index caf280a710..949164ad53 100644 --- a/panda/src/cull/geomBinBackToFront.I +++ b/panda/src/cull/geomBinBackToFront.I @@ -77,7 +77,7 @@ draw(CullTraverser *trav) const { // Description: //////////////////////////////////////////////////////////////////// INLINE GeomBinBackToFront:: -GeomBinBackToFront(const string &name, CullTraverser *traverser, int sort) : - GeomBin(name, traverser, sort) +GeomBinBackToFront(const string &name) : + GeomBin(name) { } diff --git a/panda/src/cull/geomBinBackToFront.h b/panda/src/cull/geomBinBackToFront.h index 3957a50c09..24846c8ca0 100644 --- a/panda/src/cull/geomBinBackToFront.h +++ b/panda/src/cull/geomBinBackToFront.h @@ -24,11 +24,10 @@ // without a Z-buffer. //////////////////////////////////////////////////////////////////// class EXPCL_PANDA GeomBinBackToFront : public GeomBin { -public: - INLINE GeomBinBackToFront(const string &name, - CullTraverser *traverser = NULL, - int sort = 0); +PUBLISHED: + INLINE GeomBinBackToFront(const string &name); +public: virtual void clear_current_states(); virtual void record_current_state(GraphicsStateGuardian *gsg, CullState *cs, int draw_order, diff --git a/panda/src/cull/geomBinFixed.I b/panda/src/cull/geomBinFixed.I index 760a715b9c..6341414cc1 100644 --- a/panda/src/cull/geomBinFixed.I +++ b/panda/src/cull/geomBinFixed.I @@ -78,7 +78,7 @@ draw(CullTraverser *trav) const { // Description: //////////////////////////////////////////////////////////////////// INLINE GeomBinFixed:: -GeomBinFixed(const string &name, CullTraverser *traverser, int sort) : - GeomBin(name, traverser, sort) +GeomBinFixed(const string &name) : + GeomBin(name) { } diff --git a/panda/src/cull/geomBinFixed.h b/panda/src/cull/geomBinFixed.h index 90299100ed..959dfb8b81 100644 --- a/panda/src/cull/geomBinFixed.h +++ b/panda/src/cull/geomBinFixed.h @@ -21,11 +21,10 @@ // specified at each GeomBinTransition. //////////////////////////////////////////////////////////////////// class EXPCL_PANDA GeomBinFixed : public GeomBin { -public: - INLINE GeomBinFixed(const string &name, - CullTraverser *traverser = NULL, - int sort = 0); +PUBLISHED: + INLINE GeomBinFixed(const string &name); +public: virtual void clear_current_states(); virtual void record_current_state(GraphicsStateGuardian *gsg, CullState *cs, int draw_order, diff --git a/panda/src/cull/geomBinGroup.I b/panda/src/cull/geomBinGroup.I index 8e70b00e0f..c531be66de 100644 --- a/panda/src/cull/geomBinGroup.I +++ b/panda/src/cull/geomBinGroup.I @@ -9,23 +9,11 @@ // Description: //////////////////////////////////////////////////////////////////// INLINE GeomBinGroup:: -GeomBinGroup(const string &name, CullTraverser *traverser, int sort) : - GeomBin(name, traverser, sort) +GeomBinGroup(const string &name) : + GeomBin(name) { } -//////////////////////////////////////////////////////////////////// -// Function: GeomBinGroup::add_sub_bin -// Access: Public -// Description: Appends the indicated bin to the end of the sub_bin -// list, and returns the new index. -//////////////////////////////////////////////////////////////////// -INLINE int GeomBinGroup:: -add_sub_bin(GeomBin *sub_bin) { - _sub_bins.push_back(sub_bin); - return _sub_bins.size() - 1; -} - //////////////////////////////////////////////////////////////////// // Function: GeomBinGroup::get_num_bins // Access: Public @@ -46,19 +34,3 @@ get_bin(int n) { nassertr(n >= 0 && n < (int)_sub_bins.size(), NULL); return _sub_bins[n]; } - -//////////////////////////////////////////////////////////////////// -// Function: GeomBinGroup::remove_bin -// Access: Public -// Description: Removes the nth bin. All subsequent index numbers -// shift down by one. The return value is the -// just-removed bin, which may be deleted if it is not -// immediately saved. -//////////////////////////////////////////////////////////////////// -INLINE PT(GeomBin) GeomBinGroup:: -remove_bin(int n) { - nassertr(n >= 0 && n < (int)_sub_bins.size(), NULL); - PT(GeomBin) keep = get_bin(n); - _sub_bins.erase(_sub_bins.begin() + n); - return keep; -} diff --git a/panda/src/cull/geomBinGroup.cxx b/panda/src/cull/geomBinGroup.cxx index 1e36588239..37f50bdd88 100644 --- a/panda/src/cull/geomBinGroup.cxx +++ b/panda/src/cull/geomBinGroup.cxx @@ -12,6 +12,75 @@ TypeHandle GeomBinGroup::_type_handle; +//////////////////////////////////////////////////////////////////// +// Function: GeomBinGroup::Destructor +// Access: Public, Virtual +// Description: +//////////////////////////////////////////////////////////////////// +GeomBinGroup:: +~GeomBinGroup() { + nassertv(!is_attached()); + + // Disassociate all of our children before we destruct. + SubBins::iterator sbi; + for (sbi = _sub_bins.begin(); sbi != _sub_bins.end(); ++sbi) { + GeomBin *sub_bin = (*sbi); + sub_bin->_parent = (GeomBin *)NULL; + } + _sub_bins.clear(); +} + + +//////////////////////////////////////////////////////////////////// +// Function: GeomBinGroup::add_sub_bin +// Access: Public +// Description: Appends the indicated bin to the end of the sub_bin +// list, and returns the new index. +//////////////////////////////////////////////////////////////////// +int GeomBinGroup:: +add_sub_bin(GeomBin *sub_bin) { + nassertr(!sub_bin->has_parent(), -1); + nassertr(!sub_bin->is_attached(), -1); + nassertr(sub_bin->has_name(), -1); + + sub_bin->_parent = this; + _sub_bins.push_back(sub_bin); + + if (is_attached()) { + sub_bin->_traverser = _traverser; + _traverser->attach_sub_bin(sub_bin); + } + + return _sub_bins.size() - 1; +} + +//////////////////////////////////////////////////////////////////// +// Function: GeomBinGroup::remove_bin +// Access: Public +// Description: Removes the nth bin. All subsequent index numbers +// shift down by one. The return value is the +// just-removed bin, which may be deleted if it is not +// immediately saved. +//////////////////////////////////////////////////////////////////// +PT(GeomBin) GeomBinGroup:: +remove_bin(int n) { + nassertr(n >= 0 && n < (int)_sub_bins.size(), NULL); + PT(GeomBin) sub_bin = get_bin(n); + nassertr(sub_bin->get_parent() == this, NULL); + + if (is_attached()) { + nassertr(sub_bin->is_attached(), NULL); + nassertr(sub_bin->_traverser == _traverser, NULL); + _traverser->detach_sub_bin(sub_bin); + sub_bin->_traverser = (CullTraverser *)NULL; + } + + _sub_bins.erase(_sub_bins.begin() + n); + sub_bin->_parent = (GeomBin *)NULL; + + return sub_bin; +} + //////////////////////////////////////////////////////////////////// // Function: GeomBinGroup::clear_current_states // Access: Public, Virtual @@ -22,6 +91,13 @@ TypeHandle GeomBinGroup::_type_handle; //////////////////////////////////////////////////////////////////// void GeomBinGroup:: clear_current_states() { + // This should never be called for toplevel bins, only sub bins--and + // a GeomBinGroup should never be a sub bin. The function will do + // the right thing even if it is called, but this is probably a + // mistake. + cull_cat.warning() + << "GeomBinGroup::clear_current_states() called\n"; + SubBins::iterator sbi; for (sbi = _sub_bins.begin(); sbi != _sub_bins.end(); ++sbi) { (*sbi)->clear_current_states(); @@ -51,6 +127,13 @@ record_current_state(GraphicsStateGuardian *gsg, CullState *cs, //////////////////////////////////////////////////////////////////// void GeomBinGroup:: draw(CullTraverser *trav) { + // This should never be called for toplevel bins, only sub bins--and + // a GeomBinGroup should never be a sub bin. The function will do + // the right thing even if it is called, but this is probably a + // mistake. + cull_cat.warning() + << "GeomBinGroup::draw() called\n"; + SubBins::iterator sbi; for (sbi = _sub_bins.begin(); sbi != _sub_bins.end(); ++sbi) { (*sbi)->draw(trav); @@ -84,3 +167,68 @@ write(ostream &out, int indent_level) const { indent(out, indent_level) << "}\n"; } + +//////////////////////////////////////////////////////////////////// +// Function: GeomBinGroup::attach +// Access: Protected, Virtual +// Description: Formally adds the GeomBin to its indicated Traverser. +//////////////////////////////////////////////////////////////////// +void GeomBinGroup:: +attach() { + nassertv(has_name()); + nassertv(_traverser != (CullTraverser *)NULL); + nassertv(!_is_attached); + + // In the case of a GeomBinGroup, the bin is only a toplevel bin + // (visible by name from the CullTraverser), and not a sub bin + // (directly renderable). + if (!has_parent()) { + _traverser->attach_toplevel_bin(this); + } + + _is_attached = true; + + // Now attach each of our sub bins. + SubBins::const_iterator sbi; + for (sbi = _sub_bins.begin(); sbi != _sub_bins.end(); ++sbi) { + GeomBin *sub_bin = (*sbi); + nassertv(!sub_bin->is_attached()); + sub_bin->_traverser = _traverser; + sub_bin->attach(); + } +} + +//////////////////////////////////////////////////////////////////// +// Function: GeomBinGroup::detach +// Access: Protected, Virtual +// Description: Detaches the bin from whichever CullTraverser it is +// currently attached to. The bin will no longer be +// rendered. The return value is a PT(GeomBin) that +// refers to the GeomBin itself; the caller should save +// this pointer in a local PT variable to avoid possibly +// destructing the GeomBin (since detaching it may +// remove the last outstanding reference count). +//////////////////////////////////////////////////////////////////// +PT(GeomBin) GeomBinGroup:: +detach() { + nassertr(_is_attached, NULL); + nassertr(_traverser != (CullTraverser *)NULL, NULL); + + PT(GeomBin) keep = this; + + if (!has_parent()) { + _traverser->detach_toplevel_bin(this); + } + + _is_attached = false; + + // Now detach each of our sub bins. + SubBins::const_iterator sbi; + for (sbi = _sub_bins.begin(); sbi != _sub_bins.end(); ++sbi) { + GeomBin *sub_bin = (*sbi); + sub_bin->detach(); + sub_bin->_traverser = (CullTraverser *)NULL; + } + + return keep; +} diff --git a/panda/src/cull/geomBinGroup.h b/panda/src/cull/geomBinGroup.h index 5adbdb2bb1..ee241a23b0 100644 --- a/panda/src/cull/geomBinGroup.h +++ b/panda/src/cull/geomBinGroup.h @@ -23,15 +23,16 @@ // a given CullState should be assigned to. //////////////////////////////////////////////////////////////////// class EXPCL_PANDA GeomBinGroup : public GeomBin { -public: - INLINE GeomBinGroup(const string &name, CullTraverser *traverser = NULL, - int sort = 0); +PUBLISHED: + INLINE GeomBinGroup(const string &name); + virtual ~GeomBinGroup(); - INLINE int add_sub_bin(GeomBin *sub_bin); + int add_sub_bin(GeomBin *sub_bin); INLINE int get_num_bins() const; INLINE GeomBin *get_bin(int n); - INLINE PT(GeomBin) remove_bin(int n); + PT(GeomBin) remove_bin(int n); +public: virtual int choose_bin(CullState *cs) const=0; virtual void clear_current_states(); @@ -44,6 +45,10 @@ public: virtual void output(ostream &out) const; virtual void write(ostream &out, int indent_level = 0) const; +protected: + virtual void attach(); + virtual PT(GeomBin) detach(); + private: typedef vector SubBins; SubBins _sub_bins; diff --git a/panda/src/cull/geomBinNormal.cxx b/panda/src/cull/geomBinNormal.cxx index 6e144ed89b..93ebc5d634 100644 --- a/panda/src/cull/geomBinNormal.cxx +++ b/panda/src/cull/geomBinNormal.cxx @@ -19,16 +19,21 @@ TypeHandle GeomBinNormal::_type_handle; // Description: //////////////////////////////////////////////////////////////////// GeomBinNormal:: -GeomBinNormal(const string &name, CullTraverser *traverser, int sort) : - GeomBinGroup(name, traverser, sort) +GeomBinNormal(const string &name) : + GeomBinGroup(name) { - add_sub_bin(new GeomBinUnsorted("opaque")); - add_sub_bin(new GeomBinBackToFront("transparent")); + GeomBinUnsorted *opaque = new GeomBinUnsorted("opaque"); + GeomBinBackToFront *transparent = new GeomBinBackToFront("transparent"); + opaque->set_sort(10); + transparent->set_sort(20); + + add_sub_bin(opaque); + add_sub_bin(transparent); } //////////////////////////////////////////////////////////////////// // Function: GeomBinNormal::Constructor -// Access: Public +// Access: Public, Virtual // Description: Identifies the particular sub-bin the indicated // CullState should be assigned to. //////////////////////////////////////////////////////////////////// diff --git a/panda/src/cull/geomBinNormal.h b/panda/src/cull/geomBinNormal.h index f77f9a9318..2c639b10ad 100644 --- a/panda/src/cull/geomBinNormal.h +++ b/panda/src/cull/geomBinNormal.h @@ -22,10 +22,10 @@ // back-to-front. //////////////////////////////////////////////////////////////////// class EXPCL_PANDA GeomBinNormal : public GeomBinGroup { -public: - GeomBinNormal(const string &name, CullTraverser *traverser = NULL, - int sort = 0); +PUBLISHED: + GeomBinNormal(const string &name); +public: virtual int choose_bin(CullState *cs) const; public: diff --git a/panda/src/cull/geomBinTransition.I b/panda/src/cull/geomBinTransition.I index de3f4dd94e..282a952308 100644 --- a/panda/src/cull/geomBinTransition.I +++ b/panda/src/cull/geomBinTransition.I @@ -18,7 +18,7 @@ GeomBinTransition() { // Description: //////////////////////////////////////////////////////////////////// INLINE GeomBinTransition:: -GeomBinTransition(GeomBin *bin, int draw_order) : +GeomBinTransition(const string &bin, int draw_order) : OnOffTransition(TD_on), _value(bin), _draw_order(draw_order) @@ -44,8 +44,8 @@ off() { // bin. //////////////////////////////////////////////////////////////////// INLINE void GeomBinTransition:: -set_on(GeomBin *bin, int draw_order) { - nassertv(bin != (GeomBin *)NULL); +set_on(const string &bin, int draw_order) { + nassertv(!bin.empty()); _value = bin; _draw_order = draw_order; OnOffTransition::set_on(); @@ -54,13 +54,13 @@ set_on(GeomBin *bin, int draw_order) { //////////////////////////////////////////////////////////////////// // Function: GeomBinTransition::get_bin // Access: Public -// Description: Returns the bin that the GeomBinTransition +// Description: Returns the bin name that the GeomBinTransition // represents. It is only valid to call this if is_on() // has returned true. //////////////////////////////////////////////////////////////////// -INLINE PT(GeomBin) GeomBinTransition:: +INLINE string GeomBinTransition:: get_bin() const { - nassertr(is_on(), NULL); + nassertr(is_on(), string()); return _value; } diff --git a/panda/src/cull/geomBinTransition.cxx b/panda/src/cull/geomBinTransition.cxx index c741763180..382170b300 100644 --- a/panda/src/cull/geomBinTransition.cxx +++ b/panda/src/cull/geomBinTransition.cxx @@ -8,6 +8,8 @@ #include +#include + TypeHandle GeomBinTransition::_type_handle; //////////////////////////////////////////////////////////////////// @@ -43,7 +45,7 @@ set_value_from(const OnOffTransition *other) { DCAST_INTO_V(ot, other); _value = ot->_value; _draw_order = ot->_draw_order; - nassertv(_value != (GeomBin *)NULL); + nassertv(!_value.empty()); } //////////////////////////////////////////////////////////////////// @@ -56,7 +58,7 @@ compare_values(const OnOffTransition *other) const { const GeomBinTransition *ot; DCAST_INTO_R(ot, other, false); if (_value != ot->_value) { - return (int)(_value - ot->_value); + return strcmp(_value.c_str(), ot->_value.c_str()); } return _draw_order - ot->_draw_order; } @@ -68,8 +70,7 @@ compare_values(const OnOffTransition *other) const { //////////////////////////////////////////////////////////////////// void GeomBinTransition:: output_value(ostream &out) const { - nassertv(_value != (GeomBin *)NULL); - out << *_value << ":" << _draw_order; + out << _value << ":" << _draw_order; } //////////////////////////////////////////////////////////////////// @@ -80,6 +81,61 @@ output_value(ostream &out) const { //////////////////////////////////////////////////////////////////// void GeomBinTransition:: write_value(ostream &out, int indent_level) const { - nassertv(_value != (GeomBin *)NULL); - indent(out, indent_level) << *_value << ":" << _draw_order << "\n"; + indent(out, indent_level) << _value << ":" << _draw_order << "\n"; +} + +//////////////////////////////////////////////////////////////////// +// Function: GeomBinTransition::register_with_factory +// Access: Public, Static +// Description: Factory method to generate a GeomBinTransition object +//////////////////////////////////////////////////////////////////// +void GeomBinTransition:: +register_with_read_factory() { + BamReader::get_factory()->register_factory(get_class_type(), make_GeomBinTransition); +} + +//////////////////////////////////////////////////////////////////// +// Function: GeomBinTransition::write_datagram +// Access: Public +// Description: Function to write the important information in +// the particular object to a Datagram +//////////////////////////////////////////////////////////////////// +void GeomBinTransition:: +write_datagram(BamWriter *manager, Datagram &me) { + OnOffTransition::write_datagram(manager, me); + me.add_string(_value); + me.add_int32(_draw_order); +} + +//////////////////////////////////////////////////////////////////// +// Function: GeomBinTransition::make_GeomBinTransition +// Access: Public +// Description: Factory method to generate a GeomBinTransition object +//////////////////////////////////////////////////////////////////// +TypedWriteable *GeomBinTransition:: +make_GeomBinTransition(const FactoryParams ¶ms) { + GeomBinTransition *me = new GeomBinTransition; + BamReader *manager; + Datagram packet; + + parse_params(params, manager, packet); + DatagramIterator scan(packet); + + me->fillin(scan, manager); + return me; +} + +//////////////////////////////////////////////////////////////////// +// Function: GeomBinTransition::fillin +// Access: Protected +// Description: Function that reads out of the datagram (or asks +// manager to read) all of the data that is needed to +// re-create this object and stores it in the appropiate +// place +//////////////////////////////////////////////////////////////////// +void GeomBinTransition:: +fillin(DatagramIterator &scan, BamReader *manager) { + OnOffTransition::fillin(scan, manager); + _value = scan.get_string(); + _draw_order = scan.get_int32(); } diff --git a/panda/src/cull/geomBinTransition.h b/panda/src/cull/geomBinTransition.h index 999499f67b..ea03017db9 100644 --- a/panda/src/cull/geomBinTransition.h +++ b/panda/src/cull/geomBinTransition.h @@ -16,15 +16,16 @@ // Description : //////////////////////////////////////////////////////////////////// class EXPCL_PANDA GeomBinTransition : public OnOffTransition { -public: +PUBLISHED: INLINE GeomBinTransition(); - INLINE GeomBinTransition(GeomBin *bin, int draw_order = 0); + INLINE GeomBinTransition(const string &bin, int draw_order); INLINE static GeomBinTransition off(); - INLINE void set_on(GeomBin *bin, int draw_order = 0); - INLINE PT(GeomBin) get_bin() const; + INLINE void set_on(const string &bin, int draw_order); + INLINE string get_bin() const; INLINE int get_draw_order() const; - + +public: virtual NodeTransition *make_copy() const; virtual NodeAttribute *make_attrib() const; @@ -34,9 +35,18 @@ protected: virtual void output_value(ostream &out) const; virtual void write_value(ostream &out, int indent_level) const; - PT(GeomBin) _value; + string _value; int _draw_order; +public: + static void register_with_read_factory(); + virtual void write_datagram(BamWriter* manager, Datagram &me); + + static TypedWriteable *make_GeomBinTransition(const FactoryParams ¶ms); + +protected: + void fillin(DatagramIterator& scan, BamReader* manager); + public: virtual TypeHandle get_type() const { return get_class_type(); diff --git a/panda/src/cull/geomBinUnsorted.I b/panda/src/cull/geomBinUnsorted.I index cf1d8a0f1c..ca0aa55191 100644 --- a/panda/src/cull/geomBinUnsorted.I +++ b/panda/src/cull/geomBinUnsorted.I @@ -9,7 +9,7 @@ // Description: //////////////////////////////////////////////////////////////////// INLINE GeomBinUnsorted:: -GeomBinUnsorted(const string &name, CullTraverser *traverser, int sort) : - GeomBin(name, traverser, sort) +GeomBinUnsorted(const string &name) : + GeomBin(name) { } diff --git a/panda/src/cull/geomBinUnsorted.h b/panda/src/cull/geomBinUnsorted.h index 75db098b2a..7ddbe10ef7 100644 --- a/panda/src/cull/geomBinUnsorted.h +++ b/panda/src/cull/geomBinUnsorted.h @@ -23,11 +23,11 @@ // order. //////////////////////////////////////////////////////////////////// class EXPCL_PANDA GeomBinUnsorted : public GeomBin { -public: - INLINE GeomBinUnsorted(const string &name, CullTraverser *traverser = NULL, - int sort = 0); +PUBLISHED: + INLINE GeomBinUnsorted(const string &name); virtual ~GeomBinUnsorted(); +public: virtual void clear_current_states(); virtual void record_current_state(GraphicsStateGuardian *gsg, CullState *cs, int draw_order, diff --git a/panda/src/doc/eggSyntax.txt b/panda/src/doc/eggSyntax.txt index 9928637808..79fdf923fa 100644 --- a/panda/src/doc/eggSyntax.txt +++ b/panda/src/doc/eggSyntax.txt @@ -174,11 +174,18 @@ appear before they are referenced. is any of the other options, it specifies the type of transparency to be enabled. + bin { bin-name } + + This specifies the bin name order of all polygons with this + texture applied, in the absence of a bin name specified on the + polygon itself. See the description for bin under polygon + attributes. + draw_order { number } This specifies the fixed drawing order of all polygons with this texture applied, in the absence of a drawing order specified on - the polygon itself. See the description for draw-order under + the polygon itself. See the description for draw_order under polygon attributes. { transform-definition } @@ -404,22 +411,39 @@ GEOMETRY ENTRIES it to be viewed from either side. + bin { bin-name } + + It is sometimes important to control the order in which objects + are rendered, particularly when transparency is in use. In Panda, + this is achieved via the use of named bins and, within certain + kinds of bins, sometimes an explicit draw_order is also used (see + below). + + In the normal (state-sorting) mode, Panda renders its geometry by + first grouping into one or more named bins, and then rendering the + bins in a specified order. The programmer is free to define any + number of bins, named whatever he/she desires. + + This scalar specifies which bin this particular polygon is to be + rendered within. If no bin scalar is given, or if the name given + does not match any of the known bins, the polygon will be assigned + to the default bin, which renders all opaque geometry sorted by + state, followed by all transparent geometry sorted back-to-front. + + See also draw_order, below. + + draw_order { number } - This defines the fixed drawing order of this polygon. Drawing - order is very important when using certain kinds of transparency. - Normally, Performer will draw all opaque objects first, then all - transparent objects from back to front. Sometimes the - back-to-front sorting can fail, especially in the case of a small - polygon immediately in front of a large polygon. In this case, it - may be necessary to explicitly give the order in which the - polygons should be drawn. + This works in conjunction with bin, above, to further refine the + order in which this polygon is drawn, relative to other geometry + in the same bin. If (and only if) the bin type named in the bin + scalar is a GeomBinFixed, this draw_order is used to define the + fixed order that all geometry in the same will be rendered, from + smaller numbers to larger numbers. - All objects with a given draw-order will be drawn before all - objects with a higher draw-order. Objects with a zero or - unspecified draw-order will be drawn first if they are opaque, and - in order from back to front if they are transparent. A negative - draw-order is not allowed. + If no bin scalar is specified, the default is a bin named "fixed", + which is a GeomBinFixed object that always exists by default. name { @@ -797,11 +821,17 @@ GROUPING ENTRIES affected by fog. It will be created with the appropriate GeoState to have fog disabled. + bin { bin-name } + + This specifies the bin name for all polygons at or below this node + that do not explicitly set their own bin. See the description of + bin for geometry attributes, above. + draw_order { number } This specifies the drawing order for all polygons at or below this node that do not explicitly set their own drawing order. See the - description of draw-order for geometry attributes, above. + description of draw_order for geometry attributes, above. write_through { boolean-value } diff --git a/panda/src/egg/eggAlphaMode.I b/panda/src/egg/eggAlphaMode.I index 27ca75bcec..ea272555d3 100644 --- a/panda/src/egg/eggAlphaMode.I +++ b/panda/src/egg/eggAlphaMode.I @@ -12,7 +12,7 @@ INLINE EggAlphaMode:: EggAlphaMode() { _alpha_mode = AM_unspecified; - _draw_order = 0.0; + _draw_order = 0; _has_draw_order = false; } @@ -66,21 +66,25 @@ get_alpha_mode() const { //////////////////////////////////////////////////////////////////// // Function: EggAlphaMode::set_draw_order // Access: Public -// Description: +// Description: Sets the "draw-order" flag associated with this +// object. This specifies a particular order in which +// objects of this type should be drawn, within the +// specified bin. If a bin is not explicitly specified, +// "fixed" is used. See also set_bin(). //////////////////////////////////////////////////////////////////// INLINE void EggAlphaMode:: -set_draw_order(double order) { +set_draw_order(int order) { _draw_order = order; _has_draw_order = true; } - //////////////////////////////////////////////////////////////////// // Function: EggAlphaMode::get_draw_order // Access: Public -// Description: +// Description: Returns the "draw-order" flag as set for this +// particular object. See set_draw_order(). //////////////////////////////////////////////////////////////////// -INLINE double EggAlphaMode:: +INLINE int EggAlphaMode:: get_draw_order() const { return _draw_order; } @@ -88,7 +92,8 @@ get_draw_order() const { //////////////////////////////////////////////////////////////////// // Function: EggAlphaMode::has_draw_order // Access: Public -// Description: +// Description: Returns true if the draw-order flag has been set for +// this particular object. See set_draw_order(). //////////////////////////////////////////////////////////////////// INLINE bool EggAlphaMode:: has_draw_order() const { @@ -98,13 +103,64 @@ has_draw_order() const { //////////////////////////////////////////////////////////////////// // Function: EggAlphaMode::clear_draw_order // Access: Public -// Description: +// Description: Removes the draw-order flag from this particular +// object. See set_draw_order(). //////////////////////////////////////////////////////////////////// INLINE void EggAlphaMode:: clear_draw_order() { _has_draw_order = false; } +//////////////////////////////////////////////////////////////////// +// Function: EggAlphaMode::set_bin +// Access: Public +// Description: Sets the "bin" string for this particular object. +// This names a particular bin in which the object +// should be rendered. The exact meaning of a bin is +// implementation defined, but generally a GeomBin +// matching each bin name must also be specifically +// added to the rendering engine (e.g. the +// CullTraverser) in use for this to work. See also +// set_draw_order(). +//////////////////////////////////////////////////////////////////// +INLINE void EggAlphaMode:: +set_bin(const string &bin) { + _bin = bin; +} + +//////////////////////////////////////////////////////////////////// +// Function: EggAlphaMode::get_bin +// Access: Public +// Description: Returns the bin name that has been set for this +// particular object, if any. See set_bin(). +//////////////////////////////////////////////////////////////////// +INLINE string EggAlphaMode:: +get_bin() const { + return _bin; +} + +//////////////////////////////////////////////////////////////////// +// Function: EggAlphaMode::has_bin +// Access: Public +// Description: Returns true if a bin name has been set for this +// particular object. See set_bin(). +//////////////////////////////////////////////////////////////////// +INLINE bool EggAlphaMode:: +has_bin() const { + return !_bin.empty(); +} + +//////////////////////////////////////////////////////////////////// +// Function: EggAlphaMode::clear_bin +// Access: Public +// Description: Removes the bin name that was set for this particular +// object. See set_bin(). +//////////////////////////////////////////////////////////////////// +INLINE void EggAlphaMode:: +clear_bin() { + _bin = string(); +} + //////////////////////////////////////////////////////////////////// // Function: EggAlphaMode::Inequality Operator // Access: Public diff --git a/panda/src/egg/eggAlphaMode.cxx b/panda/src/egg/eggAlphaMode.cxx index d5a8f4d1ce..b60256058e 100644 --- a/panda/src/egg/eggAlphaMode.cxx +++ b/panda/src/egg/eggAlphaMode.cxx @@ -26,6 +26,10 @@ write(ostream &out, int indent_level) const { indent(out, indent_level) << " draw-order { " << get_draw_order() << " }\n"; } + if (has_bin()) { + indent(out, indent_level) + << " bin { " << get_bin() << " }\n"; + } } //////////////////////////////////////////////////////////////////// @@ -46,6 +50,10 @@ operator == (const EggAlphaMode &other) const { } } + if (_bin != other._bin) { + return false; + } + return true; } @@ -70,6 +78,10 @@ operator < (const EggAlphaMode &other) const { } } + if (_bin != other._bin) { + return _bin < other._bin; + } + return false; } diff --git a/panda/src/egg/eggAlphaMode.h b/panda/src/egg/eggAlphaMode.h index ceab0131d7..9e076ede62 100644 --- a/panda/src/egg/eggAlphaMode.h +++ b/panda/src/egg/eggAlphaMode.h @@ -40,11 +40,16 @@ public: INLINE void set_alpha_mode(AlphaMode mode); INLINE AlphaMode get_alpha_mode() const; - INLINE void set_draw_order(double order); - INLINE double get_draw_order() const; + INLINE void set_draw_order(int order); + INLINE int get_draw_order() const; INLINE bool has_draw_order() const; INLINE void clear_draw_order(); + INLINE void set_bin(const string &bin); + INLINE string get_bin() const; + INLINE bool has_bin() const; + INLINE void clear_bin(); + // Comparison operators are handy. bool operator == (const EggAlphaMode &other) const; INLINE bool operator != (const EggAlphaMode &other) const; @@ -54,8 +59,9 @@ public: private: AlphaMode _alpha_mode; - double _draw_order; + int _draw_order; bool _has_draw_order; + string _bin; public: diff --git a/panda/src/egg/eggGroup.cxx b/panda/src/egg/eggGroup.cxx index b1e0a1aa5c..cee36381f3 100644 --- a/panda/src/egg/eggGroup.cxx +++ b/panda/src/egg/eggGroup.cxx @@ -265,6 +265,57 @@ write(ostream &out, int indent_level) const { indent(out, indent_level) << "}\n"; } +//////////////////////////////////////////////////////////////////// +// Function: EggGroup::determine_alpha_mode +// Access: Public, Virtual +// Description: Walks back up the hierarchy, looking for an EggGroup +// or EggPrimitive or some such object at this level or +// above this group that has an alpha_mode other than +// AM_unspecified. Returns a valid EggAlphaMode pointer +// if one is found, or NULL otherwise. +//////////////////////////////////////////////////////////////////// +EggAlphaMode *EggGroup:: +determine_alpha_mode() { + if (get_alpha_mode() != AM_unspecified) { + return this; + } + return EggGroupNode::determine_alpha_mode(); +} + +//////////////////////////////////////////////////////////////////// +// Function: EggGroup::determine_draw_order +// Access: Public, Virtual +// Description: Walks back up the hierarchy, looking for an EggGroup +// or EggPrimitive or some such object at this level or +// above this group that has a draw_order specified. +// Returns a valid EggAlphaMode pointer if one is found, +// or NULL otherwise. +//////////////////////////////////////////////////////////////////// +EggAlphaMode *EggGroup:: +determine_draw_order() { + if (has_draw_order()) { + return this; + } + return EggGroupNode::determine_draw_order(); +} + +//////////////////////////////////////////////////////////////////// +// Function: EggGroup::determine_bin +// Access: Public, Virtual +// Description: Walks back up the hierarchy, looking for an EggGroup +// or EggPrimitive or some such object at this level or +// above this group that has a bin specified. Returns a +// valid EggAlphaMode pointer if one is found, or NULL +// otherwise. +//////////////////////////////////////////////////////////////////// +EggAlphaMode *EggGroup:: +determine_bin() { + if (has_bin()) { + return this; + } + return EggGroupNode::determine_bin(); +} + //////////////////////////////////////////////////////////////////// // Function: EggGroup::parse_egg // Access: Public diff --git a/panda/src/egg/eggGroup.h b/panda/src/egg/eggGroup.h index 59b0dd5e59..e2cfab6427 100644 --- a/panda/src/egg/eggGroup.h +++ b/panda/src/egg/eggGroup.h @@ -77,6 +77,10 @@ public: virtual void write(ostream &out, int indent_level) const; bool parse_egg(const string &egg_syntax); + virtual EggAlphaMode *determine_alpha_mode(); + virtual EggAlphaMode *determine_draw_order(); + virtual EggAlphaMode *determine_bin(); + void set_group_type(GroupType type); INLINE GroupType get_group_type() const; diff --git a/panda/src/egg/eggNode.cxx b/panda/src/egg/eggNode.cxx index 5caa985131..04ad6542b5 100644 --- a/panda/src/egg/eggNode.cxx +++ b/panda/src/egg/eggNode.cxx @@ -11,6 +11,59 @@ TypeHandle EggNode::_type_handle; +//////////////////////////////////////////////////////////////////// +// Function: EggNode::determine_alpha_mode +// Access: Public, Virtual +// Description: Walks back up the hierarchy, looking for an EggGroup +// or EggPrimitive or some such object at this level or +// above this node that has an alpha_mode other than +// AM_unspecified. Returns a valid EggAlphaMode pointer +// if one is found, or NULL otherwise. +//////////////////////////////////////////////////////////////////// +EggAlphaMode *EggNode:: +determine_alpha_mode() { + if (_parent == (EggGroupNode *)NULL) { + // Too bad; we're done. + return (EggAlphaMode *)NULL; + } + return _parent->determine_alpha_mode(); +} + +//////////////////////////////////////////////////////////////////// +// Function: EggNode::determine_draw_order +// Access: Public, Virtual +// Description: Walks back up the hierarchy, looking for an EggGroup +// or EggPrimitive or some such object at this level or +// above this node that has a draw_order specified. +// Returns a valid EggAlphaMode pointer if one is found, +// or NULL otherwise. +//////////////////////////////////////////////////////////////////// +EggAlphaMode *EggNode:: +determine_draw_order() { + if (_parent == (EggGroupNode *)NULL) { + // Too bad; we're done. + return (EggAlphaMode *)NULL; + } + return _parent->determine_draw_order(); +} + +//////////////////////////////////////////////////////////////////// +// Function: EggNode::determine_bin +// Access: Public, Virtual +// Description: Walks back up the hierarchy, looking for an EggGroup +// or EggPrimitive or some such object at this level or +// above this node that has a bin specified. Returns a +// valid EggAlphaMode pointer if one is found, or NULL +// otherwise. +//////////////////////////////////////////////////////////////////// +EggAlphaMode *EggNode:: +determine_bin() { + if (_parent == (EggGroupNode *)NULL) { + // Too bad; we're done. + return (EggAlphaMode *)NULL; + } + return _parent->determine_bin(); +} #ifndef NDEBUG diff --git a/panda/src/egg/eggNode.h b/panda/src/egg/eggNode.h index 08ad308515..5015cb840a 100644 --- a/panda/src/egg/eggNode.h +++ b/panda/src/egg/eggNode.h @@ -16,6 +16,7 @@ #include class EggGroupNode; +class EggAlphaMode; //////////////////////////////////////////////////////////////////// // Class : EggNode @@ -36,6 +37,10 @@ public: INLINE bool is_under_transform() const; INLINE bool is_local_coord() const; + virtual EggAlphaMode *determine_alpha_mode(); + virtual EggAlphaMode *determine_draw_order(); + virtual EggAlphaMode *determine_bin(); + INLINE const LMatrix4d &get_vertex_frame() const; INLINE const LMatrix4d &get_node_frame() const; INLINE const LMatrix4d &get_vertex_frame_inv() const; diff --git a/panda/src/egg/eggPrimitive.cxx b/panda/src/egg/eggPrimitive.cxx index 05c6f013e1..81a229494f 100644 --- a/panda/src/egg/eggPrimitive.cxx +++ b/panda/src/egg/eggPrimitive.cxx @@ -13,6 +13,66 @@ TypeHandle EggPrimitive::_type_handle; +//////////////////////////////////////////////////////////////////// +// Function: EggPrimitive::determine_alpha_mode +// Access: Public, Virtual +// Description: Walks back up the hierarchy, looking for an EggPrimitive +// or EggPrimitive or some such object at this level or +// above this primitive that has an alpha_mode other than +// AM_unspecified. Returns a valid EggAlphaMode pointer +// if one is found, or NULL otherwise. +//////////////////////////////////////////////////////////////////// +EggAlphaMode *EggPrimitive:: +determine_alpha_mode() { + if (get_alpha_mode() != AM_unspecified) { + return this; + } + if (has_texture() && get_texture()->get_alpha_mode() != AM_unspecified) { + return get_texture(); + } + return EggNode::determine_alpha_mode(); +} + +//////////////////////////////////////////////////////////////////// +// Function: EggPrimitive::determine_draw_order +// Access: Public, Virtual +// Description: Walks back up the hierarchy, looking for an EggPrimitive +// or EggPrimitive or some such object at this level or +// above this primitive that has a draw_order specified. +// Returns a valid EggAlphaMode pointer if one is found, +// or NULL otherwise. +//////////////////////////////////////////////////////////////////// +EggAlphaMode *EggPrimitive:: +determine_draw_order() { + if (has_draw_order()) { + return this; + } + if (has_texture() && get_texture()->has_draw_order()) { + return get_texture(); + } + return EggNode::determine_draw_order(); +} + +//////////////////////////////////////////////////////////////////// +// Function: EggPrimitive::determine_bin +// Access: Public, Virtual +// Description: Walks back up the hierarchy, looking for an EggPrimitive +// or EggPrimitive or some such object at this level or +// above this primitive that has a bin specified. Returns a +// valid EggAlphaMode pointer if one is found, or NULL +// otherwise. +//////////////////////////////////////////////////////////////////// +EggAlphaMode *EggPrimitive:: +determine_bin() { + if (has_bin()) { + return this; + } + if (has_texture() && get_texture()->has_bin()) { + return get_texture(); + } + return EggNode::determine_bin(); +} + //////////////////////////////////////////////////////////////////// // Function: EggPrimitive::reverse_vertex_ordering // Access: Public, Virtual diff --git a/panda/src/egg/eggPrimitive.h b/panda/src/egg/eggPrimitive.h index ae018a94b4..c4955c196b 100644 --- a/panda/src/egg/eggPrimitive.h +++ b/panda/src/egg/eggPrimitive.h @@ -51,6 +51,10 @@ public: INLINE EggPrimitive &operator = (const EggPrimitive ©); INLINE ~EggPrimitive(); + virtual EggAlphaMode *determine_alpha_mode(); + virtual EggAlphaMode *determine_draw_order(); + virtual EggAlphaMode *determine_bin(); + INLINE void set_texture(PT(EggTexture) texture); INLINE void clear_texture(); INLINE PT(EggTexture) get_texture() const; diff --git a/panda/src/egg/parser.yxx b/panda/src/egg/parser.yxx index e6d86e4e95..c5467c8c44 100644 --- a/panda/src/egg/parser.yxx +++ b/panda/src/egg/parser.yxx @@ -384,7 +384,10 @@ texture_body: } } else if (cmp_nocase_uh(name, "draw_order") == 0) { - texture->set_draw_order(value); + texture->set_draw_order((int)value); + + } else if (cmp_nocase_uh(name, "bin") == 0) { + texture->set_bin(strval); } else if (cmp_nocase_uh(name, "alpha_file") == 0) { texture->set_alpha_file(strval); @@ -811,7 +814,9 @@ group_body: group->set_alpha_mode(a); } } else if (cmp_nocase_uh(name, "draw_order") == 0) { - group->set_draw_order(value); + group->set_draw_order((int)value); + } else if (cmp_nocase_uh(name, "bin") == 0) { + group->set_bin(strval); } else if (cmp_nocase_uh(name, "collide_mask") == 0) { group->set_collide_mask(value); } else if (cmp_nocase_uh(name, "from_collide_mask") == 0) { @@ -1325,7 +1330,9 @@ primitive_body: primitive->set_alpha_mode(a); } } else if (cmp_nocase_uh(name, "draw_order") == 0) { - primitive->set_draw_order(value); + primitive->set_draw_order((int)value); + } else if (cmp_nocase_uh(name, "bin") == 0) { + primitive->set_bin(strval); } else { eggyywarning("Unknown scalar " + name); } @@ -1373,7 +1380,9 @@ nurbs_surface_body: primitive->set_alpha_mode(a); } } else if (cmp_nocase_uh(name, "draw_order") == 0) { - primitive->set_draw_order(value); + primitive->set_draw_order((int)value); + } else if (cmp_nocase_uh(name, "bin") == 0) { + primitive->set_bin(strval); } else if (cmp_nocase_uh(name, "u_subdiv") == 0) { primitive->set_u_subdiv(value); } else if (cmp_nocase_uh(name, "v_subdiv") == 0) { @@ -1418,7 +1427,9 @@ nurbs_curve_body: primitive->set_alpha_mode(a); } } else if (cmp_nocase_uh(name, "draw_order") == 0) { - primitive->set_draw_order(value); + primitive->set_draw_order((int)value); + } else if (cmp_nocase_uh(name, "bin") == 0) { + primitive->set_bin(strval); } else if (cmp_nocase_uh(name, "subdiv") == 0) { primitive->set_subdiv(value); } else if (cmp_nocase_uh(name, "type") == 0) { diff --git a/panda/src/egg2sg/Sources.pp b/panda/src/egg2sg/Sources.pp index d3373db61a..f3f6cfe646 100644 --- a/panda/src/egg2sg/Sources.pp +++ b/panda/src/egg2sg/Sources.pp @@ -4,7 +4,7 @@ #begin lib_target #define TARGET egg2sg #define LOCAL_LIBS \ - collide egg builder loader chan char switchnode cull + cull collide egg builder loader chan char switchnode #define SOURCES \ animBundleMaker.cxx animBundleMaker.h characterMaker.cxx \ diff --git a/panda/src/egg2sg/eggLoader.cxx b/panda/src/egg2sg/eggLoader.cxx index 6407642ae0..b81938f048 100644 --- a/panda/src/egg2sg/eggLoader.cxx +++ b/panda/src/egg2sg/eggLoader.cxx @@ -40,6 +40,7 @@ #include #include #include +#include #include #include #include @@ -49,6 +50,7 @@ #include #include #include +#include #include #include @@ -895,17 +897,39 @@ setup_bucket(BuilderBucket &bucket, NamedNode *parent, } // Assign the appropriate properties to the bucket. - EggAlphaMode::AlphaMode am = egg_prim->get_alpha_mode(); + + // The three "alpha mode"-associated properties--alpha mode, draw + // order, and bin--can be defined directly at the primitive, at a + // group above the primitive, or an a texture applied to the + // primitive. The EggNode::determine_*() functions can find the + // right pointer to the level at which this is actually defined for + // a given primitive. + EggAlphaMode::AlphaMode am = EggAlphaMode::AM_unspecified; bool implicit_alpha = false; + bool has_draw_order = false; + int draw_order = 0; + bool has_bin = false; + string bin; + + EggAlphaMode *egg_alpha; + egg_alpha = egg_prim->determine_alpha_mode(); + if (egg_alpha != (EggAlphaMode *)NULL) { + am = egg_alpha->get_alpha_mode(); + } + egg_alpha = egg_prim->determine_draw_order(); + if (egg_alpha != (EggAlphaMode *)NULL) { + has_draw_order = true; + draw_order = egg_alpha->get_draw_order(); + } + egg_alpha = egg_prim->determine_bin(); + if (egg_alpha != (EggAlphaMode *)NULL) { + has_bin = true; + bin = egg_alpha->get_bin(); + } bucket._trans.set_transition(new TextureTransition(TextureTransition::off())); if (egg_prim->has_texture()) { PT(EggTexture) egg_tex = egg_prim->get_texture(); - // If the primitive didn't specify an alpha mode, allow the - // texture to specify one. - if (am == EggAlphaMode::AM_unspecified) { - am = egg_tex->get_alpha_mode(); - } const TextureDef &def = _textures[egg_tex]; if (def._texture != (TextureTransition *)NULL) { @@ -957,7 +981,8 @@ setup_bucket(BuilderBucket &bucket, NamedNode *parent, break; case EggAlphaMode::AM_blend_no_occlude: - bucket._trans.set_transition(new TransparencyTransition(TransparencyProperty::M_alpha_sorted)); + bucket._trans.set_transition(new TransparencyTransition(TransparencyProperty::M_alpha)); + bucket._trans.set_transition(new DepthWriteTransition(DepthWriteTransition::off())); break; case EggAlphaMode::AM_ms: @@ -973,6 +998,13 @@ setup_bucket(BuilderBucket &bucket, NamedNode *parent, break; } + if (has_bin) { + bucket._trans.set_transition(new GeomBinTransition(bin, draw_order)); + + } else if (has_draw_order) { + bucket._trans.set_transition(new GeomBinTransition("fixed", draw_order)); + } + if (egg_prim->get_bface_flag()) { // The primitive is marked with backface culling disabled--we want // to see both sides. diff --git a/panda/src/express/typeHandle.cxx b/panda/src/express/typeHandle.cxx index 57db7871dd..c8b18f21fe 100644 --- a/panda/src/express/typeHandle.cxx +++ b/panda/src/express/typeHandle.cxx @@ -667,3 +667,19 @@ get_parent_towards(TypeHandle type) const { TypedObject:: ~TypedObject() { } + + +//////////////////////////////////////////////////////////////////// +// Function: TypedObject::get_type +// Access: Public, Virtual +// Description: +//////////////////////////////////////////////////////////////////// +TypeHandle TypedObject:: +get_type() const { + // Normally, this function should never be called, because it is a + // pure virtual function. If it is called, you probably called + // get_type() on a recently-destructed object. + express_cat.warning() + << "TypedObject::get_type() called!\n"; + return _type_handle; +} diff --git a/panda/src/sgattrib/config_sgattrib.cxx b/panda/src/sgattrib/config_sgattrib.cxx index 0487fa892b..707d69c8d7 100644 --- a/panda/src/sgattrib/config_sgattrib.cxx +++ b/panda/src/sgattrib/config_sgattrib.cxx @@ -186,15 +186,16 @@ ConfigureFn(config_sgattrib) { //Registration of writeable object's creation //functions with BamReader's factory - RenderRelation::register_with_read_factory(); - TransformTransition::register_with_read_factory(); - TextureTransition::register_with_read_factory(); - TextureApplyTransition::register_with_read_factory(); - TransparencyTransition::register_with_read_factory(); - CullFaceTransition::register_with_read_factory(); - DecalTransition::register_with_read_factory(); - PruneTransition::register_with_read_factory(); BillboardTransition::register_with_read_factory(); ColorMatrixTransition::register_with_read_factory(); + CullFaceTransition::register_with_read_factory(); + DecalTransition::register_with_read_factory(); + DepthWriteTransition::register_with_read_factory(); + PruneTransition::register_with_read_factory(); + RenderRelation::register_with_read_factory(); + TextureApplyTransition::register_with_read_factory(); + TextureTransition::register_with_read_factory(); + TransformTransition::register_with_read_factory(); + TransparencyTransition::register_with_read_factory(); } diff --git a/panda/src/sgattrib/depthWriteTransition.cxx b/panda/src/sgattrib/depthWriteTransition.cxx index 73096c5272..968ae0455b 100644 --- a/panda/src/sgattrib/depthWriteTransition.cxx +++ b/panda/src/sgattrib/depthWriteTransition.cxx @@ -6,6 +6,11 @@ #include "depthWriteTransition.h" #include "depthWriteAttribute.h" +#include +#include +#include +#include + TypeHandle DepthWriteTransition::_type_handle; //////////////////////////////////////////////////////////////////// @@ -28,3 +33,55 @@ NodeAttribute *DepthWriteTransition:: make_attrib() const { return new DepthWriteAttribute; } + +//////////////////////////////////////////////////////////////////// +// Function: DepthWriteTransition::register_with_factory +// Access: Public, Static +// Description: Factory method to generate a DepthWriteTransition object +//////////////////////////////////////////////////////////////////// +void DepthWriteTransition:: +register_with_read_factory() { + BamReader::get_factory()->register_factory(get_class_type(), make_DepthWriteTransition); +} + +//////////////////////////////////////////////////////////////////// +// Function: DepthWriteTransition::write_datagram +// Access: Public +// Description: Function to write the important information in +// the particular object to a Datagram +//////////////////////////////////////////////////////////////////// +void DepthWriteTransition:: +write_datagram(BamWriter *manager, Datagram &me) { + OnOffTransition::write_datagram(manager, me); +} + +//////////////////////////////////////////////////////////////////// +// Function: DepthWriteTransition::make_DepthWriteTransition +// Access: Public +// Description: Factory method to generate a DepthWriteTransition object +//////////////////////////////////////////////////////////////////// +TypedWriteable *DepthWriteTransition:: +make_DepthWriteTransition(const FactoryParams ¶ms) { + DepthWriteTransition *me = new DepthWriteTransition; + BamReader *manager; + Datagram packet; + + parse_params(params, manager, packet); + DatagramIterator scan(packet); + + me->fillin(scan, manager); + return me; +} + +//////////////////////////////////////////////////////////////////// +// Function: DepthWriteTransition::fillin +// Access: Protected +// Description: Function that reads out of the datagram (or asks +// manager to read) all of the data that is needed to +// re-create this object and stores it in the appropiate +// place +//////////////////////////////////////////////////////////////////// +void DepthWriteTransition:: +fillin(DatagramIterator &scan, BamReader *manager) { + OnOffTransition::fillin(scan, manager); +} diff --git a/panda/src/sgattrib/depthWriteTransition.h b/panda/src/sgattrib/depthWriteTransition.h index 59f2a7e0c0..57e98e77a1 100644 --- a/panda/src/sgattrib/depthWriteTransition.h +++ b/panda/src/sgattrib/depthWriteTransition.h @@ -23,6 +23,15 @@ public: virtual NodeTransition *make_copy() const; virtual NodeAttribute *make_attrib() const; +public: + static void register_with_read_factory(); + virtual void write_datagram(BamWriter* manager, Datagram &me); + + static TypedWriteable *make_DepthWriteTransition(const FactoryParams ¶ms); + +protected: + void fillin(DatagramIterator& scan, BamReader* manager); + public: virtual TypeHandle get_type() const { return get_class_type();