diff --git a/panda/src/display/displayRegion.I b/panda/src/display/displayRegion.I index 5a831df834..f74d0fdb53 100644 --- a/panda/src/display/displayRegion.I +++ b/panda/src/display/displayRegion.I @@ -27,7 +27,10 @@ operator < (const DisplayRegion &other) const { //////////////////////////////////////////////////////////////////// // Function: DisplayRegion::get_lens_index // Access: Public -// Description: Gets the index into a lens_node lens array. 0 default +// Description: Returns the specific lens of the associated Camera +// that will be used for rendering this scene. Most +// Cameras hold only one lens, but for multiple lenses +// this method may be used to selected between them. //////////////////////////////////////////////////////////////////// INLINE int DisplayRegion:: get_lens_index() const { diff --git a/panda/src/display/displayRegion.cxx b/panda/src/display/displayRegion.cxx index b6e662054b..4fc9508792 100644 --- a/panda/src/display/displayRegion.cxx +++ b/panda/src/display/displayRegion.cxx @@ -104,7 +104,8 @@ cleanup() { // variety of setups, such as fish eye rendering. // The default is 0. //////////////////////////////////////////////////////////////////// -void DisplayRegion::set_lens_index(int index) { +void DisplayRegion:: +set_lens_index(int index) { int pipeline_stage = Thread::get_current_pipeline_stage(); nassertv(pipeline_stage == 0); CDWriter cdata(_cycler); diff --git a/panda/src/display/displayRegion.h b/panda/src/display/displayRegion.h index 28b27ed494..c7fc55a9c6 100644 --- a/panda/src/display/displayRegion.h +++ b/panda/src/display/displayRegion.h @@ -101,8 +101,8 @@ PUBLISHED: virtual void set_texture_reload_priority(int texture_reload_priority); INLINE int get_texture_reload_priority() const; - INLINE int get_lens_index() const; void set_lens_index(int index); + INLINE int get_lens_index() const; virtual void set_cull_traverser(CullTraverser *trav); CullTraverser *get_cull_traverser(); diff --git a/panda/src/display/graphicsEngine.cxx b/panda/src/display/graphicsEngine.cxx index 228a2f9358..dac5382db5 100644 --- a/panda/src/display/graphicsEngine.cxx +++ b/panda/src/display/graphicsEngine.cxx @@ -1671,8 +1671,9 @@ setup_scene(GraphicsStateGuardian *gsg, DisplayRegionPipelineReader *dr) { } camera_node->cleanup_aux_scene_data(current_thread); - Lens *lens = camera_node->get_lens( dr->get_lens_index() ); - if (lens == (Lens *)NULL) { + int lens_index = dr->get_lens_index(); + Lens *lens = camera_node->get_lens(lens_index); + if (lens == (Lens *)NULL || !camera_node->get_lens_active(lens_index)) { // No lens, no draw. return NULL; } diff --git a/panda/src/pgraph/config_pgraph.cxx b/panda/src/pgraph/config_pgraph.cxx index 044e9e4a5c..a33d355b88 100644 --- a/panda/src/pgraph/config_pgraph.cxx +++ b/panda/src/pgraph/config_pgraph.cxx @@ -294,6 +294,15 @@ ConfigVariableBool flatten_geoms "only the NodePath interfaces; you may still make the lower-level " "SceneGraphReducer calls directly.")); +ConfigVariableInt max_lenses +("max-lenses", 100, + PRC_DESC("Specifies an upper limit on the maximum number of lenses " + "and the maximum lens index number) that may be associated with " + "a single LensNode. There is no technical reason for this " + "limitation, but very large numbers are probably a mistake, so " + "this can be used as a simple sanity check. Set it larger or " + "smaller to suit your needs.")); + ConfigVariableBool polylight_info ("polylight-info", false, PRC_DESC("Set this true to view some info statements regarding the polylight. " diff --git a/panda/src/pgraph/config_pgraph.h b/panda/src/pgraph/config_pgraph.h index 7751a389cc..4bb96690b4 100644 --- a/panda/src/pgraph/config_pgraph.h +++ b/panda/src/pgraph/config_pgraph.h @@ -57,6 +57,7 @@ extern ConfigVariableInt max_collect_indices; extern EXPCL_PANDA_PGRAPH ConfigVariableBool premunge_data; extern ConfigVariableBool preserve_geom_nodes; extern ConfigVariableBool flatten_geoms; +extern ConfigVariableInt max_lenses; extern ConfigVariableBool polylight_info; extern ConfigVariableDouble lod_fade_time; diff --git a/panda/src/pgraph/lensNode.I b/panda/src/pgraph/lensNode.I index 72119788e7..8d1a36a165 100644 --- a/panda/src/pgraph/lensNode.I +++ b/panda/src/pgraph/lensNode.I @@ -21,21 +21,19 @@ // changed or destroyed, this LensNode is not // affected. //////////////////////////////////////////////////////////////////// - INLINE void LensNode:: copy_lens(const Lens &lens) { - return copy_lens(0, lens); + return copy_lens(0, lens); } +//////////////////////////////////////////////////////////////////// +// Function: LensNode::copy_lens +// Access: Published +// Description: Copies the indicated lens into the specified slot. +//////////////////////////////////////////////////////////////////// INLINE void LensNode:: -copy_lens(long index, const Lens &lens) { - if ( (index > (long) (_additional_lenses.size() + 1) ) || (index <= 0) ) - _lens = lens.make_copy(); - else - _additional_lenses[index-1] = lens.make_copy(); - if (_shown_frustum != (PandaNode *)NULL) { - show_frustum(); - } +copy_lens(int index, const Lens &lens) { + set_lens(index, lens.make_copy()); } //////////////////////////////////////////////////////////////////// @@ -45,29 +43,9 @@ copy_lens(long index, const Lens &lens) { // pointer. If the lens is subsequently modified, the // LensNode properties immediately reflect the change. //////////////////////////////////////////////////////////////////// - INLINE void LensNode:: set_lens(Lens *lens) { - return set_lens(0, lens); -} - -INLINE void LensNode:: -set_lens(long index, Lens *lens) { - if (index > MAX_LENSES) - return; // Sanity check - while ( index >= (long) (_additional_lenses.size() + 1) ) { - _additional_lenses.push_back(lens); - _lens_is_active.push_back(false); - } - - if (index <= 0) - _lens = lens; - else - _additional_lenses[index-1] = lens; - activate_lens(index); - if (_shown_frustum != (PandaNode *)NULL) { - show_frustum(); - } + return set_lens(0, lens); } //////////////////////////////////////////////////////////////////// @@ -75,29 +53,65 @@ set_lens(long index, Lens *lens) { // Access: Published // Description: Returns a pointer to the particular Lens // associated with this LensNode, or NULL if there is -// not yet a Lens associated. +// not yet a Lens associated. If an index number is +// specified, returns the nth lens. //////////////////////////////////////////////////////////////////// INLINE Lens *LensNode:: -get_lens(long index) const { - if ( ( index > (long) _additional_lenses.size() ) || (index <= 0) ) - return _lens; - return _additional_lenses[index-1]; +get_lens(int index) const { + nassertr(index >= 0 && index < max_lenses, NULL); // Sanity check + + if (index < (int)_lenses.size()) { + return _lenses[index]._lens; + } + return NULL; } +//////////////////////////////////////////////////////////////////// +// Function: LensNode::get_lens_active +// Access: Published +// Description: Returns the active flag for the nth lens. +//////////////////////////////////////////////////////////////////// INLINE bool LensNode:: -activate_lens(long index) { - if ( ( index >= (long) (_additional_lenses.size() + 1) ) || (index < 0) ) - return false; - if ( _lens_is_active[index] ) - return false; - _lens_is_active[index] = true; - return true; +get_lens_active(int index) const { + nassertr(index >= 0 && index < max_lenses, false); + + if (index < (int)_lenses.size()) { + return _lenses[index]._is_active; + } + return false; } +//////////////////////////////////////////////////////////////////// +// Function: LensNode::activate_lens +// Access: Published +// Description: An alternate way to call set_lens_active(index, +// true). +//////////////////////////////////////////////////////////////////// INLINE bool LensNode:: -deactivate_lens(long index) { - if ( ( index > (long) (_additional_lenses.size() + 1) ) || (index < 0) ) - return false; - _lens_is_active[index] = true; - return true; +activate_lens(int index) { + return set_lens_active(index, true); } + +//////////////////////////////////////////////////////////////////// +// Function: LensNode::deactivate_lens +// Access: Published +// Description: An alternate way to call set_lens_active(index, +// false). +//////////////////////////////////////////////////////////////////// +INLINE bool LensNode:: +deactivate_lens(int index) { + return set_lens_active(index, false); +} + +//////////////////////////////////////////////////////////////////// +// Function: LensNode::is_in_view +// Access: Published +// Description: Returns true if the given point is within the bounds +// of the lens of the LensNode (i.e. if the camera can +// see the point). +//////////////////////////////////////////////////////////////////// +INLINE bool LensNode:: +is_in_view(const LPoint3f &pos) { + return is_in_view(0, pos); +} + diff --git a/panda/src/pgraph/lensNode.cxx b/panda/src/pgraph/lensNode.cxx index 0c5fb3de81..5002dd3fc0 100644 --- a/panda/src/pgraph/lensNode.cxx +++ b/panda/src/pgraph/lensNode.cxx @@ -30,10 +30,12 @@ TypeHandle LensNode::_type_handle; //////////////////////////////////////////////////////////////////// LensNode:: LensNode(const string &name, Lens *lens) : - PandaNode(name), - _lens(lens) + PandaNode(name) { - _lens_is_active.push_back(true); // The default lens is on by default. + if (lens == NULL) { + lens = new PerspectiveLens; + } + set_lens(0, lens); } //////////////////////////////////////////////////////////////////// @@ -44,9 +46,8 @@ LensNode(const string &name, Lens *lens) : LensNode:: LensNode(const LensNode ©) : PandaNode(copy), - _lens(copy._lens) + _lenses(copy._lenses) { - _lens_is_active.push_back(true); // The default lens is on by default. } //////////////////////////////////////////////////////////////////// @@ -75,6 +76,65 @@ make_copy() const { return new LensNode(*this); } +//////////////////////////////////////////////////////////////////// +// Function: LensNode::set_lens +// Access: Published +// Description: Sets the indicated lens. Although a LensNode +// normally holds only one lens, it may optionally +// include multiple lenses, each with a different index +// number. The different lenses may be referenced by +// index number on the DisplayRegion. Adding a new lens +// automatically makes it active. +//////////////////////////////////////////////////////////////////// +void LensNode:: +set_lens(int index, Lens *lens) { + nassertv(index >= 0 && index < max_lenses); // Sanity check + + while (index >= (int)_lenses.size()) { + LensSlot slot; + slot._is_active = false; + _lenses.push_back(slot); + } + + _lenses[index]._lens = lens; + _lenses[index]._is_active = true; + + if (_shown_frustum != (PandaNode *)NULL) { + show_frustum(); + } +} + +//////////////////////////////////////////////////////////////////// +// Function: LensNode::set_lens_active +// Access: Published +// Description: Sets the active flag for the nth lens. When a lens +// is inactive, it is not used for rendering, and any +// DisplayRegions associated with it are implicitly +// inactive as well. Returns true if the flag is +// changed, false if it already had this value. +//////////////////////////////////////////////////////////////////// +bool LensNode:: +set_lens_active(int index, bool flag) { + nassertr(index >= 0 && index < max_lenses, false); + + while (index >= (int)_lenses.size()) { + LensSlot slot; + slot._is_active = false; + _lenses.push_back(slot); + } + + if (_lenses[index]._is_active == flag) { + return false; + } + + _lenses[index]._is_active = flag; + + if (_shown_frustum != (PandaNode *)NULL) { + show_frustum(); + } + return true; +} + //////////////////////////////////////////////////////////////////// // Function: LensNode::is_in_view // Access: Published @@ -83,8 +143,10 @@ make_copy() const { // see the point). //////////////////////////////////////////////////////////////////// bool LensNode:: -is_in_view(const LPoint3f &pos) { - PT(BoundingVolume) bv = _lens->make_bounds(); +is_in_view(int index, const LPoint3f &pos) { + Lens *lens = get_lens(index); + nassertr(lens != (Lens *)NULL, false); + PT(BoundingVolume) bv = lens->make_bounds(); if (bv == (BoundingVolume *)NULL) { return false; } @@ -109,8 +171,12 @@ show_frustum() { _shown_frustum = geom_node; add_child(_shown_frustum); - if (_lens != (Lens *)NULL) { - geom_node->add_geom(_lens->make_geometry()); + for (Lenses::const_iterator li = _lenses.begin(); + li != _lenses.end(); + ++li) { + if ((*li)._is_active && (*li)._lens != (Lens *)NULL) { + geom_node->add_geom((*li)._lens->make_geometry()); + } } } @@ -136,11 +202,17 @@ hide_frustum() { void LensNode:: output(ostream &out) const { PandaNode::output(out); - if (_lens != (Lens *)NULL) { - out << " ("; - _lens->output(out); - out << ")"; + + out << " ("; + for (Lenses::const_iterator li = _lenses.begin(); + li != _lenses.end(); + ++li) { + if ((*li)._is_active && (*li)._lens != (Lens *)NULL) { + out << " "; + (*li)._lens->output(out); + } } + out << " )"; } //////////////////////////////////////////////////////////////////// @@ -151,8 +223,13 @@ output(ostream &out) const { void LensNode:: write(ostream &out, int indent_level) const { PandaNode::write(out, indent_level); - if (_lens != (Lens *)NULL) { - _lens->write(out, indent_level + 2); + + for (Lenses::const_iterator li = _lenses.begin(); + li != _lenses.end(); + ++li) { + if ((*li)._is_active && (*li)._lens != (Lens *)NULL) { + (*li)._lens->write(out, indent_level + 2); + } } } @@ -177,7 +254,10 @@ void LensNode:: write_datagram(BamWriter *manager, Datagram &dg) { PandaNode::write_datagram(manager, dg); - manager->write_pointer(dg, _lens); + // For now, we only write out lens 0, simply because that's what we + // always have done. Should probably write out all lenses for the + // future. + manager->write_pointer(dg, get_lens(0)); } //////////////////////////////////////////////////////////////////// @@ -190,7 +270,7 @@ write_datagram(BamWriter *manager, Datagram &dg) { int LensNode:: complete_pointers(TypedWritable **p_list, BamReader *manager) { int pi = PandaNode::complete_pointers(p_list, manager); - _lens = DCAST(Lens, p_list[pi++]); + set_lens(0, DCAST(Lens, p_list[pi++])); return pi; } diff --git a/panda/src/pgraph/lensNode.h b/panda/src/pgraph/lensNode.h index 66348228fd..5cbfd47ab9 100644 --- a/panda/src/pgraph/lensNode.h +++ b/panda/src/pgraph/lensNode.h @@ -15,8 +15,6 @@ #ifndef LENSNODE_H #define LENSNODE_H -#define MAX_LENSES 5 - #include "pandabase.h" #include "pandaNode.h" @@ -33,7 +31,7 @@ //////////////////////////////////////////////////////////////////// class EXPCL_PANDA_PGRAPH LensNode : public PandaNode { PUBLISHED: - LensNode(const string &name, Lens *lens = new PerspectiveLens()); + LensNode(const string &name, Lens *lens = NULL); protected: LensNode(const LensNode ©); @@ -46,25 +44,35 @@ public: PUBLISHED: INLINE void copy_lens(const Lens &lens); + INLINE void copy_lens(int index, const Lens &lens); INLINE void set_lens(Lens *lens); - INLINE void copy_lens(long index, const Lens &lens); - INLINE void set_lens(long index, Lens *lens); - INLINE Lens *get_lens(long index = 0) const; - INLINE bool activate_lens(long index); - INLINE bool deactivate_lens(long index); + void set_lens(int index, Lens *lens); + INLINE Lens *get_lens(int index = 0) const; + + bool set_lens_active(int index, bool active); + INLINE bool get_lens_active(int index) const; - bool is_in_view(const LPoint3f &pos); + INLINE bool activate_lens(int index); + INLINE bool deactivate_lens(int index); + + INLINE bool is_in_view(const LPoint3f &pos); + bool is_in_view(int index, const LPoint3f &pos); void show_frustum(); void hide_frustum(); protected: - PT(Lens) _lens; PT(PandaNode) _shown_frustum; - vector _additional_lenses; - vector _lens_is_active; + class LensSlot { + public: + PT(Lens) _lens; + bool _is_active; + }; + typedef pvector Lenses; + Lenses _lenses; + public: static void register_with_read_factory(); virtual void write_datagram(BamWriter *manager, Datagram &dg);