premature checkin

This commit is contained in:
David Rose 2002-02-23 00:27:36 +00:00
parent 725724bd72
commit a41e2cac34
37 changed files with 3786 additions and 0 deletions

View File

@ -0,0 +1,54 @@
#define OTHER_LIBS interrogatedb:c dconfig:c dtoolconfig:m \
dtoolutil:c dtoolbase:c dtool:m
#define LOCAL_LIBS gobj putil graph linmath express pandabase
#begin lib_target
#define TARGET pgraph
#define SOURCES \
colorAttrib.h colorAttrib.I \
config_pgraph.h \
cycleData.h cycleData.I \
cycleDataReader.h cycleDataReader.I \
cycleDataWriter.h cycleDataWriter.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
// #define INCLUDED_SOURCES
#define SOURCES $[SOURCES] \
colorAttrib.cxx \
config_pgraph.cxx \
cycleData.cxx \
cycleDataReader.cxx \
cycleDataWriter.cxx \
pandaNode.cxx \
pipeline.cxx \
pipelineCycler.cxx \
pipelineCyclerBase.cxx \
renderAttrib.cxx \
renderState.cxx \
textureAttrib.cxx
#define INSTALL_HEADERS \
pandaNode.h pandaNode.I
#define IGATESCAN all
#end lib_target
#begin test_bin_target
#define TARGET test_pgraph
#define SOURCES \
test_pgraph.cxx
#define LOCAL_LIBS $[LOCAL_LIBS] pgraph
#define OTHER_LIBS $[OTHER_LIBS] pystub
#end test_bin_target

View File

@ -0,0 +1,66 @@
// Filename: colorAttrib.I
// 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 .
//
////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////
// Function: ColorAttrib::Constructor
// Access: Private
// Description: Use ColorAttrib::make() to construct a new
// ColorAttrib object.
////////////////////////////////////////////////////////////////////
INLINE ColorAttrib::
ColorAttrib(ColorAttrib::Type type, const Colorf &color) :
_type(type),
_color(color)
{
}
////////////////////////////////////////////////////////////////////
// Function: ColorAttrib::get_color_type
// Access: Published
// Description: Returns the type of color specified by this
// ColorAttrib. The options are:
//
// T_vertex - use the vertex color specified in the
// geometry itself.
//
// T_flat - use the color specified in this
// ColorAttrib for all geometry. You can get this
// color via get_color().
//
// T_off - do not issue any color commands at all.
// This is generally used only in contexts where the
// color is meaningless, e.g. when drawing directly to
// the depth buffer.
////////////////////////////////////////////////////////////////////
INLINE ColorAttrib::Type ColorAttrib::
get_color_type() const {
return _type;
}
////////////////////////////////////////////////////////////////////
// Function: ColorAttrib::get_color
// Access: Published
// Description: If the type is T_flat, this returns the color that
// will be applied to geometry. If the type is anything
// else, this is meaningless.
////////////////////////////////////////////////////////////////////
INLINE const Colorf &ColorAttrib::
get_color() const {
return _color;
}

View File

@ -0,0 +1,127 @@
// Filename: colorAttrib.cxx
// 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 .
//
////////////////////////////////////////////////////////////////////
#include "colorAttrib.h"
#include "dcast.h"
TypeHandle ColorAttrib::_type_handle;
////////////////////////////////////////////////////////////////////
// Function: ColorAttrib::make_vertex
// Access: Published, Static
// Description: Constructs a new ColorAttrib object that indicates
// geometry should be rendered according to its own
// vertex color.
////////////////////////////////////////////////////////////////////
CPT(RenderAttrib) ColorAttrib::
make_vertex() {
ColorAttrib *attrib = new ColorAttrib(T_vertex, Colorf(0.0f, 0.0f, 0.0f, 1.0f));
return return_new(attrib);
}
////////////////////////////////////////////////////////////////////
// Function: ColorAttrib::make_flat
// Access: Published, Static
// Description: Constructs a new ColorAttrib object that indicates
// geometry should be rendered in the indicated color.
////////////////////////////////////////////////////////////////////
CPT(RenderAttrib) ColorAttrib::
make_flat(const Colorf &color) {
ColorAttrib *attrib = new ColorAttrib(T_flat, color);
return return_new(attrib);
}
////////////////////////////////////////////////////////////////////
// Function: ColorAttrib::make_off
// Access: Published, Static
// Description: Constructs a new ColorAttrib object that indicates
// geometry should be rendered without any color
// commands at all.
////////////////////////////////////////////////////////////////////
CPT(RenderAttrib) ColorAttrib::
make_off() {
ColorAttrib *attrib = new ColorAttrib(T_off, Colorf(0.0f, 0.0f, 0.0f, 1.0f));
return return_new(attrib);
}
////////////////////////////////////////////////////////////////////
// Function: ColorAttrib::output
// Access: Public, Virtual
// Description:
////////////////////////////////////////////////////////////////////
void ColorAttrib::
output(ostream &out) const {
out << get_type() << ":";
switch (get_color_type()) {
case T_vertex:
out << "vertex";
break;
case T_flat:
out << "(" << get_color() << ")";
break;
case T_off:
out << "off";
break;
}
}
////////////////////////////////////////////////////////////////////
// Function: ColorAttrib::compare_to_impl
// Access: Protected, Virtual
// Description: Intended to be overridden by derived ColorAttrib
// types to return a unique number indicating whether
// this ColorAttrib is equivalent to the other one.
//
// This should return 0 if the two ColorAttrib 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 ColorAttrib
// objects whose get_type() functions return the same.
////////////////////////////////////////////////////////////////////
int ColorAttrib::
compare_to_impl(const RenderAttrib *other) const {
const ColorAttrib *ta;
DCAST_INTO_R(ta, other, 0);
if (_type != ta->_type) {
return (int)_type - (int)ta->_type;
}
if (_type == T_flat) {
return _color.compare_to(ta->_color);
}
return 0;
}
////////////////////////////////////////////////////////////////////
// Function: ColorAttrib::make_default_impl
// Access: Protected, Virtual
// Description: Intended to be overridden by derived ColorAttrib
// types to specify what the default property for a
// ColorAttrib of this type should be.
//
// This should return a newly-allocated ColorAttrib of
// the same type that corresponds to whatever the
// standard default for this kind of ColorAttrib is.
////////////////////////////////////////////////////////////////////
RenderAttrib *ColorAttrib::
make_default_impl() const {
return new ColorAttrib(T_vertex, Colorf(0.0f, 0.0f, 0.0f, 1.0f));
}

View File

@ -0,0 +1,81 @@
// Filename: colorAttrib.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 COLORATTRIB_H
#define COLORATTRIB_H
#include "pandabase.h"
#include "renderAttrib.h"
#include "luse.h"
////////////////////////////////////////////////////////////////////
// Class : ColorAttrib
// Description : Indicates what color should be applied to renderable
// geometry.
////////////////////////////////////////////////////////////////////
class EXPCL_PANDA ColorAttrib : public RenderAttrib {
PUBLISHED:
enum Type {
T_vertex, T_flat, T_off
};
private:
INLINE ColorAttrib(Type type, const Colorf &color);
PUBLISHED:
static CPT(RenderAttrib) make_vertex();
static CPT(RenderAttrib) make_flat(const Colorf &color);
static CPT(RenderAttrib) make_off();
INLINE Type get_color_type() const;
INLINE const Colorf &get_color() const;
public:
virtual void output(ostream &out) const;
protected:
virtual int compare_to_impl(const RenderAttrib *other) const;
virtual RenderAttrib *make_default_impl() const;
private:
Type _type;
Colorf _color;
public:
static TypeHandle get_class_type() {
return _type_handle;
}
static void init_type() {
TypedWritableReferenceCount::init_type();
register_type(_type_handle, "ColorAttrib",
TypedWritableReferenceCount::get_class_type());
}
virtual TypeHandle get_type() const {
return get_class_type();
}
virtual TypeHandle force_init_type() {init_type(); return get_class_type();}
private:
static TypeHandle _type_handle;
};
#include "colorAttrib.I"
#endif

View File

@ -0,0 +1,61 @@
// Filename: config_pgraph.cxx
// Created by: drose (21Feb02)
//
////////////////////////////////////////////////////////////////////
//
// 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 "config_pgraph.h"
#include "colorAttrib.h"
#include "pandaNode.h"
#include "renderAttrib.h"
#include "renderState.h"
#include "textureAttrib.h"
#include "dconfig.h"
Configure(config_pgraph);
NotifyCategoryDef(pgraph, "");
ConfigureFn(config_pgraph) {
init_libpgraph();
}
////////////////////////////////////////////////////////////////////
// Function: init_libpgraph
// Description: Initializes the library. This must be called at
// least once before any of the functions or classes in
// this library can be used. Normally it will be
// called by the static initializers and need not be
// called explicitly, but special cases exist.
////////////////////////////////////////////////////////////////////
void
init_libpgraph() {
static bool initialized = false;
if (initialized) {
return;
}
initialized = true;
ColorAttrib::init_type();
PandaNode::init_type();
RenderAttrib::init_type();
RenderState::init_type();
TextureAttrib::init_type();
PandaNode::register_with_read_factory();
RenderState::register_with_read_factory();
}

View File

@ -0,0 +1,29 @@
// Filename: config_pgraph.h
// Created by: drose (21Feb02)
//
////////////////////////////////////////////////////////////////////
//
// 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 CONFIG_PGRAPH_H
#define CONFIG_PGRAPH_H
#include "pandabase.h"
#include "notifyCategoryProxy.h"
NotifyCategoryDecl(pgraph, EXPCL_PANDA, EXPTP_PANDA);
extern EXPCL_PANDA void init_libpgraph();
#endif

View File

@ -0,0 +1,27 @@
// Filename: cycleData.I
// Created by: drose (21Feb02)
//
////////////////////////////////////////////////////////////////////
//
// 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: CycleData::Constructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
INLINE CycleData::
CycleData() {
}

View File

@ -0,0 +1,29 @@
// Filename: cycleData.cxx
// Created by: drose (21Feb02)
//
////////////////////////////////////////////////////////////////////
//
// 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 "cycleData.h"
////////////////////////////////////////////////////////////////////
// Function: CycleData::Destructor
// Access: Public, Virtual
// Description:
////////////////////////////////////////////////////////////////////
CycleData::
~CycleData() {
}

View File

@ -0,0 +1,44 @@
// Filename: cycleData.h
// Created by: drose (21Feb02)
//
////////////////////////////////////////////////////////////////////
//
// 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 CYCLEDATA_H
#define CYCLEDATA_H
#include "pandabase.h"
#include "referenceCount.h"
////////////////////////////////////////////////////////////////////
// Class : CycleData
// Description : A single page of data maintained by a PipelineCycler.
// Normally you should inherit from this class to define
// the data structures that are important to protect
// between stages of a pipeline. See PipelineCycler.
////////////////////////////////////////////////////////////////////
class EXPCL_PANDA CycleData : public ReferenceCount {
public:
INLINE CycleData();
virtual ~CycleData();
virtual CycleData *make_copy() const=0;
};
#include "cycleData.I"
#endif

View File

