diff --git a/panda/src/pgraph/portalNode.I b/panda/src/pgraph/portalNode.I new file mode 100755 index 0000000000..864749dadb --- /dev/null +++ b/panda/src/pgraph/portalNode.I @@ -0,0 +1,126 @@ +// Filename: portalNode.I +// Created by: masad (13May04) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved +// +// All use of this software is subject to the terms of the Panda 3d +// Software license. You should have received a copy of this license +// along with this source code; you will also find a current copy of +// the license at http://etc.cmu.edu/panda3d/docs/license/ . +// +// To contact the maintainers of this program write to +// panda3d-general@lists.sourceforge.net . +// +//////////////////////////////////////////////////////////////////// + + +//////////////////////////////////////////////////////////////////// +// Function: PortalNode::set_portal_mask +// Access: Published +// Description: Simultaneously sets both the "from" and "into" +// PortalMask values to the same thing. +//////////////////////////////////////////////////////////////////// +INLINE void PortalNode:: +set_portal_mask(PortalMask mask) { + set_from_portal_mask(mask); + set_into_portal_mask(mask); +} + +//////////////////////////////////////////////////////////////////// +// Function: PortalNode::set_from_portal_mask +// Access: Published +// Description: Sets the "from" PortalMask. In order for a +// portal to be detected from this object into +// another object, the intersection of this object's +// "from" mask and the other object's "into" mask must +// be nonzero. +//////////////////////////////////////////////////////////////////// +INLINE void PortalNode:: +set_from_portal_mask(PortalMask mask) { + _from_portal_mask = mask; +} + +//////////////////////////////////////////////////////////////////// +// Function: PortalNode::set_into_portal_mask +// Access: Published +// Description: Sets the "into" PortalMask. In order for a +// portal to be detected from another object into +// this object, the intersection of the other object's +// "from" mask and this object's "into" mask must be +// nonzero. +//////////////////////////////////////////////////////////////////// +INLINE void PortalNode:: +set_into_portal_mask(PortalMask mask) { + _into_portal_mask = mask; + + // We mark the bound stale when this changes, not because the actual + // bounding volume changes, but rather because we piggyback the + // computing of the _net_portal_mask on the bounding volume. + mark_bound_stale(); +} + +//////////////////////////////////////////////////////////////////// +// Function: PortalNode::get_from_portal_mask +// Access: Published +// Description: Returns the current "from" PortalMask. In order for +// a portal to be detected from this object into +// another object, the intersection of this object's +// "from" mask and the other object's "into" mask must +// be nonzero. +//////////////////////////////////////////////////////////////////// +INLINE PortalMask PortalNode:: +get_from_portal_mask() const { + return _from_portal_mask; +} + +//////////////////////////////////////////////////////////////////// +// Function: PortalNode::get_into_portal_mask +// Access: Published +// Description: Returns the current "into" PortalMask. In order for +// a portal to be detected from another object into +// this object, the intersection of the other object's +// "from" mask and this object's "into" mask must be +// nonzero. +//////////////////////////////////////////////////////////////////// +INLINE PortalMask PortalNode:: +get_into_portal_mask() const { + return _into_portal_mask; +} + +//////////////////////////////////////////////////////////////////// +// Function: PortalNode::set_portal_geom +// Access: Published +// Description: Sets the state of the "portal geom" flag for this +// PortalNode. Normally, this is false; when this is +// set true, the PortalSolids in this node will test +// for portals with actual renderable geometry, in +// addition to whatever PortalSolids may be indicated +// by the from_portal_mask. +// +// Setting this to true causes this to test *all* +// GeomNodes for portals. It is an all-or-none +// thing; there is no way to portal with only some +// GeomNodes, as GeomNodes have no into_portal_mask. +//////////////////////////////////////////////////////////////////// +INLINE void PortalNode:: +set_portal_geom(bool flag) { + if (flag) { + _flags |= F_portal_geom; + } else { + _flags &= ~F_portal_geom; + } +} + +//////////////////////////////////////////////////////////////////// +// Function: PortalNode::get_portal_geom +// Access: Published +// Description: Returns the current state of the portal_geom flag. +// See set_portal_geom(). +//////////////////////////////////////////////////////////////////// +INLINE bool PortalNode:: +get_portal_geom() const { + return (_flags & F_portal_geom) != 0; +} diff --git a/panda/src/pgraph/portalNode.cxx b/panda/src/pgraph/portalNode.cxx new file mode 100755 index 0000000000..2ddb226123 --- /dev/null +++ b/panda/src/pgraph/portalNode.cxx @@ -0,0 +1,329 @@ +// Filename: portalNode.cxx +// Created by: drose (16Mar02) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved +// +// All use of this software is subject to the terms of the Panda 3d +// Software license. You should have received a copy of this license +// along with this source code; you will also find a current copy of +// the license at http://etc.cmu.edu/panda3d/docs/license/ . +// +// To contact the maintainers of this program write to +// panda3d-general@lists.sourceforge.net . +// +//////////////////////////////////////////////////////////////////// + +#include "portalNode.h" + +#include "geomNode.h" +#include "cullTraverserData.h" +#include "cullTraverser.h" +#include "renderState.h" +#include "transformState.h" +#include "colorScaleAttrib.h" +#include "transparencyAttrib.h" +#include "datagram.h" +#include "datagramIterator.h" +#include "bamReader.h" +#include "bamWriter.h" + +TypeHandle PortalNode::_type_handle; + + +//////////////////////////////////////////////////////////////////// +// Function: PortalNode::Constructor +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +PortalNode:: +PortalNode(const string &name) : + PandaNode(name), + _from_portal_mask(PortalMask::all_on()), + _into_portal_mask(PortalMask::all_on()), + _flags(0) +{ + // PortalNodes are hidden by default. + set_draw_mask(DrawMask::all_off()); +} + +//////////////////////////////////////////////////////////////////// +// Function: PortalNode::Copy Constructor +// Access: Protected +// Description: +//////////////////////////////////////////////////////////////////// +PortalNode:: +PortalNode(const PortalNode ©) : + PandaNode(copy), + _from_portal_mask(copy._from_portal_mask), + _into_portal_mask(copy._into_portal_mask), + _flags(copy._flags) +{ +} + +//////////////////////////////////////////////////////////////////// +// Function: PortalNode::Destructor +// Access: Public, Virtual +// Description: +//////////////////////////////////////////////////////////////////// +PortalNode:: +~PortalNode() { +} + +//////////////////////////////////////////////////////////////////// +// Function: PortalNode::make_copy +// Access: Public, Virtual +// Description: Returns a newly-allocated Node that is a shallow copy +// of this one. It will be a different Node pointer, +// but its internal data may or may not be shared with +// that of the original Node. +//////////////////////////////////////////////////////////////////// +PandaNode *PortalNode:: +make_copy() const { + return new PortalNode(*this); +} + +//////////////////////////////////////////////////////////////////// +// Function: PortalNode::preserve_name +// Access: Public, Virtual +// Description: Returns true if the node's name has extrinsic meaning +// and must be preserved across a flatten operation, +// false otherwise. +//////////////////////////////////////////////////////////////////// +bool PortalNode:: +preserve_name() const { + return true; +} + +//////////////////////////////////////////////////////////////////// +// Function: PortalNode::xform +// Access: Public, Virtual +// Description: Transforms the contents of this node by the indicated +// matrix, if it means anything to do so. For most +// kinds of nodes, this does nothing. +//////////////////////////////////////////////////////////////////// +void PortalNode:: +xform(const LMatrix4f &mat) { + nassertv(!mat.is_nan()); + +} + +//////////////////////////////////////////////////////////////////// +// Function: PortalNode::combine_with +// Access: Public, Virtual +// Description: Collapses this node with the other node, if possible, +// and returns a pointer to the combined node, or NULL +// if the two nodes cannot safely be combined. +// +// The return value may be this, other, or a new node +// altogether. +// +// This function is called from GraphReducer::flatten(), +// and need not deal with children; its job is just to +// decide whether to collapse the two nodes and what the +// collapsed node should look like. +//////////////////////////////////////////////////////////////////// +PandaNode *PortalNode:: +combine_with(PandaNode *other) { + if (is_exact_type(get_class_type()) && + other->is_exact_type(get_class_type())) { + // Two PortalNodes can combine, but only if they have the same + // name, because the name is often meaningful. + PortalNode *cother = DCAST(PortalNode, other); + if (get_name() == cother->get_name()) { + return this; + } + + // Two PortalNodes with different names can't combine. + return (PandaNode *)NULL; + } + + return PandaNode::combine_with(other); +} + +//////////////////////////////////////////////////////////////////// +// Function: PortalNode::has_cull_callback +// Access: Public, Virtual +// Description: Should be overridden by derived classes to return +// true if cull_callback() has been defined. Otherwise, +// returns false to indicate cull_callback() does not +// need to be called for this node during the cull +// traversal. +//////////////////////////////////////////////////////////////////// +bool PortalNode:: +has_cull_callback() const { + return true; +} + +//////////////////////////////////////////////////////////////////// +// Function: PortalNode::cull_callback +// Access: Public, Virtual +// Description: If has_cull_callback() returns true, this function +// will be called during the cull traversal to perform +// any additional operations that should be performed at +// cull time. This may include additional manipulation +// of render state or additional visible/invisible +// decisions, or any other arbitrary operation. +// +// By the time this function is called, the node has +// already passed the bounding-volume test for the +// viewing frustum, and the node's transform and state +// have already been applied to the indicated +// CullTraverserData object. +// +// The return value is true if this node should be +// visible, or false if it should be culled. +//////////////////////////////////////////////////////////////////// +bool PortalNode:: +cull_callback(CullTraverser *trav, CullTraverserData &data) { + // Append our portal vizzes to the drawing, even though they're + // not actually part of the scene graph. + // Now carry on to render our child nodes. + return true; +} + + +//////////////////////////////////////////////////////////////////// +// Function: PortalNode::output +// Access: Public, Virtual +// Description: Writes a brief description of the node to the +// indicated output stream. This is invoked by the << +// operator. It may be overridden in derived classes to +// include some information relevant to the class. +//////////////////////////////////////////////////////////////////// +void PortalNode:: +output(ostream &out) const { + PandaNode::output(out); +} + + +//////////////////////////////////////////////////////////////////// +// Function: PortalNode::recompute_bound +// Access: Protected, Virtual +// Description: Recomputes the dynamic bounding volume for this +// object. This is the bounding volume for the node and +// all of its children, and normally does not need to be +// specialized beyond PandaNode; we specialize this +// function just so we can piggyback on it the +// setting the _net_portal_mask bits. +//////////////////////////////////////////////////////////////////// +BoundingVolume *PortalNode:: +recompute_bound() { + BoundingVolume *result = PandaNode::recompute_bound(); + return result; +} + +//////////////////////////////////////////////////////////////////// +// Function: PortalNode::recompute_internal_bound +// Access: Protected, Virtual +// Description: Called when needed to recompute the node's +// _internal_bound object. Nodes that contain anything +// of substance should redefine this to do the right +// thing. +//////////////////////////////////////////////////////////////////// +BoundingVolume *PortalNode:: +recompute_internal_bound() { + // First, get ourselves a fresh, empty bounding volume. + BoundingVolume *bound = PandaNode::recompute_internal_bound(); + nassertr(bound != (BoundingVolume *)NULL, bound); + + // Now actually compute the bounding volume by putting it around all + return bound; +} + +//////////////////////////////////////////////////////////////////// +// Function: PortalNode::get_last_pos_state +// Access: Protected +// Description: Returns a RenderState for rendering the ghosted +// portal rectangle that represents the previous frame's +// position, for those collision nodes that indicate a +// velocity. +//////////////////////////////////////////////////////////////////// +CPT(RenderState) PortalNode:: +get_last_pos_state() { + // Once someone asks for this pointer, we hold its reference count + // and never free it. + static CPT(RenderState) state = (const RenderState *)NULL; + if (state == (const RenderState *)NULL) { + state = RenderState::make + (ColorScaleAttrib::make(LVecBase4f(1.0f, 1.0f, 1.0f, 0.5f)), + TransparencyAttrib::make(TransparencyAttrib::M_alpha)); + } + + return state; +} + + +//////////////////////////////////////////////////////////////////// +// Function: PortalNode::register_with_read_factory +// Access: Public, Static +// Description: Tells the BamReader how to create objects of type +// PortalNode. +//////////////////////////////////////////////////////////////////// +void PortalNode:: +register_with_read_factory() { + BamReader::get_factory()->register_factory(get_class_type(), make_from_bam); +} + +//////////////////////////////////////////////////////////////////// +// Function: PortalNode::write_datagram +// Access: Public, Virtual +// Description: Writes the contents of this object to the datagram +// for shipping out to a Bam file. +//////////////////////////////////////////////////////////////////// +void PortalNode:: +write_datagram(BamWriter *manager, Datagram &dg) { + PandaNode::write_datagram(manager, dg); +} + +//////////////////////////////////////////////////////////////////// +// Function: PortalNode::complete_pointers +// Access: Public, Virtual +// Description: Receives an array of pointers, one for each time +// manager->read_pointer() was called in fillin(). +// Returns the number of pointers processed. +//////////////////////////////////////////////////////////////////// +int PortalNode:: +complete_pointers(TypedWritable **p_list, BamReader *manager) { + int pi = PandaNode::complete_pointers(p_list, manager); + + return pi; +} + +//////////////////////////////////////////////////////////////////// +// Function: PortalNode::make_from_bam +// Access: Protected, Static +// Description: This function is called by the BamReader's factory +// when a new object of type PortalNode is encountered +// in the Bam file. It should create the PortalNode +// and extract its information from the file. +//////////////////////////////////////////////////////////////////// +TypedWritable *PortalNode:: +make_from_bam(const FactoryParams ¶ms) { + PortalNode *node = new PortalNode(""); + DatagramIterator scan; + BamReader *manager; + + parse_params(params, scan, manager); + node->fillin(scan, manager); + + return node; +} + +//////////////////////////////////////////////////////////////////// +// Function: PortalNode::fillin +// Access: Protected +// Description: This internal function is called by make_from_bam to +// read in all of the relevant data from the BamFile for +// the new PortalNode. +//////////////////////////////////////////////////////////////////// +void PortalNode:: +fillin(DatagramIterator &scan, BamReader *manager) { + PandaNode::fillin(scan, manager); + + _from_portal_mask.set_word(scan.get_uint32()); + _into_portal_mask.set_word(scan.get_uint32()); + _flags = scan.get_uint8(); +} diff --git a/panda/src/pgraph/portalNode.h b/panda/src/pgraph/portalNode.h new file mode 100755 index 0000000000..77f1428503 --- /dev/null +++ b/panda/src/pgraph/portalNode.h @@ -0,0 +1,112 @@ +// Filename: portalNode.h +// Created by: masad (13May04) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved +// +// All use of this software is subject to the terms of the Panda 3d +// Software license. You should have received a copy of this license +// along with this source code; you will also find a current copy of +// the license at http://etc.cmu.edu/panda3d/docs/license/ . +// +// To contact the maintainers of this program write to +// panda3d-general@lists.sourceforge.net . +// +//////////////////////////////////////////////////////////////////// + +#ifndef PORTALNODE_H +#define PORTALNODE_H + +#include "pandabase.h" + +#include "portalMask.h" +#include "pandaNode.h" + +//////////////////////////////////////////////////////////////////// +// Class : PortalNode +// Description : A node in the scene graph that can hold a +// Portal Polygon, which is a rectangle. Other +// types of polygons are not supported for +// now. It also holds a PT(PandaNode) Zone that +// this portal is connected to +//////////////////////////////////////////////////////////////////// +class EXPCL_PANDA PortalNode : public PandaNode { +PUBLISHED: + PortalNode(const string &name); + +protected: + PortalNode(const PortalNode ©); + +public: + virtual ~PortalNode(); + virtual PandaNode *make_copy() const; + virtual bool preserve_name() const; + virtual void xform(const LMatrix4f &mat); + virtual PandaNode *combine_with(PandaNode *other); + + virtual bool has_cull_callback() const; + virtual bool cull_callback(CullTraverser *trav, CullTraverserData &data); + + virtual void output(ostream &out) const; + +PUBLISHED: + INLINE void set_portal_mask(PortalMask mask); + INLINE void set_from_portal_mask(PortalMask mask); + INLINE void set_into_portal_mask(PortalMask mask); + INLINE PortalMask get_from_portal_mask() const; + INLINE PortalMask get_into_portal_mask() const; + + INLINE void set_portal_geom(bool flag); + INLINE bool get_portal_geom() const; + +protected: + virtual BoundingVolume *recompute_bound(); + virtual BoundingVolume *recompute_internal_bound(); + +private: + CPT(RenderState) get_last_pos_state(); + + // This data is not cycled, for now. We assume the collision + // traversal will take place in App only. Perhaps we will revisit + // this later. + PortalMask _from_portal_mask; + PortalMask _into_portal_mask; + + enum Flags { + F_portal_geom = 0x0001, + // Presently only 8 bits are written to the bam file. + }; + int _flags; + +public: + static void register_with_read_factory(); + virtual void write_datagram(BamWriter *manager, Datagram &dg); + virtual int complete_pointers(TypedWritable **plist, BamReader *manager); + +protected: + static TypedWritable *make_from_bam(const FactoryParams ¶ms); + void fillin(DatagramIterator &scan, BamReader *manager); + +public: + static TypeHandle get_class_type(void) { + return _type_handle; + } + static void init_type(void) { + PandaNode::init_type(); + register_type(_type_handle, "PortalNode", + PandaNode::get_class_type()); + } + virtual TypeHandle get_type(void) const { + return get_class_type(); + } + virtual TypeHandle force_init_type() {init_type(); return get_class_type();} + +private: + static TypeHandle _type_handle; +}; + +#include "portalNode.I" + +#endif