From 8e178ae9d605940f1c8b9125cb9f70e5828277c0 Mon Sep 17 00:00:00 2001 From: David Rose Date: Wed, 26 Jul 2006 21:40:53 +0000 Subject: [PATCH] obviate the need to call Actor.update() most of the time --- panda/src/char/Sources.pp | 9 +- panda/src/char/char_composite1.cxx | 1 - panda/src/char/char_composite2.cxx | 2 +- panda/src/char/character.cxx | 29 +++ panda/src/char/character.h | 2 + panda/src/char/characterJoint.cxx | 182 ++++++++++++++++-- panda/src/char/characterJoint.h | 12 +- panda/src/char/characterJointEffect.I | 39 ++++ panda/src/char/characterJointEffect.cxx | 239 ++++++++++++++++++++++++ panda/src/char/characterJointEffect.h | 100 ++++++++++ panda/src/char/config_char.cxx | 3 + panda/src/egg2pg/characterMaker.cxx | 2 +- panda/src/pgraph/billboardEffect.cxx | 3 +- panda/src/pgraph/billboardEffect.h | 3 +- panda/src/pgraph/compassEffect.cxx | 5 +- panda/src/pgraph/compassEffect.h | 3 +- panda/src/pgraph/nodePath.cxx | 7 +- panda/src/pgraph/renderEffect.cxx | 3 +- panda/src/pgraph/renderEffect.h | 4 +- panda/src/pgraph/renderEffects.cxx | 5 +- panda/src/pgraph/renderEffects.h | 5 +- panda/src/putil/bam.h | 3 +- 22 files changed, 620 insertions(+), 41 deletions(-) create mode 100644 panda/src/char/characterJointEffect.I create mode 100644 panda/src/char/characterJointEffect.cxx create mode 100644 panda/src/char/characterJointEffect.h diff --git a/panda/src/char/Sources.pp b/panda/src/char/Sources.pp index 626aa882cf..10dd84d482 100644 --- a/panda/src/char/Sources.pp +++ b/panda/src/char/Sources.pp @@ -12,7 +12,9 @@ #define SOURCES \ character.I character.h \ characterJoint.h characterJointBundle.I \ - characterJointBundle.h characterSlider.h \ + characterJointBundle.h \ + characterJointEffect.h characterJointEffect.I \ + characterSlider.h \ characterVertexSlider.I characterVertexSlider.h \ config_char.h \ jointVertexTransform.I jointVertexTransform.h @@ -20,6 +22,7 @@ #define INCLUDED_SOURCES \ character.cxx \ characterJoint.cxx characterJointBundle.cxx \ + characterJointEffect.cxx \ characterSlider.cxx \ characterVertexSlider.cxx \ config_char.cxx \ @@ -28,7 +31,9 @@ #define INSTALL_HEADERS \ character.I character.h \ characterJoint.h characterJointBundle.I \ - characterJointBundle.h characterSlider.h \ + characterJointBundle.h \ + characterJointEffect.h characterJointEffect.I \ + characterSlider.h \ characterVertexSlider.I characterVertexSlider.h \ config_char.h \ jointVertexTransform.I jointVertexTransform.h diff --git a/panda/src/char/char_composite1.cxx b/panda/src/char/char_composite1.cxx index 1fc52363d8..5d53d0af35 100644 --- a/panda/src/char/char_composite1.cxx +++ b/panda/src/char/char_composite1.cxx @@ -1,4 +1,3 @@ - #include "config_char.cxx" #include "character.cxx" #include "characterJoint.cxx" diff --git a/panda/src/char/char_composite2.cxx b/panda/src/char/char_composite2.cxx index e58ae1d9f2..887acf1d59 100644 --- a/panda/src/char/char_composite2.cxx +++ b/panda/src/char/char_composite2.cxx @@ -1,4 +1,4 @@ - +#include "characterJointEffect.cxx" #include "characterSlider.cxx" #include "characterVertexSlider.cxx" #include "jointVertexTransform.cxx" diff --git a/panda/src/char/character.cxx b/panda/src/char/character.cxx index dad4fa72f9..8e1d05538b 100644 --- a/panda/src/char/character.cxx +++ b/panda/src/char/character.cxx @@ -74,6 +74,7 @@ Character(const string &name) : //////////////////////////////////////////////////////////////////// Character:: ~Character() { + r_clear_joint_characters(get_bundle()); } //////////////////////////////////////////////////////////////////// @@ -251,6 +252,9 @@ copy_joints(PartGroup *copy, PartGroup *orig) { for (ci = orig->_children.begin(); ci != orig->_children.end(); ++ci) { PartGroup *orig_child = (*ci); PartGroup *copy_child = orig_child->make_copy(); + if (copy_child->is_of_type(CharacterJoint::get_class_type())) { + DCAST(CharacterJoint, copy_child)->set_character(this); + } copy->_children.push_back(copy_child); copy_joints(copy_child, orig_child); } @@ -449,6 +453,7 @@ copy_node_pointers(const Character *from, const Character::NodeMap &node_map) { // Here's an internal joint that the source Character was // animating directly. We'll animate our corresponding // joint the same way. + dest_joint->set_character(this); dest_joint->add_net_transform(dest_node); } } @@ -466,6 +471,7 @@ copy_node_pointers(const Character *from, const Character::NodeMap &node_map) { // Here's an internal joint that the source Character was // animating directly. We'll animate our corresponding // joint the same way. + dest_joint->set_character(this); dest_joint->add_local_transform(dest_node); } } @@ -633,6 +639,29 @@ redirect_slider(const VertexSlider *vs, Character::GeomSliderMap &gsmap) { return new_cvs; } +//////////////////////////////////////////////////////////////////// +// Function: Character::r_clear_joint_characters +// Access: Private +// Description: Recursively walks through the joint hierarchy and +// clears any _character pointers on all the joints. +// Intended to be called just before Character +// destruction. +//////////////////////////////////////////////////////////////////// +void Character:: +r_clear_joint_characters(PartGroup *part) { + if (part->is_of_type(CharacterJoint::get_class_type())) { + CharacterJoint *joint = DCAST(CharacterJoint, part); + nassertv(joint->get_character() == this); + joint->set_character(NULL); + } + + int num_children = part->get_num_children(); + for (int i = 0; i < num_children; ++i) { + PartGroup *child = part->get_child(i); + r_clear_joint_characters(child); + } +} + //////////////////////////////////////////////////////////////////// // Function: Character::register_with_read_factory // Access: Public, Static diff --git a/panda/src/char/character.h b/panda/src/char/character.h index 07fc645eae..569175c157 100644 --- a/panda/src/char/character.h +++ b/panda/src/char/character.h @@ -107,6 +107,8 @@ private: GeomJointMap &gjmap); PT(CharacterVertexSlider) redirect_slider(const VertexSlider *vs, GeomSliderMap &gsmap); + void r_clear_joint_characters(PartGroup *part); + // This vector is used by the ComputedVertices object to index back // into our joints and sliders. typedef vector_PartGroupStar Parts; diff --git a/panda/src/char/characterJoint.cxx b/panda/src/char/characterJoint.cxx index 988e642a8f..339588a23d 100644 --- a/panda/src/char/characterJoint.cxx +++ b/panda/src/char/characterJoint.cxx @@ -19,7 +19,7 @@ #include "characterJoint.h" #include "config_char.h" #include "jointVertexTransform.h" - +#include "characterJointEffect.h" #include "datagram.h" #include "datagramIterator.h" #include "bamReader.h" @@ -33,7 +33,9 @@ TypeHandle CharacterJoint::_type_handle; // Description: For internal use only. //////////////////////////////////////////////////////////////////// CharacterJoint:: -CharacterJoint() { +CharacterJoint() : + _character(NULL) +{ } //////////////////////////////////////////////////////////////////// @@ -44,6 +46,7 @@ CharacterJoint() { CharacterJoint:: CharacterJoint(const CharacterJoint ©) : MovingPartMatrix(copy), + _character(NULL), _net_transform(copy._net_transform), _initial_net_transform_inverse(copy._initial_net_transform_inverse) { @@ -56,9 +59,11 @@ CharacterJoint(const CharacterJoint ©) : // Description: //////////////////////////////////////////////////////////////////// CharacterJoint:: -CharacterJoint(PartGroup *parent, const string &name, - const LMatrix4f &initial_value) - : MovingPartMatrix(parent, name, initial_value) +CharacterJoint(Character *character, + PartGroup *parent, const string &name, + const LMatrix4f &initial_value) : + MovingPartMatrix(parent, name, initial_value), + _character(character) { Thread *current_thread = Thread::get_current_thread(); @@ -79,6 +84,7 @@ CharacterJoint(PartGroup *parent, const string &name, CharacterJoint:: ~CharacterJoint() { nassertv(_vertex_transforms.empty()); + nassertv(_character == (Character *)NULL); } //////////////////////////////////////////////////////////////////// @@ -179,9 +185,15 @@ update_internals(PartGroup *parent, bool self_changed, bool parent_changed, // from the root. Returns true if the node is // successfully added, false if it had already been // added. +// +// A CharacterJointEffect for this joint's Character +// will automatically be added to the specified node. //////////////////////////////////////////////////////////////////// bool CharacterJoint:: add_net_transform(PandaNode *node) { + if (_character != (Character *)NULL) { + node->set_effect(CharacterJointEffect::make(_character)); + } return _net_transform_nodes.insert(node).second; } @@ -193,9 +205,18 @@ add_net_transform(PandaNode *node) { // transform from the root. Returns true if the node is // successfully removed, false if it was not on the // list. +// +// If the node has a CharacterJointEffect that matches +// this joint's Character, it will be cleared. //////////////////////////////////////////////////////////////////// bool CharacterJoint:: remove_net_transform(PandaNode *node) { + CPT(RenderEffect) effect = node->get_effect(CharacterJointEffect::get_class_type()); + if (effect != (RenderEffect *)NULL && + DCAST(CharacterJointEffect, effect)->get_character() == _character) { + node->clear_effect(CharacterJointEffect::get_class_type()); + } + return (_net_transform_nodes.erase(node) > 0); } @@ -220,6 +241,19 @@ has_net_transform(PandaNode *node) const { //////////////////////////////////////////////////////////////////// void CharacterJoint:: clear_net_transforms() { + NodeList::iterator ai; + for (ai = _net_transform_nodes.begin(); + ai != _net_transform_nodes.end(); + ++ai) { + PandaNode *node = *ai; + + CPT(RenderEffect) effect = node->get_effect(CharacterJointEffect::get_class_type()); + if (effect != (RenderEffect *)NULL && + DCAST(CharacterJointEffect, effect)->get_character() == _character) { + node->clear_effect(CharacterJointEffect::get_class_type()); + } + } + _net_transform_nodes.clear(); } @@ -231,9 +265,20 @@ clear_net_transforms() { // transform from its parent. Returns true if the node // is successfully added, false if it had already been // added. +// +// The Character pointer should be the Character object +// that owns this joint; this will be used to create a +// CharacterJointEffect for this node. If it is NULL, +// no such effect will be created. +// +// A CharacterJointEffect for this joint's Character +// will automatically be added to the specified node. //////////////////////////////////////////////////////////////////// bool CharacterJoint:: add_local_transform(PandaNode *node) { + if (_character != (Character *)NULL) { + node->set_effect(CharacterJointEffect::make(_character)); + } return _local_transform_nodes.insert(node).second; } @@ -245,9 +290,18 @@ add_local_transform(PandaNode *node) { // transform from its parent. Returns true if the node // is successfully removed, false if it was not on the // list. +// +// If the node has a CharacterJointEffect that matches +// this joint's Character, it will be cleared. //////////////////////////////////////////////////////////////////// bool CharacterJoint:: remove_local_transform(PandaNode *node) { + CPT(RenderEffect) effect = node->get_effect(CharacterJointEffect::get_class_type()); + if (effect != (RenderEffect *)NULL && + DCAST(CharacterJointEffect, effect)->get_character() == _character) { + node->clear_effect(CharacterJointEffect::get_class_type()); + } + return (_local_transform_nodes.erase(node) > 0); } @@ -272,6 +326,19 @@ has_local_transform(PandaNode *node) const { //////////////////////////////////////////////////////////////////// void CharacterJoint:: clear_local_transforms() { + NodeList::iterator ai; + for (ai = _local_transform_nodes.begin(); + ai != _local_transform_nodes.end(); + ++ai) { + PandaNode *node = *ai; + + CPT(RenderEffect) effect = node->get_effect(CharacterJointEffect::get_class_type()); + if (effect != (RenderEffect *)NULL && + DCAST(CharacterJointEffect, effect)->get_character() == _character) { + node->clear_effect(CharacterJointEffect::get_class_type()); + } + } + _local_transform_nodes.clear(); } @@ -298,6 +365,73 @@ get_net_transform(LMatrix4f &transform) const { transform = _net_transform; } +//////////////////////////////////////////////////////////////////// +// Function: CharacterJoint::get_character +// Access: Published +// Description: Returns the Character that owns this joint. +//////////////////////////////////////////////////////////////////// +Character *CharacterJoint:: +get_character() const { + return _character; +} + +//////////////////////////////////////////////////////////////////// +// Function: CharacterJoint::set_character +// Access: Private +// Description: Changes the Character that owns this joint. +//////////////////////////////////////////////////////////////////// +void CharacterJoint:: +set_character(Character *character) { + if (character != _character) { + + if (character != (Character *)NULL) { + // Change or set a _character pointer on each joint's exposed + // node. + NodeList::iterator ai; + for (ai = _net_transform_nodes.begin(); + ai != _net_transform_nodes.end(); + ++ai) { + PandaNode *node = *ai; + node->set_effect(CharacterJointEffect::make(character)); + } + for (ai = _local_transform_nodes.begin(); + ai != _local_transform_nodes.end(); + ++ai) { + PandaNode *node = *ai; + node->set_effect(CharacterJointEffect::make(character)); + } + + } else { // (character == (Character *)NULL) + // Clear the _character pointer on each joint's exposed node. + NodeList::iterator ai; + for (ai = _net_transform_nodes.begin(); + ai != _net_transform_nodes.end(); + ++ai) { + PandaNode *node = *ai; + + CPT(RenderEffect) effect = node->get_effect(CharacterJointEffect::get_class_type()); + if (effect != (RenderEffect *)NULL && + DCAST(CharacterJointEffect, effect)->get_character() == _character) { + node->clear_effect(CharacterJointEffect::get_class_type()); + } + } + for (ai = _local_transform_nodes.begin(); + ai != _local_transform_nodes.end(); + ++ai) { + PandaNode *node = *ai; + + CPT(RenderEffect) effect = node->get_effect(CharacterJointEffect::get_class_type()); + if (effect != (RenderEffect *)NULL && + DCAST(CharacterJointEffect, effect)->get_character() == _character) { + node->clear_effect(CharacterJointEffect::get_class_type()); + } + } + } + } + + _character = character; +} + //////////////////////////////////////////////////////////////////// // Function: CharacterJoint::write_datagram // Access: Public @@ -305,22 +439,23 @@ get_net_transform(LMatrix4f &transform) const { // the particular object to a Datagram //////////////////////////////////////////////////////////////////// void CharacterJoint:: -write_datagram(BamWriter *manager, Datagram &me) -{ +write_datagram(BamWriter *manager, Datagram &me) { NodeList::iterator ni; MovingPartMatrix::write_datagram(manager, me); + manager->write_pointer(me, _character); + me.add_uint16(_net_transform_nodes.size()); - for(ni = _net_transform_nodes.begin(); - ni != _net_transform_nodes.end(); - ni++) { + for (ni = _net_transform_nodes.begin(); + ni != _net_transform_nodes.end(); + ni++) { manager->write_pointer(me, (*ni)); } me.add_uint16(_local_transform_nodes.size()); - for(ni = _local_transform_nodes.begin(); - ni != _local_transform_nodes.end(); - ni++) { + for (ni = _local_transform_nodes.begin(); + ni != _local_transform_nodes.end(); + ni++) { manager->write_pointer(me, (*ni)); } @@ -340,6 +475,10 @@ fillin(DatagramIterator &scan, BamReader *manager) { int i; MovingPartMatrix::fillin(scan, manager); + if (manager->get_file_minor_ver() >= 4) { + manager->read_pointer(scan); + } + _num_net_nodes = scan.get_uint16(); for(i = 0; i < _num_net_nodes; i++) { manager->read_pointer(scan); @@ -356,15 +495,20 @@ fillin(DatagramIterator &scan, BamReader *manager) { //////////////////////////////////////////////////////////////////// // Function: CharacterJoint::complete_pointers // Access: Public -// Description: Takes in a vector of pointes to TypedWritable +// Description: Takes in a vector of pointers to TypedWritable // objects that correspond to all the requests for // pointers that this object made to BamReader. //////////////////////////////////////////////////////////////////// int CharacterJoint:: -complete_pointers(TypedWritable **p_list, BamReader* manager) -{ +complete_pointers(TypedWritable **p_list, BamReader* manager) { int pi = MovingPartMatrix::complete_pointers(p_list, manager); + if (manager->get_file_minor_ver() >= 4) { + _character = DCAST(Character, p_list[pi++]); + } else { + _character = NULL; + } + int i; for (i = 0; i < _num_net_nodes; i++) { add_net_transform(DCAST(PandaNode, p_list[pi++])); @@ -383,8 +527,7 @@ complete_pointers(TypedWritable **p_list, BamReader* manager) // Description: Factory method to generate a CharacterJoint object //////////////////////////////////////////////////////////////////// TypedWritable* CharacterJoint:: -make_CharacterJoint(const FactoryParams ¶ms) -{ +make_CharacterJoint(const FactoryParams ¶ms) { CharacterJoint *me = new CharacterJoint; DatagramIterator scan; BamReader *manager; @@ -400,8 +543,7 @@ make_CharacterJoint(const FactoryParams ¶ms) // Description: Factory method to generate a CharacterJoint object //////////////////////////////////////////////////////////////////// void CharacterJoint:: -register_with_read_factory() -{ +register_with_read_factory() { BamReader::get_factory()->register_factory(get_class_type(), make_CharacterJoint); } diff --git a/panda/src/char/characterJoint.h b/panda/src/char/characterJoint.h index 10428dcdf5..4e52e12c15 100644 --- a/panda/src/char/characterJoint.h +++ b/panda/src/char/characterJoint.h @@ -25,6 +25,7 @@ #include "pandaNode.h" class JointVertexTransform; +class Character; //////////////////////////////////////////////////////////////////// // Class : CharacterJoint @@ -37,7 +38,8 @@ protected: CharacterJoint(const CharacterJoint ©); public: - CharacterJoint(PartGroup *parent, const string &name, + CharacterJoint(Character *character, + PartGroup *parent, const string &name, const LMatrix4f &initial_value); virtual ~CharacterJoint(); @@ -60,7 +62,15 @@ PUBLISHED: void get_transform(LMatrix4f &transform) const; void get_net_transform(LMatrix4f &transform) const; + Character *get_character() const; + private: + void set_character(Character *character); + +private: + // Not a reference-counted pointer. + Character *_character; + typedef pset< PT(PandaNode) > NodeList; NodeList _net_transform_nodes; NodeList _local_transform_nodes; diff --git a/panda/src/char/characterJointEffect.I b/panda/src/char/characterJointEffect.I new file mode 100644 index 0000000000..e8d94d6f91 --- /dev/null +++ b/panda/src/char/characterJointEffect.I @@ -0,0 +1,39 @@ +// Filename: characterJointEffect.I +// Created by: drose (26Jul06) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved +// +// All use of this software is subject to the terms of the Panda 3d +// Software license. You should have received a copy of this license +// along with this source code; you will also find a current copy of +// the license at http://etc.cmu.edu/panda3d/docs/license/ . +// +// To contact the maintainers of this program write to +// panda3d-general@lists.sourceforge.net . +// +//////////////////////////////////////////////////////////////////// + + +//////////////////////////////////////////////////////////////////// +// Function: CharacterJointEffect::Constructor +// Access: Private +// Description: Use CharacterJointEffect::make() to construct a new +// CharacterJointEffect object. +//////////////////////////////////////////////////////////////////// +INLINE CharacterJointEffect:: +CharacterJointEffect() { +} + +//////////////////////////////////////////////////////////////////// +// Function: CharacterJointEffect::get_character +// Access: Published +// Description: Returns the Character that will get update() called +// on it when this node's relative transform is queried. +//////////////////////////////////////////////////////////////////// +INLINE Character *CharacterJointEffect:: +get_character() const { + return _character; +} diff --git a/panda/src/char/characterJointEffect.cxx b/panda/src/char/characterJointEffect.cxx new file mode 100644 index 0000000000..c413d971b6 --- /dev/null +++ b/panda/src/char/characterJointEffect.cxx @@ -0,0 +1,239 @@ +// Filename: characterJointEffect.cxx +// Created by: drose (26Jul06) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved +// +// All use of this software is subject to the terms of the Panda 3d +// Software license. You should have received a copy of this license +// along with this source code; you will also find a current copy of +// the license at http://etc.cmu.edu/panda3d/docs/license/ . +// +// To contact the maintainers of this program write to +// panda3d-general@lists.sourceforge.net . +// +//////////////////////////////////////////////////////////////////// + +#include "characterJointEffect.h" +#include "cullTraverser.h" +#include "cullTraverserData.h" +#include "nodePath.h" +#include "look_at.h" +#include "bamReader.h" +#include "bamWriter.h" +#include "datagram.h" +#include "datagramIterator.h" + +TypeHandle CharacterJointEffect::_type_handle; + +//////////////////////////////////////////////////////////////////// +// Function: CharacterJointEffect::make +// Access: Published, Static +// Description: Constructs a new CharacterJointEffect object that +// references the indicated character. When a relative +// get_transform() is called on the node that contains +// the CharacterJointEffect, it will implicitly call +// character->update() first. +//////////////////////////////////////////////////////////////////// +CPT(RenderEffect) CharacterJointEffect:: +make(Character *character) { + CharacterJointEffect *effect = new CharacterJointEffect; + effect->_character = character; + return return_new(effect); +} + +//////////////////////////////////////////////////////////////////// +// Function: CharacterJointEffect::safe_to_transform +// Access: Public, Virtual +// Description: Returns true if it is generally safe to transform +// this particular kind of RenderEffect by calling the +// xform() method, false otherwise. +//////////////////////////////////////////////////////////////////// +bool CharacterJointEffect:: +safe_to_transform() const { + return false; +} + +//////////////////////////////////////////////////////////////////// +// Function: CharacterJointEffect::output +// Access: Public, Virtual +// Description: +//////////////////////////////////////////////////////////////////// +void CharacterJointEffect:: +output(ostream &out) const { + out << get_type() << "(" << _character->get_name() << ")"; +} + +//////////////////////////////////////////////////////////////////// +// Function: CharacterJointEffect::has_cull_callback +// Access: Public, Virtual +// Description: Should be overridden by derived classes to return +// true if cull_callback() has been defined. Otherwise, +// returns false to indicate cull_callback() does not +// need to be called for this effect during the cull +// traversal. +//////////////////////////////////////////////////////////////////// +bool CharacterJointEffect:: +has_cull_callback() const { + return true; +} + +//////////////////////////////////////////////////////////////////// +// Function: CharacterJointEffect::cull_callback +// Access: Public, Virtual +// Description: If has_cull_callback() returns true, this function +// will be called during the cull traversal to perform +// any additional operations that should be performed at +// cull time. This may include additional manipulation +// of render state or additional visible/invisible +// decisions, or any other arbitrary operation. +// +// At the time this function is called, the current +// node's transform and state have not yet been applied +// to the net_transform and net_state. This callback +// may modify the node_transform and node_state to apply +// an effective change to the render state at this +// level. +//////////////////////////////////////////////////////////////////// +void CharacterJointEffect:: +cull_callback(CullTraverser *trav, CullTraverserData &data, + CPT(TransformState) &node_transform, + CPT(RenderState) &) const { + CPT(TransformState) dummy_transform = TransformState::make_identity(); + adjust_transform(dummy_transform, node_transform, data.node()); +} + +//////////////////////////////////////////////////////////////////// +// Function: CharacterJointEffect::has_adjust_transform +// Access: Public, Virtual +// Description: Should be overridden by derived classes to return +// true if adjust_transform() has been defined, and +// therefore the RenderEffect has some effect on the +// node's apparent local and net transforms. +//////////////////////////////////////////////////////////////////// +bool CharacterJointEffect:: +has_adjust_transform() const { + return true; +} + +//////////////////////////////////////////////////////////////////// +// Function: CharacterJointEffect::adjust_transform +// Access: Public, Virtual +// Description: Performs some operation on the node's apparent net +// and/or local transforms. This will only be called if +// has_adjust_transform() is redefined to return true. +// +// Both parameters are in/out. The original transforms +// will be passed in, and they may (or may not) be +// modified in-place by the RenderEffect. +//////////////////////////////////////////////////////////////////// +void CharacterJointEffect:: +adjust_transform(CPT(TransformState) &net_transform, + CPT(TransformState) &node_transform, + PandaNode *node) const { + _character->update(); + node_transform = node->get_transform(); +} + + +//////////////////////////////////////////////////////////////////// +// Function: CharacterJointEffect::compare_to_impl +// Access: Protected, Virtual +// Description: Intended to be overridden by derived CharacterJointEffect +// types to return a unique number indicating whether +// this CharacterJointEffect is equivalent to the other one. +// +// This should return 0 if the two CharacterJointEffect 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 CharacterJointEffect +// objects whose get_type() functions return the same. +//////////////////////////////////////////////////////////////////// +int CharacterJointEffect:: +compare_to_impl(const RenderEffect *other) const { + const CharacterJointEffect *ta; + DCAST_INTO_R(ta, other, 0); + + if (_character != ta->_character) { + return _character < ta->_character ? -1 : 1; + } + return 0; +} + +//////////////////////////////////////////////////////////////////// +// Function: CharacterJointEffect::register_with_read_factory +// Access: Public, Static +// Description: Tells the BamReader how to create objects of type +// CharacterJointEffect. +//////////////////////////////////////////////////////////////////// +void CharacterJointEffect:: +register_with_read_factory() { + BamReader::get_factory()->register_factory(get_class_type(), make_from_bam); +} + +//////////////////////////////////////////////////////////////////// +// Function: CharacterJointEffect::write_datagram +// Access: Public, Virtual +// Description: Writes the contents of this object to the datagram +// for shipping out to a Bam file. +//////////////////////////////////////////////////////////////////// +void CharacterJointEffect:: +write_datagram(BamWriter *manager, Datagram &dg) { + RenderEffect::write_datagram(manager, dg); + + manager->write_pointer(dg, _character); +} + +//////////////////////////////////////////////////////////////////// +// Function: CharacterJointEffect::complete_pointers +// Access: Public, Virtual +// Description: Receives an array of pointers, one for each time +// manager->read_pointer() was called in fillin(). +// Returns the number of pointers processed. +//////////////////////////////////////////////////////////////////// +int CharacterJointEffect:: +complete_pointers(TypedWritable **p_list, BamReader *manager) { + int pi = RenderEffect::complete_pointers(p_list, manager); + + _character = DCAST(Character, p_list[pi++]); + + return pi; +} + +//////////////////////////////////////////////////////////////////// +// Function: CharacterJointEffect::make_from_bam +// Access: Protected, Static +// Description: This function is called by the BamReader's factory +// when a new object of type CharacterJointEffect is encountered +// in the Bam file. It should create the CharacterJointEffect +// and extract its information from the file. +//////////////////////////////////////////////////////////////////// +TypedWritable *CharacterJointEffect:: +make_from_bam(const FactoryParams ¶ms) { + CharacterJointEffect *effect = new CharacterJointEffect; + DatagramIterator scan; + BamReader *manager; + + parse_params(params, scan, manager); + effect->fillin(scan, manager); + + return effect; +} + +//////////////////////////////////////////////////////////////////// +// Function: CharacterJointEffect::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 CharacterJointEffect. +//////////////////////////////////////////////////////////////////// +void CharacterJointEffect:: +fillin(DatagramIterator &scan, BamReader *manager) { + RenderEffect::fillin(scan, manager); + + manager->read_pointer(scan); +} diff --git a/panda/src/char/characterJointEffect.h b/panda/src/char/characterJointEffect.h new file mode 100644 index 0000000000..d40676554e --- /dev/null +++ b/panda/src/char/characterJointEffect.h @@ -0,0 +1,100 @@ +// Filename: characterJointEffect.h +// Created by: drose (26Jul06) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved +// +// All use of this software is subject to the terms of the Panda 3d +// Software license. You should have received a copy of this license +// along with this source code; you will also find a current copy of +// the license at http://etc.cmu.edu/panda3d/docs/license/ . +// +// To contact the maintainers of this program write to +// panda3d-general@lists.sourceforge.net . +// +//////////////////////////////////////////////////////////////////// + +#ifndef CHARACTERJOINTEFFECT_H +#define CHARACTERJOINTEFFECT_H + +#include "pandabase.h" + +#include "renderEffect.h" +#include "luse.h" +#include "nodePath.h" +#include "character.h" + +//////////////////////////////////////////////////////////////////// +// Class : CharacterJointEffect +// Description : This effect will be added automatically to a node by +// CharacterJoint::add_net_transform() and +// CharacterJoint::add_local_transform(). +// +// The effect binds the node back to the character, so +// that querying the relative transform of the affected +// node will automatically force the indicated character +// to be updated first. +//////////////////////////////////////////////////////////////////// +class EXPCL_PANDA CharacterJointEffect : public RenderEffect { +private: + INLINE CharacterJointEffect(); + +PUBLISHED: + static CPT(RenderEffect) make(Character *character); + + INLINE Character *get_character() const; + +public: + virtual bool safe_to_transform() const; + virtual void output(ostream &out) const; + + virtual bool has_cull_callback() const; + virtual void cull_callback(CullTraverser *trav, CullTraverserData &data, + CPT(TransformState) &node_transform, + CPT(RenderState) &node_state) const; + + virtual bool has_adjust_transform() const; + virtual void adjust_transform(CPT(TransformState) &net_transform, + CPT(TransformState) &node_transform, + PandaNode *node) const; + +protected: + virtual int compare_to_impl(const RenderEffect *other) const; + +private: + PT(Character) _character; + +public: + static void register_with_read_factory(); + virtual void write_datagram(BamWriter *manager, Datagram &dg); + virtual int complete_pointers(TypedWritable **plist, + BamReader *manager); + +protected: + static TypedWritable *make_from_bam(const FactoryParams ¶ms); + void fillin(DatagramIterator &scan, BamReader *manager); + +public: + static TypeHandle get_class_type() { + return _type_handle; + } + static void init_type() { + RenderEffect::init_type(); + register_type(_type_handle, "CharacterJointEffect", + RenderEffect::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 "characterJointEffect.I" + +#endif + diff --git a/panda/src/char/config_char.cxx b/panda/src/char/config_char.cxx index f34d9b75de..8a9282a4f4 100644 --- a/panda/src/char/config_char.cxx +++ b/panda/src/char/config_char.cxx @@ -21,6 +21,7 @@ #include "character.h" #include "characterJoint.h" #include "characterJointBundle.h" +#include "characterJointEffect.h" #include "characterSlider.h" #include "characterVertexSlider.h" #include "jointVertexTransform.h" @@ -62,6 +63,7 @@ init_libchar() { Character::init_type(); CharacterJoint::init_type(); CharacterJointBundle::init_type(); + CharacterJointEffect::init_type(); CharacterSlider::init_type(); CharacterVertexSlider::init_type(); JointVertexTransform::init_type(); @@ -77,6 +79,7 @@ init_libchar() { Character::register_with_read_factory(); CharacterJoint::register_with_read_factory(); CharacterJointBundle::register_with_read_factory(); + CharacterJointEffect::register_with_read_factory(); CharacterSlider::register_with_read_factory(); CharacterVertexSlider::register_with_read_factory(); JointVertexTransform::register_with_read_factory(); diff --git a/panda/src/egg2pg/characterMaker.cxx b/panda/src/egg2pg/characterMaker.cxx index 342bc32afd..6fa321dfc9 100644 --- a/panda/src/egg2pg/characterMaker.cxx +++ b/panda/src/egg2pg/characterMaker.cxx @@ -261,7 +261,7 @@ build_joint_hierarchy(EggNode *egg_node, PartGroup *part, int index) { LMatrix4f matf = LCAST(float, matd); CharacterJoint *joint = - new CharacterJoint(part, egg_group->get_name(), matf); + new CharacterJoint(_character_node, part, egg_group->get_name(), matf); index = _parts.size(); _parts.push_back(joint); diff --git a/panda/src/pgraph/billboardEffect.cxx b/panda/src/pgraph/billboardEffect.cxx index 2caad2603d..6da6928bd9 100644 --- a/panda/src/pgraph/billboardEffect.cxx +++ b/panda/src/pgraph/billboardEffect.cxx @@ -197,7 +197,8 @@ has_adjust_transform() const { //////////////////////////////////////////////////////////////////// void BillboardEffect:: adjust_transform(CPT(TransformState) &net_transform, - CPT(TransformState) &node_transform) const { + CPT(TransformState) &node_transform, + PandaNode *) const { // A BillboardEffect can only affect the net transform when it is to // a particular node. A billboard to a camera is camera-dependent, // of course, so it has no effect in the absence of any particular diff --git a/panda/src/pgraph/billboardEffect.h b/panda/src/pgraph/billboardEffect.h index 4080d1dbba..ab0cebc16c 100644 --- a/panda/src/pgraph/billboardEffect.h +++ b/panda/src/pgraph/billboardEffect.h @@ -66,7 +66,8 @@ public: virtual bool has_adjust_transform() const; virtual void adjust_transform(CPT(TransformState) &net_transform, - CPT(TransformState) &node_transform) const; + CPT(TransformState) &node_transform, + PandaNode *node) const; protected: virtual int compare_to_impl(const RenderEffect *other) const; diff --git a/panda/src/pgraph/compassEffect.cxx b/panda/src/pgraph/compassEffect.cxx index 7e15b6d095..29c255f42f 100644 --- a/panda/src/pgraph/compassEffect.cxx +++ b/panda/src/pgraph/compassEffect.cxx @@ -145,7 +145,7 @@ cull_callback(CullTraverser *trav, CullTraverserData &data, CPT(TransformState) true_net_transform = data.get_net_transform(trav); CPT(TransformState) want_net_transform = true_net_transform; - adjust_transform(want_net_transform, node_transform); + adjust_transform(want_net_transform, node_transform, data.node()); // Now compute the transform that will convert true_net_transform to // want_transform. This is inv(true_net_transform) * want_transform. @@ -185,7 +185,8 @@ has_adjust_transform() const { //////////////////////////////////////////////////////////////////// void CompassEffect:: adjust_transform(CPT(TransformState) &net_transform, - CPT(TransformState) &node_transform) const { + CPT(TransformState) &node_transform, + PandaNode *) const { if (_properties == 0) { // Nothing to do. return; diff --git a/panda/src/pgraph/compassEffect.h b/panda/src/pgraph/compassEffect.h index c522dfce93..f6d19b2589 100644 --- a/panda/src/pgraph/compassEffect.h +++ b/panda/src/pgraph/compassEffect.h @@ -90,7 +90,8 @@ public: virtual bool has_adjust_transform() const; virtual void adjust_transform(CPT(TransformState) &net_transform, - CPT(TransformState) &node_transform) const; + CPT(TransformState) &node_transform, + PandaNode *node) const; protected: virtual int compare_to_impl(const RenderEffect *other) const; diff --git a/panda/src/pgraph/nodePath.cxx b/panda/src/pgraph/nodePath.cxx index 379195079c..21ea105d15 100644 --- a/panda/src/pgraph/nodePath.cxx +++ b/panda/src/pgraph/nodePath.cxx @@ -5805,11 +5805,12 @@ r_get_net_transform(NodePathComponent *comp, Thread *current_thread) const { } else { int pipeline_stage = current_thread->get_pipeline_stage(); CPT(TransformState) net_transform = r_get_net_transform(comp->get_next(pipeline_stage, current_thread), current_thread); - CPT(TransformState) transform = comp->get_node()->get_transform(current_thread); + PandaNode *node = comp->get_node(); + CPT(TransformState) transform = node->get_transform(current_thread); - CPT(RenderEffects) effects = comp->get_node()->get_effects(current_thread); + CPT(RenderEffects) effects = node->get_effects(current_thread); if (effects->has_adjust_transform()) { - effects->adjust_transform(net_transform, transform); + effects->adjust_transform(net_transform, transform, node); } return net_transform->compose(transform); diff --git a/panda/src/pgraph/renderEffect.cxx b/panda/src/pgraph/renderEffect.cxx index 5309cc50e1..a48d265bd3 100644 --- a/panda/src/pgraph/renderEffect.cxx +++ b/panda/src/pgraph/renderEffect.cxx @@ -199,7 +199,8 @@ has_adjust_transform() const { // modified in-place by the RenderEffect. //////////////////////////////////////////////////////////////////// void RenderEffect:: -adjust_transform(CPT(TransformState) &, CPT(TransformState) &) const { +adjust_transform(CPT(TransformState) &, CPT(TransformState) &, + PandaNode *) const { } //////////////////////////////////////////////////////////////////// diff --git a/panda/src/pgraph/renderEffect.h b/panda/src/pgraph/renderEffect.h index 9c06a89925..40cd542cf8 100644 --- a/panda/src/pgraph/renderEffect.h +++ b/panda/src/pgraph/renderEffect.h @@ -31,6 +31,7 @@ class CullTraverser; class CullTraverserData; +class PandaNode; //////////////////////////////////////////////////////////////////// // Class : RenderEffect @@ -78,7 +79,8 @@ public: virtual bool has_adjust_transform() const; virtual void adjust_transform(CPT(TransformState) &net_transform, - CPT(TransformState) &node_transform) const; + CPT(TransformState) &node_transform, + PandaNode *node) const; PUBLISHED: INLINE int compare_to(const RenderEffect &other) const; diff --git a/panda/src/pgraph/renderEffects.cxx b/panda/src/pgraph/renderEffects.cxx index 706dd1272e..cd28f3fdcc 100644 --- a/panda/src/pgraph/renderEffects.cxx +++ b/panda/src/pgraph/renderEffects.cxx @@ -520,10 +520,11 @@ cull_callback(CullTraverser *trav, CullTraverserData &data, //////////////////////////////////////////////////////////////////// void RenderEffects:: adjust_transform(CPT(TransformState) &net_transform, - CPT(TransformState) &node_transform) const { + CPT(TransformState) &node_transform, + PandaNode *node) const { Effects::const_iterator ei; for (ei = _effects.begin(); ei != _effects.end(); ++ei) { - (*ei)._effect->adjust_transform(net_transform, node_transform); + (*ei)._effect->adjust_transform(net_transform, node_transform, node); } } diff --git a/panda/src/pgraph/renderEffects.h b/panda/src/pgraph/renderEffects.h index 6c2f2402b1..de0b5ebae3 100644 --- a/panda/src/pgraph/renderEffects.h +++ b/panda/src/pgraph/renderEffects.h @@ -107,8 +107,9 @@ public: CPT(RenderState) &node_state) const; INLINE bool has_adjust_transform() const; - virtual void adjust_transform(CPT(TransformState) &net_transform, - CPT(TransformState) &node_transform) const; + void adjust_transform(CPT(TransformState) &net_transform, + CPT(TransformState) &node_transform, + PandaNode *node) const; static void init_states(); diff --git a/panda/src/putil/bam.h b/panda/src/putil/bam.h index b2bcc66d84..224b28887b 100644 --- a/panda/src/putil/bam.h +++ b/panda/src/putil/bam.h @@ -36,10 +36,11 @@ static const unsigned short _bam_major_ver = 6; // Bumped to major version 5 on 5/6/05 for new Geom implementation. // Bumped to major version 6 on 2/11/06 to factor out PandaNode::CData. -static const unsigned short _bam_minor_ver = 3; +static const unsigned short _bam_minor_ver = 4; // Bumped to minor version 1 on 3/12/06 to add Texture::_compression. // Bumped to minor version 2 on 3/17/06 to add PandaNode::_draw_control_mask. // Bumped to minor version 3 on 3/21/06 to add Texture::_ram_images. +// Bumped to minor version 4 on 7/26/06 to add CharacterJoint::_character. #endif