@ -0,0 +1,68 @@
// Filename: cycleDataReader.I
// Created by: drose (21Feb02)
//
////////////////////////////////////////////////////////////////////
//
// 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: CycleDataReader::Constructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
template<class CycleDataType>
INLINE CycleDataReader<CycleDataType>::
CycleDataReader(const PipelineCycler<CycleDataType> &cycler) :
_cycler(cycler)
{
_pointer = (const CycleDataType *)_cycler.read();
}
////////////////////////////////////////////////////////////////////
// Function: CycleDataReader::Copy Constructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
template<class CycleDataType>
INLINE CycleDataReader<CycleDataType>::
CycleDataReader(const CycleDataReader<CycleDataType> &copy) :
_cycler(copy._cycler),
_pointer(copy._pointer)
{
_cycler.increment_read(_pointer);
}
////////////////////////////////////////////////////////////////////
// Function: CycleDataReader::Destructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
template<class CycleDataType>
INLINE CycleDataReader<CycleDataType>::
~CycleDataReader() {
_cycler.release_read(_pointer);
}
////////////////////////////////////////////////////////////////////
// Function: CycleDataReader::operator ->
// Access: Public
// Description: This provides an indirect member access to the actual
// CycleData data.
////////////////////////////////////////////////////////////////////
template<class CycleDataType>
INLINE const CycleDataType *CycleDataReader<CycleDataType>::
operator -> () const {
return _pointer;
}

View File

@ -0,0 +1,19 @@
// Filename: cycleDataReader.cxx
// Created by: drose (21Feb02)
//
////////////////////////////////////////////////////////////////////
//
// 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 "cycleDataReader.h"

View File

@ -0,0 +1,59 @@
// Filename: cycleDataReader.h
// Created by: drose (21Feb02)
//
////////////////////////////////////////////////////////////////////
//
// 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 CYCLEDATAREADER_H
#define CYCLEDATAREADER_H
#include "pandabase.h"
#include "cycleData.h"
#include "pipelineCycler.h"
////////////////////////////////////////////////////////////////////
// Class : CycleDataReader
// Description : This template class calls PipelineCycler::read() in
// the constructor and PipelineCycler::release_read() in
// the destructor. In the interim, it provides a
// transparent read-only access to the CycleData.
//
// It exists as a syntactic convenience to access the
// data in the CycleData. It also allows the whole
// system to compile down to nothing if
// SUPPORT_PIPELINING is not defined.
////////////////////////////////////////////////////////////////////
template<class CycleDataType>
class CycleDataReader {
public:
INLINE CycleDataReader(const PipelineCycler<CycleDataType> &cycler);
INLINE CycleDataReader(const CycleDataReader<CycleDataType> &copy);
INLINE ~CycleDataReader();
INLINE const CycleDataType *operator -> () const;
private:
const PipelineCycler<CycleDataType> &_cycler;
const CycleDataType *_pointer;
};
// This abbreviation macro is used for ease of typing.
#define CDR(type) CycleDataReader< type >
#include "cycleDataReader.I"
#endif

View File

@ -0,0 +1,80 @@
// Filename: cycleDataWriter.I
// Created by: drose (21Feb02)
//
////////////////////////////////////////////////////////////////////
//
// 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: CycleDataWriter::Constructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
template<class CycleDataType>
INLINE CycleDataWriter<CycleDataType>::
CycleDataWriter(PipelineCycler<CycleDataType> &cycler) :
_cycler(cycler)
{
_pointer = (CycleDataType *)_cycler.write();
}
////////////////////////////////////////////////////////////////////
// Function: CycleDataWriter::Copy Constructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
template<class CycleDataType>
INLINE CycleDataWriter<CycleDataType>::
CycleDataWriter(const CycleDataWriter<CycleDataType> &copy) :
_cycler(copy._cycler),
_pointer(copy._pointer)
{
_cycler.increment_write(_pointer);
}
////////////////////////////////////////////////////////////////////
// Function: CycleDataWriter::Destructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
template<class CycleDataType>
INLINE CycleDataWriter<CycleDataType>::
~CycleDataWriter() {
_cycler.release_write(_pointer);
}
////////////////////////////////////////////////////////////////////
// Function: CycleDataWriter::operator ->
// Access: Public
// Description: This provides an indirect member access to the actual
// CycleData data.
////////////////////////////////////////////////////////////////////
template<class CycleDataType>
INLINE CycleDataType *CycleDataWriter<CycleDataType>::
operator -> () {
return _pointer;
}
////////////////////////////////////////////////////////////////////
// Function: CycleDataWriter::operator ->
// Access: Public
// Description: This provides an indirect member access to the actual
// CycleData data.
////////////////////////////////////////////////////////////////////
template<class CycleDataType>
INLINE const CycleDataType *CycleDataWriter<CycleDataType>::
operator -> () const {
return _pointer;
}

View File

@ -0,0 +1,19 @@
// Filename: cycleDataWriter.cxx
// Created by: drose (21Feb02)
//
////////////////////////////////////////////////////////////////////
//
// 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 "cycleDataWriter.h"

View File

@ -0,0 +1,59 @@
// Filename: cycleDataWriter.h
// Created by: drose (21Feb02)
//
////////////////////////////////////////////////////////////////////
//
// 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 CYCLEDATAWRITER_H
#define CYCLEDATAWRITER_H
#include "pandabase.h"
#include "cycleData.h"
#include "pipelineCycler.h"
////////////////////////////////////////////////////////////////////
// Class : CycleDataWriter
// Description : This template class calls PipelineCycler::write() in
// the constructor and PipelineCycler::release_write() in
// the destructor. In the interim, it provides a
// transparent read-write access to the CycleData.
//
// It exists as a syntactic convenience to access the
// data in the CycleData. It also allows the whole
// system to compile down to nothing if
// SUPPORT_PIPELINING is not defined.
////////////////////////////////////////////////////////////////////
template<class CycleDataType>
class CycleDataWriter {
public:
INLINE CycleDataWriter(PipelineCycler<CycleDataType> &cycler);
INLINE CycleDataWriter(const CycleDataWriter<CycleDataType> &copy);
INLINE ~CycleDataWriter();
INLINE CycleDataType *operator -> ();
INLINE const CycleDataType *operator -> () const;
private:
PipelineCycler<CycleDataType> &_cycler;
CycleDataType *_pointer;
};
#define CDW(type) CycleDataWriter< type >
#include "cycleDataWriter.I"
#endif

View File

