more refinements

This commit is contained in:
David Rose 2002-02-23 18:28:02 +00:00
parent 7feba65c50
commit 1ac667d4c6
28 changed files with 1639 additions and 101 deletions

View File

@ -8,32 +8,40 @@
#define SOURCES \
colorAttrib.h colorAttrib.I \
config_pgraph.h \
cullHandler.h \
qpcullTraverser.h qpcullTraverser.I \
cycleData.h cycleData.I \
cycleDataReader.h cycleDataReader.I \
cycleDataWriter.h cycleDataWriter.I \
qpgeomNode.h qpgeomNode.I \
pandaNode.h pandaNode.I \
pipeline.h pipeline.I \
pipelineCycler.h pipelineCycler.I \
pipelineCyclerBase.h pipelineCyclerBase.I \
renderAttrib.h renderAttrib.I \
renderState.h renderState.I \
textureAttrib.h textureAttrib.I
textureAttrib.h textureAttrib.I \
transformAttrib.h transformAttrib.I
#define COMBINED_SOURCES $[TARGET]_composite1.cxx $[TARGET]_composite2.cxx
// #define SOURCES $[SOURCES] \
#define INCLUDED_SOURCES \
// #define COMBINED_SOURCES $[TARGET]_composite1.cxx $[TARGET]_composite2.cxx
// #define INCLUDED_SOURCES \
#define SOURCES $[SOURCES] \
colorAttrib.cxx \
config_pgraph.cxx \
cullHandler.cxx \
qpcullTraverser.cxx \
cycleData.cxx \
cycleDataReader.cxx \
cycleDataWriter.cxx \
qpgeomNode.cxx \
pandaNode.cxx \
pipeline.cxx \
pipelineCycler.cxx \
pipelineCyclerBase.cxx \
renderAttrib.cxx \
renderState.cxx \
textureAttrib.cxx
textureAttrib.cxx \
transformAttrib.cxx
#define INSTALL_HEADERS \
pandaNode.h pandaNode.I

View File

@ -18,6 +18,10 @@
#include "colorAttrib.h"
#include "dcast.h"
#include "bamReader.h"
#include "bamWriter.h"
#include "datagram.h"
#include "datagramIterator.h"
TypeHandle ColorAttrib::_type_handle;
@ -30,7 +34,7 @@ TypeHandle ColorAttrib::_type_handle;
////////////////////////////////////////////////////////////////////
CPT(RenderAttrib) ColorAttrib::
make_vertex() {
ColorAttrib *attrib = new ColorAttrib(T_vertex, Colorf(0.0f, 0.0f, 0.0f, 1.0f));
ColorAttrib *attrib = new ColorAttrib(T_vertex);
return return_new(attrib);
}
@ -55,7 +59,7 @@ make_flat(const Colorf &color) {
////////////////////////////////////////////////////////////////////
CPT(RenderAttrib) ColorAttrib::
make_off() {
ColorAttrib *attrib = new ColorAttrib(T_off, Colorf(0.0f, 0.0f, 0.0f, 1.0f));
ColorAttrib *attrib = new ColorAttrib(T_off);
return return_new(attrib);
}
@ -123,5 +127,59 @@ compare_to_impl(const RenderAttrib *other) const {
////////////////////////////////////////////////////////////////////
RenderAttrib *ColorAttrib::
make_default_impl() const {
return new ColorAttrib(T_vertex, Colorf(0.0f, 0.0f, 0.0f, 1.0f));
return new ColorAttrib;
}
////////////////////////////////////////////////////////////////////
// Function: ColorAttrib::register_with_read_factory
// Access: Public, Static
// Description: Tells the BamReader how to create objects of type
// ColorAttrib.
////////////////////////////////////////////////////////////////////
void ColorAttrib::
register_with_read_factory() {
BamReader::get_factory()->register_factory(get_class_type(), make_from_bam);
}
////////////////////////////////////////////////////////////////////
// Function: ColorAttrib::write_datagram
// Access: Public, Virtual
// Description: Writes the contents of this object to the datagram
// for shipping out to a Bam file.
////////////////////////////////////////////////////////////////////
void ColorAttrib::
write_datagram(BamWriter *manager, Datagram &dg) {
RenderAttrib::write_datagram(manager, dg);
}
////////////////////////////////////////////////////////////////////
// Function: ColorAttrib::make_from_bam
// Access: Protected, Static
// Description: This function is called by the BamReader's factory
// when a new object of type ColorAttrib is encountered
// in the Bam file. It should create the ColorAttrib
// and extract its information from the file.
////////////////////////////////////////////////////////////////////
TypedWritable *ColorAttrib::
make_from_bam(const FactoryParams &params) {
ColorAttrib *attrib = new ColorAttrib;
DatagramIterator scan;
BamReader *manager;
parse_params(params, scan, manager);
attrib->fillin(scan, manager);
return new_from_bam(attrib, manager);
}
////////////////////////////////////////////////////////////////////
// Function: ColorAttrib::fillin
// Access: Protected
// Description: This internal function is called by make_from_bam to
// read in all of the relevant data from the BamFile for
// the new ColorAttrib.
////////////////////////////////////////////////////////////////////
void ColorAttrib::
fillin(DatagramIterator &scan, BamReader *manager) {
RenderAttrib::fillin(scan, manager);
}

View File

@ -36,7 +36,8 @@ PUBLISHED:
};
private:
INLINE ColorAttrib(Type type, const Colorf &color);
INLINE ColorAttrib(Type type = T_vertex,
const Colorf &color = Colorf(0.0f, 0.0f, 0.0f, 1.0f));
PUBLISHED:
static CPT(RenderAttrib) make_vertex();
@ -56,15 +57,23 @@ protected:
private:
Type _type;
Colorf _color;
public:
static void register_with_read_factory();
virtual void write_datagram(BamWriter *manager, Datagram &dg);
protected:
static TypedWritable *make_from_bam(const FactoryParams &params);
void fillin(DatagramIterator &scan, BamReader *manager);
public:
static TypeHandle get_class_type() {
return _type_handle;
}
static void init_type() {
TypedWritableReferenceCount::init_type();
RenderAttrib::init_type();
register_type(_type_handle, "ColorAttrib",
TypedWritableReferenceCount::get_class_type());
RenderAttrib::get_class_type());
}
virtual TypeHandle get_type() const {
return get_class_type();

View File

@ -19,10 +19,12 @@
#include "config_pgraph.h"
#include "colorAttrib.h"
#include "qpgeomNode.h"
#include "pandaNode.h"
#include "renderAttrib.h"
#include "renderState.h"
#include "textureAttrib.h"
#include "transformAttrib.h"
#include "dconfig.h"
@ -51,11 +53,17 @@ init_libpgraph() {
initialized = true;
ColorAttrib::init_type();
qpGeomNode::init_type();
PandaNode::init_type();
RenderAttrib::init_type();
RenderState::init_type();
TextureAttrib::init_type();
TransformAttrib::init_type();
ColorAttrib::register_with_read_factory();
qpGeomNode::register_with_read_factory();
PandaNode::register_with_read_factory();
RenderState::register_with_read_factory();
TextureAttrib::register_with_read_factory();
TransformAttrib::register_with_read_factory();
}

View File

@ -0,0 +1,36 @@
// Filename: cullHandler.cxx
// Created by: drose (23Feb02)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license. You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://www.panda3d.org/license.txt .
//
// To contact the maintainers of this program write to
// panda3d@yahoogroups.com .
//
////////////////////////////////////////////////////////////////////
#include "cullHandler.h"
#include "geom.h"
#include "renderState.h"
////////////////////////////////////////////////////////////////////
// Function: CullHandler::found_geom
// Access: Public, Virtual
// Description: This callback function is intended to be overridden
// by a derived class. This is called as each Geom is
// discovered by the CullTraverser.
//
// This default method simply outputs a message to cerr;
// it's not intended to be used except for debugging.
////////////////////////////////////////////////////////////////////
void CullHandler::
found_geom(Geom *geom, const RenderState *state) {
cerr << *geom << " " << *state << "\n";
}

View File

@ -0,0 +1,42 @@
// Filename: cullHandler.h
// Created by: drose (23Feb02)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license. You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://www.panda3d.org/license.txt .
//
// To contact the maintainers of this program write to
// panda3d@yahoogroups.com .
//
////////////////////////////////////////////////////////////////////
#ifndef CULLHANDLER_H
#define CULLHANDLER_H
#include "pandabase.h"
class Geom;
class RenderState;
////////////////////////////////////////////////////////////////////
// Class : CullHandler
// Description : This defines the abstract interface for an object
// that receives Geoms identified by the CullTraverser.
// By itself, it's not a particularly useful class; to
// use it, derive from it and redefine found_geom().
////////////////////////////////////////////////////////////////////
class EXPCL_PANDA CullHandler {
public:
virtual void found_geom(Geom *geom, const RenderState *state);
};
#endif

View File

@ -51,9 +51,6 @@ private:
const CycleDataType *_pointer;
};
// This abbreviation macro is used for ease of typing.
#define CDR(type) CycleDataReader< type >
#include "cycleDataReader.I"
#endif

