From 1ac667d4c69d5e4cc54445b1bf20c50cafd84a0b Mon Sep 17 00:00:00 2001 From: David Rose Date: Sat, 23 Feb 2002 18:28:02 +0000 Subject: [PATCH] more refinements --- panda/src/pgraph/Sources.pp | 18 +- panda/src/pgraph/colorAttrib.cxx | 64 ++++- panda/src/pgraph/colorAttrib.h | 15 +- panda/src/pgraph/config_pgraph.cxx | 8 + panda/src/pgraph/cullHandler.cxx | 36 +++ panda/src/pgraph/cullHandler.h | 42 ++++ panda/src/pgraph/cycleDataReader.h | 3 - panda/src/pgraph/cycleDataWriter.h | 2 - panda/src/pgraph/pandaNode.I | 42 ++-- panda/src/pgraph/pandaNode.cxx | 57 +++-- panda/src/pgraph/pandaNode.h | 15 +- panda/src/pgraph/pgraph_composite1.cxx | 15 +- panda/src/pgraph/pgraph_composite2.cxx | 17 +- panda/src/pgraph/qpcullTraverser.I | 17 ++ panda/src/pgraph/qpcullTraverser.cxx | 117 ++++++++++ panda/src/pgraph/qpcullTraverser.h | 62 +++++ panda/src/pgraph/qpgeomNode.I | 140 +++++++++++ panda/src/pgraph/qpgeomNode.cxx | 214 +++++++++++++++++ panda/src/pgraph/qpgeomNode.h | 118 ++++++++++ panda/src/pgraph/renderAttrib.cxx | 13 +- panda/src/pgraph/renderAttrib.h | 1 + panda/src/pgraph/renderState.cxx | 8 + panda/src/pgraph/test_pgraph.cxx | 49 ++-- panda/src/pgraph/textureAttrib.cxx | 58 +++++ panda/src/pgraph/textureAttrib.h | 12 +- panda/src/pgraph/transformAttrib.I | 172 ++++++++++++++ panda/src/pgraph/transformAttrib.cxx | 308 +++++++++++++++++++++++++ panda/src/pgraph/transformAttrib.h | 117 ++++++++++ 28 files changed, 1639 insertions(+), 101 deletions(-) create mode 100644 panda/src/pgraph/cullHandler.cxx create mode 100644 panda/src/pgraph/cullHandler.h create mode 100644 panda/src/pgraph/qpcullTraverser.I create mode 100644 panda/src/pgraph/qpcullTraverser.cxx create mode 100644 panda/src/pgraph/qpcullTraverser.h create mode 100644 panda/src/pgraph/qpgeomNode.I create mode 100644 panda/src/pgraph/qpgeomNode.cxx create mode 100644 panda/src/pgraph/qpgeomNode.h create mode 100644 panda/src/pgraph/transformAttrib.I create mode 100644 panda/src/pgraph/transformAttrib.cxx create mode 100644 panda/src/pgraph/transformAttrib.h diff --git a/panda/src/pgraph/Sources.pp b/panda/src/pgraph/Sources.pp index 181948c6a7..ec340e01b0 100644 --- a/panda/src/pgraph/Sources.pp +++ b/panda/src/pgraph/Sources.pp @@ -8,32 +8,40 @@ #define SOURCES \ colorAttrib.h colorAttrib.I \ config_pgraph.h \ + cullHandler.h \ + qpcullTraverser.h qpcullTraverser.I \ cycleData.h cycleData.I \ cycleDataReader.h cycleDataReader.I \ cycleDataWriter.h cycleDataWriter.I \ + qpgeomNode.h qpgeomNode.I \ pandaNode.h pandaNode.I \ pipeline.h pipeline.I \ pipelineCycler.h pipelineCycler.I \ pipelineCyclerBase.h pipelineCyclerBase.I \ renderAttrib.h renderAttrib.I \ renderState.h renderState.I \ - textureAttrib.h textureAttrib.I + textureAttrib.h textureAttrib.I \ + transformAttrib.h transformAttrib.I - #define COMBINED_SOURCES $[TARGET]_composite1.cxx $[TARGET]_composite2.cxx -// #define SOURCES $[SOURCES] \ - #define INCLUDED_SOURCES \ +// #define COMBINED_SOURCES $[TARGET]_composite1.cxx $[TARGET]_composite2.cxx +// #define INCLUDED_SOURCES \ + #define SOURCES $[SOURCES] \ colorAttrib.cxx \ config_pgraph.cxx \ + cullHandler.cxx \ + qpcullTraverser.cxx \ cycleData.cxx \ cycleDataReader.cxx \ cycleDataWriter.cxx \ + qpgeomNode.cxx \ pandaNode.cxx \ pipeline.cxx \ pipelineCycler.cxx \ pipelineCyclerBase.cxx \ renderAttrib.cxx \ renderState.cxx \ - textureAttrib.cxx + textureAttrib.cxx \ + transformAttrib.cxx #define INSTALL_HEADERS \ pandaNode.h pandaNode.I diff --git a/panda/src/pgraph/colorAttrib.cxx b/panda/src/pgraph/colorAttrib.cxx index b5c5ce7264..b8b7565532 100644 --- a/panda/src/pgraph/colorAttrib.cxx +++ b/panda/src/pgraph/colorAttrib.cxx @@ -18,6 +18,10 @@ #include "colorAttrib.h" #include "dcast.h" +#include "bamReader.h" +#include "bamWriter.h" +#include "datagram.h" +#include "datagramIterator.h" TypeHandle ColorAttrib::_type_handle; @@ -30,7 +34,7 @@ TypeHandle ColorAttrib::_type_handle; //////////////////////////////////////////////////////////////////// CPT(RenderAttrib) ColorAttrib:: make_vertex() { - ColorAttrib *attrib = new ColorAttrib(T_vertex, Colorf(0.0f, 0.0f, 0.0f, 1.0f)); + ColorAttrib *attrib = new ColorAttrib(T_vertex); return return_new(attrib); } @@ -55,7 +59,7 @@ make_flat(const Colorf &color) { //////////////////////////////////////////////////////////////////// CPT(RenderAttrib) ColorAttrib:: make_off() { - ColorAttrib *attrib = new ColorAttrib(T_off, Colorf(0.0f, 0.0f, 0.0f, 1.0f)); + ColorAttrib *attrib = new ColorAttrib(T_off); return return_new(attrib); } @@ -123,5 +127,59 @@ compare_to_impl(const RenderAttrib *other) const { //////////////////////////////////////////////////////////////////// RenderAttrib *ColorAttrib:: make_default_impl() const { - return new ColorAttrib(T_vertex, Colorf(0.0f, 0.0f, 0.0f, 1.0f)); + return new ColorAttrib; +} + +//////////////////////////////////////////////////////////////////// +// Function: ColorAttrib::register_with_read_factory +// Access: Public, Static +// Description: Tells the BamReader how to create objects of type +// ColorAttrib. +//////////////////////////////////////////////////////////////////// +void ColorAttrib:: +register_with_read_factory() { + BamReader::get_factory()->register_factory(get_class_type(), make_from_bam); +} + +//////////////////////////////////////////////////////////////////// +// Function: ColorAttrib::write_datagram +// Access: Public, Virtual +// Description: Writes the contents of this object to the datagram +// for shipping out to a Bam file. +//////////////////////////////////////////////////////////////////// +void ColorAttrib:: +write_datagram(BamWriter *manager, Datagram &dg) { + RenderAttrib::write_datagram(manager, dg); +} + +//////////////////////////////////////////////////////////////////// +// Function: ColorAttrib::make_from_bam +// Access: Protected, Static +// Description: This function is called by the BamReader's factory +// when a new object of type ColorAttrib is encountered +// in the Bam file. It should create the ColorAttrib +// and extract its information from the file. +//////////////////////////////////////////////////////////////////// +TypedWritable *ColorAttrib:: +make_from_bam(const FactoryParams ¶ms) { + ColorAttrib *attrib = new ColorAttrib; + DatagramIterator scan; + BamReader *manager; + + parse_params(params, scan, manager); + attrib->fillin(scan, manager); + + return new_from_bam(attrib, manager); +} + +//////////////////////////////////////////////////////////////////// +// Function: ColorAttrib::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 ColorAttrib. +//////////////////////////////////////////////////////////////////// +void ColorAttrib:: +fillin(DatagramIterator &scan, BamReader *manager) { + RenderAttrib::fillin(scan, manager); } diff --git a/panda/src/pgraph/colorAttrib.h b/panda/src/pgraph/colorAttrib.h index 3bb4e9979f..ea43e559ce 100644 --- a/panda/src/pgraph/colorAttrib.h +++ b/panda/src/pgraph/colorAttrib.h @@ -36,7 +36,8 @@ PUBLISHED: }; private: - INLINE ColorAttrib(Type type, const Colorf &color); + INLINE ColorAttrib(Type type = T_vertex, + const Colorf &color = Colorf(0.0f, 0.0f, 0.0f, 1.0f)); PUBLISHED: static CPT(RenderAttrib) make_vertex(); @@ -56,15 +57,23 @@ protected: private: Type _type; Colorf _color; + +public: + static void register_with_read_factory(); + virtual void write_datagram(BamWriter *manager, Datagram &dg); + +protected: + static TypedWritable *make_from_bam(const FactoryParams ¶ms); + void fillin(DatagramIterator &scan, BamReader *manager); public: static TypeHandle get_class_type() { return _type_handle; } static void init_type() { - TypedWritableReferenceCount::init_type(); + RenderAttrib::init_type(); register_type(_type_handle, "ColorAttrib", - TypedWritableReferenceCount::get_class_type()); + RenderAttrib::get_class_type()); } virtual TypeHandle get_type() const { return get_class_type(); diff --git a/panda/src/pgraph/config_pgraph.cxx b/panda/src/pgraph/config_pgraph.cxx index 37462bf723..1e2c6c7fd2 100644 --- a/panda/src/pgraph/config_pgraph.cxx +++ b/panda/src/pgraph/config_pgraph.cxx @@ -19,10 +19,12 @@ #include "config_pgraph.h" #include "colorAttrib.h" +#include "qpgeomNode.h" #include "pandaNode.h" #include "renderAttrib.h" #include "renderState.h" #include "textureAttrib.h" +#include "transformAttrib.h" #include "dconfig.h" @@ -51,11 +53,17 @@ init_libpgraph() { initialized = true; ColorAttrib::init_type(); + qpGeomNode::init_type(); PandaNode::init_type(); RenderAttrib::init_type(); RenderState::init_type(); TextureAttrib::init_type(); + TransformAttrib::init_type(); + ColorAttrib::register_with_read_factory(); + qpGeomNode::register_with_read_factory(); PandaNode::register_with_read_factory(); RenderState::register_with_read_factory(); + TextureAttrib::register_with_read_factory(); + TransformAttrib::register_with_read_factory(); } diff --git a/panda/src/pgraph/cullHandler.cxx b/panda/src/pgraph/cullHandler.cxx new file mode 100644 index 0000000000..93aae74b1b --- /dev/null +++ b/panda/src/pgraph/cullHandler.cxx @@ -0,0 +1,36 @@ +// Filename: cullHandler.cxx +// Created by: drose (23Feb02) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved +// +// All use of this software is subject to the terms of the Panda 3d +// Software license. You should have received a copy of this license +// along with this source code; you will also find a current copy of +// the license at http://www.panda3d.org/license.txt . +// +// To contact the maintainers of this program write to +// panda3d@yahoogroups.com . +// +//////////////////////////////////////////////////////////////////// + +#include "cullHandler.h" +#include "geom.h" +#include "renderState.h" + +//////////////////////////////////////////////////////////////////// +// Function: CullHandler::found_geom +// Access: Public, Virtual +// Description: This callback function is intended to be overridden +// by a derived class. This is called as each Geom is +// discovered by the CullTraverser. +// +// This default method simply outputs a message to cerr; +// it's not intended to be used except for debugging. +//////////////////////////////////////////////////////////////////// +void CullHandler:: +found_geom(Geom *geom, const RenderState *state) { + cerr << *geom << " " << *state << "\n"; +} diff --git a/panda/src/pgraph/cullHandler.h b/panda/src/pgraph/cullHandler.h new file mode 100644 index 0000000000..08848d0856 --- /dev/null +++ b/panda/src/pgraph/cullHandler.h @@ -0,0 +1,42 @@ +// Filename: cullHandler.h +// Created by: drose (23Feb02) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved +// +// All use of this software is subject to the terms of the Panda 3d +// Software license. You should have received a copy of this license +// along with this source code; you will also find a current copy of +// the license at http://www.panda3d.org/license.txt . +// +// To contact the maintainers of this program write to +// panda3d@yahoogroups.com . +// +//////////////////////////////////////////////////////////////////// + +#ifndef CULLHANDLER_H +#define CULLHANDLER_H + +#include "pandabase.h" + +class Geom; +class RenderState; + +//////////////////////////////////////////////////////////////////// +// Class : CullHandler +// Description : This defines the abstract interface for an object +// that receives Geoms identified by the CullTraverser. +// By itself, it's not a particularly useful class; to +// use it, derive from it and redefine found_geom(). +//////////////////////////////////////////////////////////////////// +class EXPCL_PANDA CullHandler { +public: + virtual void found_geom(Geom *geom, const RenderState *state); +}; + +#endif + + + diff --git a/panda/src/pgraph/cycleDataReader.h b/panda/src/pgraph/cycleDataReader.h index 7b832944ff..0eefff7c32 100644 --- a/panda/src/pgraph/cycleDataReader.h +++ b/panda/src/pgraph/cycleDataReader.h @@ -51,9 +51,6 @@ private: const CycleDataType *_pointer; }; -// This abbreviation macro is used for ease of typing. -#define CDR(type) CycleDataReader< type > - #include "cycleDataReader.I" #endif diff --git a/panda/src/pgraph/cycleDataWriter.h b/panda/src/pgraph/cycleDataWriter.h index 218f08b128..9b213c0acb 100644 --- a/panda/src/pgraph/cycleDataWriter.h +++ b/panda/src/pgraph/cycleDataWriter.h @@ -52,8 +52,6 @@ private: CycleDataType *_pointer; }; -#define CDW(type) CycleDataWriter< type > - #include "cycleDataWriter.I" #endif diff --git a/panda/src/pgraph/pandaNode.I b/panda/src/pgraph/pandaNode.I index c4fc934965..5f444166d1 100644 --- a/panda/src/pgraph/pandaNode.I +++ b/panda/src/pgraph/pandaNode.I @@ -78,8 +78,8 @@ CData() { // Description: //////////////////////////////////////////////////////////////////// INLINE PandaNode::Children:: -Children(const PipelineCycler &cycler) : - _cdata(cycler) +Children(const PandaNode::CDReader &cdata) : + _cdata(cdata) { } @@ -115,17 +115,6 @@ get_child(int n) const { return _cdata->_down[n].get_child(); } -//////////////////////////////////////////////////////////////////// -// Function: PandaNode::Constructor -// Access: Published -// Description: -//////////////////////////////////////////////////////////////////// -INLINE PandaNode:: -PandaNode(const string &name) : - Namable(name) -{ -} - //////////////////////////////////////////////////////////////////// // Function: PandaNode::get_num_parents // Access: Published @@ -137,7 +126,7 @@ PandaNode(const string &name) : //////////////////////////////////////////////////////////////////// INLINE int PandaNode:: get_num_parents() const { - CDR(CData) cdata(_cycler); + CDReader cdata(_cycler); return cdata->_up.size(); } @@ -149,7 +138,7 @@ get_num_parents() const { //////////////////////////////////////////////////////////////////// INLINE PandaNode *PandaNode:: get_parent(int n) const { - CDR(CData) cdata(_cycler); + CDReader cdata(_cycler); nassertr(n >= 0 && n < (int)cdata->_up.size(), NULL); return cdata->_up[n]; } @@ -162,7 +151,7 @@ get_parent(int n) const { //////////////////////////////////////////////////////////////////// INLINE int PandaNode:: find_parent(PandaNode *node) const { - CDR(CData) cdata(_cycler); + CDReader cdata(_cycler); Up::const_iterator ui = cdata->_up.find(node); if (ui == cdata->_up.end()) { return -1; @@ -180,7 +169,7 @@ find_parent(PandaNode *node) const { //////////////////////////////////////////////////////////////////// INLINE int PandaNode:: get_num_children() const { - CDR(CData) cdata(_cycler); + CDReader cdata(_cycler); return cdata->_down.size(); } @@ -192,7 +181,7 @@ get_num_children() const { //////////////////////////////////////////////////////////////////// INLINE PandaNode *PandaNode:: get_child(int n) const { - CDR(CData) cdata(_cycler); + CDReader cdata(_cycler); nassertr(n >= 0 && n < (int)cdata->_down.size(), NULL); return cdata->_down[n].get_child(); } @@ -206,7 +195,7 @@ get_child(int n) const { //////////////////////////////////////////////////////////////////// INLINE int PandaNode:: get_sort(int n) const { - CDR(CData) cdata(_cycler); + CDReader cdata(_cycler); nassertr(n >= 0 && n < (int)cdata->_down.size(), -1); return cdata->_down[n].get_sort(); } @@ -222,7 +211,7 @@ get_sort(int n) const { //////////////////////////////////////////////////////////////////// INLINE void PandaNode:: set_attrib(const RenderAttrib *attrib, int override) { - CDW(CData) cdata(_cycler); + CDWriter cdata(_cycler); cdata->_state_changes = cdata->_state_changes->add(attrib, override); } @@ -237,7 +226,7 @@ set_attrib(const RenderAttrib *attrib, int override) { //////////////////////////////////////////////////////////////////// INLINE const RenderAttrib *PandaNode:: get_attrib(TypeHandle type) const { - CDR(CData) cdata(_cycler); + CDReader cdata(_cycler); int index = cdata->_state_changes->find_attrib(type); if (index >= 0) { return cdata->_state_changes->get_attrib(index); @@ -255,7 +244,7 @@ get_attrib(TypeHandle type) const { //////////////////////////////////////////////////////////////////// INLINE void PandaNode:: clear_attrib(TypeHandle type) { - CDW(CData) cdata(_cycler); + CDWriter cdata(_cycler); cdata->_state_changes = cdata->_state_changes->remove(type); } @@ -271,7 +260,7 @@ clear_attrib(TypeHandle type) { //////////////////////////////////////////////////////////////////// INLINE void PandaNode:: set_state(const RenderState *state) { - CDW(CData) cdata(_cycler); + CDWriter cdata(_cycler); cdata->_state_changes = state; } @@ -286,7 +275,7 @@ set_state(const RenderState *state) { //////////////////////////////////////////////////////////////////// INLINE const RenderState *PandaNode:: get_state() const { - CDR(CData) cdata(_cycler); + CDReader cdata(_cycler); return cdata->_state_changes; } @@ -300,7 +289,7 @@ get_state() const { //////////////////////////////////////////////////////////////////// INLINE void PandaNode:: clear_state() { - CDW(CData) cdata(_cycler); + CDWriter cdata(_cycler); cdata->_state_changes = RenderState::make_empty(); } @@ -320,6 +309,7 @@ clear_state() { //////////////////////////////////////////////////////////////////// INLINE PandaNode::Children PandaNode:: get_children() const { - return Children(_cycler); + CDReader cdata(_cycler); + return Children(cdata); } diff --git a/panda/src/pgraph/pandaNode.cxx b/panda/src/pgraph/pandaNode.cxx index 61b3a0995d..9010cf9c3b 100644 --- a/panda/src/pgraph/pandaNode.cxx +++ b/panda/src/pgraph/pandaNode.cxx @@ -50,6 +50,17 @@ make_copy() const { return new CData(*this); } +//////////////////////////////////////////////////////////////////// +// Function: PandaNode::Constructor +// Access: Published +// Description: +//////////////////////////////////////////////////////////////////// +PandaNode:: +PandaNode(const string &name) : + Namable(name) +{ +} + //////////////////////////////////////////////////////////////////// // Function: PandaNode::Copy Constructor // Access: Published @@ -64,8 +75,8 @@ PandaNode(const PandaNode ©) : // Copying a node does not copy its children. // Copy the other node's bounding volume. - CDR(CData) copy_cdata(copy._cycler); - CDW(CData) cdata(_cycler); + CDReader copy_cdata(copy._cycler); + CDWriter cdata(_cycler); cdata->_node_bounds = copy_cdata->_node_bounds; } @@ -81,8 +92,8 @@ operator = (const PandaNode ©) { ReferenceCount::operator = (copy); // Copy the other node's bounding volume. - CDR(CData) copy_cdata(copy._cycler); - CDW(CData) cdata(_cycler); + CDReader copy_cdata(copy._cycler); + CDWriter cdata(_cycler); cdata->_node_bounds = copy_cdata->_node_bounds; } @@ -95,7 +106,7 @@ PandaNode:: ~PandaNode() { // We shouldn't have any parents left by the time we destruct, or // there's a refcount fault somewhere. - CDR(CData) cdata(_cycler); + CDReader cdata(_cycler); nassertv(cdata->_up.empty()); remove_all_children(); @@ -109,7 +120,7 @@ PandaNode:: //////////////////////////////////////////////////////////////////// int PandaNode:: find_child(PandaNode *node) const { - CDR(CData) cdata(_cycler); + CDReader cdata(_cycler); // We have to search for the child by brute force, since we don't // know what sort index it was added as. @@ -139,8 +150,8 @@ find_child(PandaNode *node) const { int PandaNode:: add_child(PandaNode *child, int sort) { remove_child(child); - CDW(CData) cdata(_cycler); - CDW(CData) cdata_child(child->_cycler); + CDWriter cdata(_cycler); + CDWriter cdata_child(child->_cycler); Down::iterator ci = cdata->_down.insert(DownConnection(child, sort)); cdata_child->_up.insert(this); @@ -155,11 +166,11 @@ add_child(PandaNode *child, int sort) { //////////////////////////////////////////////////////////////////// void PandaNode:: remove_child(int n) { - CDW(CData) cdata(_cycler); + CDWriter cdata(_cycler); nassertv(n >= 0 && n < (int)cdata->_down.size()); PandaNode *child = cdata->_down[n].get_child(); - CDW(CData) cdata_child(child->_cycler); + CDWriter cdata_child(child->_cycler); cdata->_down.erase(cdata->_down.begin() + n); int num_erased = cdata_child->_up.erase(this); @@ -175,7 +186,7 @@ remove_child(int n) { //////////////////////////////////////////////////////////////////// bool PandaNode:: remove_child(PandaNode *child) { - CDW(CData) cdata_child(child->_cycler); + CDWriter cdata_child(child->_cycler); // First, look for and remove this node from the child's parent // list. @@ -185,7 +196,7 @@ remove_child(PandaNode *child) { return false; } - CDW(CData) cdata(_cycler); + CDWriter cdata(_cycler); // Now, look for and remove the child node from our down list. Down::iterator ci; @@ -208,11 +219,11 @@ remove_child(PandaNode *child) { //////////////////////////////////////////////////////////////////// void PandaNode:: remove_all_children() { - CDW(CData) cdata(_cycler); + CDWriter cdata(_cycler); Down::iterator ci; for (ci = cdata->_down.begin(); ci != cdata->_down.end(); ++ci) { PandaNode *child = (*ci).get_child(); - CDW(CData) child_cdata(child->_cycler); + CDWriter child_cdata(child->_cycler); child_cdata->_up.erase(this); } } @@ -235,13 +246,29 @@ output(ostream &out) const { void PandaNode:: write(ostream &out, int indent_level) const { indent(out, indent_level) << *this; - CDR(CData) cdata(_cycler); + CDReader cdata(_cycler); if (!cdata->_state_changes->is_empty()) { out << " (" << *cdata->_state_changes << ")"; } out << "\n"; } +//////////////////////////////////////////////////////////////////// +// Function: PandaNode::is_geom_node +// Access: Public, Virtual +// Description: A simple downcast check. Returns true if this kind +// of node happens to inherit from GeomNode, false +// otherwise. +// +// This is provided as a a faster alternative to calling +// is_of_type(GeomNode::get_class_type()), since this +// test is so important to rendering. +//////////////////////////////////////////////////////////////////// +bool PandaNode:: +is_geom_node() const { + return false; +} + //////////////////////////////////////////////////////////////////// // Function: PandaNode::register_with_read_factory // Access: Public, Static diff --git a/panda/src/pgraph/pandaNode.h b/panda/src/pgraph/pandaNode.h index b76292344b..45d951f67d 100644 --- a/panda/src/pgraph/pandaNode.h +++ b/panda/src/pgraph/pandaNode.h @@ -41,10 +41,10 @@ // is the base class of all specialized nodes, and also // serves as a generic node with no special properties. //////////////////////////////////////////////////////////////////// -class EXPCL_PANDA PandaNode : public TypedWritable, - public Namable, virtual public ReferenceCount { +class EXPCL_PANDA PandaNode : public TypedWritable, public Namable, + virtual public ReferenceCount { PUBLISHED: - INLINE PandaNode(const string &name); + PandaNode(const string &name); PandaNode(const PandaNode ©); void operator = (const PandaNode ©); virtual ~PandaNode(); @@ -75,6 +75,9 @@ PUBLISHED: virtual void output(ostream &out) const; virtual void write(ostream &out, int indent_level) const; +public: + virtual bool is_geom_node() const; + private: class EXPCL_PANDA DownConnection { public: @@ -114,6 +117,8 @@ private: }; PipelineCycler _cycler; + typedef CycleDataReader CDReader; + typedef CycleDataWriter CDWriter; public: // Use this interface when you want to walk through the list of @@ -122,14 +127,14 @@ public: // However, it does not protect you from self-modifying loops. class EXPCL_PANDA Children { public: - INLINE Children(const PipelineCycler &cycler); + INLINE Children(const CDReader &cdata); INLINE Children(const Children ©); INLINE int get_num_children() const; INLINE PandaNode *get_child(int n) const; private: - CDR(CData) _cdata; + CDReader _cdata; }; INLINE Children get_children() const; diff --git a/panda/src/pgraph/pgraph_composite1.cxx b/panda/src/pgraph/pgraph_composite1.cxx index 44ee9b7459..be9362eb84 100644 --- a/panda/src/pgraph/pgraph_composite1.cxx +++ b/panda/src/pgraph/pgraph_composite1.cxx @@ -1,6 +1,9 @@ -#include "colorAttrib.cxx" -#include "config_pgraph.cxx" -#include "cycleData.cxx" -#include "cycleDataReader.cxx" -#include "cycleDataWriter.cxx" -#include "pandaNode.cxx" +#include "colorAttrib.cxx" +#include "config_pgraph.cxx" +#include "cullHandler.cxx" +#include "qpcullTraverser.cxx" +#include "cycleData.cxx" +#include "cycleDataReader.cxx" +#include "cycleDataWriter.cxx" +#include "qpgeomNode.cxx" +#include "pandaNode.cxx" diff --git a/panda/src/pgraph/pgraph_composite2.cxx b/panda/src/pgraph/pgraph_composite2.cxx index eba2143101..8f652b82d5 100644 --- a/panda/src/pgraph/pgraph_composite2.cxx +++ b/panda/src/pgraph/pgraph_composite2.cxx @@ -1,8 +1,9 @@ -#include "pipeline.cxx" -#include "pipelineCycler.cxx" -#include "pipelineCyclerBase.cxx" -#include "renderAttrib.cxx" -#include "renderState.cxx" -#include "test_pgraph.cxx" -#include "textureAttrib.cxx" - +#include "pipeline.cxx" +#include "pipelineCycler.cxx" +#include "pipelineCyclerBase.cxx" +#include "renderAttrib.cxx" +#include "renderState.cxx" +#include "test_pgraph.cxx" +#include "textureAttrib.cxx" +#include "transformAttrib.cxx" + diff --git a/panda/src/pgraph/qpcullTraverser.I b/panda/src/pgraph/qpcullTraverser.I new file mode 100644 index 0000000000..3cb2b6a504 --- /dev/null +++ b/panda/src/pgraph/qpcullTraverser.I @@ -0,0 +1,17 @@ +// Filename: qpcullTraverser.I +// Created by: drose (23Feb02) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved +// +// All use of this software is subject to the terms of the Panda 3d +// Software license. You should have received a copy of this license +// along with this source code; you will also find a current copy of +// the license at http://www.panda3d.org/license.txt . +// +// To contact the maintainers of this program write to +// panda3d@yahoogroups.com . +// +//////////////////////////////////////////////////////////////////// diff --git a/panda/src/pgraph/qpcullTraverser.cxx b/panda/src/pgraph/qpcullTraverser.cxx new file mode 100644 index 0000000000..55e37db904 --- /dev/null +++ b/panda/src/pgraph/qpcullTraverser.cxx @@ -0,0 +1,117 @@ +// Filename: qpcullTraverser.cxx +// Created by: drose (23Feb02) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved +// +// All use of this software is subject to the terms of the Panda 3d +// Software license. You should have received a copy of this license +// along with this source code; you will also find a current copy of +// the license at http://www.panda3d.org/license.txt . +// +// To contact the maintainers of this program write to +// panda3d@yahoogroups.com . +// +//////////////////////////////////////////////////////////////////// + +#include "qpcullTraverser.h" +#include "renderState.h" +#include "cullHandler.h" +#include "dcast.h" +#include "qpgeomNode.h" + +//////////////////////////////////////////////////////////////////// +// Function: qpCullTraverser::Constructor +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +qpCullTraverser:: +qpCullTraverser() { + _initial_state = RenderState::make_empty(); + _world_transform = DCAST(TransformAttrib, TransformAttrib::make_identity()); + _cull_handler = (CullHandler *)NULL; +} + +//////////////////////////////////////////////////////////////////// +// Function: qpCullTraverser::set_initial_state +// Access: Public +// Description: Sets the initial RenderState at the top of the scene +// graph we are traversing. If this is not set, the +// default is the empty state. +//////////////////////////////////////////////////////////////////// +void qpCullTraverser:: +set_initial_state(const RenderState *initial_state) { + _initial_state = initial_state; +} + +//////////////////////////////////////////////////////////////////// +// Function: qpCullTraverser::set_world_transform +// Access: Public +// Description: Specifies the net inverse transform of the camera +// viewing the scene. Normally, this is the same as the +// transform specified in the initial state, but it +// might be different if we are culling a subgraph, +// for instance. +// +// This is used to evaluate camera-dependent attributes +// like billboards and LOD nodes. +//////////////////////////////////////////////////////////////////// +void qpCullTraverser:: +set_world_transform(const TransformAttrib *world_transform) { + _world_transform = world_transform; +} + +//////////////////////////////////////////////////////////////////// +// Function: qpCullTraverser::set_cull_handler +// Access: Public +// Description: Specifies the object that will receive the culled +// Geoms. This must be called before traverse(). +//////////////////////////////////////////////////////////////////// +void qpCullTraverser:: +set_cull_handler(CullHandler *cull_handler) { + _cull_handler = cull_handler; +} + +//////////////////////////////////////////////////////////////////// +// Function: qpCullTraverser::traverse +// Access: Public +// Description: Begins the traversal from the indicated node. +//////////////////////////////////////////////////////////////////// +void qpCullTraverser:: +traverse(PandaNode *root) { + nassertv(_cull_handler != (CullHandler *)NULL); + + r_traverse(root, _initial_state, 0); +} + +//////////////////////////////////////////////////////////////////// +// Function: qpCullTraverser::r_traverse +// Access: Private +// Description: The recursive traversal implementation. +//////////////////////////////////////////////////////////////////// +void qpCullTraverser:: +r_traverse(PandaNode *node, const RenderState *state, int flags) { + CPT(RenderState) next_state = state->compose(node->get_state()); + + if (node->is_geom_node()) { + qpGeomNode *geom_node; + DCAST_INTO_V(geom_node, node); + + int num_geoms = geom_node->get_num_geoms(); + for (int i = 0; i < num_geoms; i++) { + Geom *geom = geom_node->get_geom(i); + CPT(RenderState) geom_state = + next_state->compose(geom_node->get_geom_state(i)); + _cull_handler->found_geom(geom, geom_state); + } + } + + // Now visit all the node's children. + PandaNode::Children cr = node->get_children(); + int num_children = cr.get_num_children(); + for (int i = 0; i < num_children; i++) { + r_traverse(cr.get_child(i), next_state, flags); + } +} diff --git a/panda/src/pgraph/qpcullTraverser.h b/panda/src/pgraph/qpcullTraverser.h new file mode 100644 index 0000000000..42e2b30bbb --- /dev/null +++ b/panda/src/pgraph/qpcullTraverser.h @@ -0,0 +1,62 @@ +// Filename: qpcullTraverser.h +// Created by: drose (23Feb02) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved +// +// All use of this software is subject to the terms of the Panda 3d +// Software license. You should have received a copy of this license +// along with this source code; you will also find a current copy of +// the license at http://www.panda3d.org/license.txt . +// +// To contact the maintainers of this program write to +// panda3d@yahoogroups.com . +// +//////////////////////////////////////////////////////////////////// + +#ifndef qpCULLTRAVERSER_H +#define qpCULLTRAVERSER_H + +#include "pandabase.h" + +#include "renderState.h" +#include "transformAttrib.h" +#include "pointerTo.h" + +class PandaNode; +class CullHandler; + +//////////////////////////////////////////////////////////////////// +// Class : CullTraverser +// Description : This object performs a depth-first traversal of the +// scene graph, with optional view-frustum culling, +// collecting CullState and searching for GeomNodes. +// Each renderable Geom encountered is passed along with +// its associated RenderState to the CullHandler object. +//////////////////////////////////////////////////////////////////// +class EXPCL_PANDA qpCullTraverser { +public: + qpCullTraverser(); + + void set_initial_state(const RenderState *initial_state); + void set_world_transform(const TransformAttrib *world_transform); + void set_cull_handler(CullHandler *cull_handler); + + void traverse(PandaNode *root); + +private: + void r_traverse(PandaNode *node, const RenderState *state, int flags); + + CPT(RenderState) _initial_state; + CPT(TransformAttrib) _world_transform; + CullHandler *_cull_handler; +}; + +#include "qpcullTraverser.I" + +#endif + + + diff --git a/panda/src/pgraph/qpgeomNode.I b/panda/src/pgraph/qpgeomNode.I new file mode 100644 index 0000000000..f3b81f5339 --- /dev/null +++ b/panda/src/pgraph/qpgeomNode.I @@ -0,0 +1,140 @@ +// Filename: qpgeomNode.I +// Created by: drose (23Feb02) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved +// +// All use of this software is subject to the terms of the Panda 3d +// Software license. You should have received a copy of this license +// along with this source code; you will also find a current copy of +// the license at http://www.panda3d.org/license.txt . +// +// To contact the maintainers of this program write to +// panda3d@yahoogroups.com . +// +//////////////////////////////////////////////////////////////////// + + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomNode::GeomEntry::Constructor +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +INLINE qpGeomNode::GeomEntry:: +GeomEntry(Geom *geom, const RenderState *state) : + _geom(geom), + _state(state) +{ +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomNode::CData::Constructor +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +INLINE qpGeomNode::CData:: +CData() { +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomNode::get_num_geoms +// Access: Public +// Description: Returns the number of geoms in the node. +//////////////////////////////////////////////////////////////////// +INLINE int qpGeomNode:: +get_num_geoms() const { + CDReader cdata(_cycler); + return cdata->_geoms.size(); +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomNode::get_geom +// Access: Public +// Description: Returns the nth geom of the node. +//////////////////////////////////////////////////////////////////// +INLINE Geom *qpGeomNode:: +get_geom(int n) const { + CDReader cdata(_cycler); + nassertr(n >= 0 && n < (int)cdata->_geoms.size(), NULL); + return cdata->_geoms[n]._geom; +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomNode::get_geom_state +// Access: Public +// Description: Returns the RenderState associated with the nth geom +// of the node. This is just the RenderState directly +// associated with the Geom; the actual state in which +// the Geom is rendered will also be affected by +// RenderStates that appear on the scene graph in nodes +// above this GeomNode. +//////////////////////////////////////////////////////////////////// +INLINE const RenderState *qpGeomNode:: +get_geom_state(int n) const { + CDReader cdata(_cycler); + nassertr(n >= 0 && n < (int)cdata->_geoms.size(), NULL); + return cdata->_geoms[n]._state; +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomNode::set_state +// Access: Public +// Description: Changes the RenderState associated with the nth geom +// of the node. This is just the RenderState directly +// associated with the Geom; the actual state in which +// the Geom is rendered will also be affected by +// RenderStates that appear on the scene graph in nodes +// above this GeomNode. +//////////////////////////////////////////////////////////////////// +INLINE void qpGeomNode:: +set_state(int n, const RenderState *state) { + CDWriter cdata(_cycler); + nassertv(n >= 0 && n < (int)cdata->_geoms.size()); + cdata->_geoms[n]._state = state; +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomNode::add_geom +// Access: Published +// Description: Adds a new Geom to the node. The geom is given the +// indicated state (which may be +// RenderState::make_empty(), to completely inherit its +// state from the scene graph). +// +// The return value is the index number of the new Geom. +//////////////////////////////////////////////////////////////////// +INLINE int qpGeomNode:: +add_geom(Geom *geom, const RenderState *state) { + nassertr(geom != (Geom *)NULL, -1); + nassertr(state != (RenderState *)NULL, -1); + CDWriter cdata(_cycler); + + cdata->_geoms.push_back(GeomEntry(geom, state)); + return cdata->_geoms.size() - 1; +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomNode::remove_geom +// Access: Published +// Description: Removes the nth geom from the node. +//////////////////////////////////////////////////////////////////// +INLINE void qpGeomNode:: +remove_geom(int n) { + CDWriter cdata(_cycler); + nassertv(n >= 0 && n < (int)cdata->_geoms.size()); + + cdata->_geoms.erase(cdata->_geoms.begin() + n); +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomNode::remove_all_geoms +// Access: Published +// Description: Removes all the geoms from the node at once. +//////////////////////////////////////////////////////////////////// +INLINE void qpGeomNode:: +remove_all_geoms() { + CDWriter cdata(_cycler); + cdata->_geoms.clear(); +} diff --git a/panda/src/pgraph/qpgeomNode.cxx b/panda/src/pgraph/qpgeomNode.cxx new file mode 100644 index 0000000000..4dea7a5a07 --- /dev/null +++ b/panda/src/pgraph/qpgeomNode.cxx @@ -0,0 +1,214 @@ +// Filename: qpgeomNode.cxx +// Created by: drose (23Feb02) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved +// +// All use of this software is subject to the terms of the Panda 3d +// Software license. You should have received a copy of this license +// along with this source code; you will also find a current copy of +// the license at http://www.panda3d.org/license.txt . +// +// To contact the maintainers of this program write to +// panda3d@yahoogroups.com . +// +//////////////////////////////////////////////////////////////////// + +#include "qpgeomNode.h" +#include "bamReader.h" +#include "bamWriter.h" +#include "datagram.h" +#include "datagramIterator.h" +#include "indent.h" + +TypeHandle qpGeomNode::_type_handle; + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomNode::CData::Copy Constructor +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +qpGeomNode::CData:: +CData(const qpGeomNode::CData ©) : + _geoms(copy._geoms) +{ +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomNode::CData::make_copy +// Access: Public, Virtual +// Description: +//////////////////////////////////////////////////////////////////// +CycleData *qpGeomNode::CData:: +make_copy() const { + return new CData(*this); +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomNode::Constructor +// Access: Published +// Description: +//////////////////////////////////////////////////////////////////// +qpGeomNode:: +qpGeomNode(const string &name) : + PandaNode(name) +{ +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomNode::Copy Constructor +// Access: Published +// Description: +//////////////////////////////////////////////////////////////////// +qpGeomNode:: +qpGeomNode(const qpGeomNode ©) : + PandaNode(copy) +{ + // Copy the other node's _geoms. + CDReader copy_cdata(copy._cycler); + CDWriter cdata(_cycler); + cdata->_geoms = copy_cdata->_geoms; +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomNode::Copy Assignment Operator +// Access: Published +// Description: +//////////////////////////////////////////////////////////////////// +void qpGeomNode:: +operator = (const qpGeomNode ©) { + PandaNode::operator = (copy); + + // Copy the other node's _geoms. + CDReader copy_cdata(copy._cycler); + CDWriter cdata(_cycler); + cdata->_geoms = copy_cdata->_geoms; +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomNode::Destructor +// Access: Published, Virtual +// Description: +//////////////////////////////////////////////////////////////////// +qpGeomNode:: +~qpGeomNode() { +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomNode::write_verbose +// Access: Published +// Description: Writes a detailed description of all the Geoms in the +// node. +//////////////////////////////////////////////////////////////////// +void qpGeomNode:: +write_verbose(ostream &out, int indent_level) const { + CDReader cdata(_cycler); + PandaNode::write(out, indent_level); + Geoms::const_iterator gi; + for (gi = cdata->_geoms.begin(); gi != cdata->_geoms.end(); ++gi) { + const GeomEntry &entry = (*gi); + indent(out, indent_level + 2) + << *entry._geom << " (" << *entry._state << ")\n"; + entry._geom->write_verbose(out, indent_level + 4); + } +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomNode::output +// Access: Public, Virtual +// Description: +//////////////////////////////////////////////////////////////////// +void qpGeomNode:: +output(ostream &out) const { + PandaNode::output(out); + out << " (" << get_num_geoms() << " geoms)"; +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomNode::write +// Access: Public, Virtual +// Description: +//////////////////////////////////////////////////////////////////// +void qpGeomNode:: +write(ostream &out, int indent_level) const { + CDReader cdata(_cycler); + PandaNode::write(out, indent_level); + Geoms::const_iterator gi; + for (gi = cdata->_geoms.begin(); gi != cdata->_geoms.end(); ++gi) { + const GeomEntry &entry = (*gi); + indent(out, indent_level + 2) + << *entry._geom << " (" << *entry._state << ")\n"; + } +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomNode::is_geom_node +// Access: Public, Virtual +// Description: A simple downcast check. Returns true if this kind +// of node happens to inherit from GeomNode, false +// otherwise. +// +// This is provided as a a faster alternative to calling +// is_of_type(GeomNode::get_class_type()), since this +// test is so important to rendering. +//////////////////////////////////////////////////////////////////// +bool qpGeomNode:: +is_geom_node() const { + return true; +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomNode::register_with_read_factory +// Access: Public, Static +// Description: Tells the BamReader how to create objects of type +// qpGeomNode. +//////////////////////////////////////////////////////////////////// +void qpGeomNode:: +register_with_read_factory() { + BamReader::get_factory()->register_factory(get_class_type(), make_from_bam); +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomNode::write_datagram +// Access: Public, Virtual +// Description: Writes the contents of this object to the datagram +// for shipping out to a Bam file. +//////////////////////////////////////////////////////////////////// +void qpGeomNode:: +write_datagram(BamWriter *manager, Datagram &dg) { + PandaNode::write_datagram(manager, dg); +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomNode::make_from_bam +// Access: Protected, Static +// Description: This function is called by the BamReader's factory +// when a new object of type qpGeomNode is encountered +// in the Bam file. It should create the qpGeomNode +// and extract its information from the file. +//////////////////////////////////////////////////////////////////// +TypedWritable *qpGeomNode:: +make_from_bam(const FactoryParams ¶ms) { + qpGeomNode *node = new qpGeomNode(""); + DatagramIterator scan; + BamReader *manager; + + parse_params(params, scan, manager); + node->fillin(scan, manager); + + return node; +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomNode::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 qpGeomNode. +//////////////////////////////////////////////////////////////////// +void qpGeomNode:: +fillin(DatagramIterator &scan, BamReader *manager) { + PandaNode::fillin(scan, manager); +} diff --git a/panda/src/pgraph/qpgeomNode.h b/panda/src/pgraph/qpgeomNode.h new file mode 100644 index 0000000000..e97daa663c --- /dev/null +++ b/panda/src/pgraph/qpgeomNode.h @@ -0,0 +1,118 @@ +// Filename: qpgeomNode.h +// Created by: drose (22Feb02) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved +// +// All use of this software is subject to the terms of the Panda 3d +// Software license. You should have received a copy of this license +// along with this source code; you will also find a current copy of +// the license at http://www.panda3d.org/license.txt . +// +// To contact the maintainers of this program write to +// panda3d@yahoogroups.com . +// +//////////////////////////////////////////////////////////////////// + +#ifndef qpGEOMNODE_H +#define qpGEOMNODE_H + +#include "pandabase.h" + +#include "pandaNode.h" +#include "pointerToArray.h" +#include "geom.h" +#include "pipelineCycler.h" +#include "cycleData.h" +#include "pvector.h" + +//////////////////////////////////////////////////////////////////// +// Class : GeomNode +// Description : A node that holds Geom objects, renderable pieces of +// geometry. This is the primary kind of leaf node in +// the scene graph; almost all visible objects will be +// contained in a GeomNode somewhere. +//////////////////////////////////////////////////////////////////// +class EXPCL_PANDA qpGeomNode : public PandaNode { +PUBLISHED: + qpGeomNode(const string &name); + +public: + qpGeomNode(const qpGeomNode ©); + void operator = (const qpGeomNode ©); + virtual ~qpGeomNode(); + +PUBLISHED: + INLINE int get_num_geoms() const; + INLINE Geom *get_geom(int n) const; + INLINE const RenderState *get_geom_state(int n) const; + INLINE void set_state(int n, const RenderState *state); + + INLINE int add_geom(Geom *geom, const RenderState *state); + INLINE void remove_geom(int n); + INLINE void remove_all_geoms(); + + void write_verbose(ostream &out, int indent_level) const; + +public: + virtual void output(ostream &out) const; + virtual void write(ostream &out, int indent_level) const; + + virtual bool is_geom_node() const; + +private: + class GeomEntry { + public: + INLINE GeomEntry(Geom *geom, const RenderState *state); + PT(Geom) _geom; + CPT(RenderState) _state; + }; + typedef pvector Geoms; + + // This is the data that must be cycled between pipeline stages. + class EXPCL_PANDA CData : public CycleData { + public: + INLINE CData(); + CData(const CData ©); + virtual CycleData *make_copy() const; + + Geoms _geoms; + }; + + PipelineCycler _cycler; + typedef CycleDataReader CDReader; + typedef CycleDataWriter CDWriter; + +public: + static void register_with_read_factory(); + virtual void write_datagram(BamWriter *manager, Datagram &dg); + +protected: + static TypedWritable *make_from_bam(const FactoryParams ¶ms); + void fillin(DatagramIterator &scan, BamReader *manager); + +public: + static TypeHandle get_class_type() { + return _type_handle; + } + static void init_type() { + PandaNode::init_type(); + register_type(_type_handle, "qpGeomNode", + PandaNode::get_class_type()); + } + virtual TypeHandle get_type() const { + return get_class_type(); + } + virtual TypeHandle force_init_type() {init_type(); return get_class_type();} + +private: + static TypeHandle _type_handle; + + friend class PandaNode::Children; +}; + +#include "qpgeomNode.I" + +#endif diff --git a/panda/src/pgraph/renderAttrib.cxx b/panda/src/pgraph/renderAttrib.cxx index 4bd8a266d4..e4b7bb9ba5 100644 --- a/panda/src/pgraph/renderAttrib.cxx +++ b/panda/src/pgraph/renderAttrib.cxx @@ -160,7 +160,7 @@ compare_to_impl(const RenderAttrib *other) const { // RenderAttrib (that is, a subsequent RenderAttrib // completely replaces the preceding one). On the other // hand, some kinds of RenderAttrib (for instance, -// TextureTransform) might combine in meaningful ways. +// TransformAttrib) might combine in meaningful ways. //////////////////////////////////////////////////////////////////// CPT(RenderAttrib) RenderAttrib:: compose_impl(const RenderAttrib *other) const { @@ -238,3 +238,14 @@ new_from_bam(RenderAttrib *attrib, BamReader *manager) { // reader expects that. return (RenderAttrib *)pointer.p(); } + +//////////////////////////////////////////////////////////////////// +// Function: RenderAttrib::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 RenderAttrib. +//////////////////////////////////////////////////////////////////// +void RenderAttrib:: +fillin(DatagramIterator &scan, BamReader *manager) { +} diff --git a/panda/src/pgraph/renderAttrib.h b/panda/src/pgraph/renderAttrib.h index 5eab65509d..6686783938 100644 --- a/panda/src/pgraph/renderAttrib.h +++ b/panda/src/pgraph/renderAttrib.h @@ -80,6 +80,7 @@ public: protected: static TypedWritable *new_from_bam(RenderAttrib *attrib, BamReader *manager); + void fillin(DatagramIterator &scan, BamReader *manager); public: static TypeHandle get_class_type() { diff --git a/panda/src/pgraph/renderState.cxx b/panda/src/pgraph/renderState.cxx index 5828e0f1d8..c88ade0e5e 100644 --- a/panda/src/pgraph/renderState.cxx +++ b/panda/src/pgraph/renderState.cxx @@ -272,6 +272,14 @@ compose(const RenderState *other) const { cerr << "composing " << *this << " with " << *other << "\n"; + // We handle empty state (identity) as a trivial special case. + if (is_empty()) { + return other; + } + if (other->is_empty()) { + return this; + } + if (other == this) { // compose(this) has to be handled as a special case, because the // caching problem is so different. diff --git a/panda/src/pgraph/test_pgraph.cxx b/panda/src/pgraph/test_pgraph.cxx index fd9d818679..6b7d8ec3ef 100644 --- a/panda/src/pgraph/test_pgraph.cxx +++ b/panda/src/pgraph/test_pgraph.cxx @@ -19,7 +19,13 @@ #include "pandaNode.h" #include "textureAttrib.h" #include "colorAttrib.h" +#include "transformAttrib.h" #include "texture.h" +#include "qpgeomNode.h" +#include "geomTristrip.h" +#include "geomTrifan.h" +#include "qpcullTraverser.h" +#include "cullHandler.h" void list_hierarchy(PandaNode *node, int indent_level) { @@ -51,32 +57,31 @@ main(int argc, char *argv[]) { PandaNode *a1 = new PandaNode("a1"); a->add_child(a1); + qpGeomNode *g1 = new qpGeomNode("g1"); + a1->add_child(g1); + + Geom *geom1 = new GeomTristrip; + g1->add_geom(geom1, RenderState::make_empty()); + Geom *geom2 = new GeomTrifan; + g1->add_geom(geom2, b->get_state()); + + qpGeomNode *g2 = new qpGeomNode("g2"); + b->add_child(g2); + g2->add_geom(geom1, b->get_state()); + g2->set_attrib(TransformAttrib::make_mat(LMatrix4f::translate_mat(10, 0, 0))); + cerr << "\n"; list_hierarchy(root, 0); - cerr << "\nroot's attribs:\n"; - root->get_state()->write(cerr, 0); + qpCullTraverser trav; + CullHandler cull_handler; + trav.set_cull_handler(&cull_handler); + cerr << "\n"; + trav.traverse(root); - cerr << "\na's attribs:\n"; - a->get_state()->write(cerr, 0); - - cerr << "\nroot compose a:\n"; - CPT(RenderState) result1 = root->get_state()->compose(a->get_state()); - result1->write(cerr, 0); - - // a->clear_state(); - - cerr << "\nroot compose root:\n"; - CPT(RenderState) result2 = root->get_state()->compose(root->get_state()); - result2->write(cerr, 0); - - cerr << "\nroot compose a:\n"; - CPT(RenderState) result3 = root->get_state()->compose(a->get_state()); - result3->write(cerr, 0); - - cerr << "\na compose root:\n"; - CPT(RenderState) result4 = a->get_state()->compose(root->get_state()); - result4->write(cerr, 0); + cerr << "\n"; + trav.traverse(root); + cerr << "\n"; return 0; } diff --git a/panda/src/pgraph/textureAttrib.cxx b/panda/src/pgraph/textureAttrib.cxx index b60a71a626..667ad7b2e1 100644 --- a/panda/src/pgraph/textureAttrib.cxx +++ b/panda/src/pgraph/textureAttrib.cxx @@ -17,6 +17,10 @@ //////////////////////////////////////////////////////////////////// #include "textureAttrib.h" +#include "bamReader.h" +#include "bamWriter.h" +#include "datagram.h" +#include "datagramIterator.h" TypeHandle TextureAttrib::_type_handle; @@ -97,3 +101,57 @@ RenderAttrib *TextureAttrib:: make_default_impl() const { return new TextureAttrib; } + +//////////////////////////////////////////////////////////////////// +// Function: TextureAttrib::register_with_read_factory +// Access: Public, Static +// Description: Tells the BamReader how to create objects of type +// TextureAttrib. +//////////////////////////////////////////////////////////////////// +void TextureAttrib:: +register_with_read_factory() { + BamReader::get_factory()->register_factory(get_class_type(), make_from_bam); +} + +//////////////////////////////////////////////////////////////////// +// Function: TextureAttrib::write_datagram +// Access: Public, Virtual +// Description: Writes the contents of this object to the datagram +// for shipping out to a Bam file. +//////////////////////////////////////////////////////////////////// +void TextureAttrib:: +write_datagram(BamWriter *manager, Datagram &dg) { + RenderAttrib::write_datagram(manager, dg); +} + +//////////////////////////////////////////////////////////////////// +// Function: TextureAttrib::make_from_bam +// Access: Protected, Static +// Description: This function is called by the BamReader's factory +// when a new object of type TextureAttrib is encountered +// in the Bam file. It should create the TextureAttrib +// and extract its information from the file. +//////////////////////////////////////////////////////////////////// +TypedWritable *TextureAttrib:: +make_from_bam(const FactoryParams ¶ms) { + TextureAttrib *attrib = new TextureAttrib; + DatagramIterator scan; + BamReader *manager; + + parse_params(params, scan, manager); + attrib->fillin(scan, manager); + + return new_from_bam(attrib, manager); +} + +//////////////////////////////////////////////////////////////////// +// Function: TextureAttrib::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 TextureAttrib. +//////////////////////////////////////////////////////////////////// +void TextureAttrib:: +fillin(DatagramIterator &scan, BamReader *manager) { + RenderAttrib::fillin(scan, manager); +} diff --git a/panda/src/pgraph/textureAttrib.h b/panda/src/pgraph/textureAttrib.h index ada6cab259..f09214d097 100644 --- a/panda/src/pgraph/textureAttrib.h +++ b/panda/src/pgraph/textureAttrib.h @@ -50,15 +50,23 @@ protected: private: PT(Texture) _texture; + +public: + static void register_with_read_factory(); + virtual void write_datagram(BamWriter *manager, Datagram &dg); + +protected: + static TypedWritable *make_from_bam(const FactoryParams ¶ms); + void fillin(DatagramIterator &scan, BamReader *manager); public: static TypeHandle get_class_type() { return _type_handle; } static void init_type() { - TypedWritableReferenceCount::init_type(); + RenderAttrib::init_type(); register_type(_type_handle, "TextureAttrib", - TypedWritableReferenceCount::get_class_type()); + RenderAttrib::get_class_type()); } virtual TypeHandle get_type() const { return get_class_type(); diff --git a/panda/src/pgraph/transformAttrib.I b/panda/src/pgraph/transformAttrib.I new file mode 100644 index 0000000000..fd1581cfc3 --- /dev/null +++ b/panda/src/pgraph/transformAttrib.I @@ -0,0 +1,172 @@ +// Filename: transformAttrib.I +// Created by: drose (23Feb02) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved +// +// All use of this software is subject to the terms of the Panda 3d +// Software license. You should have received a copy of this license +// along with this source code; you will also find a current copy of +// the license at http://www.panda3d.org/license.txt . +// +// To contact the maintainers of this program write to +// panda3d@yahoogroups.com . +// +//////////////////////////////////////////////////////////////////// + + +//////////////////////////////////////////////////////////////////// +// Function: TransformAttrib::Constructor +// Access: Private +// Description: Use TransformAttrib::make() to construct a new +// TransformAttrib object. +//////////////////////////////////////////////////////////////////// +INLINE TransformAttrib:: +TransformAttrib() { + _flags = F_is_identity | F_singular_known; +} + +//////////////////////////////////////////////////////////////////// +// Function: TransformAttrib::is_identity +// Access: Published +// Description: Returns true if the transform represents the identity +// matrix, false otherwise. +//////////////////////////////////////////////////////////////////// +INLINE bool TransformAttrib:: +is_identity() const { + return ((_flags & F_is_identity) != 0); +} + +//////////////////////////////////////////////////////////////////// +// Function: TransformAttrib::is_singular +// Access: Published +// Description: Returns true if the transform represents a singular +// transform (that is, it has a zero scale, and it +// cannot be inverted), or false otherwise. +//////////////////////////////////////////////////////////////////// +INLINE bool TransformAttrib:: +is_singular() const { + check_singular(); + return ((_flags & F_is_singular) != 0); +} + +//////////////////////////////////////////////////////////////////// +// Function: TransformAttrib::has_components +// Access: Published +// Description: Returns true if the transform can be described by +// separate pos, hpr, and scale components. Most +// transforms we use in everyday life can be so +// described, but some kinds of transforms (for +// instance, those involving a skew) cannot. +// +// This is not related to whether the transform was +// originally described componentwise. Even a transform +// that was constructed with a 4x4 may return true here +// if the matrix is a simple affine matrix with no skew. +// +// If this returns true, you may safely call get_pos(), +// etc., to retrieve the components. +//////////////////////////////////////////////////////////////////// +INLINE bool TransformAttrib:: +has_components() const { + check_components(); + return ((_flags & F_has_components) != 0); +} + +//////////////////////////////////////////////////////////////////// +// Function: TransformAttrib::get_pos +// Access: Published +// Description: Returns the pos component of the transform. It is an +// error to call this if has_components() returned +// false. +//////////////////////////////////////////////////////////////////// +INLINE const LVecBase3f &TransformAttrib:: +get_pos() const { + check_components(); + nassertr(has_components(), _pos); + return _pos; +} + +//////////////////////////////////////////////////////////////////// +// Function: TransformAttrib::get_hpr +// Access: Published +// Description: Returns the hpr component of the transform. It is an +// error to call this if has_components() returned +// false. +//////////////////////////////////////////////////////////////////// +INLINE const LVecBase3f &TransformAttrib:: +get_hpr() const { + check_components(); + nassertr(has_components(), _hpr); + return _hpr; +} + +//////////////////////////////////////////////////////////////////// +// Function: TransformAttrib::get_scale +// Access: Published +// Description: Returns the scale component of the transform. It is an +// error to call this if has_components() returned +// false. +//////////////////////////////////////////////////////////////////// +INLINE const LVecBase3f &TransformAttrib:: +get_scale() const { + check_components(); + nassertr(has_components(), _scale); + return _scale; +} + +//////////////////////////////////////////////////////////////////// +// Function: TransformAttrib::get_mat +// Access: Published +// Description: Returns the matrix that describes the transform. +//////////////////////////////////////////////////////////////////// +INLINE const LMatrix4f &TransformAttrib:: +get_mat() const { + check_mat(); + return _mat; +} + +//////////////////////////////////////////////////////////////////// +// Function: TransformAttrib::check_singular +// Access: Private +// Description: Ensures that we know whether the matrix is singular. +//////////////////////////////////////////////////////////////////// +INLINE void TransformAttrib:: +check_singular() const { + // This pretends to be a const function, even though it's not, + // because it only updates a transparent cache value. + if ((_flags & F_singular_known) == 0) { + ((TransformAttrib *)this)->calc_singular(); + } +} + +//////////////////////////////////////////////////////////////////// +// Function: TransformAttrib::check_components +// Access: Private +// Description: Ensures that we know the components of the transform +// (or that we know they cannot be derived). +//////////////////////////////////////////////////////////////////// +INLINE void TransformAttrib:: +check_components() const { + // This pretends to be a const function, even though it's not, + // because it only updates a transparent cache value. + if ((_flags & F_components_known) == 0) { + ((TransformAttrib *)this)->calc_components(); + } +} + +//////////////////////////////////////////////////////////////////// +// Function: TransformAttrib::check_mat +// Access: Private +// Description: Ensures that we know the overall matrix. +//////////////////////////////////////////////////////////////////// +INLINE void TransformAttrib:: +check_mat() const { + // This pretends to be a const function, even though it's not, + // because it only updates a transparent cache value. + if ((_flags & F_mat_known) == 0) { + ((TransformAttrib *)this)->calc_mat(); + } +} diff --git a/panda/src/pgraph/transformAttrib.cxx b/panda/src/pgraph/transformAttrib.cxx new file mode 100644 index 0000000000..e15cc7b3a2 --- /dev/null +++ b/panda/src/pgraph/transformAttrib.cxx @@ -0,0 +1,308 @@ +// Filename: transformAttrib.cxx +// Created by: drose (23Feb02) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved +// +// All use of this software is subject to the terms of the Panda 3d +// Software license. You should have received a copy of this license +// along with this source code; you will also find a current copy of +// the license at http://www.panda3d.org/license.txt . +// +// To contact the maintainers of this program write to +// panda3d@yahoogroups.com . +// +//////////////////////////////////////////////////////////////////// + +#include "transformAttrib.h" +#include "bamReader.h" +#include "bamWriter.h" +#include "datagram.h" +#include "datagramIterator.h" +#include "compose_matrix.h" + +TypeHandle TransformAttrib::_type_handle; + +//////////////////////////////////////////////////////////////////// +// Function: TransformAttrib::make_identity +// Access: Published, Static +// Description: Constructs an identity transform. +//////////////////////////////////////////////////////////////////// +CPT(RenderAttrib) TransformAttrib:: +make_identity() { + TransformAttrib *attrib = new TransformAttrib; + return return_new(attrib); +} + +//////////////////////////////////////////////////////////////////// +// Function: TransformAttrib::make_components +// Access: Published, Static +// Description: Makes a new TransformAttrib with the specified +// components. +//////////////////////////////////////////////////////////////////// +CPT(RenderAttrib) TransformAttrib:: +make_components(const LVecBase3f &pos, const LVecBase3f &hpr, + const LVecBase3f &scale) { + // Make a special-case check for the identity transform. + if (pos == LVecBase3f(0.0f, 0.0f, 0.0f) && + hpr == LVecBase3f(0.0f, 0.0f, 0.0f) && + scale == LVecBase3f(1.0f, 1.0f, 1.0f)) { + return make_identity(); + } + + TransformAttrib *attrib = new TransformAttrib; + attrib->_pos = pos; + attrib->_hpr = hpr; + attrib->_scale = scale; + attrib->_flags = F_components_given | F_components_known | F_has_components; + return return_new(attrib); +} + +//////////////////////////////////////////////////////////////////// +// Function: TransformAttrib::make_components +// Access: Published, Static +// Description: Makes a new TransformAttrib with the specified +// transformation matrix. +//////////////////////////////////////////////////////////////////// +CPT(RenderAttrib) TransformAttrib:: +make_mat(const LMatrix4f &mat) { + // Make a special-case check for the identity matrix. + if (mat == LMatrix4f::ident_mat()) { + return make_identity(); + } + + TransformAttrib *attrib = new TransformAttrib; + attrib->_mat = mat; + attrib->_flags = F_mat_known; + return return_new(attrib); +} + +//////////////////////////////////////////////////////////////////// +// Function: TransformAttrib::output +// Access: Public, Virtual +// Description: +//////////////////////////////////////////////////////////////////// +void TransformAttrib:: +output(ostream &out) const { + out << get_type() << ":"; + if (is_identity()) { + out << "(identity)"; + + } else if (has_components()) { + out << "("; + if (get_pos() != LVecBase3f(0.0f, 0.0f, 0.0f)) { + out << "pos " << get_pos(); + } + if (get_hpr() != LVecBase3f(0.0f, 0.0f, 0.0f)) { + out << "hpr " << get_hpr(); + } + if (get_scale() != LVecBase3f(1.0f, 1.0f, 1.0f)) { + out << "scale " << get_scale(); + } + out << ")"; + + } else { + out << get_mat(); + } +} + +//////////////////////////////////////////////////////////////////// +// Function: TransformAttrib::compare_to_impl +// Access: Protected, Virtual +// Description: Intended to be overridden by derived TransformAttrib +// types to return a unique number indicating whether +// this TransformAttrib is equivalent to the other one. +// +// This should return 0 if the two TransformAttrib objects +// are equivalent, a number less than zero if this one +// should be sorted before the other one, and a number +// greater than zero otherwise. +// +// This will only be called with two TransformAttrib +// objects whose get_type() functions return the same. +//////////////////////////////////////////////////////////////////// +int TransformAttrib:: +compare_to_impl(const RenderAttrib *other) const { + const TransformAttrib *ta; + DCAST_INTO_R(ta, other, 0); + + if (is_identity() != ta->is_identity()) { + return is_identity() < ta->is_identity(); + } + if (is_identity()) { + // All identity transforms are equivalent to each other. + return 0; + } + + bool components_given = (_flags & F_components_given) != 0; + bool ta_components_given = (ta->_flags & F_components_given) != 0; + if (components_given != ta_components_given) { + return components_given < ta_components_given; + } + if (components_given) { + // If the transform was specified componentwise, compare them + // componentwise. + int c = _pos.compare_to(ta->_pos); + if (c != 0) { + return c; + } + c = _hpr.compare_to(ta->_hpr); + if (c != 0) { + return c; + } + c = _scale.compare_to(ta->_hpr); + return c; + + } + + // Otherwise, compare the matrices. + return get_mat().compare_to(ta->get_mat()); +} + +//////////////////////////////////////////////////////////////////// +// Function: TransformAttrib::compose_impl +// Access: Protected, Virtual +// Description: Intended to be overridden by derived RenderAttrib +// types to specify how two consecutive RenderAttrib +// objects of the same type interact. +//////////////////////////////////////////////////////////////////// +CPT(RenderAttrib) TransformAttrib:: +compose_impl(const RenderAttrib *other) const { + const TransformAttrib *ta; + DCAST_INTO_R(ta, other, other); + + // Identity times anything, duh. + if (is_identity()) { + return ta; + } else if (ta->is_identity()) { + return this; + } + + // Perhaps we should be smarter here if both transforms are + // componentwise, and multiply them componentwise. + LMatrix4f new_mat = get_mat() * ta->get_mat(); + return make_mat(new_mat); +} + +//////////////////////////////////////////////////////////////////// +// Function: TransformAttrib::make_default_impl +// Access: Protected, Virtual +// Description: Intended to be overridden by derived TransformAttrib +// types to specify what the default property for a +// TransformAttrib of this type should be. +// +// This should return a newly-allocated TransformAttrib of +// the same type that corresponds to whatever the +// standard default for this kind of TransformAttrib is. +//////////////////////////////////////////////////////////////////// +RenderAttrib *TransformAttrib:: +make_default_impl() const { + return new TransformAttrib; +} + +//////////////////////////////////////////////////////////////////// +// Function: TransformAttrib::calc_singular +// Access: Private +// Description: Determines whether the transform is singular (i.e. it +// scales to zero, and has no inverse). +//////////////////////////////////////////////////////////////////// +void TransformAttrib:: +calc_singular() { + bool singular = false; + + if (has_components()) { + // The matrix is singular if any component of its scale is 0. + singular = (_scale[0] == 0.0f || _scale[1] == 0.0f || _scale[2] == 0.0f); + } else { + // The matrix is singular if its determinant is zero. + const LMatrix4f &mat = get_mat(); + singular = (mat.get_upper_3().determinant() == 0.0f); + } + + if (singular) { + _flags |= F_is_singular; + } + _flags |= F_singular_known; +} + +//////////////////////////////////////////////////////////////////// +// Function: TransformAttrib::calc_components +// Access: Private +// Description: Derives the components from the matrix, if possible. +//////////////////////////////////////////////////////////////////// +void TransformAttrib:: +calc_components() { + bool possible = decompose_matrix(get_mat(), _scale, _hpr, _pos); + if (possible) { + // Some matrices can't be decomposed into scale, hpr, pos. + _flags |= F_has_components; + } + _flags |= F_components_known; +} + +//////////////////////////////////////////////////////////////////// +// Function: TransformAttrib::calc_mat +// Access: Private +// Description: Computes the matrix from the components. +//////////////////////////////////////////////////////////////////// +void TransformAttrib:: +calc_mat() { + compose_matrix(_mat, _scale, _hpr, _pos); + _flags |= F_mat_known; +} + +//////////////////////////////////////////////////////////////////// +// Function: TransformAttrib::register_with_read_factory +// Access: Public, Static +// Description: Tells the BamReader how to create objects of type +// TransformAttrib. +//////////////////////////////////////////////////////////////////// +void TransformAttrib:: +register_with_read_factory() { + BamReader::get_factory()->register_factory(get_class_type(), make_from_bam); +} + +//////////////////////////////////////////////////////////////////// +// Function: TransformAttrib::write_datagram +// Access: Public, Virtual +// Description: Writes the contents of this object to the datagram +// for shipping out to a Bam file. +//////////////////////////////////////////////////////////////////// +void TransformAttrib:: +write_datagram(BamWriter *manager, Datagram &dg) { + RenderAttrib::write_datagram(manager, dg); +} + +//////////////////////////////////////////////////////////////////// +// Function: TransformAttrib::make_from_bam +// Access: Protected, Static +// Description: This function is called by the BamReader's factory +// when a new object of type TransformAttrib is encountered +// in the Bam file. It should create the TransformAttrib +// and extract its information from the file. +//////////////////////////////////////////////////////////////////// +TypedWritable *TransformAttrib:: +make_from_bam(const FactoryParams ¶ms) { + TransformAttrib *attrib = new TransformAttrib; + DatagramIterator scan; + BamReader *manager; + + parse_params(params, scan, manager); + attrib->fillin(scan, manager); + + return new_from_bam(attrib, manager); +} + +//////////////////////////////////////////////////////////////////// +// Function: TransformAttrib::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 TransformAttrib. +//////////////////////////////////////////////////////////////////// +void TransformAttrib:: +fillin(DatagramIterator &scan, BamReader *manager) { + RenderAttrib::fillin(scan, manager); +} diff --git a/panda/src/pgraph/transformAttrib.h b/panda/src/pgraph/transformAttrib.h new file mode 100644 index 0000000000..e3a4fb95ef --- /dev/null +++ b/panda/src/pgraph/transformAttrib.h @@ -0,0 +1,117 @@ +// Filename: transformAttrib.h +// Created by: drose (23Feb02) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved +// +// All use of this software is subject to the terms of the Panda 3d +// Software license. You should have received a copy of this license +// along with this source code; you will also find a current copy of +// the license at http://www.panda3d.org/license.txt . +// +// To contact the maintainers of this program write to +// panda3d@yahoogroups.com . +// +//////////////////////////////////////////////////////////////////// + +#ifndef TRANSFORMATTRIB_H +#define TRANSFORMATTRIB_H + +#include "pandabase.h" + +#include "renderAttrib.h" +#include "luse.h" + +//////////////////////////////////////////////////////////////////// +// Class : TransformAttrib +// Description : Indicates a coordinate-system transform on vertices. +// TransformAttribs are the primary means for storing +// transformations on the scene graph. +// +// Transforms may be specified in one of two ways: +// componentwise, with a pos-hpr-scale, or with an +// arbitrary transform matrix. If you specify a +// transform componentwise, it will remember its +// original components. +//////////////////////////////////////////////////////////////////// +class EXPCL_PANDA TransformAttrib : public RenderAttrib { +private: + INLINE TransformAttrib(); + +PUBLISHED: + static CPT(RenderAttrib) make_identity(); + static CPT(RenderAttrib) make_components(const LVecBase3f &pos, + const LVecBase3f &hpr, + const LVecBase3f &scale); + static CPT(RenderAttrib) make_mat(const LMatrix4f &mat); + + INLINE bool is_identity() const; + INLINE bool is_singular() const; + INLINE bool has_components() const; + INLINE const LVecBase3f &get_pos() const; + INLINE const LVecBase3f &get_hpr() const; + INLINE const LVecBase3f &get_scale() const; + INLINE const LMatrix4f &get_mat() const; + +public: + virtual void output(ostream &out) const; + +protected: + virtual int compare_to_impl(const RenderAttrib *other) const; + virtual CPT(RenderAttrib) compose_impl(const RenderAttrib *other) const; + virtual RenderAttrib *make_default_impl() const; + +private: + INLINE void check_singular() const; + INLINE void check_components() const; + INLINE void check_mat() const; + void calc_singular(); + void calc_components(); + void calc_mat(); + + enum Flags { + F_is_identity = 0x0001, + F_is_singular = 0x0002, + F_singular_known = 0x0004, + F_components_given = 0x0008, + F_components_known = 0x0010, + F_has_components = 0x0020, + F_mat_known = 0x0040, + }; + LVecBase3f _pos, _hpr, _scale; + LMatrix4f _mat; + + short _flags; + +public: + static void register_with_read_factory(); + virtual void write_datagram(BamWriter *manager, Datagram &dg); + +protected: + static TypedWritable *make_from_bam(const FactoryParams ¶ms); + void fillin(DatagramIterator &scan, BamReader *manager); + +public: + static TypeHandle get_class_type() { + return _type_handle; + } + static void init_type() { + RenderAttrib::init_type(); + register_type(_type_handle, "TransformAttrib", + RenderAttrib::get_class_type()); + } + virtual TypeHandle get_type() const { + return get_class_type(); + } + virtual TypeHandle force_init_type() {init_type(); return get_class_type();} + +private: + static TypeHandle _type_handle; +}; + +#include "transformAttrib.I" + +#endif +