@ -0,0 +1,325 @@
// Filename: pandaNode.I
// Created by: drose (20Feb02)
//
////////////////////////////////////////////////////////////////////
//
// 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: PandaNode::DownConnection::Constructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
INLINE PandaNode::DownConnection::
DownConnection(PandaNode *child, int sort) :
_child(child),
_sort(sort)
{
}
////////////////////////////////////////////////////////////////////
// Function: PandaNode::DownConnection::operator <
// Access: Public
// Description: Provides a partial ordering on the children of a node
// so that they are ranked first in sort order, and then
// (by virtue of the ordered_vector) in the order they
// were added.
////////////////////////////////////////////////////////////////////
INLINE bool PandaNode::DownConnection::
operator < (const DownConnection &other) const {
return _sort < other._sort;
}
////////////////////////////////////////////////////////////////////
// Function: PandaNode::DownConnection::get_child
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
INLINE PandaNode *PandaNode::DownConnection::
get_child() const {
return _child;
}
////////////////////////////////////////////////////////////////////
// Function: PandaNode::DownConnection::get_sort
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
INLINE int PandaNode::DownConnection::
get_sort() const {
return _sort;
}
////////////////////////////////////////////////////////////////////
// Function: PandaNode::CData::Constructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
INLINE PandaNode::CData::
CData() {
_state_changes = RenderState::make_empty();
}
////////////////////////////////////////////////////////////////////
// Function: PandaNode::Children::Constructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
INLINE PandaNode::Children::
Children(const PipelineCycler<PandaNode::CData> &cycler) :
_cdata(cycler)
{
}
////////////////////////////////////////////////////////////////////
// Function: PandaNode::Children::Copy Constructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
INLINE PandaNode::Children::
Children(const PandaNode::Children &copy) :
_cdata(copy._cdata)
{
}
////////////////////////////////////////////////////////////////////
// Function: PandaNode::Children::get_num_children
// Access: Public
// Description: Returns the number of children of the node.
////////////////////////////////////////////////////////////////////
INLINE int PandaNode::Children::
get_num_children() const {
return _cdata->_down.size();
}
////////////////////////////////////////////////////////////////////
// Function: PandaNode::Children::get_child
// Access: Public
// Description: Returns the nth child of the node.
////////////////////////////////////////////////////////////////////
INLINE PandaNode *PandaNode::Children::
get_child(int n) const {
nassertr(n >= 0 && n < (int)_cdata->_down.size(), NULL);
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
// Description: Returns the number of parent nodes this node has. If
// this number is greater than 1, the node has been
// multiply instanced. The order of the parent nodes is
// not meaningful and is not related to the order in
// which the node was instanced to them.
////////////////////////////////////////////////////////////////////
INLINE int PandaNode::
get_num_parents() const {
CDR(CData) cdata(_cycler);
return cdata->_up.size();
}
////////////////////////////////////////////////////////////////////
// Function: PandaNode::get_parent
// Access: Published
// Description: Returns the nth parent node of this node. See
// get_num_parents().
////////////////////////////////////////////////////////////////////
INLINE PandaNode *PandaNode::
get_parent(int n) const {
CDR(CData) cdata(_cycler);
nassertr(n >= 0 && n < (int)cdata->_up.size(), NULL);
return cdata->_up[n];
}
////////////////////////////////////////////////////////////////////
// Function: PandaNode::find_parent
// Access: Published
// Description: Returns the index of the indicated parent node, if it
// is a parent, or -1 if it is not.
////////////////////////////////////////////////////////////////////
INLINE int PandaNode::
find_parent(PandaNode *node) const {
CDR(CData) cdata(_cycler);
Up::const_iterator ui = cdata->_up.find(node);
if (ui == cdata->_up.end()) {
return -1;
}
return ui - cdata->_up.begin();
}
////////////////////////////////////////////////////////////////////
// Function: PandaNode::get_num_children
// Access: Published
// Description: Returns the number of child nodes this node has. The
// order of the child nodes *is* meaningful and is based
// on the sort number that was passed to add_child(),
// and also on the order in which the nodes were added.
////////////////////////////////////////////////////////////////////
INLINE int PandaNode::
get_num_children() const {
CDR(CData) cdata(_cycler);
return cdata->_down.size();
}
////////////////////////////////////////////////////////////////////
// Function: PandaNode::get_child
// Access: Published
// Description: Returns the nth child node of this node. See
// get_num_children().
////////////////////////////////////////////////////////////////////
INLINE PandaNode *PandaNode::
get_child(int n) const {
CDR(CData) cdata(_cycler);
nassertr(n >= 0 && n < (int)cdata->_down.size(), NULL);
return cdata->_down[n].get_child();
}
////////////////////////////////////////////////////////////////////
// Function: PandaNode::get_sort
// Access: Published
// Description: Returns the sort index of the nth child node of this
// node (that is, the number that was passed to
// add_child()). See get_num_children().
////////////////////////////////////////////////////////////////////
INLINE int PandaNode::
get_sort(int n) const {
CDR(CData) cdata(_cycler);
nassertr(n >= 0 && n < (int)cdata->_down.size(), -1);
return cdata->_down[n].get_sort();
}
////////////////////////////////////////////////////////////////////
// Function: PandaNode::set_attrib
// Access: Published
// Description: Adds the indicated render attribute to the scene
// graph on this node. This attribute will now apply to
// this node and everything below. If there was already
// an attribute of the same type, it is replaced.
////////////////////////////////////////////////////////////////////
INLINE void PandaNode::
set_attrib(const RenderAttrib *attrib, int override) {
CDW(CData) cdata(_cycler);
cdata->_state_changes = cdata->_state_changes->add(attrib, override);
}
////////////////////////////////////////////////////////////////////
// Function: PandaNode::get_attrib
// Access: Published
// Description: Returns the render attribute of the indicated type,
// if it is defined on the node, or NULL if it is not.
// This checks only what is set on this particular node
// level, and has nothing to do with what render
// attributes may be inherited from parent nodes.
////////////////////////////////////////////////////////////////////
INLINE const RenderAttrib *PandaNode::
get_attrib(TypeHandle type) const {
CDR(CData) cdata(_cycler);
int index = cdata->_state_changes->find_attrib(type);
if (index >= 0) {
return cdata->_state_changes->get_attrib(index);
}
return NULL;
}
////////////////////////////////////////////////////////////////////
// Function: PandaNode::clear_attrib
// Access: Published
// Description: Removes the render attribute of the given type from
// this node. This node, and the subgraph below, will
// now inherit the indicated render attribute from the
// nodes above this one.
////////////////////////////////////////////////////////////////////
INLINE void PandaNode::
clear_attrib(TypeHandle type) {
CDW(CData) cdata(_cycler);
cdata->_state_changes = cdata->_state_changes->remove(type);
}
////////////////////////////////////////////////////////////////////
// Function: PandaNode::set_state
// Access: Published
// Description: Sets the complete RenderState that will be applied to
// all nodes at this level and below. (The actual state
// that will be applied to lower nodes is based on the
// composition of RenderStates from above this node as
// well). This completely replaces whatever has been
// set on this node via repeated calls to set_attrib().
////////////////////////////////////////////////////////////////////
INLINE void PandaNode::
set_state(const RenderState *state) {
CDW(CData) cdata(_cycler);
cdata->_state_changes = state;
}
////////////////////////////////////////////////////////////////////
// Function: PandaNode::get_state
// Access: Published
// Description: Returns the complete RenderState that will be applied
// to all nodes at this level and below, as set on this
// node. This returns only the RenderState set on this
// particular node, and has nothing to do with state
// that might be inherited from above.
////////////////////////////////////////////////////////////////////
INLINE const RenderState *PandaNode::
get_state() const {
CDR(CData) cdata(_cycler);
return cdata->_state_changes;
}
////////////////////////////////////////////////////////////////////
// Function: PandaNode::clear_state
// Access: Published
// Description: Resets this node to leave the render state alone.
// Nodes at this level and below will once again inherit
// their render state unchanged from the nodes above
// this level.
////////////////////////////////////////////////////////////////////
INLINE void PandaNode::
clear_state() {
CDW(CData) cdata(_cycler);
cdata->_state_changes = RenderState::make_empty();
}
////////////////////////////////////////////////////////////////////
// Function: PandaNode::get_children
// Access: Public
// Description: Returns an object that can be used to walk through
// the list of children of the node. When you intend to
// visit multiple children, using this is slightly
// faster than calling get_child() directly on the
// PandaNode, since this object keeps the PipelineCycler
// open the whole time.
//
// However, this object does not protect you from
// self-modifying loops (e.g. adding or removing
// children during traversal).
////////////////////////////////////////////////////////////////////
INLINE PandaNode::Children PandaNode::
get_children() const {
return Children(_cycler);
}

View File

@ -0,0 +1,295 @@
// Filename: pandaNode.cxx
// Created by: drose (20Feb02)
//
////////////////////////////////////////////////////////////////////
//
// 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 "pandaNode.h"
#include "bamReader.h"
#include "bamWriter.h"
#include "indent.h"
TypeHandle PandaNode::_type_handle;
////////////////////////////////////////////////////////////////////
// Function: PandaNode::CData::Copy Constructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
PandaNode::CData::
CData(const PandaNode::CData &copy) :
_down(copy._down),
_up(copy._up),
_node_bounds(copy._node_bounds),
_subgraph_bounds(copy._subgraph_bounds),
_state_changes(copy._state_changes)
{
}
////////////////////////////////////////////////////////////////////
// Function: PandaNode::CData::make_copy
// Access: Public, Virtual
// Description:
////////////////////////////////////////////////////////////////////
CycleData *PandaNode::CData::
make_copy() const {
return new CData(*this);
}
////////////////////////////////////////////////////////////////////
// Function: PandaNode::Copy Constructor
// Access: Published
// Description:
////////////////////////////////////////////////////////////////////
PandaNode::
PandaNode(const PandaNode &copy) :
TypedWritable(copy),
Namable(copy),
ReferenceCount(copy)
{
// 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);
cdata->_node_bounds = copy_cdata->_node_bounds;
}
////////////////////////////////////////////////////////////////////
// Function: PandaNode::Copy Assignment Operator
// Access: Published
// Description:
////////////////////////////////////////////////////////////////////
void PandaNode::
operator = (const PandaNode &copy) {
TypedWritable::operator = (copy);
Namable::operator = (copy);
ReferenceCount::operator = (copy);
// Copy the other node's bounding volume.
CDR(CData) copy_cdata(copy._cycler);
CDW(CData) cdata(_cycler);
cdata->_node_bounds = copy_cdata->_node_bounds;
}
////////////////////////////////////////////////////////////////////
// Function: PandaNode::Destructor
// Access: Published, Virtual
// Description:
////////////////////////////////////////////////////////////////////
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);
nassertv(cdata->_up.empty());
remove_all_children();
}
////////////////////////////////////////////////////////////////////
// Function: PandaNode::find_child
// Access: Published
// Description: Returns the index of the indicated child node, if it
// is a child, or -1 if it is not.
////////////////////////////////////////////////////////////////////
int PandaNode::
find_child(PandaNode *node) const {
CDR(CData) cdata(_cycler);
// We have to search for the child by brute force, since we don't
// know what sort index it was added as.
Down::const_iterator ci;
for (ci = cdata->_down.begin(); ci != cdata->_down.end(); ++ci) {
if ((*ci).get_child() == node) {
return ci - cdata->_down.begin();
}
}
return -1;
}
////////////////////////////////////////////////////////////////////
// Function: PandaNode::add_child
// Access: Published
// Description: Adds a new child to the node. The child is added in
// the relative position indicated by sort; if all
// children have the same sort index, the child is added
// at the end.
//
// If the same child is added to a node more than once,
// the previous instance is first removed.
//
// The return value is the index of the new child.
////////////////////////////////////////////////////////////////////
int PandaNode::
add_child(PandaNode *child, int sort) {
remove_child(child);
CDW(CData) cdata(_cycler);
CDW(CData) cdata_child(child->_cycler);
Down::iterator ci = cdata->_down.insert(DownConnection(child, sort));
cdata_child->_up.insert(this);
return ci - cdata->_down.begin();
}
////////////////////////////////////////////////////////////////////
// Function: PandaNode::remove_child
// Access: Published
// Description: Removes the nth child from the node.
////////////////////////////////////////////////////////////////////
void PandaNode::
remove_child(int n) {
CDW(CData) cdata(_cycler);
nassertv(n >= 0 && n < (int)cdata->_down.size());
PandaNode *child = cdata->_down[n].get_child();
CDW(CData) cdata_child(child->_cycler);
cdata->_down.erase(cdata->_down.begin() + n);
int num_erased = cdata_child->_up.erase(this);
nassertv(num_erased == 1);
}
////////////////////////////////////////////////////////////////////
// Function: PandaNode::remove_child
// Access: Published
// Description: Removes the indicated child from the node. Returns
// true if the child was removed, false if it was not
// already a child of the node.
////////////////////////////////////////////////////////////////////
bool PandaNode::
remove_child(PandaNode *child) {
CDW(CData) cdata_child(child->_cycler);
// First, look for and remove this node from the child's parent
// list.
int num_erased = cdata_child->_up.erase(this);
if (num_erased == 0) {
// No such node; it wasn't our child to begin with.
return false;
}
CDW(CData) cdata(_cycler);
// Now, look for and remove the child node from our down list.
Down::iterator ci;
for (ci = cdata->_down.begin(); ci != cdata->_down.end(); ++ci) {
if ((*ci).get_child() == child) {
cdata->_down.erase(ci);
return true;
}
}
// We shouldn't get here unless there was a parent-child mismatch.
nassertr(false, false);
return true;
}
////////////////////////////////////////////////////////////////////
// Function: PandaNode::remove_all_children
// Access: Published
// Description: Removes all the children from the node at once.
////////////////////////////////////////////////////////////////////
void PandaNode::
remove_all_children() {
CDW(CData) 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);
child_cdata->_up.erase(this);
}
}
////////////////////////////////////////////////////////////////////
// Function: PandaNode::output
// Access: Published, Virtual
// Description:
////////////////////////////////////////////////////////////////////
void PandaNode::
output(ostream &out) const {
out << get_type() << " " << get_name();
}
////////////////////////////////////////////////////////////////////
// Function: PandaNode::write
// Access: Published, Virtual
// Description:
////////////////////////////////////////////////////////////////////
void PandaNode::
write(ostream &out, int indent_level) const {
indent(out, indent_level) << *this;
CDR(CData) cdata(_cycler);
if (!cdata->_state_changes->is_empty()) {
out << " (" << *cdata->_state_changes << ")";
}
out << "\n";
}
////////////////////////////////////////////////////////////////////
// Function: PandaNode::register_with_read_factory
// Access: Public, Static
// Description: Tells the BamReader how to create objects of type
// PandaNode.
////////////////////////////////////////////////////////////////////
void PandaNode::
register_with_read_factory() {
BamReader::get_factory()->register_factory(get_class_type(), make_from_bam);
}
////////////////////////////////////////////////////////////////////
// Function: PandaNode::write_datagram
// Access: Public, Virtual
// Description: Writes the contents of this object to the datagram
// for shipping out to a Bam file.
////////////////////////////////////////////////////////////////////
void PandaNode::
write_datagram(BamWriter *manager, Datagram &dg) {
}
////////////////////////////////////////////////////////////////////
// Function: PandaNode::make_from_bam
// Access: Protected, Static
// Description: This function is called by the BamReader's factory
// when a new object of type PandaNode is encountered
// in the Bam file. It should create the PandaNode
// and extract its information from the file.
////////////////////////////////////////////////////////////////////
TypedWritable *PandaNode::
make_from_bam(const FactoryParams &params) {
PandaNode *node = new PandaNode("");
DatagramIterator scan;
BamReader *manager;
parse_params(params, scan, manager);
node->fillin(scan, manager);
return node;
}
////////////////////////////////////////////////////////////////////
// Function: PandaNode::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 PandaNode.
////////////////////////////////////////////////////////////////////
void PandaNode::
fillin(DatagramIterator &scan, BamReader *manager) {
}

View File