View File

@ -52,8 +52,6 @@ private:
CycleDataType *_pointer;
};
#define CDW(type) CycleDataWriter< type >
#include "cycleDataWriter.I"
#endif

View File

@ -78,8 +78,8 @@ CData() {
// Description:
////////////////////////////////////////////////////////////////////
INLINE PandaNode::Children::
Children(const PipelineCycler<PandaNode::CData> &cycler) :
_cdata(cycler)
Children(const PandaNode::CDReader &cdata) :
_cdata(cdata)
{
}
@ -115,17 +115,6 @@ get_child(int n) const {
return _cdata->_down[n].get_child();
}
////////////////////////////////////////////////////////////////////
// Function: PandaNode::Constructor
// Access: Published
// Description:
////////////////////////////////////////////////////////////////////
INLINE PandaNode::
PandaNode(const string &name) :
Namable(name)
{
}
////////////////////////////////////////////////////////////////////
// Function: PandaNode::get_num_parents
// Access: Published
@ -137,7 +126,7 @@ PandaNode(const string &name) :
////////////////////////////////////////////////////////////////////
INLINE int PandaNode::
get_num_parents() const {
CDR(CData) cdata(_cycler);
CDReader cdata(_cycler);
return cdata->_up.size();
}
@ -149,7 +138,7 @@ get_num_parents() const {
////////////////////////////////////////////////////////////////////
INLINE PandaNode *PandaNode::
get_parent(int n) const {
CDR(CData) cdata(_cycler);
CDReader cdata(_cycler);
nassertr(n >= 0 && n < (int)cdata->_up.size(), NULL);
return cdata->_up[n];
}
@ -162,7 +151,7 @@ get_parent(int n) const {
////////////////////////////////////////////////////////////////////
INLINE int PandaNode::
find_parent(PandaNode *node) const {
CDR(CData) cdata(_cycler);
CDReader cdata(_cycler);
Up::const_iterator ui = cdata->_up.find(node);
if (ui == cdata->_up.end()) {
return -1;
@ -180,7 +169,7 @@ find_parent(PandaNode *node) const {
////////////////////////////////////////////////////////////////////
INLINE int PandaNode::
get_num_children() const {
CDR(CData) cdata(_cycler);
CDReader cdata(_cycler);
return cdata->_down.size();
}
@ -192,7 +181,7 @@ get_num_children() const {
////////////////////////////////////////////////////////////////////
INLINE PandaNode *PandaNode::
get_child(int n) const {
CDR(CData) cdata(_cycler);
CDReader cdata(_cycler);
nassertr(n >= 0 && n < (int)cdata->_down.size(), NULL);
return cdata->_down[n].get_child();
}
@ -206,7 +195,7 @@ get_child(int n) const {
////////////////////////////////////////////////////////////////////
INLINE int PandaNode::
get_sort(int n) const {
CDR(CData) cdata(_cycler);
CDReader cdata(_cycler);
nassertr(n >= 0 && n < (int)cdata->_down.size(), -1);
return cdata->_down[n].get_sort();
}
@ -222,7 +211,7 @@ get_sort(int n) const {
////////////////////////////////////////////////////////////////////
INLINE void PandaNode::
set_attrib(const RenderAttrib *attrib, int override) {
CDW(CData) cdata(_cycler);
CDWriter cdata(_cycler);
cdata->_state_changes = cdata->_state_changes->add(attrib, override);
}
@ -237,7 +226,7 @@ set_attrib(const RenderAttrib *attrib, int override) {
////////////////////////////////////////////////////////////////////
INLINE const RenderAttrib *PandaNode::
get_attrib(TypeHandle type) const {
CDR(CData) cdata(_cycler);
CDReader cdata(_cycler);
int index = cdata->_state_changes->find_attrib(type);
if (index >= 0) {
return cdata->_state_changes->get_attrib(index);
@ -255,7 +244,7 @@ get_attrib(TypeHandle type) const {
////////////////////////////////////////////////////////////////////
INLINE void PandaNode::
clear_attrib(TypeHandle type) {
CDW(CData) cdata(_cycler);
CDWriter cdata(_cycler);
cdata->_state_changes = cdata->_state_changes->remove(type);
}
@ -271,7 +260,7 @@ clear_attrib(TypeHandle type) {
////////////////////////////////////////////////////////////////////
INLINE void PandaNode::
set_state(const RenderState *state) {
CDW(CData) cdata(_cycler);
CDWriter cdata(_cycler);
cdata->_state_changes = state;
}
@ -286,7 +275,7 @@ set_state(const RenderState *state) {
////////////////////////////////////////////////////////////////////
INLINE const RenderState *PandaNode::
get_state() const {
CDR(CData) cdata(_cycler);
CDReader cdata(_cycler);
return cdata->_state_changes;
}
@ -300,7 +289,7 @@ get_state() const {
////////////////////////////////////////////////////////////////////
INLINE void PandaNode::
clear_state() {
CDW(CData) cdata(_cycler);
CDWriter cdata(_cycler);
cdata->_state_changes = RenderState::make_empty();
}
@ -320,6 +309,7 @@ clear_state() {
////////////////////////////////////////////////////////////////////
INLINE PandaNode::Children PandaNode::
get_children() const {
return Children(_cycler);
CDReader cdata(_cycler);
return Children(cdata);
}

View File

@ -50,6 +50,17 @@ make_copy() const {
return new CData(*this);
}
////////////////////////////////////////////////////////////////////
// Function: PandaNode::Constructor
// Access: Published
// Description:
////////////////////////////////////////////////////////////////////
PandaNode::
PandaNode(const string &name) :
Namable(name)
{
}
////////////////////////////////////////////////////////////////////
// Function: PandaNode::Copy Constructor
// Access: Published
@ -64,8 +75,8 @@ PandaNode(const PandaNode &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);
CDReader copy_cdata(copy._cycler);
CDWriter cdata(_cycler);
cdata->_node_bounds = copy_cdata->_node_bounds;
}
@ -81,8 +92,8 @@ operator = (const PandaNode &copy) {
ReferenceCount::operator = (copy);
// Copy the other node's bounding volume.
CDR(CData) copy_cdata(copy._cycler);
CDW(CData) cdata(_cycler);
CDReader copy_cdata(copy._cycler);
CDWriter cdata(_cycler);
cdata->_node_bounds = copy_cdata->_node_bounds;
}
@ -95,7 +106,7 @@ PandaNode::
~PandaNode() {
// We shouldn't have any parents left by the time we destruct, or
// there's a refcount fault somewhere.
CDR(CData) cdata(_cycler);
CDReader cdata(_cycler);
nassertv(cdata->_up.empty());
remove_all_children();
@ -109,7 +120,7 @@ PandaNode::
////////////////////////////////////////////////////////////////////
int PandaNode::
find_child(PandaNode *node) const {
CDR(CData) cdata(_cycler);
CDReader cdata(_cycler);
// We have to search for the child by brute force, since we don't
// know what sort index it was added as.
@ -139,8 +150,8 @@ find_child(PandaNode *node) const {
int PandaNode::
add_child(PandaNode *child, int sort) {
remove_child(child);
CDW(CData) cdata(_cycler);
CDW(CData) cdata_child(child->_cycler);
CDWriter cdata(_cycler);
CDWriter cdata_child(child->_cycler);
Down::iterator ci = cdata->_down.insert(DownConnection(child, sort));
cdata_child->_up.insert(this);
@ -155,11 +166,11 @@ add_child(PandaNode *child, int sort) {
////////////////////////////////////////////////////////////////////
void PandaNode::
remove_child(int n) {
CDW(CData) cdata(_cycler);
CDWriter cdata(_cycler);
nassertv(n >= 0 && n < (int)cdata->_down.size());
PandaNode *child = cdata->_down[n].get_child();
CDW(CData) cdata_child(child->_cycler);
CDWriter cdata_child(child->_cycler);
cdata->_down.erase(cdata->_down.begin() + n);
int num_erased = cdata_child->_up.erase(this);
@ -175,7 +186,7 @@ remove_child(int n) {
////////////////////////////////////////////////////////////////////
bool PandaNode::
remove_child(PandaNode *child) {
CDW(CData) cdata_child(child->_cycler);
CDWriter cdata_child(child->_cycler);
// First, look for and remove this node from the child's parent
// list.
@ -185,7 +196,7 @@ remove_child(PandaNode *child) {
return false;
}
CDW(CData) cdata(_cycler);
CDWriter cdata(_cycler);
// Now, look for and remove the child node from our down list.
Down::iterator ci;
@ -208,11 +219,11 @@ remove_child(PandaNode *child) {
////////////////////////////////////////////////////////////////////
void PandaNode::
remove_all_children() {
CDW(CData) cdata(_cycler);
CDWriter cdata(_cycler);
Down::iterator ci;
for (ci = cdata->_down.begin(); ci != cdata->_down.end(); ++ci) {
PandaNode *child = (*ci).get_child();
CDW(CData) child_cdata(child->_cycler);
CDWriter child_cdata(child->_cycler);
child_cdata->_up.erase(this);
}
}
@ -235,13 +246,29 @@ output(ostream &out) const {
void PandaNode::
write(ostream &out, int indent_level) const {
indent(out, indent_level) << *this;
CDR(CData) cdata(_cycler);
CDReader cdata(_cycler);
if (!cdata->_state_changes->is_empty()) {
out << " (" << *cdata->_state_changes << ")";
}
out << "\n";
}
////////////////////////////////////////////////////////////////////
// Function: PandaNode::is_geom_node
// Access: Public, Virtual
// Description: A simple downcast check. Returns true if this kind
// of node happens to inherit from GeomNode, false
// otherwise.
//
// This is provided as a a faster alternative to calling
// is_of_type(GeomNode::get_class_type()), since this
// test is so important to rendering.
////////////////////////////////////////////////////////////////////
bool PandaNode::
is_geom_node() const {
return false;
}
////////////////////////////////////////////////////////////////////
// Function: PandaNode::register_with_read_factory
// Access: Public, Static

View File

@ -41,10 +41,10 @@
// is the base class of all specialized nodes, and also
// serves as a generic node with no special properties.
////////////////////////////////////////////////////////////////////
class EXPCL_PANDA PandaNode : public TypedWritable,
public Namable, virtual public ReferenceCount {
class EXPCL_PANDA PandaNode : public TypedWritable, public Namable,
virtual public ReferenceCount {
PUBLISHED:
INLINE PandaNode(const string &name);
PandaNode(const string &name);
PandaNode(const PandaNode &copy);
void operator = (const PandaNode &copy);
virtual ~PandaNode();
@ -75,6 +75,9 @@ PUBLISHED:
virtual void output(ostream &out) const;
virtual void write(ostream &out, int indent_level) const;
public:
virtual bool is_geom_node() const;
private:
class EXPCL_PANDA DownConnection {
public:
@ -114,6 +117,8 @@ private:
};
PipelineCycler<CData> _cycler;
typedef CycleDataReader<CData> CDReader;
typedef CycleDataWriter<CData> CDWriter;
public:
// Use this interface when you want to walk through the list of
@ -122,14 +127,14 @@ public:
// However, it does not protect you from self-modifying loops.
class EXPCL_PANDA Children {
public:
INLINE Children(const PipelineCycler<CData> &cycler);
INLINE Children(const CDReader &cdata);
INLINE Children(const Children &copy);
INLINE int get_num_children() const;
INLINE PandaNode *get_child(int n) const;
private:
CDR(CData) _cdata;
CDReader _cdata;
};
INLINE Children get_children() const;

View File

@ -1,6 +1,9 @@
#include "colorAttrib.cxx"
#include "config_pgraph.cxx"
#include "cycleData.cxx"
#include "cycleDataReader.cxx"
#include "cycleDataWriter.cxx"
#include "pandaNode.cxx"
#include "colorAttrib.cxx"
#include "config_pgraph.cxx"
#include "cullHandler.cxx"
#include "qpcullTraverser.cxx"
#include "cycleData.cxx"
#include "cycleDataReader.cxx"
#include "cycleDataWriter.cxx"
#include "qpgeomNode.cxx"
#include "pandaNode.cxx"

View File

@ -1,8 +1,9 @@
#include "pipeline.cxx"
#include "pipelineCycler.cxx"
#include "pipelineCyclerBase.cxx"
#include "renderAttrib.cxx"
#include "renderState.cxx"
#include "test_pgraph.cxx"
#include "textureAttrib.cxx"
#include "pipeline.cxx"
#include "pipelineCycler.cxx"
#include "pipelineCyclerBase.cxx"
#include "renderAttrib.cxx"
#include "renderState.cxx"
#include "test_pgraph.cxx"
#include "textureAttrib.cxx"
#include "transformAttrib.cxx"

View File

@ -0,0 +1,17 @@
// Filename: qpcullTraverser.I
// Created by: drose (23Feb02)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license. You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://www.panda3d.org/license.txt .
//
// To contact the maintainers of this program write to
// panda3d@yahoogroups.com .
//
////////////////////////////////////////////////////////////////////

View File

@ -0,0 +1,117 @@
// Filename: qpcullTraverser.cxx
// Created by: drose (23Feb02)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license. You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://www.panda3d.org/license.txt .
//
// To contact the maintainers of this program write to
// panda3d@yahoogroups.com .
//
////////////////////////////////////////////////////////////////////
#include "qpcullTraverser.h"
#include "renderState.h"
#include "cullHandler.h"
#include "dcast.h"
#include "qpgeomNode.h"
////////////////////////////////////////////////////////////////////
// Function: qpCullTraverser::Constructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
qpCullTraverser::
qpCullTraverser() {
_initial_state = RenderState::make_empty();
_world_transform = DCAST(TransformAttrib, TransformAttrib::make_identity());
_cull_handler = (CullHandler *)NULL;
}
////////////////////////////////////////////////////////////////////
// Function: qpCullTraverser::set_initial_state
// Access: Public
// Description: Sets the initial RenderState at the top of the scene
// graph we are traversing. If this is not set, the
// default is the empty state.
////////////////////////////////////////////////////////////////////
void qpCullTraverser::
set_initial_state(const RenderState *initial_state) {
_initial_state = initial_state;
}
////////////////////////////////////////////////////////////////////
// Function: qpCullTraverser::set_world_transform
// Access: Public
// Description: Specifies the net inverse transform of the camera
// viewing the scene. Normally, this is the same as the
// transform specified in the initial state, but it
// might be different if we are culling a subgraph,
// for instance.
//
// This is used to evaluate camera-dependent attributes
// like billboards and LOD nodes.
////////////////////////////////////////////////////////////////////
void qpCullTraverser::
set_world_transform(const TransformAttrib *world_transform) {
_world_transform = world_transform;
}
////////////////////////////////////////////////////////////////////
// Function: qpCullTraverser::set_cull_handler
// Access: Public
// Description: Specifies the object that will receive the culled
// Geoms. This must be called before traverse().
////////////////////////////////////////////////////////////////////
void qpCullTraverser::
set_cull_handler(CullHandler *cull_handler) {
_cull_handler = cull_handler;
}
////////////////////////////////////////////////////////////////////
// Function: qpCullTraverser::traverse
// Access: Public
// Description: Begins the traversal from the indicated node.
////////////////////////////////////////////////////////////////////
void qpCullTraverser::
traverse(PandaNode *root) {
nassertv(_cull_handler != (CullHandler *)NULL);
r_traverse(root, _initial_state, 0);
}
////////////////////////////////////////////////////////////////////
// Function: qpCullTraverser::r_traverse
// Access: Private
// Description: The recursive traversal implementation.
////////////////////////////////////////////////////////////////////
void qpCullTraverser::
r_traverse(PandaNode *node, const RenderState *state, int flags) {
CPT(RenderState) next_state = state->compose(node->get_state());
if (node->is_geom_node()) {
qpGeomNode *geom_node;
DCAST_INTO_V(geom_node, node);
int num_geoms = geom_node->get_num_geoms();
for (int i = 0; i < num_geoms; i++) {
Geom *geom = geom_node->get_geom(i);
CPT(RenderState) geom_state =
next_state->compose(geom_node->get_geom_state(i));
_cull_handler->found_geom(geom, geom_state);
}
}
// Now visit all the node's children.
PandaNode::Children cr = node->get_children();
int num_children = cr.get_num_children();
for (int i = 0; i < num_children; i++) {
r_traverse(cr.get_child(i), next_state, flags);
}
}

View File

@ -0,0 +1,62 @@
// Filename: qpcullTraverser.h
// Created by: drose (23Feb02)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license. You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://www.panda3d.org/license.txt .
//
// To contact the maintainers of this program write to
// panda3d@yahoogroups.com .
//
////////////////////////////////////////////////////////////////////
#ifndef qpCULLTRAVERSER_H
#define qpCULLTRAVERSER_H
#include "pandabase.h"
#include "renderState.h"
#include "transformAttrib.h"
#include "pointerTo.h"
class PandaNode;
class CullHandler;
////////////////////////////////////////////////////////////////////
// Class : CullTraverser
// Description : This object performs a depth-first traversal of the
// scene graph, with optional view-frustum culling,
// collecting CullState and searching for GeomNodes.
// Each renderable Geom encountered is passed along with
// its associated RenderState to the CullHandler object.
////////////////////////////////////////////////////////////////////
class EXPCL_PANDA qpCullTraverser {
public:
qpCullTraverser();
void set_initial_state(const RenderState *initial_state);
void set_world_transform(const TransformAttrib *world_transform);
void set_cull_handler(CullHandler *cull_handler);
void traverse(PandaNode *root);
private:
void r_traverse(PandaNode *node, const RenderState *state, int flags);
CPT(RenderState) _initial_state;
CPT(TransformAttrib) _world_transform;
CullHandler *_cull_handler;
};
#include "qpcullTraverser.I"
#endif

View File

@ -0,0 +1,140 @@
// Filename: qpgeomNode.I
// Created by: drose (23Feb02)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license. You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://www.panda3d.org/license.txt .
//
// To contact the maintainers of this program write to
// panda3d@yahoogroups.com .
//
////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////
// Function: qpGeomNode::GeomEntry::Constructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
INLINE qpGeomNode::GeomEntry::
GeomEntry(Geom *geom, const RenderState *state) :
_geom(geom),
_state(state)
{
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomNode::CData::Constructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
INLINE qpGeomNode::CData::
CData() {
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomNode::get_num_geoms
// Access: Public
// Description: Returns the number of geoms in the node.
////////////////////////////////////////////////////////////////////
INLINE int qpGeomNode::
get_num_geoms() const {
CDReader cdata(_cycler);
return cdata->_geoms.size();
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomNode::get_geom
// Access: Public
// Description: Returns the nth geom of the node.
////////////////////////////////////////////////////////////////////
INLINE Geom *qpGeomNode::
get_geom(int n) const {
CDReader cdata(_cycler);
nassertr(n >= 0 && n < (int)cdata->_geoms.size(), NULL);
return cdata->_geoms[n]._geom;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomNode::get_geom_state
// Access: Public
// Description: Returns the RenderState associated with the nth geom
// of the node. This is just the RenderState directly
// associated with the Geom; the actual state in which
// the Geom is rendered will also be affected by
// RenderStates that appear on the scene graph in nodes
// above this GeomNode.
////////////////////////////////////////////////////////////////////
INLINE const RenderState *qpGeomNode::
get_geom_state(int n) const {
CDReader cdata(_cycler);
nassertr(n >= 0 && n < (int)cdata->_geoms.size(), NULL);
return cdata->_geoms[n]._state;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomNode::set_state
// Access: Public
// Description: Changes the RenderState associated with the nth geom
// of the node. This is just the RenderState directly
// associated with the Geom; the actual state in which
// the Geom is rendered will also be affected by
// RenderStates that appear on the scene graph in nodes
// above this GeomNode.
////////////////////////////////////////////////////////////////////
INLINE void qpGeomNode::
set_state(int n, const RenderState *state) {
CDWriter cdata(_cycler);
nassertv(n >= 0 && n < (int)cdata->_geoms.size());
cdata->_geoms[n]._state = state;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomNode::add_geom
// Access: Published
// Description: Adds a new Geom to the node. The geom is given the
// indicated state (which may be
// RenderState::make_empty(), to completely inherit its
// state from the scene graph).
//
// The return value is the index number of the new Geom.
////////////////////////////////////////////////////////////////////
INLINE int qpGeomNode::
add_geom(Geom *geom, const RenderState *state) {
nassertr(geom != (Geom *)NULL, -1);
nassertr(state != (RenderState *)NULL, -1);
CDWriter cdata(_cycler);
cdata->_geoms.push_back(GeomEntry(geom, state));
return cdata->_geoms.size() - 1;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomNode::remove_geom
// Access: Published
// Description: Removes the nth geom from the node.
////////////////////////////////////////////////////////////////////
INLINE void qpGeomNode::
remove_geom(int n) {
CDWriter cdata(_cycler);
nassertv(n >= 0 && n < (int)cdata->_geoms.size());
cdata->_geoms.erase(cdata->_geoms.begin() + n);
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomNode::remove_all_geoms
// Access: Published
// Description: Removes all the geoms from the node at once.
////////////////////////////////////////////////////////////////////
INLINE void qpGeomNode::
remove_all_geoms() {
CDWriter cdata(_cycler);
cdata->_geoms.clear();
}

View File

@ -0,0 +1,214 @@
// Filename: qpgeomNode.cxx
// Created by: drose (23Feb02)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license. You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://www.panda3d.org/license.txt .
//
// To contact the maintainers of this program write to
// panda3d@yahoogroups.com .
//
////////////////////////////////////////////////////////////////////
#include "qpgeomNode.h"
#include "bamReader.h"
#include "bamWriter.h"
#include "datagram.h"
#include "datagramIterator.h"
#include "indent.h"
TypeHandle qpGeomNode::_type_handle;
////////////////////////////////////////////////////////////////////
// Function: qpGeomNode::CData::Copy Constructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
qpGeomNode::CData::
CData(const qpGeomNode::CData &copy) :
_geoms(copy._geoms)
{
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomNode::CData::make_copy
// Access: Public, Virtual
// Description:
////////////////////////////////////////////////////////////////////
CycleData *qpGeomNode::CData::
make_copy() const {
return new CData(*this);
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomNode::Constructor
// Access: Published
// Description:
////////////////////////////////////////////////////////////////////
qpGeomNode::
qpGeomNode(const string &name) :
PandaNode(name)
{
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomNode::Copy Constructor
// Access: Published
// Description:
////////////////////////////////////////////////////////////////////
qpGeomNode::
qpGeomNode(const qpGeomNode &copy) :
PandaNode(copy)
{
// Copy the other node's _geoms.
CDReader copy_cdata(copy._cycler);
CDWriter cdata(_cycler);
cdata->_geoms = copy_cdata->_geoms;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomNode::Copy Assignment Operator
// Access: Published
// Description:
////////////////////////////////////////////////////////////////////
void qpGeomNode::
operator = (const qpGeomNode &copy) {
PandaNode::operator = (copy);
// Copy the other node's _geoms.
CDReader copy_cdata(copy._cycler);
CDWriter cdata(_cycler);
cdata->_geoms = copy_cdata->_geoms;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomNode::Destructor
// Access: Published, Virtual
// Description:
////////////////////////////////////////////////////////////////////
qpGeomNode::
~qpGeomNode() {
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomNode::write_verbose
// Access: Published
// Description: Writes a detailed description of all the Geoms in the
// node.
////////////////////////////////////////////////////////////////////
void qpGeomNode::
write_verbose(ostream &out, int indent_level) const {
CDReader cdata(_cycler);
PandaNode::write(out, indent_level);
Geoms::const_iterator gi;
for (gi = cdata->_geoms.begin(); gi != cdata->_geoms.end(); ++gi) {
const GeomEntry &entry = (*gi);
indent(out, indent_level + 2)
<< *entry._geom << " (" << *entry._state << ")\n";
entry._geom->write_verbose(out, indent_level + 4);
}
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomNode::output
// Access: Public, Virtual
// Description:
////////////////////////////////////////////////////////////////////
void qpGeomNode::
output(ostream &out) const {
PandaNode::output(out);
out << " (" << get_num_geoms() << " geoms)";
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomNode::write
// Access: Public, Virtual
// Description:
////////////////////////////////////////////////////////////////////
void qpGeomNode::
write(ostream &out, int indent_level) const {
CDReader cdata(_cycler);
PandaNode::write(out, indent_level);
Geoms::const_iterator gi;
for (gi = cdata->_geoms.begin(); gi != cdata->_geoms.end(); ++gi) {
const GeomEntry &entry = (*gi);
indent(out, indent_level + 2)
<< *entry._geom << " (" << *entry._state << ")\n";
}
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomNode::is_geom_node
// Access: Public, Virtual
// Description: A simple downcast check. Returns true if this kind
// of node happens to inherit from GeomNode, false
// otherwise.
//
// This is provided as a a faster alternative to calling
// is_of_type(GeomNode::get_class_type()), since this
// test is so important to rendering.
////////////////////////////////////////////////////////////////////
bool qpGeomNode::
is_geom_node() const {
return true;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomNode::register_with_read_factory
// Access: Public, Static
// Description: Tells the BamReader how to create objects of type
// qpGeomNode.
////////////////////////////////////////////////////////////////////
void qpGeomNode::
register_with_read_factory() {
BamReader::get_factory()->register_factory(get_class_type(), make_from_bam);
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomNode::write_datagram
// Access: Public, Virtual
// Description: Writes the contents of this object to the datagram
// for shipping out to a Bam file.
////////////////////////////////////////////////////////////////////
void qpGeomNode::
write_datagram(BamWriter *manager, Datagram &dg) {
PandaNode::write_datagram(manager, dg);
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomNode::make_from_bam
// Access: Protected, Static
// Description: This function is called by the BamReader's factory
// when a new object of type qpGeomNode is encountered
// in the Bam file. It should create the qpGeomNode
// and extract its information from the file.
////////////////////////////////////////////////////////////////////
TypedWritable *qpGeomNode::
make_from_bam(const FactoryParams &params) {
qpGeomNode *node = new qpGeomNode("");
DatagramIterator scan;
BamReader *manager;
parse_params(params, scan, manager);
node->fillin(scan, manager);
return node;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomNode::fillin
// Access: Protected
// Description: This internal function is called by make_from_bam to
// read in all of the relevant data from the BamFile for
// the new qpGeomNode.
////////////////////////////////////////////////////////////////////
void qpGeomNode::
fillin(DatagramIterator &scan, BamReader *manager) {
PandaNode::fillin(scan, manager);
}

View File

@ -0,0 +1,118 @@
// Filename: qpgeomNode.h
// Created by: drose (22Feb02)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license. You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://www.panda3d.org/license.txt .
//
// To contact the maintainers of this program write to
// panda3d@yahoogroups.com .
//
////////////////////////////////////////////////////////////////////
#ifndef qpGEOMNODE_H
#define qpGEOMNODE_H
#include "pandabase.h"
#include "pandaNode.h"
#include "pointerToArray.h"
#include "geom.h"
#include "pipelineCycler.h"
#include "cycleData.h"
#include "pvector.h"
////////////////////////////////////////////////////////////////////
// Class : GeomNode
// Description : A node that holds Geom objects, renderable pieces of
// geometry. This is the primary kind of leaf node in
// the scene graph; almost all visible objects will be
// contained in a GeomNode somewhere.
////////////////////////////////////////////////////////////////////
class EXPCL_PANDA qpGeomNode : public PandaNode {
PUBLISHED:
qpGeomNode(const string &name);
public:
qpGeomNode(const qpGeomNode &copy);
void operator = (const qpGeomNode &copy);
virtual ~qpGeomNode();
PUBLISHED:
INLINE int get_num_geoms() const;
INLINE Geom *get_geom(int n) const;
INLINE const RenderState *get_geom_state(int n) const;
INLINE void set_state(int n, const RenderState *state);
INLINE int add_geom(Geom *geom, const RenderState *state);
INLINE void remove_geom(int n);
INLINE void remove_all_geoms();
void write_verbose(ostream &out, int indent_level) const;
public:
virtual void output(ostream &out) const;
virtual void write(ostream &out, int indent_level) const;
virtual bool is_geom_node() const;
private:
class GeomEntry {
public:
INLINE GeomEntry(Geom *geom, const RenderState *state);
PT(Geom) _geom;
CPT(RenderState) _state;
};
typedef pvector<GeomEntry> Geoms;
// This is the data that must be cycled between pipeline stages.
class EXPCL_PANDA CData : public CycleData {
public:
INLINE CData();
CData(const CData &copy);
virtual CycleData *make_copy() const;
Geoms _geoms;
};
PipelineCycler<CData> _cycler;
typedef CycleDataReader<CData> CDReader;
typedef CycleDataWriter<CData> CDWriter;
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() {
PandaNode::init_type();
register_type(_type_handle, "qpGeomNode",
PandaNode::get_class_type());
}
virtual TypeHandle get_type() const {
return get_class_type();
}
virtual TypeHandle force_init_type() {init_type(); return get_class_type();}
private:
static TypeHandle _type_handle;
friend class PandaNode::Children;
};
#include "qpgeomNode.I"
#endif

View File

@ -160,7 +160,7 @@ compare_to_impl(const RenderAttrib *other) const {
// RenderAttrib (that is, a subsequent RenderAttrib
// completely replaces the preceding one). On the other
// hand, some kinds of RenderAttrib (for instance,
// TextureTransform) might combine in meaningful ways.
// TransformAttrib) might combine in meaningful ways.
////////////////////////////////////////////////////////////////////
CPT(RenderAttrib) RenderAttrib::
compose_impl(const RenderAttrib *other) const {
@ -238,3 +238,14 @@ new_from_bam(RenderAttrib *attrib, BamReader *manager) {
// reader expects that.
return (RenderAttrib *)pointer.p();
}
////////////////////////////////////////////////////////////////////
// Function: RenderAttrib::fillin
// Access: Protected
// Description: This internal function is called by make_from_bam to
// read in all of the relevant data from the BamFile for
// the new RenderAttrib.
////////////////////////////////////////////////////////////////////
void RenderAttrib::
fillin(DatagramIterator &scan, BamReader *manager) {
}

View File

@ -80,6 +80,7 @@ public:
protected:
static TypedWritable *new_from_bam(RenderAttrib *attrib, BamReader *manager);
void fillin(DatagramIterator &scan, BamReader *manager);
public:
static TypeHandle get_class_type() {

View File

@ -272,6 +272,14 @@ compose(const RenderState *other) const {
cerr << "composing " << *this << " with " << *other << "\n";
// We handle empty state (identity) as a trivial special case.
if (is_empty()) {
return other;
}
if (other->is_empty()) {
return this;
}
if (other == this) {
// compose(this) has to be handled as a special case, because the
// caching problem is so different.

View File

@ -19,7 +19,13 @@
#include "pandaNode.h"
#include "textureAttrib.h"
#include "colorAttrib.h"
#include "transformAttrib.h"
#include "texture.h"
#include "qpgeomNode.h"
#include "geomTristrip.h"
#include "geomTrifan.h"
#include "qpcullTraverser.h"
#include "cullHandler.h"
void
list_hierarchy(PandaNode *node, int indent_level) {
@ -51,32 +57,31 @@ main(int argc, char *argv[]) {
PandaNode *a1 = new PandaNode("a1");
a->add_child(a1);
qpGeomNode *g1 = new qpGeomNode("g1");
a1->add_child(g1);
Geom *geom1 = new GeomTristrip;
g1->add_geom(geom1, RenderState::make_empty());
Geom *geom2 = new GeomTrifan;
g1->add_geom(geom2, b->get_state());
qpGeomNode *g2 = new qpGeomNode("g2");
b->add_child(g2);
g2->add_geom(geom1, b->get_state());
g2->set_attrib(TransformAttrib::make_mat(LMatrix4f::translate_mat(10, 0, 0)));
cerr << "\n";
list_hierarchy(root, 0);
cerr << "\nroot's attribs:\n";
root->get_state()->write(cerr, 0);
qpCullTraverser trav;
CullHandler cull_handler;
trav.set_cull_handler(&cull_handler);
cerr << "\n";
trav.traverse(root);
cerr << "\na's attribs:\n";
a->get_state()->write(cerr, 0);
cerr << "\nroot compose a:\n";
CPT(RenderState) result1 = root->get_state()->compose(a->get_state());
result1->write(cerr, 0);
// a->clear_state();
cerr << "\nroot compose root:\n";
CPT(RenderState) result2 = root->get_state()->compose(root->get_state());
result2->write(cerr, 0);
cerr << "\nroot compose a:\n";
CPT(RenderState) result3 = root->get_state()->compose(a->get_state());
result3->write(cerr, 0);
cerr << "\na compose root:\n";
CPT(RenderState) result4 = a->get_state()->compose(root->get_state());
result4->write(cerr, 0);
cerr << "\n";
trav.traverse(root);
cerr << "\n";
return 0;
}

View File

@ -17,6 +17,10 @@
////////////////////////////////////////////////////////////////////
#include "textureAttrib.h"
#include "bamReader.h"
#include "bamWriter.h"
#include "datagram.h"
#include "datagramIterator.h"
TypeHandle TextureAttrib::_type_handle;
@ -97,3 +101,57 @@ RenderAttrib *TextureAttrib::
make_default_impl() const {
return new TextureAttrib;
}
////////////////////////////////////////////////////////////////////
// Function: TextureAttrib::register_with_read_factory
// Access: Public, Static
// Description: Tells the BamReader how to create objects of type
// TextureAttrib.
////////////////////////////////////////////////////////////////////
void TextureAttrib::
register_with_read_factory() {
BamReader::get_factory()->register_factory(get_class_type(), make_from_bam);
}
////////////////////////////////////////////////////////////////////
// Function: TextureAttrib::write_datagram
// Access: Public, Virtual
// Description: Writes the contents of this object to the datagram
// for shipping out to a Bam file.
////////////////////////////////////////////////////////////////////
void TextureAttrib::
write_datagram(BamWriter *manager, Datagram &dg) {
RenderAttrib::write_datagram(manager, dg);
}
////////////////////////////////////////////////////////////////////
// Function: TextureAttrib::make_from_bam
// Access: Protected, Static
// Description: This function is called by the BamReader's factory
// when a new object of type TextureAttrib is encountered
// in the Bam file. It should create the TextureAttrib
// and extract its information from the file.
////////////////////////////////////////////////////////////////////
TypedWritable *TextureAttrib::
make_from_bam(const FactoryParams &params) {
TextureAttrib *attrib = new TextureAttrib;
DatagramIterator scan;
BamReader *manager;
parse_params(params, scan, manager);
attrib->fillin(scan, manager);
return new_from_bam(attrib, manager);
}
////////////////////////////////////////////////////////////////////
// Function: TextureAttrib::fillin
// Access: Protected
// Description: This internal function is called by make_from_bam to
// read in all of the relevant data from the BamFile for
// the new TextureAttrib.
////////////////////////////////////////////////////////////////////
void TextureAttrib::
fillin(DatagramIterator &scan, BamReader *manager) {
RenderAttrib::fillin(scan, manager);
}

View File

@ -50,15 +50,23 @@ protected:
private:
PT(Texture) _texture;
public:
static void register_with_read_factory();
virtual void write_datagram(BamWriter *manager, Datagram &dg);
protected:
static TypedWritable *make_from_bam(const FactoryParams &params);
void fillin(DatagramIterator &scan, BamReader *manager);
public:
static TypeHandle get_class_type() {
return _type_handle;
}
static void init_type() {
TypedWritableReferenceCount::init_type();
RenderAttrib::init_type();
register_type(_type_handle, "TextureAttrib",
TypedWritableReferenceCount::get_class_type());
RenderAttrib::get_class_type());
}
virtual TypeHandle get_type() const {
return get_class_type();

View File

@ -0,0 +1,172 @@
// Filename: transformAttrib.I
// Created by: drose (23Feb02)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license. You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://www.panda3d.org/license.txt .
//
// To contact the maintainers of this program write to
// panda3d@yahoogroups.com .
//
////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////
// Function: TransformAttrib::Constructor
// Access: Private
// Description: Use TransformAttrib::make() to construct a new
// TransformAttrib object.
////////////////////////////////////////////////////////////////////
INLINE TransformAttrib::
TransformAttrib() {
_flags = F_is_identity | F_singular_known;
}
////////////////////////////////////////////////////////////////////
// Function: TransformAttrib::is_identity
// Access: Published
// Description: Returns true if the transform represents the identity
// matrix, false otherwise.
////////////////////////////////////////////////////////////////////
INLINE bool TransformAttrib::
is_identity() const {
return ((_flags & F_is_identity) != 0);
}
////////////////////////////////////////////////////////////////////
// Function: TransformAttrib::is_singular
// Access: Published
// Description: Returns true if the transform represents a singular
// transform (that is, it has a zero scale, and it
// cannot be inverted), or false otherwise.
////////////////////////////////////////////////////////////////////
INLINE bool TransformAttrib::
is_singular() const {
check_singular();
return ((_flags & F_is_singular) != 0);
}
////////////////////////////////////////////////////////////////////
// Function: TransformAttrib::has_components
// Access: Published
// Description: Returns true if the transform can be described by
// separate pos, hpr, and scale components. Most
// transforms we use in everyday life can be so
// described, but some kinds of transforms (for
// instance, those involving a skew) cannot.
//
// This is not related to whether the transform was
// originally described componentwise. Even a transform
// that was constructed with a 4x4 may return true here
// if the matrix is a simple affine matrix with no skew.
//
// If this returns true, you may safely call get_pos(),
// etc., to retrieve the components.
////////////////////////////////////////////////////////////////////
INLINE bool TransformAttrib::
has_components() const {
check_components();
return ((_flags & F_has_components) != 0);
}
////////////////////////////////////////////////////////////////////
// Function: TransformAttrib::get_pos
// Access: Published
// Description: Returns the pos component of the transform. It is an
// error to call this if has_components() returned
// false.
////////////////////////////////////////////////////////////////////
INLINE const LVecBase3f &TransformAttrib::
get_pos() const {
check_components();
nassertr(has_components(), _pos);
return _pos;
}
////////////////////////////////////////////////////////////////////
// Function: TransformAttrib::get_hpr
// Access: Published
// Description: Returns the hpr component of the transform. It is an
// error to call this if has_components() returned
// false.
////////////////////////////////////////////////////////////////////
INLINE const LVecBase3f &TransformAttrib::
get_hpr() const {
check_components();
nassertr(has_components(), _hpr);
return _hpr;
}
////////////////////////////////////////////////////////////////////
// Function: TransformAttrib::get_scale
// Access: Published
// Description: Returns the scale component of the transform. It is an
// error to call this if has_components() returned
// false.
////////////////////////////////////////////////////////////////////
INLINE const LVecBase3f &TransformAttrib::
get_scale() const {
check_components();
nassertr(has_components(), _scale);
return _scale;
}
////////////////////////////////////////////////////////////////////
// Function: TransformAttrib::get_mat
// Access: Published
// Description: Returns the matrix that describes the transform.
////////////////////////////////////////////////////////////////////
INLINE const LMatrix4f &TransformAttrib::
get_mat() const {
check_mat();
return _mat;
}
////////////////////////////////////////////////////////////////////
// Function: TransformAttrib::check_singular
// Access: Private
// Description: Ensures that we know whether the matrix is singular.
////////////////////////////////////////////////////////////////////
INLINE void TransformAttrib::
check_singular() const {
// This pretends to be a const function, even though it's not,
// because it only updates a transparent cache value.
if ((_flags & F_singular_known) == 0) {
((TransformAttrib *)this)->calc_singular();
}
}
////////////////////////////////////////////////////////////////////
// Function: TransformAttrib::check_components
// Access: Private
// Description: Ensures that we know the components of the transform
// (or that we know they cannot be derived).
////////////////////////////////////////////////////////////////////
INLINE void TransformAttrib::
check_components() const {
// This pretends to be a const function, even though it's not,
// because it only updates a transparent cache value.
if ((_flags & F_components_known) == 0) {
((TransformAttrib *)this)->calc_components();
}
}
////////////////////////////////////////////////////////////////////
// Function: TransformAttrib::check_mat
// Access: Private
// Description: Ensures that we know the overall matrix.
////////////////////////////////////////////////////////////////////
INLINE void TransformAttrib::
check_mat() const {
// This pretends to be a const function, even though it's not,
// because it only updates a transparent cache value.
if ((_flags & F_mat_known) == 0) {
((TransformAttrib *)this)->calc_mat();
}
}

View File

@ -0,0 +1,308 @@
// Filename: transformAttrib.cxx
// Created by: drose (23Feb02)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license. You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://www.panda3d.org/license.txt .
//
// To contact the maintainers of this program write to
// panda3d@yahoogroups.com .
//
////////////////////////////////////////////////////////////////////
#include "transformAttrib.h"
#include "bamReader.h"
#include "bamWriter.h"
#include "datagram.h"
#include "datagramIterator.h"
#include "compose_matrix.h"
TypeHandle TransformAttrib::_type_handle;
////////////////////////////////////////////////////////////////////
// Function: TransformAttrib::make_identity
// Access: Published, Static
// Description: Constructs an identity transform.
////////////////////////////////////////////////////////////////////
CPT(RenderAttrib) TransformAttrib::
make_identity() {
TransformAttrib *attrib = new TransformAttrib;
return return_new(attrib);
}
////////////////////////////////////////////////////////////////////
// Function: TransformAttrib::make_components
// Access: Published, Static
// Description: Makes a new TransformAttrib with the specified
// components.
////////////////////////////////////////////////////////////////////
CPT(RenderAttrib) TransformAttrib::
make_components(const LVecBase3f &pos, const LVecBase3f &hpr,
const LVecBase3f &scale) {
// Make a special-case check for the identity transform.
if (pos == LVecBase3f(0.0f, 0.0f, 0.0f) &&
hpr == LVecBase3f(0.0f, 0.0f, 0.0f) &&
scale == LVecBase3f(1.0f, 1.0f, 1.0f)) {
return make_identity();
}
TransformAttrib *attrib = new TransformAttrib;
attrib->_pos = pos;
attrib->_hpr = hpr;
attrib->_scale = scale;
attrib->_flags = F_components_given | F_components_known | F_has_components;
return return_new(attrib);
}
////////////////////////////////////////////////////////////////////
// Function: TransformAttrib::make_components
// Access: Published, Static
// Description: Makes a new TransformAttrib with the specified
// transformation matrix.
////////////////////////////////////////////////////////////////////
CPT(RenderAttrib) TransformAttrib::
make_mat(const LMatrix4f &mat) {
// Make a special-case check for the identity matrix.
if (mat == LMatrix4f::ident_mat()) {
return make_identity();
}
TransformAttrib *attrib = new TransformAttrib;
attrib->_mat = mat;
attrib->_flags = F_mat_known;
return return_new(attrib);
}
////////////////////////////////////////////////////////////////////
// Function: TransformAttrib::output
// Access: Public, Virtual
// Description:
////////////////////////////////////////////////////////////////////
void TransformAttrib::
output(ostream &out) const {
out << get_type() << ":";
if (is_identity()) {
out << "(identity)";
} else if (has_components()) {
out << "(";
if (get_pos() != LVecBase3f(0.0f, 0.0f, 0.0f)) {
out << "pos " << get_pos();
}
if (get_hpr() != LVecBase3f(0.0f, 0.0f, 0.0f)) {
out << "hpr " << get_hpr();
}
if (get_scale() != LVecBase3f(1.0f, 1.0f, 1.0f)) {
out << "scale " << get_scale();
}
out << ")";
} else {
out << get_mat();
}
}
////////////////////////////////////////////////////////////////////
// Function: TransformAttrib::compare_to_impl
// Access: Protected, Virtual
// Description: Intended to be overridden by derived TransformAttrib
// types to return a unique number indicating whether
// this TransformAttrib is equivalent to the other one.
//
// This should return 0 if the two TransformAttrib objects
// are equivalent, a number less than zero if this one
// should be sorted before the other one, and a number
// greater than zero otherwise.
//
// This will only be called with two TransformAttrib
// objects whose get_type() functions return the same.
////////////////////////////////////////////////////////////////////
int TransformAttrib::
compare_to_impl(const RenderAttrib *other) const {
const TransformAttrib *ta;
DCAST_INTO_R(ta, other, 0);
if (is_identity() != ta->is_identity()) {
return is_identity() < ta->is_identity();
}
if (is_identity()) {
// All identity transforms are equivalent to each other.
return 0;
}
bool components_given = (_flags & F_components_given) != 0;
bool ta_components_given = (ta->_flags & F_components_given) != 0;
if (components_given != ta_components_given) {
return components_given < ta_components_given;
}
if (components_given) {
// If the transform was specified componentwise, compare them
// componentwise.
int c = _pos.compare_to(ta->_pos);
if (c != 0) {
return c;
}
c = _hpr.compare_to(ta->_hpr);
if (c != 0) {
return c;
}
c = _scale.compare_to(ta->_hpr);
return c;
}
// Otherwise, compare the matrices.
return get_mat().compare_to(ta->get_mat());
}
////////////////////////////////////////////////////////////////////
// Function: TransformAttrib::compose_impl
// Access: Protected, Virtual
// Description: Intended to be overridden by derived RenderAttrib
// types to specify how two consecutive RenderAttrib
// objects of the same type interact.
////////////////////////////////////////////////////////////////////
CPT(RenderAttrib) TransformAttrib::
compose_impl(const RenderAttrib *other) const {
const TransformAttrib *ta;
DCAST_INTO_R(ta, other, other);
// Identity times anything, duh.
if (is_identity()) {
return ta;
} else if (ta->is_identity()) {
return this;
}
// Perhaps we should be smarter here if both transforms are
// componentwise, and multiply them componentwise.
LMatrix4f new_mat = get_mat() * ta->get_mat();
return make_mat(new_mat);
}
////////////////////////////////////////////////////////////////////
// Function: TransformAttrib::make_default_impl
// Access: Protected, Virtual
// Description: Intended to be overridden by derived TransformAttrib
// types to specify what the default property for a
// TransformAttrib of this type should be.
//
// This should return a newly-allocated TransformAttrib of
// the same type that corresponds to whatever the
// standard default for this kind of TransformAttrib is.
////////////////////////////////////////////////////////////////////
RenderAttrib *TransformAttrib::
make_default_impl() const {
return new TransformAttrib;
}
////////////////////////////////////////////////////////////////////
// Function: TransformAttrib::calc_singular
// Access: Private
// Description: Determines whether the transform is singular (i.e. it
// scales to zero, and has no inverse).
////////////////////////////////////////////////////////////////////
void TransformAttrib::
calc_singular() {
bool singular = false;
if (has_components()) {
// The matrix is singular if any component of its scale is 0.
singular = (_scale[0] == 0.0f || _scale[1] == 0.0f || _scale[2] == 0.0f);
} else {
// The matrix is singular if its determinant is zero.
const LMatrix4f &mat = get_mat();
singular = (mat.get_upper_3().determinant() == 0.0f);
}
if (singular) {
_flags |= F_is_singular;
}
_flags |= F_singular_known;
}
////////////////////////////////////////////////////////////////////
// Function: TransformAttrib::calc_components
// Access: Private
// Description: Derives the components from the matrix, if possible.
////////////////////////////////////////////////////////////////////
void TransformAttrib::
calc_components() {
bool possible = decompose_matrix(get_mat(), _scale, _hpr, _pos);
if (possible) {
// Some matrices can't be decomposed into scale, hpr, pos.
_flags |= F_has_components;
}
_flags |= F_components_known;
}
////////////////////////////////////////////////////////////////////
// Function: TransformAttrib::calc_mat
// Access: Private
// Description: Computes the matrix from the components.
////////////////////////////////////////////////////////////////////
void TransformAttrib::
calc_mat() {
compose_matrix(_mat, _scale, _hpr, _pos);
_flags |= F_mat_known;
}
////////////////////////////////////////////////////////////////////
// Function: TransformAttrib::register_with_read_factory
// Access: Public, Static
// Description: Tells the BamReader how to create objects of type
// TransformAttrib.
////////////////////////////////////////////////////////////////////
void TransformAttrib::
register_with_read_factory() {
BamReader::get_factory()->register_factory(get_class_type(), make_from_bam);
}
////////////////////////////////////////////////////////////////////
// Function: TransformAttrib::write_datagram
// Access: Public, Virtual
// Description: Writes the contents of this object to the datagram
// for shipping out to a Bam file.
////////////////////////////////////////////////////////////////////
void TransformAttrib::
write_datagram(BamWriter *manager, Datagram &dg) {
RenderAttrib::write_datagram(manager, dg);
}
////////////////////////////////////////////////////////////////////
// Function: TransformAttrib::make_from_bam
// Access: Protected, Static
// Description: This function is called by the BamReader's factory
// when a new object of type TransformAttrib is encountered
// in the Bam file. It should create the TransformAttrib
// and extract its information from the file.
////////////////////////////////////////////////////////////////////
TypedWritable *TransformAttrib::
make_from_bam(const FactoryParams &params) {
TransformAttrib *attrib = new TransformAttrib;
DatagramIterator scan;
BamReader *manager;
parse_params(params, scan, manager);
attrib->fillin(scan, manager);
return new_from_bam(attrib, manager);
}
////////////////////////////////////////////////////////////////////
// Function: TransformAttrib::fillin
// Access: Protected
// Description: This internal function is called by make_from_bam to
// read in all of the relevant data from the BamFile for
// the new TransformAttrib.
////////////////////////////////////////////////////////////////////
void TransformAttrib::
fillin(DatagramIterator &scan, BamReader *manager) {
RenderAttrib::fillin(scan, manager);
}

View File

@ -0,0 +1,117 @@
// Filename: transformAttrib.h
// Created by: drose (23Feb02)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license. You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://www.panda3d.org/license.txt .
//
// To contact the maintainers of this program write to
// panda3d@yahoogroups.com .
//
////////////////////////////////////////////////////////////////////
#ifndef TRANSFORMATTRIB_H
#define TRANSFORMATTRIB_H
#include "pandabase.h"
#include "renderAttrib.h"
#include "luse.h"
////////////////////////////////////////////////////////////////////
// Class : TransformAttrib
// Description : Indicates a coordinate-system transform on vertices.
// TransformAttribs are the primary means for storing
// transformations on the scene graph.
//
// Transforms may be specified in one of two ways:
// componentwise, with a pos-hpr-scale, or with an
// arbitrary transform matrix. If you specify a
// transform componentwise, it will remember its
// original components.
////////////////////////////////////////////////////////////////////
class EXPCL_PANDA TransformAttrib : public RenderAttrib {
private:
INLINE TransformAttrib();
PUBLISHED:
static CPT(RenderAttrib) make_identity();
static CPT(RenderAttrib) make_components(const LVecBase3f &pos,
const LVecBase3f &hpr,
const LVecBase3f &scale);
static CPT(RenderAttrib) make_mat(const LMatrix4f &mat);
INLINE bool is_identity() const;
INLINE bool is_singular() const;
INLINE bool has_components() const;
INLINE const LVecBase3f &get_pos() const;
INLINE const LVecBase3f &get_hpr() const;
INLINE const LVecBase3f &get_scale() const;
INLINE const LMatrix4f &get_mat() const;
public:
virtual void output(ostream &out) const;
protected:
virtual int compare_to_impl(const RenderAttrib *other) const;
virtual CPT(RenderAttrib) compose_impl(const RenderAttrib *other) const;
virtual RenderAttrib *make_default_impl() const;
private:
INLINE void check_singular() const;
INLINE void check_components() const;
INLINE void check_mat() const;
void calc_singular();
void calc_components();
void calc_mat();
enum Flags {
F_is_identity = 0x0001,
F_is_singular = 0x0002,
F_singular_known = 0x0004,
F_components_given = 0x0008,
F_components_known = 0x0010,
F_has_components = 0x0020,
F_mat_known = 0x0040,
};
LVecBase3f _pos, _hpr, _scale;
LMatrix4f _mat;
short _flags;
public:
static void register_with_read_factory();
virtual void write_datagram(BamWriter *manager, Datagram &dg);
protected:
static TypedWritable *make_from_bam(const FactoryParams &params);
void fillin(DatagramIterator &scan, BamReader *manager);
public:
static TypeHandle get_class_type() {
return _type_handle;
}
static void init_type() {
RenderAttrib::init_type();
register_type(_type_handle, "TransformAttrib",
RenderAttrib::get_class_type());
}
virtual TypeHandle get_type() const {
return get_class_type();
}
virtual TypeHandle force_init_type() {init_type(); return get_class_type();}
private:
static TypeHandle _type_handle;
};
#include "transformAttrib.I"
#endif