@ -0,0 +1,175 @@
// Filename: pandaNode.h
// Created by: drose (20Feb02)
//
////////////////////////////////////////////////////////////////////
//
// 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 PANDANODE_H
#define PANDANODE_H
#include "pandabase.h"
#include "cycleData.h"
#include "cycleDataReader.h"
#include "cycleDataWriter.h"
#include "pipelineCycler.h"
#include "renderState.h"
#include "typedWritable.h"
#include "boundedObject.h"
#include "namable.h"
#include "referenceCount.h"
#include "luse.h"
#include "ordered_vector.h"
#include "pointerTo.h"
////////////////////////////////////////////////////////////////////
// Class : PandaNode
// Description : A basic node of the scene graph or data graph. This
// 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 {
PUBLISHED:
INLINE PandaNode(const string &name);
PandaNode(const PandaNode &copy);
void operator = (const PandaNode &copy);
virtual ~PandaNode();
INLINE int get_num_parents() const;
INLINE PandaNode *get_parent(int n) const;
INLINE int find_parent(PandaNode *node) const;
INLINE int get_num_children() const;
INLINE PandaNode *get_child(int n) const;
INLINE int get_sort(int n) const;
int find_child(PandaNode *node) const;
int add_child(PandaNode *child, int sort = 0);
void remove_child(int n);
bool remove_child(PandaNode *child);
void remove_all_children();
INLINE void set_attrib(const RenderAttrib *attrib, int override = 0);
INLINE const RenderAttrib *get_attrib(TypeHandle type) const;
INLINE void clear_attrib(TypeHandle type);
INLINE void set_state(const RenderState *state);
INLINE const RenderState *get_state() const;
INLINE void clear_state();
virtual void output(ostream &out) const;
virtual void write(ostream &out, int indent_level) const;
private:
class DownConnection {
public:
INLINE DownConnection(PandaNode *child, int sort);
INLINE bool operator < (const DownConnection &other) const;
INLINE PandaNode *get_child() const;
INLINE int get_sort() const;
private:
// Child pointers are reference counted. That way, holding a
// pointer to the root of a subgraph keeps the entire subgraph
// around.
PT(PandaNode) _child;
int _sort;
};
typedef ov_multiset<DownConnection> Down;
// Parent pointers are not reference counted. That way, parents and
// children do not circularly reference each other. In fact, parent
// pointers are just simple pointers, with no additional data. We
// don't really need to keep the parent pointers around, but it's
// nice to be able to walk up the graph.
typedef ov_set<PandaNode *> Up;
// This is the data that must be cycled between pipeline stages.
class CData : public CycleData {
public:
INLINE CData();
CData(const CData &copy);
virtual CycleData *make_copy() const;
Down _down;
Up _up;
BoundedObject _node_bounds;
BoundedObject _subgraph_bounds;
CPT(RenderState) _state_changes;
};
PipelineCycler<CData> _cycler;
public:
// Use this interface when you want to walk through the list of
// children. This saves a tiny bit of overhead between each step,
// by keeping the PipelineCycler open for reading the whole time.
// However, it does not protect you from self-modifying loops.
class Children {
public:
INLINE Children(const PipelineCycler<CData> &cycler);
INLINE Children(const Children &copy);
INLINE int get_num_children() const;
INLINE PandaNode *get_child(int n) const;
private:
CDR(CData) _cdata;
};
INLINE Children get_children() const;
public:
static void register_with_read_factory();
virtual void write_datagram(BamWriter *manager, Datagram &dg);
protected:
static TypedWritable *make_from_bam(const FactoryParams &params);
void fillin(DatagramIterator &scan, BamReader *manager);
public:
static TypeHandle get_class_type() {
return _type_handle;
}
static void init_type() {
TypedWritable::init_type();
ReferenceCount::init_type();
register_type(_type_handle, "PandaNode",
TypedWritable::get_class_type(),
ReferenceCount::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;
};
INLINE ostream &operator << (ostream &out, const PandaNode &node) {
node.output(out);
return out;
}
#include "pandaNode.I"
#endif

View File

@ -0,0 +1,31 @@
// Filename: pipeline.I
// Created by: drose (21Feb02)
//
////////////////////////////////////////////////////////////////////
//
// 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: Pipeline::get_render_pipeline
// Access: Public, Static
// Description: Returns a pointer to the global render pipeline.
////////////////////////////////////////////////////////////////////
INLINE Pipeline *Pipeline::
get_render_pipeline() {
if (_render_pipeline == (Pipeline *)NULL) {
make_render_pipeline();
}
return _render_pipeline;
}

View File

@ -0,0 +1,74 @@
// Filename: pipeline.cxx
// Created by: drose (21Feb02)
//
////////////////////////////////////////////////////////////////////
//
// 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 "pipeline.h"
Pipeline *Pipeline::_render_pipeline = (Pipeline *)NULL;
////////////////////////////////////////////////////////////////////
// Function: Pipeline::Constructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
Pipeline::
Pipeline(const string &name) :
Namable(name)
{
}
////////////////////////////////////////////////////////////////////
// Function: Pipeline::Destructor
// Access: Public, Virtual
// Description:
////////////////////////////////////////////////////////////////////
Pipeline::
~Pipeline() {
}
////////////////////////////////////////////////////////////////////
// Function: Pipeline::cycle
// Access: Public
// Description: Flows all the pipeline data down to the next stage.
////////////////////////////////////////////////////////////////////
void Pipeline::
cycle() {
pre_cycle();
}
////////////////////////////////////////////////////////////////////
// Function: Pipeline::pre_cycle
// Access: Protected, Virtual
// Description: A callback function intended to be overridden by a
// derived class to perform whatever operations should
// be done before cycling the pipeline.
////////////////////////////////////////////////////////////////////
void Pipeline::
pre_cycle() {
}
////////////////////////////////////////////////////////////////////
// Function: Pipeline::make_render_pipeline
// Access: Private, Static
// Description:
////////////////////////////////////////////////////////////////////
void Pipeline::
make_render_pipeline() {
nassertv(_render_pipeline == (Pipeline *)NULL);
_render_pipeline = new Pipeline("render");
}

View File

@ -0,0 +1,58 @@
// Filename: pipeline.h
// Created by: drose (21Feb02)
//
////////////////////////////////////////////////////////////////////
//
// 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 PIPELINE_H
#define PIPELINE_H
#include "pandabase.h"
#include "namable.h"
////////////////////////////////////////////////////////////////////
// Class : Pipeline
// Description : This class manages a staged pipeline of data, for
// instance the render pipeline, so that each stage of
// the pipeline can simultaneously access different
// copies of the same data. It actually maintains a
// collection of PipelineCycler objects, and manages the
// turning of all of them at once.
//
// There is one default Pipeline object, the render
// pipeline. Other specialty pipelines may be created
// as needed.
////////////////////////////////////////////////////////////////////
class EXPCL_PANDA Pipeline : public Namable {
public:
Pipeline(const string &name);
virtual ~Pipeline();
INLINE static Pipeline *get_render_pipeline();
void cycle();
protected:
virtual void pre_cycle();
private:
static void make_render_pipeline();
static Pipeline *_render_pipeline;
};
#include "pipeline.I"
#endif

View File

@ -0,0 +1,30 @@
// Filename: pipelineCycler.I
// Created by: drose (21Feb02)
//
////////////////////////////////////////////////////////////////////
//
// 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: PipelineCycler::Constructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
template<class CycleDataType>
INLINE PipelineCycler<CycleDataType>::
PipelineCycler(Pipeline *pipeline) :
PipelineCyclerBase(new CycleDataType, pipeline)
{
}

View File

@ -0,0 +1,19 @@
// Filename: pipelineCycler.cxx
// Created by: drose (21Feb02)
//
////////////////////////////////////////////////////////////////////
//
// 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 "pipelineCycler.h"

View File

@ -0,0 +1,61 @@
// Filename: pipelineCycler.h
// Created by: drose (21Feb02)
//
////////////////////////////////////////////////////////////////////
//
// 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 PIPELINECYCLER_H
#define PIPELINECYCLER_H
#include "pandabase.h"
#include "pipelineCyclerBase.h"
////////////////////////////////////////////////////////////////////
// Class : PipelineCycler
// Description : This class maintains different copies of a page of
// data between stages of the graphics pipeline (or any
// other pipelining context).
//
// The class object maintains up to n copies of a
// CycleData structure, one for each stage of the
// pipeline. The head of the pipeline is responsible
// for making changes to its copy, which are then cycled
// through the pipeline at each frame.
//
// To access the data, you must first ask for a readable
// pointer. In order to make changes to the data, you
// must ask for a writable pointer. Both kinds of
// pointers should be released when you are done, as a
// sanity check. The CycleDataReader and
// CycleDataWriter classes transparently handle this.
//
// If pipelining support is not enabled at compile time
// (that is, SUPPORT_PIPELINING is not defined), this
// object compiles to a minimum object that presents the
// same interface but with minimal runtime overhead.
// (Actually, this isn't true yet, but it will be one
// day.)
////////////////////////////////////////////////////////////////////
template<class CycleDataType>
class PipelineCycler : public PipelineCyclerBase {
public:
INLINE PipelineCycler(Pipeline *pipeline = NULL);
};
#include "pipelineCycler.I"
#endif

View File

@ -0,0 +1,109 @@
// Filename: pipelineCyclerBase.I
// Created by: drose (21Feb02)
//
////////////////////////////////////////////////////////////////////
//
// 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: PipelineCyclerBase::read
// Access: Public
// Description: Returns a const CycleData pointer, filled with the
// data for the current stage of the pipeline as seen by
// this thread. This pointer should eventually be
// released by calling release_read().
////////////////////////////////////////////////////////////////////
INLINE const CycleData *PipelineCyclerBase::
read() const {
// This function isn't truly const, but it doesn't change the data
// in any meaningful way, so we pretend it is.
((PipelineCyclerBase *)this)->_read_count++;
return _data;
}
////////////////////////////////////////////////////////////////////
// Function: PipelineCyclerBase::increment_read
// Access: Public
// Description: Increments the count on a pointer previously
// retrieved by read(); now the pointer will need to be
// released twice.
////////////////////////////////////////////////////////////////////
INLINE void PipelineCyclerBase::
increment_read(const CycleData *pointer) const {
// This function isn't truly const, but it doesn't change the data
// in any meaningful way, so we pretend it is.
nassertv(pointer == _data);
nassertv(_read_count > 0);
((PipelineCyclerBase *)this)->_read_count++;
}
////////////////////////////////////////////////////////////////////
// Function: PipelineCyclerBase::release_read
// Access: Public
// Description: Releases a pointer previously obtained via a call to
// read().
////////////////////////////////////////////////////////////////////
INLINE void PipelineCyclerBase::
release_read(const CycleData *pointer) const {
// This function isn't truly const, but it doesn't change the data
// in any meaningful way, so we pretend it is.
nassertv(pointer == _data);
nassertv(_read_count > 0);
((PipelineCyclerBase *)this)->_read_count--;
}
////////////////////////////////////////////////////////////////////
// Function: PipelineCyclerBase::write
// Access: Public
// Description: Returns a non-const CycleData pointer, filled with a
// unique copy of the data for the current stage of the
// pipeline as seen by this thread. This pointer may
// now be used to write to the data, and that copy of
// the data will be propagate to all later stages of the
// pipeline. This pointer should eventually be released
// by calling release_write().
////////////////////////////////////////////////////////////////////
INLINE CycleData *PipelineCyclerBase::
write() {
_write_count++;
return _data;
}
////////////////////////////////////////////////////////////////////
// Function: PipelineCyclerBase::increment_write
// Access: Public
// Description: Increments the count on a pointer previously
// retrieved by write(); now the pointer will need to be
// released twice.
////////////////////////////////////////////////////////////////////
INLINE void PipelineCyclerBase::
increment_write(CycleData *pointer) {
nassertv(pointer == _data);
nassertv(_write_count > 0);
_write_count++;
}
////////////////////////////////////////////////////////////////////
// Function: PipelineCyclerBase::release_write
// Access: Public
// Description: Releases a pointer previously obtained via a call to
// write().
////////////////////////////////////////////////////////////////////
INLINE void PipelineCyclerBase::
release_write(CycleData *pointer) {
nassertv(pointer == _data);
nassertv(_write_count > 0);
_write_count--;
}

View File

@ -0,0 +1,48 @@
// Filename: pipelineCyclerBase.cxx
// Created by: drose (21Feb02)
//
////////////////////////////////////////////////////////////////////
//
// 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 "pipelineCyclerBase.h"
////////////////////////////////////////////////////////////////////
// Function: PipelineCyclerBase::Constructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
PipelineCyclerBase::
PipelineCyclerBase(CycleData *initial_data, Pipeline *pipeline) :
_data(initial_data),
_pipeline(pipeline),
_read_count(0),
_write_count(0)
{
if (_pipeline == (Pipeline *)NULL) {
_pipeline = Pipeline::get_render_pipeline();
}
}
////////////////////////////////////////////////////////////////////
// Function: PipelineCyclerBase::Destructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
PipelineCyclerBase::
~PipelineCyclerBase() {
nassertv(_read_count == 0 && _write_count == 0);
}

View File

@ -0,0 +1,55 @@
// Filename: pipelineCyclerBase.h
// Created by: drose (21Feb02)
//
////////////////////////////////////////////////////////////////////
//
// 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 PIPELINECYCLERBASE_H
#define PIPELINECYCLERBASE_H
#include "pandabase.h"
#include "cycleData.h"
#include "pipeline.h"
#include "pointerTo.h"
////////////////////////////////////////////////////////////////////
// Class : PipelineCyclerBase
// Description : This is the non-template part of the implementation
// of PipelineCycler. See PipelineCycler.
////////////////////////////////////////////////////////////////////
class EXPCL_PANDA PipelineCyclerBase {
public:
PipelineCyclerBase(CycleData *initial_data, Pipeline *pipeline = NULL);
~PipelineCyclerBase();
INLINE const CycleData *read() const;
INLINE void increment_read(const CycleData *pointer) const;
INLINE void release_read(const CycleData *pointer) const;
INLINE CycleData *write();
INLINE void increment_write(CycleData *pointer);
INLINE void release_write(CycleData *pointer);
private:
PT(CycleData) _data;
Pipeline *_pipeline;
short _read_count, _write_count;
};
#include "pipelineCyclerBase.I"
#endif

View File

@ -0,0 +1,73 @@
// Filename: renderAttrib.I
// Created by: drose (21Feb02)
//
////////////////////////////////////////////////////////////////////
//
// 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: RenderAttrib::compose
// Access: Public
// Description: Returns a new RenderAttrib object that represents the
// composition of this attrib with the other attrib. In
// most cases, this is the same as the other attrib; a
// compose b produces b. Some kinds of attributes, like
// a TextureTransform, for instance, might produce a new
// result: a compose b produces c.
////////////////////////////////////////////////////////////////////
INLINE CPT(RenderAttrib) RenderAttrib::
compose(const RenderAttrib *other) const {
return compose_impl(other);
}
////////////////////////////////////////////////////////////////////
// Function: RenderAttrib::make_default
// Access: Public
// Description: Returns a different (or possibly the same)
// RenderAttrib pointer of the same type as this one
// that corresponds to whatever the standard default
// properties for render attributes of this type ought
// to be.
////////////////////////////////////////////////////////////////////
INLINE CPT(RenderAttrib) RenderAttrib::
make_default() const {
return return_new(make_default_impl());
}
////////////////////////////////////////////////////////////////////
// Function: RenderAttrib::compare_to
// Access: Public
// Description: Provides an arbitrary ordering among all unique
// RenderAttribs, so we can store the essentially
// different ones in a big set and throw away the rest.
//
// This method is not needed outside of the RenderAttrib
// class because all equivalent RenderAttrib objects are
// guaranteed to share the same pointer; thus, a pointer
// comparison is always sufficient.
////////////////////////////////////////////////////////////////////
INLINE int RenderAttrib::
compare_to(const RenderAttrib &other) const {
// First, we compare the types; if they are of different types then
// they sort differently.
TypeHandle type = get_type();
TypeHandle other_type = other.get_type();
if (type != other_type) {
return type.get_index() - other_type.get_index();
}
// We only call compare_to_impl() if they have the same type.
return compare_to_impl(&other);
}

View File

@ -0,0 +1,240 @@
// Filename: renderAttrib.cxx
// Created by: drose (21Feb02)
//
////////////////////////////////////////////////////////////////////
//
// 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 "renderAttrib.h"
#include "bamReader.h"
#include "indent.h"
RenderAttrib::Attribs RenderAttrib::_attribs;
TypeHandle RenderAttrib::_type_handle;
////////////////////////////////////////////////////////////////////
// Function: RenderAttrib::Constructor
// Access: Protected
// Description:
////////////////////////////////////////////////////////////////////
RenderAttrib::
RenderAttrib() {
_saved_entry = _attribs.end();
}
////////////////////////////////////////////////////////////////////
// Function: RenderAttrib::Copy Constructor
// Access: Private
// Description: RenderAttribs are not meant to be copied.
////////////////////////////////////////////////////////////////////
RenderAttrib::
RenderAttrib(const RenderAttrib &) {
nassertv(false);
}
////////////////////////////////////////////////////////////////////
// Function: RenderAttrib::Copy Assignment Operator
// Access: Private
// Description: RenderAttribs are not meant to be copied.
////////////////////////////////////////////////////////////////////
void RenderAttrib::
operator = (const RenderAttrib &) {
nassertv(false);
}
////////////////////////////////////////////////////////////////////
// Function: RenderAttrib::Destructor
// Access: Public, Virtual
// Description: The destructor is responsible for removing the
// RenderAttrib from the global set if it is there.
////////////////////////////////////////////////////////////////////
RenderAttrib::
~RenderAttrib() {
if (_saved_entry != _attribs.end()) {
_attribs.erase(_saved_entry);
_saved_entry = _attribs.end();
}
}
////////////////////////////////////////////////////////////////////
// Function: RenderAttrib::output
// Access: Public, Virtual
// Description:
////////////////////////////////////////////////////////////////////
void RenderAttrib::
output(ostream &out) const {
out << get_type();
}
////////////////////////////////////////////////////////////////////
// Function: RenderAttrib::write
// Access: Public, Virtual
// Description:
////////////////////////////////////////////////////////////////////
void RenderAttrib::
write(ostream &out, int indent_level) const {
indent(out, indent_level) << *this << "\n";
}
////////////////////////////////////////////////////////////////////
// Function: RenderAttrib::return_new
// Access: Protected, Static
// Description: This function is used by derived RenderAttrib types
// to share a common RenderAttrib pointer for all
// equivalent RenderAttrib objects.
//
// The make() function of the derived type should create
// a new RenderAttrib and pass it through return_new(),
// which will either save the pointer and return it
// unchanged (if this is the first similar such object)
// or delete it and return an equivalent pointer (if
// there was already a similar object saved).
////////////////////////////////////////////////////////////////////
CPT(RenderAttrib) RenderAttrib::
return_new(RenderAttrib *attrib) {
nassertr(attrib != (RenderAttrib *)NULL, attrib);
// This should be a newly allocated pointer, not one that was used
// for anything else.
nassertr(attrib->_saved_entry == _attribs.end(), attrib);
// Save the attrib in a local PointerTo so that it will be freed at
// the end of this function if no one else uses it.
CPT(RenderAttrib) pt_attrib = attrib;
pair<Attribs::iterator, bool> result = _attribs.insert(attrib);
if (result.second) {
// The attribute was inserted; save the iterator and return the
// input attribute.
attrib->_saved_entry = result.first;
return pt_attrib;
}
// The attribute was not inserted; there must be an equivalent one
// already in the set. Return that one.
return *(result.first);
}
////////////////////////////////////////////////////////////////////
// Function: RenderAttrib::compare_to_impl
// Access: Protected, Virtual
// Description: Intended to be overridden by derived RenderAttrib
// types to return a unique number indicating whether
// this RenderAttrib is equivalent to the other one.
//
// This should return 0 if the two RenderAttrib 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 RenderAttrib
// objects whose get_type() functions return the same.
////////////////////////////////////////////////////////////////////
int RenderAttrib::
compare_to_impl(const RenderAttrib *other) const {
return 0;
}
////////////////////////////////////////////////////////////////////
// Function: RenderAttrib::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.
//
// This should return the result of applying the other
// RenderAttrib to a node in the scene graph below this
// RenderAttrib, which was already applied. In most
// cases, the result is the same as the other
// 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.
////////////////////////////////////////////////////////////////////
CPT(RenderAttrib) RenderAttrib::
compose_impl(const RenderAttrib *other) const {
return other;
}
////////////////////////////////////////////////////////////////////
// Function: RenderAttrib::make_default_impl
// Access: Protected, Virtual
// Description: Intended to be overridden by derived RenderAttrib
// types to specify what the default property for a
// RenderAttrib of this type should be.
//
// This should return a newly-allocated RenderAttrib of
// the same type that corresponds to whatever the
// standard default for this kind of RenderAttrib is.
////////////////////////////////////////////////////////////////////
RenderAttrib *RenderAttrib::
make_default_impl() const {
return (RenderAttrib *)NULL;
}
////////////////////////////////////////////////////////////////////
// Function: RenderAttrib::write_datagram
// Access: Public, Virtual
// Description: Writes the contents of this object to the datagram
// for shipping out to a Bam file.
////////////////////////////////////////////////////////////////////
void RenderAttrib::
write_datagram(BamWriter *, Datagram &) {
}
////////////////////////////////////////////////////////////////////
// Function: RenderAttrib::finalize
// Access: Public, Virtual
// Description: Method to ensure that any necessary clean up tasks
// that have to be performed by this object are performed
////////////////////////////////////////////////////////////////////
void RenderAttrib::
finalize() {
// Unref the pointer that we explicitly reffed in make_from_bam().
unref();
// We should never get back to zero after unreffing our own count,
// because we expect to have been stored in a pointer somewhere. If
// we do get to zero, it's a memory leak; the way to avoid this is
// to call unref_delete() above instead of unref(), but this is
// dangerous to do from within a virtual function.
nassertv(get_ref_count() != 0);
}
////////////////////////////////////////////////////////////////////
// Function: RenderAttrib::new_from_bam
// Access: Protected, Static
// Description: Uniquifies the pointer for a RenderAttrib object just
// created from a bam file, and preserves its reference
// count correctly.
////////////////////////////////////////////////////////////////////
TypedWritable *RenderAttrib::
new_from_bam(RenderAttrib *attrib, BamReader *manager) {
// First, uniquify the pointer.
CPT(RenderAttrib) pointer = return_new(attrib);
// But now we have a problem, since we have to hold the reference
// count and there's no way to return a TypedWritable while still
// holding the reference count! We work around this by explicitly
// upping the count, and also setting a finalize() callback to down
// it later.
if (pointer == attrib) {
pointer->ref();
manager->register_finalize(attrib);
}
// We have to cast the pointer back to non-const, because the bam
// reader expects that.
return (RenderAttrib *)pointer.p();
}

View File

@ -0,0 +1,110 @@
// Filename: renderAttrib.h
// Created by: drose (21Feb02)
//
////////////////////////////////////////////////////////////////////
//
// 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 RENDERATTRIB_H
#define RENDERATTRIB_H
#include "pandabase.h"
#include "typedWritableReferenceCount.h"
#include "indirectCompareTo.h"
#include "pointerTo.h"
#include "pset.h"
////////////////////////////////////////////////////////////////////
// Class : RenderAttrib
// Description : This is the base class for a number of render
// attributes (other than transform) that may be set on
// scene graph nodes to control the appearance of
// geometry. This includes TextureAttrib, ColorAttrib,
// etc.
//
// You should not attempt to create or modify a
// RenderAttrib directly; instead, use the make() method
// of the appropriate kind of attrib you want. This
// will allocate and return a new RenderAttrib of the
// appropriate type, and it may share pointers if
// possible. Do not modify the new RenderAttrib if you
// wish to change its properties; instead, create a new
// one.
////////////////////////////////////////////////////////////////////
class EXPCL_PANDA RenderAttrib : public TypedWritableReferenceCount {
protected:
RenderAttrib();
private:
RenderAttrib(const RenderAttrib &copy);
void operator = (const RenderAttrib &copy);
public:
virtual ~RenderAttrib();
INLINE CPT(RenderAttrib) compose(const RenderAttrib *other) const;
INLINE CPT(RenderAttrib) make_default() const;
INLINE int compare_to(const RenderAttrib &other) const;
PUBLISHED:
virtual void output(ostream &out) const;
virtual void write(ostream &out, int indent_level) const;
protected:
static CPT(RenderAttrib) return_new(RenderAttrib *attrib);
virtual int compare_to_impl(const RenderAttrib *other) const;
virtual CPT(RenderAttrib) compose_impl(const RenderAttrib *other) const;
virtual RenderAttrib *make_default_impl() const=0;
private:
typedef pset<const RenderAttrib *, IndirectCompareTo<RenderAttrib> > Attribs;
static Attribs _attribs;
Attribs::iterator _saved_entry;
public:
virtual void write_datagram(BamWriter *manager, Datagram &dg);
virtual void finalize();
protected:
static TypedWritable *new_from_bam(RenderAttrib *attrib, BamReader *manager);
public:
static TypeHandle get_class_type() {
return _type_handle;
}
static void init_type() {
TypedWritableReferenceCount::init_type();
register_type(_type_handle, "RenderAttrib",
TypedWritableReferenceCount::get_class_type());
}
virtual TypeHandle get_type() const {
return get_class_type();
}
virtual TypeHandle force_init_type() {init_type(); return get_class_type();}
private:
static TypeHandle _type_handle;
};
INLINE ostream &operator << (ostream &out, const RenderAttrib &attrib) {
attrib.output(out);
return out;
}
#include "renderAttrib.I"
#endif

View File

@ -0,0 +1,150 @@
// Filename: renderState.I
// Created by: drose (21Feb02)
//
////////////////////////////////////////////////////////////////////
//
// 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: RenderState::Attribute::Constructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
INLINE RenderState::Attribute::
Attribute(const RenderAttrib *attrib, int override) :
_type(attrib->get_type()),
_attrib(attrib),
_override(override)
{
}
////////////////////////////////////////////////////////////////////
// Function: RenderState::Attribute::Constructor
// Access: Public
// Description: This constructor makes an invalid Attribute with no
// RenderAttrib pointer; its purpose is just to make an
// object we can use to look up a particular type in the
// Attribute set.
////////////////////////////////////////////////////////////////////
INLINE RenderState::Attribute::
Attribute(TypeHandle type) :
_type(type),
_attrib(NULL),
_override(0)
{
}
////////////////////////////////////////////////////////////////////
// Function: RenderState::Attribute::Copy Constructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
INLINE RenderState::Attribute::
Attribute(const Attribute &copy) :
_type(copy._type),
_attrib(copy._attrib),
_override(copy._override)
{
}
////////////////////////////////////////////////////////////////////
// Function: RenderState::Attribute::Copy Assignment Operator
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
INLINE void RenderState::Attribute::
operator = (const Attribute &copy) {
_type = copy._type;
_attrib = copy._attrib;
_override = copy._override;
}
////////////////////////////////////////////////////////////////////
// Function: RenderState::Attribute::operator <
// Access: Public
// Description: This is used by the Attributes set to uniquify
// RenderAttributes by type. Only one RenderAttrib of a
// given type is allowed in the set. This ordering must
// also match the ordering reported by compare_to().
////////////////////////////////////////////////////////////////////
INLINE bool RenderState::Attribute::
operator < (const Attribute &other) const {
return _type < other._type;
}
////////////////////////////////////////////////////////////////////
// Function: RenderState::Attribute::compare_to
// Access: Public
// Description: Provides an indication of whether a particular
// attribute is equivalent to another one, for purposes
// of generating unique RenderStates. This should
// compare all properties of the Attribute, but it is
// important that the type is compared first, to be
// consistent with the ordering defined by operator <.
////////////////////////////////////////////////////////////////////
INLINE int RenderState::Attribute::
compare_to(const Attribute &other) const {
if (_type != other._type) {
return _type.get_index() - other._type.get_index();
}
if (_attrib != other._attrib) {
return _attrib - other._attrib;
}
return _override - other._override;
}
////////////////////////////////////////////////////////////////////
// Function: RenderState::is_empty
// Access: Published
// Description: Returns true if the state is empty, false otherwise.
////////////////////////////////////////////////////////////////////
INLINE bool RenderState::
is_empty() const {
return _attributes.empty();
}
////////////////////////////////////////////////////////////////////
// Function: RenderState::get_num_attribs
// Access: Published
// Description: Returns the number of separate attributes indicated
// in the state.
////////////////////////////////////////////////////////////////////
INLINE int RenderState::
get_num_attribs() const {
return _attributes.size();
}
////////////////////////////////////////////////////////////////////
// Function: RenderState::get_attrib
// Access: Published
// Description: Returns the nth attribute in the state.
////////////////////////////////////////////////////////////////////
INLINE const RenderAttrib *RenderState::
get_attrib(int n) const {
nassertr(n >= 0 && n < (int)_attributes.size(), NULL);
return _attributes[n]._attrib;
}
////////////////////////////////////////////////////////////////////
// Function: RenderState::get_override
// Access: Published
// Description: Returns the override associated with the nth
// attribute in the state.
////////////////////////////////////////////////////////////////////
INLINE int RenderState::
get_override(int n) const {
nassertr(n >= 0 && n < (int)_attributes.size(), 0);
return _attributes[n]._override;
}

View File

@ -0,0 +1,631 @@
// Filename: renderState.cxx
// Created by: drose (21Feb02)
//
////////////////////////////////////////////////////////////////////
//
// 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 "renderState.h"
#include "bamReader.h"
#include "bamWriter.h"
#include "datagramIterator.h"
#include "indent.h"
#include "compareTo.h"
RenderState::States RenderState::_states;
CPT(RenderState) RenderState::_empty_state;
TypeHandle RenderState::_type_handle;
////////////////////////////////////////////////////////////////////
// Function: RenderState::Constructor
// Access: Protected
// Description: Actually, this could be a private constructor, since
// no one inherits from RenderState, but gcc gives us a
// spurious warning if all constructors are private.
////////////////////////////////////////////////////////////////////
RenderState::
RenderState() {
_saved_entry = _states.end();
_self_compose = (RenderState *)NULL;
}
////////////////////////////////////////////////////////////////////
// Function: RenderState::Copy Constructor
// Access: Private
// Description: RenderStates are not meant to be copied.
////////////////////////////////////////////////////////////////////
RenderState::
RenderState(const RenderState &) {
nassertv(false);
}
////////////////////////////////////////////////////////////////////
// Function: RenderState::Copy Assignment Operator
// Access: Private
// Description: RenderStates are not meant to be copied.
////////////////////////////////////////////////////////////////////
void RenderState::
operator = (const RenderState &) {
nassertv(false);
}
////////////////////////////////////////////////////////////////////
// Function: RenderState::Destructor
// Access: Public, Virtual
// Description: The destructor is responsible for removing the
// RenderState from the global set if it is there.
////////////////////////////////////////////////////////////////////
RenderState::
~RenderState() {
// Remove the deleted RenderState object from the global pool.
if (_saved_entry != _states.end()) {
_states.erase(_saved_entry);
_saved_entry = _states.end();
cerr << "Removing " << (void *)this << ", " << _states.size()
<< " remaining.\n";
}
// Now make sure we clean up all other floating pointers to the
// RenderState. These may be scattered around in the various
// CompositionCaches from other RenderState objects.
// Fortunately, since we added CompositionCache records in pairs, we
// know exactly the set of RenderState objects that have us in their
// cache: it's the same set of RenderState objects that we have in
// our own cache.
// We do need to put some thought into this loop, because as we
// clear out cache entries we'll cause other RenderState objects to
// destruct, which could cause things to get pulled out of our own
// _composition_cache map. We don't want to get bitten by this
// cascading effect.
CompositionCache::iterator ci;
ci = _composition_cache.begin();
while (ci != _composition_cache.end()) {
{
PT(RenderState) other = (RenderState *)(*ci).first;
Composition comp = (*ci).second;
// We should never have a reflexive entry in this map. If we
// do, something got screwed up elsewhere.
nassertv(other != this);
// Now we're holding a reference count to the other state, as well
// as to the computed result (if any), so neither object will be
// tempted to destruct. Go ahead and remove ourselves from the
// other cache.
other->_composition_cache.erase(this);
// It's all right if the other state destructs now, since it
// won't try to remove itself from our own composition cache any
// more. Someone might conceivably delete the *next* entry,
// though, so we should be sure to let all that deleting finish
// up before we attempt to increment ci, by closing the scope
// here.
}
// Now it's safe to increment ci, because the current cache entry
// has not gone away, and if the next one has, by now it's safely
// gone.
++ci;
}
// Also, if we called compose(this) at some point and the return
// value was something other than this, we need to decrement the
// associated reference count.
if (_self_compose != (RenderState *)NULL && _self_compose != this) {
unref_delete((RenderState *)_self_compose);
}
}
////////////////////////////////////////////////////////////////////
// Function: RenderState::operator <
// Access: Public
// Description: Provides an arbitrary ordering among all unique
// RenderStates, so we can store the essentially
// different ones in a big set and throw away the rest.
//
// This method is not needed outside of the RenderState
// class because all equivalent RenderState objects are
// guaranteed to share the same pointer; thus, a pointer
// comparison is always sufficient.
////////////////////////////////////////////////////////////////////
bool RenderState::
operator < (const RenderState &other) const {
// We must compare all the properties of the attributes, not just
// the type; thus, we compare them one at a time using compare_to().
return lexicographical_compare(_attributes.begin(), _attributes.end(),
other._attributes.begin(), other._attributes.end(),
CompareTo<Attribute>());
}
////////////////////////////////////////////////////////////////////
// Function: RenderState::find_attrib
// Access: Published
// Description: Searches for an attribute with the indicated type in
// the state, and returns its index if it is found, or
// -1 if it is not.
////////////////////////////////////////////////////////////////////
int RenderState::
find_attrib(TypeHandle type) const {
Attributes::const_iterator ai = _attributes.find(Attribute(type));
if (ai == _attributes.end()) {
return -1;
}
return ai - _attributes.begin();
}
////////////////////////////////////////////////////////////////////
// Function: RenderState::make_empty
// Access: Published, Static
// Description: Returns a RenderState with no attributes set.
////////////////////////////////////////////////////////////////////
CPT(RenderState) RenderState::
make_empty() {
// The empty state is asked for so often, we make it a special case
// and store a pointer forever once we find it the first time.
if (_empty_state == (RenderState *)NULL) {
RenderState *state = new RenderState;
_empty_state = return_new(state);
}
return _empty_state;
}
////////////////////////////////////////////////////////////////////
// Function: RenderState::make
// Access: Published, Static
// Description: Returns a RenderState with one attribute set.
////////////////////////////////////////////////////////////////////
CPT(RenderState) RenderState::
make(const RenderAttrib *attrib, int override) {
RenderState *state = new RenderState;
state->_attributes.reserve(1);
state->_attributes.insert(Attribute(attrib, override));
return return_new(state);
}
////////////////////////////////////////////////////////////////////
// Function: RenderState::make
// Access: Published, Static
// Description: Returns a RenderState with two attributes set.
////////////////////////////////////////////////////////////////////
CPT(RenderState) RenderState::
make(const RenderAttrib *attrib1,
const RenderAttrib *attrib2, int override) {
RenderState *state = new RenderState;
state->_attributes.reserve(2);
state->_attributes.push_back(Attribute(attrib1, override));
state->_attributes.push_back(Attribute(attrib2, override));
state->_attributes.sort();
return return_new(state);
}
////////////////////////////////////////////////////////////////////
// Function: RenderState::make
// Access: Published, Static
// Description: Returns a RenderState with three attributes set.
////////////////////////////////////////////////////////////////////
CPT(RenderState) RenderState::
make(const RenderAttrib *attrib1,
const RenderAttrib *attrib2,
const RenderAttrib *attrib3, int override) {
RenderState *state = new RenderState;
state->_attributes.reserve(2);
state->_attributes.push_back(Attribute(attrib1, override));
state->_attributes.push_back(Attribute(attrib2, override));
state->_attributes.push_back(Attribute(attrib3, override));
state->_attributes.sort();
return return_new(state);
}
////////////////////////////////////////////////////////////////////
// Function: RenderState::make
// Access: Published, Static
// Description: Returns a RenderState with four attributes set.
////////////////////////////////////////////////////////////////////
CPT(RenderState) RenderState::
make(const RenderAttrib *attrib1,
const RenderAttrib *attrib2,
const RenderAttrib *attrib3,
const RenderAttrib *attrib4, int override) {
RenderState *state = new RenderState;
state->_attributes.reserve(2);
state->_attributes.push_back(Attribute(attrib1, override));
state->_attributes.push_back(Attribute(attrib2, override));
state->_attributes.push_back(Attribute(attrib3, override));
state->_attributes.push_back(Attribute(attrib4, override));
state->_attributes.sort();
return return_new(state);
}
////////////////////////////////////////////////////////////////////
// Function: RenderState::compose
// Access: Published
// Description: Returns a new RenderState object that represents the
// composition of this state with the other state.
//
// The result of this operation is cached, and will be
// retained as long as both this RenderState object and
// the other RenderState object continue to exist.
// Should one of them destruct, the cached entry will be
// removed, and its pointer will be allowed to destruct
// as well.
////////////////////////////////////////////////////////////////////
CPT(RenderState) RenderState::
compose(const RenderState *other) const {
// This method isn't strictly const, because it updates the cache,
// but we pretend that it is because it's only a cache which is
// transparent to the rest of the interface.
cerr << "composing " << *this << " with " << *other << "\n";
if (other == this) {
// compose(this) has to be handled as a special case, because the
// caching problem is so different.
if (_self_compose != (RenderState *)NULL) {
return _self_compose;
}
CPT(RenderState) result = do_compose(this);
((RenderState *)this)->_self_compose = result;
if (result != this) {
// If the result of compose(this) is something other than this,
// explicitly increment the reference count. We have to be sure
// to decrement it again later, in our destructor.
_self_compose->ref();
// (If the result was just this again, we still store the
// result, but we don't increment the reference count, since
// that would be a self-referential leak. What a mess this is.)
}
return _self_compose;
}
// Is this composition already cached?
CompositionCache::const_iterator ci = _composition_cache.find(other);
if (ci != _composition_cache.end()) {
const Composition &comp = (*ci).second;
if (comp._result == (const RenderState *)NULL) {
// Well, it wasn't cached already, but we already had an entry
// (probably created for the reverse direction), so use the same
// entry to store the new result.
((Composition &)comp)._result = do_compose(other);
}
// Here's the cache!
cerr << " returning cached result " << (void *)comp._result.p() << "\n";
return comp._result;
}
// We need to make a new cache entry, both in this object and in the
// other object. We make both records so the other RenderState
// object will know to delete the entry from this object when it
// destructs, and vice-versa.
// The cache entry in this object is the only one that indicates the
// result; the other will be NULL for now.
CPT(RenderState) result = do_compose(other);
// We store them in this order, on the off-chance that other is the
// same as this, a degenerate case which is still worth supporting.
((RenderState *)other)->_composition_cache[this]._result = NULL;
((RenderState *)this)->_composition_cache[other]._result = result;
cerr << " returning new result " << (void *)result.p() << "\n";
return result;
}
////////////////////////////////////////////////////////////////////
// Function: RenderState::add
// Access: Published
// Description: Returns a new RenderState object that represents the
// same as the source state, with the new RenderAttrib
// added. If there is already a RenderAttrib with the
// same type, it is replaced.
////////////////////////////////////////////////////////////////////
CPT(RenderState) RenderState::
add(const RenderAttrib *attrib, int override) const {
RenderState *new_state = new RenderState;
back_insert_iterator<Attributes> result =
back_inserter(new_state->_attributes);
Attribute new_attribute(attrib, override);
Attributes::const_iterator ai = _attributes.begin();
while (ai != _attributes.end() && (*ai) < new_attribute) {
*result = *ai;
++ai;
++result;
}
*result = new_attribute;
++result;
while (ai != _attributes.end()) {
*result = *ai;
++ai;
++result;
}
return return_new(new_state);
}
////////////////////////////////////////////////////////////////////
// Function: RenderState::remove
// Access: Published
// Description: Returns a new RenderState object that represents the
// same as the source state, with the indicated
// RenderAttrib removed
////////////////////////////////////////////////////////////////////
CPT(RenderState) RenderState::
remove(TypeHandle type) const {
RenderState *new_state = new RenderState;
back_insert_iterator<Attributes> result =
back_inserter(new_state->_attributes);
Attributes::const_iterator ai = _attributes.begin();
while (ai != _attributes.end()) {
if ((*ai)._type != type) {
*result = *ai;
++result;
}
++ai;
}
return return_new(new_state);
}
////////////////////////////////////////////////////////////////////
// Function: RenderState::output
// Access: Public, Virtual
// Description:
////////////////////////////////////////////////////////////////////
void RenderState::
output(ostream &out) const {
if (_attributes.empty()) {
out << "empty";
} else {
Attributes::const_iterator ai = _attributes.begin();
out << (*ai)._type;
++ai;
while (ai != _attributes.end()) {
out << " " << (*ai)._type;
++ai;
}
}
}
////////////////////////////////////////////////////////////////////
// Function: RenderState::write
// Access: Public, Virtual
// Description:
////////////////////////////////////////////////////////////////////
void RenderState::
write(ostream &out, int indent_level) const {
indent(out, indent_level) << _attributes.size() << " attribs:\n";
Attributes::const_iterator ai;
for (ai = _attributes.begin(); ai != _attributes.end(); ++ai) {
const Attribute &attribute = (*ai);
attribute._attrib->write(out, indent_level + 2);
}
}
////////////////////////////////////////////////////////////////////
// Function: RenderState::return_new
// Access: Private, Static
// Description: This function is used to share a common RenderState
// pointer for all equivalent RenderState objects.
//
// See the similar logic in RenderAttrib. The idea is
// to create a new RenderState object and pass it
// through this function, which will share the pointer
// with a previously-created RenderState object if it is
// equivalent.
////////////////////////////////////////////////////////////////////
CPT(RenderState) RenderState::
return_new(RenderState *state) {
cerr << "RenderState::return_new(" << *state << ")\n";
nassertr(state != (RenderState *)NULL, state);
// This should be a newly allocated pointer, not one that was used
// for anything else.
nassertr(state->_saved_entry == _states.end(), state);
// Save the state in a local PointerTo so that it will be freed at
// the end of this function if no one else uses it.
CPT(RenderState) pt_state = state;
pair<States::iterator, bool> result = _states.insert(state);
if (result.second) {
// The state was inserted; save the iterator and return the
// input state.
state->_saved_entry = result.first;
cerr << " produces new pointer " << (void *)pt_state.p() << "\n";
return pt_state;
}
// The state was not inserted; there must be an equivalent one
// already in the set. Return that one.
cerr << " returns old pointer " << (void *)(*(result.first)) << "\n";
return *(result.first);
}
////////////////////////////////////////////////////////////////////
// Function: RenderState::do_compose
// Access: Private
// Description: The private implemention of compose(); this actually
// composes two RenderStates, without bothering with the
// cache.
////////////////////////////////////////////////////////////////////
CPT(RenderState) RenderState::
do_compose(const RenderState *other) const {
// First, build a new Attributes member that represents the union of
// this one and that one.
Attributes::const_iterator ai = _attributes.begin();
Attributes::const_iterator bi = other->_attributes.begin();
// Create a new RenderState that will hold the result.
RenderState *new_state = new RenderState;
back_insert_iterator<Attributes> result =
back_inserter(new_state->_attributes);
while (ai != _attributes.end() && bi != other->_attributes.end()) {
if ((*ai) < (*bi)) {
// Here is an attribute that we have in the original, which is
// not present in the secondary.
*result = *ai;
++ai;
++result;
} else if ((*bi) < (*ai)) {
// Here is a new attribute we have in the secondary, that was
// not present in the original.
*result = *bi;
++bi;
++result;
} else {
// Here is an attribute we have in both. Does one override the
// other?
const Attribute &a = (*ai);
const Attribute &b = (*bi);
if (a._override < b._override) {
// B overrides.
*result = *bi;
} else if (b._override < a._override) {
// A overrides.
*result = *bi;
} else {
// No, they're equivalent, so compose them.
*result = Attribute(a._attrib->compose(b._attrib), b._override);
}
++ai;
++bi;
++result;
}
}
while (ai != _attributes.end()) {
*result = *ai;
++ai;
++result;
}
while (bi != other->_attributes.end()) {
*result = *bi;
++bi;
++result;
}
return return_new(new_state);
}
////////////////////////////////////////////////////////////////////
// Function: RenderState::register_with_read_factory
// Access: Public, Static
// Description: Tells the BamReader how to create objects of type
// RenderState.
////////////////////////////////////////////////////////////////////
void RenderState::
register_with_read_factory() {
BamReader::get_factory()->register_factory(get_class_type(), make_from_bam);
}
////////////////////////////////////////////////////////////////////
// Function: RenderState::write_datagram
// Access: Public, Virtual
// Description: Writes the contents of this object to the datagram
// for shipping out to a Bam file.
////////////////////////////////////////////////////////////////////
void RenderState::
write_datagram(BamWriter *manager, Datagram &dg) {
}
////////////////////////////////////////////////////////////////////
// Function: RenderState::finalize
// Access: Public, Virtual
// Description: Method to ensure that any necessary clean up tasks
// that have to be performed by this object are performed
////////////////////////////////////////////////////////////////////
void RenderState::
finalize() {
// Unref the pointer that we explicitly reffed in make_from_bam().
unref();
// We should never get back to zero after unreffing our own count,
// because we expect to have been stored in a pointer somewhere. If
// we do get to zero, it's a memory leak; the way to avoid this is
// to call unref_delete() above instead of unref(), but this is
// dangerous to do from within a virtual function.
nassertv(get_ref_count() != 0);
}
////////////////////////////////////////////////////////////////////
// Function: RenderState::make_from_bam
// Access: Protected, Static
// Description: This function is called by the BamReader's factory
// when a new object of type RenderState is encountered
// in the Bam file. It should create the RenderState
// and extract its information from the file.
////////////////////////////////////////////////////////////////////
TypedWritable *RenderState::
make_from_bam(const FactoryParams &params) {
RenderState *state = new RenderState;
DatagramIterator scan;
BamReader *manager;
parse_params(params, scan, manager);
state->fillin(scan, manager);
return new_from_bam(state, manager);
}
////////////////////////////////////////////////////////////////////
// Function: RenderState::new_from_bam
// Access: Protected, Static
// Description: Uniquifies the pointer for a RenderState object just
// created from a bam file, and preserves its reference
// count correctly.
////////////////////////////////////////////////////////////////////
TypedWritable *RenderState::
new_from_bam(RenderState *state, BamReader *manager) {
// First, uniquify the pointer.
CPT(RenderState) pointer = return_new(state);
// But now we have a problem, since we have to hold the reference
// count and there's no way to return a TypedWritable while still
// holding the reference count! We work around this by explicitly
// upping the count, and also setting a finalize() callback to down
// it later.
if (pointer == state) {
pointer->ref();
manager->register_finalize(state);
}
// We have to cast the pointer back to non-const, because the bam
// reader expects that.
return (RenderState *)pointer.p();
}
////////////////////////////////////////////////////////////////////
// Function: RenderState::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 RenderState.
////////////////////////////////////////////////////////////////////
void RenderState::
fillin(DatagramIterator &scan, BamReader *manager) {
}

View File

@ -0,0 +1,172 @@
// Filename: renderState.h
// Created by: drose (21Feb02)
//
////////////////////////////////////////////////////////////////////
//
// 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 RENDERSTATE_H
#define RENDERSTATE_H
#include "pandabase.h"
#include "renderAttrib.h"
#include "typedWritableReferenceCount.h"
#include "pointerTo.h"
#include "indirectLess.h"
#include "ordered_vector.h"
////////////////////////////////////////////////////////////////////
// Class : RenderState
// Description : This represents a unique collection of RenderAttrib
// objects that correspond to a particular renderable
// state.
//
// You should not attempt to create or modify a
// RenderState object directly. Instead, call one of
// the make() functions to create one for you. And
// instead of modifying a RenderState object, create a
// new one.
////////////////////////////////////////////////////////////////////
class EXPCL_PANDA RenderState : public TypedWritableReferenceCount {
protected:
RenderState();
private:
RenderState(const RenderState &copy);
void operator = (const RenderState &copy);
public:
virtual ~RenderState();
bool operator < (const RenderState &other) const;
PUBLISHED:
INLINE bool is_empty() const;
INLINE int get_num_attribs() const;
INLINE const RenderAttrib *get_attrib(int n) const;
INLINE int get_override(int n) const;
int find_attrib(TypeHandle type) const;
static CPT(RenderState) make_empty();
static CPT(RenderState) make(const RenderAttrib *attrib, int override = 0);
static CPT(RenderState) make(const RenderAttrib *attrib1,
const RenderAttrib *attrib2, int override = 0);
static CPT(RenderState) make(const RenderAttrib *attrib1,
const RenderAttrib *attrib2,
const RenderAttrib *attrib3, int override = 0);
static CPT(RenderState) make(const RenderAttrib *attrib1,
const RenderAttrib *attrib2,
const RenderAttrib *attrib3,
const RenderAttrib *attrib4, int override = 0);
CPT(RenderState) compose(const RenderState *other) const;
CPT(RenderState) add(const RenderAttrib *attrib, int override = 0) const;
CPT(RenderState) remove(TypeHandle type) const;
void output(ostream &out) const;
void write(ostream &out, int indent_level) const;
private:
static CPT(RenderState) return_new(RenderState *state);
CPT(RenderState) do_compose(const RenderState *other) const;
private:
typedef pset<const RenderState *, IndirectLess<RenderState> > States;
static States _states;
static CPT(RenderState) _empty_state;
// This iterator records the entry corresponding to this RenderState
// object in the above global set. We keep the iterator around so
// we can remove it when the RenderState destructs.
States::iterator _saved_entry;
// This data structure manages the job of caching the composition of
// two RenderStates. It's complicated because we have to be sure to
// remove the entry if *either* of the input RenderStates destructs.
// To implement this, we always record Composition entries in pairs,
// one in each of the two involved RenderState objects.
class Composition {
public:
CPT(RenderState) _result;
};
typedef pmap<const RenderState *, Composition> CompositionCache;
CompositionCache _composition_cache;
// This pointer is used to cache the result of compose(this). This
// has to be a special case, because we have to handle the reference
// counts carefully so that we don't leak. Most of the time, the
// result of compose(this) is this, which should not be reference
// counted, but other times the result is something else (which
// should be).
const RenderState *_self_compose;
// This is the actual set of data within the RenderState: a set of
// RenderAttribs.
class Attribute {
public:
INLINE Attribute(const RenderAttrib *attrib, int override);
INLINE Attribute(TypeHandle type);
INLINE Attribute(const Attribute &copy);
INLINE void operator = (const Attribute &copy);
INLINE bool operator < (const Attribute &other) const;
INLINE int compare_to(const Attribute &other) const;
TypeHandle _type;
CPT(RenderAttrib) _attrib;
int _override;
};
typedef ov_set<Attribute> Attributes;
Attributes _attributes;
public:
static void register_with_read_factory();
virtual void write_datagram(BamWriter *manager, Datagram &dg);
virtual void finalize();
protected:
static TypedWritable *make_from_bam(const FactoryParams &params);
static TypedWritable *new_from_bam(RenderState *state, BamReader *manager);
void fillin(DatagramIterator &scan, BamReader *manager);
public:
static TypeHandle get_class_type() {
return _type_handle;
}
static void init_type() {
TypedWritableReferenceCount::init_type();
register_type(_type_handle, "RenderState",
TypedWritableReferenceCount::get_class_type());
}
virtual TypeHandle get_type() const {
return get_class_type();
}
virtual TypeHandle force_init_type() {init_type(); return get_class_type();}
private:
static TypeHandle _type_handle;
};
INLINE ostream &operator << (ostream &out, const RenderState &state) {
state.output(out);
return out;
}
#include "renderState.I"
#endif

View File

@ -0,0 +1,82 @@
// Filename: test_pgraph.cxx
// Created by: drose (21Feb02)
//
////////////////////////////////////////////////////////////////////
//
// 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 "pandaNode.h"
#include "textureAttrib.h"
#include "colorAttrib.h"
#include "texture.h"
void
list_hierarchy(PandaNode *node, int indent_level) {
node->write(cerr, indent_level);
PandaNode::Children cr = node->get_children();
int num_children = cr.get_num_children();
for (int i = 0; i < num_children; i++) {
list_hierarchy(cr.get_child(i), indent_level + 2);
}
}
int
main(int argc, char *argv[]) {
PT(Texture) tex = new Texture;
tex->set_name("tex");
PT(PandaNode) root = new PandaNode("root");
root->set_attrib(TextureAttrib::make_off());
root->set_attrib(ColorAttrib::make_flat(Colorf(1, 0, 0, 1)));
PandaNode *a = new PandaNode("a");
root->add_child(a);
a->set_attrib(TextureAttrib::make(tex));
PandaNode *b = new PandaNode("b");
root->add_child(b);
b->set_attrib(ColorAttrib::make_vertex());
PandaNode *a1 = new PandaNode("a1");
a->add_child(a1);
cerr << "\n";
list_hierarchy(root, 0);
cerr << "\nroot's attribs:\n";
root->get_state()->write(cerr, 0);
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);
return 0;
}

View File

@ -0,0 +1,52 @@
// Filename: textureAttrib.I
// Created by: drose (21Feb02)
//
////////////////////////////////////////////////////////////////////
//
// 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: TextureAttrib::Constructor
// Access: Private
// Description: Use TextureAttrib::make() to construct a new
// TextureAttrib object.
////////////////////////////////////////////////////////////////////
INLINE TextureAttrib::
TextureAttrib() {
}
////////////////////////////////////////////////////////////////////
// Function: TextureAttrib::is_off
// Access: Published
// Description: Returns true if the TextureAttrib is an 'off'
// TextureAttrib, indicating that it should disable
// texturing.
////////////////////////////////////////////////////////////////////
INLINE bool TextureAttrib::
is_off() const {
return _texture == (Texture *)NULL;
}
////////////////////////////////////////////////////////////////////
// Function: TextureAttrib::get_texture
// Access: Published
// Description: If the TextureAttrib is not an 'off' TextureAttrib,
// returns the texture that is associated. Otherwise,
// return NULL.
////////////////////////////////////////////////////////////////////
INLINE Texture *TextureAttrib::
get_texture() const {
return _texture;
}

View File

@ -0,0 +1,99 @@
// Filename: textureAttrib.cxx
// Created by: drose (21Feb02)
//
////////////////////////////////////////////////////////////////////
//
// 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 "textureAttrib.h"
TypeHandle TextureAttrib::_type_handle;
////////////////////////////////////////////////////////////////////
// Function: TextureAttrib::make
// Access: Published, Static
// Description: Constructs a new TextureAttrib object suitable for
// rendering the indicated texture onto geometry.
////////////////////////////////////////////////////////////////////
CPT(RenderAttrib) TextureAttrib::
make(Texture *texture) {
TextureAttrib *attrib = new TextureAttrib;
attrib->_texture = texture;
return return_new(attrib);
}
////////////////////////////////////////////////////////////////////
// Function: TextureAttrib::make_off
// Access: Published, Static
// Description: Constructs a new TextureAttrib object suitable for
// rendering untextured geometry.
////////////////////////////////////////////////////////////////////
CPT(RenderAttrib) TextureAttrib::
make_off() {
TextureAttrib *attrib = new TextureAttrib;
return return_new(attrib);
}
////////////////////////////////////////////////////////////////////
// Function: TextureAttrib::output
// Access: Public, Virtual
// Description:
////////////////////////////////////////////////////////////////////
void TextureAttrib::
output(ostream &out) const {
out << get_type() << ":";
if (is_off()) {
out << "(off)";
} else {
out << _texture->get_name();
}
}
////////////////////////////////////////////////////////////////////
// Function: TextureAttrib::compare_to_impl
// Access: Protected, Virtual
// Description: Intended to be overridden by derived TextureAttrib
// types to return a unique number indicating whether
// this TextureAttrib is equivalent to the other one.
//
// This should return 0 if the two TextureAttrib 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 TextureAttrib
// objects whose get_type() functions return the same.
////////////////////////////////////////////////////////////////////
int TextureAttrib::
compare_to_impl(const RenderAttrib *other) const {
const TextureAttrib *ta;
DCAST_INTO_R(ta, other, 0);
return (int)(_texture - ta->_texture);
}
////////////////////////////////////////////////////////////////////
// Function: TextureAttrib::make_default_impl
// Access: Protected, Virtual
// Description: Intended to be overridden by derived TextureAttrib
// types to specify what the default property for a
// TextureAttrib of this type should be.
//
// This should return a newly-allocated TextureAttrib of
// the same type that corresponds to whatever the
// standard default for this kind of TextureAttrib is.
////////////////////////////////////////////////////////////////////
RenderAttrib *TextureAttrib::
make_default_impl() const {
return new TextureAttrib;
}

View File

@ -0,0 +1,75 @@
// Filename: textureAttrib.h
// Created by: drose (21Feb02)
//
////////////////////////////////////////////////////////////////////
//
// 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 TEXTUREATTRIB_H
#define TEXTUREATTRIB_H
#include "pandabase.h"
#include "renderAttrib.h"
#include "texture.h"
////////////////////////////////////////////////////////////////////
// Class : TextureAttrib
// Description : Indicates which texture should be applied as the
// primary texture. Also see TextureAttrib2 for the
// secondary texture.
////////////////////////////////////////////////////////////////////
class EXPCL_PANDA TextureAttrib : public RenderAttrib {
private:
INLINE TextureAttrib();
PUBLISHED:
static CPT(RenderAttrib) make(Texture *tex);
static CPT(RenderAttrib) make_off();
INLINE bool is_off() const;
INLINE Texture *get_texture() const;
public:
virtual void output(ostream &out) const;
protected:
virtual int compare_to_impl(const RenderAttrib *other) const;
virtual RenderAttrib *make_default_impl() const;
private:
PT(Texture) _texture;
public:
static TypeHandle get_class_type() {
return _type_handle;
}
static void init_type() {
TypedWritableReferenceCount::init_type();
register_type(_type_handle, "TextureAttrib",
TypedWritableReferenceCount::get_class_type());
}
virtual TypeHandle get_type() const {
return get_class_type();
}
virtual TypeHandle force_init_type() {init_type(); return get_class_type();}
private:
static TypeHandle _type_handle;
};
#include "textureAttrib.I"
#endif